diff --git a/Repo-docs-EVENTS-AND-AUDIT.-.md b/Repo-docs-EVENTS-AND-AUDIT.-.md new file mode 100644 index 0000000..975e9a5 --- /dev/null +++ b/Repo-docs-EVENTS-AND-AUDIT.-.md @@ -0,0 +1,150 @@ + + +> Mirrored from `/mnt/DATA/git/govoplan-core/docs/EVENTS_AND_AUDIT.md`. +> Origin: `repository`. +> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context. + +--- +# Events And Audit + +GovOPlaN uses a small kernel event contract first, not a broad command bus. +Commands remain module-owned application-service methods or API endpoints until +there is a concrete need for durable asynchronous command orchestration. Events +are facts about completed work and are safe for audit, projections, optional +module reactions, and operator diagnostics. + +## Current Decision + +- Use `govoplan_core.core.events.PlatformEvent` for domain and platform events. +- Use `EventBus` as the in-process dispatch contract for immediate module + reactions. +- Keep durable dispatch out of the first API shape. A database outbox can wrap + the same `PlatformEvent` envelope later without changing event producers. +- Keep commands out of the kernel until workflows need retryable, durable, + operator-visible command records. + +This keeps the first contract small while preserving room for a DB outbox, +Redis/Celery dispatch, or workflow-owned command orchestration later. + +## Trace IDs + +Every `PlatformEvent` has: + +- `event_id`: unique ID for that event. +- `correlation_id`: stable ID for the whole request, workflow, or job. +- `causation_id`: the event ID or external operation ID that caused this + event. + +The FastAPI app factory creates an event context for every request. It accepts +`X-Correlation-ID` or `X-Request-ID` when the value is a compact safe trace ID, +otherwise it generates a new ID. Responses include `X-Correlation-ID`. + +Audit logging reads the current event context and stores trace IDs in +`details._trace`. Callers can also pass explicit `correlation_id` and +`causation_id` to `audit_event` or `audit_from_principal`. + +## Audit MVP Boundary + +`govoplan-audit` owns: + +- the `audit_log` table and audit API routes +- audit route contribution through its module manifest +- audit retention behavior in cooperation with policy/retention settings +- future audit sink/export capability implementations + +`govoplan-core` owns: + +- `AuditEvent` and `AuditSink` protocol contracts +- request and event trace context +- the compatibility `audit_event` helper while routes are still migrating +- retention orchestration that calls module capabilities + +Feature modules should record audit facts through a small audit API or future +`audit.sink` capability. They should not import audit storage internals. + +## Initial Domain Event Inventory + +Access: + +- `access.account.created` +- `access.account.updated` +- `access.membership.created` +- `access.membership.updated` +- `access.group.created` +- `access.group.updated` +- `access.role.created` +- `access.role.updated` +- `access.role.deleted` +- `access.api_key.created` +- `access.api_key.revoked` +- `access.session.created` +- `access.session.revoked` + +Tenancy: + +- `tenancy.tenant.created` +- `tenancy.tenant.updated` +- `tenancy.tenant.suspended` +- `tenancy.tenant.reactivated` +- `tenancy.tenant.delete_requested` +- `tenancy.tenant.delete_blocked` +- `tenancy.tenant.deleted` + +Policy: + +- `policy.system.updated` +- `policy.tenant.updated` +- `policy.user.updated` +- `policy.group.updated` +- `policy.campaign.updated` +- `policy.effective_policy.changed` + +Files: + +- `files.file.uploaded` +- `files.file.renamed` +- `files.file.deleted` +- `files.file.frozen` +- `files.share.created` +- `files.share.revoked` +- `files.connector.imported` +- `files.connector.access_denied` + +Mail: + +- `mail.profile.created` +- `mail.profile.updated` +- `mail.profile.credentials_rotated` +- `mail.profile.tested` +- `mail.message.sent` +- `mail.message.send_failed` +- `mail.imap.appended` +- `mail.imap.append_failed` +- `mail.mailbox.message_seen` + +Campaign: + +- `campaign.created` +- `campaign.version.created` +- `campaign.validated` +- `campaign.built` +- `campaign.reviewed` +- `campaign.queued` +- `campaign.send_started` +- `campaign.recipient_attempted` +- `campaign.recipient_delivered` +- `campaign.recipient_failed` +- `campaign.paused` +- `campaign.resumed` +- `campaign.cancelled` +- `campaign.report.exported` + +## Event Payload Rules + +- Payloads must be JSON-serializable. +- Use stable IDs, not ORM objects. +- Include tenant ID when tenant-scoped. +- Include actor/principal references only as DTOs or primitive IDs. +- Do not include secrets, raw message bodies, full recipient lists, or file + content. +- Put large evidence in owning module storage and reference it by ID.