iOS 0.32.0: cards, games, events, Today, the small-web directory and hello links #315

Closed
paulhitt wants to merge 0 commits from release/0-32-0 into main
paulhitt commented 2026-10-05 09:46:13 +00:00 (Migrated from gitlab.com)

What 0.32 adds

Six features, all inside ordinary sealed messages or one public file. The relay sees nothing new about anyone. The wire contract is SPEC §6.31 to §6.35 and §8.12 in flamenet-e2e (docs/spec-0-32).

  1. Stickers and cards in FlameNet's art. A second sticker pack, "FlameNet", with 24 drawn stickers (SVG sources and the render script in Art/stickers/). Cards in the nine flamenet.io designs, in 1:1 chats and groups. A card can be sealed until a day: the receiver's app keeps it closed until then, and the composer says this is a courtesy between apps, not a lock.
  2. Games in 1:1 chats: chess, checkers, reversi and tic-tac-toe, with the rules engines in the local package Packages/FlamenetGames (its own tests and the shared games-v1 vectors). Moves are never queued; a failed send takes the move back.
  3. Events with RSVPs. Revisions and cancels come only from the organizer. The card says everyone in the chat sees your answer. "Add to calendar" uses the system sheet and reads nothing from the calendar.
  4. The Today tab: one signed file fetched from the home relay at /today.json, with no credentials, no account or device id and no query string, at most once an hour. Headlines, delayed market prices, weather for cities picked on the phone, the site of the day and the latest blog post. The last good copy is kept and shown offline with "From ".
  5. The small-web directory from flamenet.io, shipped in the app. Search runs on the phone. Sending a site to a chat sends the URL and its title, and nothing is fetched.
  6. Hello links (https://flamenetmessenger.com/hi#<address>) on the address card, in the QR code and in every scanner, and the flamenetmessenger:// URL scheme. Opening one fills in the add screen; nothing is sent until the person confirms.

Stories (owner request): take a story down for everyone (§6.35), edit its caption (§6.15), and the feed, the composer and the viewer always show the whole photo, never cropped.

Also from the review rounds: parental controls hide Today and the directory; sign-out and a lost-device wipe clear the Today file and weather picks; every scanner binds by fnid; a game invitation counts as unread and a move does not; after the test pass, an offline start opens to the chats and connects in the background, and a sealed card on screen opens at its time without leaving the chat.

Bug fixes included:

  • A snoozed chat now holds its notices and the incoming-call banner, as mute does.
  • Edits, reactions, pins, profile pictures and delivery keys sent alone are submitted silent, as §6.15, §6.9, §6.19 and §8.4 require.
  • A queued group message leaves "pending" once it goes.
  • Search in Forward and Send a file can be read again (white text on a pale sheet on iOS 26 and later).
  • Story composer text uses the page's own ink, so the audience line and caption are readable.
  • A DEBUG test launch never reaches production by default: the unit-test host and UI suites resolve to a closed loopback port unless a UI launch names a server. Release builds are unchanged.
  • AFailedRetirementIsRetriedTests no longer races the stub relay.

Version 0.32.0, build 32.

How it was tested

Everything ran on this Mac against relays started on 127.0.0.1. Nothing touched a production host.

  • Unit target at the release tip: 1132 XCTest tests and 572 Swift Testing tests, 0 failures; the two new UI suites (a card opening on screen, readable story composers) passed 5 of 5.
  • CI's ui-tests job, run locally at the tip with no relay given: 90 tests, 19 ran and 71 skipped for want of a live relay, 0 failures (the job's floor is 10).
  • FlamenetGames: 15 of 15 in a release build, including every deep perft count (FLAMENET_GAMES_DEEP=1).
  • Shared vectors from flamenet-e2e, read by the app's own code: content kinds 24 of 24 written byte for byte and 132 of 132 read; hello links 37 of 37 and scans 18 of 18; the Today sequence and If-None-Match cases pass; the extended backup payload set round-trips 3 of 3. Each loader was shown to go red on a changed vector.
  • The app engines against Android's: 77 of 77 (interop-swift-kotlin.mjs).
  • End to end with an Android peer on a local relay: 79 checks passed and 2 failed in the reference run. Both failures (a sealed card on screen not opening at its time, and a cold start with the relay down landing on sign-in) were fixed afterwards and are covered by tests; the end-to-end run itself was not repeated.

CI changes in this branch

.e2e-ref moves to flamenet-e2e d07ed14 (docs/spec-0-32), the commit Tests/Vectors was copied from. The vector gate in unit-tests and the advisory vectors-head also compare content-kinds-v1, today-v1 and hello-link-v1.

Before this can go green

  • Push flamenet-e2e docs/spec-0-32 first. The pinned commit has to exist on gitlab.com before the gate can check it out.
  • parity-scrub clones Android main. Until the Android 0.32 MR is merged it reports 5 HIGH findings (game, gmove, gend, rsvp, unpost: iOS sends kinds Android main does not know) and fails. Against the Android release branch it reports none. Merge Android first, or rerun the job after it lands.
  • vectors-head (advisory) stays red until the spec branch is merged to e2e main, because main does not have the three new files yet.

Not done

  • No App Store upload and no TestFlight build. Store notes and the release step are the owner's.
  • The production Today signing key does not exist yet. TodayKeys.production is empty, so a release build refuses every Today file until the key is made and added here. The development key is compiled into DEBUG builds only.
  • The relay serving /today.json and /hi is not deployed; that needs the owner.
  • Universal links for hello links need an Apple portal change and are later work.

For the reviewer

  • 65 commits, including merges of the feature branches. SPEC.md in flamenet-e2e is the contract the commits follow.
  • New Swift files mean the project must be regenerated with Scripts/generate.sh.
  • Off-the-record threads keep every new piece of state in memory only; the backup and sealed-store field tests cover the new fields.

Generated with Claude Code

<h2 id="what-032-adds">What 0.32 adds</h2> <p>Six features, all inside ordinary sealed messages or one public file. The relay sees nothing new about anyone. The wire contract is SPEC §6.31 to §6.35 and §8.12 in flamenet-e2e (docs/spec-0-32).</p> <ol type="1"> <li>Stickers and cards in FlameNet's art. A second sticker pack, "FlameNet", with 24 drawn stickers (SVG sources and the render script in <code>Art/stickers/</code>). Cards in the nine flamenet.io designs, in 1:1 chats and groups. A card can be sealed until a day: the receiver's app keeps it closed until then, and the composer says this is a courtesy between apps, not a lock.</li> <li>Games in 1:1 chats: chess, checkers, reversi and tic-tac-toe, with the rules engines in the local package <code>Packages/FlamenetGames</code> (its own tests and the shared games-v1 vectors). Moves are never queued; a failed send takes the move back.</li> <li>Events with RSVPs. Revisions and cancels come only from the organizer. The card says everyone in the chat sees your answer. "Add to calendar" uses the system sheet and reads nothing from the calendar.</li> <li>The Today tab: one signed file fetched from the home relay at <code>/today.json</code>, with no credentials, no account or device id and no query string, at most once an hour. Headlines, delayed market prices, weather for cities picked on the phone, the site of the day and the latest blog post. The last good copy is kept and shown offline with "From <date>".</li> <li>The small-web directory from flamenet.io, shipped in the app. Search runs on the phone. Sending a site to a chat sends the URL and its title, and nothing is fetched.</li> <li>Hello links (<code>https://flamenetmessenger.com/hi#&lt;address&gt;</code>) on the address card, in the QR code and in every scanner, and the <code>flamenetmessenger://</code> URL scheme. Opening one fills in the add screen; nothing is sent until the person confirms.</li> </ol> <p>Stories (owner request): take a story down for everyone (§6.35), edit its caption (§6.15), and the feed, the composer and the viewer always show the whole photo, never cropped.</p> <p>Also from the review rounds: parental controls hide Today and the directory; sign-out and a lost-device wipe clear the Today file and weather picks; every scanner binds by fnid; a game invitation counts as unread and a move does not; after the test pass, an offline start opens to the chats and connects in the background, and a sealed card on screen opens at its time without leaving the chat.</p> <p>Bug fixes included:</p> <ul> <li>A snoozed chat now holds its notices and the incoming-call banner, as mute does.</li> <li>Edits, reactions, pins, profile pictures and delivery keys sent alone are submitted silent, as §6.15, §6.9, §6.19 and §8.4 require.</li> <li>A queued group message leaves "pending" once it goes.</li> <li>Search in Forward and Send a file can be read again (white text on a pale sheet on iOS 26 and later).</li> <li>Story composer text uses the page's own ink, so the audience line and caption are readable.</li> <li>A DEBUG test launch never reaches production by default: the unit-test host and UI suites resolve to a closed loopback port unless a UI launch names a server. Release builds are unchanged.</li> <li>AFailedRetirementIsRetriedTests no longer races the stub relay.</li> </ul> <p>Version 0.32.0, build 32.</p> <h2 id="how-it-was-tested">How it was tested</h2> <p>Everything ran on this Mac against relays started on 127.0.0.1. Nothing touched a production host.</p> <ul> <li>Unit target at the release tip: 1132 XCTest tests and 572 Swift Testing tests, 0 failures; the two new UI suites (a card opening on screen, readable story composers) passed 5 of 5.</li> <li>CI's ui-tests job, run locally at the tip with no relay given: 90 tests, 19 ran and 71 skipped for want of a live relay, 0 failures (the job's floor is 10).</li> <li>FlamenetGames: 15 of 15 in a release build, including every deep perft count (FLAMENET_GAMES_DEEP=1).</li> <li>Shared vectors from flamenet-e2e, read by the app's own code: content kinds 24 of 24 written byte for byte and 132 of 132 read; hello links 37 of 37 and scans 18 of 18; the Today sequence and If-None-Match cases pass; the extended backup payload set round-trips 3 of 3. Each loader was shown to go red on a changed vector.</li> <li>The app engines against Android's: 77 of 77 (<code>interop-swift-kotlin.mjs</code>).</li> <li>End to end with an Android peer on a local relay: 79 checks passed and 2 failed in the reference run. Both failures (a sealed card on screen not opening at its time, and a cold start with the relay down landing on sign-in) were fixed afterwards and are covered by tests; the end-to-end run itself was not repeated.</li> </ul> <h2 id="ci-changes-in-this-branch">CI changes in this branch</h2> <p><code>.e2e-ref</code> moves to flamenet-e2e d07ed14 (docs/spec-0-32), the commit <code>Tests/Vectors</code> was copied from. The vector gate in <code>unit-tests</code> and the advisory <code>vectors-head</code> also compare content-kinds-v1, today-v1 and hello-link-v1.</p> <h2 id="before-this-can-go-green">Before this can go green</h2> <ul> <li>Push flamenet-e2e docs/spec-0-32 first. The pinned commit has to exist on gitlab.com before the gate can check it out.</li> <li><code>parity-scrub</code> clones Android main. Until the Android 0.32 MR is merged it reports 5 HIGH findings (game, gmove, gend, rsvp, unpost: iOS sends kinds Android main does not know) and fails. Against the Android release branch it reports none. Merge Android first, or rerun the job after it lands.</li> <li><code>vectors-head</code> (advisory) stays red until the spec branch is merged to e2e main, because main does not have the three new files yet.</li> </ul> <h2 id="not-done">Not done</h2> <ul> <li>No App Store upload and no TestFlight build. Store notes and the release step are the owner's.</li> <li>The production Today signing key does not exist yet. <code>TodayKeys.production</code> is empty, so a release build refuses every Today file until the key is made and added here. The development key is compiled into DEBUG builds only.</li> <li>The relay serving <code>/today.json</code> and <code>/hi</code> is not deployed; that needs the owner.</li> <li>Universal links for hello links need an Apple portal change and are later work.</li> </ul> <h2 id="for-the-reviewer">For the reviewer</h2> <ul> <li>65 commits, including merges of the feature branches. SPEC.md in flamenet-e2e is the contract the commits follow.</li> <li>New Swift files mean the project must be regenerated with <code>Scripts/generate.sh</code>.</li> <li>Off-the-record threads keep every new piece of state in memory only; the backup and sealed-store field tests cover the new fields.</li> </ul> <p>Generated with <a href="https://claude.com/claude-code">Claude Code</a></p>
paulhitt commented 2026-10-05 09:46:13 +00:00 (Migrated from gitlab.com)

assigned to @paulhitt

assigned to @paulhitt

Closed: release/0-32-0 at 4afa7640 is contained whole in merge/ios-0-32-unify, which is the branch that lands 0.32 on main. Nothing here is lost.

🤖 Generated with Claude Code

Closed: `release/0-32-0` at `4afa7640` is contained whole in `merge/ios-0-32-unify`, which is the branch that lands 0.32 on main. Nothing here is lost. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
extant2000git closed this pull request 2026-10-14 18:22:43 +00:00

Pull request closed

Please reopen this pull request to perform a merge.
Sign in to join this conversation.