TITIP-005 Vaults
| Status | Accepted |
| Version | 0.1 |
| Stage | 0 — Authority |
Purpose
Define the vault: a recipient-scoped container of guidance, its lifecycle, and the rule that sensitive plaintext does not sit in the database.
For the prototype, vault behaviour is a module inside backend. Extraction to a vault repository waits until alpha or production security boundaries require it (ADR-001). The contract is the same either way.
Decisions
- A vault has exactly one owner. It has zero or more recipient assignments. Zero recipients means the vault cannot appear in a release case.
- Assignment is explicit. There is no “family” principal that expands to every contact.
- An assignment may carry a rule that forces
HOLDeven when the case is eligible. Prototype rule:recipient_age_gte: 18for the daughter’s vault. If age is unknown, status isHOLD, not a guess. - Vaults are not a password manager. The write path must reject prohibited fields and should reject obvious secret patterns in instruction text (a 12- or 24-word seed phrase, a labelled
password:orPIN:line). Rejection is a validation error, not silent stripping, so the owner sees why. - Instruction text and document bytes are restricted data. They must be envelope-encrypted before persistence (ADR-006). Metadata needed to list a vault (title, category, recipient display name, status) may be stored as confidential metadata, not as a copy of the instruction.
- Versioning: an edit creates a new content version. Release packaging uses the version current at approval time and records that version id on the case. Later edits must not change what an already-approved package contained.
- Deletion follows TITIP-011. Deleting a vault destroys ciphertext and data keys. It does not erase the audit event that the vault existed and was deleted.
Lifecycle
DRAFT → ACTIVE → ARCHIVED
│
└→ DELETED
| State | Meaning |
|---|---|
DRAFT |
Owner is still writing. Must not be packaged for release. |
ACTIVE |
Eligible to be included if assigned and the case allows it. |
ARCHIVED |
Kept for the owner’s history. Must not be newly packaged. |
DELETED |
Ciphertext destroyed. Tombstone metadata only, per retention policy. |
SUSPENDED is reserved for a security hold on a single vault (suspected secret or abuse). A suspended vault must not be packaged. Global release hold is separate and lives on the platform, not on each vault (policies/release-safety.md).
Packaging is not a vault state. A release package is a recipient-scoped snapshot produced by the delivery module.
What vault is responsible for
Even while it is a backend module, the boundary is:
- envelope encryption and field-level encryption of restricted fields
- access control
- content versioning
- retention and deletion of ciphertext
- recipient segmentation
- release packaging of authorised snapshots
The module must not decide that a life-check policy is satisfied. It receives a release case that delivery is allowed to package.
Acceptance
- Prohibited secret fields cannot be stored (
contracts/schemas/instruction.schema.json). - Two recipients assigned different vaults cannot read across that boundary, including in simulation UI.
- A draft vault does not appear in a simulated package.