Files
amethyst/quartz/plans/README.md
T
Claude 1d66e4e2f6 feat(marmot): implement account identity proof v2, the current profile's leaf binding
Stage 2 of the Marmot resync. A member leaf carries two unrelated keys — the
MLS BasicCredential identity, which is the member's Nostr account key, and the
MLS leaf signature key MLS generates per device — and MLS never checks that the
account agreed to the leaf key next to it. Without a proof, anyone able to
author a leaf can claim any account's identity.

This is also what makes us classifiable at all. MDK decides Legacy vs Current
purely on whether a group requires extension 0xf2f1 or component 0x8009; we
required neither, so profile classification errored out before any component
check ran.

Adds the common authorization-proof envelope (foundation/authorization-proofs.md):
104 fixed-width bytes of signer pubkey, big-endian uint64 timestamp and BIP-340
signature, with event-id reconstruction. The created_at bounds are load-bearing
twice over — the lower bound rejects zero, and the upper bound (2^53-1) catches
a uint64 whose top bit is set, which reads back negative as a Kotlin Long.

Deliberately absent: any comparison of created_at against a local clock. A proof
authorizes a long-lived key binding, not a one-time operation, and a wall-clock
rule would let skew make two members reach different verdicts on the same Commit.

The component itself signs a kind-450 template through NostrSigner rather than
raw BIP-340, which is the whole point of the indirection: a NIP-46 bunker or
NIP-55 app can produce a proof without exposing arbitrary signing. create()
therefore re-verifies everything the signer returned — pubkey, timestamp, kind,
tags, content, recomputed id, signature — since an external signer is free to
substitute a stale or altered event.

Also adds the app-component id registry, and the RFC 9420 signature-scheme
mapping to MlsCiphersuite (declared outside the companion: an enum's entries
initialize before its companion object, so entry constructor arguments cannot
read companion properties).

Tested two ways. Sixteen tests pin the spec's published fixture — canonical
event serialization, event id, signature, the 104-byte layout — and check that
every signed input actually binds, including a ciphersuite change that leaves
the signature scheme untouched. Six more validate the proofs in
marmot-current-profile.json: those come from a separate implementation, for
randomly generated keys, which is the interop property a fixed vector cannot
establish. Full quartz marmot suite: 395 tests, 0 failures.

Nothing reads or writes these on a real leaf yet — the carrier is the
app_data_dictionary, which is Stage 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kCuA6tc4JQzHPCDd39GHq
2026-09-08 15:04:59 +00:00

3.0 KiB

quartz plans

Audited 2026-09-08. 12 plans: 7 shipped (archived), 0 in-progress, 4 queued, 1 closed (negative result).

Queued

Plan Summary
2026-05-08-local-headers-explorer.md Headers-only Bitcoin P2P client to verify NIP-03 OTS attestations without a trusted block explorer.
2026-06-12-giftwrap-deletion-requests.md Let a recipient-authored kind-5 delete/block a gift wrap (kind 1059) addressed to them.
2026-07-03-incremental-negentropy-storage.md Always-current (created_at, id) index so cold NEG-OPENs stop paying a full scan + seal (~340 ms at 50k vs strfry's ~21 ms).
2026-07-04-small-req-floor.md Small-REQ dispatch floor: decomposed, inline fast path tried and reverted (no wire-level win); floor is transport-side.
2026-08-13-gpu-pow-mining.md GPU NIP-13 mining declined (ARMv8 has SHA-256 in silicon, mobile GPUs do not). Midstate is ~3x on JVM targets; Android hinges on Conscrypt per-digest JNI cost, still unmeasured. created_at refresh while mining shipped.
2026-09-08-marmot-spec-resync.md Marmot moved off the MIP-era spec (2026-07-02): group state split into app_data_dictionary components, account identity proof v2, and a convergence engine. Current MDK rejects our groups outright. Gap analysis + 8-stage plan; Stages 0 (interop reference repointed at mdk, current-profile vector generator) and 2 (account-identity-proof v2) done.

Archived (shipped)

Plan Summary
archive/2026-06-03-fix-nip46-bunker-double-resume-plan.md Fix NIP-46 bunker double-resume crash and retry id-reuse races via Channel-per-request + fresh id per attempt.
archive/2026-06-04-auth-scope-vs-policy.md Move relay-server authenticated-identity state from the policy into the engine-owned connection scope.
archive/2026-06-09-clink.md Implement CLINK (Offers/Debits/Manage) Lightning-over-Nostr pointers, events, and client/server in Quartz.
archive/2026-06-11-runstr-interop.md RUNSTR kind-1301 workout events and supporting fitness kinds in Quartz plus Amethyst fitness screens.
archive/2026-06-19-napplet-nip5a-resolver.md Platform-agnostic NIP-5A static-site resolver verifying content-addressed Blossom blobs against signed manifests.
archive/2026-06-20-powr-interop.md Parse and render the POWR/NIP-101e kind-1301 strength-workout dialect alongside the existing RUNSTR dialect.
archive/2026-06-28-git-smart-http-browser.md Git smart-HTTP v2 client to browse NIP-34 repo file trees and render source from the clone URL.