Data Subject Rights Fulfillment (C7)
Table of contents
- Data Subject Rights Fulfillment (C7)
- Intent
- Summary
- Composes
- Composition logic
- Composition-level invariants
- Examples
- Walkthrough — GDPR Article 15 access request, end to end
- Walkthrough — GDPR Article 17 erasure request, the hold gate firing
- Rejection path — re-fulfillment, wrong right type, incomplete enumeration
- Rejection path — erasure write fails after the purges commit (the orphan)
- CCPA/CPRA — consumer deletion request
- HIPAA §164.524 — access to a designated record set
- Regulated adversarial scenarios
- Generation acceptance
- Edge cases and explicit non-goals
- Standards references
- Status
- Lineage notes
A regulated composition: when a data subject exercises a right of access or erasure, four claims about that subject’s records collide — access (show everything), erasure (remove it, or justify why not), legal hold (you may not remove this), and consent (you are, or are not, allowed to act). C7 is the structure that resolves the collision per record and proves the resolution from the records alone. It composes Selective Disclosure (the disclosure-accounting surface), Defensible Retention (C1, as substrate — reaching Legal Hold, Retention Window, and Audit Trail transitively, and supplying the hold-blocks-purge erasure gate), and Consent (a read-only authority oracle, consulted but never mutated). The load-bearing emergent guarantee has two halves: no-silent-omission — every record in the subject’s enumerated universe carries exactly one recorded, attributed disposition (
included/withheld(reason)for access;erased/retained(reason)for erasure), so no record is quietly dropped from a response; and request ⇔ accountable-complete-fulfillment binding bijection — a fulfillment commits the complete disposition set, every response-disclosure recorded in Selective Disclosure, and the Audit Trail event together or not at all, so there is no fulfilled request without its complete, sealed disposition record and none of the reverse. C7 enforces the structural erasure gate (an Active hold blocks erasure, via C1) and records the asserted disposition and its auditable reason; it does not adjudicate the legal nuance of each exemption — that is counsel’s call, and an Erasure Coordination composing concept, named rather than absorbed.
Intent
Every system that holds personal data must, on demand, answer a data subject exercising a statutory right — and the hard part is not the happy path of handing over or deleting data, it is the conflict the request surfaces. A right-of-access request (GDPR — the EU General Data Protection Regulation — Article 15) says show me everything you hold about me. A right-of-erasure request (GDPR Article 17, the “right to be forgotten”) says delete it. But the same records are often subject to a legal hold that forbids destruction (litigation is anticipated, a regulator is investigating), to a retention obligation that mandates keeping them for a statutory period, and to a web of consent decisions that determine whether the data could lawfully be processed at all. These claims do not merely coexist; on a single record they actively contradict one another. Delete this and you may not delete this cannot both be honored. The system must choose, per record, and — this is the regulated bar — it must be able to prove afterward that the choice it made was the lawful one, from the records alone, without a developer in the room to narrate what the code did.
This is the friction C7 exists to resolve, and naming it precisely is what keeps the composition honest: C7 is not a “rights system”; it is a conflict-resolution system over competing truth claims about a record universe. Four claims collide on the subject’s records — access (Article 15: show everything), erasure (Article 17: remove, or justify non-removal), legal hold and retention (via C1: you cannot remove this, regardless of the clock), and consent (the lawful-basis question: are you allowed to act at all?). The resolution surface is a per-record disposition — a single recorded, attributed verdict for every record in the subject’s enumerated universe — plus a no-silent-omission completeness guarantee that no record escapes the enumeration without a disposition. A DSAR (Data Subject Access Request — the umbrella term for a subject exercising any of these rights) is fulfilled not when data is handed over or deleted, but when every in-scope record carries a disposition an auditor can read and defend.
No single constituent resolves the collision. Selective Disclosure records that a disclosure occurred — to whom, what scope, under what authority — but it does not enumerate a subject’s record universe, does not perform or block erasure, and does not know what a legal hold is. Defensible Retention (C1) owns exactly the erasure-versus-preservation gate: its hold-blocks-purge invariant is the structural rule that delete this yields to you may not delete this, and its Retention Window leg supplies the kept-for-a-statutory-period exemption — but C1 knows nothing of access requests, disclosure accounting, or consent as a lawful basis. Consent owns the grant/revoke/expire lifecycle and the point-in-time check that answers was there a lawful basis? — but it is, by its own specification, not an enforcement surface and not an orchestrator. The structure that enumerates the universe, resolves each record’s competing claims into one disposition, records every response-disclosure, and seals the whole fulfillment as one accountable act belongs to no single constituent. It belongs to the composition, and this composition is that structure.
This is a composition, not a new primitive. Selective Disclosure, Defensible Retention, and Consent are unchanged; C7 is the wiring that makes them coherent as a single rights-fulfillment surface. It introduces emergent actions — receive_request, fulfill_access_request, fulfill_erasure_request, and the read-only disposition_report — that belong to no single constituent and exist only because the three are wired together. The erasure action in particular wraps C1’s purge_record gate: the same hold-blocks-purge decision C1 already makes becomes, at C7’s layer, the mapping from a gate outcome to a recorded per-record disposition (ok → erased, under-legal-hold → retained(legal-hold), not-eligible → retained(retention-obligation)), with C7 adding only the consent-basis branch (Article 17(1)(b) — was consent the only basis, and is it gone?) and the enumeration-and-completeness structure that makes the answer cover the whole universe rather than one record at a time.
A load-bearing scoping decision follows from the reframe. The composition’s spine is Access (Article 15) and Erasure (Article 17) only — the two rights whose claims most sharply collide and whose fulfillment most needs the per-record disposition surface. The other rights in the Article 15–20 family (rectification under Article 16, restriction under Article 18, portability under Article 20, objection under Article 21) are lighter variants of the same fulfillment surface or are named composing concepts; modeling each as a first-class lifecycle would inflate the composition without exercising a structurally new claim-collision. They are named in Edge cases, not absorbed.
What the composition is not: it is not the identity-verification surface that confirms the requester actually is the subject (or their authorized representative) — that is a Party Identity / Actor Identity composing concept, named not absorbed; it is not the legal adjudicator that decides whether a given Article 17(3) exemption genuinely applies (an Erasure Coordination composing concept, and ultimately counsel’s call) — C7 records the asserted disposition and its reason, and routes the legitimacy question to an externally-clearable check; it is not the data-extraction or redaction engine that assembles the access payload (the host’s obligation, signalled by the included dispositions); it is not the deletion engine for records outside the library’s stores (a host obligation named in the completeness boundary); and it is not a statutory-deadline clock that computes or enforces the one-month fulfillment window under Article 12(3) (C7 records received_at and fulfilled_at as the records-alone source; whether the deadline was met is an externally-clearable or composing concept). Each is named explicitly in Edge cases.
Summary
Data Subject Rights Fulfillment is a regulated composition (a spec that wires two or more atoms — freestanding, self-contained pattern specs — together) that solves a problem none of its constituents solves alone: when a person exercises their legal right to see or to delete the personal data an organization holds about them, the organization must work out, for every record, what to do — and prove afterward that it did the lawful thing, using only the records it kept. The difficulty is that the request collides with other rules: some records are under a legal hold that forbids deletion, some must be kept for a legally mandated period, and some were collected under a consent that may since have been withdrawn. C7 resolves this one record at a time. It assigns every record in the person’s data a single disposition — a recorded verdict — and the set of allowed verdicts is fixed: for an access request, a record is included (handed over) or withheld with a stated reason (it implicates a third party, or a legal exemption applies); for an erasure request, a record is erased, or retained with a stated reason (a legal hold blocks deletion, a retention period has not elapsed, or another lawful basis still applies).
It wires three constituents. Selective Disclosure is the running log of every time the person’s data was shared and with whom — read to answer the access right’s “who has my data been disclosed to?” and written to record the act of responding to the request itself. Defensible Retention (composition C1) is the substrate that supplies the deletion gate: its built-in rule that “a record under an active legal hold cannot be purged” is the structural answer to the erasure-versus-preservation collision, and through it C7 reaches Legal Hold, Retention Window, and the tamper-evident Audit Trail without maintaining duplicates. Consent is consulted as a read-only oracle — C7 asks it “was consent the basis for processing this, and is that consent still in force?” to decide whether erasure is actually due, but C7 never changes a consent record.
The composition’s defining emergent guarantee (a property that appears only when the atoms are combined — no single atom carries it) has two halves. No-silent-omission: every record in the person’s enumerated data universe carries exactly one disposition, so nothing is quietly left out of a response — the completeness an auditor checks. Binding bijection: a fulfillment commits the complete set of dispositions, the record of the disclosure to the requester, and the sealed Audit Trail event all together or not at all — so there is never a fulfilled request whose disposition record is missing or incomplete. C7 enforces the structural gate (an active hold blocks erasure) and records each disposition with an auditable reason; it does not rule on the legal fine print of whether a particular exemption truly applies — that is named as counsel’s and a composing pattern’s job, not absorbed here.
Its most common uses are GDPR Article 15 access and Article 17 erasure fulfillment, CCPA/CPRA (the California Consumer Privacy Act, as amended by the California Privacy Rights Act) consumer access and deletion requests, and HIPAA (the US Health Insurance Portability and Accountability Act) §164.524 access to a designated record set. Any system that must answer a data subject’s access or deletion request and prove, from records alone, that every record was dispositioned and that legal holds and retention obligations were honored throughout, is a candidate for this composition.
Composes
-
Selective Disclosure — the disclosure-accounting surface, used in both directions. Read: an access fulfillment queries the Selective Disclosure store by
subject_refto answer GDPR Article 15(1)(c) — the recipients or categories of recipient to whom the personal data have been disclosed — drawn from the records alone. Write: every fulfillment records the act of responding to the requester as oneSelectiveDisclosure.record(subject_ref, recipient = requester, scope, authority)call, so the disclosure of the subject’s own data back to them (or to their authorized representative) is itself an accountable, immutable disclosure event. C7 thereby resolves, in favor of recording, the deployment-policy question Selective Disclosure’s Disclosures to the subject themselves edge case leaves open: a regulated rights-fulfillment surface records its own responses. The composition callsrecordandread. -
Defensible Retention — the regulated retention-governance composition, used here as a substrate: C7 names it the way an atom is named, and reaches Legal Hold, Retention Window, and the Audit Trail substrate transitively through it rather than maintaining separate instances (per the Compositions of compositions convention — see
spec-format.md). C1 is the erasure path. Each in-scope record an erasure request would destroy is gated through C1’spurge_record(retention_id, actor_ref, credential) → ok | rejected(not-known | not-eligible | under-legal-hold | recording-failure), whose outcomes map directly onto C7’s erasure dispositions (the load-bearing wiring decision, below). Through C1, C7 inherits the hold-blocks-purge gate (C1 Invariant 1), the retention-not-elapsed precondition (Retention Window, surfacing asnot-eligible), and the tamper-evident, attributed Audit Trail on which C7 records its own fulfillment events. C7 records those events by callingAuditTrail.record_actiondirectly on the one Audit Trail instance the C1 substrate carries — the established substrate-composition pattern (Multi-Party Approval, the first composition to compose another composition, records its own approval events on the Audit Trail its substrate carries; C7 records itsdsar.*events the same way). The capability is Audit Trail’s own declaredrecord_actionand its Invariant 1 (attribution coverage), reached through the named C1 substrate — not an ambient reach-through and not a passthrough C1 must expose. One substrate instance; no duplicate Audit Trail, Legal Hold, or Retention Window at this layer. -
Consent — a read-only authority oracle, never mutated by C7. The composition calls
Consent.check(subject_ref, purpose, at_time?) → granted | revoked | expired | not-knownandConsent.read(query)to answer one question in the erasure path: was consent the lawful basis for processing this record, and is that consent still in force? — the Article 17(1)(b) determination (erasure is due when the subject withdrew the consent the processing rested on and there is no other lawful ground). Consent is a decision-input oracle, not a data source the composition writes to: a DSAR neither grants, revokes, nor expires consent. (A subject who withdraws consent does so through the Consent & Preference Management composition (C2), whosewithdraw_consentis the mutating surface; C7 reads the resulting state, it does not produce it.) This read-only discipline is load-bearing — it is what keeps Consent a freestanding authority surface rather than an artifact C7 co-owns, and it is stated as an emergent invariant (Consent-non-mutation, below).
The Selective Disclosure store and the Consent store are owned by their respective constituent instances; the Legal Hold, Retention Window, and Audit Trail stores are owned by the C1 substrate. C7 owns no constituent state — it indexes across them with its own emergent maps (request_to_fulfillment, request_to_subject, below) and resolves each in-scope record into a disposition that it records but whose underlying authority lives in a constituent.
A surface C7 needs that no constituent provides is the enumeration of a subject’s record universe with a per-record disposition — the accountable answer to what records about this subject exist, and what did we decide about each? This is a composition-introduced surface at C7’s layer (one of the four legitimate capability-provenance sources — see pressure-testing.md §Capability provenance), and its eventual clean home is a forthcoming Completeness Model atom — accountable enumeration of a record universe with per-record disposition — framed as a shared foundational primitive that C7 and C8 (KYC — Know Your Customer — / Customer Onboarding) both exercise and that C7 merely exposes, not a C7-owned abstraction (the same discipline by which C6 seeded a forthcoming Subset Proof atom rather than letting the ledger own subset-verification). The forthcoming atom is named on the roadmap, not authored here; until it lands there is no live link, and C7 carries the enumeration as a composition-introduced surface bounded by the host-declared record-source registry (Configuration, and the Completeness boundary edge case).
Composition logic
Composition state
The composition owns emergent state that wires the constituents into one queryable rights-fulfillment surface. None of this state belongs to a single constituent.
request_to_subject— map fromrequest_idto{subject_ref, right_type, requester, received_at}. Populated byreceive_request; immutable thereafter. This is the request-identity and intake-provenance index: it records that a rights request was received, for which subject, of which type, from which requester, and when — the records-alone source for the statutory-clock question (when did the clock start?) and the join key from arequest_idback to its subject. Arequest_idpresent here but absent fromrequest_to_fulfillmentis a Received (not-yet-fulfilled) request; present in both is Fulfilled.request_to_fulfillment— map fromrequest_idto the fulfillment record:{right_type, fulfilled_at, dispositions, response_disclosure_id, fulfillment_event_id}. This is the binding backbone.dispositionsis the complete set of per-record verdicts{record_ref, source, disposition, reason}covering the entire enumerated in-scope universe — it is the no-silent-omission surface, the thing an auditor reads to confirm every record was accounted for.sourcenames the registry-declared store or constituent the record was enumerated from (whichrecord_source_registryentry, or the Selective Disclosure / Consent / C1 store);reasoncarries the disposition’s authority reference — a C1 gate outcome, aconsent_idand state, a host-declared basis or exemption citation — so the verdict is self-describing (Invariant 4).response_disclosure_idis the Selective Disclosure record of the response to the requester;fulfillment_event_idis the Audit Trail event that seals the fulfillment and carries the complete disposition set in its payload — sorequest_to_fulfillmentis the queryable mirror of an authoritative sealed event, not an independent store an edit could silently diverge from. Populated by a successfulfulfill_access_requestorfulfill_erasure_requestonly after all constituent writes succeed — its population is the per-action atomicity obligation (Invariant 1). Never modified after insertion; Fulfilled is terminal.
The Selective Disclosure store (disclosure records), the Consent store (consent records), and the C1 substrate’s stores (Legal Hold, Retention Window, Audit Trail emergent state) are owned by their respective constituent instances. C7 duplicates none of them; it indexes across them via the two maps above and carries each record’s disposition in the fulfillment record, while the authority for that disposition — the hold, the retention obligation, the consent state — lives in a constituent and is re-readable there.
The enumerated in-scope universe for a subject_ref is not stored as standing state; it is computed at fulfillment time by the composition-introduced enumeration surface (Composes; the forthcoming Completeness Model atom) over the host-declared record_source_registry plus the constituent stores C7 can name. The fulfillment record’s dispositions set is the durable, records-alone snapshot of that universe at fulfillment time.
Configuration
record_source_registry— the deployment-declared enumeration of the business-record sources over which C7’s completeness guarantee holds, and the per-record surfaces each source exposes. C7 computes a subject’s in-scope universe as the union of (a) the subject’s records in the constituent stores it can name — the Selective Disclosure store, the Consent store, and (for erasure) the Retention Window records under the C1 substrate — and (b) the host business-record stores named in this registry. The registry is the declaring source (capability provenance) for every host-supplied capability the dispositions rest on; each named source must expose, per record: a subject-scoped enumeration surface (therecord_refand itssource); adeclared_basisfield naming the lawful ground(s) for processing the record (consumed by the erasure other-lawful-basis branch — aconsent(purpose)value routes to the Consent oracle, a non-consent value is the ground itself); for erasure, either a C1retention_id(records under C1 retention — the gated path) or a host-owned delete surface (host-managed records — the host performs and attests the delete); and for access, the host’s per-record Article 15(4) third-party-confidentiality and legal-exemption determinations (consumed by the accesswithheld(...)branch). Declaring these surfaces here is what keeps the disposition branches capability-provenance-clean: each disposition’s authority traces to this deployment-declared configuration capability rather than to an ambient “the host knows.” This registry is the load-bearing host obligation: no-silent-omission is a guarantee over the declared universe, and whether the registry names every store actually holding the subject’s data — and whether each host-supplieddeclared_basis/ determination is legally correct — are externally-clearable checks (the host’s, not C7’s, to clear). A store the registry omits is invisible to C7, and a record in it is neither enumerated nor dispositioned — the honest boundary stated in the Completeness boundary edge case, not papered over.audit_trail_retention_policy— inherited, not re-configured. C7 records its fulfillment events (dsar.received,dsar.access_fulfilled,dsar.erasure_fulfilled) on the Audit Trail instance reached transitively through the C1 substrate — the same instance on which C1 records its retention and hold decisions, so a fulfillment event and the per-recordrecord_purgedevents it precipitates share one immutable, sealed log. That instance carries the host’s regulatory retention policy for audit events as itsaudit_trail_retention_policy(the same Configuration value C1 supplies on its own retention and hold events);AuditTrail.record_actiontakes a per-callretention_policyargument, and C7 inherits C1’s configured value and passes it on everydsar.*record_actioncall (the call sites below carryretention_policy = audit_trail_retention_policy) — C7 supplies the inherited value rather than overriding C1’s policy choice. The fulfillment audit events should persist at least as long as the longest retention obligation over any record they disposition — often longer, for post-erasure litigation defensibility (the record is gone; the proof it was lawfully erased must outlive it).
Primitive policies
The composition takes string-typed inputs at its action boundaries; each is validated either at this layer or by a constituent.
request_id— opaque, system-generated byreceive_request; never reused. The key of both composition maps under byte-identity equality; never normalized.subject_ref— opaque reference to the data subject whose records are the universe. Must contain at least one non-whitespace character (invalid-request). Passed toSelectiveDisclosure.record/readandConsent.check/readas theirsubject_ref; equality is opaque byte-identity, not normalized or case-folded. The composition does not validate that the subject exists in any external system — that, and confirming therequesteris the subject or an authorized representative, is a Party Identity / Actor Identity composing concept (Edge cases — Requester identity verification).right_type— one of exactly two named values:access(GDPR Article 15) orerasure(GDPR Article 17). Any other value isinvalid-request. The two-value bound is the spine-scoping decision (Intent); the lighter Article 16–21 rights are named composing concepts, not additionalright_typevalues.requester— non-empty string naming the party who submitted the request (the subject, or an authorized representative — a law firm, a parent for a minor, an executor). Must contain at least one non-whitespace character. Carried inrequest_to_subjectand named as therecipienton the response-disclosure, so the records show to whom the subject’s data was released in fulfilling the request.actor_ref+credential— the operator executing the fulfillment, and their opaque credential. Both flow toAuditTrail.record_action(and the Actor Identity reached transitively through the C1 substrate), which binds the operator cryptographically to every fulfillment event. The composition does not inspect the credential; the substrate validates it and may surfaceinvalid-credential, mapped per the uniform rejection rule below. Whetheractor_refis authorized to fulfill DSARs is an inward-authorization question C7 does not gate — it composes no Permissions instance; operator authorization is a named composing concept (Edge cases — Operator authorization), exactly as C1 leaves hold-placement authorization to a composing Permissions pattern.record_ref— opaque byte-identity for a record in the enumerated universe, surfaced by the enumeration. Equality is byte-identity; no case-folding, normalization, or trimming (inherited from C1’srecord_refidentity discipline). The unit a disposition is recorded against.retention_id— opaque C1 handle for a record under C1 retention, surfaced by the registry for C1-managed records; the argument C7 passes topurge_record. Opaque; never normalized.
No primitive is case-sensitivity-normalized at the composition layer; deployments wanting normalization wire it at the calling layer before invoking composition actions.
Action wiring
The composition exposes four actions: one intake (receive_request), two fulfillment siblings (fulfill_access_request, fulfill_erasure_request), and one read-only query (disposition_report). The two fulfillment actions are siblings over one fulfillment core — they share the enumerate-then-disposition-then-bind structure, the no-silent-omission completeness obligation, and the binding-bijection atomic commit; they differ only in their disposition vocabulary and their downstream effect (access determines and discloses; erasure determines and, for erased records, irreversibly purges through C1). They are kept as two actions rather than one parametrized fulfill_request precisely because that downstream-effect difference is a load-bearing behavioral fork — folding an irreversible purge and a pure disclosure under one parameter would hide exactly the kind of decision Pass 3 exists to surface (the Two siblings, not one parametrized action edge case defends the cut). The emergent invariants are stated over every fulfillment record, so they bind both siblings uniformly.
Uniform record_action rejection-mapping rule. For every AuditTrail.record_action call below (recorded on the substrate Audit Trail instance), the substrate’s rejection taxonomy (invalid-credential | invalid-request | recording-failure) maps uniformly. Where the audit write follows an irreversible constituent effect (an erasure fulfillment whose purge_record calls have already committed), invalid-credential / invalid-request / recording-failure all surface as rejected(recording-failure) at the C7 boundary, with the resulting orphan handled per the Cross-store consistency under partial failure edge case. For receive_request (a single audit write with no prior constituent effect), invalid-credential and invalid-request surface as clean pre-state rejections. Deployments requiring credential pre-validation before any irreversible purge wire an Actor Identity pre-check above C7 (a composing peer).
receive_request
receive_request(subject_ref, right_type, requester, actor_ref, credential) →
{request_id, received_at}
| rejected(invalid-request | recording-failure)
Records that a data subject rights request was received, stamping the intake moment that starts the statutory clock. Steps:
- Validate
subject_ref,requester,actor_refeach non-empty andright_type ∈ {access, erasure}. Any failure →rejected(invalid-request). Stop. - Assign a fresh opaque
request_id. AuditTrail.record_action(action_ref = dsar.received, actor_ref, credential, data = {request_id, subject_ref, right_type, requester, received_at = now}, retention_policy = audit_trail_retention_policy)→event_id. Map per the uniform rule: substrateinvalid-credential/invalid-requestsurface asrejected(invalid-request)(a clean pre-state rejection — no prior constituent effect — mirroring C1’s own boundary treatment of substrateinvalid-credential), andrecording-failureasrejected(recording-failure); on any such failure no map is populated (the request is not resolvable without its intake event). Stop.- Populate
request_to_subject[request_id] = {subject_ref, right_type, requester, received_at = now}only after the intake event lands. - Return
{request_id, received_at}. The request is now Received.
C7 records the intake but does not compute or enforce the Article 12(3) one-month fulfillment deadline — received_at and the later fulfilled_at are the records-alone source from which deadline compliance is an externally-clearable or composing-pattern computation (Edge cases — Statutory deadline is not enforced here).
fulfill_access_request
fulfill_access_request(request_id, actor_ref, credential) →
{request_id, dispositions, response_disclosure_id, event_id}
| rejected(
not-known
| wrong-right-type
| already-fulfilled
| incomplete-enumeration
| recording-failure
)
Resolves a received access request into a complete, accountable per-record disposition set and discloses it to the requester. Steps:
- Resolve
request_idinrequest_to_subject. Absent →rejected(not-known). Ifrequest_idis already inrequest_to_fulfillment→rejected(already-fulfilled)(Fulfilled is terminal — Invariant 6). If the storedright_type ≠ access→rejected(wrong-right-type)(an erasure request must be fulfilled through the erasure sibling). Resolve{subject_ref, requester}. - Enumerate the in-scope universe for
subject_refvia the composition-introduced enumeration surface overrecord_source_registryplus the constituent stores. If any declared source fails to enumerate (a registered store is unreachable), →rejected(incomplete-enumeration); nothing is recorded. Completeness is all-or-nothing at the enumeration boundary — a partial enumeration must never be silently fulfilled as if complete, because that is precisely the silent omission the composition exists to forbid. - Resolve each enumerated record’s access disposition (read-only determinations; no record is mutated by an access fulfillment):
- host-declared third-party-confidentiality implication (GDPR Article 15(4) — the access right shall not adversely affect the rights and freedoms of others) →
withheld(third-party-confidentiality), reason carrying the host’s determination reference; - host-declared legal exemption (a privilege or statutory bar) →
withheld(legal-exemption), reason carrying the citation; - otherwise →
included. Additionally readSelectiveDisclosure.read({subject_ref})to assemble the Article 15(1)(c) answer — the recipients to whom the subject’s data has been disclosed. This recipients answer is part of the access response content (its records-alone source is the Selective Disclosure read), not a per-record disposition; the host assembles it into the export alongside theincludedrecords. To give the recipients limb the same tamper-evidence the disposition set has, the read result (the set of disclosure records returned, or a cryptographic digest of it) is bound into the sealeddsar.access_fulfilledevent at step 4 — so a host that later drops a recipient from the export leaves a detectable seal mismatch, and the 15(1)(c) completeness is records-grounded, not an unsealed host assembly. The disposition set covers every enumerated record (Invariant 2); an enumeration that finds no records is a valid fulfillment with an empty disposition set — the meaningful “we hold no records about you” answer — distinct fromincomplete-enumeration(a declared source failed to respond).
- host-declared third-party-confidentiality implication (GDPR Article 15(4) — the access right shall not adversely affect the rights and freedoms of others) →
- Commit atomically — the binding (Invariant 1): record the response as a disclosure,
SelectiveDisclosure.record(subject_ref, recipient = requester, scope = "dsar:access:designated-record-set", authority = {type: regulatory, reference: "GDPR Article 15"})→response_disclosure_id; thenAuditTrail.record_action(action_ref = dsar.access_fulfilled, actor_ref, credential, data = {request_id, subject_ref, requester, dispositions, recipients_digest, response_disclosure_id, fulfilled_at = now}, retention_policy = audit_trail_retention_policy)→event_id— the complete disposition set and the Article 15(1)(c) recipients digest are carried in the eventdata(for a very large universe, a cryptographic digest of the set, mechanism-neutral exactly as C6 treats its subset proofs), so the set is sealed and tamper-evident and a later silent edit to it breaks the seal; then populaterequest_to_fulfillment[request_id] = {access, fulfilled_at = now, dispositions, response_disclosure_id, fulfillment_event_id = event_id}, which mirrors the authoritative sealed event as the queryable index. A failure of either write after the other began →rejected(recording-failure), orphan per the Cross-store consistency under partial failure edge case. - Return
{request_id, dispositions, response_disclosure_id, event_id}. The request is now Fulfilled. Assembling and transmitting the actual access payload for theincludedrecords is the host’s obligation, signalled by theincludeddispositions; C7 records what was decided and disclosed, not the bytes of the export.
fulfill_erasure_request
fulfill_erasure_request(request_id, actor_ref, credential) →
{request_id, dispositions, response_disclosure_id, event_id}
| rejected(
not-known
| wrong-right-type
| already-fulfilled
| incomplete-enumeration
| recording-failure
)
Resolves a received erasure request into a complete per-record disposition set, irreversibly purging through C1 exactly the records that no claim preserves, and discloses the outcome to the requester. This action wraps C1’s purge_record gate: the same hold-blocks-purge decision C1 already makes becomes the source of the two preservation dispositions. Steps:
- Resolve
request_idinrequest_to_subject;not-known/already-fulfilled/wrong-right-type(here:right_type ≠ erasure) exactly as the access sibling. Resolve{subject_ref, requester}. - Enumerate the in-scope universe as in the access sibling;
incomplete-enumerationon any source failure, nothing recorded. As on the access path, an enumeration that finds no records is a valid fulfillment with an empty disposition set (nothing to erase, nothing retained), distinct fromincomplete-enumeration(a declared source failed to respond). - Resolve each enumerated record’s erasure disposition, first match in this precedence wins (the precedence is stated explicitly so the disposition is deterministic and the recorded reason is the strongest applicable claim):
- Other-lawful-basis (read-only, precedes any purge). Consult the record’s host-declared
declared_basis(a per-record field therecord_source_registrysurface declares — Configuration). A declared non-consent ground still in force (legal-obligation, contract, vital-interests, …) →retained(other-lawful-basis), reason naming the ground; nopurge_recordcall is made. Where the declared basis isconsent(purpose), consult the Consent oracleConsent.check(subject_ref, purpose)and map all four first-class outcomes (never collapse them — the Consent atom madecheck4-valued deliberately):granted→ the consent basis is in force →retained(other-lawful-basis), reason carrying theconsent_id, no purge;revokedorexpired→ the consent basis is gone (withdrawn, or lapsed — Article 17(1)(b)’s “consent withdrawn and no other ground” is satisfied for this ground) → the record falls through to the C1 gate (sub-step 2), where any hold or retention obligation may still preserve it;not-known→ the host declared a consent basis the Consent store has no record of — a registry/Consent disagreement that is dispositioned with an explicitanomaly(consent-basis-not-known)reason and surfaced to the compliance dashboard as a finding, never silently defaulted to either erase or retain (the Consent analog of the C1not-knowncase, Enumeration names a record C1 does not manage). This other-lawful-basis branch is the one disposition C7 adds on top of C1’s gate, and it is read-only — it must precede any purge, because a purge is irreversible and a record another basis preserves must never be probed by destroying it. - Else, attempt the gated purge for a C1-managed record. First confirm the registry-supplied
(record_ref, retention_id)pairing against C1’s authoritativeretention_id→record_refbinding — exposed in C1’spurge_eligible()tuples(retention_id, record_ref, …)for every retention-eligible record (precisely the records a purge can actually destroy, so the confirmation is load-bearing exactly where it can prevent harm). A registry that pairsrecord_refwith aretention_idC1 binds to a differentrecord_refis a mis-pairing surfaced as a finding (Enumeration names a record C1 does not manage), never purged on the registry’s unverified say-so. Then callpurge_record(retention_id, actor_ref, credential)— the sameactor_refandcredentialthat run this fulfillment, so C1’srecord_purgedevent and the C7dsar.erasure_fulfilledevent attribute the destruction to one actor (a generator must not thread a service-account intopurge_recordwhile the operator runs the fulfillment — the two events would disagree on who erased the record). Map the gate outcome to the disposition —ok→erased;under-legal-hold→retained(legal-hold)(Article 17(3)(e) — preservation for the establishment, exercise, or defence of legal claims);not-eligible→retained(retention-obligation)(Article 17(3)(b) — a legal retention obligation).not-knownfrom C1 means the registry named aretention_idC1 does not manage at all — a registry/enumeration inconsistency surfaced as a finding (Enumeration names a record C1 does not manage), not a silent skip.recording-failurefrom C1 is the inherited C1-internal orphan, distinct from C7’s own binding orphan: C1’sRetentionWindow.purgehas already destroyed the record but C1’s ownrecord_purgedaudit write failed (C1’s most consequential atomicity hole), so the record is gone with norecord_purgedevent. C7 fails the fulfillment, but the compensation is two-layered and both layers must be discharged (Cross-store consistency under partial failure). - Host-managed records (enumerated by the registry but not under C1 retention) carry no C1 gate: erasure of the underlying record is the host’s delete obligation, and C7 records the
eraseddisposition (the host performs the delete) or the host-declaredretained(...)disposition (the host asserts a preservation basis), with the host obligation named in the Completeness boundary edge case. The disposition set covers every enumerated record (Invariant 2); theeraseddispositions are irreversible by the time step 4 runs. - Commit atomically — the binding (Invariant 1):
SelectiveDisclosure.record(subject_ref, recipient = requester, scope = "dsar:erasure:outcome", authority = {type: regulatory, reference: "GDPR Article 17"})→response_disclosure_id; thenAuditTrail.record_action(action_ref = dsar.erasure_fulfilled, actor_ref, credential, data = {request_id, subject_ref, requester, dispositions, response_disclosure_id, fulfilled_at = now}, retention_policy = audit_trail_retention_policy)→event_id— the complete disposition set (or its cryptographic digest, for a large universe) is carried in the eventdata, sealed and tamper-evident; then populaterequest_to_fulfillment[request_id], mirroring the authoritative event. The per-recordrecord_purgedevents are already recorded by C1 inside eachpurge_record; thedsar.erasure_fulfilledevent binds the whole disposition set into one sealed fulfillment. A failure after the step-3 purges committed →rejected(recording-failure), the orphan (erased records without the fulfillment binding) handled per the Cross-store consistency under partial failure edge case — the composition’s most consequential atomicity gap, inherited from C1’s own irreversible-purge contract. - Return
{request_id, dispositions, response_disclosure_id, event_id}. The request is now Fulfilled.
disposition_report (read-only)
disposition_report(request_id) →
{status, right_type, received_at, dispositions?, response_disclosure_id?, fulfilled_at?}
| rejected(not-known)
The read-only surface a subject, auditor, or regulator uses to read the outcome of a request. Resolves request_id: absent from request_to_subject → rejected(not-known); present but not yet in request_to_fulfillment → {status: Received, right_type, received_at} (no dispositions yet); Fulfilled → the complete fulfillment record including the per-record dispositions, response_disclosure_id, and fulfilled_at. No Audit Trail record is produced — this is a pure read that changes no state. Logging who read a disposition report and when is a composing access-log concept (Edge cases — Auditing the report reads), named rather than absorbed, mirroring C6’s treatment of its own verification-query reads.
The load-bearing wiring decision — per-record disposition with no-silent-omission, bound atomically; the erasure gate wraps C1
The composition’s structural reason to exist has two halves.
Half 1 — every in-scope record carries exactly one disposition, and the fulfillment binds the complete set atomically. A fulfillment enumerates the subject’s whole in-scope universe and records, for every record, exactly one disposition with an auditable reason; the complete disposition set, the response-disclosure, and the sealed Audit Trail event commit together or not at all.
Principle. A rights response an auditor can trust requires two facts to be inseparable: that every record in the subject’s universe was accounted for (none silently dropped), and that the account is itself immutable, attributed, and tamper-evident. Likely objection: why not let each constituent answer for its own records — Selective Disclosure for disclosures, C1 for retained records — and union the answers? Mechanism that resolves it: because no constituent enumerates the universe, and a union of per-constituent answers has no completeness guarantee — a record in a host store no constituent governs would simply be absent, and absence is invisible to a reader who only sees what was returned. C7 closes this by computing the in-scope universe once over the host-declared registry plus the nameable stores, recording a disposition for every enumerated record, and binding the complete set into one sealed fulfillment event (request_to_fulfillment, populated only after the disclosure and the audit event both land). The enumeration boundary is itself guarded: a source that fails to enumerate yields incomplete-enumeration and records nothing, so a partial universe is never fulfilled as if whole. Result: an auditor reads one fulfillment record and sees a verdict for every record the declared universe contains — no-silent-omission — and that record is non-repudiable and tamper-evident, which no constituent provides alone.
Half 2 — the erasure gate is C1’s hold-blocks-purge decision, wrapped, not re-derived. The disposition that resolves the erasure-versus-preservation collision is read off C1’s purge_record outcome; C7 adds only the upstream other-lawful-basis branch.
Principle. Delete this and you may not delete this cannot both hold; the resolution must be structural and records-checkable, not a runtime check a well-meaning operator can bypass. Likely objection: doesn’t a rights-fulfillment system need its own hold-and-retention logic? Mechanism that resolves it: no — re-deriving hold-checking would duplicate exactly the gate C1 already owns and proves (C1 Invariant 1, hold-blocks-purge; C1’s purge_record is irreversible and self-audits each purge). C7 instead maps the gate’s existing outcomes onto dispositions (ok → erased, under-legal-hold → retained(legal-hold), not-eligible → retained(retention-obligation)), inheriting the gate’s structural guarantee and its Retention Window exemption for free, and adds the single concept C1 does not carry — the Article 17(1)(b) question of whether another lawful basis means erasure was never due (the read-only Consent-oracle branch, which must precede the irreversible purge). This is capability provenance honored: C7’s erasure-validity invariant rests on C1 Invariant 1 and C1’s declared purge_record action — named constituent sources, not an ambient “the system blocks deletion.” Result: the erasure-versus-preservation collision is resolved by the same gate C1 already proves, every preservation disposition traces to a records-checkable C1 outcome, and C7 stays a thin conflict-resolution-and-accounting layer over a proven substrate rather than a re-implementation of it.
Composition-level invariants
These invariants emerge from the composition. None belongs to a single constituent; each requires two or more working together to hold. Each invariant’s Rests on: clause is its capability-provenance record (see pressure-testing.md §Capability provenance): every clause traces to a declared source — a named constituent invariant or action, a deployment-declared configuration capability, or a composition-introduced surface C7 itself owns.
-
Invariant 1 — Request ⇔ accountable-complete-fulfillment binding bijection (load-bearing). The binding — a Fulfilled request’s complete disposition set in
request_to_fulfillment, its response-disclosure (response_disclosure_id), and itsdsar.access_fulfilled/dsar.erasure_fulfilledAudit Trail event — commits together or not at all: every Fulfilled request has exactly one such binding, and everydsar.*_fulfilledevent corresponds to exactly one Fulfilled request whoserequest_idit carries; the binding is bijective. Modulo the inherited irreversible-purge contract: on the erasure path the per-recordpurge_recordcalls (Action wiring,fulfill_erasure_requeststep 3) precede the binding and are irreversible, so a failure of the step-4 binding after some purges have committed is reachable — leaving records irreversiblyerasedwith no fulfillment binding. That state is not a counterexample to the bijection (which is a claim about the binding, not the purges); it is the explicitly-named orphan the Cross-store consistency under partial failure edge case governs by compensation, exactly as C1’s own Invariant 5 holds modulo the Audit Trail partial-attestation contract rather than overclaiming atomicity across an irreversible boundary. The access path carries no such irreversible precursor, so there the binding is atomic without qualification. This is the load-bearing atomicity claim and (with Invariant 2) the formal-model subject — the model verifies the binding bijection and scopes out the inherited purge orphan, exactly as this modulo-clause names; it mirrors C2’s Invariant 3 (revocation-propagation completeness) and C6’s Invariant 1 (disclosure-accountability binding bijection) at the fulfillment boundary. Rests on: Selective Disclosure Invariants 1 and 6 (record immutability, append-only durability), Audit Trail Invariant 1 (attribution coverage) reached through the named C1 substrate per the substrate-composition convention, the composition’srequest_to_fulfillment-population-after-both-writes discipline (Action wiring, step 4), the host transaction boundary, and — for the erasure path’s modulo-clause — C1’s irreversible-purge contract (Edge cases — Cross-store consistency under partial failure). -
Invariant 2 — No-silent-omission (load-bearing). For every Fulfilled request, the fulfillment record’s disposition set carries exactly one disposition for every record in the subject’s enumerated in-scope universe — no enumerated record is absent, and no record carries two dispositions. An enumeration that cannot be completed over the declared universe yields
incomplete-enumerationand produces no fulfillment, so a partial universe is never recorded as if complete. This is the totality/coverage claim the formal model checks alongside the binding (a property C6’s model did not need). Defended in-line: the fulfillment actions enumerate once (step 2, all-or-nothing — a source failure aborts before any disposition or purge), disposition every enumerated record (step 3), and bind the complete set (step 4). Rests on: the composition-introduced enumeration surface (Composes; the forthcoming Completeness Model atom) bounded by the deployment-declaredrecord_source_registryconfiguration capability (Configuration), and the all-or-nothing enumeration guard in the fulfillment actions. The guarantee holds over the declared universe; whether the registry names every store actually holding the subject’s data is an externally-clearable check (Generation acceptance), not a property C7 can self-verify — stated honestly rather than overclaimed. -
Invariant 3 — Erasure validity (over the C1-gated records). No C1-managed record is dispositioned
erasedby an erasure fulfillment while an Active Legal Hold covers it or while its retention obligation has not elapsed; such a record is dispositionedretained(legal-hold)(Article 17(3)(e)) orretained(retention-obligation)(Article 17(3)(b)) instead. C7 re-derives no hold-checking — the disposition is read directly off the C1 gate. The invariant is scoped to C1-managed records because the structural hold-blocks-erasure guarantee is the C1 gate; a host-managed record (enumerated by the registry but not under a C1retention_id) bypasses this gate, so a host-managed record under a hold registered only in a host store and not in C1’s Legal Hold instance is not protected by this invariant. That bypass is a named host obligation and an externally-clearable gap (Edge cases — Host-managed records bypass the C1 hold gate); a deployment that needs the hold guarantee over a record places it under C1 retention so it acquires aretention_idand the gate. Rests on: C1 Invariant 1 (hold-blocks-purge) and C1’s declaredpurge_recordaction, whoseunder-legal-holdandnot-eligiblerejections are the sole source of the two preservation dispositions — named constituent sources, no ambient “the system blocks deletion.” -
Invariant 4 — Disposition groundedness. Every disposition in every fulfillment record traces to a declared authority, never a free-floating assertion: each C1-gated
erased/retained(legal-hold)/retained(retention-obligation)disposition to apurge_recordoutcome on the namedretention_id(arecord_purgedorpurge_blocked_by_holdevent); eachretained(other-lawful-basis)disposition to theConsent.checkstate result (with the governingconsent_idresolved via the pairedConsent.read—checkreturns the four-valued state,readnames the record), or to a host-declared non-consentdeclared_basissurfaced through the registry; eachincluded/withheld(third-party-confidentiality)/withheld(legal-exemption)access disposition to the host’s per-record determination surfaced through the registry; and each host-managederased/retained(...)disposition (the records with no C1retention_id) to the host delete-surface attestation or the host-declareddeclared_basisnamed in the disposition’sreason. No disposition — C1-gated, consent-based, access-determination, or host-managed — is a bare claim; every verdict names the recorded or host-attested authority it rests on. Rests on: C1’spurge_record(C1-gated erasure dispositions), the Consent oracle’scheckandread(the other-lawful-basis branch), and the hostdeclared_basis/ determinations / delete-attestation surfaced through the deployment-declaredrecord_source_registry(access and host-managed dispositions — a declared configuration capability, not an ambient host claim). Mirrors C2’s Invariant 4 (registration grounding); the host-managed-record branch’s authority is host-attested rather than records-checkable, so its legitimacy is an externally-clearable check (Generation acceptance). -
Invariant 5 — Every response-disclosure recorded. Every fulfillment — access or erasure — records its response to the requester as exactly one Selective Disclosure record, bound into the fulfillment record as
response_disclosure_id. The release of the subject’s data, or of the erasure outcome, back to the requester is itself an accountable, immutable disclosure event. Defended in-line: the fulfillment actions’ step 4 callsSelectiveDisclosure.recordbefore the binding completes, and Invariant 1 makes the disclosure and the fulfillment inseparable. This structurally closes, for the DSAR-response case, the deployment-policy question Selective Disclosure’s Disclosures to the subject themselves edge case leaves open — a regulated rights-fulfillment surface records its own responses. Rests on: Selective Disclosure’srecordaction and Invariants 1 and 6, and Invariant 1’s binding. -
Invariant 6 — Fulfillment terminality. A request transitions Received → Fulfilled exactly once, and Fulfilled is terminal. A second
fulfill_*against a Fulfilled request returnsalready-fulfilledand changes no state — no second disposition set, no second response-disclosure, no second fulfillment event. Defended in-line:request_to_fulfillmentis inserted once (Action wiring, step 4) and the fulfillment actions’ step 1 rejects an already-presentrequest_idwithalready-fulfilled. Rests on: the composition-introducedrequest_to_fulfillmentinsertion-once discipline and thealready-fulfilledguard; the request-lifecycle analog of Consent’s Invariant 3 (terminal absorption). -
Invariant 7 — Consent non-mutation. No C7 action grants, revokes, or expires a consent record; Consent is consulted only through
checkandread. The consent state C7 reads is produced elsewhere — a subject’s withdrawal flows through the Consent & Preference Management composition’s (C2)withdraw_consent— never through a DSAR. Defended in-line: Consent appears in the action wiring only asConsent.checkinfulfill_erasure_requeststep 3.1 and (optionally)Consent.read; no action callsgrant,revoke, or any mutating surface. Why load-bearing: it is what keeps Consent a freestanding authority oracle rather than an artifact C7 co-owns. Were C7 to mutate consent, C7 and C2 would both own consent state — the exact ambiguity the read-only-oracle discipline forecloses, and the reason the approved EOS (Essence of Software — Daniel Jackson’s framework for specifying software concepts as freestanding, composable units) cut names Consent a decision-input oracle, not a data source equal to Selective Disclosure. Rests on: the action wiring (the absence of any Consent-mutating call is the structural guarantee). -
Invariant 8 — Constituent invariants preserved. All Selective Disclosure invariants (1–6) hold over the disclosure store; all Consent invariants (1–9) hold over the consent store; all Defensible Retention (C1) invariants (1–8) hold over the substrate, and transitively all Legal Hold, Retention Window, and Audit Trail invariants hold over their instances. C7 weakens no constituent invariant. Rests on: each constituent’s own Generation acceptance bar over its store instance.
The binding bijection (Invariant 1) plus no-silent-omission (Invariant 2) give the accountable-completeness property — every request is resolved into a complete, sealed, per-record account. Erasure validity (Invariant 3) plus disposition groundedness (Invariant 4) give the defensible-resolution property — every verdict, especially every preservation, traces to a records-checkable authority. Response-disclosure recording (Invariant 5) makes the fulfillment itself an accountable disclosure; terminality (Invariant 6) and Consent non-mutation (Invariant 7) close the request lifecycle and hold the oracle boundary; Invariant 8 preserves every constituent guarantee underneath.
Examples
Walkthrough — GDPR Article 15 access request, end to end
A SaaS (Software-as-a-Service) company deploys C7 over its customer data. Its record_source_registry names four subject-scoped sources: the CRM (Customer Relationship Management) store, the support-ticket store, the Selective Disclosure store, and the Consent store.
-
Intake. A user submits an access request through the privacy portal. The DSAR officer calls
receive_request(subject_ref = "user-5521", right_type = "access", requester = "user-5521 (verified via privacy portal)", actor_ref = "dsr_officer_k", credential = <cred>)→{request_id = "dsar-3001", received_at = "2026-06-08T09:00:00Z"}. The substrate Audit Trail recordsdsar.received; the request is Received. - Fulfillment. The officer calls
fulfill_access_request("dsar-3001", "dsr_officer_k", <cred>). The composition:- Enumerates
user-5521’s in-scope universe over the registry → five records:r1(profile, CRM),r2(an open support ticket),r3(a support ticket that quotes a second customer’s account details),r4(a billing dispute record flagged by the host as attorney-client privileged),r5(the marketing-consent record). All four sources enumerate successfully — noincomplete-enumeration. - Dispositions each record (read-only determinations):
r1 → included;r2 → included;r3 → withheld(third-party-confidentiality)(Article 15(4) — releasing it would expose the second customer’s data), reason carrying the host’s15(4)determination reference;r4 → withheld(legal-exemption), reason carrying the privilege citation;r5 → included. It also readsSelectiveDisclosure.read({subject_ref: "user-5521"})→ two prior third-party disclosures (an analytics vendor, a payment processor), which become the Article 15(1)(c) recipients portion of the response. - Commits atomically:
SelectiveDisclosure.record(subject_ref = "user-5521", recipient = "user-5521 (verified via privacy portal)", scope = "dsar:access:designated-record-set", authority = {type: regulatory, reference: "GDPR Article 15"})→disc-9001; thenAuditTrail.record_action(action_ref = dsar.access_fulfilled, actor_ref = "dsr_officer_k", <cred>, data = {request_id: "dsar-3001", dispositions: <the complete five-record set, summary: 3 included / 2 withheld>, response_disclosure_id: "disc-9001", fulfilled_at})→ev-7001; thenrequest_to_fulfillment["dsar-3001"] = {access, fulfilled_at, dispositions (all five), response_disclosure_id: "disc-9001", fulfillment_event_id: "ev-7001"}. The request is now Fulfilled. - Returns the five dispositions,
disc-9001, andev-7001.
- Enumerates
- The auditor reads the outcome.
disposition_report("dsar-3001")returns one verdict for each of the five enumerated records — Invariant 2 (no-silent-omission): nothing was quietly dropped, and the two withheld records carry a stated reason rather than vanishing from the response. The host then assembles and transmits the actual export for the threeincludedrecords (the export bytes are the host’s job; C7 recorded what was decided and disclosed).
Walkthrough — GDPR Article 17 erasure request, the hold gate firing
A bank deploys C7 over its customer records; the C1 substrate runs hold_check_mode = strict (the required posture under litigation exposure). A customer requests erasure.
-
Intake.
receive_request(subject_ref = "cust-8830", right_type = "erasure", requester = "cust-8830", actor_ref = "dsr_officer_m", credential = <cred>)→{request_id = "dsar-4002", received_at}.dsar.receivedrecorded; Received. - Fulfillment.
fulfill_erasure_request("dsar-4002", "dsr_officer_m", <cred>). The composition enumerates four in-scope records and resolves each by the disposition precedence:r1— a marketing profile under C1 retentionret-r1(retention elapsed, no hold), declared basisconsent(marketing:email). Other-lawful-basis probe:Consent.check("cust-8830", "marketing:email")→revoked, and no other basis is declared → erasure is due.purge_record(ret-r1, "dsr_officer_m", <cred>)→ok→erased. (C1 records its ownrecord_purgedevent withhold_check_result: empty.)r2— a transaction record underret-r2, covered by an Active litigation hold. Other-lawful-basis: none.purge_record(ret-r2, …)→under-legal-hold→retained(legal-hold)(Article 17(3)(e)), reason carrying the blockinghold_id. The hold gate fires — this is the collision C7 exists to resolve, read directly off C1’s gate. (C1 records apurge_blocked_by_holdevent.)r3— a KYC identity record underret-r3, a 5-year retention obligation not yet elapsed. Other-lawful-basis: none asserted.purge_record(ret-r3, …)→not-eligible→retained(retention-obligation)(Article 17(3)(b)).r4— a fraud-monitoring record whose declared basis islegal-obligation(AML — Anti-Money-Laundering — monitoring), a non-consent lawful ground still in force. Other-lawful-basis probe matches first →retained(other-lawful-basis)(Article 17(1)(b) — a ground for processing persists); nopurge_recordcall is made forr4.- Commits atomically:
SelectiveDisclosure.record(subject_ref = "cust-8830", recipient = "cust-8830", scope = "dsar:erasure:outcome", authority = {type: regulatory, reference: "GDPR Article 17"})→disc-9002; thenAuditTrail.record_action(action_ref = dsar.erasure_fulfilled, …, data = {request_id: "dsar-4002", dispositions: <the complete four-record set, summary: 1 erased / 3 retained>, response_disclosure_id: "disc-9002", fulfilled_at})→ev-7002; thenrequest_to_fulfillment["dsar-4002"]is populated. Fulfilled.
- The outcome is defensible from the records.
disposition_report("dsar-4002")shows all four records dispositioned (Invariant 2): oneerased, threeretainedwith three different reasons, each traceable (Invariant 4) —r2andr3to their C1purge_recordoutcomes,r4to the host-declared AML basis,r1’s erasure to arecord_purgedevent whosehold_check_result: emptyproves the gate passed. No held or retention-bound record was erased (Invariant 3). The customer is told, in the response disclosure, exactly what was deleted and what was kept and why.
Rejection path — re-fulfillment, wrong right type, incomplete enumeration
- Already fulfilled (terminal). A retry:
fulfill_erasure_request("dsar-4002", …)→rejected(already-fulfilled). No second purge, no second disclosure, no second event —r1is not erased twice (it is already gone); the single fulfillment from the first call stands (Invariant 6). - Wrong right type. For a Received, not-yet-fulfilled erasure request — say
dsar-4003, intake recorded but no fulfillment yet —fulfill_access_request("dsar-4003", …)→rejected(wrong-right-type); the access sibling refuses to fulfill an erasure request. Nothing is recorded. (Against an already-fulfilled request the step-1 precedence returnsalready-fulfilledbefore it reaches theright_typecheck — terminality dominates wrong-right-type — so the wrong-right-type path is exercised only by a still-Received request.) - Incomplete enumeration (the no-silent-omission guard). During an access fulfillment, one registered source — the support-ticket store — is unreachable. The enumeration cannot be completed over the declared universe →
rejected(incomplete-enumeration). No disposition is recorded, no response-disclosure is written, the request stays Received. A partial universe is never fulfilled as if whole — the exact silent omission the composition forbids. The officer retries once the store recovers.
Rejection path — erasure write fails after the purges commit (the orphan)
An erasure fulfillment purges r1 (step 3 → ok, erased) and then, at step 4, the dsar.erasure_fulfilled Audit Trail write returns recording-failure (the seal mechanism is briefly unreachable). The composition returns rejected(recording-failure). The result is an orphan: r1 is irreversibly erased (its C1 record_purged event exists) but request_to_fulfillment["dsar-4002"] has no binding and no dsar.erasure_fulfilled event. This is the composition’s most consequential atomicity gap, inherited from C1’s own irreversible-purge contract; the Cross-store consistency under partial failure edge case governs compensation (retry the fulfillment-event write until it lands; surface the orphan to the compliance dashboard; the recovered event carries cascade_recovery = true). The TLA+ (Temporal Logic of Actions — a formal specification language for concurrent systems) model and its buggy twins make mechanical that a non-atomic fulfillment commit is reachably unsafe — see Lineage §Formal model.
CCPA/CPRA — consumer deletion request
A California consumer submits a deletion request under the CCPA (California Consumer Privacy Act), as amended by the CPRA (California Privacy Rights Act). The erasure path runs unchanged; CCPA §1798.105(d)’s retained-purpose exceptions (completing a transaction, detecting security incidents, complying with a legal obligation) map onto the same retained(...) dispositions the GDPR Article 17(3) exemptions do — a record kept to satisfy a legal obligation is retained(retention-obligation) via the C1 gate, a record kept under a non-consent basis is retained(other-lawful-basis). The response disclosure carries authority = {type: regulatory, reference: "CCPA §1798.105"}. The cross-domain structural identity is the point: the disposition surface is regulation-agnostic; only the cited authority on the response and the host’s exemption determinations change.
HIPAA §164.524 — access to a designated record set
A patient requests access to their records under HIPAA §164.524 (a covered entity must provide access to protected health information in a designated record set). The access path runs; §164.524(a)(1) grounds for denial — psychotherapy notes, information compiled for legal proceedings — map onto withheld(legal-exemption) dispositions with the citation as the reason. The Selective Disclosure read that answers GDPR Article 15(1)(c) does double duty here as the HIPAA §164.528 accounting-of-disclosures surface. The same per-record disposition structure serves both regimes.
Regulated adversarial scenarios
Three scenarios the composition must survive in regulated contexts.
Regulator audit — “prove every record in the subject’s universe was dispositioned, and that no held or retention-bound record was erased.” A DPA (Data Protection Authority — a national GDPR regulator) examines a fulfilled erasure request. It calls disposition_report(request_id): by Invariant 2 (no-silent-omission), every enumerated record carries exactly one disposition — there is no record the response silently dropped. For every erased disposition, the auditor cross-reads the C1 substrate’s record_purged event and confirms hold_check_result: empty (Invariant 3, resting on C1 Invariant 1 — hold-blocks-purge). For every retained(legal-hold) / retained(retention-obligation), it confirms the then-Active hold or the unelapsed retention via C1’s stores. AuditTrail.verify_record on the dsar.erasure_fulfilled event confirms the disposition set was not altered after the fact. The examiner consults no source code or runbooks; every claim is verified from the records by virtue of Invariants 2, 3, and 4.
Disputed erasure — the data subject challenges a retention. A subject’s representative challenges: “you claim you could not delete record r2 — prove a hold actually existed.” The system presents the retained(legal-hold) disposition with its reason (the blocking hold_id) and, via the C1 substrate, LegalHold.read({record_ref: r2}) — the Active hold with placed_by, hold_reason, placed_at, and case_ref, all immutable by Legal Hold’s Invariant 1. AuditTrail.verify_record on the dsar.erasure_fulfilled event confirms the disposition was not fabricated or back-filled. The challenge cannot be sustained without claiming the entire hold store was fabricated, at which point the Tamper Evidence seal (via the C1 substrate) is the structural rebuttal — the same rebuttal chain C1’s own disputed-destruction scenario establishes, with C7 adding the disposition binding (Invariant 4) that ties the retention claim to a specific recorded hold. The symmetric challenge — “you erased a record you should have kept” — is answered by the dsar.erasure_fulfilled event plus the C1 record_purged event whose hold_check_result: empty proves the gate passed at purge time.
Breach or incident investigation — “during the compromise window, was any held record erased under cover of a DSAR?” An investigator suspects an attacker used forged erasure requests to destroy records under legal hold. They query dsar.erasure_fulfilled events in the window (reached through the substrate Audit Trail in Event Log insertion order) and, for each erased disposition, cross-read the corresponding C1 record_purged event’s hold_check_result. A held record showing erased would be the smoking gun — but Invariant 3 forecloses it structurally: the C1 gate would have returned under-legal-hold and yielded retained(legal-hold), never erased. Because the disposition set is part of the hashed dsar.erasure_fulfilled payload, an attempt to silently shrink the set (to hide an improperly-erased record) breaks the seal — the same append-only, sealed-log rebuttal C2 and C6 rely on. The forensic window is bounded by the substrate’s seal cadence; the newest fulfillments in the unsealed tail carry per-event immutability but become seal-verifiable only at the next cadence.
Generation acceptance
A derived implementation of C7 is acceptable — in the regulator-acceptance sense — when an external auditor, given the composition’s emergent state plus the Selective Disclosure, Consent, and Defensible Retention (C1) substrate stores, can do all of the following without recourse to source code, runbooks, or developer narration.
Audit-Trail-traversal-clearable checks
These checks an auditor answers by reading the composition’s records — the two emergent maps plus the Selective Disclosure store and the C1 substrate (including the Audit Trail reached through it).
-
Fulfillment binding coverage. For every Fulfilled request in
request_to_fulfillment, confirm exactly onedsar.access_fulfilledordsar.erasure_fulfilledAudit Trail event carries itsrequest_id, thatAuditTrail.verify_recordreturnsverifiedfor it, and that itsresponse_disclosure_idresolves to a Selective Disclosure record. A Fulfilled request with no fulfillment event, with more than one, or with a danglingresponse_disclosure_idis a conformance failure (Invariant 1). The inverse: everydsar.*_fulfilledevent names arequest_idpresent inrequest_to_fulfillment. -
Disposition completeness (no-silent-omission). For every fulfillment record, confirm every record in the disposition set carries exactly one disposition drawn from the right-type’s vocabulary (access: includedwithheld(third-party-confidentiality)withheld(legal-exemption); erasure:erasedretained(legal-hold)retained(retention-obligation)retained(other-lawful-basis), plus the registry/constituent-disagreement dispositionanomaly(…)— e.g.anomaly(consent-basis-not-known), or the unknown-retention / mis-pairing anomaly — that an enumerated record carries per Action wiring step 3, surfaced as a finding and never silently erased or retained), that norecord_refappears twice, and that the set’s cardinality equals the enumerated-universe size recorded in the sealed fulfillment event. The completeness re-check is right-type-specific, because re-enumeration is only valid where nothing was destroyed: for access, re-enumerate over the samerecord_source_registryand confirm no record present in the re-enumeration (modulo records created since fulfillment) is absent from the disposition set — a present-but-absent record is a coverage failure. For erasure, theerasedrecords no longer exist, so re-enumeration is not the test (it would false-positive every erased record as “missing”); instead confirm the sealed disposition-set cardinality equals the recorded enumerated-universe size, and cross-check eacheraseddisposition against a C1record_purgedevent — completeness for the erased subset rests on the sealed-at-fulfillment-time disposition set (Invariant 2 via the binding, Invariant 1), not a post-hoc re-enumeration of destroyed records. Either way a record dropped from the disposition set is a coverage failure (Invariant 2). -
Erasure-validity cross-check. For every
eraseddisposition, confirm the C1record_purgedevent for that record’sretention_idcarrieshold_check_result: empty(the gate passed). For everyretained(legal-hold), confirm apurge_blocked_by_holdevent whosehold_check_resultnames a then-Active hold; for everyretained(retention-obligation), confirm the record’s retention was unelapsed atfulfilled_at. Aneraseddisposition over a record that had an Active hold at fulfillment time is a conformance failure (Invariant 3, resting on C1 Invariant 1). -
Disposition groundedness. For every disposition, confirm its reason traces to a recorded authority: erasure dispositions to a C1
purge_recordoutcome (arecord_purgedorpurge_blocked_by_holdevent) or, forretained(other-lawful-basis), to aConsent.check-derivable state or a host-declared non-consent basis named in the reason; accesswithheld(...)dispositions to the host determination reference named in the reason. A disposition whose reason names no recoverable authority is a conformance failure (Invariant 4). -
Response-disclosure coverage. For every fulfillment, confirm
response_disclosure_idresolves to a Selective Disclosure record namingrecipient = requester, the appropriate regulatoryauthority, and ascopeidentifying the fulfillment, and that thedsar.*_fulfilledevent references it. A fulfillment with no bound response-disclosure is a conformance failure (Invariant 5). - Constituent Generation acceptance bars. Verify each constituent’s own Generation acceptance bar over its store: Selective Disclosure’s six checks, Consent’s seven checks, and Defensible Retention’s bar (which transitively clears Legal Hold, Retention Window, and Audit Trail). C7’s invariants depend on the correctness of the constituents’ invariants.
Externally-clearable checks
These audit questions arise around C7 but cannot be answered from the composition’s records alone — they are the composition’s named audit-gaps, each routed to the evidence that owns it.
- Whether the
record_source_registrynames every store holding the subject’s data. C7’s no-silent-omission (Invariant 2) is complete over the declared universe; whether that universe is the whole universe — that no store quietly holds the subject’s data outside the registry — requires the host’s data-inventory or data-map, not C7’s records. This is the load-bearing completeness-boundary audit-gap (Edge cases — Completeness boundary); a record in an undeclared store is invisible to C7 by construction. - Whether a
withheld(...)orretained(other-lawful-basis)determination was legally correct. C7 records the asserted disposition and its reason; whether Article 15(4) third-party confidentiality genuinely applied, whether a claimed privilege genuinely held, or whether a claimed non-consent basis genuinely justified retention under Article 17(1)(b) requires legal analysis — an Erasure/Access Coordination composing concept (Edge cases — Erasure Coordination is the legal adjudicator), paralleling C1’s whether the retention policy was correctly chosen and Selective Disclosure’s authority legitimacy is unclearable. - Whether the
requesterwas the subject or a duly authorized representative. C7 records the asserted requester and names it the disclosure recipient; verifying that identity is a Party Identity / Actor Identity composing concept (Edge cases — Requester identity verification). - Whether the
actor_refwas authorized to fulfill DSARs. C7 attributes the operator via the substrate’s Actor Identity but does not gate on inward authorization; whether the operator was permitted to act requires a Permissions instance scoped to DSAR-fulfillment authority (Edge cases — Operator authorization). - Whether the statutory deadline was met. C7 records
received_atandfulfilled_at; whether their difference satisfies the GDPR Article 12(3) one-month window (or its CCPA 45-day analog) is a computation over the records plus the regulation that C7 does not perform or enforce (Edge cases — Statutory deadline is not enforced here).
Edge cases and explicit non-goals
-
The four-claim conflict and disposition precedence. When access, erasure, legal hold/retention, and consent all bear on one record, C7 resolves them into one disposition by a stated precedence so the verdict is deterministic and the recorded reason is the strongest applicable claim. For erasure the precedence is: (1) other-lawful-basis (a persisting non-consent ground, or a still-
grantedconsent) →retained(other-lawful-basis), checked first and read-only because it determines whether erasure is due at all and must precede the irreversible purge; (2) the C1 gate’sunder-legal-hold→retained(legal-hold); (3) the C1 gate’snot-eligible→retained(retention-obligation); (4)erased. A record under both a hold and another lawful basis isretained(other-lawful-basis)by precedence — but the auditor can still observe the hold via the C1 substrate, because C7’s disposition records the governing reason while the constituent stores retain the full set of applicable claims. The precedence is a recording convention, not a legal ranking; C7 does not assert that one exemption legally dominates another, only that it records one governing reason and leaves the constituent evidence intact for the rest. -
Completeness boundary — host records outside the library are a named host obligation. C7’s no-silent-omission guarantee (Invariant 2) holds over the universe the
record_source_registrydeclares: the Selective Disclosure store, the Consent store, the C1-managed retention records, and the host business-record stores the registry names. A store the registry omits is invisible to C7 — its records are neither enumerated nor dispositioned, and C7 cannot detect their absence (you cannot enumerate what you were never told about). This is stated honestly rather than overclaimed: C7 does not guarantee it found all of a subject’s data across an enterprise; it guarantees it dispositioned every record in the declared universe, completely and atomically. Whether the registry is itself complete — names every store actually holding the subject’s data — is the host’s data-inventory obligation and an externally-clearable check (Generation acceptance). A deployment that under-declares the registry produces fulfillments that are internally complete but globally partial; closing that gap is the host’s data-mapping discipline, not a property C7 can self-enforce. -
The enumeration-with-disposition surface is composition-introduced; a forthcoming Completeness Model atom is its eventual home. The capability enumerate a subject’s record universe and attach a per-record disposition is introduced at C7’s layer (a composition-introduced surface — one of the four legitimate capability-provenance sources). No constituent provides it: Selective Disclosure enumerates disclosures, Consent enumerates consents, C1 enumerates retentions, but none enumerates the universe with a disposition per record. The clean eventual home is a forthcoming Completeness Model atom — accountable enumeration of a record universe with per-record disposition — the structural sibling of the forthcoming Subset Proof atom C6 seeded. It is deliberately framed as a shared foundational primitive that C7 and C8 (KYC / Customer Onboarding) both exercise and that C7 merely exposes — naming it a C7-owned abstraction would let the first system that needs it capture an ontology that belongs to the library, the same ontology-capture C6 avoided by not making subset-verification ledger-owned. The atom is named on the roadmap, not authored here; until it lands there is no live link, and C7 carries the surface as composition-introduced, bounded by the registry.
-
Erasure Coordination is the legal adjudicator; C7 records, it does not rule. C7 enforces the structural gate (an Active hold blocks erasure, via C1) and records the asserted disposition with its reason. It does not adjudicate the legal nuance of whether a given Article 17(3) exemption genuinely applies, whether a claimed lawful basis genuinely justifies retention, or whether an Article 15(4) third-party interest genuinely outweighs the access right. Those are legal determinations — counsel’s call, and an Erasure Coordination composing concept (named, forthcoming). C7’s contribution is to make the determination auditable: the disposition and its reason are recorded and sealed, so a later legal review starts from a complete, immutable account of what was decided and why, rather than reconstructing it. The legitimacy of each determination is the externally-clearable check; the recording of it is C7’s contract.
-
Cross-store consistency under partial failure. The fulfillment actions write across stores in sequence. For access, the writes are
SelectiveDisclosure.recordthenAuditTrail.record_actionthen therequest_to_fulfillmentpopulation — all compensable: a failure between them leaves no irreversible effect, the second write is retried against intact state, and an orphan (a response-disclosure with no fulfillment event) is a compliance finding resolved by compensating the audit write. For erasure, the step-3purge_recordcalls are irreversible (C1’s Purged state is terminal), and there are two distinct orphan layers a generator must not conflate: - Layer 1 — the C1-internal orphan. If
purge_recordreturnsrecording-failure, C1’sRetentionWindow.purgehas already destroyed the record but C1’s ownrecord_purgedaudit write failed — a destroyed record with norecord_purgedevent, C1’s own most-consequential atomicity hole. This orphan is inside C1; C7 cannot compensate it by retrying thedsar.erasure_fulfilledevent (a C7-level event does not supply the missing C1record_purged). C7 fails the fulfillment, surfaces the C1-internal orphan (the destroyedrecord_refwith norecord_purged) to the compliance dashboard, and routes its recovery to C1’s own compensation discipline — the FRCP-grade alerting condition C1 names. - Layer 2 — the C7 binding orphan. If the per-record purges all committed cleanly (each with its
record_purgedevent) but the step-4dsar.erasure_fulfilledwrite then fails, the records are erased with no C7 fulfillment binding. This is C7’s own orphan: the implementation (a) retries thedsar.erasure_fulfilledwrite until it lands, (b) surfaces the request and the already-erasedrecord_refs as a high-priority finding, and (c) marks the recovered eventcascade_recovery = trueso an auditor distinguishes a clean fulfillment from a recovered one.
The two layers have different owners and different recovery surfaces; an implementation that retries only the C7 event leaves a Layer-1 destroyed-record-without-record_purged orphan undischarged — the exact spoliation-evidence gap C1 flags. Deployments under litigation exposure treat the gap window between the first irreversible purge and the fulfillment-event landing as a hard alerting condition. The host transaction boundary is what makes the access-path writes, and the erasure-path binding (disposition set + disclosure + event), commit together in the conforming case.
-
Two siblings, not one parametrized action.
fulfill_access_requestandfulfill_erasure_requestcould have been onefulfill_request(request_id, …)branching on the storedright_type. They are kept separate because their downstream effects differ in kind: access determines and discloses (no record is mutated), while erasure determines and, forerasedrecords, irreversibly purges through C1. Folding an irreversible destruction and a pure disclosure under one parameter would hide a load-bearing behavioral fork behind a flag — a generator (or a reader) would have to trace the parameter to discover that one path destroys data and the other does not, which is exactly the hidden-decision smell Pass 3 exists to surface. Two crisp actions, each with its own disposition vocabulary and rejection nuance, make the fork explicit at the signature; the shared enumerate-disposition-bind machinery lives once in the load-bearing wiring decision and the emergent invariants (stated over every fulfillment record), so the siblings duplicate no logic — only the disposition vocabulary and the downstream effect differ. -
Requester identity verification is a composing concept. C7 records the asserted
requesterand names it the disclosure recipient; it does not verify that the requester is the subject or a duly authorized representative (a parent for a minor, an executor for a deceased subject, a law firm under power of attorney). Releasing a subject’s data to an impostor, or erasing it on a forged request, is the catastrophic DSAR failure — and its prevention is identity verification, a Party Identity / Actor Identity composing concept wired ahead ofreceive_request. C7 attributes the operator who runs the fulfillment (via the substrate) and records the asserted requester; binding the requester to a verified identity is the composing layer’s obligation, and verifying it is an externally-clearable check. -
Operator authorization is a composing concept. Whether the
actor_refrunning a fulfillment is authorized to fulfill DSARs is an inward-authorization question C7 does not gate — it composes no Permissions instance (the approved EOS cut is Selective Disclosure + Defensible Retention + Consent). The operator is attributed cryptographically via the substrate’s Actor Identity, so an auditor can always answer who ran the fulfillment; whether they were permitted to requires a Permissions instance scoped to DSAR-fulfillment authority, a composing pattern exactly as C1 leaves hold-placement authorization to a composing Permissions pattern. Keeping Permissions out of the cut is deliberate — adding it would make C7 a four-constituent composition to gate something every administrative action shares, better handled once at a composing administrative layer. -
Statutory deadline is not enforced here. GDPR Article 12(3) requires fulfillment within one month of receipt (extendable to three for complex requests); CCPA sets 45 days. C7 records
received_at(atreceive_request) andfulfilled_at(atfulfill_*) as the records-alone source for deadline compliance, but it does not compute the deadline, flag an overdue request, or block a late fulfillment. Deadline tracking — a clock that derives a due date fromreceived_at, surfaces overdue requests, and escalates — is a separate concept (a forthcoming Regulatory Deadline / SLA — Service-Level Agreement — clock pattern, or a host dashboard reading C7’s timestamps); absorbing it would pull C7 into deadline-computation and overdue-state management it has no reason to own. The timestamps are the bridge; the clock is a composing concept. -
Enumeration names a record C1 does not manage, or mis-pairs it. Two registry/C1 disagreements are findings, never silent skips. (a) Unknown retention. If the registry surfaces a
retention_idandpurge_recordreturnsnot-known, the registry asserted C1 management C1 does not have. (b) Mis-pairing. If the registry pairs arecord_refwith aretention_idthat C1’sretention_to_recordmaps to a differentrecord_ref, the registry’s pairing is wrong — purging on it would destroy the wrong record while recordingerasedagainst the named one. C7 confirms the(record_ref, retention_id)pairing against C1’s authoritative binding — C1’spurge_eligible()exposes theretention_id→record_refpairing for every retention-eligible record, exactly the records a purge can destroy — before purging (Action wiring, step 3.2); a mismatch is dispositioned with an explicit anomaly reason and surfaced to the compliance dashboard, not purged. Both cases breach no-silent-omission if dropped and hide a registry misconfiguration if treated as host-managed; reconciling the registry against the C1 substrate is the host’s configuration obligation. -
Host-managed records bypass the C1 hold gate. A record enumerated by the registry but not placed under C1 retention (no
retention_id) is dispositioned through the host delete surface (erasure) or host determination (access), not through C1’spurge_record— so the hold-blocks-purge gate (C1 Invariant 1) does not run for it, and Invariant 3 is explicitly scoped to exclude it. Consequence: a host-managed record under a preservation hold registered only in a host store — never placed in C1’s Legal Hold instance — could be host-erasedwith no gate firing. C7 cannot close this from inside: it has no hold oracle for records outside C1. The honest boundary: the structural hold guarantee covers exactly the C1-managed records, and a deployment that needs it over a record must place that record under C1 retention (giving it aretention_idand the gate). Whether every hold-bearing record is in fact under C1 — rather than held only in a host store C7 cannot gate — is an externally-clearable check, parallel to the Completeness boundary registry-completeness gap. A host-managederaseddisposition is therefore a host-attested outcome, not a records-alone-provable one (Invariant 4; Generation acceptance externally-clearable checks). -
disposition_reportread-authorization and read-auditing are composing concepts.disposition_reporttakes only arequest_idand is a pure read that records nothing. It deliberately does not gate on who is reading — read-authorization is a composing concept, the same cut C7 makes for operator authorization (no Permissions instance in the constituent set) and requester identity (a Party/Actor Identity concept). This is load-bearing to state plainly, because a disposition report is not inherently low-sensitivity: it exposes the existence andhold_idof legal holds over a subject (litigation intelligence), the privilege citations behindwithheld(legal-exemption), the lawful bases behind everyretained(...), and — for a fulfilled erasure — it may be the only surviving description of records that no longer exist. A deployment therefore should gatedisposition_reportbehind authorization that confirms the reader is the subject (or a duly authorized representative, the same verification fulfillment needs) or a permitted auditor, and should consider an access-log over the reads (mirroring C6’s verification-query reads and Audit Trail’s Failed-Attempt Log concept). C7 names the gate as required-by-the-deployment rather than asserting the read is safe ungated;request_idbeing opaque is not an access-control substitute. C7’s own audited surface is the fulfillment (received, access-fulfilled, erasure-fulfilled), not queries against it. -
The lighter Article 15–20 rights are named composing concepts, not additional spines. C7’s spine is Access (Article 15) and Erasure (Article 17). Rectification (Article 16) is a record amendment whose accountability — that a correction was made, by whom, when — is a Selective-Disclosure-adjacent or Audit-Trail-recorded concept, not a per-record-disposition collision; Restriction (Article 18) is a processing-suppression flag closer to Consent/C2’s gate than to a fulfillment; Portability (Article 20) is an export-format concept over the same
includedset Access already disposions; Objection (Article 21) is a lawful-basis re-evaluation that feeds the same other-lawful-basis branch erasure already consults. Each is a lighter variant of, or a feeder into, the surface C7 already provides; modeling each as a first-classright_typewould inflate the composition without exercising a structurally new claim-collision. They are named here and left to composing patterns (or to a later extension of this composition) rather than absorbed. -
Access payload assembly and redaction are the host’s. For
includedaccess dispositions, C7 records that the record is to be disclosed; it does not retrieve, format, redact, or transmit the underlying data. Assembling the Article 15 export — gathering the bytes, applying any field-level redaction within an included record, delivering it in a portable format — is the host’s obligation, signalled by theincludeddispositions, exactly as Selective Disclosure records that a disclosure occurred without performing it. C7’s contract is the disposition and its accounting, not the export mechanics. -
A Fulfilled request is a point-in-time snapshot; later records are not retroactively covered. Fulfillment is terminal (Invariant 6): the disposition set is the universe as enumerated at
fulfilled_at. Records created after fulfillment — a new support ticket, a new transaction — are not retroactively dispositioned by the closed request; a subject wanting them addressed submits a new request. This is the correct model (a request answers the state at the time it was answered), and it parallels Consent’s most-recent-grant semantics and Selective Disclosure’s point-in-time disclosure history: the records faithfully document what was true when the request was fulfilled, not a perpetually-updating view. -
Concurrency. Two concurrent
fulfill_*calls against the samerequest_idmust be serialized: the first transitions the request to Fulfilled, the second observesalready-fulfilled(Invariant 6) — implementations serialize onrequest_id, exactly as C1 serializes its hold-check-and-purge onrecord_ref. Concurrent fulfillments for different requests (even for the same subject) do not conflict; each enumerates and binds independently. A concurrent consent withdrawal (through C2) and an erasure fulfillment that reads the Consent oracle are not a race in the harmful sense: the oracle read is point-in-time, and whichever consent state the read observes is the state recorded as the basis for that record’s disposition — a withdrawal landing after the read does not retroactively change a disposition already bound, and the subject’s remedy for a record retained under a basis that has since changed is a new request, per the point-in-time snapshot rule above. -
Clock semantics.
received_atandfulfilled_atare read from the substrate’s clock authority at record time — injected by the Audit Trail substrate into the action, not sampled inside C7’s own transition (logic-confinement, inherited from the substrate per C6’s Clock source edge case). They are best-effort wall-time annotations; the Event Logsequence_number(via the substrate) is the authoritative order source. For deployments where DSAR timestamps carry legal force — proving a request was fulfilled within the statutory window — a Trusted Timestamping composition (per RFC 3161 — the Internet standard for trusted time-stamping) provides the verifiable time anchor; C7 inherits the substrate’s clock-source treatment and does not reconcile clock skew further.
Standards references
C7 is the structural form of the data-subject-rights-fulfillment requirement: enumerate a subject’s record universe, resolve each record’s competing claims into one accountable disposition, and prove the resolution from the records alone. Its primary anchors:
- GDPR (EU General Data Protection Regulation) Article 15 (Right of access by the data subject) — the subject may obtain confirmation of processing, a copy of the data, and the recipients or categories of recipient to whom the personal data have been disclosed (Article 15(1)(c)). C7’s access path produces the per-record
included/withheld(...)disposition set, and the Selective Disclosure read answers the recipients limb from the records alone. - GDPR Article 15(4) — the right to obtain a copy shall not adversely affect the rights and freedoms of others. The
withheld(third-party-confidentiality)disposition is the structural form of this limit; C7 records the assertion, and its legitimacy is the externally-clearable check. - GDPR Article 17 (Right to erasure / “right to be forgotten”) — Article 17(1) names the grounds that trigger erasure, including 17(1)(b) (consent withdrawn and no other lawful ground — the Consent-oracle branch). Article 17(3) names the exemptions: 17(3)(b) (compliance with a legal obligation / retention —
retained(retention-obligation)via the C1 Retention Window leg) and 17(3)(e) (establishment, exercise, or defence of legal claims —retained(legal-hold)via the C1 hold-blocks-purge gate). C7’s erasure path is the structural resolution of Article 17 against its own 17(3) exemptions. - GDPR Article 12(3) — fulfillment within one month of receipt. C7 records
received_atandfulfilled_atas the records-alone source; deadline computation is a composing/externally-clearable concept. - GDPR Articles 16, 18, 20, 21 (rectification, restriction, portability, objection) — named composing concepts (Edge cases — The lighter Article 15–20 rights), lighter variants of or feeders into the fulfillment surface rather than additional spines.
- CCPA / CPRA (California Consumer Privacy Act, as amended by the California Privacy Rights Act) — §1798.100 (right to access / know) maps to the access path; §1798.105 (right to delete) maps to the erasure path, with §1798.105(d)’s retained-purpose exceptions mapping onto the same
retained(...)dispositions as the GDPR Article 17(3) exemptions. The cross-domain identity — one disposition surface, regulation-agnostic — is the composition’s thesis. - HIPAA (US Health Insurance Portability and Accountability Act) §164.524 (Access of individuals to protected health information) — access to a designated record set; §164.524(a)(1) grounds for denial map to
withheld(legal-exemption). - HIPAA §164.526 (Amendment of protected health information) — the rectification analog, a named composing concept (Article 16 family).
- HIPAA §164.528 (Accounting of disclosures) — the Selective Disclosure read that answers GDPR Article 15(1)(c) does double duty as the §164.528 accounting surface.
C7 inherits the broader standards compliance of its constituents:
- Through Defensible Retention (C1) (and transitively Legal Hold, Retention Window, and the Audit Trail substrate with its Event Log, Actor Identity, Tamper Evidence, and Retention Window): FRCP (US Federal Rules of Civil Procedure) Rule 37(e) litigation-hold preservation, SOX (Sarbanes-Oxley Act) §802, SEC (US Securities and Exchange Commission) Rule 17a-4, HIPAA §164.530(j), GDPR Article 17’s interaction with retention obligations, and the full Audit Trail standards inheritance (HIPAA §164.312(b) audit controls, ISO/IEC 27001 §A.12.4, GDPR Articles 30 and 32). C7’s erasure gate is C1’s hold-blocks-purge gate, so these are inherited at the gate, not re-anchored.
- Through Selective Disclosure: GDPR Article 15(1)(c) and Article 30, HIPAA §164.528, and SEC Rule 17a-4 at the disclosure-accounting layer — the surface that records each fulfillment response and answers the recipients limb of access.
- Through Consent: GDPR Article 6(1)(a) and Article 7 (consent as a lawful basis and its withdrawal), Article 17(1)(b) (the withdrawn-consent erasure trigger C7’s other-lawful-basis branch consults), CCPA/CPRA opt-out, and HIPAA §164.508 authorization — read as the authority oracle, never mutated.
Status
grounded on Final Critique 5 — 2026-06-09 (drafted 2026-06-08; author gating review complete — two foundational + five refining findings closed; formal-layer vote YES and the derived TLA+ model + two buggy twins verified in tools/harness/ — formal layer discharged; fresh-reader Opus council complete (Final Critique 4) — three foundational + eight refining findings folded, foundational to zero; Phase 4 Opus Happy-Torvalds-X2 clearance gate cleared in a fresh session 2026-06-09 (Final Critique 5) — foundational findings at zero, six refining/rhetorical findings folded, the correct TLA+ model and both buggy twins re-verified). Drafted against the approved C7 architectural cut — Selective Disclosure + Defensible Retention (C1, as substrate → Legal Hold + Retention Window + Audit Trail, reached transitively) + Consent (read-only authority oracle) — with the conflict-resolution-over-a-record-universe reframe, the per-record disposition model, two sibling fulfillment actions over one fulfillment core, and the no-silent-omission + binding-bijection emergent guarantees as the load-bearing claims. Regulated-pattern conventions (Regulated adversarial scenarios; Generation acceptance with the Audit-Trail-traversal-clearable / externally-clearable split) baked in from the first draft, inherited from the methodology directly per pressure-testing.md §Regulated-pattern conventions. The formal-layer vote is YES (the binding-bijection atomicity and the no-silent-omission coverage are load-bearing concurrency/safety claims a derived TLA+ model verifies); the model and its two buggy twins are authored and verified, so the formal prerequisite is discharged. With the gating review, the verifying formal model with its buggy twins, the fresh-reader council, and the Phase 4 clearance gate all cleared at zero foundational findings, the pattern is grounded on Final Critique 5.
Lineage notes
Regulated composition. The two regulated-overlay conventions — Regulated adversarial scenarios and Generation acceptance (with the Audit-Trail-traversal-clearable / externally-clearable split) — are inherited from the methodology directly (pressure-testing.md), baked in from the first draft, not re-derived from predecessor patterns. The primary structural references are Consent & Preference Management (C2) for the binding-bijection shape (its revoke ⇔ complete-downstream-enumeration binding is the structural twin of C7’s request ⇔ complete-disposition-enumeration binding), Immutable Transaction Ledger (C6) for the substrate-composition shape, the composition-introduced-surface + forthcoming-atom pattern (Subset Proof → Completeness Model), and the TLA+ binding-bijection model + buggy twin, and Defensible Retention (C1) for the erasure/disposition branches and the hold-blocks-purge gate C7’s erasure path wraps.
Structural milestone. This composition retires the four forthcoming-references to C7 across the atom corpus — in atoms/consent.md, atoms/legal-hold.md (two references), atoms/selective-disclosure.md, and atoms/provenance.md: each atom’s pending marker is removed and the reference made a live link, and Selective Disclosure’s stale constituent guess (its entry had pre-listed a flat seven-atom list) is corrected to the grounded cut — Selective Disclosure + Defensible Retention (C1) substrate + Consent oracle — mirroring how C6’s grounding corrected Selective Disclosure’s C6 entry.
Capability-provenance self-check. Every emergent invariant’s Rests on: clause traces to one of the four declared sources (pressure-testing.md §Capability provenance): named constituent invariants/actions (C1 Invariant 1 and purge_record for erasure validity; Selective Disclosure Invariants 1/6 and Audit Trail Invariant 1 for the binding; Consent check/read for the other-lawful-basis branch), the deployment-declared record_source_registry configuration capability (no-silent-omission’s universe bound), and composition-introduced surfaces (the enumeration-with-disposition surface; the request_to_fulfillment insertion discipline). No invariant rests on an ambient “the system can…”. C7 is the first composition authored under the capability-provenance rule.
Author gating review — 2026-06-08 (3×3 baseline + author Final Critique; author-led, not fresh-reader). The author ran the three passes against the full draft, consolidating the baseline rounds with an author Final-Critique-shaped closing pass. Seven findings surfaced — two foundational, five refining — all closed in-pattern. The grounding-granting fresh-reader council is a separate step (below, Chunk 6); this entry is the author’s own adversarial pass, recorded for the round trail. Per-finding format F-id — short name — class → fix:
- F1 — disposition set absent from the sealed fulfillment event — foundational (Pass 1 GRID / Pass 3). The
dsar.*_fulfilledAudit Trail event’sdatacarried only adisposition_summary(counts), but Invariant 1’s binding claim and the breach-forensics adversarial scenario both assert the complete disposition set is part of the hashed, sealed payload — so a silent edit to the set inrequest_to_fulfillment(C7’s mutable emergent map) would have been undetectable, breaking the no-silent-omission rebuttal the spec leans on. The seal protected a count, not the set. → The eventdatanow carries the complete disposition set (or, for a very large universe, a cryptographic digest of it — mechanism-neutral exactly as C6 treats subset proofs);request_to_fulfillmentis reframed as the queryable mirror of the authoritative sealed event, not an independent store. Both fulfillment actions’ step 4, both walkthroughs, and the Application-state entry updated. This is the foundational soundness fix of the round — the binding and the breach rebuttal now hold mechanically. - F4 — fulfillment-event recording surface under-declared (capability-provenance / FC5-1 class) — foundational (Pass 2 EOS). C7 records its
dsar.*events on the Audit Trail reached transitively through C1, but the draft did not state by what right — C1 exposes norecord_actionpassthrough, so a fresh Pass-2 reader could flag the capability as attributed to a substrate that does not expose it (the exact FC5-1 trap the capability-provenance rule generalizes). → Composes now states explicitly that C7 callsAuditTrail.record_actiondirectly on the one Audit Trail instance the C1 substrate carries, defended as the established substrate-composition pattern (Multi-Party Approval records its own events on the Audit Trail its substrate carries), with the capability named as Audit Trail’s ownrecord_action+ Invariant 1 reached through the named C1 substrate — a declared source, not an ambient reach-through. Preempts the council’s most likely Pass-2 finding. - F2 — disposition tuple
sourceundefined; redundantbasis_ref?— refining (Pass 1 / Pass 3). The disposition verdict{record_ref, source, disposition, reason, basis_ref?}usedsourcewithout defining it and carried bothreasonand an overlappingbasis_ref?. →sourcedefined (the registry-declared store or constituent the record was enumerated from); the tuple consolidated to{record_ref, source, disposition, reason}withreasoncarrying the authority reference. - F3 — empty universe conflated with incomplete enumeration — refining (Pass 3). The draft did not distinguish a subject with no records (a valid “we hold nothing about you” fulfillment with an empty disposition set) from a failed enumeration (
incomplete-enumeration). →fulfill_access_requeststep 3 now names the empty-universe-is-valid case explicitly, distinct from the source-failure rejection. - F5 — Article 15(1)(c) recipients answer had no home in the fulfillment schema — refining (Pass 3). The recipients answer was said to be “carried in the fulfillment” but the fulfillment-record schema has no recipients field. → Clarified: the recipients answer is part of the access response content (host-assembled), with the Selective Disclosure read as its records-alone source — not a per-record disposition.
- F6 —
EOSunglossed at first body use — refining (Pass 1 acronym discipline). → Glossed at its first occurrence (Invariant 7). - Final Critique (author, X2 posture). Re-ran all three passes after the fixes. Foundational findings (F1, F4) confirmed closed; the capability-provenance self-check re-verified that every emergent invariant’s Rests on: clause resolves to a declared source (named constituent invariant/action, the
record_source_registryconfig capability, or a composition-introduced surface) with zero ambient dependencies. Foundational findings at zero. Pass 2 confirmed the three externalizations the council is most likely to probe — the composition-introduced enumeration surface (forthcoming Completeness Model atom), Consent read-only-oracle non-mutation, and the no-Permissions operator-authorization boundary — are EOS-clean. The pattern is author-clean but not yetgrounded: grounding is gated on the verifying formal model (vote YES, below) and the fresh-reader Opus council (below).
Formal-layer vote: YES. The binding-bijection atomicity (Invariant 1) and the no-silent-omission coverage/totality (Invariant 2) are load-bearing concurrency/safety claims across the disposition set, the response-disclosure, and the dsar.*_fulfilled event — a TLA+-class claim of the shape C2’s and C6’s binding-bijection models already verify, extended with the per-disposition coverage totality C6’s binding-only model did not need. The other emergent invariants are not TLA+-class: erasure validity (Invariant 3) is C1’s hold-blocks-purge gate, modeled in defensible-retention.tla; disposition groundedness (Invariant 4), response-disclosure recording (Invariant 5), terminality (Invariant 6), and Consent non-mutation (Invariant 7) are single-write-path or records-shape arguments; Invariant 8 is each constituent’s own bar.
Formal model — 2026-06-08: TLA+ authored and verified; formal layer discharged. Derived model data-subject-rights-fulfillment.tla with config data-subject-rights-fulfillment.cfg, checked via tools/harness/ (the repo’s tla-checker WASM checker; no Java). What it checks: per fulfillment over an in-scope record universe Records, four sub-writes — disp[r] (per-record disposition; the coverage dimension), sdState (Selective Disclosure response-disclosure), auditState (the dsar.*_fulfilled event sealing the set), bound (the request_to_fulfillment binding). Two composition-level safety properties under every interleaving: the load-bearing Invariant 1 (Inv1_BindingBijection + Inv1_NoDanglingFulfillment + Inv1_NoOrphanEvent — the fulfillment is in one of two coherent configurations, uncreated or fully-committed, never a dangling partial) and the load-bearing Invariant 2 (Inv2_NoSilentOmission — a committed/bound fulfillment carries a disposition for every record, the totality/coverage check C6’s model did not need). The CORRECT model performs all sub-writes as a single atomic action (the step-4 “commit atomically” form); 2 reachable states, all invariants hold. Bounds/saturation: Records = {r1, r2}; the property is per-fulfillment-local and record-count-insensitive — the atomic commit yields 2 states at any universe size, so Records = {r1, r2, r3} holds at 2 states with no new behavior. The bound is saturated and the verification value lives in the twins, exactly as in C6’s disclosure-count insensitivity. Buggy twins (two, isolating the two load-bearing invariants): data-subject-rights-fulfillment-buggy.tla splits the commit into separate interleavable sub-steps (WriteSD → WriteAudit → Bind) with no compensation — the naive non-atomic implementation the Cross-store consistency under partial failure edge case warns against; TLC stops after WriteSD alone (sdState = present, auditState = absent, bound = FALSE — a dangling response-disclosure with no sealed event) and rejects it on Inv1_BindingBijection at 2 states. data-subject-rights-fulfillment-buggy-coverage.tla keeps the binding atomic but disposes records one at a time and commits without a full-coverage guard, so a committed fulfillment with an undispositioned in-scope record is reachable; TLC rejects it on Inv2_NoSilentOmission at 4 states. The two twins are the vacuity guard on both guarantees — the binding hazard (as in C6) and the novel coverage hazard — so the correct model’s green is meaningful on each. Conflict-protocol outcome: none — the model corroborates the English; the spec already requires “commit atomically” (Invariant 1) and a disposition for every enumerated record (Invariant 2), which is exactly the correct/buggy distinction. Canonical English unchanged. The per-record irreversible purge_record calls and the inherited partial-failure orphan are deliberately out of model scope (C1’s contract, modeled in defensible-retention.tla). Reproduce: cd tools/harness && node check.mjs ../../compositions/data-subject-rights-fulfillment.tla (and … -buggy.tla --buggy, … -buggy-coverage.tla --buggy).
Fresh-reader Opus council — 2026-06-08 (Pass 1 GRID / Pass 2 EOS / Pass 3 Linus-X2; three independent cold readers). Three separate Opus reviewers, one per pass, each given only the committed spec plus the pass question set — no author context, no prior-round findings — and each told explicitly to re-attack the prose rather than trust this Lineage’s “closed” claims. Pass 1 returned zero foundational findings; Pass 2 returned zero foundational (with one borderline flagged for adjudication); Pass 3 (Linus-X2) returned three foundational findings — the council earning its keep, exactly as it did on C6. All findings folded in-pattern; foundational findings now at zero. Per-finding format F-id — short name — class → fix:
- FC-L1 — Consent oracle’s
expired/not-knownoutcomes undefined in the erasure precedence — foundational (Pass 3).fulfill_erasure_requeststep 3.1 — C7’s one contribution on top of C1’s borrowed gate — consumed the 4-valuedConsent.check(granted | revoked | expired | not-known) but mapped onlygranted(retain) and impliedrevoked(proceed);expiredandnot-knownwere undefined, so a generator had to guess where two of four outcomes land, with opposite legal consequences (silently retaining lapsed-consent data, or silently destroying records on an unconfirmable basis — the latter an attacker’s lever via a forgeddeclared_basis). → Step 3.1 now maps all four outcomes explicitly:granted→retained(other-lawful-basis);revoked/expired→ consent basis gone, fall through to the C1 gate;not-known→ ananomaly(consent-basis-not-known)finding routed to the same dashboard-surfacing discipline as the parallel C1not-knowncase, never silently defaulted. This was the council’s highest-value finding. - FC-L2 — the erasure path conflated two distinct orphan layers and left the cross-layer actor unbound — foundational (Pass 3). C7’s “wraps
purge_record” mapped C1’srecording-failureto “fail the fulfillment per step 5,” but C1’srecording-failuremeansRetentionWindow.purgealready destroyed the record while C1’s ownrecord_purgedwrite failed — a C1-internal orphan (destroyed record, norecord_purged) that retrying the C7dsar.erasure_fulfilledevent cannot heal; and nothing bound thepurge_recordactor to the fulfillment actor, so C1’srecord_purgedand C7’s fulfillment event could attribute one destruction to two actors. → Step 3.2 now passes the sameactor_ref/credentialtopurge_recordand names the binding obligation; the Cross-store consistency under partial failure edge case now distinguishes Layer 1 (the C1-internal destroyed-record orphan, routed to C1’s compensation) from Layer 2 (the C7 binding orphan, retried +cascade_recovery-marked), with the warning that healing only Layer 2 leaves the FRCP spoliation gap open. - FC-L3 — Invariant 1’s “committed together or not at all” overclaimed against the documented purge orphan — foundational (Pass 3). The load-bearing binding-bijection invariant was stated unconditionally, but the irreversible per-record purges precede the step-4 binding, so erased-records-without-binding is a reachable state the spec’s own orphan edge case describes — the invariant contradicted the edge case, and the TLA+ model’s green came precisely from scoping the purges out. → Invariant 1 now carries an explicit modulo-clause (parallel to C1’s Invariant 5 modulo the Audit-Trail partial-attestation contract): the binding commits atomically; the erasure path’s irreversible purges precede it, so the reachable failure is the named orphan governed by compensation — the bijection is a claim about the binding, not the purges, and the model verifies exactly that. The access path’s binding stays atomic without qualification.
- FC-E2 — host-declared per-record surfaces (
declared_basis, access determinations, host delete) used but not declared in the registry config — refining (Pass 2 EOS, capability-provenance; flagged borderline-foundational). The non-consentretained(other-lawful-basis)branch, the accesswithheld(...)branch, and the host-managederased/retainedbranch each rested on a host-supplied per-record surface thatrecord_source_registry(the declaring config capability) did not enumerate — an undeclared-dependency seam hiding behind the (correctly-declared, council-verified) Consent-oracle and C1-gate halves. →record_source_registryConfiguration now declares, per record, the enumeration surface, thedeclared_basisfield, the C1retention_id-or-host-delete surface, and the access third-party/exemption determinations — so every disposition’s authority traces to the deployment-declared config capability. Invariant 4 extended to cover the host-managed branch; legitimacy of each host assertion routed to the externally-clearable checks. - FC-L5 — host-managed records bypass the C1 hold gate; Invariant 3 was silently C1-scoped — refining (Pass 3). → Invariant 3 now states its scope (C1-managed records) explicitly, and a new Host-managed records bypass the C1 hold gate edge case names the bypass as a host obligation and externally-clearable gap (a deployment needing the structural hold guarantee places the record under C1 retention).
- FC-L4 —
record_ref(disposition key) andretention_id(purge key) pairing unverified — refining (Pass 3). A registry mis-pairing could purge the wrong record while recordingerasedagainst the named one. → Step 3.2 now confirms the(record_ref, retention_id)pairing against C1’s authoritativeretention_to_recordbefore purging; the anomaly edge case covers mis-pairing alongside the unknown-retention case. - FC-L6 — the access Article 15(1)(c) recipients limb was unsealed — refining (Pass 3). No-silent-omission sealed the disposition set but not the recipients answer, so a host could drop a recipient untraceably. → A
recipients_digestof the Selective Disclosure read is now bound into the sealeddsar.access_fulfilledevent. - FC-L7 —
disposition_reportargued inherently low-sensitivity while the requester is unverified — refining (Pass 3). The “subject reading their own outcome” defense was circular given C7 verifies no requester identity, and the report can expose hold existence, privilege citations, and the only surviving description of erased records. → The report reads edge case now names read-authorization as a required composing gate (parallel to operator authorization), not an inherent-safety claim. - FC-L8 — Generation acceptance check 2 prescribed a re-enumeration impossible for erased records — refining (Pass 3). → Check 2 split by right-type: access re-enumerates; erasure verifies the sealed disposition-set cardinality against the recorded universe size and cross-checks each
erasedagainst arecord_purgedevent, without re-enumerating destroyed records. - FC-E1 — Audit Trail Invariant 1 cited two layers down — refining (Pass 2). → Invariant 1’s Rests on: now names “reached through the named C1 substrate per the substrate-composition convention,” making the transitive citation path explicit.
- FC-G1/G2/G3 — acronym glosses (
KYC,TLA+,SLA) and the empty-universe-valid case stated for access only — refining (Pass 1). →KYC/TLA+/SLAglossed at first body use; the erasure sibling now states the empty-universe-is-a-valid-fulfillment case its access twin already carried. (Pass 1’s disposition-tuple back-link nit is accepted as-is: the tuple is defined once in Composition state and consistent; per-use-site back-links would be over-cross-referencing — recorded rhetorical, not closed.)
Pass 1 independently confirmed all nine GRID nodes resolved, canonical section order, the external link graph, and — checked against the constituent specs — every cited constituent signature and invariant count (Consent 1–9, C1 1–8, Selective Disclosure 1–6). Pass 2 independently verified five capability-provenance claims head-on against the constituent specs — the purge_record outcome mapping, C1 Invariant 1 = hold-blocks-purge, the AuditTrail.record_action substrate reach-through (the FC5-1-class defense the author added in the gating review — confirmed genuinely present in the body), the read-only Consent.check, and the enumeration-as-composition-introduced surface — all clean; the seam it found was on the host-declared surfaces (FC-E2), a different axis. With FC-L1/L2/L3 and FC-E2 closed, foundational findings are at zero.
- Opus clearance gate — Happy Torvalds X2 — 2026-06-09 (Claude Opus,
claude-opus-4-8): clean of foundational findings; six refining/rhetorical findings folded; foundational at zero; grounds on Final Critique 5. Run in a fresh session against the committed spec, fresh-reader discipline throughout (only the spec, the methodology pass-question sections, the three constituent specs, and the three.tlafiles read; Lineage “closed” claims re-derived from the spec body, not trusted). All three passes run; Pass 3 at X2 depth. Formal model re-verified:node check.mjsreproduces the CORRECT model holding at 2 states,-buggyREJECTED onInv1_BindingBijection(2 states), and-buggy-coverageREJECTED onInv2_NoSilentOmission(4 states) — the green is non-vacuous on both load-bearing invariants. Capability provenance re-verified head-on against the constituent specs: C1’spurge_recordoutcome mapping andretention_id→record_refbinding (viapurge_eligible()), C1 Invariant 1 (hold-blocks-purge) and Invariant 5 (modulo Audit-Trail partial-attestation), theAuditTrail.record_actionsubstrate reach-through, Consent’s 4-valuedcheck+read(and the read-only non-mutation boundary), Selective Disclosure’srecord/readand the Disclosures to the subject themselves edge case, and the invariant counts (Consent 1–9, C1 1–8, Selective Disclosure 1–6) — all confirmed present in the cited constituents. Per-finding format F-id — short name — class → fix: - FC5-1 —
AuditTrail.record_actionper-callretention_policymis-stated and omitted — refining (Pass 2). Configuration claimedrecord_action“takes no per-call retention argument,” but C1 passesretention_policy=audit_trail_retention_policyon every call (C1 Configuration + action wiring), and C7’s threerecord_actioncalls omitted it — a constituent-signature contradiction touching the load-bearing post-erasure audit-retention property. → Configuration corrected to state the per-call argument; C7 now passes the inheritedretention_policy = audit_trail_retention_policyon all threedsar.*calls (dsar.received,dsar.access_fulfilled,dsar.erasure_fulfilled) without overriding C1’s policy. - FC5-2 — mis-pairing check cited C1’s internal
retention_to_recordmap (not a C1-exposed surface) — refining (Pass 2, capability provenance). C1 exposes no public read overretention_to_record; theretention_id→record_refbinding is exposed viapurge_eligible()tuples (for retention-eligible records — exactly the records a purge can destroy). → Action wiring step 3.2 and the Enumeration names a record C1 does not manage edge case now citepurge_eligible()as the exposed authoritative binding, so the safety-critical pre-purge confirmation traces to a declared C1 action. - FC5-3 —
anomaly(…)dispositions produced by the wiring but absent from Generation acceptance check 2’s vocabulary — refining (Pass 3; FC-L1 propagation gap). Step 3 disposes a registry/constituent-disagreement record asanomaly(consent-basis-not-known)/ unknown-retention / mis-pairing (never silently erase/retain), but check 2’s enumerated erasure vocabulary omitted it, so an auditor would false-flag a correctly-handled anomaly as out-of-vocabulary. → Check 2’s erasure vocabulary now includes theanomaly(…)disposition class. - FC5-4 — wrong-right-type rejection example used an already-fulfilled request — refining (Pass 3). The example called
fulfill_access_requeston the fulfilled erasure requestdsar-4002, which step-1 precedence rejects asalready-fulfilledbefore theright_typecheck — so the example could not actually producewrong-right-type. → Rewritten to use a Received, not-yet-fulfilled erasure request, with a note that terminality dominates wrong-right-type. - FC5-5 —
consent_idattributed toConsent.check— refining/rhetorical (Pass 2). Invariant 4 read “aConsent.checkresult naming theconsent_id,” butcheckreturns only the 4-valued state; theconsent_idis named byConsent.read(which C7 also composes and whose use Invariant 4’s Rests on: already declares). → Reworded to attribute the state tocheckand theconsent_idto the pairedread. - FC5-6 —
receive_requestsubstrateinvalid-credentialmapping under-stated — refining/rhetorical (Pass 1/Pass 3). Step 3 said “on failure →rejected(recording-failure)” while the uniform rule callsinvalid-credential/invalid-requestclean pre-state rejections; the two disagreed. → Step 3 now maps substrateinvalid-credential/invalid-request→rejected(invalid-request)(clean pre-state, mirroring C1’s own boundary treatment ofinvalid-credential) andrecording-failure→rejected(recording-failure), consistent with the uniform rule and the action signature.
The six load-bearing Pass-3 stress points the gate prompt names — the irreversible-erasure two-layer orphan, the four-claim precedence + 4-outcome Consent mapping, the read-only-oracle boundary, no-silent-omission over the registry, the binding-bijection-vs-purge ordering (Invariant 1’s modulo-clause), and the host-managed hold-gate bypass — each re-derived from the spec body and found soundly handled and honestly bounded; no foundational gap. The structural-milestone forthcoming-links to C7 across the atom corpus were already retired at drafting (the atom files carry live links). Foundational findings: zero. Grounds on Final Critique 5.