saphan decision
Files signed decision records and governance documents into the law store, reads them back, and keeps the workspace's bridge (its shared git record) in step with them.
Files signed decision records and governance documents into the law store, reads them back, and keeps the workspace's bridge (its shared git record) in step with them. Each text is stored at an address made of its citation key and the SHA-256 of its exact bytes, so you can always tell which text was in force at a given time. Keys come in four families: architecture decision records (adr-0001), governance documents (gov-<slug>), conventions (conv-<slug>), and other canon documents addressed by their path (for example skills/lang-go/SKILL.md). A stored text binds only when it is signed, verifies, and has the status RATIFIED; a PROPOSAL is a recommendation.
Filing is three steps, and the signing key never leaves the machine that holds it:
On the machine that holds the root key, saphan decision file with --root-key and --actor signs and files in one step — except on an installation with a gateway, where --root-key on decision file is refused and the three-step form is the only one. On such an installation the filing runs on the gateway and lands in the gateway's bridge, so the --bridge and --checkout paths of file, project and census are paths on the gateway host, and saphan decision migrate must be run on the gateway host itself.
For every document except an architecture decision record, a filing is accepted only when its signer is, byte for byte, an owner named in the installation's root-signed deployment record; if no owner can be determined, the filing is refused. For an architecture decision record, any signer using the root key is accepted. Before anything is written, the installation's edition (read from the same deployment record) decides whether a customer's own version of a locked or team document is accepted (see saphan decision classes); if the edition cannot be read, every customer version is refused. A version signed by the vendor is accepted in every edition.
saphan decision canonical
Prints the exact signing subject for one filing: the address the text will be stored at, and the payload the signature must cover. It writes nothing and contacts nothing, so any machine can state precisely what is to be signed. Give saphan decision file the same key, status, filer and time afterwards, or the signature will not match.
| flag | type | default | what it does |
|---|---|---|---|
--class | string | The document's mutability class: locked, team or open. Required for a path-addressed canon key, optional for governance and convention keys, refused for an architecture decision record; it is part of what is signed. | |
--decision | string | The citation key this text is a version of, such as adr-0001, gov-<slug> or conv-<slug>, or a canon document's path in the bridge, which is converted to its key (required). | |
--filed-at | string | The time of the filing, as an RFC 3339 timestamp (required); it is part of what is signed, so the command never reads a clock for it. | |
--filed-by | string | Who performs the filing (required); it is part of what is signed and cannot be changed afterwards. | |
--status | string | PROPOSAL, RATIFIED, SUPERSEDED or WITHDRAWN (required); only RATIFIED binds. | |
--title | string | A human-readable label; it is not part of the address and nothing is looked up by it. |
saphan decision census
Compares the bridge's decisions/, governance/, conventions/ and skills/ directories against the law store, in both directions: stale or hand-edited files, admitted texts with no file, files for texts never admitted, and governance documents nobody has signed. With --checkout it measures another clone instead, for example one on a remote machine, to tell whether it is behind. Exit code 2 means it found a disagreement; 3 means it could not run (no bridge here, or the path is not a suitable checkout).
| flag | type | default | what it does |
|---|---|---|---|
--branch | string | The branch the bridge must already be on; checked, never switched to. Defaults to main. | |
--bridge | string | Absolute path to the bridge working tree; defaults to bridge inside the workspace. | |
--checkout | string | Absolute path to another clone to compare instead of the bridge; it is only read. Needs both that path and the law store reachable from this machine. | |
--git | string | The git executable to use; defaults to git on your PATH. | |
--verbose | bool | false | Print the full listing and remarks; a clean result otherwise prints a single line. |
saphan decision classes
Prints the table that assigns each canon document path a class (locked, team or open) and the editions (solo, team, enterprise) that accept a customer's own version of it. A path the table does not name is open; the vendor's own versions are accepted in every edition.
saphan decision diff
Prints the newest unsigned draft of a canon document as a unified diff against the version the store currently accepts, which is what the owner reads before signing. Lines that are not part of the diff start with remark: . It writes nothing and reads no key. The baseline is whatever the store accepts now; the owner rule is checked only when a text is filed, so a version accepted under an older rule can still be the baseline.
saphan decision draft
Stores an unsigned draft of a governance or convention document for the owner to review and sign. A draft never binds, is never written into the bridge, and its author and time are what you typed, not attested. Architecture decision records are not drafted; file them directly. Accepting the text is the owner's separate act with saphan decision file.
| flag | type | default | what it does |
|---|---|---|---|
--decision | string | The citation key the text is a draft of (required); architecture decision records are refused. | |
--drafted-at | string | The time of drafting, as an RFC 3339 timestamp (required); the command reads no clock. | |
--drafted-by | string | Who drafted the text (required); it is recorded as typed, not verified. | |
--title | string | A human-readable label; it is not part of the address. |
saphan decision file
Files one text and its owner signature into the law store, verifying the signature before writing and refusing a pair that could never be read as valid. A filing without any signature is refused. On the machine that holds the root key, --root-key with --actor signs and files in one pass instead of taking an envelope; on an installation with a gateway that one-pass form is refused.
Before anything is written, two checks run: for every document except an architecture decision record, the signer must be exactly an owner named in the installation's root-signed deployment record (if no owner can be determined, the filing is refused); and the installation's edition decides whether a customer's own version of a locked or team document is accepted (an unreadable edition refuses every customer version; a vendor-signed version is accepted in every edition).
⚠ A filed text cannot be changed or removed: the store accepts no revision. A correction is a new filing, for example with the status SUPERSEDED or WITHDRAWN.
Once stored, the newest accepted text of every document in the law store is written into the bridge in one commit that stages only the files it wrote and names this filing as its cause, and the bridge is compared back against the store. Where the bridge cannot be written (missing, on another branch, detached, mid-rebase or mid-merge) the filing still stands, and the command reports it as not projected and exits 3; exit 2 means the comparison disagreed or an accepted text could not be written into the bridge. It does not update other clones.
| flag | type | default | what it does |
|---|---|---|---|
--actor | string | Who signs, required with --root-key and refused without it. It is never taken from your configuration or environment, because it is part of the signature; it is not the same as --filed-by. | |
--branch | string | The branch the bridge must already be on; checked, never switched to. Defaults to main. | |
--bridge | string | Absolute path to the bridge working tree; defaults to bridge inside the workspace. | |
--class | string | The document's mutability class: locked, team or open; required for a path-addressed canon key, refused for an architecture decision record. It is part of what is signed. | |
--decision | string | The citation key this text is a version of, or a canon document's path in the bridge (required). | |
--envelope | string | The owner's signature envelope line, given directly; prefer --envelope-file, because a command line is saved in shell history. | |
--envelope-file | string | Absolute path to a file holding the signature envelope line. | |
--filed-at | string | The time of the filing, as an RFC 3339 timestamp (required); it must match what was signed. | |
--filed-by | string | Who performs the filing (required); it must match what was signed. | |
--git | string | The git executable to use; defaults to git on your PATH. | |
--root-key | string | ⛔ Absolute path to the root private key on this machine, to sign and file in one pass. Always a path, never key contents or a key elsewhere; refused together with an envelope. | |
--signed-at | string | The time of signing, with --root-key (refused without it); defaults to --filed-at. | |
--status | string | PROPOSAL, RATIFIED, SUPERSEDED or WITHDRAWN (required); it must match what was signed. | |
--title | string | A human-readable label; it is not part of the address. |
saphan decision ls
Lists the citation keys the law store holds at least one text for, with each key's family and the title of its newest text. It says nothing about whether a text binds (use saphan decision show for that), and a failed listing is reported as a failure, never as an empty store. Unsigned drafts are listed too, marked as unsigned and not binding.
| flag | type | default | what it does |
|---|---|---|---|
--cited | stringArray | A citation key to check: is it in the store, and does its current text bind? Repeat for several; a key the store does not hold makes the command fail. A key the store holds whose current text does not bind is reported as in-store not-binding and does not make the command fail. |
saphan decision migrate
Signs and files every canon document under the bridge's governance/, conventions/ and skills/ directories into the law store in one act, then writes the record back into the bridge and compares the two. The whole batch is judged before anything is written: if any document would be refused, nothing is written unless you pass --skip-refused. Documents already current are skipped, and a document whose bytes differ from the stored text is refused rather than filed as a new version. The same owner and edition checks as saphan decision file apply to every document, and a filed text cannot be changed or removed afterwards. On an installation with a gateway, run it on the gateway host itself; elsewhere it is refused. Prefix with saphan dry-run to see the verdict for each document without writing.
| flag | type | default | what it does |
|---|---|---|---|
--actor | string | Who signs (required); it is part of every signature and never taken from your configuration. | |
--branch | string | The branch the bridge must already be on; checked, never switched to. Defaults to main. | |
--bridge | string | Absolute path to the bridge working tree; defaults to bridge inside the workspace. | |
--class-from-table | bool | false | Take each document's class from the table saphan decision classes prints (required, because the class is part of what is signed). |
--filed-at | string | The time of the filing, as an RFC 3339 timestamp (required). | |
--filed-by | string | Who performs the filing (required). | |
--git | string | The git executable to use; defaults to git on your PATH. | |
--root-key | string | ⛔ Absolute path to the root private key on this machine (required); a path, never key contents. | |
--signed-at | string | The time of signing; defaults to --filed-at. | |
--skip-refused | bool | false | File every document that would be accepted and leave the refused ones out, instead of refusing to start. |
--status | string | PROPOSAL, RATIFIED, SUPERSEDED or WITHDRAWN (required); only RATIFIED documents bind and are written into the bridge. |
saphan decision project
Writes the newest accepted text of every document in the law store into the bridge, as one commit staging only the files it wrote, then compares the bridge back against the store. It is idempotent: with nothing to change it makes no commit. It never deletes a file, never creates a missing directory, never switches branch, and refuses a bridge that is detached or in the middle of a rebase or merge. Exit code 2 means the comparison found a disagreement; 3 means nothing could be compared.
| flag | type | default | what it does |
|---|---|---|---|
--branch | string | The branch the bridge must already be on; checked, never switched to. Defaults to main. | |
--bridge | string | Absolute path to the bridge working tree; defaults to bridge inside the workspace. | |
--git | string | The git executable to use; defaults to git on your PATH. |
saphan decision show
Reads one document from the law store by its citation key and says whether it binds. Each text is reported as verified, unsigned, unverifiable (signed, but this machine cannot tell by whom), absent or unmeasured (the store could not be reached); only a verified RATIFIED text binds.
| flag | type | default | what it does |
|---|---|---|---|
--all | bool | false | Show every stored text of the document, newest first, not only the current one. |
saphan decision sign
Signs one filing's subject with the root key on this machine and writes the signature envelope to a file; this is the only step that touches a private key. The envelope is never printed: standard output carries only a record of the act (who signed, the key id, the time and the payload digest). Status and filing time are checked before anything is signed. A key file whose permissions let other users read it is refused. Who may sign is not checked here: saphan decision file checks it when the envelope is filed.
| flag | type | default | what it does |
|---|---|---|---|
--actor | string | Who signs (required). For every document except an architecture decision record, saphan decision file accepts the filing only if this is exactly (byte for byte) an owner named in the installation's root-signed deployment record; if no owner can be determined, the filing is refused. For an architecture decision record any signer using the root key is accepted. sign itself does not check this. Never taken from your configuration or environment. | |
--class | string | The document's mutability class: locked, team or open; required for a path-addressed canon key, refused for an architecture decision record. | |
--decision | string | The citation key this text is a version of, or a canon document's path in the bridge (required). | |
--filed-at | string | The time of the filing, as an RFC 3339 timestamp (required); it is part of what is signed. | |
--filed-by | string | Who will perform the filing (required); it is part of what is signed and is separate from who signs. | |
--out | string | Absolute path the envelope is written to (required); a relative path is refused, and so is a file that already exists. The file is created readable by you alone. | |
--root-key | string | ⛔ Absolute path to the root private key on this machine; defaults to trust/root.key under the installation's directory (~/.saphan/trust/root.key for a per-user installation, /opt/saphan/trust/root.key for a machine-wide one). A relative path is refused. Always a path, never key contents or a key on another machine. | |
--signed-at | string | The time of signing, as an RFC 3339 timestamp (required); the command reads no clock, because this time is part of the signature. | |
--status | string | PROPOSAL, RATIFIED, SUPERSEDED or WITHDRAWN (required); only RATIFIED binds. | |
--title | string | A human-readable label; it is not part of the address. |
Global options apply to every command — see Every command.
saphan cost
Shows what a stream has cost, from the run record: the number of runs, each run with its model, its cost in US dollars, its status and its token counts (input, cached, output and reasoning), and the s
saphan deny-unix-exec
Runs a command under a filter that forbids it, and everything it starts, from creating Unix-domain sockets that could reach a daemon on the host.