| … | … | @@ -28,10 +28,9 @@ export const usage = `pgh repo — browse repos served by the daemon |
| 28 | 28 | Admin: grant a peer push authority |
| 29 | 29 | pgh repo local-key <name> Print this daemon's tracker local key |
| 30 | 30 | pgh repo revoke <name> <userId> Revoke a writer |
| 31 | | pgh repo resync <name> [--admit-from <owner-url>] |
| 32 | | Heal a stuck tracker: clean re-join in |
| 33 | | a fresh corestore (+ auto-admit if the |
| 34 | | owner url is given)` |
| 31 | pgh repo resync <name> Heal a stuck tracker: clean re-join in |
| 32 | a fresh corestore + P2P doorbell |
| 33 | auto-admission (no url)` |
| 35 | 34 | |
| 36 | 35 | export async function run (client, args) { |
| 37 | 36 | const sub = args[0] |
| … | … | @@ -190,26 +189,14 @@ export async function run (client, args) { |
| 190 | 189 | // (repo-resync RPC → forceResync). Recovers a standalone peer whose tracker |
| 191 | 190 | // can't reconcile a group manifest migration (crash-loops or silently freezes) |
| 192 | 191 | // — a fresh namespace does NOT heal it (same primaryKey-derived local writer), |
| 193 | | // only a fresh corestore does. The re-join is READ-ONLY until admitted; with |
| 194 | | // --admit-from <owner-url> the peer auto-requests admission of its new local |
| 195 | | // key from the tracker owner, who auto-approves iff this peer already holds |
| 196 | | // write authority (repo-request-writer). One command = heal + participate. |
| 192 | // only a fresh corestore does. The daemon AUTO-ADMITS the re-joined key via the |
| 193 | // P2P doorbell (an optimistic request-writer op vouched by this peer's old |
| 194 | // writer key; the owner admits on apply) — no url, no HTTP, fully over |
| 195 | // hyperswarm. One command = heal + participate. |
| 197 | 196 | if (sub === 'resync') { |
| 198 | 197 | const name = args[1] |
| 199 | | if (!name) throw new Error('usage: pgh repo resync <name> [--admit-from <owner-url>]') |
| 200 | | const res = await client.call('repo-resync', { repo: name }) |
| 201 | | if (res && res.error) return res |
| 202 | | const ai = args.indexOf('--admit-from') |
| 203 | | const owner = ai !== -1 ? args[ai + 1] : null |
| 204 | | if (!owner || !res || !res.localKey) return res |
| 205 | | const pc = await PghPeerClient.connect({ url: owner }) |
| 206 | | let admission |
| 207 | | try { |
| 208 | | admission = await pc.call('repo-request-writer', { name, writerKey: res.localKey }) |
| 209 | | } finally { |
| 210 | | await pc.close() |
| 211 | | } |
| 212 | | return { ...res, admission } |
| 198 | if (!name) throw new Error('usage: pgh repo resync <name>') |
| 199 | return client.call('repo-resync', { repo: name }) |
| 213 | 200 | } |
| 214 | 201 | |
| 215 | 202 | if (sub === 'revoke') { |