docs(spec): concretize identity model — signer abstraction + binding
Three connected updates triggered by aiolabs/lnbits#9 (in-progress hardening of user Nostr keypair storage with NIP-46 bunker support): §7.2 expanded — per-user signing is no longer abstract "future work". Defines the 4-implementation signer abstraction (BotSigner / LocalSigner / RemoteBunkerSigner / ClientSideOnlySigner) matching lnbits#9's design. MUST design plugins with this abstraction even when v1 only ships BotSigner — Phase 2c plugs in user signers without refactor. §7.3 new — external-identity binding. Any system that can answer "for chat handle X, what signer should I use?" works. LNbits is the reference identity provider but not the only valid one. Binding MUST be opt-in, verifiable, revocable. §11 + §12 updated — open question on bunker UX folds into the new sections; reference identity provider added to §12 with pointer to lnbits#9. Spec stays runtime-agnostic — LNbits is one valid provider, not mandatory. Communities without an existing Nostr identity stack stay on v1 BotSigner indefinitely. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8f83d8df5e
commit
3d29beecba
1 changed files with 84 additions and 10 deletions
|
|
@ -443,16 +443,70 @@ enables classifier tuning.
|
||||||
- Relay operators MAY auth-gate (require NIP-42) to prevent
|
- Relay operators MAY auth-gate (require NIP-42) to prevent
|
||||||
community-scoped writes from non-members. Out of band coordination.
|
community-scoped writes from non-members. Out of band coordination.
|
||||||
|
|
||||||
### 7.2 Future (bunker / remote signers)
|
### 7.2 Per-user signing (v2; design-for-it now)
|
||||||
|
|
||||||
Future spec versions will support per-user signing via NIP-46
|
Once external-identity binding is in place (see §7.3), the bot SHOULD
|
||||||
(remote signing) so that events are attributable to individual users'
|
sign events as the originating user, not as itself. The chat-room →
|
||||||
Nostr identities, not the bot. The chat-room → community mapping
|
community mapping stays the same; only the signer changes.
|
||||||
stays the same; only the signer changes.
|
|
||||||
|
|
||||||
Implementations SHOULD design their signing layer with this
|
Implementations MUST design their signing layer as an abstraction so
|
||||||
forward-compatibility in mind (i.e. don't hardcode "the bot is
|
per-user signing plugs in without refactor. Recommended interface
|
||||||
always the signer" deep in the data model).
|
(adopted from the LNbits reference implementation, see §12):
|
||||||
|
|
||||||
|
| Signer | Holds | Where it signs |
|
||||||
|
|---|---|---|
|
||||||
|
| `BotSigner` | One server-side keypair shared across all events | Server-side, in-process. The v1 fallback. |
|
||||||
|
| `LocalSigner` | A user's encrypted-at-rest keypair on the bot's host | Server-side, in-process, but per-user |
|
||||||
|
| `RemoteBunkerSigner` | A NIP-46 remote-signer connection (per-user) | RPC over relay (kind 24133) to the user's bunker |
|
||||||
|
| `ClientSideOnlySigner` | Nothing — sentinel meaning "user signs in their own client" | Not the bot; events for this user come in via subscription from elsewhere |
|
||||||
|
|
||||||
|
For each captured message the bot:
|
||||||
|
|
||||||
|
1. Looks up the originating chat handle (e.g. MXID) in its binding
|
||||||
|
table (§7.3).
|
||||||
|
2. If bound and the signer is server-callable (`LocalSigner` /
|
||||||
|
`RemoteBunkerSigner`), signs as the user. Drop the `author` tag
|
||||||
|
(the pubkey is the attribution).
|
||||||
|
3. If unbound — or bound to `ClientSideOnlySigner` for a verb the
|
||||||
|
user must sign themselves — falls back to `BotSigner` with the
|
||||||
|
`author` tag (the v1 §7.1 behavior).
|
||||||
|
|
||||||
|
This degrades gracefully: a community can run v1 indefinitely with
|
||||||
|
just `BotSigner`; users opt into sovereignty individually as they
|
||||||
|
bind their identity.
|
||||||
|
|
||||||
|
**NIP-46 is the recommended remote signer protocol.** It's what the
|
||||||
|
Nostr ecosystem is converging on for client-without-nsec flows, and
|
||||||
|
it works without browser extensions on iOS — important for any
|
||||||
|
Matrix client that runs on mobile.
|
||||||
|
|
||||||
|
### 7.3 External-identity binding (v2)
|
||||||
|
|
||||||
|
For per-user signing to mean anything, the bot needs a verified
|
||||||
|
mapping from `chat handle → external identity → signer`. The binding
|
||||||
|
mechanism is implementation-defined but MUST be:
|
||||||
|
|
||||||
|
- **Opt-in** per user. No silent association.
|
||||||
|
- **Verifiable** — the binding proves the user controls both identities
|
||||||
|
(e.g. magic-link round-trip, signature challenge, NIP-39 external
|
||||||
|
identity proof).
|
||||||
|
- **Revocable** — user can unbind. Bot drops back to fallback.
|
||||||
|
|
||||||
|
The spec does not mandate a specific identity provider. Any system
|
||||||
|
that can answer "for chat handle X, what signer should I use?" works:
|
||||||
|
|
||||||
|
- A **Lightning/Nostr account system** (LNbits, Alby Hub, etc.) — the
|
||||||
|
reference implementation, since these already hold user pubkeys
|
||||||
|
and have an auth surface that can mediate the binding flow.
|
||||||
|
- A **standalone web app** with its own auth and a `bind chat handle`
|
||||||
|
flow.
|
||||||
|
- An **on-Nostr profile claim** — user publishes a kind 0 / 30311 /
|
||||||
|
similar with a chat-handle attestation; bot reads relay and
|
||||||
|
cryptographically verifies the claim.
|
||||||
|
- A **NIP-39 external-identity proof** in the user's profile.
|
||||||
|
|
||||||
|
Adopters without any of the above can stay on v1 (`BotSigner` only)
|
||||||
|
— per-user signing is enhancement, not requirement.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -698,8 +752,13 @@ Not yet decided in this draft:
|
||||||
- **Migration / weekly review.** Bullet-journal-style migration of
|
- **Migration / weekly review.** Bullet-journal-style migration of
|
||||||
stale open items into a new period. Needs a verb (`!migrate`?)
|
stale open items into a new period. Needs a verb (`!migrate`?)
|
||||||
and a state transition spec.
|
and a state transition spec.
|
||||||
- **External signer story.** NIP-46 bunker integration concrete
|
- **External signer story.** NIP-46 bunker integration is sketched
|
||||||
shape.
|
in §7.2 / §7.3; the LNbits reference identity provider is being
|
||||||
|
hardened in [aiolabs/lnbits#9](https://git.atitlan.io/aiolabs/lnbits/issues/9).
|
||||||
|
Pending: ergonomics of the chat-side binding flow (DM the bot? web
|
||||||
|
callback? both?), and how to handle `ClientSideOnlySigner` users
|
||||||
|
whose events can't be bot-published at all (the bot subscribes and
|
||||||
|
mirrors instead).
|
||||||
|
|
||||||
Contributions welcome on any of these.
|
Contributions welcome on any of these.
|
||||||
|
|
||||||
|
|
@ -732,6 +791,21 @@ scoping in §5. A ZeroClaw-based implementation would carry the
|
||||||
`["client", "maubot-tracker", "..."]`; renderers ignore the difference
|
`["client", "maubot-tracker", "..."]`; renderers ignore the difference
|
||||||
since they filter by community `a`-tag.
|
since they filter by community `a`-tag.
|
||||||
|
|
||||||
|
### Reference identity provider
|
||||||
|
|
||||||
|
The aiolabs reference implementation uses [LNbits](https://lnbits.com/)
|
||||||
|
(specifically the [aiolabs fork](https://git.atitlan.io/aiolabs/lnbits))
|
||||||
|
as its identity provider — each user already has an LNbits account with
|
||||||
|
a Nostr `pubkey` field; the in-progress [issue #9 hardening](https://git.atitlan.io/aiolabs/lnbits/issues/9)
|
||||||
|
introduces a `NostrSigner` abstraction (`LocalSigner` / `RemoteBunkerSigner`
|
||||||
|
/ `ClientSideOnlySigner`) that matches the per-user-signing model in §7.2
|
||||||
|
exactly. The bot stores `(chat_handle → lnbits_user_id)` and resolves the
|
||||||
|
signer per-user at publish time.
|
||||||
|
|
||||||
|
Other communities can substitute their own identity provider (any system
|
||||||
|
that maps chat handles to Nostr signers per §7.3) — LNbits is one such
|
||||||
|
provider, not the only one.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue