Saphan StudioDocs
Audit and compliance

Tracing one change backward

The walk-through — from a merged change back to the decision, the review, the order and the cost.

This is the walk-through to run in the room. Pick one merged change, ideally one the operator did not choose for you, and follow it backward. Every link in the chain is a record that existed before your question was asked, which is the property being demonstrated — not the neatness of the chain.

Work backward rather than forward. Forward from an order you are shown what somebody intended; backward from a merge you are shown what actually landed.

Each command below takes the workspace it should read. Substitute your own path for <path>.

Start at the merge, in your own version control

Take the merge commit from your own repository, not from us. Your version control is the independent end of the chain: whoever wrote the commit, its history is held by a system the product does not own. ⚠ The product does write there — saphan merge lands a gated change on your main line, and with a forge credential configured it pushes and calls the forge's merge — but only as the consequence of a recorded human decision, and the merge commits it writes carry text trailers naming that decision (they are not cryptographically signed).

Note the commit identifier. Everything below hangs off it.

What an auditor asks here — could the product have created this merge on its own? No. A merged state is observed from a real merge and is never a status the engine grants, and the engine's merge act runs only when a person invokes it after the gate. If a change is in your main line, a human decision or your own automation put it there.

Find the decision that authorised it

saphan gates --workspace <path>

Each row is one decision, and carries the actor, the decision from a closed set of words, the time, and the evidence the decision rested on. Locate the row for this change's stream.

Read the actor name as a registry handle, not as a free-text field. Where a historical spelling appears, the render shows it verbatim with a marker indicating the canonical actor it resolves to.

What an auditor asks here — three things, and they are the substance of the walk-through:

  • Was there evidence, or just an approval? An approval without evidence attached is not representable. If the decision exists, evidence was supplied for it.
  • Could the row have been edited since? A later edit of any field, including the actor, breaks verification — and verification is re-checked at merge rather than only at the moment of writing. So an edit made after the fact would have had to survive a check performed at the merge you started from.
  • Does it establish an individual? Look at which regime the row is in; saphan gates prints it. Above the person epoch an owner-class decision names the person's own key and the assertion is kept, so it does establish which person's key signed it. At or below the epoch it establishes only the recorded name and that the row verifies under the workspace key, and not which holder of that key wrote it. Take that limit seriously and read what this does not prove before you write the finding up either way.

Where a review verdict fits. The review verdict and its notes are documents of the change, signed by the reviewer's seat, and they are among the documents a verification bundle carries. The gate row of the review class is signed by the review seat too, above the epoch. To check the whole chain of one change without trusting the machine that produced it, use verify a change yourself; it answers "as of a checkpoint", and the limits are on the limits of the signed record.

Confirm the deciding name was allowed to decide

saphan actor list --workspace <path>

The name recorded as having decided must be enrolled and active in the signed actor registry at the moment of the write, or the write is refused. That check has no off switch, no warning tier and no grace period.

This command reports the roster gap — every actor name the gate log records, how many rows each has written, when each was last seen, and what the guard would say about it today. Read the status word before the rows. A gap that could not be measured is reported as unmeasured, and nothing about who would be refused may be concluded from it.

Add --json for a machine-readable report if you are collecting this into working papers.

What an auditor asks here — can a retired name still approve things? No. Retiring an actor takes effect immediately, regardless of any grant that has not expired. What survives is the decisions that name already wrote, which keep their verification either way.

Read the order that commissioned the work

Work is commissioned by a document, and the document is addressable. Every order a run receives carries a person's passkey approval, bound to the exact order text, single-use and time-limited, and the door that places it refuses one that is unapproved, expired or already spent; whether the order's signature chain back to your root is also enforced is the trust.enforce setting, read on the deployment. Signing it proves who wrote those bytes; registering it answers the other question — is this the current order, and which exact bytes were they? — by recording the document's digest, the commit that carries it, who signed it, and until when it stands. What comes back is a short reference you can paste in place of the document's body.

saphan verify <ref> --stream <stream-name> --workspace <path>

The check resolves the reference to a registration and confirms that the committed bytes match. Passing the document's path instead does not weaken it — the path must still resolve to an active registration over matching committed bytes.

A registration's currency is one of a closed set of words, and it is computed from an append-only log of acts rather than stored as a field anything can overwrite. Withdrawal is a new act. That is why the record can still answer the question an auditor actually asks: what did this order say at the moment that run was dispatched — not what the file says today.

What an auditor asks here — was the work in scope of what was authorised? Compare the registered order at dispatch time against the change you started from. This is the step where a scope finding surfaces, and it is the reason a reference is worth more than a link to a file.

Read the run that did the work

The run record states what ran, under which configuration and which standing instructions, what confined it and which directories stayed writable, how long it took, what it cost, and — on a refusal — the rule and the reason. Read it as the account of what happened, as distinct from what was requested.

Two properties of this row matter to a walk-through. The confinement claim it carries is reproducible: it names the enforcing tool and the writable directories, so your own team can run the same tool with the same policy and attempt to write outside them. And the binary's identity was resolved on the machine that ran it, not on the control plane that dispatched it.

Run records are not signed. They pin content and identity, which is a weaker claim than a signature — see what the record guarantees for why the four kinds of record are kept apart.

One honest note on the surface. This section does not document a single command that prints a run record for you, and it will not invent one. The rows are in your record store and are queryable there; the surfaces that render them belong to operations. If your walk-through has to be repeatable by a non-engineer, agree the query or the surface with your operator before the audit rather than during it.

Read what it cost, in the same place

Cost sits on the run's own row, next to the evidence for the same work rather than on a separate invoice, and it is recorded as names, references and numbers only. What did this change cost therefore gets its answer in the same record, and from the same walk, as who approved it. That is the difference between a governed process and two systems that happen to be about the same work.

One cost fact is worth an auditor's attention in its own right, because it is a fail-closed default rather than a feature — with one limit stated below. A seat can carry a billing class, and the class lives on the same signed seat row as every other fact about that seat — changing it means a new owner-signed entry, not a configuration edit, so nothing can move a seat onto pay-per-token billing without an owner deciding so on the record. An absent class is projected as unknown, never as permission. A consumer that gates spending on an explicit class therefore treats every seat that predates the field exactly as it treats an explicitly metered one — refused until an owner act says otherwise. A permissive default here would have made such a guard decorative on every seat that already existed. ⚠ No dispatch check in the product reads the class today; it is a declaration that appears in reports.

machine list and fleet show both project the current billing class beside the rest of a seat's identity, so you can check it without a separate query.

What an auditor asks here — whether a per-run budget was set and enforced before dispatch. The cost recorded on the run row is what happened; the quote and the ceiling are recorded on the same row, and how they are set — and on which backends the ceiling actually stops a run — is in budgeting a run and before a dollar is spent.

State the chain, and then state its ends

At the end you should be able to write one paragraph — this merge, that decision by that actor with that evidence at that time, commissioned by that order in those exact bytes, executed by that run under that configuration at that cost. And you should be able to say which links you verified yourself and which you read.

Those are different, and checks you can run yourself is the list of the ones you can move from the second column to the first.

On this page