Skip to content

Commit 99dfe68

Browse files
committed
plan: four slices added: 002 supply chain early, 003 FIPS build leg, 025 encryption at rest, 026 store-and-forward receipts
Changes 7, 8 and 9 of the 2026-09-20 plan, landed as one branch because all three move the same change-log count. 002 (phase 0, S, depends on 000, counted in M9): a CycloneDX SBOM from the gate and on every release, build provenance attested on release artifacts, one README line for the TLS floor. 003 (phase 0, M, depends on 000, counted in M2): a second gate matrix entry on a UBI9 container with OTP 28.5.0.5 built from source with --enable-fips, FIPS mode entered before crypto loads, a smoke that proves it, and the crypto:supports/1 diff committed; it is where 024's FIPS properties run. 025 (phase 2, M, depends on 010 and 024): the Trinity.Keys custody seam with a local adapter first, envelope encryption for blobs nothing indexes, and the measured dm-crypt baseline for everything SQLite indexes. 026 (phase 2, L, depends on 024): receipt/2 gains a queued-then-acknowledged mode with hybrid logical clocks and Merkle merge; blocked on the external plane's answer, routed through the owner. ROADMAP: rows, the M2 and M9 conditions, the graph, a note that 025 and 026 carry no milestone yet, and the change-log entry deriving 40. One correction to the previous change-log entry: it escaped the pipe inside the deriving command, which plan_check rule 5's pattern does not match, so the rule read the older entry's 36 and passed by coincidence. Both entries now use the bare pipe the rule expects and the rule reads 40. plan_check: PASS (191 tracked files). trinity.names: OK. trinity.reuse: OK. Signed-off-by: Ayla Croft <aylacroft@proton.me>
1 parent 8bdddf8 commit 99dfe68

5 files changed

Lines changed: 320 additions & 4 deletions

File tree

‎ROADMAP.md‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,26 @@ A size given as `M or L` is conditional on a decision named in that slice's file
1313
|---|---|---|
1414
| **M0 Stands** | Repo, gate, packaging path proven | 000, 001 approved |
1515
| **M1 Talks** | Streaming chat with any provider, persisted, crash-safe | 010–013 approved |
16-
| **M2 Acts** | Tools with permission gate, one side-effect membrane, local receipts, context compaction | 020–024 approved |
16+
| **M2 Acts** | Tools with permission gate, one side-effect membrane, local receipts, context compaction; the FIPS build leg that proves 024's properties | 003, 020–024 approved |
1717
| **M3 Remembers** | Persona, always-on memory, FTS + semantic recall, project context, and data you can take with you | 030–034 approved |
1818
| **M4 Learns** | Skills system with agent self-management + approval | 040–041 approved |
1919
| **M5a Automates** | Cron tasks and MCP, client and server, with authorization | 050, 059–062 approved |
2020
| **M5b Reaches** | Gateways over PubSub, subagents | 070–072, 080 approved (081 optional, outside the milestone) |
2121
| **M6 Ships** | Observability, native desktop shell, signed releases | 090–101 approved |
2222
| **M7 Sandboxed** | Executable skills in an in-VM sandbox | 110 approved |
23-
| **M9 Donatable** | OSS hygiene audited, supply chain signed, AAIF Sandbox package complete, shared libraries extracted | 120–123 approved (122 filing is an owner action) |
23+
| **M9 Donatable** | OSS hygiene audited, supply chain signed, AAIF Sandbox package complete, shared libraries extracted | 002, 120–123 approved (122 filing is an owner action) |
24+
25+
Slices 025 and 026 carry no milestone: they serve regulated deployments after M2 and are assigned when the
26+
standards register names the rows that ask for them.
2427

2528
## Slices
2629

2730
| ID | Slice | Phase | Size | Depends on | Status |
2831
|---|---|---|---|---|---|
2932
| 000 | Toolchain, repo bootstrap, quality gate | 0 Foundation | L | none | approved |
3033
| 001 | Packaging spike: Burrito + ex_tauri smoke build | 0 Foundation | M | 000 | approved |
34+
| 002 | Supply chain, early: SBOM, build provenance, the TLS floor | 0 Foundation | S | 000 | planned |
35+
| 003 | FIPS build leg in CI, from source | 0 Foundation | M | 000 | planned |
3136
| 010 | Core domain + persistence (Ecto/SQLite, schemas, Repo owner) | 1 Core loop | M | 000 | planned |
3237
| 011 | LLM provider layer (req_llm behind `Trinity.LLM` behaviour) | 1 Core loop | M | 010 | planned |
3338
| 012 | Session process + agent loop (gen_statem, DynamicSupervisor, rehydration) | 1 Core loop | L | 010, 011 | planned |
@@ -37,6 +42,8 @@ A size given as `M or L` is conditional on a decision named in that slice's file
3742
| 022 | Core tools: filesystem, web fetch/search, shell (MuonTrap) | 2 Tools | L | 021 | planned |
3843
| 023 | Context compaction + session lineage | 2 Tools | M | 012 | planned |
3944
| 024 | Effect catalog, authority selection (`TRINITY_AUTHORITY`), local receipts | 2 Tools | L | 021, 022 | planned |
45+
| 025 | Encryption at rest, and the key-custody seam | 2 Tools | M | 010, 024 | planned |
46+
| 026 | Store-and-forward receipts for disconnected operation | 2 Tools | L | 024 | planned |
4047
| 030 | Persona (SOUL) + always-on memory tier | 3 Memory | M | 012 | planned |
4148
| 031 | Session search (SQLite FTS5) | 3 Memory | S | 010 | planned |
4249
| 032 | Embeddings + semantic memory + hybrid retrieval | 3 Memory | L | 031 | planned |
@@ -81,8 +88,12 @@ for planning, not deadlines; the point here is the cut line, not a duration.
8188

8289
```
8390
000 ─┬─ 001 ─────────────────────────────────────────── 100 ── 101
91+
├─ 002 (supply chain, early)
92+
├─ 003 (FIPS build leg; runs 024's FIPS tests)
8493
└─ 010 ─┬─ 011 ─┬─ 090
85-
│ └─ 012 ─┬─ 013 ── 021 ── 022 ── 024 ── 061 ── 062
94+
│ └─ 012 ─┬─ 013 ── 021 ── 022 ── 024 ─┬─ 061 ── 062
95+
│ │ ├─ 025 (also needs 010)
96+
│ │ └─ 026
8697
│ ├─ 020 ─┬─ 040 ── 041 ── 110
8798
│ │ ├─ 059 ── 060 ── 061
8899
│ │ └─ 080 ── (081 optional, also needs 061)
@@ -110,4 +121,5 @@ After 012, multiple branches are independent. If running more than one coding ag
110121
| 2026-09-05 | Authority made an adapter behind a behaviour rather than a mode (ADR-0008, ADR-0010). ADR-0009 opened for the Jido question, decided at the 012 checkpoint. Slice 024 added: effect catalog, `TRINITY_AUTHORITY`, local receipts. Alignment appendices on 012, 020, 021, 022, 023, 030, 032, 040, 041. |
111122
| 2026-09-05 | Review pass before commit 1. Counts in the three entries above were typed, not derived, and none matches the tree; a decreasing count is impossible under insert-never-renumber. Derived this date: `find slices -name SLICE.md | wc -l` → **38**. Milestones are derived from the Milestones table, not from memory. From here, any count in this log names the command that produced it. Entries above are not rewritten. |
112123
| 2026-09-06 | Plan corrections, round 2. **Supersedes the slice count in the entry above:** that entry derived **38** on 2026-09-05, before slices 082, 083 and 084 were withdrawn and slice 034 was added. Re-derived this date, not adjusted by arithmetic: `find slices -name SLICE.md | wc -l` → **36**. The entry above is not rewritten. `scripts/plan_check.sh` now enforces this count, the acceptance-criteria numbering, the Definition-of-Done ranges, ROADMAP/SLICE.md agreement, and the absence of references to paths not in `git ls-files`. |
113-
| 2026-09-20 | The MCP phase replanned under owner decisions of 2026-09-08, recorded in ADR-0007 decisions 5 to 8: beam_mcp 0.8.0 is the server core; 059 measures the capability gap and probes the `:server` seam (S/M); 060 is Trinity's thin driver (L, the M/L condition decided); the OAuth client role moves from 060 to 062; 061 carries a named blocker on the MRTR wrapper; the four `M5 Always-on` headers on 059 to 062 read M5a Automates, as this file has since 2026-09-08. R14 re-scoped, R15 closed. Re-derived this date: `find slices -name SLICE.md \| wc -l` → **36**. |
124+
| 2026-09-20 | The MCP phase replanned under owner decisions of 2026-09-08, recorded in ADR-0007 decisions 5 to 8: beam_mcp 0.8.0 is the server core; 059 measures the capability gap and probes the `:server` seam (S/M); 060 is Trinity's thin driver (L, the M/L condition decided); the OAuth client role moves from 060 to 062; 061 carries a named blocker on the MRTR wrapper; the four `M5 Always-on` headers on 059 to 062 read M5a Automates, as this file has since 2026-09-08. R14 re-scoped, R15 closed. Re-derived this date: `find slices -name SLICE.md | wc -l` → **36**. |
125+
| 2026-09-20 | Four slices added under the accepted 2026-09-20 plan: 002 (supply chain, early: SBOM, provenance, TLS floor; counted in M9), 003 (FIPS build leg from source; counted in M2 because it runs 024's FIPS properties), 025 (encryption at rest and the key-custody seam) and 026 (store-and-forward receipts; blocked on the external plane's answer). Re-derived this date: `find slices -name SLICE.md | wc -l` → **40**. |
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Slice 002: Supply chain, early: SBOM, build provenance, the TLS floor
2+
3+
| Field | Value |
4+
|---|---|
5+
| Phase | 0 Foundation |
6+
| Milestone | M9 Donatable |
7+
| Size | S |
8+
| Depends on | 000 |
9+
| Status | see ROADMAP.md |
10+
11+
Added 2026-09-20. Slice 121 keeps Scorecard, Sigstore signing of release artifacts, SLSA and the registry entry,
12+
and depends on the release pipeline; the three items here need none of that and are cheap enough to carry from
13+
now on.
14+
15+
## Goal
16+
A CycloneDX software bill of materials generated by the gate and attached to every release; build provenance
17+
attested on release artifacts through GitHub's attestation action; one README line stating the TLS floor and
18+
that any MAC in an envelope Trinity mints is Trinity's and an approved one in FIPS mode.
19+
20+
## Why
21+
Vision goal 10. A reviewer of a public tree expects to find what is in the binary and where the binary came
22+
from without asking; a regulated deployment requires both on request. Deferring them to slice 121 means every
23+
release before it ships without them.
24+
25+
## Scope
26+
**In:**
27+
- `sbom` (hex.pm, `mix sbom.cyclonedx`, CycloneDX) as a dev and test dependency; a gate step that generates
28+
`sbom.cdx.json` and fails on a generation error; the file attached to every release by the package workflow.
29+
- `actions/attest-build-provenance`, pinned to a commit SHA with its release in a comment like the other actions,
30+
attesting each artifact the package workflow uploads. The attestation is verified in the same workflow with
31+
`gh attestation verify` and the output kept in the run summary.
32+
- One README line under Running from source: the TLS floor is 1.2, and any MAC over an envelope Trinity mints is
33+
Trinity's own and is an approved algorithm in FIPS mode.
34+
- `VERSIONS.md` row for `sbom`.
35+
**Out:**
36+
- Signing the SBOM or the artifacts with a Trinity-held key; Scorecard; SLSA levels; the registry entry. All
37+
slice 121.
38+
- A cryptography bill of materials. It follows once the minimum elements for one are published.
39+
40+
## Design notes
41+
The SBOM is generated from `mix.lock`, so it is exact for Hex dependencies and blind to the Rust crates of the
42+
desktop shell; the file says so in a top-level property and slice 121 adds the crate half. Provenance is
43+
GitHub's, over the artifact's digest, and proves where the bytes were built, not what they do.
44+
45+
## Deliverables
46+
- `mix.exs` dependency and gate step; `.github/workflows/package.yml` upload and attest steps; `README.md` line;
47+
`lib/trinity/versions.ex` row and regenerated `VERSIONS.md`.
48+
49+
## Acceptance criteria
50+
1. [auto] `mix gate` generates `sbom.cdx.json` and the file validates as CycloneDX (the validator's command and
51+
exit code pasted).
52+
2. [auto] A package run attaches the SBOM to its artifacts and attests each artifact; `gh attestation verify`
53+
exits 0 for each, output in the run summary (run id cited).
54+
3. [auto] The README carries the TLS floor line, and a test pins it so the line cannot vanish silently.
55+
4. [auto] Gate green; coverage line reported.
56+
57+
## Proof required
58+
- For each criterion: the command and its output, or a test name and its result. A sentence is not proof.
59+
60+
## Manual verification queue
61+
None. Every acceptance criterion in this slice is `[auto]` and is proven by a command or a test.
62+
If that changes during the slice, the criterion is retagged and this section is filled at G1.
63+
64+
## Definition of Done
65+
- [ ] `mix gate` green · [ ] AC1–4 proven · [ ] docs/ADR/VERSIONS updated if affected · [ ] ROADMAP status → done · [ ] final commit + tag
66+
67+
## Commit & tag
68+
`feat(s002): complete slice 002 (supply chain, early)` · tag `slice/002`
69+
70+
## Risks / open questions
71+
- The SBOM's blindness to the desktop shell's crates is stated in the file itself; a reader who misses the
72+
property misreads the bill. Slice 121 closes it.

‎slices/003-fips-build-leg/SLICE.md‎

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Slice 003: A FIPS build leg in CI, from source, so FIPS claims are proven rather than asserted
2+
3+
| Field | Value |
4+
|---|---|
5+
| Phase | 0 Foundation |
6+
| Milestone | M2 Acts |
7+
| Size | M |
8+
| Depends on | 000 |
9+
| Status | see ROADMAP.md |
10+
11+
Added 2026-09-20. Counted toward M2 Acts because its reason to exist is slice 024's FIPS property tests, which
12+
cannot run anywhere else: the developer machine's OTP reports `crypto:info_fips()` as `not_supported`, and the
13+
hosted BEAM images the gate uses are not FIPS builds.
14+
15+
## Goal
16+
A second entry in the gate workflow's matrix that runs the whole suite on an OTP 28.5.0.5 built from source with
17+
`--enable-fips` against the validated OpenSSL of a UBI9 container, with FIPS mode entered before the crypto
18+
application loads, and a smoke that proves the mode is on. The default leg stays exactly as it is.
19+
20+
## Why
21+
Slice 024's amendment says FIPS mode selects P-384 and never denies for want of a signer. Until a build runs
22+
in FIPS mode, that is a sentence. This leg is the measurement. It also answers, once, what else in the tree
23+
reaches an algorithm FIPS mode removes.
24+
25+
## Scope
26+
**In:**
27+
- A container image built by its own workflow, rebuilt when `.tool-versions` changes: UBI9, the distribution's
28+
OpenSSL and its FIPS provider, OTP 28.5.0.5 from source with `--enable-fips`, Elixir 1.20.4. Published to the
29+
repository's container registry so the gate leg pulls rather than builds.
30+
- The gate leg: `fips_mode: true` for `:crypto` in the release's `sys.config` equivalent for tests, set before
31+
crypto loads; the smoke `crypto:info_fips() =:= enabled` and the `fips_provider_buildinfo` key present in
32+
`crypto:info/0`; then `mix test` and the rest of the gate as the default leg runs it.
33+
- A committed record of `crypto:supports/1` on the FIPS leg diffed against the default leg, so the removed
34+
algorithms are a list in the tree and not a memory.
35+
- Runner minutes measured over the first ten runs and written into NOTES.md.
36+
**Out:**
37+
- Making FIPS mode the default anywhere; changing the OTP pin; ML-DSA (the UBI9 OpenSSL is a 3.0 line and does
38+
not carry it; that measurement waits for a build against OpenSSL 3.5 or later and is `:unknown` until then).
39+
- A FIPS-mode desktop bundle. Whether Burrito can wrap a `--enable-fips` ERTS is slice 100's question.
40+
41+
## Design notes
42+
Entering or leaving FIPS mode on a running node is unsupported by OTP, so the leg sets the mode in configuration
43+
and never toggles it in a test. A test that needs a removed algorithm on this leg is a finding, not a skip: it is
44+
listed in the committed diff with the slice that owns it.
45+
46+
## Deliverables
47+
- `.github/workflows/fips-image.yml` and the Containerfile; the second matrix entry in `.github/workflows/gate.yml`;
48+
`docs/fips-leg.md` with the `crypto:supports/1` diff and how to reproduce the image; NOTES.md with the minutes.
49+
50+
## Acceptance criteria
51+
1. [auto] On the FIPS leg, `crypto:info_fips()` returns `enabled` and `crypto:info/0` carries
52+
`fips_provider_buildinfo` (log excerpt with the run id).
53+
2. [auto] On the FIPS leg, `crypto:sign/4` with `eddsa` returns `notsup` and with `ecdsa` on `secp384r1` and
54+
`sha384` returns a signature that verifies (test).
55+
3. [auto] The committed `crypto:supports/1` diff between the two legs matches what the leg prints (test).
56+
4. [auto] The whole gate runs on the leg; every red is either fixed or listed by test name with its owning slice
57+
in `docs/fips-leg.md`; there is no skip tag.
58+
5. [auto] Gate green on both legs; coverage line reported.
59+
60+
## Proof required
61+
- For each criterion: the command and its output, or a test name and its result, with the run id. A sentence is
62+
not proof.
63+
64+
## Manual verification queue
65+
None. Every acceptance criterion in this slice is `[auto]` and is proven by a command or a test.
66+
If that changes during the slice, the criterion is retagged and this section is filled at G1.
67+
68+
## Definition of Done
69+
- [ ] `mix gate` green · [ ] AC1–5 proven · [ ] docs/ADR/VERSIONS updated if affected · [ ] ROADMAP status → done · [ ] final commit + tag
70+
71+
## Commit & tag
72+
`feat(s003): complete slice 003 (FIPS build leg)` · tag `slice/003`
73+
74+
## Risks / open questions
75+
- Building OTP from source is slow; the image workflow exists so the gate leg does not pay for it on every push.
76+
If the image cannot be cached in the registry for a reason found at G1, the leg runs on a schedule and on
77+
demand rather than on every push, and the slice says so.
78+
- The validated provider a container ships is the distribution's claim; the slice cites the certificate number
79+
the distribution publishes and does not restate it as Trinity's.

0 commit comments

Comments
 (0)