Build verified checkpoint containers for TrueNAS

This commit is contained in:
Quintine committed 2026-09-21 17:48:25 +10:00
1 parent c5508b727a
commit 64e8299aeb
27 files changed
+536 -16

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
/** UUID v4 for browser operations, including private LAN HTTP origins. */
export function randomId(): string {
// Unlike randomUUID(), getRandomValues is available outside secure contexts.
const bytes = globalThis.crypto.getRandomValues(new Uint8Array(16));
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0'));
return [
hex.slice(0, 4).join(''),
hex.slice(4, 6).join(''),
hex.slice(6, 8).join(''),
hex.slice(8, 10).join(''),
hex.slice(10).join(''),
].join('-');
}
+10
View File
@@ -0,0 +1,10 @@
/** The administrator configures the external origin; forwarded headers are untrusted. */
export function requestOrigin(request: Request, configured?: string): string {
if (!configured) return new URL(request.url).origin;
const url = new URL(configured);
if (
!['http:', 'https:'].includes(url.protocol) ||
url.username || url.password || url.search || url.hash || url.pathname !== '/'
) throw new Error('DUNE_PUBLIC_ORIGIN must be an HTTP(S) origin without a path.');
return url.origin;
}
+2 -1
View File
@@ -1,3 +1,4 @@
import { randomId } from './random-id';
import { EXPANSIONS, FACTIONS } from '../game/catalog';
import { requestMayHaveCompleted } from './client-request';
@@ -108,7 +109,7 @@ export function createRoomEntry(
roomCode?: string,
): RoomEntryAttempt {
const entry = {
operationId: globalThis.crypto.randomUUID(),
operationId: randomId(),
sessionToken: Array.from(
globalThis.crypto.getRandomValues(new Uint8Array(32)),
(byte) => byte.toString(16).padStart(2, '0'),
+3 -2
View File
@@ -1,3 +1,4 @@
import { randomId } from './random-id';
import type { GameView } from '../game/engine';
export const HANDOVER_CLAIM_STORAGE_KEY = 'dune.pending-seat-handover.v1';
@@ -98,7 +99,7 @@ export function createHandoverKit(
version: 1,
roomCode,
playerId,
offerId: crypto.randomUUID(),
offerId: randomId(),
handoverSecret: secret(),
}),
);
@@ -111,7 +112,7 @@ export function createHandoverClaim(kit: SeatHandoverKit): SavedHandoverClaim {
playerId: kit.playerId,
offerId: kit.offerId,
handoverSecret: kit.handoverSecret,
operationId: crypto.randomUUID(),
operationId: randomId(),
newSessionToken: secret(),
}),
});
+2 -1
View File
@@ -1,3 +1,4 @@
import { randomId } from './random-id';
export type SeatRecoveryKit = Readonly<{
format: 'dune-seat-recovery';
version: 1;
@@ -106,7 +107,7 @@ export function createRecoveryAttempt(
type: 'recoverSeat',
playerId: kit.playerId,
recoverySecret: kit.recoverySecret,
operationId: globalThis.crypto.randomUUID(),
operationId: randomId(),
newSessionToken: secret256(),
});
}