feat: replace Subject retirement with durable explicit deletion

This commit is contained in:
2026-10-28 11:18:43 +09:00
parent 618880d38d
commit a06f6bfb3d
71 changed files with 7448 additions and 315 deletions
+46
View File
@@ -12,3 +12,49 @@ Hosts retain body ownership across inactivity, reserve actual execution quiescen
- [`api`]: shared Host operations and bounded responses
- [`job`]: consolidation selection rules and result validation
- [`journal`]: individually committed activity operations, source coverage, retry receipts, and bounded reading
## Explicit Subject deletion
`begin_subject_deletion(subject_id, operation_id)` commits a permanent content-free
fence in this store **before** the Host stops execution or erases external content.
The operation ID is unique within this storage scope. Exact retries return current
saved state; a different key for that Subject or reuse for another Subject conflicts.
Pending fences survive restart and a failed purge. Normal reads, writes, saved-receipt
replay, cached Host/Journal contexts and authority lookup cannot use a fenced Subject.
Subject discovery hides fenced records before pagination. SQL INSERT/UPDATE guards
cover direct and indirect owners, checking both OLD and NEW ownership on UPDATE.
Deleting a grant never restores non-Subject fallback: content-free Worker identity
fences remain, and the Host must consult them before fallback authorization.
The Host uses `subject_deletion` / `pending_subject_deletions` for recovery and
`deletion_subject_workers` / `deletion_subject_sessions` / `deletion_subject_jobs`
only as cleanup inventories, not authority or model-visible content. It must fence
creation reservations, quiesce Workers and in-flight delivery, purge Job inputs/results
and live Job execution copies, and clear resident/derived caches. Source Worker/Session
originals and pre-existing archives have independent retention lifecycles: the Workspace
Host archives source originals rather than erasing them. Those archives may contain
previously injected Memory; Workdirs, Tickets, exports and external provider copies are
also outside Subject content erasure. These boundaries must be explained to the user.
The domain rechecks after out-of-DB capture callbacks and before returning Job read
responses; already returned DTOs cannot be revoked by SQLite. Host lifecycle locking
must cover delivery/reinjection of previously fetched content as well as finish.
Only after external cleanup succeeds may the Host call
`finish_subject_deletion(subject_id, operation_id)`. One transaction deletes Subject,
Memory/history, staging/evidence, Surface snapshots/runs, permission sources/receipts,
child grants, writer/session bindings, Journal content/generations/deliveries/receipts,
links, and the Subject's `legacy_record_archive` rows. A purge error rolls back all
those deletions without undoing the separately committed fence. Ordinary history
retention and explicit Journal Session-erasure rules are unchanged for other Subjects.
Retained records contain only deletion operation/time/completion and execution/session
identities needed to prevent reuse; existing content-free Session-erasure markers and
workspace-only migration metadata remain. Other Subjects and storage scopes are untouched.
The deletion migration adds fences without erasing or reactivating existing data. Old `retired`
JSON/SQL records deserialize as `SubjectState::LegacyRetired` and remain readable
until explicitly deleted. There is no current retirement API. Normal Worker deletion
still does not implicitly delete Subject memory.
Completion means logical erasure from domain and Host-managed storage, **not** secure
physical overwriting: SQLite free pages, WAL files, filesystem snapshots, backups and
external copies can retain bytes under their own retention/erasure policies.