import assert from 'node:assert/strict'; import { ConvexStore } from '../src/lib/server/store'; import { hashSecret } from '../src/lib/server/security'; import { parseRestoreMarkerPhase, validateRestoreMarkerTarget, validateRestoreMarkerWrite, } from '../src/lib/server/restore-marker'; const marker = process.env.RESTORE_MARKER; const phase = parseRestoreMarkerPhase(process.env.RESTORE_MARKER_PHASE); const target = validateRestoreMarkerTarget(process.env.CONVEX_SELF_HOSTED_URL); validateRestoreMarkerWrite({ phase, allowWrite: process.env.SMOKE_ALLOW_WRITE, confirmation: process.env.RESTORE_MARKER_CONFIRMATION, }); const characterId = Number(process.env.RESTORE_MARKER_CHARACTER_ID ?? '998000001'); if (!marker || !/^[A-Za-z0-9._-]{8,100}$/.test(marker)) throw new Error('RESTORE_MARKER must be a synthetic 8–100 character identifier'); if (!Number.isSafeInteger(characterId) || characterId < 90_000_000) throw new Error('RESTORE_MARKER_CHARACTER_ID must be a synthetic safe integer'); const store = new ConvexStore(target.toString(), process.env.CONVEX_BRIDGE_SECRET!); const sessionHash = hashSecret(`restore-marker-session:${marker}`); const ownerHash = hashSecret(`restore-marker-owner:${marker}`); if (phase === 'write') { const now = Date.now(); const user = await store.completeLogin({ characterId, name: `Restore marker ${marker}`, ownerHash, scopes: ['esi-assets.read_assets.v1'], encryptedTokens: `restore-marker-placeholder:${marker}`, tokenExpiresAt: now + 60_000, sessionHash, sessionExpiresAt: now + 60 * 60_000, }); console.log(`Restore marker written: character=${characterId}, user=${user.userId}`); } else if (phase === 'verify') { const session = await store.session(sessionHash); assert(session, 'restore marker session is missing'); const characters = await store.characters(session.userId); assert(characters.some((character) => character.id === characterId && character.name === `Restore marker ${marker}`), 'restore marker character is missing or changed'); console.log(`Restore marker verified: character=${characterId}, user=${session.userId}`); } else if (phase === 'expect-invalidated') { assert.equal(await store.session(sessionHash), null, 'restore marker session remains usable; invalidation is incomplete'); console.log(`Restore marker invalidation verified: character=${characterId}`); } else { throw new Error('RESTORE_MARKER_PHASE must be write, verify, or expect-invalidated'); }