| … | … | @@ -0,0 +1,37 @@ |
| 1 | // bridge-claim.js — the exact bytes a peer signs to claim a name on a bridge. |
| 2 | // |
| 3 | // ⛔ ONE DEFINITION, BECAUSE A MISMATCH IS SILENT. The claimant builds these bytes and the bridge |
| 4 | // rebuilds them; if the two ever disagree by a byte, `readAttested` returns null and the bridge |
| 5 | // reports "proof does not attest that identity" — which reads as a hostile or broken caller, not as |
| 6 | // a version skew. There is no error that says "we disagree about the format". So the format lives in |
| 7 | // the one package both sides already depend on, next to the verifier that consumes it, rather than |
| 8 | // being written twice and eventually written wrong. |
| 9 | // |
| 10 | // ⛔ VERSIONED AND PREFIXED. The prefix keeps a claim proof from ever verifying as a release proof — |
| 11 | // releasing BURNS a name permanently, and a proof that could be repurposed between the two would let |
| 12 | // a captured claim destroy what it was meant to create. The version means what is bound can change |
| 13 | // later without both shapes being silently accepted at once. |
| 14 | // |
| 15 | // ⚠ Colons are safe separators here and that is a property of the inputs, not an accident: a bridge |
| 16 | // username cannot contain one (it must be a usable path segment), and nonces and feed keys are hex. |
| 17 | |
| 18 | import b4a from 'b4a' |
| 19 | |
| 20 | export const CLAIM = 'favela-bridge:v1:claim' |
| 21 | export const RELEASE = 'favela-bridge:v1:release' |
| 22 | |
| 23 | /** |
| 24 | * What a claimant signs. The REQUEST is inside it, not just the nonce: a proof covering only the |
| 25 | * challenge could be captured and replayed to claim a DIFFERENT name under the signer's root — |
| 26 | * consent proven, control proven, and the wrong name registered. |
| 27 | */ |
| 28 | export function claimBytes ({ nonce, username, feedKey }) { |
| 29 | return b4a.from([CLAIM, nonce, username, feedKey || ''].join(':'), 'utf8') |
| 30 | } |
| 31 | |
| 32 | /** What a releaser signs. No feed: giving up a name says nothing about where a feed lives. */ |
| 33 | export function releaseBytes ({ nonce, username }) { |
| 34 | return b4a.from([RELEASE, nonce, username].join(':'), 'utf8') |
| 35 | } |
| 36 | |
| 37 | export default { claimBytes, releaseBytes, CLAIM, RELEASE } |