| … | … | @@ -26,9 +26,16 @@ |
| 26 | 26 | // head, touching nothing. `POST /:did` is a PERMANENT, IRREVERSIBLE append to the global PLC |
| 27 | 27 | // op-log — there is no delete and no undo. |
| 28 | 28 | // |
| 29 | | // ORDERING: the new key is placed FIRST. Lower index = higher authority in a dispute (did-plc |
| 30 | | // §4: a recovery fork must be signed by a key with a LOWER index than the one it overrides). The |
| 31 | | // existing key is preserved, so current capability is never reduced — only added to. |
| 29 | // ORDERING: the new key is APPENDED, never prepended. Lower index = higher authority (did-plc §4: |
| 30 | // a recovery fork must be signed by a key with a STRICTLY LOWER index than the one it overrides). |
| 31 | // |
| 32 | // It is tempting to rank a fresh offline key first "because it is the safest one". That is |
| 33 | // backwards. A key at [0] is supreme: nothing can fork against it, so a photograph of that paper |
| 34 | // ends the identity with no recourse — precisely the unrecoverable shape keet has and did:plc |
| 35 | // exists to avoid. Keeping the incumbent root at [0] preserves its power to fork back if the |
| 36 | // backup is ever stolen, while the backup at [1] still fixes the single-key LOSS problem. |
| 37 | // |
| 38 | // The existing key is always preserved, so capability is only ever added to, never reduced. |
| 32 | 39 | // |
| 33 | 40 | // ⚠ Do not register a key you have not recorded. An unbacked-up rotation key is the exact |
| 34 | 41 | // failure this tool exists to prevent, and registering one merely moves the single point. |
| … | … | @@ -148,9 +155,10 @@ async function cmdAdd () { |
| 148 | 155 | const signer = usable[0] |
| 149 | 156 | console.log(`\nsigning with: [${signer.i}] ${signer.s.label}`) |
| 150 | 157 | |
| 151 | | // New key FIRST — highest authority. Everything else carried forward unchanged: a PLC op |
| 152 | | // replaces the whole document state, it is not a patch. |
| 153 | | const rotationDidKeys = [addKey, ...current] |
| 158 | // New key APPENDED — the incumbent root keeps index 0 and therefore keeps fork authority over |
| 159 | // the backup. Everything else carried forward unchanged: a PLC op replaces the whole document |
| 160 | // state, it is not a patch. |
| 161 | const rotationDidKeys = [...current, addKey] |
| 154 | 162 | const unsigned = buildUpdateOp({ |
| 155 | 163 | prevSignedOp: head, |
| 156 | 164 | rotationDidKeys, |
| … | … | @@ -164,7 +172,7 @@ async function cmdAdd () { |
| 164 | 172 | const chk = checkUpdateOp(signedOp, head) |
| 165 | 173 | console.log(`\nlocal validation: ${chk.ok ? 'PASS' : 'FAIL — ' + chk.error}`) |
| 166 | 174 | console.log('\nresulting rotationKeys:') |
| 167 | | rotationDidKeys.forEach((k, i) => console.log(` [${i}] ${k}${k === addKey ? ' <-- NEW (highest authority)' : ''}`)) |
| 175 | rotationDidKeys.forEach((k, i) => console.log(` [${i}] ${k}${k === addKey ? ' <-- NEW backup (lower authority than [0], by design)' : ''}`)) |
| 168 | 176 | console.log('\nop to be submitted:') |
| 169 | 177 | console.log(JSON.stringify(signedOp, null, 2)) |
| 170 | 178 | |