From 63fe704ef16afd79873d4bb0eda2bdf2b1ea36b7 Mon Sep 17 00:00:00 2001 From: jwinterm Date: Thu, 13 Aug 2026 10:37:13 -0400 Subject: [PATCH] chore(openapi): regenerate for the auth rotation-proof doc changes utoipa derives the /auth/extension operation description and the rotation_signature / seed_fingerprint property docs from the doc comments, which changed when the rotation proof became instance- and target-bound. CI has an openapi-drift job that diffs a fresh gen_openapi against the committed spec, so this keeps that gate green. --- openapi.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openapi.json b/openapi.json index 238d069..dd63aab 100644 --- a/openapi.json +++ b/openapi.json @@ -85,7 +85,7 @@ "auth" ], "summary": "Register a new extension wallet or authenticate an existing one.", - "description": "The BTC pubkey hash is the unique identity. A signed timestamp proves control\nof the BTC private key (defeats registration with a stolen public key). When\nthe PoW gate applies and the wallet is new, a valid `altcha_solution` is\nrequired; a returning user (a known `pubkey_hash`) bypasses PoW.\n\n## Derivation rotation is authenticated (account-takeover defense)\n\nA known `seed_fingerprint` at a NEW `pubkey_hash` (the wallet changed its\nderivation scheme) may re-point the existing user row — but ONLY when the\nrequest also carries a `rotation_signature` that verifies against the BTC key\nalready on file for that user (proving control of the seed-derived key, not\nmerely knowledge of the fingerprint, which `check_restore` discloses and is\nnot secret). A bare fingerprint match WITHOUT a valid rotation proof is\ntreated as a brand-new identity: a fresh user row is created on the new\n`pubkey_hash` and the matched victim row is never modified. The rotation path\nis gated by PoW exactly like any other new-pubkey registration.", + "description": "The BTC pubkey hash is the unique identity. A signed timestamp proves control\nof the BTC private key (defeats registration with a stolen public key). When\nthe PoW gate applies and the wallet is new, a valid `altcha_solution` is\nrequired; a returning user (a known `pubkey_hash`) bypasses PoW.\n\n## Derivation rotation is authenticated (account-takeover defense)\n\nA known `seed_fingerprint` at a NEW `pubkey_hash` (the wallet changed its\nderivation scheme) may re-point the existing user row — but ONLY when the\nrequest also carries a `rotation_signature` that verifies against the BTC key\nalready on file for that user (proving control of the seed-derived key, not\nmerely knowledge of the fingerprint, which `check_restore` discloses and is\nnot secret). That proof signs a dedicated message, NOT the login message: see\n[`rotation_message`], which binds a rotation-specific prefix, the new\n`pubkey_hash`, the timestamp and this instance's canonical public API URL, so\na captured login signature is worthless here and a proof minted for one\ninstance does not verify on another. A bare fingerprint match WITHOUT a valid\nrotation proof is treated as a brand-new identity: a fresh user row is created\non the new `pubkey_hash` and the matched victim row is never modified. The\nrotation path is gated by PoW exactly like any other new-pubkey registration.\n\n## Adopting a `pubkey_hash` onto a keyless row\n\nA row minted by [`nostr_register`] carries no `pubkey_hash`, so that wallet's\nfirst call here matches nothing by pubkey. When the fingerprint matches such a\nrow AND the BTC key on file for it is exactly the key submitted (whose control\nthis request already proved), it is the same wallet: the submitted\n`pubkey_hash` is adopted onto that row (`is_new=false`) instead of minting a\nsecond identity that would strand the handle, tips and premium state. If the\nrow already has a `pubkey_hash`, or the BTC keys differ, nothing is adopted.", "operationId": "extension_register", "requestBody": { "content": { @@ -3263,14 +3263,14 @@ "string", "null" ], - "description": "Derivation-rotation proof: BIP-137 base64 signature of the SAME\n`smirk-auth-{signed_timestamp}` message under the BTC key ALREADY ON FILE\nfor the user identified by `seed_fingerprint`. Required to re-point an\nexisting user row; without it (or if it does not verify against the stored\nkey) a fingerprint match is treated as a brand-new identity and the\nexisting row is never touched. See [`extension_register`]." + "description": "Derivation-rotation proof: BIP-137 base64 signature under the BTC key\nALREADY ON FILE for the user identified by `seed_fingerprint`, over the\nDEDICATED rotation message\n`smirk-rotate-v1|{public_api_url}|{pubkey_hash}|{signed_timestamp}`, where\n`public_api_url` is this instance's canonical API base with any trailing\n`/` removed and `pubkey_hash` is `hex(SHA256(submitted btc public_key))`.\nIt is deliberately NOT the login message: a captured login signature must\nbe useless as a rotation proof, and a proof minted for one instance must\nnot verify on another. Required to re-point an existing user row; without\nit (or if it does not verify against the stored key) a fingerprint match is\ntreated as a brand-new identity and the existing row is never touched. See\n[`extension_register`]." }, "seed_fingerprint": { "type": [ "string", "null" ], - "description": "Seed fingerprint `hex(SHA256(SHA256(seed))[..])`. Used for restore and to\nLOCATE a candidate user row for the derivation-rotation path. By itself it\nis NOT authority: a rotation also requires `rotation_signature` below." + "description": "Seed fingerprint `hex(SHA256(SHA256(seed))[..])`. Used for restore and to\nLOCATE a candidate user row for the derivation-rotation path. By itself it\nis NOT authority: re-pointing an existing row additionally requires either\n`rotation_signature` below or that the row's on-file BTC key is exactly the\none submitted in `keys` (whose control this request already proves)." }, "signature": { "type": "string",