TITIP-010 Audit trail
| Status | Accepted |
| Version | 0.1 |
| Stage | 0 — Authority |
Purpose
Require an explainable record of security-sensitive actions. If it cannot be answered from audit events, the feature is not done.
Decisions
- Audit is append-only. Events are not updated to hide mistakes. A correction is a new event.
- The trail is event-driven. Domain modules emit facts. They do not write ad hoc log lines and call that an audit (ADR-007).
- Events must not contain instruction plaintext, document bytes, secrets, or raw OTPs. They may contain ids, policy versions, evidence codes, channel, template id, and provider acceptance.
- Clocks are UTC. Actor is
owner,trusted_contact,recipient,reviewer, orsystem, each with an id.
Questions the trail must answer
| Question | Minimum event |
|---|---|
| Who changed the release or life-check policy, and when? | policy.version.activated |
| Who added, accepted, rejected, or removed a trusted contact? | trusted_contact.* |
| What life-check notices were sent? | notification.requested and notification.provider_accepted or notification.provider_failed |
| Who verified the trusted contact? | trusted_contact.verified |
| Why did release become eligible? | release.case.eligible with evidence codes and policy_version |
| Who approved the release? | release.case.approved |
| What was delivered? | release.package.created with vault ids and content version ids, not bodies |
| When did the recipient access it? | release.recipient.accessed |
Eligibility example
{
"type": "release.case.eligible",
"user_id": "usr_example",
"release_case_id": "rel_example",
"policy_version": "7",
"evidence": [
"life_check_unconfirmed",
"grace_period_elapsed",
"trusted_contact_confirmed"
]
}
policy_version is a string, matching the schema, even when the value is numeric.
Critical mutations
The following must emit an audit event in the same transaction as the state change, or the state change rolls back:
- owner registration and session revocation
- trusted-contact invite, accept, reject, verify, remove
- vault create, assign, archive, delete
- instruction version create
- life-check policy activate
- escalation transition
- release-case create, hold, approve, reject, deliver
- global release hold on and off
- recipient access
Activity timeline in the owner app is a projection of these events, filtered for the owner. It is not a second log with different facts.
Retention
Audit retention is longer than vault ciphertext. See policies/retention.md. Deleting an account does not allow the owner to rewrite history. It does require dropping payloads that are not needed to explain the action.
Acceptance
- UC-06 simulation emits
release.case.eligiblewith the three codes and does not emitrelease.case.approved. - A test that writes an instruction cannot find that text in the audit store.