Newest first. Each entry carries the App Store / TestFlight blurb, the internal detail behind it, and what was deliberately left undone.
You can tip people now. Press and hold a message to send its author a few sats, and see what a message has been tipped on the message itself. Connect a Lightning wallet and tips are paid without leaving Comb, so it can tell you the payment actually went through. You can also give an agent an allowance to tip on your behalf, capped per tip and per day, and stop it at any time.
This is the first build of Comb that can move real money. Please read this before connecting anything.
- Zaps work without a wallet connection: Comb hands an invoice to a Lightning wallet app on your iPhone and never learns whether you paid it.
- If you connect a wallet in Settings, Comb pays invoices in place, with no second confirmation step. Choosing an amount and tapping the button is the whole flow. That is deliberate, and it is also the thing to know before you try it.
- Use a throwaway wallet connection with a small cap (a few hundred sats). Most wallets let you create an app connection with its own budget. Do not connect your main wallet to a TestFlight build.
- Start with 1 sat. The amounts on offer start at 21.
- Agent allowances are untested by any real agent. Nothing in the app can publish a spend request yet, so this path has only ever been exercised by unit tests.
If something takes money and does not say so, that is the most important bug you can report.
Zaps, end to end. The receive half had been stranded on an unmerged branch since before 0.1.0; it is now on main along with everything built on top of it.
CombCore/Zap.swift— receipt verification split intodecodeReceipt(offline, runs in the projector) andverifyReceipt(needs the issuer key, runs at read time). Same shape as edits and deletions: record the claim, judge it where the evidence is.CombStore/Zaps.swift,Schema.swift— azapprojection with a unique index on bolt11 as the replay defence, pluszap_attemptandlnurl_issueras local-only tables. Projection version 7 → 9.Comb/Features/Timeline/Zap*.swift— the sheet, the presenter, the zappers list, and the chips on a message row.
Sender-attested zaps (kind 40004). Standard NIP-57 cannot work on a
membership-gated Buzz relay: an LNURL provider is not a member, so its receipt is
refused and the tally stays empty forever. The payer now publishes the proof
instead. A BOLT-11 invoice commits to a payment hash and the preimage is revealed
only on settlement, so sha256(preimage) == payment_hash is settlement, checkable
by anyone offline with no third party. CombCore/Bolt11.swift decodes exactly two
facts and skips everything else; it is tested against BOLT-11's own published
vectors rather than invoices this repo made.
Nostr Wallet Connect (NIP-47). CombNet/NWCSession.swift is modelled on
PairingSession, not RelaySession: every call on the latter waits for a NIP-42
challenge that a wallet relay never sends, so each would hang for thirty seconds
and throw. NIP-44 only — NIP-47 says a wallet advertising no encryption tag
supports only NIP-04, and NIP-04 is AES-CBC with no authentication, which is not
something to carry spend authorisation over. The credential lives in its own
Keychain service so "forget my wallet" and "forget my identity" cannot delete each
other.
Agent spending allowances (kind 40005). An agent is a pubkey in the roster and
holds no credential: it publishes a request, and the funder's device decides
against a grant the agent cannot read or forge. Two dials, a rolling-window
allowance and a per-tip ceiling, and deliberately no approve-each-spend prompt,
because a stream of approvals is one people learn to wave through. Six safety
rails are unit-tested and the replay guard is mutation-tested. spend_grant and
spend_ledger are local-only and outside the projection tables, so a rebuild
cannot invent permission to spend.
Privacy fix carried in. LNURLClient was using URLSession.shared, which
accepts cookies into the shared store and caches by ETag, so a wallet provider
could have linked one zap to the next across launches and communities. Now an
ephemeral session that keeps nothing, matching what third-party images already
got in a4e81a0.
Version bump: 0.1.2 → 0.2.0, build 11 → 12.
-
make export DEVELOPMENT_TEAM=…and upload via Transporter or Organizer - Export compliance auto-clears (
ITSAppUsesNonExemptEncryption = NO) - Paste the tester notes above into TestFlight "What to Test"
- Run
docs/ZAP-TESTING.mdonce against a real wallet before inviting testers - Tag pushed:
git push origin v0.2.0
- No real money has moved through any of this. Every test is against a fake
wallet.
docs/ZAP-TESTING.mdis the run that would change that and has not been done. - Agent allowances have never been exercised by a real agent. Nothing can publish a kind 40005 yet.
- Kinds 40004 and 40005 are unconfirmed against a real Buzz relay. The fake models no kind allowlist and Comb already ships kind 40003, so the risk is low but it is not measured.
- The deep-link path mostly cannot attest. Sampled against real providers,
neither
opensats@vlt.genordamus@sendsats.lolimplements LUD-21verify, so a zap handed to a wallet app cannot learn its own preimage and stays a pending marker until it expires. Tallies lean on NIP-47 in practice. - A refused agent is told nothing. Publishing a refusal would publish the reader's budget to the room. An encrypted reply to the agent alone is the obvious improvement and is not built.
design/text-roles-and-contrastis still unmerged, holding the typography overhaul and channel create/join/leave. Its zap commits now conflict with main.- Contrast has still never been measured on device, and VoiceOver has still never been run end to end. Both predate this release.