149 lines
6.0 KiB
Python
149 lines
6.0 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from govoplan_audit.backend.db import models as audit_models # noqa: F401 - populate Audit ORM metadata
|
|
from govoplan_core.core.access import (
|
|
CAPABILITY_AUDIT_RECORDER,
|
|
CAPABILITY_AUDIT_RETENTION,
|
|
CAPABILITY_AUTH_PERMISSION_EVALUATOR,
|
|
CAPABILITY_AUTH_PRINCIPAL_RESOLVER,
|
|
)
|
|
from govoplan_core.core.module_guards import drop_table_retirement_provider, persistent_table_uninstall_guard
|
|
from govoplan_core.core.modules import DocumentationTopic, FrontendModule, MigrationSpec, ModuleContext, ModuleManifest
|
|
from govoplan_core.core.provider_governance import declared_module_architecture
|
|
from govoplan_core.core.events import CAPABILITY_PLATFORM_EVENT_OUTBOX
|
|
from govoplan_core.core.views import ViewSurface
|
|
from govoplan_core.db.base import Base
|
|
|
|
|
|
def _route_factory(context: ModuleContext):
|
|
del context
|
|
from govoplan_audit.backend.api.v1.routes import router
|
|
|
|
return router
|
|
|
|
|
|
def _audit_recorder(context: ModuleContext):
|
|
del context
|
|
from govoplan_audit.backend.recording import SqlAuditRecorder
|
|
|
|
return SqlAuditRecorder()
|
|
|
|
|
|
def _audit_retention(context: ModuleContext):
|
|
del context
|
|
from govoplan_audit.backend.retention import SqlAuditRetentionProvider
|
|
|
|
return SqlAuditRetentionProvider()
|
|
|
|
|
|
def _event_outbox(context: ModuleContext):
|
|
from govoplan_audit.backend.outbox import SqlAuditOutbox
|
|
|
|
return SqlAuditOutbox(
|
|
max_attempts=getattr(
|
|
context.settings,
|
|
"platform_event_outbox_max_attempts",
|
|
8,
|
|
)
|
|
)
|
|
|
|
|
|
manifest = ModuleManifest(
|
|
id="audit",
|
|
name="Audit",
|
|
version="0.1.8",
|
|
required_capabilities=(CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR),
|
|
route_factory=_route_factory,
|
|
documentation=(
|
|
DocumentationTopic(
|
|
id="audit.read-authorized-evidence",
|
|
title="Read authorized audit evidence",
|
|
summary="Audit history explains who performed a governed action, when it happened, and which resource and trace context were involved.",
|
|
body="Audit views are permission- and tenant-scoped. Entries are evidence, not editable business records. Sensitive payloads may be redacted while stable resource, actor, outcome, request, run, and trace references remain available for investigation.",
|
|
documentation_types=("user",),
|
|
audience=("auditor", "tenant_admin", "operator"),
|
|
metadata={
|
|
"kind": "reference",
|
|
"help_contexts": [
|
|
"audit.admin.system",
|
|
"audit.admin.tenant",
|
|
"audit.event-details",
|
|
],
|
|
"surfaces": ["audit.admin.system", "audit.admin.tenant"],
|
|
},
|
|
),
|
|
DocumentationTopic(
|
|
id="audit.recording-retention-and-outbox",
|
|
title="Operate audit recording and event delivery",
|
|
summary="Audit owns durable audit records, retention operations, and the transactional platform-event outbox.",
|
|
body="Modules record bounded audit facts through the Audit capability. Governed platform events are committed to the outbox with retry and delivery metadata so a failed consumer does not erase the originating transaction. Worker dispatch is partitioned by tenant entitlement; an unavailable consumer retains its durable delivery and records an operator-required outcome instead of acknowledging the event. Retention and destructive retirement must preserve the configured evidence and recovery guarantees.",
|
|
documentation_types=("admin",),
|
|
audience=("auditor", "security_officer", "operator"),
|
|
related_modules=("policy", "ops"),
|
|
metadata={
|
|
"kind": "reference",
|
|
"help_contexts": [
|
|
"audit.recording",
|
|
"audit.retention",
|
|
"audit.event-outbox",
|
|
],
|
|
},
|
|
),
|
|
),
|
|
frontend=FrontendModule(
|
|
module_id="audit",
|
|
package_name="@govoplan/audit-webui",
|
|
view_surfaces=(
|
|
ViewSurface(id="audit.admin.system", module_id="audit", kind="section", label="System audit", order=90),
|
|
ViewSurface(id="audit.admin.tenant", module_id="audit", kind="section", label="Tenant audit", order=100),
|
|
),
|
|
),
|
|
migration_spec=MigrationSpec(
|
|
module_id="audit",
|
|
metadata=Base.metadata,
|
|
script_location=str(
|
|
Path(__file__).with_name("migrations") / "versions"
|
|
),
|
|
retirement_supported=True,
|
|
retirement_provider=drop_table_retirement_provider(
|
|
audit_models.AuditLog,
|
|
audit_models.AuditOutboxDelivery,
|
|
audit_models.AuditOutboxEvent,
|
|
label="Audit",
|
|
),
|
|
retirement_notes="Destructive retirement drops audit-owned database tables after the installer captures a database snapshot.",
|
|
),
|
|
uninstall_guard_providers=(
|
|
persistent_table_uninstall_guard(
|
|
audit_models.AuditLog,
|
|
audit_models.AuditOutboxDelivery,
|
|
audit_models.AuditOutboxEvent,
|
|
label="Audit",
|
|
),
|
|
),
|
|
capability_factories={
|
|
CAPABILITY_AUDIT_RECORDER: _audit_recorder,
|
|
CAPABILITY_AUDIT_RETENTION: _audit_retention,
|
|
CAPABILITY_PLATFORM_EVENT_OUTBOX: _event_outbox,
|
|
},
|
|
architecture=declared_module_architecture(
|
|
layer="governance_accountability",
|
|
kind="governance",
|
|
maturity="vertical_slice",
|
|
documentation_ref="docs/AUDIT_TRACE_CONTEXT.md",
|
|
test_ref="tests/test_audit_module_contract.py",
|
|
known_limits=("Cross-deployment archival and evidentiary export profiles are not yet reference-ready.",),
|
|
owned_concepts=("audit record", "audit retention", "transactional event outbox"),
|
|
non_owned_concepts=("domain record", "policy decision", "external effect"),
|
|
recovery_docs=("README.md",),
|
|
security_docs=("docs/AUDIT_TRACE_CONTEXT.md",),
|
|
operations_docs=("README.md",),
|
|
),
|
|
)
|
|
|
|
|
|
def get_manifest() -> ModuleManifest:
|
|
return manifest
|