mirror of
https://github.com/block/buzz.git
synced 2026-10-31 14:31:02 +00:00
feat(relay): import owner section workspace
Co-authored-by: Larry <loganj+larry@squareup.com> Signed-off-by: Logan Johnson <loganj@squareup.com>
This commit is contained in:
23
docs/nips/NIP-SW.fixtures.json
Normal file
23
docs/nips/NIP-SW.fixtures.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"version": 1,
|
||||
"kinds": {"import": 9050, "projection": 30623},
|
||||
"limits": {"sections": 100, "assignments": 1000, "encrypted_metadata_bytes": 65535, "key_envelope_bytes": 4096},
|
||||
"owner": "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"import": {
|
||||
"version": 1,
|
||||
"action_id": "dddddddd-dddd-4ddd-8ddd-dddddddddddd",
|
||||
"source_event_id": "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"source_hash": "3333333333333333333333333333333333333333333333333333333333333333",
|
||||
"key_epoch": 1,
|
||||
"owner_key_envelope": "nip44-owner-envelope",
|
||||
"sections": [{"id":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","rank":0,"encrypted_label":"ciphertext-label","encrypted_icon":null}],
|
||||
"assignments": [{"channel_id":"cccccccc-cccc-4ccc-8ccc-cccccccccccc","section_id":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"}]
|
||||
},
|
||||
"projection": {
|
||||
"coordinate": "1111111111111111111111111111111111111111111111111111111111111111:1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"tags": [
|
||||
["d", "1111111111111111111111111111111111111111111111111111111111111111:1111111111111111111111111111111111111111111111111111111111111111"],
|
||||
["p", "1111111111111111111111111111111111111111111111111111111111111111"]
|
||||
]
|
||||
}
|
||||
}
|
||||
52
docs/nips/NIP-SW.md
Normal file
52
docs/nips/NIP-SW.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# NIP-SW: Owner section-workspace import
|
||||
|
||||
## Status
|
||||
|
||||
Stage 1 is an opt-in migration tracer bullet. Set `BUZZ_SECTION_WORKSPACE_IMPORT_ENABLED=true` to accept imports. No client enables it yet. Viewer grants, revocation, moves, and section management are later protocol stages.
|
||||
|
||||
## Kinds and authority
|
||||
|
||||
- `9050`: owner-signed revision-zero import command.
|
||||
- `30623`: relay-signed, reader-specific current projection.
|
||||
|
||||
The relay resolves the community from the request host. It never accepts a community UUID from the command. The command signer is the immutable workspace owner. Import requires `users:write`, is accepted at most once for `(community, owner)`, and references an existing owner-authored kind-30078 event in that community. Exact signed-event replay is idempotent; every different later import conflicts.
|
||||
|
||||
## Import
|
||||
|
||||
Kind 9050 has exactly these tags:
|
||||
|
||||
```json
|
||||
[["p", "<owner-pubkey>"], ["action", "<action-uuid>"]]
|
||||
```
|
||||
|
||||
The `p` value must equal the signer. Content is ordinary strict JSON (the signed Nostr event ID already binds its exact bytes):
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"action_id": "<uuid>",
|
||||
"source_event_id": "<kind-30078-event-id>",
|
||||
"source_hash": "<sha256-lower-hex-of-decrypted-legacy-state>",
|
||||
"key_epoch": 1,
|
||||
"owner_key_envelope": "<nip44-wrapped-workspace-key>",
|
||||
"sections": [{"id":"<uuid>","rank":0,"encrypted_label":"<ciphertext>","encrypted_icon":null}],
|
||||
"assignments": [{"channel_id":"<uuid>","section_id":"<uuid>"}]
|
||||
}
|
||||
```
|
||||
|
||||
The relay rejects unknown fields, unsupported versions, nil or duplicate IDs, non-permutation ranks, duplicate channel assignments, unknown sections, missing/cross-community/deleted channels, a missing/cross-community/wrong-author legacy source, more than 100 sections or 1,000 assignments, metadata over 65,535 bytes, and key envelopes over 4,096 bytes.
|
||||
|
||||
Labels and icons remain client-encrypted. Stage 1 freezes neither a custom JSON canonicalization profile nor metadata encryption details; supported clients must agree on those before cutover.
|
||||
|
||||
## Owner projection
|
||||
|
||||
On the first accepted import, the relay atomically stores the verified command and a relay-signed kind-30623 projection at:
|
||||
|
||||
```text
|
||||
d=<owner-pubkey>:<reader-pubkey>
|
||||
p=<reader-pubkey>
|
||||
```
|
||||
|
||||
There is exactly one `p` tag and it matches the reader component of `d`. The owner projection therefore uses `<owner>:<owner>`. Its content contains version 1, owner pubkey, workspace/layout/assignment revision 1, key epoch 1, the source migration marker, that reader's key envelope, sections, and assignments.
|
||||
|
||||
Kind 30623 is relay-only and parameterized replaceable. Every historical REQ, HTTP query, count, search hydration, known-event-ID lookup, and live fan-out applies result-level `p` authorization. Knowing an event ID is not authorization.
|
||||
Reference in New Issue
Block a user