Trust & Signing
How to approve, sign, seal, verify, and amend .it documents.
The trust lifecycle
draft → tracked → approved → signed → frozen → amended (optional)
Each step is a keyword. Each keyword is a line in the document. No external system required.
When rendered, trust blocks print ink-first — approvals, signatures, and the seal appear as hairline legal-document entries, not colored boxes, and date-only timestamps render as plain dates (12 June 2026, no 00:00 UTC). A sealed document reads like a contract, not an app.
Step 1: Track changes
track: | version: 1.0 | by: Ahmed Al-Rashid
This activates history. From this point, the CLI can record revisions below the history: boundary.
Step 2: Approve
Named approvals with role and timestamp:
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
Multiple approvals are common — legal, finance, management, compliance.
Step 3: Sign
Integrity hash seal (tamper-evident record):
sign: Ahmed Al-Rashid | role: CEO | at: 2026-03-06T14:32:00Z | hash: sha256:a1b2c3d4...
sign: is tamper-evident — it records the signer's name, role, timestamp, and a SHA-256 hash of the document body at the time of signing. If the document is modified after signing, the stored hash will no longer match and verification will report the discrepancy. This is integrity sealing, not cryptographic non-repudiation (there are no private keys or PKI).
Step 4: Freeze
Seal the document:
freeze: | status: locked | at: 2026-03-06T14:33:00Z | hash: sha256:e5f6a7b8...
After freeze:, the document is immutable. Any edit changes the content, which invalidates the hash.
Seal with the CLI
One command does sign + freeze:
dotit seal contract.it --signer "Ahmed Al-Rashid" --role "CEO"
This:
- Computes the content hash
- Adds a
sign:block - Adds a
freeze:block with the hash - Writes the sealed file
Verify anytime
dotit verify contract.it
✓ Document integrity verified
Signer: Ahmed Al-Rashid (CEO)
Sealed: 2026-03-06T14:33:00Z
Hash: sha256:a1b2c3...
Amendments: 0
Status: INTACT — no modifications detected
If someone edits the file:
✗ Document integrity FAILED
Expected hash: sha256:a1b2c3...
Actual hash: sha256:x9y8z7...
Status: TAMPERED — content has been modified since sealing
Step 5: Amend (when needed)
A frozen contract needs to change. You have two options:
Without amendment: (the old way):
- Break the seal
- Edit the document
- Re-approve
- Re-sign
- Re-freeze
All original signatures are voided. The audit trail has a gap.
With amendment: (the IntentText way):
amendment: Payment terms updated | section: Payment | was: Net 30 | now: Net 15 | ref: Amendment #1 | by: Ahmed Al-Rashid | approved-by: Sarah Chen
The original seal is preserved. The amendment is additive — it records what changed, where, and who authorized it.
Amend with the CLI
dotit amend contract.it \
--section "Payment" \
--was "Net 30" \
--now "Net 15" \
--ref "Amendment #1" \
--by "Ahmed Al-Rashid"
Verify after amendment
dotit verify contract.it
✓ Document integrity verified
Signer: Ahmed Al-Rashid (CEO)
Sealed: 2026-03-06T14:33:00Z
Hash: sha256:a1b2c3...
Amendments: 1
#1: Payment terms updated (2026-03-15) by Ahmed Al-Rashid
Status: INTACT — original seal preserved, 1 amendment applied
View history
dotit history contract.it
v1.0 2026-03-01 Ahmed Al-Rashid Initial draft
v1.1 2026-03-03 Sarah Chen Legal review — clause 4.2 updated
v1.2 2026-03-05 Ahmed Al-Rashid Final edits
2026-03-06 Ahmed Al-Rashid SEALED
2026-03-15 Ahmed Al-Rashid Amendment #1: Payment terms
Filter by author or section:
dotit history contract.it --by "Sarah Chen"
dotit history contract.it --section "Payment"
dotit history contract.it --json
The history boundary
The history: keyword separates the document from machine-managed history:
title: Consulting Agreement
text: Terms and conditions...
freeze: | status: locked
history:
revision: | version: 1.0 | at: 2026-03-01 | by: Ahmed | change: Initial draft
revision: | version: 1.1 | at: 2026-03-03 | by: Sarah | change: Legal review
History is below the history: keyword. You read it, but the CLI manages it.
Physical signatures for print
sign: is tamper-evident — records signer name, role, timestamp, and SHA-256 hash. Verifiable by code.
signline: is physical — a printed signature line for paper:
signline: Ahmed Al-Rashid | role: CEO | org: Acme Corp | date-line: Date | width: 60%
signline: James Miller | role: CFO | org: GlobalTech Inc. | date-line: Date | width: 60%
Use both in contracts that need digital verification and paper signatures:
sign: Ahmed Al-Rashid | role: CEO | at: 2026-03-06T14:32:00Z
signline: Ahmed Al-Rashid | role: CEO | org: Acme Corp | date-line: Date
sign: | signline: | |
|---|---|---|
| Type | Digital | Physical |
| Verification | SHA-256 hash comparison | Visual on paper |
| Lives in | The .it file | The printed output |
| Queryable | Yes | Yes |
What exactly gets hashed
The hash is reproducible by anyone — there is no secret. Given the source file and any SHA-256 implementation, you can recompute it and confirm a seal yourself. The algorithm runs on the raw source text, in order:
- Cut at the
history:boundary. Only the content abovehistory:is hashed, so appending audit-log entries never changes the document hash. (No boundary → the whole file.) - Drop the seal lines. Lines starting with
sign:,freeze:, oramendment:are removed before hashing — their ownhash:field refers to the body without them, so including them would be circular. (approve:lines are hashed — an approval is part of what it approves.) - Join with
\nand trim. Surviving lines are joined with LF and the whole string is trimmed once. - Hash.
sha256:+ the hex SHA-256 of those UTF-8 bytes.
:::note Reproducibility & determinism
Encoding is UTF-8, line ending is LF (\n) — a file saved with CRLF hashes
differently, so normalize line endings before hashing. The hash covers the canonical
source text, so property order and spacing inside a line matter. Editing in the visual
editor preserves trust lines verbatim, so a normal save never perturbs the hash. The
exact, byte-level spec — with a reference reimplementation that reproduces the core
hash — is SPEC §4.1.
:::
What sealing does — and doesn't — prove
Be precise about the guarantee, because "signed" means different things in different systems:
- ✅ Tamper-evidence. If a single byte of the hashed body changes after sealing,
verifyfails. This is real and useful: it proves the document you're holding is bit-for-bit the one that was sealed. - ✅ Self-verifiable, offline, forever. No vendor, key server, or network is needed to check a seal — just the file and SHA-256. The trust property travels with the file.
- ❌ Not cryptographic non-repudiation. There are no private keys or PKI. A
sign:line asserts who sealed which content; it does not cryptographically bind that assertion to a verified identity. Anyone who can edit the file can also recompute a new hash and re-seal it under any name — what they cannot do is silently alter the sealed body and have the old seal still verify. - ❌ Not a trusted timestamp. The
at:time is self-asserted, not attested by a third party.
This is the right default for the overwhelming majority of business documents — invoices, agreements, approvals — where the question is "has this been altered since we agreed to it?" rather than "can I prove in court who signed it." When you need more, the model is designed to layer without changing the file format:
| Tier | What it adds | Status |
|---|---|---|
| Tamper-evidence | SHA-256 seal, self-verifiable | Built in, free, today |
| Trusted timestamp | RFC-3161 / notary attestation of when | Managed/paid path |
| Identity binding | X.509 / PKI signature over the same hash | Managed/paid path |
The higher tiers attest the same canonical hash defined above — so a document can start
as a plain tamper-evident .it file and gain notarization or PKI later without rewriting
its content.
Related: