Initial commit
This commit is contained in:
commit
8c709fb52f
771 files changed
+222983
No files matched your search
@@ -0,0 +1,127 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
createRecoveryAttempt,
|
||||
createRecoveryKit,
|
||||
parseRecoveryKit,
|
||||
serializeRecoveryKit,
|
||||
} from '../lib/seat-recovery';
|
||||
|
||||
const playerId = '93c66e7c-2d3b-4845-aedf-5d1f06cf3371';
|
||||
const fixture = () => ({
|
||||
format: 'dune-seat-recovery',
|
||||
version: 1,
|
||||
roomCode: 'ABCD2345',
|
||||
playerId,
|
||||
recoverySecret: 'a1'.repeat(32),
|
||||
});
|
||||
|
||||
void test('generated recovery kit has a 256-bit lowercase hexadecimal secret and round-trips through copy text', () => {
|
||||
const first = createRecoveryKit('ABCD2345', playerId);
|
||||
const second = createRecoveryKit('ABCD2345', playerId);
|
||||
assert.match(first.recoverySecret, /^[0-9a-f]{64}$/);
|
||||
assert.notEqual(first.recoverySecret, second.recoverySecret);
|
||||
assert.deepEqual(parseRecoveryKit(serializeRecoveryKit(first)), first);
|
||||
assert.equal(Object.isFrozen(first), true);
|
||||
assert.deepEqual(Object.keys(first).sort(), [
|
||||
'format',
|
||||
'playerId',
|
||||
'recoverySecret',
|
||||
'roomCode',
|
||||
'version',
|
||||
]);
|
||||
});
|
||||
|
||||
void test('pretty and single-line pasted kits identify exactly the same private seat', () => {
|
||||
const kit = fixture();
|
||||
assert.deepEqual(
|
||||
parseRecoveryKit(JSON.stringify(kit)),
|
||||
parseRecoveryKit(` ${JSON.stringify(kit, null, 2)}\n`),
|
||||
);
|
||||
});
|
||||
|
||||
void test('malformed, truncated, oversized and unsupported kits are rejected without echoing their secrets', () => {
|
||||
const bad = [
|
||||
'',
|
||||
'{',
|
||||
'[]',
|
||||
'null',
|
||||
JSON.stringify('not a kit'),
|
||||
JSON.stringify({ ...fixture(), format: 'unrelated' }),
|
||||
JSON.stringify({ ...fixture(), version: 2 }),
|
||||
JSON.stringify({
|
||||
...fixture(),
|
||||
recoverySecret: 'private-secret-not-to-echo',
|
||||
}),
|
||||
JSON.stringify({ ...fixture(), newSessionToken: 'b2'.repeat(32) }),
|
||||
'x'.repeat(4097),
|
||||
];
|
||||
for (const text of bad)
|
||||
assert.throws(
|
||||
() => parseRecoveryKit(text),
|
||||
(error: unknown) =>
|
||||
error instanceof Error &&
|
||||
!error.message.includes('private-secret-not-to-echo'),
|
||||
);
|
||||
});
|
||||
|
||||
void test('kit validation forbids URLs, noncanonical identifiers and malformed keys', () => {
|
||||
for (const roomCode of [
|
||||
'../rooms',
|
||||
'abcd2345',
|
||||
'ABCD2340',
|
||||
'ABCD23456',
|
||||
'https://example.test',
|
||||
])
|
||||
assert.throws(() =>
|
||||
parseRecoveryKit(JSON.stringify({ ...fixture(), roomCode })),
|
||||
);
|
||||
for (const id of [
|
||||
'',
|
||||
'player-one',
|
||||
`${playerId}?secret=x`,
|
||||
playerId.toUpperCase(),
|
||||
])
|
||||
assert.throws(() =>
|
||||
parseRecoveryKit(JSON.stringify({ ...fixture(), playerId: id })),
|
||||
);
|
||||
for (const recoverySecret of [
|
||||
'a'.repeat(63),
|
||||
'a'.repeat(65),
|
||||
'A'.repeat(64),
|
||||
'z'.repeat(64),
|
||||
])
|
||||
assert.throws(() =>
|
||||
parseRecoveryKit(JSON.stringify({ ...fixture(), recoverySecret })),
|
||||
);
|
||||
assert.throws(() => createRecoveryKit('../rooms', playerId));
|
||||
});
|
||||
|
||||
void test('an explicit recovery attempt has fresh secure credentials and an immutable exact retry payload', () => {
|
||||
const kit = parseRecoveryKit(JSON.stringify(fixture()));
|
||||
const attempt = createRecoveryAttempt(kit);
|
||||
const sentBody = JSON.stringify(attempt);
|
||||
assert.equal(attempt.type, 'recoverSeat');
|
||||
assert.equal(attempt.playerId, kit.playerId);
|
||||
assert.equal(attempt.recoverySecret, kit.recoverySecret);
|
||||
assert.match(
|
||||
attempt.operationId,
|
||||
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/,
|
||||
);
|
||||
assert.match(attempt.newSessionToken, /^[0-9a-f]{64}$/);
|
||||
assert.notEqual(attempt.newSessionToken, kit.recoverySecret);
|
||||
assert.equal(Object.isFrozen(attempt), true);
|
||||
assert.throws(
|
||||
() => Object.assign(attempt, { operationId: 'changed' }),
|
||||
TypeError,
|
||||
);
|
||||
assert.equal(
|
||||
JSON.stringify(attempt),
|
||||
sentBody,
|
||||
'retrying the retained attempt produces an identical request',
|
||||
);
|
||||
const newAttempt = createRecoveryAttempt(kit);
|
||||
assert.notEqual(newAttempt.operationId, attempt.operationId);
|
||||
assert.notEqual(newAttempt.newSessionToken, attempt.newSessionToken);
|
||||
assert.equal(newAttempt.recoverySecret, attempt.recoverySecret);
|
||||
});
|
||||
Reference in new issue
Block a user