import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { DatabaseSync } from "node:sqlite"; import test from "node:test"; import { AUTHENTICATE_ACTIVE_DEVICE_SQL, DEACTIVATE_OWNED_HOST_SQL, FREE_BETA_ACCESS_BOUNDARY, REVOKE_ACTIVE_DEVICE_CREDENTIALS_SQL, } from "../db/access-boundary.ts"; import { CLAIM_HOST_SQL } from "../db/pairing.ts"; import { REQUIRED_PUBLIC_BETA_P0_KEYS } from "../db/launch-gates.ts"; function createClaimCapacityDatabase() { const db = new DatabaseSync(":memory:"); db.exec(` CREATE TABLE beta_programs ( id TEXT PRIMARY KEY, state TEXT NOT NULL, capacity_slots INTEGER, starts_at TEXT NOT NULL, ends_at TEXT, created_at TEXT NOT NULL ); CREATE TABLE entitlement_grants ( account_id TEXT NOT NULL, state TEXT NOT NULL, capacity_slots INTEGER, starts_at TEXT NOT NULL, ends_at TEXT, revoked_at TEXT ); CREATE TABLE launch_gates ( key TEXT PRIMARY KEY, priority TEXT NOT NULL, status TEXT NOT NULL, owner TEXT, notes TEXT NOT NULL, evidence_url TEXT ); CREATE TABLE pairing_requests ( id TEXT PRIMARY KEY, account_id TEXT NOT NULL, requested_name TEXT NOT NULL, os TEXT NOT NULL, code_hash TEXT NOT NULL, status TEXT NOT NULL, expires_at TEXT NOT NULL, locked_at TEXT, failed_attempts INTEGER NOT NULL DEFAULT 0 ); CREATE TABLE hosts ( id TEXT PRIMARY KEY, account_id TEXT NOT NULL, name TEXT NOT NULL, os TEXT NOT NULL, lifecycle TEXT NOT NULL, slot_state TEXT NOT NULL, connection_state TEXT NOT NULL, daemon_version TEXT, ed25519_public TEXT, x25519_public TEXT, identity_fingerprint TEXT UNIQUE, claim_request_id TEXT, claimed_at TEXT, created_at TEXT NOT NULL, deactivated_at TEXT ); `); const gate = db.prepare( `INSERT INTO launch_gates (key, priority, status, owner, notes, evidence_url) VALUES (?, 'P0', 'passed', 'test', 'verified', 'https://evidence.example.test/p0')`, ); for (const key of REQUIRED_PUBLIC_BETA_P0_KEYS) gate.run(key); return db; } function claimHost(db, digit, accountId, now) { const pairingId = `pair_${digit.repeat(32)}`; db.prepare( `INSERT INTO pairing_requests (id, account_id, requested_name, os, code_hash, status, expires_at) VALUES (?, ?, ?, 'linux', ?, 'waiting', '2026-08-12T13:00:00.000Z')`, ).run(pairingId, accountId, `Host ${digit}`, `hash-${digit}`); return Number(db.prepare(CLAIM_HOST_SQL).run( `host_${digit.repeat(32)}`, `ed-${digit}`, `x-${digit}`, `fingerprint-${digit}`, now, now, pairingId, `hash-${digit}`, now, "linux", now, now, now, now, null, ).changes); } test("documents the free-beta expiry operation boundary", () => { assert.deepEqual( FREE_BETA_ACCESS_BOUNDARY.map(({ operation, requiresCurrentEntitlement }) => [operation, requiresCurrentEntitlement]), [ ["create_pairing", true], ["claim_pairing", true], ["cancel_pairing", false], ["connect_device", false], ["revoke_host", false], ], ); }); test("keeps an existing active device usable after entitlement expiry until explicit revocation", () => { const db = new DatabaseSync(":memory:"); db.exec(` CREATE TABLE hosts ( id TEXT PRIMARY KEY, account_id TEXT NOT NULL, lifecycle TEXT NOT NULL, slot_state TEXT NOT NULL, connection_state TEXT NOT NULL, deactivated_at TEXT ); CREATE TABLE device_credentials ( id TEXT PRIMARY KEY, host_id TEXT NOT NULL, token_hash TEXT NOT NULL, status TEXT NOT NULL, expires_at TEXT, last_used_at TEXT, revoked_at TEXT ); CREATE TABLE entitlement_grants ( id TEXT PRIMARY KEY, account_id TEXT NOT NULL, state TEXT NOT NULL, ends_at TEXT, revoked_at TEXT ); INSERT INTO hosts VALUES ('host_a', 'account_a', 'active', 'active', 'online', NULL); INSERT INTO device_credentials VALUES ('credential_a', 'host_a', 'token-hash', 'active', NULL, NULL, NULL); INSERT INTO entitlement_grants VALUES ('grant_expired', 'account_a', 'active', '2026-08-11T00:00:00.000Z', NULL); `); const now = "2026-08-12T12:00:00.000Z"; assert.equal( Number(db.prepare(AUTHENTICATE_ACTIVE_DEVICE_SQL).run(now, "host_a", "token-hash").changes), 1, ); assert.equal(db.prepare("SELECT last_used_at FROM device_credentials WHERE id = 'credential_a'").get().last_used_at, now); assert.equal(Number(db.prepare(REVOKE_ACTIVE_DEVICE_CREDENTIALS_SQL).run(now, "host_a").changes), 1); assert.equal(Number(db.prepare(DEACTIVATE_OWNED_HOST_SQL).run(now, "host_a", "account_a").changes), 1); assert.equal( Number(db.prepare(AUTHENTICATE_ACTIVE_DEVICE_SQL).run(now, "host_a", "token-hash").changes), 0, ); db.close(); }); test("rechecks current per-account capacity atomically when a daemon claims a waiting pairing", () => { const db = createClaimCapacityDatabase(); const now = "2026-08-12T12:00:00.000Z"; db.prepare( `INSERT INTO beta_programs (id, state, capacity_slots, starts_at, ends_at, created_at) VALUES ('beta', 'active', 2, ?, NULL, ?)`, ).run(now, now); assert.equal(claimHost(db, "1", "account_public", now), 1); db.prepare("UPDATE beta_programs SET capacity_slots = 1 WHERE id = 'beta'").run(); assert.equal(claimHost(db, "2", "account_public", now), 0); assert.equal( db.prepare( "SELECT COUNT(*) AS count FROM hosts WHERE account_id = 'account_public' AND lifecycle = 'active'", ).get().count, 1, ); db.prepare( `INSERT INTO entitlement_grants (account_id, state, capacity_slots, starts_at, ends_at, revoked_at) VALUES ('account_public', 'active', 1, ?, NULL, NULL)`, ).run(now); assert.equal(claimHost(db, "3", "account_public", now), 1); assert.equal(claimHost(db, "4", "account_public", now), 0); assert.equal( db.prepare( "SELECT COUNT(*) AS count FROM hosts WHERE account_id = 'account_public' AND lifecycle = 'active'", ).get().count, 2, ); db.close(); }); test("keeps entitlement checks on new access while security exits stay independent", async () => { const [pairingSql, repository, relayControl, stateModel, contract] = await Promise.all([ readFile(new URL("../db/pairing.ts", import.meta.url), "utf8"), readFile(new URL("../db/repository.ts", import.meta.url), "utf8"), readFile(new URL("../db/relay-control-plane.ts", import.meta.url), "utf8"), readFile(new URL("../docs/state-model.md", import.meta.url), "utf8"), readFile(new URL("../docs/commercial-contract.md", import.meta.url), "utf8"), ]); assert.match(pairingSql, /CURRENT_PAIRING_ACCESS/); assert.match(pairingSql, /HOST_CLAIM_CAPACITY/); assert.match(pairingSql, /PUBLIC_BETA_GATE_READY_SQL/); assert.match(relayControl, /authorizeDeviceForRelay/); assert.match(repository, /REVOKE_ACTIVE_DEVICE_CREDENTIALS_SQL/); assert.match(repository, /DEACTIVATE_OWNED_HOST_SQL/); assert.match(stateModel, /主机撤销.*撤销所有设备凭证.*释放席位/); assert.match(stateModel, /第 N\+1 台返回 `device_capacity_exceeded`/); assert.match(contract, /设备离线不释放席位/); assert.match(contract, /明确撤销才释放/); });