The written contract and the shared vectors for Flamenet Messenger 0.32. Both apps were built against it, and their release branches pin this branch's last commit, d07ed14.
SPEC.md: greeting cards (§6.31), events and answers (§6.32), games in a chat (§6.33), hello links (§6.34), taking a story down (§6.35) and editing a story's caption (§6.15), §18.1 for what 0.32 changes, push-token registration (§8.11, which shipped code already cited), and the Today file (§8.12) with its six refusal reasons. §9's tables and the test counts match what the suites report.
Vectors: content-kinds-v1.json (24 written, 132 read), games-v1.json (rules and perft counts for all four games), hello-link-v1.json (37 links, 18 scans), today-v1.json (signed with the development key, which is not secret) and its generator, and backup-payload-v1.json extended with cards, events and games.
conformance.mjs checks the new vectors and the spec's own examples against them. relay-today.mjs checks a relay's /today.json, and skips until a relay answers the route.
test/interop/build.sh builds the Swift driver from the 0.32 iOS tree (it needs the card, event and game files and the FlamenetGames package).
How it was tested
Every job in this repo's CI, run locally from a fresh clone at d07ed14: secret sweep clean (71 files); conformance 123 passed; ratchet 35; client 167; vault 26, all with 0 failed; check-spec-counts 2 counts match (relay.mjs and interop.mjs skipped, as in CI); doc references 125 sections resolve; 62 exports documented; both entry points resolve.
Against the 0.32 relay (release/0-32) on 127.0.0.1: relay.mjs 272 of 272 with the Swift driver built, the count SPEC.md now states, and relay-today.mjs 20 of 20. From a clean clone at d07ed14 with no driver, as the relay's CI runs it: 265 passed, 0 failed, 2 skipped.
Both apps read all 132 content-kind envelopes as the vectors say and write all 24 written ones byte for byte; both pass the hello-link, Today and backup payload vectors; the two app engines interoperate 77 of 77 through interop-swift-kotlin.mjs with the new build script.
Order
Push and merge this first. The iOS, Android and relay 0.32 branches pin d07ed14 in .e2e-ref, and their pipelines check it out from gitlab.com.
Not run
interop.mjs (Swift against JS) and interop-kotlin.mjs (Kotlin against JS) were not run in the 0.32 test pass. CONTRIBUTING asks for all three before a release.
For the reviewer
The relay's spec and engine pages are generated from SPEC.md and README.md here. The relay's 0.32 branch carries pages regenerated from d07ed14, so they go public only when the relay is deployed.
The development Today key in the vectors is for tests only. The production key has not been made.
<h2 id="what-this-adds">What this adds</h2> <p>The written contract and the shared vectors for Flamenet Messenger 0.32. Both apps were built against it, and their release branches pin this branch's last commit, d07ed14.</p> <ul> <li>SPEC.md: greeting cards (§6.31), events and answers (§6.32), games in a chat (§6.33), hello links (§6.34), taking a story down (§6.35) and editing a story's caption (§6.15), §18.1 for what 0.32 changes, push-token registration (§8.11, which shipped code already cited), and the Today file (§8.12) with its six refusal reasons. §9's tables and the test counts match what the suites report.</li> <li>Vectors: <code>content-kinds-v1.json</code> (24 written, 132 read), <code>games-v1.json</code> (rules and perft counts for all four games), <code>hello-link-v1.json</code> (37 links, 18 scans), <code>today-v1.json</code> (signed with the development key, which is not secret) and its generator, and <code>backup-payload-v1.json</code> extended with cards, events and games.</li> <li><code>conformance.mjs</code> checks the new vectors and the spec's own examples against them. <code>relay-today.mjs</code> checks a relay's <code>/today.json</code>, and skips until a relay answers the route.</li> <li><code>test/interop/build.sh</code> builds the Swift driver from the 0.32 iOS tree (it needs the card, event and game files and the FlamenetGames package).</li> </ul> <h2 id="how-it-was-tested">How it was tested</h2> <ul> <li>Every job in this repo's CI, run locally from a fresh clone at d07ed14: secret sweep clean (71 files); conformance 123 passed; ratchet 35; client 167; vault 26, all with 0 failed; check-spec-counts 2 counts match (relay.mjs and interop.mjs skipped, as in CI); doc references 125 sections resolve; 62 exports documented; both entry points resolve.</li> <li>Against the 0.32 relay (release/0-32) on 127.0.0.1: <code>relay.mjs</code> 272 of 272 with the Swift driver built, the count SPEC.md now states, and <code>relay-today.mjs</code> 20 of 20. From a clean clone at d07ed14 with no driver, as the relay's CI runs it: 265 passed, 0 failed, 2 skipped.</li> <li>Both apps read all 132 content-kind envelopes as the vectors say and write all 24 written ones byte for byte; both pass the hello-link, Today and backup payload vectors; the two app engines interoperate 77 of 77 through <code>interop-swift-kotlin.mjs</code> with the new build script.</li> </ul> <h2 id="order">Order</h2> <p>Push and merge this first. The iOS, Android and relay 0.32 branches pin d07ed14 in <code>.e2e-ref</code>, and their pipelines check it out from gitlab.com.</p> <h2 id="not-run">Not run</h2> <ul> <li><code>interop.mjs</code> (Swift against JS) and <code>interop-kotlin.mjs</code> (Kotlin against JS) were not run in the 0.32 test pass. CONTRIBUTING asks for all three before a release.</li> </ul> <h2 id="for-the-reviewer">For the reviewer</h2> <ul> <li>The relay's spec and engine pages are generated from SPEC.md and README.md here. The relay's 0.32 branch carries pages regenerated from d07ed14, so they go public only when the relay is deployed.</li> <li>The development Today key in the vectors is for tests only. The production key has not been made.</li> </ul> <p>Generated with <a href="https://claude.com/claude-code">Claude Code</a></p>
Merged into main as part of 4b4042f (merge commit 0af0173, branch spec/unify-0-32). The head commit d07ed14 is in main history, so this PR is closed as merged rather than merged again.
Merged into main as part of 4b4042f (merge commit 0af0173, branch spec/unify-0-32). The head commit d07ed14 is in main history, so this PR is closed as merged rather than merged again.
A note on the other branch this repo was carrying. chore/read-like-a-library (43cee3f, 2026-09-08) unbolded bold spans of six words or more across SPEC.md, SECURITY.md, SELF-HOSTING.md and AUDIT-SCOPE.md. It no longer merges: SPEC.md and AUDIT-SCOPE.md both conflict after five weeks of spec work.
Re-applying the rule mechanically to main was tried and discarded. A six-word count cannot tell three different things apart, and all three are in the first eight hunks it produced:
a bolded normative clause, **MUST select the private key by the spk_idcarried in theprekey envelope**, where the emphasis is on the requirement;
a defined term being introduced, the **web engine** ... from the **web client**;
a field label that opens a definition, **`re`, what a message is about.**
Flattening those in a normative document costs more than the bold does. 98 long spans remain in the five documents and they are better judged one at a time, by a reader, than by a word count.
The branch is deleted; 43cee3f stays reachable as a loose object until gc.
A note on the other branch this repo was carrying. `chore/read-like-a-library` (43cee3f, 2026-09-08) unbolded bold spans of six words or more across SPEC.md, SECURITY.md, SELF-HOSTING.md and AUDIT-SCOPE.md. It no longer merges: SPEC.md and AUDIT-SCOPE.md both conflict after five weeks of spec work.
Re-applying the rule mechanically to main was tried and discarded. A six-word count cannot tell three different things apart, and all three are in the first eight hunks it produced:
- a bolded normative clause, `**MUST select the private key by the `spk_id` carried in the `prekey` envelope**`, where the emphasis is on the requirement;
- a defined term being introduced, `the **web engine** ... from the **web client**`;
- a field label that opens a definition, ``**`re`, what a message is about.**``
Flattening those in a normative document costs more than the bold does. 98 long spans remain in the five documents and they are better judged one at a time, by a reader, than by a word count.
The branch is deleted; 43cee3f stays reachable as a loose object until gc.
Pull request closed
This pull request cannot be reopened because the branch was deleted.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What this adds
The written contract and the shared vectors for Flamenet Messenger 0.32. Both apps were built against it, and their release branches pin this branch's last commit,
d07ed14.content-kinds-v1.json(24 written, 132 read),games-v1.json(rules and perft counts for all four games),hello-link-v1.json(37 links, 18 scans),today-v1.json(signed with the development key, which is not secret) and its generator, andbackup-payload-v1.jsonextended with cards, events and games.conformance.mjschecks the new vectors and the spec's own examples against them.relay-today.mjschecks a relay's/today.json, and skips until a relay answers the route.test/interop/build.shbuilds the Swift driver from the 0.32 iOS tree (it needs the card, event and game files and the FlamenetGames package).How it was tested
d07ed14: secret sweep clean (71 files); conformance 123 passed; ratchet 35; client 167; vault 26, all with 0 failed; check-spec-counts 2 counts match (relay.mjs and interop.mjs skipped, as in CI); doc references 125 sections resolve; 62 exports documented; both entry points resolve.relay.mjs272 of 272 with the Swift driver built, the count SPEC.md now states, andrelay-today.mjs20 of 20. From a clean clone atd07ed14with no driver, as the relay's CI runs it: 265 passed, 0 failed, 2 skipped.interop-swift-kotlin.mjswith the new build script.Order
Push and merge this first. The iOS, Android and relay 0.32 branches pin
d07ed14in.e2e-ref, and their pipelines check it out from gitlab.com.Not run
interop.mjs(Swift against JS) andinterop-kotlin.mjs(Kotlin against JS) were not run in the 0.32 test pass. CONTRIBUTING asks for all three before a release.For the reviewer
d07ed14, so they go public only when the relay is deployed.Generated with Claude Code
assigned to @paulhitt
Merged into main as part of
4b4042f(merge commit0af0173, branch spec/unify-0-32). The head commitd07ed14is in main history, so this PR is closed as merged rather than merged again.A note on the other branch this repo was carrying.
chore/read-like-a-library(43cee3f, 2026-09-08) unbolded bold spans of six words or more across SPEC.md, SECURITY.md, SELF-HOSTING.md and AUDIT-SCOPE.md. It no longer merges: SPEC.md and AUDIT-SCOPE.md both conflict after five weeks of spec work.Re-applying the rule mechanically to main was tried and discarded. A six-word count cannot tell three different things apart, and all three are in the first eight hunks it produced:
**MUST select the private key by thespk_idcarried in theprekeyenvelope**, where the emphasis is on the requirement;the **web engine** ... from the **web client**;**`re`, what a message is about.**Flattening those in a normative document costs more than the bold does. 98 long spans remain in the five documents and they are better judged one at a time, by a reader, than by a word count.
The branch is deleted;
43cee3fstays reachable as a loose object until gc.Pull request closed