Skip to content

Adds the getting-started guide and rotation runbook - #29

Merged
johnnyt merged 1 commit into
mainfrom
enc-nsi-guides-runbook
Aug 28, 2026
Merged

Adds the getting-started guide and rotation runbook#29
johnnyt merged 1 commit into
mainfrom
enc-nsi-guides-runbook

Conversation

@johnnyt

@johnnyt johnnyt commented Aug 28, 2026

Copy link
Copy Markdown
Member

The two guides the B3 graph puts after the envelope: guides/getting-started.md
and guides/rotation-runbook.md. Both are required before a first release, and
both are written against the package as it exists on main rather than against
the records alone.

The six statement-decisions the bead asks the guides to carry

Stated, not re-decided. Each is a claim the accepted records already fix, and
each now has a place a reader meets it:

  1. Key material arrives through init/1 and never through use options or
    a config file. The getting-started guide shows the compile-time refusal.
  2. Why a host chooses 0x0478, and the required :max_age with no
    default - framed as the answer to how long a crypto-shred takes to take
    effect on a running node, which is why the package will not pick one.
  3. Two root secrets from day one, equal at install (ADR-0005 open
    question 5). A deployment that provisions both never performs P1 step 0,
    the most destructive-looking no-op in the design: generating a fresh
    reference root rather than copying it moves every tenant reference in the
    deployment.
  4. The four procedures, each with preconditions, steps, independent
    verification and rollback, plus both blast radius tables (ADR-0003
    decision 10's attacker table, and ADR-0005's per-step table).
  5. Which steps ship as functions and which are actions on a store this
    package does not own
    , labelled per step, with cache drainage inside each
    destructive procedure rather than as a follow-up.
  6. The honest wording on shredding: a shred destroys plaintext, not
    attribution. The header pseudonym is permanent, and the holder of the
    reference subkey can re-identify it by guess-and-confirm forever, in every
    retained backup. Deleting the tenant's ciphertext rows is
    compliance-mandatory wherever tenant attribution is itself personal data,
    and the shred claim must never be stated as full erasure.

The runbook also carries ADR-0005 decision 1's two-vocabulary mapping table,
decision 2's window, decision 3's "rotation adds a name, a shred removes one,
pruning is manual", decision 6's seam, and ADR-0004 decision 10's division of
labour with encryptor_ecto - the statements the B3 graph lists as carried by
D1 rather than implemented by a bead.

Every code block runs

test/guides_test.exs executes the guides against Encryptor.GuideVaults,
which transcribes the printed vault modules, the printed store and the printed
provider. 25 tests, one per guide claim, named after the claim. A guide that
drifts from the landed surface fails the gate rather than misleading a reader.

Two deliberate differences from the printed text, recorded in the support
module's moduledoc: the non-secret configuration the guides show in
config/config.exs is passed as use options in the suite, and
MyApp.MerchantKeys is an Agent rather than a table (this package defines no
storage).

Documentation currency

README.md moves from "designed, not built" to "built, not released", links
both guides, and gives the installation form as a SHA-pinned git dependency.
The reserved encryptor 0.1.0 on Hex is a name reservation holding no
implementation, and neither the README nor either guide tells a reader to
depend on it. Encryptor's moduledoc had two stale sentences (contracts "under
way", entry points "not built yet"); both are corrected and the guides are
named from there.

Nothing is asserted from ADR-0006, which is at Proposed: the guides mention no
telemetry at all.

Gate

Full mix quality, foreground, under the fleet gate lock:

  • format, compile (warnings as errors), credo --strict, dialyzer: clean
  • dependencies: no unused
  • 386 of 386 tests, 98.2% coverage against a 90% floor
  • Doctor / Gettext / Sobelow declared permanently inapplicable and did not run

mix docs builds both guides as ExDoc extras under a Guides group with no
warnings referencing them.

Sabotage: 25 mutations, one at a time, mix compile --force between each,
every one observed red for the test that cites it and reverted.
The kit's
scan reports no missing and no unverifiable notes. One mutation was rejected
and replaced: removing Envelope.require_binding/4 is not red for the
copied-wrapping test, because the vault-side comparison catches it too. The
note on that test records the double defence, and the mutation that does go
red drops the tenant-ref pair from Envelope.binding/3.

/wurk:verify --unattended: backlog empty (this bead has no plan document).
Own-claim machine checks run instead, all clean - no non-ASCII in any new or
changed file, no {:encryptor, "~> 0.1"} dependency form anywhere, no
telemetry claim, and every error reason and function the guides cite checked
against Encryptor.Error.reason/0 and lib/.

Terminology firewall: four scans clean over the worktree, the outbound diff,
the commit message, and the example-domain drift terms, with a positive control
confirming the pipeline can hit (20 in the guide, 101 in the diff). The two
worked domains are the canonical ones: card processing throughout, and the
signup wizard for the payload-with-no-table context example.

Flagged for the reviewer

  • README.md and Encryptor's moduledoc were edited outside a strict
    reading of "two guides".
    Both contradicted the landed package and both are
    the first thing a reader of the guides arrives from; a getting-started guide
    that disagrees with the README it is linked from is worse than neither.
  • CLAUDE.md still says "Nothing is implemented yet" and still describes
    the package as a scaffold. Left alone deliberately - it is agent instruction
    rather than user documentation, and correcting it is not this bead's. Worth
    its own bead.
  • .quality.exs and coveralls.json still carry the moduledoc-only scaffold
    deviation
    (treat_no_relevant_lines_as_covered), whose own comment says to
    drop it once the package has real code. Not touched here; also worth a bead.

Refs: enc-nsi

Two guides, both required before a first release, written after the
envelope because a getting-started guide for an unimplemented package
is a promise rather than a document.

The getting-started guide stands up a single-key vault and then a
per-tenant one. It states where key material may come from - the
init/1 callback, never use options and never a config file - when to
configure 0x0478 and when to keep the signing default, and why
:max_age is required with no default: it is the answer to how long a
crypto-shred takes to take effect on a running node.

It requires two root secrets from day one, holding the same bytes. A
deployment that provisions both at install never performs P1 step 0,
which is the most destructive-looking no-op in the design: generating
a fresh reference root rather than copying moves every tenant
reference in the deployment.

The rotation runbook is the four procedures with their preconditions,
steps, independent verification and rollback, both blast radius
tables, and the two-vocabulary mapping across the packages. Every step
says whether it is a function this package ships or an action on a
store it does not own, and cache drainage is a step inside each
destructive procedure rather than a follow-up. It carries the honest
wording on shredding: a shred destroys plaintext, not attribution.

Every code block in both guides is executed by Encryptor.GuidesTest
against modules transcribed from the printed text, so a guide that
drifts from the landed surface fails the gate.

README reports the package as built rather than as a scaffold and
gives the installation form as a SHA-pinned git dependency; the
reserved 0.1.0 on Hex holds no implementation.

Refs: enc-nsi
@johnnyt
johnnyt merged commit 5f9cb1f into main Aug 28, 2026
1 check passed
@johnnyt
johnnyt deleted the enc-nsi-guides-runbook branch August 28, 2026 02:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant