| … | … | @@ -1623,6 +1623,42 @@ export class Sidecar { |
| 1623 | 1623 | return await this._nameRegistry.resolve(params.name) |
| 1624 | 1624 | }) |
| 1625 | 1625 | |
| 1626 | // Repair a claim written before org #142, whose identityRoot holds this |
| 1627 | // device's key instead of the root. Only the anchoring device can do it, |
| 1628 | // and only to its own chain's root — the registry enforces both; the |
| 1629 | // checks here exist to give a real error instead of an op that apply |
| 1630 | // silently drops. |
| 1631 | svc.handle('reanchor-name', async (ctx, params) => { |
| 1632 | if (!params || !params.name) throw new Error('reanchor-name requires { name }') |
| 1633 | if (!this._nameRegistry.writable) { |
| 1634 | throw new Error('name registry is not writable on this sidecar (join via invite first)') |
| 1635 | } |
| 1636 | const existing = await this._nameRegistry.resolve(params.name) |
| 1637 | if (!existing) throw new Error('name not claimed: ' + params.name) |
| 1638 | |
| 1639 | const signer = this._nameSigner() |
| 1640 | if (typeof signer === 'string') { |
| 1641 | throw new Error('this identity has no attestation chain, so it cannot prove which root owns the name') |
| 1642 | } |
| 1643 | if (existing.publisher.identityRoot === signer.identityRoot) { |
| 1644 | return { ok: true, alreadyAnchored: true, entry: existing } |
| 1645 | } |
| 1646 | if (existing.publisher.identityRoot !== signer.devicePubkey) { |
| 1647 | throw new Error( |
| 1648 | 'name "' + params.name + '" is anchored to ' + |
| 1649 | String(existing.publisher.identityRoot).slice(0, 12) + '… — this device is ' + |
| 1650 | String(signer.devicePubkey).slice(0, 12) + '…; only the anchoring key can re-anchor' |
| 1651 | ) |
| 1652 | } |
| 1653 | |
| 1654 | await this._nameRegistry.reanchor(params.name, signer) |
| 1655 | const entry = await this._nameRegistry.resolve(params.name) |
| 1656 | if (entry.publisher.identityRoot !== signer.identityRoot) { |
| 1657 | throw new Error('re-anchor did not apply for "' + params.name + '" (op refused)') |
| 1658 | } |
| 1659 | return { ok: true, entry } |
| 1660 | }) |
| 1661 | |
| 1626 | 1662 | svc.handle('release-name', async (ctx, params) => { |
| 1627 | 1663 | if (!params || !params.name) throw new Error('release-name requires { name }') |
| 1628 | 1664 | await this._nameRegistry.release(params.name, this._nameSigner()) |