| … | … | @@ -149,6 +149,13 @@ export class StateBaseV3 { |
| 149 | 149 | this._selfHead = null // our current signed head rev — announced over presence so a BEHIND co-owner is |
| 150 | 150 | this._presenceSenders = new Set() // excluded from the election (anti-freeze); re-announced on head change |
| 151 | 151 | this._getMembers = typeof opts.getMembers === 'function' ? opts.getMembers : null |
| 152 | // RESYNC heal (force-non-creator): open as a NON-creator even when we're the lowest-key member, so a |
| 153 | // fresh-corestore re-join gets a FRESH (primaryKey-derived) local writer instead of re-opening the |
| 154 | // deterministic _gsKeyPair genesis writer (which a fresh store cannot shed and autobase will not |
| 155 | // linearize when backfilled — see _open + hyper-proto-peer resync). Mirrors keet: a device that lost |
| 156 | // its store re-joins as a NEW random writer via the doorbell (keet-core pairing/keys.js), never the |
| 157 | // old writer. Set on a resync boot only (device-node.js passes forceNonCreator: !!resyncStore). |
| 158 | this._forceNonCreator = opts.forceNonCreator === true |
| 152 | 159 | // Injectable crypto for membership-gated admission (keet attestation primitives). |
| 153 | 160 | // attest: sign localKey‖base.key as our keet identity; verifyAttest: IdentityKey.verify. |
| 154 | 161 | this._attest = typeof opts.attest === 'function' ? opts.attest : null |
| … | … | @@ -345,9 +352,12 @@ export class StateBaseV3 { |
| 345 | 352 | |
| 346 | 353 | async _open () { |
| 347 | 354 | if (!this._detBaseKey) throw new Error('StateBaseV3 requires roomSeed (deterministic key)') |
| 348 | | const amCreator = (!this._getMembers || !this._selfKey) ? true : await this._amCreator() |
| 349 | | console.log('[state-base-v3] room=%s %s base=%s', this._roomKeyHex.slice(0, 12), |
| 350 | | amCreator ? 'creator' : 'member', this._detBaseKey.toString('hex').slice(0, 12)) |
| 355 | // forceNonCreator (resync heal): never elect as creator → open with keyPair=null → a FRESH local |
| 356 | // writer; the deterministic genesis (_gsKeyPair) becomes a REMOTE writer that replicates + linearizes |
| 357 | // normally (the proven non-creator path), instead of an un-sheddable, un-linearizable local writer. |
| 358 | const amCreator = this._forceNonCreator ? false : ((!this._getMembers || !this._selfKey) ? true : await this._amCreator()) |
| 359 | console.log('[state-base-v3] room=%s %s%s base=%s', this._roomKeyHex.slice(0, 12), |
| 360 | amCreator ? 'creator' : 'member', this._forceNonCreator ? ' (resync: forced non-creator)' : '', this._detBaseKey.toString('hex').slice(0, 12)) |
| 351 | 361 | await this._openBase(this._detBaseKey, amCreator ? this._gsKeyPair : null) |
| 352 | 362 | } |
| 353 | 363 | |