Files
nekonest-cloud/tests/relay-control-plane.test.mjs

1168 lines
48 KiB
JavaScript

import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import { DatabaseSync } from "node:sqlite";
import test from "node:test";
import {
RELAY_AUTHORIZATION_MAX_TTL_SECONDS,
RELAY_SIGNING_KEY_FOR_SNAPSHOT_SQL,
classifySnapshotPlacement,
canonicalJson,
signRelayAuthorizationSnapshot,
verifyRelayAuthorizationSnapshot,
} from "../db/relay-authorization.ts";
import {
ACTIVATE_PHONE_PRINCIPAL_SQL,
ACTIVATE_PHONE_ROUTE_SQL,
ADVANCE_AUTHORIZATION_AFTER_CLAIM_SQL,
ADVANCE_AUTHORIZATION_AFTER_PHONE_ACTIVATION_SQL,
ADVANCE_AUTHORIZATION_AFTER_PHONE_REVOKE_SQL,
ADVANCE_AUTHORIZATION_AFTER_REVOKE_SQL,
AUTHORIZE_PHONE_ROUTE_SQL,
CLAIM_PHONE_HANDOFF_ACTIVATION_SQL,
CONSUME_PHONE_HANDOFF_SQL,
DELETE_SUPERSEDED_PENDING_PHONE_PRINCIPALS_SQL,
DELETE_SUPERSEDED_PENDING_PHONE_ROUTES_SQL,
FINALIZE_PHONE_HANDOFF_ACTIVATION_SQL,
PHONE_FOR_NODE_REVOCATION_SQL,
REVOKE_PHONE_PRINCIPAL_SQL,
REVOKE_PHONE_ROUTES_SQL,
} from "../db/relay-control-sql.ts";
import {
AUTHENTICATE_RELAY_NODE_IDENTITY_SQL,
createTrustedRelayMtlsAssertion,
verifyTrustedRelayMtlsIdentity,
} from "../db/relay-node-identity.ts";
import {
decryptRegistrationReplay,
encryptRegistrationReplay,
} from "../db/registration-replay.ts";
import { REQUIRED_PUBLIC_BETA_P0_KEYS } from "../db/launch-gates.ts";
import { CONSUME_CLAIM_RATE_SQL, RESERVE_PAIRING_SQL } from "../db/pairing.ts";
import { isWritableRelayPlacement, resolveRelayPlacementRoute } from "../db/relay-routing.ts";
import { authorityAfterMigrationFailure } from "../db/relay-migration-state.ts";
import {
COMPLETED_RELAY_PURGE_PROOF_SQL,
relayPurgeCompletionAuditId,
relayPurgeRecordCanReturn,
} from "../db/relay-purge-proof.ts";
function migrationStatements(source) {
return source
.split("--> statement-breakpoint")
.map((statement) => statement.trim())
.filter(Boolean);
}
test("resolves stable ingress to exactly one active local or remote Relay", () => {
assert.match(AUTHORIZE_PHONE_ROUTE_SQL, /placements\.state IN \('active', 'draining'\)/);
assert.equal(isWritableRelayPlacement("active", "active"), true);
assert.equal(isWritableRelayPlacement("draining", "active"), true);
assert.equal(isWritableRelayPlacement("copying", "active"), false);
assert.equal(isWritableRelayPlacement("draining", "offline"), false);
const placement = {
tenant_id: `tenant_${"a".repeat(32)}`,
tenant_status: "active",
home_region: "cn-east",
relay_node_id: "node_east_1",
generation: 4,
placement_state: "active",
authorization_revision: 9,
internal_endpoint_ref: "relay-east-1",
relay_node_status: "active",
};
assert.deepEqual(resolveRelayPlacementRoute(placement, "node_east_1"), {
relay_node_id: "node_east_1",
placement_generation: 4,
home_region: "cn-east",
local: true,
});
assert.deepEqual(resolveRelayPlacementRoute(placement, "node_west_1"), {
relay_node_id: "node_east_1",
placement_generation: 4,
home_region: "cn-east",
local: false,
endpoint_ref: "relay-east-1",
});
assert.deepEqual(
resolveRelayPlacementRoute({ ...placement, placement_state: "draining" }, "node_west_1"),
{
relay_node_id: "node_east_1",
placement_generation: 4,
home_region: "cn-east",
local: false,
endpoint_ref: "relay-east-1",
},
);
assert.throws(
() => resolveRelayPlacementRoute({ ...placement, placement_state: "switching" }, "node_west_1"),
/租户 Relay 正在准备/,
);
assert.throws(
() => resolveRelayPlacementRoute({ ...placement, relay_node_status: "offline" }, "node_west_1"),
/目标 Relay 节点当前不可用/,
);
assert.throws(
() => resolveRelayPlacementRoute({ ...placement, internal_endpoint_ref: "https:\/\/evil.example" }, "node_west_1"),
/目标 Relay 内部路由不可用/,
);
});
test("rolls back only before switch and never makes a stale source authoritative afterward", () => {
const fence = {
state: "copying",
source_node_id: "node_source",
target_node_id: "node_target",
source_generation: 4,
target_generation: 5,
};
assert.deepEqual(authorityAfterMigrationFailure(fence), {
nodeId: "node_source",
generation: 4,
});
assert.deepEqual(authorityAfterMigrationFailure({ ...fence, state: "draining" }), {
nodeId: "node_target",
generation: 5,
});
});
test("canonicalizes and signs a bounded Ed25519 authorization snapshot", async () => {
assert.equal(
canonicalJson({ z: 1, a: [true, { y: null, x: "猫" }] }),
'{"a":[true,{"x":"猫","y":null}],"z":1}',
);
const keys = await crypto.subtle.generateKey({ name: "Ed25519" }, true, ["sign", "verify"]);
const issuedAt = "2026-08-12T12:00:00.000Z";
const payload = {
snapshot_version: 1,
tenant_id: `tenant_${"a".repeat(32)}`,
tenant_status: "active",
home_region: "cn-east",
relay_node_id: "node_cn-east-1",
placement_generation: 3,
authorization_revision: 7,
devices: [
{
device_id: `host_${"b".repeat(32)}`,
name: "Workstation",
os: "windows",
ed25519_public: "e".repeat(43),
x25519_public: "x".repeat(43),
credential_hash: "c".repeat(64),
identity_fingerprint: "d".repeat(64),
},
],
issued_at: issuedAt,
expires_at: new Date(
Date.parse(issuedAt) + RELAY_AUTHORIZATION_MAX_TTL_SECONDS * 1_000,
).toISOString(),
};
const snapshot = await signRelayAuthorizationSnapshot({
kid: "relay-signing-2026-08",
privateKey: keys.privateKey,
payload,
});
assert.equal(
await verifyRelayAuthorizationSnapshot({
snapshot,
publicKey: keys.publicKey,
nowMs: Date.parse(issuedAt) + 60_000,
}),
true,
);
assert.equal(
await verifyRelayAuthorizationSnapshot({
snapshot: {
...snapshot,
payload: { ...snapshot.payload, authorization_revision: 8 },
},
publicKey: keys.publicKey,
nowMs: Date.parse(issuedAt) + 60_000,
}),
false,
);
assert.equal(
await verifyRelayAuthorizationSnapshot({
snapshot: {
...snapshot,
payload: {
...snapshot.payload,
devices: [{ ...snapshot.payload.devices[0], x25519_public: "y".repeat(43) }],
},
},
publicKey: keys.publicKey,
nowMs: Date.parse(issuedAt) + 60_000,
}),
false,
);
await assert.rejects(
signRelayAuthorizationSnapshot({
kid: "relay-signing-2026-08",
privateKey: keys.privateKey,
payload: {
...payload,
devices: [{ ...payload.devices[0], ed25519_public: "invalid" }],
},
}),
/invalid_snapshot_device_public_key/,
);
assert.equal(
await verifyRelayAuthorizationSnapshot({
snapshot: {
...snapshot,
payload: {
...snapshot.payload,
devices: [{ ...snapshot.payload.devices[0], name: "Other" }],
},
},
publicKey: keys.publicKey,
nowMs: Date.parse(issuedAt) + 60_000,
}),
false,
);
assert.equal(
await verifyRelayAuthorizationSnapshot({
snapshot,
publicKey: keys.publicKey,
nowMs: Date.parse(payload.expires_at),
}),
false,
);
await assert.rejects(
signRelayAuthorizationSnapshot({
kid: "relay-signing-2026-08",
privateKey: keys.privateKey,
payload: {
...payload,
expires_at: new Date(
Date.parse(issuedAt) + (RELAY_AUTHORIZATION_MAX_TTL_SECONDS + 1) * 1_000,
).toISOString(),
},
}),
/snapshot_ttl_exceeds_maximum/,
);
});
test("selects only a signing key valid through the full snapshot lifetime", () => {
const db = new DatabaseSync(":memory:");
db.exec(`
CREATE TABLE relay_signing_keys (
kid TEXT PRIMARY KEY, public_key_jwk TEXT, private_key_ref TEXT,
status TEXT, not_before TEXT, not_after TEXT
);
INSERT INTO relay_signing_keys VALUES
('old-too-short', '{}', 'env:key#old', 'active',
'2026-08-12T11:00:00.000Z', '2026-08-12T12:04:59.999Z'),
('overlap-old', '{}', 'env:key#overlap', 'active',
'2026-08-12T11:30:00.000Z', '2026-08-12T12:05:00.000Z'),
('new', '{}', 'env:key#new', 'active',
'2026-08-12T11:59:00.000Z', '2026-08-13T00:00:00.000Z');
`);
const select = db.prepare(RELAY_SIGNING_KEY_FOR_SNAPSHOT_SQL);
assert.equal(select.get(
"2026-08-12T12:00:00.000Z",
"2026-08-12T12:05:00.000Z",
).kid, "new");
db.prepare("UPDATE relay_signing_keys SET status = 'retired' WHERE kid = 'new'").run();
assert.equal(select.get(
"2026-08-12T12:00:00.000Z",
"2026-08-12T12:05:00.000Z",
).kid, "overlap-old");
db.prepare("UPDATE relay_signing_keys SET status = 'retired' WHERE kid = 'overlap-old'").run();
assert.equal(select.get(
"2026-08-12T12:00:00.000Z",
"2026-08-12T12:05:00.000Z",
), undefined);
db.close();
});
test("fails full snapshot refresh for wrong node, stale generation, suspended tenant, or provisioning", () => {
const placement = {
relay_node_id: "node_a",
generation: 3,
tenant_status: "active",
placement_state: "active",
};
assert.equal(classifySnapshotPlacement({ placement, nodeId: "node_a", expectedGeneration: 3 }), "ready");
assert.equal(classifySnapshotPlacement({
placement: { ...placement, placement_state: "draining" },
nodeId: "node_a",
expectedGeneration: 3,
}), "ready");
assert.equal(classifySnapshotPlacement({ placement, nodeId: "node_b", expectedGeneration: 3 }), "wrong_node");
assert.equal(classifySnapshotPlacement({ placement, nodeId: "node_a", expectedGeneration: 2 }), "stale_generation");
assert.equal(classifySnapshotPlacement({
placement: { ...placement, tenant_status: "suspended" },
nodeId: "node_a",
expectedGeneration: 3,
}), "suspended");
assert.equal(classifySnapshotPlacement({
placement: { ...placement, placement_state: "copying" },
nodeId: "node_a",
expectedGeneration: 3,
}), "provisioning");
});
test("installs shared-relay tables, backfills placement and stores no plaintext private keys", async () => {
const migration = await readFile(
new URL("../drizzle/0012_shared_relay_control_plane.sql", import.meta.url),
"utf8",
);
const db = new DatabaseSync(":memory:");
db.exec(`
CREATE TABLE accounts (id TEXT PRIMARY KEY);
CREATE TABLE tenant_instances (
id TEXT PRIMARY KEY, account_id TEXT NOT NULL,
credential_revision INTEGER NOT NULL DEFAULT 0, tombstoned_at TEXT
);
INSERT INTO accounts VALUES ('acct_a');
INSERT INTO tenant_instances VALUES
('tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'acct_a', 4, NULL);
`);
for (const statement of migrationStatements(migration)) db.exec(statement);
assert.deepEqual(
{ ...db.prepare(
`SELECT home_region_id, generation, state
FROM tenant_placements WHERE tenant_id = ?`,
).get("tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") },
{ home_region_id: "region_default", generation: 1, state: "provisioning" },
);
assert.deepEqual(
{ ...db.prepare(
`SELECT revision, status
FROM tenant_authorization_state WHERE tenant_id = ?`,
).get("tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") },
{ revision: 4, status: "active" },
);
const signingColumns = db.prepare("PRAGMA table_info(relay_signing_keys)").all();
assert.equal(signingColumns.some((column) => column.name === "private_key"), false);
assert.equal(signingColumns.some((column) => column.name === "private_key_ref"), true);
const nodeIdentityColumns = db.prepare("PRAGMA table_info(relay_node_credentials)").all();
assert.equal(nodeIdentityColumns.some((column) => column.name === "token_hash"), false);
const allNewColumns = [
"relay_regions",
"relay_nodes",
"tenant_placements",
"tenant_authorization_state",
"relay_signing_keys",
"relay_node_credentials",
"phone_handoff_tickets",
"phone_route_handles",
"relay_phone_principals",
].flatMap((table) => db.prepare(`PRAGMA table_info(${table})`).all());
assert.equal(
allNewColumns.some((column) => /prompt|session|attachment|private_key$/u.test(column.name)),
false,
);
db.close();
});
test("fences one Relay migration through quiesce, copy, switch, drain, and active", async () => {
const migration = await readFile(
new URL("../drizzle/0013_relay_migration_fencing.sql", import.meta.url),
"utf8",
);
const db = new DatabaseSync(":memory:");
db.exec(`
PRAGMA foreign_keys = ON;
CREATE TABLE tenant_instances (id TEXT PRIMARY KEY);
CREATE TABLE relay_nodes (id TEXT PRIMARY KEY);
CREATE TABLE tenant_placements (
tenant_id TEXT PRIMARY KEY, relay_node_id TEXT, generation INTEGER,
state TEXT, last_error_code TEXT, updated_at TEXT
);
INSERT INTO tenant_instances VALUES ('tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
INSERT INTO relay_nodes VALUES ('node_source'), ('node_target');
INSERT INTO tenant_placements VALUES
('tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_source', 4, 'active', NULL,
'2026-08-12T12:00:00.000Z');
`);
for (const statement of migrationStatements(migration)) db.exec(statement);
const insert = db.prepare(`
INSERT INTO relay_migrations
(id, tenant_id, source_node_id, target_node_id, source_generation,
target_generation, state, requested_by, reason, started_at, updated_at)
VALUES (?, 'tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_source', 'node_target',
4, 5, 'quiescing', 'admin', 'capacity move', ?, ?)
`);
const now = "2026-08-12T12:00:01.000Z";
insert.run(`migration_${"a".repeat(32)}`, now, now);
assert.throws(
() => insert.run(`migration_${"b".repeat(32)}`, now, now),
/UNIQUE constraint failed/,
);
assert.throws(
() => db.prepare(`
INSERT INTO relay_migrations
(id, tenant_id, source_node_id, target_node_id, source_generation,
target_generation, state, requested_by, reason, started_at, updated_at)
VALUES (?, 'tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_source', 'node_target',
4, 9, 'failed', 'admin', 'invalid fence', ?, ?)
`).run(`migration_${"c".repeat(32)}`, now, now),
/CHECK constraint failed/,
);
const placement = () => ({ ...db.prepare(
"SELECT relay_node_id, generation, state FROM tenant_placements",
).get() });
db.prepare("UPDATE tenant_placements SET state = 'quiescing'").run();
assert.deepEqual(placement(), { relay_node_id: "node_source", generation: 4, state: "quiescing" });
db.prepare("UPDATE tenant_placements SET state = 'copying'").run();
db.prepare("UPDATE relay_migrations SET state = 'copying'").run();
assert.notEqual(placement().state, "active");
db.prepare("UPDATE tenant_placements SET state = 'switching'").run();
db.prepare("UPDATE relay_migrations SET state = 'switching'").run();
assert.notEqual(placement().state, "active");
db.prepare("UPDATE tenant_placements SET relay_node_id = 'node_target', generation = 5, state = 'draining'").run();
db.prepare("UPDATE relay_migrations SET state = 'draining'").run();
assert.deepEqual(placement(), { relay_node_id: "node_target", generation: 5, state: "draining" });
db.prepare("UPDATE tenant_placements SET state = 'active'").run();
db.prepare("UPDATE relay_migrations SET state = 'completed'").run();
assert.deepEqual(placement(), { relay_node_id: "node_target", generation: 5, state: "active" });
db.close();
});
test("fences one permanent Relay purge per tenant and covers live credentials and backups", async () => {
const [migration, control, relayPrimitive] = await Promise.all([
readFile(new URL("../drizzle/0014_relay_tenant_purge.sql", import.meta.url), "utf8"),
readFile(new URL("../db/relay-purges.ts", import.meta.url), "utf8"),
readFile(new URL("../relay/internal/tenantpurge/purge.go", import.meta.url), "utf8"),
]);
const db = new DatabaseSync(":memory:");
db.exec(`
PRAGMA foreign_keys = ON;
CREATE TABLE account_deletion_requests (id TEXT PRIMARY KEY);
CREATE TABLE tenant_instances (id TEXT PRIMARY KEY);
CREATE TABLE relay_nodes (id TEXT PRIMARY KEY);
INSERT INTO account_deletion_requests VALUES ('deletion_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
INSERT INTO tenant_instances VALUES ('tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
INSERT INTO relay_nodes VALUES ('node_a');
`);
for (const statement of migrationStatements(migration)) db.exec(statement);
const insert = db.prepare(`
INSERT INTO relay_purge_jobs
(id, deletion_request_id, tenant_id, relay_node_id, placement_generation,
state, requested_by, reason, started_at, updated_at)
VALUES (?, 'deletion_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
'tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_a', ?,
'quiescing', 'admin', 'confirmed deletion', ?, ?)
`);
const now = "2026-08-12T12:00:00.000Z";
insert.run(`purge_${"a".repeat(32)}`, 4, now, now);
assert.throws(
() => insert.run(`purge_${"b".repeat(32)}`, 4, now, now),
/UNIQUE constraint failed/,
);
assert.throws(
() => db.prepare(`
INSERT INTO relay_purge_jobs
(id, deletion_request_id, tenant_id, relay_node_id, placement_generation,
state, requested_by, reason, started_at, updated_at)
VALUES (?, 'deletion_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
'tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_a', 0,
'quiescing', 'admin', 'invalid', ?, ?)
`).run(`purge_${"c".repeat(32)}`, now, now),
/CHECK constraint failed|UNIQUE constraint failed/,
);
assert.match(control, /DELETE FROM device_registration_replays/);
assert.match(control, /DELETE FROM device_credentials/);
assert.match(control, /DELETE FROM phone_route_handles/);
assert.match(control, /DELETE FROM relay_phone_principals/);
assert.match(control, /DELETE FROM phone_handoff_tickets/);
assert.match(control, /generation = CASE WHEN state = 'deleting' THEN generation \+ 1/);
assert.match(control, /SET lifecycle = 'deleting', desired_state = 'deleted'/);
assert.match(control, /status = 'deleting'/);
const completionAudit = control.lastIndexOf("INSERT OR IGNORE INTO audit_events");
const completionFence = control.lastIndexOf("UPDATE relay_purge_jobs\n SET state = 'completed'");
assert.ok(completionAudit > control.indexOf("SET status = 'deleted'"));
assert.ok(completionFence > completionAudit);
assert.match(control.slice(completionAudit, completionFence), /NOT EXISTS \(SELECT 1 FROM phone_route_handles/);
assert.match(control.slice(completionAudit, completionFence), /generation = \?7 \+ 1 AND state = 'deleted'/);
assert.match(control.slice(completionFence), /json_extract\(after_json, '\$\.evidence_sha256'\) = \?1/);
assert.doesNotMatch(control.slice(completionFence), /db\.prepare\(/);
assert.match(control, /return validatePurgeRecordForReturn\(record\)/);
assert.match(control, /existing\.state !== "failed"\) return validatePurgeRecordForReturn\(existing\)/);
assert.match(control, /if \(raced\) return validatePurgeRecordForReturn\(raced\)/);
assert.match(control, /const current = await reloadPurge\(purgeId\)/);
assert.match(control, /current\.state === "completed"\) return validatePurgeRecordForReturn\(current\)/);
assert.doesNotMatch(control, /state === "completed"[^\n]*return (?:record|existing|raced|current)/);
assert.match(relayPrimitive, /delete tenant Relay backups/);
assert.match(relayPrimitive, /symbolic link/);
db.close();
});
test("accepts an idempotent completed purge only with its full deterministic proof", () => {
assert.equal(relayPurgeRecordCanReturn("quiescing", false), true);
assert.equal(relayPurgeRecordCanReturn("failed", false), true);
assert.equal(relayPurgeRecordCanReturn("completed", false), false);
assert.equal(relayPurgeRecordCanReturn("completed", true), true);
const db = new DatabaseSync(":memory:");
const purgeId = `purge_${"a".repeat(32)}`;
const evidence = "e".repeat(64);
const auditId = relayPurgeCompletionAuditId(purgeId);
db.exec(`
CREATE TABLE relay_purge_jobs (
id TEXT PRIMARY KEY, deletion_request_id TEXT NOT NULL, tenant_id TEXT NOT NULL,
relay_node_id TEXT NOT NULL, placement_generation INTEGER NOT NULL,
state TEXT NOT NULL, evidence_sha256 TEXT
);
CREATE TABLE audit_events (
id TEXT PRIMARY KEY, actor_id TEXT NOT NULL, action TEXT NOT NULL,
target_type TEXT NOT NULL, target_id TEXT NOT NULL, after_json TEXT
);
CREATE TABLE tenant_authorization_state (tenant_id TEXT PRIMARY KEY, status TEXT NOT NULL);
CREATE TABLE tenant_placements (
tenant_id TEXT PRIMARY KEY, relay_node_id TEXT, generation INTEGER NOT NULL, state TEXT NOT NULL
);
CREATE TABLE tenant_instances (
id TEXT PRIMARY KEY, account_id TEXT NOT NULL, lifecycle TEXT NOT NULL,
desired_state TEXT NOT NULL, observed_state TEXT NOT NULL
);
CREATE TABLE account_deletion_requests (
id TEXT PRIMARY KEY, account_id TEXT NOT NULL, status TEXT NOT NULL
);
CREATE TABLE accounts (id TEXT PRIMARY KEY, status TEXT NOT NULL);
CREATE TABLE hosts (
id TEXT PRIMARY KEY, account_id TEXT NOT NULL, lifecycle TEXT, slot_state TEXT
);
CREATE TABLE device_credentials (id TEXT PRIMARY KEY, host_id TEXT NOT NULL);
CREATE TABLE phone_route_handles (id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL);
CREATE TABLE relay_phone_principals (phone_id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL);
CREATE TABLE phone_handoff_tickets (id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL);
INSERT INTO relay_purge_jobs VALUES (
'${purgeId}', 'deletion_a', 'tenant_a', 'node_a', 4, 'completed', '${evidence}'
);
INSERT INTO audit_events VALUES (
'${auditId}', 'node_a', 'relay.purge.completed', 'relay_purge', '${purgeId}',
json_object('evidence_sha256', '${evidence}')
);
INSERT INTO tenant_authorization_state VALUES ('tenant_a', 'deleted');
INSERT INTO tenant_placements VALUES ('tenant_a', NULL, 5, 'deleted');
INSERT INTO tenant_instances VALUES ('tenant_a', 'account_a', 'deleted', 'deleted', 'deleted');
INSERT INTO account_deletion_requests VALUES ('deletion_a', 'account_a', 'relay_purged');
INSERT INTO accounts VALUES ('account_a', 'relay_purged');
INSERT INTO hosts VALUES ('host_a', 'account_a', 'deactivated', 'released');
`);
const proof = () => Number(
db.prepare(COMPLETED_RELAY_PURGE_PROOF_SQL).get(purgeId, auditId, evidence).proof_valid,
);
assert.equal(proof(), 1);
db.prepare("INSERT INTO phone_route_handles VALUES ('route_a', 'tenant_a')").run();
assert.equal(proof(), 0);
db.prepare("DELETE FROM phone_route_handles").run();
db.prepare("UPDATE audit_events SET after_json = json_object('evidence_sha256', ?)")
.run("f".repeat(64));
assert.equal(proof(), 0);
db.prepare("DELETE FROM audit_events").run();
assert.equal(proof(), 0);
db.close();
});
test("consumes a 60-second origin-bound phone handoff only once", () => {
const db = new DatabaseSync(":memory:");
db.exec(`
CREATE TABLE phone_handoff_tickets (
id TEXT PRIMARY KEY, ticket_hash TEXT NOT NULL, expected_origin TEXT NOT NULL,
expires_at TEXT NOT NULL, consumed_at TEXT, consumed_by_node_id TEXT,
pending_phone_name TEXT, pending_ed25519_public TEXT,
pending_x25519_public TEXT, pending_identity_fingerprint TEXT
);
INSERT INTO phone_handoff_tickets
(id, ticket_hash, expected_origin, expires_at, consumed_at) VALUES
('handoff_a', '${"a".repeat(64)}', 'https://pwa.example.test',
'2026-08-12T12:01:00.000Z', NULL);
`);
const consume = db.prepare(CONSUME_PHONE_HANDOFF_SQL);
assert.equal(
consume.run(
"2026-08-12T12:00:30.000Z",
"handoff_a",
"a".repeat(64),
"https://pwa.example.test",
"node_a",
"Phone",
"e".repeat(43),
"x".repeat(43),
"f".repeat(64),
).changes,
1,
);
assert.equal(
consume.run(
"2026-08-12T12:00:31.000Z",
"handoff_a",
"a".repeat(64),
"https://pwa.example.test",
"node_a",
"Phone",
"e".repeat(43),
"x".repeat(43),
"f".repeat(64),
).changes,
0,
);
db.exec(
`INSERT INTO phone_handoff_tickets
(id, ticket_hash, expected_origin, expires_at, consumed_at) VALUES
('handoff_b', '${"b".repeat(64)}', 'https://pwa.example.test',
'2026-08-12T12:01:00.000Z', NULL)`,
);
assert.equal(
consume.run(
"2026-08-12T12:00:30.000Z",
"handoff_b",
"b".repeat(64),
"https://evil.example.test",
"node_a",
"Phone",
"e".repeat(43),
"x".repeat(43),
"f".repeat(64),
).changes,
0,
);
assert.equal(
consume.run(
"2026-08-12T12:01:00.000Z",
"handoff_b",
"b".repeat(64),
"https://pwa.example.test",
"node_a",
"Phone",
"e".repeat(43),
"x".repeat(43),
"f".repeat(64),
).changes,
0,
);
db.close();
});
test("records an exact idempotency key for ambiguous phone handoff completion", async () => {
const [migration, activationMigration, control] = await Promise.all([
readFile(new URL("../drizzle/0015_phone_handoff_idempotency.sql", import.meta.url), "utf8"),
readFile(new URL("../drizzle/0016_phone_handoff_activation.sql", import.meta.url), "utf8"),
readFile(new URL("../db/relay-control-plane.ts", import.meta.url), "utf8"),
]);
const db = new DatabaseSync(":memory:");
db.exec("CREATE TABLE phone_handoff_tickets (id TEXT PRIMARY KEY)");
for (const statement of migrationStatements(migration)) db.exec(statement);
for (const statement of migrationStatements(activationMigration)) db.exec(statement);
const columns = db.prepare("PRAGMA table_info(phone_handoff_tickets)").all().map((row) => row.name);
assert.ok(columns.includes("completed_phone_id"));
assert.ok(columns.includes("completed_phone_token_hash"));
assert.ok(columns.includes("completed_route_handle_hash"));
assert.ok(columns.includes("activation_nonce"));
assert.ok(columns.includes("activated_at"));
assert.match(control, /completed_phone_id = \?/);
assert.match(control, /completed_phone_token_hash !== phoneTokenHash/);
assert.match(control, /completed_route_handle_hash !== routeHandleHash/);
assert.match(control, /An identical request may have won the one-shot consume update/);
db.close();
});
test("keeps handoff credentials pending until the first exact route proof activates them once", () => {
const db = new DatabaseSync(":memory:");
const tokenHash = "a".repeat(64);
const routeHash = "b".repeat(64);
db.exec(`
CREATE TABLE phone_handoff_tickets (
id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL, consumed_by_node_id TEXT,
completed_at TEXT, completed_phone_id TEXT, completed_phone_token_hash TEXT,
completed_route_handle_hash TEXT, activation_nonce TEXT UNIQUE, activated_at TEXT
);
CREATE TABLE relay_phone_principals (
phone_id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL, token_hash TEXT NOT NULL,
name TEXT NOT NULL, ed25519_public TEXT NOT NULL, x25519_public TEXT NOT NULL,
identity_fingerprint TEXT NOT NULL, status TEXT NOT NULL,
revoked_at TEXT, last_used_at TEXT
);
CREATE TABLE phone_route_handles (
id TEXT PRIMARY KEY, handle_hash TEXT NOT NULL, tenant_id TEXT NOT NULL,
phone_id TEXT NOT NULL, status TEXT NOT NULL, revoked_at TEXT, last_used_at TEXT
);
CREATE TABLE relay_regions (id TEXT PRIMARY KEY, code TEXT NOT NULL);
CREATE TABLE tenant_placements (
tenant_id TEXT PRIMARY KEY, home_region_id TEXT NOT NULL, relay_node_id TEXT,
generation INTEGER NOT NULL, state TEXT NOT NULL
);
CREATE TABLE tenant_authorization_state (
tenant_id TEXT PRIMARY KEY, status TEXT NOT NULL, revision INTEGER NOT NULL,
updated_at TEXT NOT NULL
);
INSERT INTO relay_regions VALUES ('region_a', 'cn-east-1');
INSERT INTO tenant_placements VALUES ('tenant_a', 'region_a', 'node_a', 3, 'active');
INSERT INTO tenant_authorization_state VALUES ('tenant_a', 'active', 7, '2026-08-12T12:00:00.000Z');
INSERT INTO phone_handoff_tickets VALUES (
'handoff_a', 'tenant_a', 'node_a', '2026-08-12T12:00:00.000Z',
'phone_a', '${tokenHash}', '${routeHash}', NULL, NULL
);
INSERT INTO relay_phone_principals VALUES (
'phone_a', 'tenant_a', '${tokenHash}', 'Phone', 'ed', 'x', '${"f".repeat(64)}',
'pending', NULL, NULL
);
INSERT INTO phone_route_handles VALUES (
'route_a', '${routeHash}', 'tenant_a', 'phone_a', 'pending', NULL, NULL
);
`);
assert.equal(db.prepare(AUTHORIZE_PHONE_ROUTE_SQL).get(routeHash, tokenHash), undefined);
const nonce = "activation_" + "c".repeat(32);
const changes = [
db.prepare(CLAIM_PHONE_HANDOFF_ACTIVATION_SQL)
.run(nonce, routeHash, tokenHash, "2026-08-12T11:59:00.000Z", "node_a").changes,
db.prepare(ACTIVATE_PHONE_PRINCIPAL_SQL).run(nonce, tokenHash).changes,
db.prepare(ACTIVATE_PHONE_ROUTE_SQL).run(nonce, routeHash, tokenHash).changes,
db.prepare(ADVANCE_AUTHORIZATION_AFTER_PHONE_ACTIVATION_SQL)
.run("2026-08-12T12:00:01.000Z", nonce).changes,
db.prepare(FINALIZE_PHONE_HANDOFF_ACTIVATION_SQL)
.run("2026-08-12T12:00:01.000Z", nonce).changes,
].map(Number);
assert.deepEqual(changes, [1, 1, 1, 1, 1]);
assert.equal(db.prepare(AUTHORIZE_PHONE_ROUTE_SQL).get(routeHash, tokenHash).phone_id, "phone_a");
assert.equal(db.prepare("SELECT revision FROM tenant_authorization_state").get().revision, 8);
const losingNonce = "activation_" + "d".repeat(32);
const repeated = [
db.prepare(CLAIM_PHONE_HANDOFF_ACTIVATION_SQL)
.run(losingNonce, routeHash, tokenHash, "2026-08-12T11:59:00.000Z", "node_a").changes,
db.prepare(ACTIVATE_PHONE_PRINCIPAL_SQL).run(losingNonce, tokenHash).changes,
db.prepare(ACTIVATE_PHONE_ROUTE_SQL).run(losingNonce, routeHash, tokenHash).changes,
db.prepare(ADVANCE_AUTHORIZATION_AFTER_PHONE_ACTIVATION_SQL)
.run("2026-08-12T12:00:02.000Z", losingNonce).changes,
db.prepare(FINALIZE_PHONE_HANDOFF_ACTIVATION_SQL)
.run("2026-08-12T12:00:02.000Z", losingNonce).changes,
].map(Number);
assert.deepEqual(repeated, [0, 0, 0, 0, 0]);
assert.equal(db.prepare("SELECT revision FROM tenant_authorization_state").get().revision, 8);
db.close();
});
test("an expired response-lost handoff can be superseded without deleting active phones", () => {
const db = new DatabaseSync(":memory:");
db.exec(`
CREATE TABLE phone_handoff_tickets (
id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL, expires_at TEXT NOT NULL,
pending_identity_fingerprint TEXT, completed_phone_id TEXT,
completed_phone_token_hash TEXT, completed_route_handle_hash TEXT,
activation_nonce TEXT
);
CREATE TABLE relay_phone_principals (
phone_id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL, token_hash TEXT NOT NULL,
status TEXT NOT NULL
);
CREATE TABLE phone_route_handles (
id TEXT PRIMARY KEY, handle_hash TEXT NOT NULL, tenant_id TEXT NOT NULL,
phone_id TEXT NOT NULL, status TEXT NOT NULL
);
INSERT INTO phone_handoff_tickets VALUES
('handoff_old', 'tenant_a', '2026-08-12T12:00:00.000Z', 'fingerprint_a',
'phone_old', 'token_old', 'route_old', NULL),
('handoff_new', 'tenant_a', '2026-08-12T12:01:30.000Z', 'fingerprint_a',
NULL, NULL, NULL, NULL),
('handoff_active', 'tenant_a', '2026-08-12T12:00:00.000Z', 'fingerprint_b',
'phone_active', 'token_active', 'route_active', 'activation_done');
INSERT INTO relay_phone_principals VALUES
('phone_old', 'tenant_a', 'token_old', 'pending'),
('phone_active', 'tenant_a', 'token_active', 'active');
INSERT INTO phone_route_handles VALUES
('handle_old', 'route_old', 'tenant_a', 'phone_old', 'pending'),
('handle_active', 'route_active', 'tenant_a', 'phone_active', 'active');
`);
assert.equal(
db.prepare(DELETE_SUPERSEDED_PENDING_PHONE_ROUTES_SQL)
.run('handoff_new', '2026-08-12T12:00:01.000Z').changes,
1,
);
assert.equal(
db.prepare(DELETE_SUPERSEDED_PENDING_PHONE_PRINCIPALS_SQL)
.run('handoff_new', '2026-08-12T12:00:01.000Z').changes,
1,
);
assert.deepEqual(
db.prepare("SELECT phone_id, status FROM relay_phone_principals").all().map((row) => ({ ...row })),
[{ phone_id: "phone_active", status: "active" }],
);
assert.deepEqual(
db.prepare("SELECT id, status FROM phone_route_handles").all().map((row) => ({ ...row })),
[{ id: "handle_active", status: "active" }],
);
db.close();
});
test("requires a short-lived trusted mTLS terminator assertion", async () => {
const assertionSecret = "m".repeat(32);
const timestampSeconds = 1_786_536_000;
const identity = {
nodeId: "node_cn-east-1",
spiffeId: "spiffe://nekonest.cloud/relay/cn-east-1",
certificateFingerprintSha256: "a".repeat(64),
};
const pathname = "/api/internal/relay/heartbeat";
const assertion = await createTrustedRelayMtlsAssertion({
assertionSecret,
method: "POST",
pathname,
...identity,
timestampSeconds,
});
const request = new Request(`https://control.example.test${pathname}`, {
method: "POST",
headers: {
"x-neko-relay-node-id": identity.nodeId,
"x-neko-mtls-spiffe-id": identity.spiffeId,
"x-neko-mtls-cert-sha256": identity.certificateFingerprintSha256,
"x-neko-mtls-verified": "SUCCESS",
"x-neko-mtls-timestamp": String(timestampSeconds),
"x-neko-mtls-assertion": assertion,
},
});
assert.deepEqual(
await verifyTrustedRelayMtlsIdentity({
request,
assertionSecret,
nowMs: timestampSeconds * 1_000,
}),
identity,
);
await assert.rejects(
verifyTrustedRelayMtlsIdentity({ request, assertionSecret: "", nowMs: timestampSeconds * 1_000 }),
/not configured/,
);
const spoofed = new Request(request, {
headers: { ...Object.fromEntries(request.headers), "x-neko-mtls-spiffe-id": "spiffe://evil/relay" },
});
await assert.rejects(
verifyTrustedRelayMtlsIdentity({ request: spoofed, assertionSecret, nowMs: timestampSeconds * 1_000 }),
);
await assert.rejects(
verifyTrustedRelayMtlsIdentity({
request,
assertionSecret,
nowMs: (timestampSeconds + 31) * 1_000,
}),
/expired/,
);
});
test("binds Relay node identity to active unexpired SPIFFE and certificate records", () => {
const db = new DatabaseSync(":memory:");
db.exec(`
CREATE TABLE relay_nodes (id TEXT PRIMARY KEY, status TEXT);
CREATE TABLE relay_node_credentials (
node_id TEXT, mtls_spiffe_id TEXT, certificate_fingerprint_sha256 TEXT,
status TEXT, issued_at TEXT, expires_at TEXT, revoked_at TEXT, last_used_at TEXT
);
INSERT INTO relay_nodes VALUES ('node_a', 'active');
INSERT INTO relay_node_credentials VALUES
('node_a', 'spiffe://nekonest.cloud/relay/a', '${"a".repeat(64)}', 'active',
'2026-08-12T11:00:00.000Z', '2026-08-12T13:00:00.000Z', NULL, NULL);
`);
const authenticate = db.prepare(AUTHENTICATE_RELAY_NODE_IDENTITY_SQL);
const args = [
"2026-08-12T12:00:00.000Z", "node_a",
"spiffe://nekonest.cloud/relay/a", "a".repeat(64),
];
assert.equal(authenticate.run(...args).changes, 1);
assert.equal(authenticate.run(args[0], args[1], "spiffe://evil/relay", args[3]).changes, 0);
assert.equal(authenticate.run(args[0], args[1], args[2], "b".repeat(64)).changes, 0);
db.prepare("UPDATE relay_node_credentials SET revoked_at = ?, status = 'revoked'")
.run("2026-08-12T12:00:01.000Z");
assert.equal(authenticate.run(...args).changes, 0);
db.prepare("UPDATE relay_node_credentials SET revoked_at = NULL, status = 'active', expires_at = ?")
.run("2026-08-12T12:00:00.000Z");
assert.equal(authenticate.run(...args).changes, 0);
db.close();
});
test("encrypts one bounded registration response for lost-response replay", async () => {
const response = {
device_id: `host_${"a".repeat(32)}`,
token: "b".repeat(64),
name: "Workstation",
transport_mode: "sealed",
connection_state: "provisioning",
retry_after_seconds: 5,
};
const common = {
retryKey: "c".repeat(64),
pairingId: `pair_${"d".repeat(32)}`,
requestHash: "e".repeat(64),
};
const encrypted = await encryptRegistrationReplay({ ...common, response });
assert.doesNotMatch(encrypted.ciphertext, new RegExp(response.token));
assert.deepEqual(await decryptRegistrationReplay({ ...common, ...encrypted }), response);
await assert.rejects(
decryptRegistrationReplay({ ...common, ...encrypted, retryKey: "f".repeat(64) }),
);
const db = new DatabaseSync(":memory:");
db.exec("CREATE TABLE device_registration_replays (pairing_id TEXT PRIMARY KEY, request_hash TEXT)");
db.prepare("INSERT INTO device_registration_replays VALUES (?, ?)").run(common.pairingId, common.requestHash);
assert.throws(
() => db.prepare("INSERT INTO device_registration_replays VALUES (?, ?)")
.run(common.pairingId, "f".repeat(64)),
/UNIQUE constraint failed/,
);
db.close();
});
test("authorizes phone routing only when handle and active token digest match one tenant", () => {
const db = new DatabaseSync(":memory:");
db.exec(`
CREATE TABLE phone_route_handles (
handle_hash TEXT, tenant_id TEXT, phone_id TEXT, status TEXT,
revoked_at TEXT
);
CREATE TABLE relay_phone_principals (
phone_id TEXT, tenant_id TEXT, token_hash TEXT, name TEXT,
ed25519_public TEXT, x25519_public TEXT, identity_fingerprint TEXT,
status TEXT, revoked_at TEXT
);
CREATE TABLE tenant_placements (
tenant_id TEXT, home_region_id TEXT, relay_node_id TEXT,
generation INTEGER, state TEXT
);
CREATE TABLE relay_regions (id TEXT, code TEXT);
CREATE TABLE tenant_authorization_state (tenant_id TEXT, status TEXT);
INSERT INTO relay_regions VALUES ('region_a', 'cn-east');
INSERT INTO tenant_authorization_state VALUES ('tenant_a', 'active'), ('tenant_b', 'active');
INSERT INTO tenant_placements VALUES
('tenant_a', 'region_a', 'node_a', 1, 'active'),
('tenant_b', 'region_a', 'node_a', 1, 'active');
INSERT INTO relay_phone_principals VALUES
('phone_a', 'tenant_a', '${"a".repeat(64)}', 'Phone A', 'ed-a', 'x-a', 'fp-a', 'active', NULL),
('phone_b', 'tenant_b', '${"b".repeat(64)}', 'Phone B', 'ed-b', 'x-b', 'fp-b', 'active', NULL);
INSERT INTO phone_route_handles VALUES
('${"1".repeat(64)}', 'tenant_a', 'phone_a', 'active', NULL),
('${"2".repeat(64)}', 'tenant_b', 'phone_b', 'active', NULL);
`);
const authorize = db.prepare(AUTHORIZE_PHONE_ROUTE_SQL);
assert.equal(authorize.get("1".repeat(64), "a".repeat(64)).phone_id, "phone_a");
assert.equal(authorize.get("1".repeat(64), "b".repeat(64)), undefined);
assert.equal(authorize.get("2".repeat(64), "a".repeat(64)), undefined);
assert.equal(authorize.get("1".repeat(64), ""), undefined);
db.prepare("UPDATE relay_phone_principals SET status = 'revoked', revoked_at = '2026-08-12T12:00:00.000Z' WHERE phone_id = 'phone_a'").run();
assert.equal(authorize.get("1".repeat(64), "a".repeat(64)), undefined);
db.close();
});
test("revokes a phone only through its current tenant placement and rejects it afterward", () => {
const db = new DatabaseSync(":memory:");
db.exec(`
CREATE TABLE tenant_placements (tenant_id TEXT, relay_node_id TEXT);
CREATE TABLE relay_phone_principals (
phone_id TEXT, tenant_id TEXT, token_hash TEXT, name TEXT,
ed25519_public TEXT, x25519_public TEXT, identity_fingerprint TEXT,
status TEXT, revoked_at TEXT
);
CREATE TABLE phone_route_handles (
handle_hash TEXT, tenant_id TEXT, phone_id TEXT, status TEXT, revoked_at TEXT
);
CREATE TABLE tenant_authorization_state (
tenant_id TEXT PRIMARY KEY, revision INTEGER, status TEXT, updated_at TEXT
);
CREATE TABLE relay_regions (id TEXT, code TEXT);
INSERT INTO relay_regions VALUES ('region_a', 'cn-east');
ALTER TABLE tenant_placements ADD home_region_id TEXT;
ALTER TABLE tenant_placements ADD generation INTEGER;
ALTER TABLE tenant_placements ADD state TEXT;
INSERT INTO tenant_placements VALUES ('tenant_a', 'node_a', 'region_a', 1, 'active');
INSERT INTO relay_phone_principals VALUES
('phone_a', 'tenant_a', '${"a".repeat(64)}', 'Phone', 'ed', 'x', 'fp', 'active', NULL);
INSERT INTO phone_route_handles VALUES
('${"1".repeat(64)}', 'tenant_a', 'phone_a', 'active', NULL);
INSERT INTO tenant_authorization_state VALUES
('tenant_a', 1, 'active', '2026-08-12T11:00:00.000Z');
`);
const ownership = db.prepare(PHONE_FOR_NODE_REVOCATION_SQL);
assert.equal(ownership.get('tenant_a', 'phone_a').relay_node_id, 'node_a');
assert.equal(ownership.get('tenant_b', 'phone_a'), undefined);
const now = '2026-08-12T12:00:00.000Z';
assert.equal(db.prepare(REVOKE_PHONE_PRINCIPAL_SQL).run(now, 'phone_a', 'tenant_a').changes, 1);
assert.equal(db.prepare(REVOKE_PHONE_ROUTES_SQL).run(now, 'phone_a', 'tenant_a').changes, 1);
assert.equal(db.prepare(ADVANCE_AUTHORIZATION_AFTER_PHONE_REVOKE_SQL)
.run(now, 'tenant_a', 'phone_a').changes, 1);
const authorize = db.prepare(AUTHORIZE_PHONE_ROUTE_SQL);
assert.equal(authorize.get('1'.repeat(64), 'a'.repeat(64)), undefined);
assert.equal(db.prepare("SELECT revision FROM tenant_authorization_state").get().revision, 2);
db.close();
});
test("advances authorization revision only after a committed claim or revoke", () => {
const db = new DatabaseSync(":memory:");
db.exec(`
CREATE TABLE tenant_instances (id TEXT PRIMARY KEY, account_id TEXT NOT NULL);
CREATE TABLE tenant_authorization_state (
tenant_id TEXT PRIMARY KEY, revision INTEGER NOT NULL, updated_at TEXT NOT NULL
);
CREATE TABLE hosts (
id TEXT PRIMARY KEY, lifecycle 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
);
INSERT INTO tenant_instances VALUES
('tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'acct_a');
INSERT INTO tenant_authorization_state VALUES
('tenant_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 0, '2026-08-12T11:00:00.000Z');
INSERT INTO hosts VALUES
('host_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'active', NULL);
INSERT INTO device_credentials VALUES
('credential_a', 'host_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', '${"c".repeat(64)}', 'active');
`);
const claim = db.prepare(ADVANCE_AUTHORIZATION_AFTER_CLAIM_SQL);
assert.equal(
claim.run(
"2026-08-12T12:00:00.000Z",
"acct_a",
"credential_a",
"host_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"c".repeat(64),
).changes,
1,
);
assert.equal(
claim.run(
"2026-08-12T12:00:01.000Z",
"acct_a",
"credential_missing",
"host_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"c".repeat(64),
).changes,
0,
);
db.prepare("UPDATE hosts SET lifecycle = 'deactivated', deactivated_at = ? WHERE id = ?")
.run("2026-08-12T12:00:02.000Z", "host_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
assert.equal(
db.prepare(ADVANCE_AUTHORIZATION_AFTER_REVOKE_SQL).run(
"2026-08-12T12:00:02.000Z",
"acct_a",
"host_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"2026-08-12T12:00:02.000Z",
).changes,
1,
);
assert.equal(
db.prepare("SELECT revision FROM tenant_authorization_state").get().revision,
2,
);
db.close();
});
test("atomically reserves finite host capacity and does not double-book a pending slot", () => {
const db = new DatabaseSync(":memory:");
db.exec(`
CREATE TABLE beta_programs (
id TEXT PRIMARY KEY, capacity_slots INTEGER, state TEXT NOT NULL,
starts_at TEXT NOT NULL, ends_at TEXT, created_at TEXT NOT NULL
);
CREATE TABLE launch_gates (
key TEXT PRIMARY KEY, priority TEXT NOT NULL, status TEXT NOT NULL,
owner TEXT, notes TEXT, evidence_url TEXT
);
CREATE TABLE entitlement_grants (
account_id TEXT NOT NULL, state TEXT NOT NULL, starts_at TEXT NOT NULL,
ends_at TEXT, revoked_at TEXT, capacity_slots INTEGER
);
CREATE TABLE hosts (
account_id TEXT NOT NULL, lifecycle TEXT NOT NULL, slot_state TEXT NOT NULL
);
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, created_at TEXT NOT NULL
);
INSERT INTO beta_programs VALUES
('beta', 1, 'active', '2026-08-12T00:00:00.000Z', NULL,
'2026-08-12T00:00:00.000Z');
`);
const insertGate = db.prepare(
`INSERT INTO launch_gates VALUES (?, 'P0', 'passed', 'owner', 'evidence', 'https://example.test/evidence')`,
);
for (const key of REQUIRED_PUBLIC_BETA_P0_KEYS) insertGate.run(key);
const reserve = db.prepare(RESERVE_PAIRING_SQL);
const params = (id, code) => [
id,
"acct_a",
"Host",
"linux",
code,
"2026-08-12T12:10:00.000Z",
"2026-08-12T12:00:00.000Z",
];
assert.equal(reserve.run(...params("pair_a", "a".repeat(64))).changes, 1);
assert.equal(reserve.run(...params("pair_b", "b".repeat(64))).changes, 0);
db.prepare("UPDATE pairing_requests SET status = 'cancelled' WHERE id = 'pair_a'").run();
assert.equal(reserve.run(...params("pair_b", "b".repeat(64))).changes, 1);
db.close();
});
test("keeps Relay-provided registration source hashes in isolated rate-limit buckets", () => {
const db = new DatabaseSync(":memory:");
db.exec(`
CREATE TABLE pairing_claim_rate_limits (
source_hash TEXT NOT NULL, window_start TEXT NOT NULL,
attempts INTEGER NOT NULL, updated_at TEXT NOT NULL,
PRIMARY KEY (source_hash, window_start)
);
`);
const consume = db.prepare(CONSUME_CLAIM_RATE_SQL);
const window = "2026-08-12T12:00:00.000Z";
for (let index = 0; index < 20; index += 1) {
assert.equal(consume.run("a".repeat(64), window, window).changes, 1);
}
assert.equal(consume.run("a".repeat(64), window, window).changes, 0);
assert.equal(consume.run("b".repeat(64), window, window).changes, 1);
assert.equal(db.prepare("SELECT attempts FROM pairing_claim_rate_limits WHERE source_hash = ?")
.get("b".repeat(64)).attempts, 1);
db.close();
});
test("removes activation polling and exposes only stable-endpoint relay APIs", async () => {
const [registration, dashboardHandoff, consume, complete, relayRepository, docs,
registerRoute, snapshotRoute, revokePhoneRoute] = await Promise.all([
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/pwa/handoff/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/internal/relay/consume-phone-handoff/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/internal/relay/complete-phone-handoff/route.ts", import.meta.url), "utf8"),
readFile(new URL("../db/relay-control-plane.ts", import.meta.url), "utf8"),
readFile(new URL("../docs/daemon-relay-handoff.md", import.meta.url), "utf8"),
readFile(new URL("../app/api/internal/relay/register-device/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/internal/relay/authorization-snapshot/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/internal/relay/revoke-phone/route.ts", import.meta.url), "utf8"),
]);
assert.doesNotMatch(registration, /activation_poll_path|relay_url/);
assert.match(registration, /connection_state/);
assert.match(dashboardHandoff, /createPhoneHandoffTicket/);
assert.match(consume, /phone_ed25519_public/);
assert.match(consume, /phone_x25519_public/);
assert.match(complete, /phone_token_hash/);
assert.doesNotMatch(relayRepository, /phone_token:\s*string/);
assert.match(relayRepository, /routeHandleHash/);
assert.match(registerRoute, /authenticateRelayNode/);
assert.match(registerRoute, /trustedSourceHash/);
assert.match(registerRoute, /registrationRetryKey/);
assert.doesNotMatch(registerRoute, /x-forwarded-for|cf-connecting-ip|relay_url|redirect/);
assert.match(snapshotRoute, /placementGeneration/);
assert.match(relayRepository, /classifySnapshotPlacement/);
assert.match(relayRepository, /expectedGeneration: input\.placementGeneration/);
assert.match(relayRepository, /access_suspended/);
assert.match(revokePhoneRoute, /authenticateRelayNode/);
assert.match(relayRepository, /phone\.revoked/);
assert.match(
relayRepository,
/placements\.state IN \('active', 'draining'\) AND placements\.relay_node_id = \?/,
);
assert.match(registration, /device_registration_replays/);
const claimBody = registration.slice(registration.indexOf("export async function claimDevice"));
assert.ok(
claimBody.indexOf("FROM device_registration_replays WHERE pairing_id")
< claimBody.indexOf("const pairing = await db"),
"lost-response replay must resolve before a spent pairing code is rejected",
);
assert.match(registration, /device_identity_conflict/);
assert.match(registration, /device_capacity_exceeded/);
assert.match(registration, /registration_disabled/);
assert.match(registration, /registration_rate_limited/);
assert.match(registration, /protocol_upgrade_required/);
assert.match(docs, /同一.*服务地址/);
});