Data Subject Rights Fulfillment (C7)

Table of contents
  1. Data Subject Rights Fulfillment (C7)
    1. Intent
    2. Summary
    3. Composes
    4. Composition logic
      1. Composition state
      2. Configuration
      3. Primitive policies
      4. Action wiring
        1. receive_request
        2. fulfill_access_request
        3. fulfill_erasure_request
        4. disposition_report (read-only)
      5. The load-bearing wiring decision — per-record disposition with no-silent-omission, bound atomically; the erasure gate wraps C1
    5. Composition-level invariants
    6. Examples
      1. Walkthrough — GDPR Article 15 access request, end to end
      2. Walkthrough — GDPR Article 17 erasure request, the hold gate firing
      3. Rejection path — re-fulfillment, wrong right type, incomplete enumeration
      4. Rejection path — erasure write fails after the purges commit (the orphan)
      5. CCPA/CPRA — consumer deletion request
      6. HIPAA §164.524 — access to a designated record set
      7. Regulated adversarial scenarios
    7. Generation acceptance
      1. Audit-Trail-traversal-clearable checks
      2. Externally-clearable checks
    8. Edge cases and explicit non-goals
    9. Standards references
    10. Status
    11. 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 (okerased, under-legal-holdretained(legal-hold), not-eligibleretained(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_ref to 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 one SelectiveDisclosure.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 calls record and read.

  • 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’s purge_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 as not-eligible), and the tamper-evident, attributed Audit Trail on which C7 records its own fulfillment events. C7 records those events by calling AuditTrail.record_action directly 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 its dsar.* events the same way). The capability is Audit Trail’s own declared record_action and 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-known and Consent.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), whose withdraw_consent is 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 atomaccountable 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 from request_id to {subject_ref, right_type, requester, received_at}. Populated by receive_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 a request_id back to its subject. A request_id present here but absent from request_to_fulfillment is a Received (not-yet-fulfilled) request; present in both is Fulfilled.
  • request_to_fulfillment — map from request_id to the fulfillment record: {right_type, fulfilled_at, dispositions, response_disclosure_id, fulfillment_event_id}. This is the binding backbone. dispositions is 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. source names the registry-declared store or constituent the record was enumerated from (which record_source_registry entry, or the Selective Disclosure / Consent / C1 store); reason carries the disposition’s authority reference — a C1 gate outcome, a consent_id and state, a host-declared basis or exemption citation — so the verdict is self-describing (Invariant 4). response_disclosure_id is the Selective Disclosure record of the response to the requester; fulfillment_event_id is the Audit Trail event that seals the fulfillment and carries the complete disposition set in its payload — so request_to_fulfillment is the queryable mirror of an authoritative sealed event, not an independent store an edit could silently diverge from. Populated by a successful fulfill_access_request or fulfill_erasure_request only 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 (the record_ref and its source); a declared_basis field naming the lawful ground(s) for processing the record (consumed by the erasure other-lawful-basis branch — a consent(purpose) value routes to the Consent oracle, a non-consent value is the ground itself); for erasure, either a C1 retention_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 access withheld(...) 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-supplied declared_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_policyinherited, 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-record record_purged events it precipitates share one immutable, sealed log. That instance carries the host’s regulatory retention policy for audit events as its audit_trail_retention_policy (the same Configuration value C1 supplies on its own retention and hold events); AuditTrail.record_action takes a per-call retention_policy argument, and C7 inherits C1’s configured value and passes it on every dsar.* record_action call (the call sites below carry retention_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 by receive_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 to SelectiveDisclosure.record/read and Consent.check/read as their subject_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 the requester is 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) or erasure (GDPR Article 17). Any other value is invalid-request. The two-value bound is the spine-scoping decision (Intent); the lighter Article 16–21 rights are named composing concepts, not additional right_type values.
  • 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 in request_to_subject and named as the recipient on 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 to AuditTrail.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 surface invalid-credential, mapped per the uniform rejection rule below. Whether actor_ref is 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’s record_ref identity 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 to purge_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:

  1. Validate subject_ref, requester, actor_ref each non-empty and right_type ∈ {access, erasure}. Any failure → rejected(invalid-request). Stop.
  2. Assign a fresh opaque request_id.
  3. 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: substrate invalid-credential / invalid-request surface as rejected(invalid-request) (a clean pre-state rejection — no prior constituent effect — mirroring C1’s own boundary treatment of substrate invalid-credential), and recording-failure as rejected(recording-failure); on any such failure no map is populated (the request is not resolvable without its intake event). Stop.
  4. Populate request_to_subject[request_id] = {subject_ref, right_type, requester, received_at = now} only after the intake event lands.
  5. 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:

  1. Resolve request_id in request_to_subject. Absent → rejected(not-known). If request_id is already in request_to_fulfillmentrejected(already-fulfilled) (Fulfilled is terminal — Invariant 6). If the stored right_type ≠ accessrejected(wrong-right-type) (an erasure request must be fulfilled through the erasure sibling). Resolve {subject_ref, requester}.
  2. Enumerate the in-scope universe for subject_ref via the composition-introduced enumeration surface over record_source_registry plus 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.
  3. 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 read SelectiveDisclosure.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 the included records. 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 sealed dsar.access_fulfilled event 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 from incomplete-enumeration (a declared source failed to respond).
  4. 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; then AuditTrail.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 event data (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 populate request_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.
  5. Return {request_id, dispositions, response_disclosure_id, event_id}. The request is now Fulfilled. Assembling and transmitting the actual access payload for the included records is the host’s obligation, signalled by the included dispositions; 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:

  1. Resolve request_id in request_to_subject; not-known / already-fulfilled / wrong-right-type (here: right_type ≠ erasure) exactly as the access sibling. Resolve {subject_ref, requester}.
  2. Enumerate the in-scope universe as in the access sibling; incomplete-enumeration on 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 from incomplete-enumeration (a declared source failed to respond).
  3. 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):
  4. Other-lawful-basis (read-only, precedes any purge). Consult the record’s host-declared declared_basis (a per-record field the record_source_registry surface declares — Configuration). A declared non-consent ground still in force (legal-obligation, contract, vital-interests, …) → retained(other-lawful-basis), reason naming the ground; no purge_record call is made. Where the declared basis is consent(purpose), consult the Consent oracle Consent.check(subject_ref, purpose) and map all four first-class outcomes (never collapse them — the Consent atom made check 4-valued deliberately): granted → the consent basis is in force → retained(other-lawful-basis), reason carrying the consent_id, no purge; revoked or expired → 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 explicit anomaly(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 C1 not-known case, 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.
  5. Else, attempt the gated purge for a C1-managed record. First confirm the registry-supplied (record_ref, retention_id) pairing against C1’s authoritative retention_idrecord_ref binding — exposed in C1’s purge_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 pairs record_ref with a retention_id C1 binds to a different record_ref is 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 call purge_record(retention_id, actor_ref, credential)the same actor_ref and credential that run this fulfillment, so C1’s record_purged event and the C7 dsar.erasure_fulfilled event attribute the destruction to one actor (a generator must not thread a service-account into purge_record while the operator runs the fulfillment — the two events would disagree on who erased the record). Map the gate outcome to the disposition — okerased; under-legal-holdretained(legal-hold) (Article 17(3)(e) — preservation for the establishment, exercise, or defence of legal claims); not-eligibleretained(retention-obligation) (Article 17(3)(b) — a legal retention obligation). not-known from C1 means the registry named a retention_id C1 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-failure from C1 is the inherited C1-internal orphan, distinct from C7’s own binding orphan: C1’s RetentionWindow.purge has already destroyed the record but C1’s own record_purged audit write failed (C1’s most consequential atomicity hole), so the record is gone with no record_purged event. C7 fails the fulfillment, but the compensation is two-layered and both layers must be discharged (Cross-store consistency under partial failure).
  6. 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 erased disposition (the host performs the delete) or the host-declared retained(...) 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); the erased dispositions are irreversible by the time step 4 runs.
  7. 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; then AuditTrail.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 event data, sealed and tamper-evident; then populate request_to_fulfillment[request_id], mirroring the authoritative event. The per-record record_purged events are already recorded by C1 inside each purge_record; the dsar.erasure_fulfilled event 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.
  8. 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_subjectrejected(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 (okerased, under-legal-holdretained(legal-hold), not-eligibleretained(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 its dsar.access_fulfilled / dsar.erasure_fulfilled Audit Trail event — commits together or not at all: every Fulfilled request has exactly one such binding, and every dsar.*_fulfilled event corresponds to exactly one Fulfilled request whose request_id it carries; the binding is bijective. Modulo the inherited irreversible-purge contract: on the erasure path the per-record purge_record calls (Action wiring, fulfill_erasure_request step 3) precede the binding and are irreversible, so a failure of the step-4 binding after some purges have committed is reachable — leaving records irreversibly erased with 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’s request_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-enumeration and 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-declared record_source_registry configuration 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 erased by an erasure fulfillment while an Active Legal Hold covers it or while its retention obligation has not elapsed; such a record is dispositioned retained(legal-hold) (Article 17(3)(e)) or retained(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 C1 retention_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 a retention_id and the gate. Rests on: C1 Invariant 1 (hold-blocks-purge) and C1’s declared purge_record action, whose under-legal-hold and not-eligible rejections 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 a purge_record outcome on the named retention_id (a record_purged or purge_blocked_by_hold event); each retained(other-lawful-basis) disposition to the Consent.check state result (with the governing consent_id resolved via the paired Consent.readcheck returns the four-valued state, read names the record), or to a host-declared non-consent declared_basis surfaced through the registry; each included / withheld(third-party-confidentiality) / withheld(legal-exemption) access disposition to the host’s per-record determination surfaced through the registry; and each host-managed erased / retained(...) disposition (the records with no C1 retention_id) to the host delete-surface attestation or the host-declared declared_basis named in the disposition’s reason. 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’s purge_record (C1-gated erasure dispositions), the Consent oracle’s check and read (the other-lawful-basis branch), and the host declared_basis / determinations / delete-attestation surfaced through the deployment-declared record_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 calls SelectiveDisclosure.record before 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’s record action 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 returns already-fulfilled and changes no state — no second disposition set, no second response-disclosure, no second fulfillment event. Defended in-line: request_to_fulfillment is inserted once (Action wiring, step 4) and the fulfillment actions’ step 1 rejects an already-present request_id with already-fulfilled. Rests on: the composition-introduced request_to_fulfillment insertion-once discipline and the already-fulfilled guard; 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 check and read. 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 as Consent.check in fulfill_erasure_request step 3.1 and (optionally) Consent.read; no action calls grant, 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.

  1. 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 records dsar.received; the request is Received.

  2. 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 — no incomplete-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’s 15(4) determination reference; r4 → withheld(legal-exemption), reason carrying the privilege citation; r5 → included. It also reads SelectiveDisclosure.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; then AuditTrail.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; then request_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, and ev-7001.
  3. 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 three included records (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.

  1. 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.received recorded; Received.

  2. 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 retention ret-r1 (retention elapsed, no hold), declared basis consent(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>)okerased. (C1 records its own record_purged event with hold_check_result: empty.)
    • r2 — a transaction record under ret-r2, covered by an Active litigation hold. Other-lawful-basis: none. purge_record(ret-r2, …)under-legal-holdretained(legal-hold) (Article 17(3)(e)), reason carrying the blocking hold_id. The hold gate fires — this is the collision C7 exists to resolve, read directly off C1’s gate. (C1 records a purge_blocked_by_hold event.)
    • r3 — a KYC identity record under ret-r3, a 5-year retention obligation not yet elapsed. Other-lawful-basis: none asserted. purge_record(ret-r3, …)not-eligibleretained(retention-obligation) (Article 17(3)(b)).
    • r4 — a fraud-monitoring record whose declared basis is legal-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); no purge_record call is made for r4.
    • Commits atomically: SelectiveDisclosure.record(subject_ref = "cust-8830", recipient = "cust-8830", scope = "dsar:erasure:outcome", authority = {type: regulatory, reference: "GDPR Article 17"})disc-9002; then AuditTrail.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; then request_to_fulfillment["dsar-4002"] is populated. Fulfilled.
  3. The outcome is defensible from the records. disposition_report("dsar-4002") shows all four records dispositioned (Invariant 2): one erased, three retained with three different reasons, each traceable (Invariant 4) — r2 and r3 to their C1 purge_record outcomes, r4 to the host-declared AML basis, r1’s erasure to a record_purged event whose hold_check_result: empty proves 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 — r1 is 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 returns already-fulfilled before it reaches the right_type check — 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).

  1. Fulfillment binding coverage. For every Fulfilled request in request_to_fulfillment, confirm exactly one dsar.access_fulfilled or dsar.erasure_fulfilled Audit Trail event carries its request_id, that AuditTrail.verify_record returns verified for it, and that its response_disclosure_id resolves to a Selective Disclosure record. A Fulfilled request with no fulfillment event, with more than one, or with a dangling response_disclosure_id is a conformance failure (Invariant 1). The inverse: every dsar.*_fulfilled event names a request_id present in request_to_fulfillment.

  2. 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: included withheld(third-party-confidentiality) withheld(legal-exemption); erasure: erased retained(legal-hold) retained(retention-obligation) retained(other-lawful-basis), plus the registry/constituent-disagreement disposition anomaly(…) — 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 no record_ref appears 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 same record_source_registry and 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, the erased records 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 each erased disposition against a C1 record_purged event — 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).
  3. Erasure-validity cross-check. For every erased disposition, confirm the C1 record_purged event for that record’s retention_id carries hold_check_result: empty (the gate passed). For every retained(legal-hold), confirm a purge_blocked_by_hold event whose hold_check_result names a then-Active hold; for every retained(retention-obligation), confirm the record’s retention was unelapsed at fulfilled_at. An erased disposition over a record that had an Active hold at fulfillment time is a conformance failure (Invariant 3, resting on C1 Invariant 1).

  4. Disposition groundedness. For every disposition, confirm its reason traces to a recorded authority: erasure dispositions to a C1 purge_record outcome (a record_purged or purge_blocked_by_hold event) or, for retained(other-lawful-basis), to a Consent.check-derivable state or a host-declared non-consent basis named in the reason; access withheld(...) dispositions to the host determination reference named in the reason. A disposition whose reason names no recoverable authority is a conformance failure (Invariant 4).

  5. Response-disclosure coverage. For every fulfillment, confirm response_disclosure_id resolves to a Selective Disclosure record naming recipient = requester, the appropriate regulatory authority, and a scope identifying the fulfillment, and that the dsar.*_fulfilled event references it. A fulfillment with no bound response-disclosure is a conformance failure (Invariant 5).

  6. 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_registry names 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(...) or retained(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 requester was 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_ref was 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_at and fulfilled_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-granted consent) → 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’s under-legal-holdretained(legal-hold); (3) the C1 gate’s not-eligibleretained(retention-obligation); (4) erased. A record under both a hold and another lawful basis is retained(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_registry declares: 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 atomaccountable 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.record then AuditTrail.record_action then the request_to_fulfillment population — 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-3 purge_record calls 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_record returns recording-failure, C1’s RetentionWindow.purge has already destroyed the record but C1’s own record_purged audit write failed — a destroyed record with no record_purged event, C1’s own most-consequential atomicity hole. This orphan is inside C1; C7 cannot compensate it by retrying the dsar.erasure_fulfilled event (a C7-level event does not supply the missing C1 record_purged). C7 fails the fulfillment, surfaces the C1-internal orphan (the destroyed record_ref with no record_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_purged event) but the step-4 dsar.erasure_fulfilled write then fails, the records are erased with no C7 fulfillment binding. This is C7’s own orphan: the implementation (a) retries the dsar.erasure_fulfilled write until it lands, (b) surfaces the request and the already-erased record_refs as a high-priority finding, and (c) marks the recovered event cascade_recovery = true so 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_request and fulfill_erasure_request could have been one fulfill_request(request_id, …) branching on the stored right_type. They are kept separate because their downstream effects differ in kind: access determines and discloses (no record is mutated), while erasure determines and, for erased records, 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 requester and 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 of receive_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_ref running 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 (at receive_request) and fulfilled_at (at fulfill_*) 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 from received_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_id and purge_record returns not-known, the registry asserted C1 management C1 does not have. (b) Mis-pairing. If the registry pairs a record_ref with a retention_id that C1’s retention_to_record maps to a different record_ref, the registry’s pairing is wrong — purging on it would destroy the wrong record while recording erased against the named one. C7 confirms the (record_ref, retention_id) pairing against C1’s authoritative binding — C1’s purge_eligible() exposes the retention_idrecord_ref pairing 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’s purge_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-erased with 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 a retention_id and 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-managed erased disposition is therefore a host-attested outcome, not a records-alone-provable one (Invariant 4; Generation acceptance externally-clearable checks).

  • disposition_report read-authorization and read-auditing are composing concepts. disposition_report takes only a request_id and 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 and hold_id of legal holds over a subject (litigation intelligence), the privilege citations behind withheld(legal-exemption), the lawful bases behind every retained(...), and — for a fulfilled erasure — it may be the only surviving description of records that no longer exist. A deployment therefore should gate disposition_report behind 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_id being 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 included set 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-class right_type would 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 included access 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 the included dispositions, 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 same request_id must be serialized: the first transitions the request to Fulfilled, the second observes already-fulfilled (Invariant 6) — implementations serialize on request_id, exactly as C1 serializes its hold-check-and-purge on record_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_at and fulfilled_at are 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 Log sequence_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_at and fulfilled_at as 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.*_fulfilled Audit Trail event’s data carried only a disposition_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 in request_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 event data now 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_fulfillment is 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 no record_action passthrough, 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 calls AuditTrail.record_action directly 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 own record_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 source undefined; redundant basis_ref? — refining (Pass 1 / Pass 3). The disposition verdict {record_ref, source, disposition, reason, basis_ref?} used source without defining it and carried both reason and an overlapping basis_ref?. → source defined (the registry-declared store or constituent the record was enumerated from); the tuple consolidated to {record_ref, source, disposition, reason} with reason carrying 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_request step 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 — EOS unglossed 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_registry config 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 yet grounded: 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 (WriteSDWriteAuditBind) 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-known outcomes undefined in the erasure precedence — foundational (Pass 3). fulfill_erasure_request step 3.1 — C7’s one contribution on top of C1’s borrowed gate — consumed the 4-valued Consent.check (granted | revoked | expired | not-known) but mapped only granted (retain) and implied revoked (proceed); expired and not-known were 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 forged declared_basis). → Step 3.1 now maps all four outcomes explicitly: grantedretained(other-lawful-basis); revoked/expired → consent basis gone, fall through to the C1 gate; not-known → an anomaly(consent-basis-not-known) finding routed to the same dashboard-surfacing discipline as the parallel C1 not-known case, 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’s recording-failure to “fail the fulfillment per step 5,” but C1’s recording-failure means RetentionWindow.purge already destroyed the record while C1’s own record_purged write failed — a C1-internal orphan (destroyed record, no record_purged) that retrying the C7 dsar.erasure_fulfilled event cannot heal; and nothing bound the purge_record actor to the fulfillment actor, so C1’s record_purged and C7’s fulfillment event could attribute one destruction to two actors. → Step 3.2 now passes the same actor_ref/credential to purge_record and 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-consent retained(other-lawful-basis) branch, the access withheld(...) branch, and the host-managed erased/retained branch each rested on a host-supplied per-record surface that record_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_registry Configuration now declares, per record, the enumeration surface, the declared_basis field, the C1 retention_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) and retention_id (purge key) pairing unverified — refining (Pass 3). A registry mis-pairing could purge the wrong record while recording erased against the named one. → Step 3.2 now confirms the (record_ref, retention_id) pairing against C1’s authoritative retention_to_record before 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_digest of the Selective Disclosure read is now bound into the sealed dsar.access_fulfilled event.
  • FC-L7 — disposition_report argued 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 erased against a record_purged event, 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+/SLA glossed 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 .tla files 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.mjs reproduces the CORRECT model holding at 2 states, -buggy REJECTED on Inv1_BindingBijection (2 states), and -buggy-coverage REJECTED on Inv2_NoSilentOmission (4 states) — the green is non-vacuous on both load-bearing invariants. Capability provenance re-verified head-on against the constituent specs: C1’s purge_record outcome mapping and retention_idrecord_ref binding (via purge_eligible()), C1 Invariant 1 (hold-blocks-purge) and Invariant 5 (modulo Audit-Trail partial-attestation), the AuditTrail.record_action substrate reach-through, Consent’s 4-valued check + read (and the read-only non-mutation boundary), Selective Disclosure’s record/read and 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_action per-call retention_policy mis-stated and omitted — refining (Pass 2). Configuration claimed record_action “takes no per-call retention argument,” but C1 passes retention_policy=audit_trail_retention_policy on every call (C1 Configuration + action wiring), and C7’s three record_action calls 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 inherited retention_policy = audit_trail_retention_policy on all three dsar.* 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_record map (not a C1-exposed surface) — refining (Pass 2, capability provenance). C1 exposes no public read over retention_to_record; the retention_idrecord_ref binding is exposed via purge_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 cite purge_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 as anomaly(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 the anomaly(…) disposition class.
  • FC5-4 — wrong-right-type rejection example used an already-fulfilled request — refining (Pass 3). The example called fulfill_access_request on the fulfilled erasure request dsar-4002, which step-1 precedence rejects as already-fulfilled before the right_type check — so the example could not actually produce wrong-right-type. → Rewritten to use a Received, not-yet-fulfilled erasure request, with a note that terminality dominates wrong-right-type.
  • FC5-5 — consent_id attributed to Consent.check — refining/rhetorical (Pass 2). Invariant 4 read “a Consent.check result naming the consent_id,” but check returns only the 4-valued state; the consent_id is named by Consent.read (which C7 also composes and whose use Invariant 4’s Rests on: already declares). → Reworded to attribute the state to check and the consent_id to the paired read.
  • FC5-6 — receive_request substrate invalid-credential mapping under-stated — refining/rhetorical (Pass 1/Pass 3). Step 3 said “on failure → rejected(recording-failure)” while the uniform rule calls invalid-credential/invalid-request clean pre-state rejections; the two disagreed. → Step 3 now maps substrate invalid-credential/invalid-requestrejected(invalid-request) (clean pre-state, mirroring C1’s own boundary treatment of invalid-credential) and recording-failurerejected(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.


Grace Commons — open foundation for business logic patterns.

This site uses Just the Docs, a documentation theme for Jekyll.