Start where the companion piece stopped, because the construction only makes sense against the specific thing it has to produce.

A deviation is raised overnight on a granulation step. By morning an agent chain has assembled the timeline, retrieved the batch record and the prior deviations, written an impact assessment and proposed a disposition. A reviewer in the quality unit opens the record and applies an electronic signature whose meaning is approval. Every entry in that sequence is attributable to an account, timestamped, unaltered and bound. And the question the regulation actually asks — which person determined that this material meets its specifications, against what evidence — has no field to land in.

This piece builds the field. Not as a schema change, which would be a smaller idea than the problem, but as three constructions that have to arrive together because any one of them alone leaves the gap open.

The deviation, the chain, the identifiers and every code sample below are a constructed illustration, assembled from patterns documented in published regulation and vendor documentation. Nothing here reports a real batch, product, site, company, deployment or engagement, and none of it is a validated artefact or a compliance deliverable. It is a design argument written to be read.

Construction one: the grant, created at the handoff

The unit of the existing model is the entitlement: a standing capability attached to a service account, saying what that account may do, indefinitely, until someone changes it. Entitlements are reviewed periodically, and the review is the compensating control for the fact that no decision is recorded at the point of use.

The unit of this construction is the grant: an object created at the moment authority passes, valid for one piece of work, and evidenced by its own existence.

A grant has five properties, and dropping any of them collapses it back into an entitlement wearing different clothes.

  1. It is created at the handoff, not inherited from the environment. If the receiving agent could have obtained the capability without the sending agent constructing something, no handoff occurred and there is nothing to evidence.
  2. It names its parent. A grant with no parent pointer is a root. There is exactly one root in a valid chain, and it is a person; anything else claiming rootship is a bug the verifier must reject rather than a configuration a site may choose.
  3. It permits strictly less than its parent. Not less than or equal. A grant identical to its parent carries no information, because it is the same grant with a new identifier, and a chain of identical grants is decorative.
  4. It is scoped, and it expires. Scope binds it to one deviation, one batch, one change request. Expiry is bounded by the parent's expiry, so no descendant can outlive the authority it derives from.
  5. It pins the evidence it was issued against. A digest over the exact record set in front of the issuer at the moment of issue. This is the field that turns "what the decider could see" from a reconstruction into a lookup.
FIGURE 1 · THE GRANT CHAIN One root. Three grants. Each narrower than the one above it. ROOT AUTHORITY a named member of the quality unit the root of a valid chain is a person — never a service, at any depth issues GRANT 0 · THE INVESTIGATION MANDATE scoped to deviation DEV-2026-0814 · expires in 24 hours permits: read_batch_record · read_equipment_logs · read_prior_deviations              draft_assessment · recommend_disposition everything the work needs, and nothing that decides derives GRANT 1 · THE RETRIEVAL AGENT parent: grant 0 · expires no later than its parent permits: read_batch_record · read_equipment_logs · read_prior_deviations dropped: draft_assessment · recommend_disposition it fetches; it does not conclude derives GRANT 2 · THE DRAFTING AGENT parent: grant 0 · evidence digest pinned at issue permits: draft_assessment · recommend_disposition dropped: read_batch_record · read_equipment_logs · read_prior_deviations it reasons over what it was given, and cannot widen the evidence set THE TERMINAL CAPABILITY approve reject release appears in no grant in this chain, and cannot: the issuing rule mints it only to a principal that is a person The chain narrows at every step, and it terminates upward in a person rather than downward in a service.

The narrowing property is the one that gets dropped first in implementation, and it is the one doing the most work. Consider the retrieval agent and the drafting agent in the figure. The retrieval agent holds three read capabilities and no writing capability. The drafting agent holds the two authoring capabilities and none of the reads — which means it cannot widen the evidence set behind its own conclusion. That is not a security nicety. It is the property that makes an impact assessment reviewable, because the evidence the assessment rests on is fixed and named before the assessment exists, rather than being whatever the drafting step happened to reach for.

What this changes about scoping a defect. The teardown's sharpest operational failure was the extension of an investigation to associated batches. Under ambient authority, a defect in a retrieval step bounds the affected population at everything the service account touched in the window, because that is the only boundary the record supports. Under per-decision grants, the affected population is exactly the set of decisions whose chains contain a grant derived from the defective step — an enumerable set, recoverable by query, defensible in front of somebody who will ask how the number was arrived at.

And what it changes about stopping. Revocation currently has one granularity: disable the account, and everything stops. A grant chain gives three. Revoke one leaf grant and one agent loses one capability on one deviation. Revoke a mid-chain grant and everything derived from it fails closed. Revoke the root and that investigation ends while every other investigation continues. The estate stops being a system where the only available response to a defect is a full stoppage of the quality workflow.

Construction two: draft, recommend, decide — and the line between the second and the third

The regulation assigns approve-or-reject to the quality control unit. It does not assign the drafting of an impact assessment to anyone in particular, and it does not say a human must personally retrieve a batch record. The interesting boundary is therefore not between human work and machine work; it is between the work that produces a recommendation and the act that makes a determination.

That boundary can be drawn precisely, and it falls into three bands.

  • Freely delegable. Retrieving batch records, equipment logs, environmental data and prior deviations. Summarising a timeline. Drafting an impact assessment. Computing a proposed disposition. Any grant in a valid chain may hold these, subject to its scope and its expiry.
  • Delegable only with a person committing. Opening a deviation. Extending an investigation to further batches or products. Raising a change request. A chain may prepare each of these completely; a person commits it, and the record shows the preparation and the commitment as two acts by two principals.
  • Never issuable to a chain. Approving a disposition. Approving a change. Rejecting material. Releasing a batch. There is no scope, no expiry and no chain depth at which a grant carrying one of these is valid.
FIGURE 2 · THE CAPABILITY LINE Draft and recommend are delegable. Decide is not. BAND ONE · FREELY DELEGABLE TO A CHAIN read_batch_record  ·  read_equipment_logs  ·  read_environmental_logs read_prior_deviations  ·  summarise_timeline draft_assessment  ·  compute_proposed_disposition held by any grant in a valid chain, subject to that chain’s scope and expiry BAND TWO · DELEGABLE ONLY WITH A PERSON IN THE PATH open_deviation  ·  extend_investigation_to_batches  ·  raise_change_request a chain may prepare these; a person commits them the record shows the preparation and the commitment as two separate acts, with two separate principals — which is the distinction the countersignature currently collapses BAND THREE · NEVER ISSUABLE TO A CHAIN approve_disposition  ·  approve_change  ·  reject_material  ·  release_batch stated positively: the authority service mints these only to a principal whose kind is person, and the system of record verifies the kind at the point of action rather than trusting the caller — so a chain cannot cross the line by being well formed enforced at the resource, not in configuration State it as an issuance rule, not as a prohibition. A prohibition can be forgotten; an issuance rule cannot.

The middle band is the one people argue about, and the argument is worth having in the open. Its purpose is not ceremony. It is that a chain which can open its own deviations and extend its own investigations can also, without anyone intending it, define the boundaries of the problem it is investigating — and the regulation's requirement that an investigation extend to associated batches is precisely a requirement about a boundary. Preparing that extension is analytical work an agent does well. Committing to it is a determination about scope, and scope determinations are where investigations go wrong.

The third band needs a stronger form of statement than a policy, and this is the part of the construction I would defend hardest.

State it as an issuance rule, not as a prohibition. A prohibition says: do not grant release_batch to a service principal. It lives in a policy document, or in a rule in an authorisation engine, and it is enforced by whoever remembers it during the next migration, the next vendor integration, the next emergency. An issuance rule says something different in kind: the authority service will mint a grant carrying a terminal capability only when the requesting principal's kind is person. There is no configuration path that produces the forbidden grant, because the code that could produce it does not exist. The difference matters at exactly the moment when it matters most, which is when somebody is under pressure at two in the morning.

And verify at the resource, not only at the issuer. A check at the authority service establishes that a grant was permitted to be created. A check at the system of record establishes that this call was within the authority it was actually made under. Those are different questions and only the second is the one an inspector is asking. The batch-release endpoint should evaluate the presented chain — root is a person, no link widens, none has expired, the terminal capability is held directly by a person and not by any derivative — and refuse on any failure. That evaluation is a few dozen lines and it is the only place in the design where a mistake is unrecoverable, so it is the one place worth over-testing.

Configuration

The construction, in three files

Written to be read rather than deployed. The first file is the grant and the issuance rule that makes the capability line structural rather than procedural. The second is the verifier that runs where the action lands. The third is the decision record, which is where the sector's retention constraint shows up as concrete field choices rather than as a paragraph of intent.

The load-bearing lines are the Capability split and the return type of issue. Terminal capabilities are a separate type from delegable ones, and the only overload of issue that accepts a TerminalCapability requires a Person. That is the capability line expressed so that violating it is not a policy breach but a type error — and, at runtime, a rejected request rather than a granted one.

grant.ts
/** Capabilities a chain may hold. Nothing here decides anything. */
export type DelegableCapability =
  | "read_batch_record"
  | "read_equipment_logs"
  | "read_environmental_logs"
  | "read_prior_deviations"
  | "summarise_timeline"
  | "draft_assessment"
  | "recommend_disposition";

/** Capabilities the regulation assigns to a unit of persons. Never held by a chain. */
export type TerminalCapability =
  | "approve_disposition"
  | "approve_change"
  | "reject_material"
  | "release_batch";

export interface Person {
  readonly kind: "person";
  readonly directoryId: string;
  /** Captured at issue. A directory is a live system; a record is an archive. */
  readonly printedName: string;
  readonly unit: "quality" | "production" | "engineering";
}

export interface Workload {
  readonly kind: "workload";
  readonly workloadId: string;
  readonly component: string;
}

export type Principal = Person | Workload;

export interface Grant {
  readonly grantId: string;
  /** Exactly one grant in a valid chain has null here, and its holder is a Person. */
  readonly parentGrantId: string | null;
  readonly holder: Principal;
  readonly permits: readonly DelegableCapability[];
  readonly scope: { readonly deviationId: string; readonly batchId: string };
  readonly notAfterIso: string;
  /** Digest over the exact record set in front of the issuer at issue time. */
  readonly evidenceDigest: string;
  readonly issuedIso: string;
}

/** A grant that carries a terminal capability. Its holder is a Person by type. */
export interface TerminalGrant {
  readonly grantId: string;
  readonly holder: Person;
  readonly permits: readonly TerminalCapability[];
  readonly scope: { readonly deviationId: string; readonly batchId: string };
  readonly notAfterIso: string;
  readonly evidenceDigest: string;
  readonly issuedIso: string;
}

export type IssueFailure =
  | { readonly kind: "would-widen"; readonly added: readonly DelegableCapability[] }
  | { readonly kind: "does-not-narrow" }
  | { readonly kind: "would-outlive-parent"; readonly parentNotAfterIso: string }
  | { readonly kind: "scope-mismatch"; readonly parentScope: string }
  | { readonly kind: "non-person-root"; readonly holderKind: "workload" };

export type IssueResult<T> =
  | { readonly ok: true; readonly grant: T }
  | { readonly ok: false; readonly failure: IssueFailure };

/**
 * Derive a narrower grant from a parent. There is deliberately no parameter by which a
 * caller can add a capability the parent does not hold, and no overload accepting a
 * TerminalCapability — which is the capability line, expressed structurally.
 */
export function deriveGrant(
  parent: Grant,
  holder: Principal,
  permits: readonly DelegableCapability[],
  notAfterIso: string,
  newGrantId: string,
  issuedIso: string,
): IssueResult<Grant> {
  const added = permits.filter((c) => !parent.permits.includes(c));
  if (added.length > 0) {
    return { ok: false, failure: { kind: "would-widen", added } };
  }
  if (permits.length === parent.permits.length) {
    // A grant identical to its parent IS the parent, with a new identifier and no new
    // information. Callers wanting a pass-through should pass the parent, not clone it.
    return { ok: false, failure: { kind: "does-not-narrow" } };
  }
  if (notAfterIso > parent.notAfterIso) {
    return { ok: false, failure: { kind: "would-outlive-parent", parentNotAfterIso: parent.notAfterIso } };
  }
  return {
    ok: true,
    grant: {
      grantId: newGrantId,
      parentGrantId: parent.grantId,
      holder,
      permits,
      scope: parent.scope,
      notAfterIso,
      evidenceDigest: parent.evidenceDigest,
      issuedIso,
    },
  };
}

/**
 * The issuance rule for terminal capabilities. The signature is the rule: this function
 * cannot be called with a Workload, so no code path anywhere in the estate produces a
 * terminal grant held by a chain. A prohibition can be forgotten. This cannot.
 */
export function issueTerminal(
  holder: Person,
  permits: readonly TerminalCapability[],
  scope: { readonly deviationId: string; readonly batchId: string },
  notAfterIso: string,
  evidenceDigest: string,
  grantId: string,
  issuedIso: string,
): TerminalGrant {
  return { grantId, holder, permits, scope, notAfterIso, evidenceDigest, issuedIso };
}

All three files are a constructed illustration written to be read. None is a validated artefact, none has been qualified against any specification, and using any of it in a regulated estate would require the full validation lifecycle that this piece deliberately does not attempt to describe.

Construction three: a record built for the horizon, not for the incident

This is where the sector's distinctive constraint stops being background and starts driving field-level decisions.

Pharmaceutical record retention is not measured in a fixed number of years from creation. It is measured against the batch — records are kept for a period tied to the product's expiration date, which means the retention clock for a decision made today is set by something that has not happened yet. In practice a decision record has to remain readable and meaningful long after the application that wrote it has been decommissioned, the schema it was written in has been superseded twice, and the people named in it have left.

Most systems are designed for the incident: something goes wrong, someone opens the record within weeks, and the surrounding context is still live. Design for the horizon instead and four choices change.

FIGURE 3 · THE EVIDENCE OBJECT The record has to answer the questions after the software is gone. FIELD THE QUESTION IT ANSWERS LATER decisionId + batchId the anchor Which decision is this, and what does it concern? decidedBy directory id + printed name as it stood Who decided? The name is captured at the time, because a directory is not an archive. meaning approve · reject · release What did the person determine? Not that a signature event occurred — what it meant. grantChain leaf to root, in order What authority did the preparatory work run under, and did it narrow at every step? evidenceDigest a hash over the exact set presented What could the decider see — as distinct from what the system happened to contain? recommendation + author digest of what the chain proposed What did the chain propose, and did the person agree? A divergence is evidence that a judgement occurred. exclusions what was looked for and not found Was the absence checked, or was it merely absent? The two are indistinguishable without this field. formatVersion + rendering plus a plain-text projection Can it still be read? Retention runs against the batch expiry and outlasts the application that wrote it. Every field exists because a question will be asked when nobody involved is still available to answer it.

Capture the printed name, do not reference the directory. A record holding only a directory identifier is a record that depends on a live identity system to be readable. Directories are migrated, merged, tenanted and cleaned. Capturing the printed name as it stood at the moment of decision costs one string and removes an external dependency from a record that has to survive the removal of external dependencies. This is also, not incidentally, exactly what the electronic-signature rules already ask for on the face of the signature — the construction is following an instinct the regulation already had.

Pin the evidence set, do not describe it. A record saying that the reviewer considered the batch record and the relevant prior deviations is a record that requires reconstruction, and reconstruction against a live system answers a different question than the one asked. Pinning the exact record identifiers with their versions and a digest over the set turns "what could the decider see" into a lookup. It also makes a specific and useful failure visible: if the digest cannot be recomputed because a referenced record has been superseded, the record says so rather than quietly producing a different answer.

Enumerate the exclusions. This is the field most often missing and the one that most often matters. An investigation that searched for prior occurrences on the same line and found none produces, in a conventional record, exactly the same artefact as an investigation that never searched. The two are radically different pieces of evidence and the record cannot distinguish them. Writing down what was searched for, over what scope, and that nothing was found, converts an absence into a finding. It is three fields and it is the single cheapest improvement in the whole design.

Store a rendering alongside the structure. The structured record is what queries run against. The plain-text projection is what someone reads when the query engine is gone. Storing both is redundancy, and redundancy is the correct answer to a retention horizon that outlasts software. The projection should be generated at write time from the structured form, never reconstructed later — a rendering produced years afterwards by different code is a new document, not a copy.

There is a fifth property that is less a field than a discipline: record the divergence. When a decider disagrees with the chain's recommendation, that fact is the strongest single piece of evidence available that a judgement occurred rather than an endorsement. It should be a first-class field rather than something inferable by comparing two blobs of text. And a site whose divergence rate is zero across thousands of decisions has learned something important about its own review process, whether or not it wanted to.

Where the construction breaks

A construction piece that does not attack its own design is marketing. Four ways this fails, in descending order of how likely I think they are.

The chain narrows nominally and not usefully. The narrowing rule requires each grant to permit strictly less than its parent. It is trivially satisfiable in bad faith: give the root grant every capability in the vocabulary, and every derived grant can drop one irrelevant capability and still hold everything that matters. The rule catches identical grants; it does not catch a root that was over-broad to begin with. The mitigation is not a cleverer rule, it is a review of the root grants — which is a periodic entitlement review, reintroduced at exactly one point in the design. I would rather say that plainly than pretend the construction eliminates the thing it mostly displaces.

The human commitment degrades into a second countersignature. The middle band asks a person to commit acts the chain prepares. Under throughput pressure, committing becomes clicking, and the design has bought a second signature on a second artefact. Nothing in the construction prevents this, because nothing technical can: the difference between a considered commitment and a reflexive one is not observable at the interface. What the construction does supply is the divergence rate, which makes the degradation measurable even though it cannot make it impossible. A site should watch that number the way it watches any other process indicator, and should be uncomfortable when it goes flat.

The pinned evidence set becomes a compliance artefact nobody opens. Pinning the evidence makes the record complete. It does not make anyone read it. There is a real risk that the digest is computed, stored, never verified, and quietly becomes wrong when an upstream system changes how it versions records — at which point the field is worse than absent, because it looks like assurance. The mitigation is boring and non-negotiable: recompute a sample of digests on a schedule and treat a mismatch as a deviation in its own right. If nobody is willing to fund that, the field should not be built.

The falsifier: the whole thing may be solving a problem the regulator does not have. If inspection practice treats the electronic signature on an agent-produced artefact as fully satisfying the quality unit's approve-or-reject responsibility — with no interest in what the signer could see or where the conclusion originated — then this construction is an expensive answer to a question nobody is asking, and the honest recommendation would be to build none of it. I have no basis for asserting that inspectors reject the countersignature, and I am not going to invent one. What I will say is what the asymmetry looks like: the cost of building this early is a design constraint absorbed while the estate is small, and the cost of building it after the expectation crystallises is retrofitting attribution into chains already operating on commercial product, which is the same problem as reconstructing it from logs, which is the problem the whole pair exists to say cannot be solved.

One more limit, stated because it cuts against how this argument is usually sold. Nothing here is a validated system, and nothing here shortens the validation lifecycle that would be required to put any of it into a regulated estate. The construction makes a record possible. Making it real is a qualification exercise with a specification, a risk assessment, a test protocol and a periodic review, and anyone presenting a design like this one as though it removes that work is selling something.

What to build first

The three constructions arrive together in the finished design, but they do not have to be built in one go, and the order matters more than the schedule.

  1. The exclusion list. Three fields, no new infrastructure, and it converts every investigation record from an assertion into a finding. It is independently valuable even if nothing else in this piece is ever built.
  2. The verifier at the resource. Before there are grants worth verifying, put the check in front of the terminal endpoints — release, approval, rejection — and have it reject any caller whose principal kind is not a person. That is a single guard, it is testable, and it makes the capability line real on the day it ships rather than on the day the grant model is finished.
  3. The evidence digest. Pin what was presented. This can be added to the existing record shape without the grant model existing at all, and it answers the question that comes up most often in practice.
  4. The grant chain. The largest piece, and the one that needs the authority service, the handoff interface and the verifier's chain-walking path together. Build it last, against an endpoint that is already refusing non-person callers and a record that already pins its evidence, so that the chain has something to be verified against rather than being the first thing anyone trusts.

The teardown that precedes this piece argues that the gap is structural rather than an oversight, and that no amount of validation or audit-trail rigour reaches it, because the object the framework needs was never created. Everything above is one answer to that. It is not the only possible answer, and I would rather see a different one built than see this one admired.