Skip to main content

Trust Keywords

The canonical contract tier holds 8 keywords for document integrity, authority, and in-file approval routing: track:, approve:, sign:, freeze:, amendment:, certify:, route:, and require:. This page documents the trust and routing keywords — tracking versions, recording approvals, signing with hash verification, sealing against modification, formally amending sealed documents, certifying an authority identity, and declaring an in-file approval policy with route:/require:. (The machine-managed x-trust: history/x-trust: revision blocks live below the audit-log boundary.)

track:

Category: Trust Arabic: تتبع:

Activates document version tracking. Once set, the CLI records revisions below the history: boundary automatically.

Syntax

track: | version: value | by: author

Properties

PropertyTypeRequiredDescription
versionstringyesCurrent version identifier
bystringyesWho created this version

Examples

track: | version: 1.0 | by: Ahmed Al-Rashid
track: | version: 2.3 | by: Sarah Chen

Notes

  • track: content is typically empty — data is in properties
  • Required before approve:, sign:, or freeze: can be used
  • History is recorded automatically below x-trust: history as x-trust: revision blocks

approve:

Category: Trust Arabic: اعتماد:

Named approval stamp. Records who approved the document, their role, and when.

Syntax

approve: description | by: name | role: title | at: timestamp | ref: reference

Properties

PropertyTypeRequiredDescription
bystringyesApprover name
rolestringnoApprover's role or title
atstringnoApproval timestamp (ISO 8601)
refstringnoReference to approval authority or document

Examples

approve: Legal review complete | by: Sarah Chen | role: General Counsel | at: 2026-03-05
approve: Finance approved | by: James Miller | role: CFO | at: 2026-03-06
approve: Compliance review | by: Maria Santos | role: Compliance Officer | ref: Policy CMP-2026-01

Notes

  • Multiple approve: blocks are common — legal, finance, compliance, management
  • Requires track: to be set first
  • Queryable: dotit query . --type approve --by "Sarah Chen"

sign:

Category: Trust Arabic: توقيع:

Integrity hash seal. Records the signer's name, role, timestamp, and a SHA-256 hash of the document content at the time of signing. The hash binds the signer's identity (name | role | at), so editing either the content or the named signer breaks that signature. The hash excludes styling and comments — restyling never breaks it. If the document is modified after signing, the stored hash will no longer match and verification will report the discrepancy. This is tamper evidence via hash comparison, not cryptographic non-repudiation (anyone can type a name; proving who is the @dotit/sign layer below).

Syntax

sign: signer name | role: title | at: timestamp | hash: algorithm:value | spec: version

Properties

PropertyTypeRequiredDescription
rolestringnoSigner's role
atstringnoSigning timestamp (ISO 8601)
hashstringnoContent hash at time of signing
specnumbernoSeal ruleset version that produced the hash (current 4)

Examples

sign: Ahmed Al-Rashid | role: CEO | at: 2026-03-06T14:32:00Z | hash: sha256:a1b2c3d4e5f6 | spec: 4
sign: James Miller | role: CFO | at: 2026-03-06T15:00:00Z

Cryptographic upgrade (key: + sig:)

A plain sign: line (no key:/sig:) is a named approval, like approve:. To make it cryptographically provable, the @dotit/sign package adds key: (the signer's Ed25519 public key) and sig: (an Ed25519 signature over the document hash):

sign: Ahmed Al-Rashid | role: CEO | at: 2026-03-06T14:32:00Z | hash: sha256:a1b2c3d4 | key: ed25519:<pubkey> | sig: <signature>
PropertyTypeDescription
keystringSigner's Ed25519 public key (ed25519:<base64url>)
sigstringEd25519 signature over the document hash (base64url)

The public key travels in the line, so verification needs nothing but the file. Generated and verified only by @dotit/sign (signDocumentCrypto / verifyCryptoSignatures) — never hand-written.

sign: vs x-doc: signline

sign:x-doc: signline
TypeDigitalPhysical
VerificationSHA-256 hash comparison — machine-verifiableVisual line on paper — human-verifiable
Lives inThe .it file permanentlyThe printed/PDF output
Use caseFile integrity verificationPaper contract signatures

Use both when a contract needs digital verification and paper signatures.


freeze:

Category: Trust Arabic: تجميد:

Seal the document. After freeze:, any edit to the content above invalidates the hash; the seal also covers the signatures and its own at:/status:, so editing those breaks it too. Restyling and comments are excluded — re-theming or reformatting a sealed document never breaks its seal.

Syntax

freeze: | at: timestamp | hash: algorithm:value | spec: version | status: locked

Properties

PropertyTypeDescription
statusstringlocked
atstringSealing timestamp (ISO 8601)
hashstringSeal hash (content + signatures + seal metadata)
specnumberSeal ruleset version that produced the hash (current 4)

Examples

freeze: | at: 2026-03-06T14:33:00Z | hash: sha256:e5f6a7b8 | spec: 4 | status: locked

Notes

  • freeze: content is typically empty — data is in properties
  • After freezing, the only permitted additions are amendment: blocks
  • Use dotit seal to compute the hash and add sign: + freeze: automatically
  • Use dotit verify to check the hash against current content

amendment:

Category: Trust Arabic: تعديل:

Formal change to a frozen document. Preserves the original seal while recording what was changed, where, who authorized it, and when.

Syntax

amendment: description | section: target | was: previous | now: current | ref: identifier | by: author | at: timestamp | approved-by: approver | hash: value

Properties

PropertyTypeRequiredDescription
sectionstringyesWhich section was amended
wasstringnoThe previous value or text
nowstringyesThe new value or text
refstringnoAmendment reference identifier
bystringnoWho authored the amendment
atstringnoAmendment timestamp
approved-bystringnoWho approved the amendment
hashstringnoHash of the amendment block

Examples

amendment: Payment terms updated | section: Payment | was: Net 30 | now: Net 15 | ref: Amendment #1 | by: Ahmed Al-Rashid | approved-by: Sarah Chen
amendment: Scope extended | section: Scope | now: Includes Phase 2 deliverables | ref: Amendment #2 | by: Ahmed Al-Rashid | at: 2026-04-01

The amendment model

Without amendment:, changing a frozen document means:

  1. Breaking the seal (invalidating freeze: and sign:)
  2. Making edits, re-approving, re-signing, re-freezing

All original signatures are voided. The audit trail has a gap.

With amendment::

  • The original seal is preserved
  • The amendment is additive — it records the change alongside the sealed content
  • Each amendment can have its own approval chain (approved-by:)
  • dotit verify reports both the original seal status and all amendments

CLI

dotit amend contract.it \
--section "Payment" \
--was "Net 30" \
--now "Net 15" \
--ref "Amendment #1" \
--by "Ahmed Al-Rashid"

Notes

  • Validation error AMENDMENT_WITHOUT_FREEZE if the document has no freeze: block
  • Amendments appear after freeze: but before the x-trust: history boundary
  • Each amendment is independently queryable

route:

Category: Trust (contract tier) Arabic:

Declares the order in which a document's required approvals are collected. With require: it gives a .it document its own in-file approval workflow, whose live state is derived from the file (workflowState) — never stored, so the document is the single source of truth and can never drift from a separate database. route:/require: lines stay inside the hashed body, so a sealed document keeps its hash.

Syntax

route: sequential
route: parallel

The order may also be given as a property: route: | order: sequential.

Properties

PropertyTypeRequiredDescription
orderenumnosequential (default) or parallel. The bare content (route: parallel) is read first, then this property.
  • sequential (default) — approvals are expected in the declared require: order; next is the first unfulfilled required approver.
  • parallel — all required approvals may be collected in any order.

Examples

route: sequential
require: manager
require: finance | when: amount > 100000
require: legal

Notes

  • Without a route:/require: policy a document has nothing outstanding (complete: true).
  • route:/require: were reserved in 4.4. Documents authored earlier parsed them as custom blocks; the deriver still resolves those.

require:

Category: Trust (contract tier) Arabic:

Declares one required approver for the document's approval policy. Repeat require: once per approver. A requirement is matched against the role:/by: token of the document's approve: lines; an unmatched, non-optional requirement is what keeps the workflow open.

Syntax

require: <role-or-name> | when: <condition> | optional: yes

Properties

PropertyTypeRequiredDescription
whenstringnoA single comparison (key <op> value) gating whether this approver is required (see below). When it does not hold, the requirement is inactive.
optionalenumnoyes/true marks the requirement informational — it never blocks completion.

The match token is the requirement's content (e.g. require: legal), falling back to a role:/by: property if content is empty.

Conditional requirements — when:

when: holds one comparison, key <op> value — operators = == != > < >= <= (= is loose for ==). The compare is numeric when both sides parse as numbers (thousands separators stripped), otherwise string. There is no &&/||/! and no grouping — a single comparison only. The key is resolved against the document's own values: metric: labels/keys and meta: properties. It runs on a safe recursive-descent evaluator, never eval. An unresolvable condition defaults to active (a required approval is never silently dropped because a value was missing).

metric: Contract Value | key: amount | value: 250000 | unit: USD

route: sequential
require: manager
require: finance | when: amount > 100000
require: legal | optional: yes

Deriving the live state — workflowState

workflowState(source) (and deriveWorkflowState(doc)) DERIVE the live approval state purely from the route:/require: lines and the approve: lines — nothing is stored, so re-deriving always matches the file:

import { workflowState } from "@dotit/core";

const state = workflowState(source);
// → {
// hasRoute, // true when a route:/require: policy is declared
// order, // "sequential" | "parallel"
// required, // every declared requirement, verbatim: { match, when?, optional }
// active, // requirements currently in force (their when: holds, or none)
// fulfilled, // active required match-tokens that have a matching approve:
// pending, // active, non-optional match-tokens still awaiting approval (declared order)
// next, // the next pending approver (sequential), or null
// complete, // true when every active, required approver has approved
// }

An approve: line fulfills a requirement when its role: or by: value equals the requirement's match token:

require: manager
approve: Budget reviewed | by: Sarah | role: manager | at: 2026-03-20
// → manager is now fulfilled

Examples

route: sequential
require: department-head
require: finance | when: amount >= 50000
require: ceo | when: amount >= 1000000
require: audit | optional: yes

Notes

  • A document with no route:/require: policy is complete: true (nothing outstanding).
  • require:/route: round-trip byte-for-byte and stay inside the hashed body, so a sealed document keeps its hash.

certify: (authority layer)

Category: Trust (contract tier) Arabic:

certify: is a canonical contract-tier keyword — but unlike sign:/freeze: (which are integrity, checkable from the bytes alone), it carries an authority claim that needs the issuer's key to verify. The line itself is written by the @dotit/sign authority layer: a certification authority (UTS) verifies the account/entity once, then issues a certify: line that anyone can re-check offline. The core parser recognizes certify: and round-trips it losslessly, but presence of a certify: line is a claim, not a verdict — the certified trust tier is shown only when a caller passes a cryptographically verified result from @dotit/sign.

Syntax

certify: issuer | account: id | entity: legal name | at: timestamp | hash: sha256:value | key: ed25519:pubkey | sig: signature | ica: intermediate-cert

Properties

PropertyTypeRequiredDescription
accountstringyesThe certified account identifier
entitystringnoKYC-verified legal name (identity-verified accounts)
atstringyesCertification timestamp (ISO 8601)
hashstringyesThe document hash being certified
keystringyesThe issuer's Ed25519 public key
sigstringyesThe issuer's signature over the certification payload
icastringnoIntermediate certificate token chaining the signing key to a root

Example

certify: UTS | account: al-diwan | entity: Al-Diwan Contracting W.L.L. | at: 2026-06-13T19:56:11Z | hash: sha256:a1b2c3d4 | key: ed25519:<pubkey> | sig: <signature> | ica: <intermediate-cert>

Root → intermediate certificate hierarchy

@dotit/sign 1.3 adds a CA-style key hierarchy: an offline root key vouches for a short-lived online intermediate key (via issueIntermediate()), producing the compact ica: token embedded in each certify: line. Verifiers trust only the root keyverifyCertifications() validates the chain root → intermediate → certification and returns a chain: { rootPublicKey, notBefore, notAfter }. If the online intermediate key leaks, it is rotated without re-trusting anything. A certify: line with no ica: falls back to the legacy single-key model, where the signing key itself must be the trusted key.

Notes

  • certify: lines are excluded from the document hash (like sign:/freeze:/amendment:).
  • Verified only by @dotit/sign (verifyCertifications) — never hand-computed.

The trust chain

A typical trust workflow combines the routing and integrity keywords:

title: Service Agreement

section: Parties
contact: Ahmed Al-Rashid | role: CEO | email: ahmed@acme.com
contact: Sarah Chen | role: General Counsel | email: sarah@acme.com

section: Terms
Full contract terms...

track: | version: 1.0 | by: Ahmed Al-Rashid
approve: Legal review complete | by: Sarah Chen | role: General Counsel | at: 2026-03-05
sign: Ahmed Al-Rashid | role: CEO | at: 2026-03-06T14:32:00Z | hash: sha256:a1b2c3d4 | spec: 4
freeze: | at: 2026-03-06T14:33:00Z | hash: sha256:e5f6a7b8 | spec: 4 | status: locked

Extension keywords

Automated history and revision blocks are available in the x-trust: namespace. These are managed by the CLI — you do not write them manually.

ExtensionPurpose
x-trust: historyHistory boundary marker — separates live document from machine-managed history section
x-trust: revisionAuto-generated change record written by dotit seal and dotit amend

See the extensions overview in Keywords → for full syntax.