Engine/PIP declaration is now checkable (layer.yaml plus a Tooling-client scan). Writes persist a decision record or the published fail-closed stance, live-lookup freshness is published, events_for is tenant-scoped, and mutation evidence drains to audit-core from a local outbox without blocking the mutation. Sender registration is requested as AUDIT-IN-0002. Boundary-contract amendment is requested as NET-IN-0002. Assistant: grok Assistant-Session: 01a04cea-e5e8-7081-a0fc-808ebbc35fa9
2.5 KiB
Mutation evidence emission (TEN-WP-0011-T04)
Statute §9.6. Companion §6. Current event classes are attributive: no control in this engine branches on an event's presence. Role grants as facts are live PIP input; the events are the trail.
Bound
The local events table and the local audit_outbox prove that the
records they hold were not altered or truncated after arrival. They do
not prove an event happened, and absence is not evidence of
non-occurrence. They share this service's runtime database credential,
so they are not independent custody.
Independent custody belongs to audit-core. This engine POSTs
/v1/events and holds no SQL, no admin, and no rewrite path against
audit-core's store. The external copy therefore cannot be rewritten
through tenant-engine's database credential.
Trade (declared)
| Step | Atomic with mutation? | If it fails |
|---|---|---|
Insert local events row |
yes (same transaction) | mutation rolls back |
Insert local audit_outbox row |
yes (same transaction) | mutation rolls back |
| Drain outbox to audit-core | no — after commit | mutation already succeeded; row stays pending |
Emission is non-blocking. Unavailable audit-core MUST NOT fail-open a mutation (the fact is already written) and MUST NOT fail-closed a mutation (attributive evidence is not load-bearing). Completeness is not claimed. If a future control starts branching on these events, that class must be reclassified load-bearing before it ships, and this trade revisited.
Envelope
audit-core.event.v1alpha1. source is tenant-engine. See
tenant_engine.audit_core.envelope_for. Duplicate event ids are 200
and not retried; 400/409 dead-letter; 503/transport retry.
Credentials
No secret in Git. Production sender token is projected as
TENANT_ENGINE_AUDIT_CORE_TOKEN_FILE, routed through warden route
(audit-core sender registration), never through a State Hub message.
Sender registration itself is requested as AUDIT-IN-0002.
Backfill
Decision: no backfill of pre-cutover event classes. Those rows stay in the local table. Reconstructing them into audit-core would mint evidence this engine cannot prove was complete at the time. New mutations from this workplan onward enqueue the outbox.
Configuration
| Env var | Default | Meaning |
|---|---|---|
TENANT_ENGINE_AUDIT_CORE_URL |
unset | Drain is skipped; outbox rows stay pending. |
TENANT_ENGINE_AUDIT_CORE_TOKEN_FILE |
unset | Bearer token file for POST /v1/events. |
TENANT_ENGINE_AUDIT_CORE_TIMEOUT_SECONDS |
3 |
Drain timeout. |