Skip to content

Commit 5f9cb1f

Browse files
committed
Adds the getting-started guide and runbook
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
1 parent 1b42c26 commit 5f9cb1f

8 files changed

Lines changed: 2010 additions & 11 deletions

File tree

README.md

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,23 @@ Ergonomic envelope encryption for Elixir - a vault module, pluggable key
1010
providers, and per-tenant keys - on the
1111
[aws_encryption_sdk](https://hex.pm/packages/aws_encryption_sdk) engine.
1212

13-
## Status: designed, not built
13+
## Status: built, not released
1414

1515
The five founding architecture decision records were **accepted on
16-
2026-08-27**. They fix the contracts this package is made of. **No
17-
implementation has landed yet**: `lib/` holds a moduledoc, the package is not
18-
published, and nothing below is a promise about a function you can call today.
16+
2026-08-27**. They fix the contracts this package is made of, and the vault
17+
core and the per-tenant envelope are implemented against them: the `use
18+
Encryptor.Vault` macro and its supervision tree, the configuration freeze,
19+
`encrypt/2`, `decrypt/2`, `rekey/2`, the key-provider behaviour with its
20+
`Static` and `Function` adapters, `Encryptor.Envelope`'s
21+
`provision/3`/`unwrap/2`/`rewrap/2`, and `Encryptor.Message.describe/1`.
22+
23+
**Nothing is released.** The package is not published to Hex - the reserved
24+
`encryptor 0.1.0` there is a name reservation holding no implementation - so
25+
consume it as a git dependency until the first real release. See
26+
[Installation](#installation).
27+
28+
Start with the **[getting-started guide](guides/getting-started.md)** and the
29+
**[rotation runbook](guides/rotation-runbook.md)**.
1930

2031
| Record | Decides |
2132
|---|---|
@@ -100,15 +111,32 @@ open and the design works around both until they move:
100111

101112
## Installation
102113

114+
The package is **not published to Hex**. `encryptor 0.1.0` on Hex is a name
115+
reservation and holds no implementation; do not depend on it. Until the first
116+
real release, consume this package as a git dependency pinned to a full SHA:
117+
103118
```elixir
104119
def deps do
105120
[
106-
{:encryptor, "~> 0.1"}
121+
{:encryptor, github: "riddler/encryptor", ref: "<full 40-character sha>"}
107122
]
108123
end
109124
```
110125

111-
Not yet published to Hex.
126+
Pin a SHA rather than a branch. A moving dependency on a package that decides
127+
ciphertext layout is a package that can change what your stored rows mean
128+
between two `mix deps.get` runs.
129+
130+
## Guides
131+
132+
- **[Getting started](guides/getting-started.md)** - a single-key vault and a
133+
per-tenant vault, where key material is allowed to come from, why a host
134+
chooses `0x0478`, why `max_age` has no default, and the two root secrets a
135+
deployment provisions on day one.
136+
- **[Rotation runbook](guides/rotation-runbook.md)** - the four operator
137+
procedures, what each step destroys, which steps this package ships as
138+
functions and which are actions on a store it does not own, and what a
139+
crypto-shred does and does not achieve.
112140

113141
## License
114142

changelog.d/enc-nsi.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
### Added
2+
3+
- A getting-started guide (`guides/getting-started.md`): a single-key vault and
4+
a per-tenant vault, stood up from nothing. It states where key material is
5+
allowed to come from (the `init/1` callback, never `use` options and never a
6+
config file), when to configure the unsigned `0x0478` suite and when to keep
7+
the signing default, and why `:max_age` is required with no default - it is
8+
the answer to how long a crypto-shred takes to take effect on a running node.
9+
- The guide requires **two root secrets from day one, holding the same bytes**:
10+
a pinned reference root that is never rotated, and a wrapping root that
11+
procedure P1 rotates. A deployment that provisions both at install never has
12+
to perform P1's copy-the-reference-root step, which is the most
13+
destructive-looking no-op in the design - generating a fresh value there
14+
instead of copying changes every tenant reference in the deployment.
15+
- A rotation runbook (`guides/rotation-runbook.md`): the four operator
16+
procedures - root rotation, tenant key rotation, tenant shred, version retire
17+
- each with its preconditions, steps, independent verification and rollback,
18+
plus both blast radius tables. Every step is labelled with whether it is a
19+
function this package ships or an action on a store it does not own, and
20+
cache drainage is a step inside each destructive procedure rather than a
21+
follow-up.
22+
- The runbook carries the two-vocabulary mapping table across `encryptor` and
23+
`encryptor_ecto`, because the two packages name the three key levels
24+
differently and an operator reading one runbook against the other's names can
25+
run a level 2 rotation believing it is a level 1 rotation.
26+
- The runbook states plainly what a crypto-shred does not destroy: **a shred
27+
destroys plaintext, not attribution**. The tenant pseudonym in every message
28+
header is permanent, and the holder of the reference subkey can re-identify
29+
it by guess-and-confirm forever, in every retained backup. Deleting the
30+
tenant's ciphertext rows is compliance-mandatory wherever tenant attribution
31+
is itself personal data, and the shred claim must never be stated as full
32+
erasure.
33+
- Both guides are ExDoc extras, and every code block in them is executed by
34+
`Encryptor.GuidesTest` against modules transcribed from the printed text.
35+
36+
### Changed
37+
38+
- `README.md` reports the package as built rather than as a scaffold, links
39+
both guides, and gives the installation form as a SHA-pinned git dependency.
40+
The reserved `encryptor 0.1.0` on Hex is a name reservation holding no
41+
implementation and must not be depended on.

0 commit comments

Comments
 (0)