1575 lines
67 KiB
JavaScript
1575 lines
67 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 {
|
|
addBillingPeriod,
|
|
getBillingEntitlementPresentation,
|
|
getPublicBetaPresentation,
|
|
nextEntitlementExpiry,
|
|
summarizeEntitlementComponents,
|
|
} from "../db/domain.ts";
|
|
import {
|
|
constantTimeEqualHex,
|
|
deviceRegistrationProofTranscript,
|
|
normalizePairingCode,
|
|
parseBootstrapToken,
|
|
rateWindowStart,
|
|
requestSource,
|
|
sha256Hex,
|
|
validateDeviceIdentity,
|
|
verifyDeviceRegistrationProof,
|
|
} from "../db/device-claim.ts";
|
|
import {
|
|
CANCEL_PAIRING_SQL,
|
|
CLAIM_CREDENTIAL_SQL,
|
|
CLAIM_HOST_SQL,
|
|
COMMIT_PAIRING_CLAIM_SQL,
|
|
CONSUME_CLAIM_RATE_SQL,
|
|
RECORD_FAILED_CODE_SQL,
|
|
RESERVE_PAIRING_SQL,
|
|
} from "../db/pairing.ts";
|
|
import {
|
|
REQUIRED_PUBLIC_BETA_P0_KEYS,
|
|
countBlockedPublicBetaP0,
|
|
} from "../db/launch-gates.ts";
|
|
import { deriveServiceStatus } from "../db/service-status.ts";
|
|
import {
|
|
BETA_ACCOUNTS_SQL,
|
|
BETA_ACCESS_REQUESTS_SQL,
|
|
BETA_CLAIM_ATTEMPTS_SQL,
|
|
BETA_PAIRINGS_SQL,
|
|
BETA_PROVISIONING_SQL,
|
|
BETA_SUPPORT_SQL,
|
|
deriveBetaOperationsSnapshot,
|
|
} from "../db/beta-operations.ts";
|
|
|
|
test("clamps fixed billing terms at calendar month and leap-year boundaries", () => {
|
|
assert.equal(
|
|
addBillingPeriod("2025-01-31T08:15:20.000Z", "month"),
|
|
"2025-02-28T08:15:20.000Z",
|
|
);
|
|
assert.equal(
|
|
addBillingPeriod("2024-01-31T08:15:20.000Z", "month"),
|
|
"2024-02-29T08:15:20.000Z",
|
|
);
|
|
assert.equal(
|
|
addBillingPeriod("2024-02-29T08:15:20.000Z", "year"),
|
|
"2025-02-28T08:15:20.000Z",
|
|
);
|
|
});
|
|
|
|
test("reports the next grant expiry instead of overstating mixed entitlement terms", () => {
|
|
assert.equal(
|
|
nextEntitlementExpiry([
|
|
"2027-01-01T00:00:00.000Z",
|
|
null,
|
|
"2026-09-01T00:00:00.000Z",
|
|
]),
|
|
"2026-09-01T00:00:00.000Z",
|
|
);
|
|
assert.equal(nextEntitlementExpiry([null, null]), null);
|
|
});
|
|
|
|
test("unions finite beta and exemption capacity without hiding the next change", () => {
|
|
assert.deepEqual(
|
|
summarizeEntitlementComponents(
|
|
[
|
|
{ source: "public_beta", capacity: 2, endsAt: "2026-10-01T00:00:00.000Z" },
|
|
{ source: "admin_exemption", capacity: 3, endsAt: "2026-09-01T00:00:00.000Z" },
|
|
],
|
|
1,
|
|
1,
|
|
),
|
|
{
|
|
unlimited: false,
|
|
capacitySlots: 5,
|
|
availableSlots: 3,
|
|
effectiveUntil: "2026-09-01T00:00:00.000Z",
|
|
sources: ["public_beta", "admin_exemption"],
|
|
},
|
|
);
|
|
assert.equal(
|
|
summarizeEntitlementComponents(
|
|
[{ source: "public_beta", capacity: null, endsAt: null }],
|
|
20,
|
|
2,
|
|
).availableSlots,
|
|
null,
|
|
);
|
|
});
|
|
|
|
test("pins the remediated runtime and local toolchain versions", async () => {
|
|
const packageJson = JSON.parse(
|
|
await readFile(new URL("../package.json", import.meta.url), "utf8"),
|
|
);
|
|
assert.equal(packageJson.dependencies.next, "16.3.0");
|
|
assert.equal(packageJson.dependencies.react, "19.2.8");
|
|
assert.equal(packageJson.devDependencies["react-server-dom-webpack"], "19.2.8");
|
|
assert.equal(packageJson.devDependencies.vite, "8.2.1");
|
|
assert.equal(packageJson.devDependencies["@cloudflare/vite-plugin"], "1.51.2");
|
|
assert.equal(
|
|
packageJson.overrides["@esbuild-kit/core-utils"].esbuild,
|
|
"0.25.12",
|
|
);
|
|
});
|
|
|
|
test("keeps the public trust boundary explicit", async () => {
|
|
const [trustPage, shell] = await Promise.all([
|
|
readFile(new URL("../app/trust/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/components/Shells.tsx", import.meta.url), "utf8"),
|
|
]);
|
|
assert.match(trustPage, /安全不是一句“零知识”/);
|
|
assert.match(trustPage, /附件端到端实证未完成/);
|
|
assert.match(trustPage, /Cloud 不运行模型/);
|
|
assert.match(shell, /收费功能暂不开放/);
|
|
assert.doesNotMatch(`${trustPage}\n${shell}`, /Your site is taking shape|react-loading-skeleton/);
|
|
});
|
|
|
|
test("keeps dormant money infrastructure separate from free-beta entitlements", async () => {
|
|
const [schema, migration, contract] = await Promise.all([
|
|
readFile(new URL("../db/schema.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../drizzle/0000_condemned_legion.sql", import.meta.url), "utf8"),
|
|
readFile(new URL("../docs/commercial-contract.md", import.meta.url), "utf8"),
|
|
]);
|
|
assert.match(schema, /amountMinor:\s*integer\("amount_minor"\)/);
|
|
assert.match(schema, /capacitySlots:\s*integer\("capacity_slots"\)/);
|
|
assert.doesNotMatch(schema, /["'](?:points|wallet|balance|credits?)["']/i);
|
|
assert.match(migration, /CREATE TABLE `price_versions`/);
|
|
assert.match(migration, /CREATE TABLE `entitlement_grants`/);
|
|
assert.match(migration, /CREATE TABLE `idempotency_records`/);
|
|
assert.match(contract, /不创建报价、订单、付款单/);
|
|
assert.match(contract, /具体价格均未确定/);
|
|
assert.match(contract, /不会自动扣款/);
|
|
});
|
|
|
|
test("defers quote, order, and price publication during free beta", async () => {
|
|
const [quoteRoute, priceRoute, repository, billingPage, adminPage, apiResponse, layout, packageJson] = await Promise.all([
|
|
readFile(new URL("../app/api/billing/quotes/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/admin/prices/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/billing/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/admin/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/respond.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/layout.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../package.json", import.meta.url), "utf8"),
|
|
]);
|
|
assert.match(quoteRoute, /paid_features_deferred/);
|
|
assert.match(priceRoute, /paid_features_deferred/);
|
|
assert.doesNotMatch(quoteRoute, /createOrderQuote/);
|
|
assert.doesNotMatch(priceRoute, /publishPrice/);
|
|
assert.match(repository, /const paidFeaturesEnabled: boolean = false/);
|
|
assert.match(repository, /function assertPaidFeaturesDeferred\(\): void/);
|
|
assert.match(repository, /createOrderQuote[\s\S]*?assertPaidFeaturesDeferred\(\)/);
|
|
assert.match(repository, /publishPrice[\s\S]*?assertPaidFeaturesDeferred\(\)/);
|
|
assert.doesNotMatch(billingPage, /QuoteForm|报价生成器|生成供应商|formatMoney/);
|
|
assert.doesNotMatch(adminPage, /PriceAction|\/api\/admin\/prices/);
|
|
assert.match(billingPage, /收费以后再决定/);
|
|
assert.match(apiResponse, /服务暂时不可用,请稍后重试/);
|
|
assert.doesNotMatch(apiResponse, /message\s*=\s*error\.message/);
|
|
assert.match(layout, /\/og\.png/);
|
|
assert.doesNotMatch(packageJson, /react-loading-skeleton/);
|
|
});
|
|
|
|
test("persists a minimal audited free-beta feedback workflow", async () => {
|
|
const [baseMigration, feedbackMigration, repository, userRoute, adminRoute, page, form, adminPage, shell] = await Promise.all([
|
|
readFile(new URL("../drizzle/0000_condemned_legion.sql", import.meta.url), "utf8"),
|
|
readFile(new URL("../drizzle/0005_pale_corsair.sql", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/feedback/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/admin/feedback/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/feedback/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/feedback/FeedbackForm.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/admin/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/components/Shells.tsx", import.meta.url), "utf8"),
|
|
]);
|
|
|
|
const db = new DatabaseSync(":memory:");
|
|
db.exec("PRAGMA foreign_keys = ON");
|
|
db.exec(baseMigration.replaceAll("--> statement-breakpoint", ""));
|
|
db.exec(feedbackMigration.replaceAll("--> statement-breakpoint", ""));
|
|
db.prepare(
|
|
`INSERT INTO accounts
|
|
(id, auth_subject, email, display_name, status, created_at, updated_at)
|
|
VALUES ('acct', 'subject', 'beta@example.test', 'Beta', 'active', ?, ?)`,
|
|
).run("2026-08-12T00:00:00.000Z", "2026-08-12T00:00:00.000Z");
|
|
db.prepare(
|
|
`INSERT INTO beta_feedback
|
|
(id, account_id, category, message, status, created_at, updated_at)
|
|
VALUES ('feedback_1', 'acct', 'bug', '连接后页面一直显示离线。', 'open', ?, ?)`,
|
|
).run("2026-08-12T00:00:00.000Z", "2026-08-12T00:00:00.000Z");
|
|
assert.deepEqual(
|
|
{ ...db.prepare("SELECT category, status, admin_response FROM beta_feedback").get() },
|
|
{ category: "bug", status: "open", admin_response: null },
|
|
);
|
|
const indexNames = db
|
|
.prepare("SELECT name FROM sqlite_schema WHERE type = 'index' AND tbl_name = 'beta_feedback'")
|
|
.all()
|
|
.map((row) => row.name);
|
|
assert.ok(indexNames.includes("idx_beta_feedback_account_time"));
|
|
assert.ok(indexNames.includes("idx_beta_feedback_status_time"));
|
|
|
|
assert.match(repository, /feedback:create:\$\{input\.accountId\}/);
|
|
assert.match(repository, /const scope = "feedback:resolve"/);
|
|
assert.match(repository, /feedback\.created/);
|
|
assert.match(repository, /feedback\.resolved/);
|
|
assert.match(userRoute, /getOrCreateAccount/);
|
|
assert.match(userRoute, /createFeedback/);
|
|
assert.match(adminRoute, /viewer\.isAdmin/);
|
|
assert.match(adminRoute, /resolveFeedback/);
|
|
assert.match(page, /我的反馈/);
|
|
assert.match(form, /请勿提交密钥、令牌或会话正文/);
|
|
assert.match(adminPage, /公测反馈处理/);
|
|
assert.match(shell, /\/dashboard\/feedback/);
|
|
});
|
|
|
|
test("publishes audited service incidents and derives the highest active impact", async () => {
|
|
assert.equal(deriveServiceStatus([]), "operational");
|
|
assert.equal(
|
|
deriveServiceStatus([
|
|
{ severity: "maintenance", status: "active" },
|
|
{ severity: "outage", status: "resolved" },
|
|
]),
|
|
"maintenance",
|
|
);
|
|
assert.equal(
|
|
deriveServiceStatus([
|
|
{ severity: "maintenance", status: "active" },
|
|
{ severity: "degraded", status: "active" },
|
|
{ severity: "outage", status: "active" },
|
|
]),
|
|
"outage",
|
|
);
|
|
|
|
const [baseMigration, incidentMigration, bootstrap, repository, publicRoute, adminRoute, statusPage, adminPage, shell] = await Promise.all([
|
|
readFile(new URL("../drizzle/0000_condemned_legion.sql", import.meta.url), "utf8"),
|
|
readFile(new URL("../drizzle/0006_clever_shocker.sql", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/bootstrap.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/status/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/admin/incidents/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/status/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/admin/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/components/Shells.tsx", import.meta.url), "utf8"),
|
|
]);
|
|
|
|
const db = new DatabaseSync(":memory:");
|
|
db.exec(baseMigration.replaceAll("--> statement-breakpoint", ""));
|
|
db.exec(incidentMigration.replaceAll("--> statement-breakpoint", ""));
|
|
db.prepare(
|
|
`INSERT INTO service_incidents
|
|
(id, severity, title, message, status, created_by, started_at, created_at, updated_at)
|
|
VALUES ('incident_1', 'degraded', '中继连接延迟', '部分用户可能需要稍后重新连接。', 'active', 'admin', ?, ?, ?)`,
|
|
).run(
|
|
"2026-08-12T12:00:00.000Z",
|
|
"2026-08-12T12:00:00.000Z",
|
|
"2026-08-12T12:00:00.000Z",
|
|
);
|
|
assert.deepEqual(
|
|
{ ...db.prepare("SELECT severity, status FROM service_incidents").get() },
|
|
{ severity: "degraded", status: "active" },
|
|
);
|
|
assert.ok(
|
|
db
|
|
.prepare("SELECT name FROM sqlite_schema WHERE type = 'index' AND name = 'idx_service_incidents_status_started'")
|
|
.get(),
|
|
);
|
|
|
|
assert.match(bootstrap, /0006_clever_shocker/);
|
|
assert.match(repository, /incident\.created/);
|
|
assert.match(repository, /incident\.resolved/);
|
|
assert.match(repository, /const scope = "incident:create"/);
|
|
assert.match(repository, /const scope = "incident:resolve"/);
|
|
assert.match(publicRoute, /cache-control/);
|
|
const publicStatusQuery = repository.match(
|
|
/export async function getServiceStatusSnapshot[\s\S]*?(?=export async function createServiceIncident)/,
|
|
)?.[0] ?? "";
|
|
assert.doesNotMatch(publicStatusQuery, /SELECT \*/);
|
|
assert.doesNotMatch(publicStatusQuery, /created_by|resolved_by/);
|
|
assert.match(adminRoute, /viewer\.isAdmin/);
|
|
assert.match(adminRoute, /createServiceIncident/);
|
|
assert.match(adminRoute, /resolveServiceIncident/);
|
|
assert.match(statusPage, /当前事件/);
|
|
assert.match(statusPage, /事件记录/);
|
|
assert.match(adminPage, /服务状态与故障公告/);
|
|
assert.match(shell, /service-incident-banner/);
|
|
assert.match(shell, /href="\/status"/);
|
|
});
|
|
|
|
test("exports only account-scoped control-plane data and records revocable deletion requests", async () => {
|
|
const [baseMigration, lifecycleMigration, bootstrap, repository, exportRoute, deletionRoute, securityPage, lifecycleAction, adminPage] = await Promise.all([
|
|
readFile(new URL("../drizzle/0000_condemned_legion.sql", import.meta.url), "utf8"),
|
|
readFile(new URL("../drizzle/0007_zippy_nomad.sql", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/bootstrap.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/account/export/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/account/deletion/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/security/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/security/AccountLifecycleActions.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/admin/page.tsx", import.meta.url), "utf8"),
|
|
]);
|
|
|
|
const db = new DatabaseSync(":memory:");
|
|
db.exec("PRAGMA foreign_keys = ON");
|
|
db.exec(baseMigration.replaceAll("--> statement-breakpoint", ""));
|
|
db.exec(lifecycleMigration.replaceAll("--> statement-breakpoint", ""));
|
|
const now = "2026-08-12T15:00:00.000Z";
|
|
db.prepare(
|
|
`INSERT INTO accounts
|
|
(id, auth_subject, email, display_name, status, created_at, updated_at)
|
|
VALUES ('acct', 'subject', 'owner@example.test', 'Owner', 'active', ?, ?)`,
|
|
).run(now, now);
|
|
db.prepare(
|
|
`INSERT INTO account_deletion_requests
|
|
(id, account_id, status, reason, requested_at, created_at, updated_at)
|
|
VALUES ('deletion_1', 'acct', 'requested', '暂时离开公测', ?, ?, ?)`,
|
|
).run(now, now, now);
|
|
assert.throws(() =>
|
|
db.prepare(
|
|
`INSERT INTO account_deletion_requests
|
|
(id, account_id, status, requested_at, created_at, updated_at)
|
|
VALUES ('deletion_2', 'acct', 'requested', ?, ?, ?)`,
|
|
).run(now, now, now),
|
|
);
|
|
db.prepare(
|
|
`UPDATE account_deletion_requests
|
|
SET status = 'cancelled', cancelled_at = ?, updated_at = ?
|
|
WHERE id = 'deletion_1'`,
|
|
).run(now, now);
|
|
db.prepare(
|
|
`INSERT INTO account_deletion_requests
|
|
(id, account_id, status, requested_at, created_at, updated_at)
|
|
VALUES ('deletion_2', 'acct', 'requested', ?, ?, ?)`,
|
|
).run(now, now, now);
|
|
assert.equal(
|
|
db.prepare(
|
|
"SELECT COUNT(*) AS count FROM account_deletion_requests WHERE account_id = 'acct' AND status = 'requested'",
|
|
).get().count,
|
|
1,
|
|
);
|
|
|
|
assert.match(bootstrap, /0007_zippy_nomad/);
|
|
assert.match(repository, /account\.deletion_requested/);
|
|
assert.match(repository, /account\.deletion_cancelled/);
|
|
assert.match(repository, /account:deletion:request:\$\{input\.accountId\}/);
|
|
assert.match(repository, /const scope = "account:deletion:cancel"/);
|
|
const exportFunction = repository.match(
|
|
/export async function getAccountControlPlaneExport[\s\S]*?(?=export async function runRetentionMaintenance)/,
|
|
)?.[0] ?? "";
|
|
assert.match(exportFunction, /WHERE account_id = \?/);
|
|
assert.doesNotMatch(
|
|
exportFunction,
|
|
/FROM device_credentials|FROM audit_events|FROM idempotency_records|token_hash|code_hash|lease_token_hash|secret_bundle_ref|runtime_ref|error_detail/,
|
|
);
|
|
assert.match(exportRoute, /getCloudViewer/);
|
|
assert.match(exportRoute, /content-disposition/);
|
|
assert.match(exportRoute, /cache-control/);
|
|
assert.match(deletionRoute, /readJsonMutation/);
|
|
assert.match(deletionRoute, /requestAccountDeletion/);
|
|
assert.match(deletionRoute, /cancelAccountDeletion/);
|
|
assert.match(securityPage, /\/api\/account\/export/);
|
|
assert.doesNotMatch(securityPage, /导出流程待接入|保留策略待决定/);
|
|
assert.match(lifecycleAction, /提交注销申请/);
|
|
assert.match(lifecycleAction, /撤回注销申请/);
|
|
assert.match(adminPage, /注销申请队列/);
|
|
});
|
|
|
|
test("bounds every JSON mutation and validates admin-controlled public links", async () => {
|
|
const routePaths = [
|
|
"../app/api/admin/beta/route.ts",
|
|
"../app/api/admin/exemptions/route.ts",
|
|
"../app/api/admin/launch-gates/route.ts",
|
|
"../app/api/admin/prices/route.ts",
|
|
"../app/api/admin/relay-migrations/route.ts",
|
|
"../app/api/admin/relay-purges/route.ts",
|
|
"../app/api/billing/quotes/route.ts",
|
|
"../app/api/hosts/pairing/route.ts",
|
|
"../app/api/hosts/revoke/route.ts",
|
|
"../app/api/internal/relay/register-device/route.ts",
|
|
"../app/api/internal/relay/authorize-device/route.ts",
|
|
"../app/api/internal/relay/authorization-delta/route.ts",
|
|
"../app/api/internal/relay/heartbeat/route.ts",
|
|
"../app/api/internal/relay/migrations/advance/route.ts",
|
|
"../app/api/internal/relay/purges/advance/route.ts",
|
|
"../app/api/internal/relay/resolve-device-route/route.ts",
|
|
"../app/api/internal/relay/resolve-phone-route/route.ts",
|
|
"../app/api/internal/relay/resolve-tenant-route/route.ts",
|
|
"../app/api/internal/relay/resolve-handoff-route/route.ts",
|
|
"../app/api/feedback/route.ts",
|
|
"../app/api/admin/feedback/route.ts",
|
|
"../app/api/admin/incidents/route.ts",
|
|
"../app/api/admin/retention/route.ts",
|
|
"../app/api/account/deletion/route.ts",
|
|
];
|
|
const [guard, repository, ...routes] = await Promise.all([
|
|
readFile(new URL("../app/api/respond.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
...routePaths.map((path) => readFile(new URL(path, import.meta.url), "utf8")),
|
|
]);
|
|
assert.match(guard, /application\/json/);
|
|
assert.match(guard, /sec-fetch-site/);
|
|
assert.match(guard, /32_768/);
|
|
for (const route of routes) assert.match(route, /readJsonMutation/);
|
|
assert.match(repository, /invalid_gate_status/);
|
|
assert.match(repository, /invalid_evidence_url/);
|
|
assert.match(repository, /protocol !== "https:"/);
|
|
assert.match(repository, /pairing_limit_reached/);
|
|
});
|
|
|
|
test("keeps tenant and pairing identifiers collision resistant", async () => {
|
|
const [repository, bootstrap, launchGates, pairingRoute] = await Promise.all([
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/bootstrap.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/launch-gates.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/hosts/pairing/route.ts", import.meta.url), "utf8"),
|
|
]);
|
|
assert.match(repository, /const slug = `n-\$\{identityHash\}`/);
|
|
assert.doesNotMatch(repository, /accountId\.slice\(-8\)/);
|
|
assert.match(repository, /getRandomValues\(new Uint8Array\(10\)\)/);
|
|
assert.doesNotMatch(repository, /slice\(0,\s*8\)/);
|
|
assert.match(launchGates, /pairing-claim-security/);
|
|
assert.match(bootstrap, /0001_mushy_vance_astro/);
|
|
assert.match(bootstrap, /0002_wild_ravenous/);
|
|
assert.match(bootstrap, /0005_pale_corsair/);
|
|
assert.match(bootstrap, /9002_ready_credential_reconciliation/);
|
|
assert.match(bootstrap, /cloud_schema_migrations/);
|
|
assert.match(bootstrap, /if \(!claimMigration\)/);
|
|
assert.match(bootstrap, /catch \(error\)[\s\S]*racedMigration/);
|
|
assert.match(pairingRoute, /cache-control.*no-store/);
|
|
});
|
|
|
|
test("accepts the real daemon identity shape and rejects fingerprint substitution", async () => {
|
|
const edBytes = Uint8Array.from({ length: 32 }, (_, index) => index + 1);
|
|
const xBytes = Uint8Array.from({ length: 32 }, (_, index) => 255 - index);
|
|
const base64url = (bytes) => Buffer.from(bytes).toString("base64url");
|
|
const fingerprint = await sha256Hex(Uint8Array.from([...edBytes, ...xBytes]));
|
|
assert.deepEqual(
|
|
await validateDeviceIdentity({
|
|
ed25519Public: base64url(edBytes),
|
|
x25519Public: base64url(xBytes),
|
|
identityFingerprint: fingerprint.toUpperCase(),
|
|
}),
|
|
{
|
|
ed25519Public: base64url(edBytes),
|
|
x25519Public: base64url(xBytes),
|
|
fingerprint,
|
|
},
|
|
);
|
|
await assert.rejects(
|
|
validateDeviceIdentity({
|
|
ed25519Public: base64url(edBytes),
|
|
x25519Public: base64url(xBytes),
|
|
identityFingerprint: "0".repeat(64),
|
|
}),
|
|
/invalid_identity_fingerprint/,
|
|
);
|
|
});
|
|
|
|
test("verifies a cross-language daemon proof before recovering a host record", async () => {
|
|
const vector = {
|
|
bootstrapToken: " pair_0123456789abcdef0123456789abcdef.ABCDEF0123456789ABCD ",
|
|
os: " Windows ",
|
|
ed25519Public: "ed-public",
|
|
x25519Public: "x-public",
|
|
identityFingerprint: "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789",
|
|
transportMode: " sealed ",
|
|
};
|
|
assert.equal(
|
|
Buffer.from(deviceRegistrationProofTranscript(vector)).toString("hex"),
|
|
"6e656b6f6e6573742d636c6f75642f6465766963652d726567697374726174696f6e2d70726f6f662f76310000003a706169725f30313233343536373839616263646566303132333435363738396162636465662e41424344454630313233343536373839414243440000000777696e646f77730000000965642d7075626c696300000008782d7075626c69630000004061626364656630313233343536373839616263646566303132333435363738396162636465663031323334353637383961626364656630313233343536373839000000067365616c6564",
|
|
);
|
|
|
|
const keyPair = await crypto.subtle.generateKey(
|
|
{ name: "Ed25519" },
|
|
true,
|
|
["sign", "verify"],
|
|
);
|
|
const ed25519Public = Buffer.from(
|
|
await crypto.subtle.exportKey("raw", keyPair.publicKey),
|
|
).toString("base64url");
|
|
const x25519Public = Buffer.alloc(32, 7).toString("base64url");
|
|
const identityFingerprint = await sha256Hex(
|
|
Uint8Array.from([
|
|
...Buffer.from(ed25519Public, "base64url"),
|
|
...Buffer.from(x25519Public, "base64url"),
|
|
]),
|
|
);
|
|
const proofInput = {
|
|
bootstrapToken: `pair_${"a".repeat(32)}.ABCDEF0123456789ABCD`,
|
|
os: "windows",
|
|
ed25519Public,
|
|
x25519Public,
|
|
identityFingerprint,
|
|
transportMode: "sealed",
|
|
};
|
|
const signature = Buffer.from(
|
|
await crypto.subtle.sign(
|
|
{ name: "Ed25519" },
|
|
keyPair.privateKey,
|
|
deviceRegistrationProofTranscript(proofInput),
|
|
),
|
|
).toString("base64url");
|
|
assert.equal(
|
|
await verifyDeviceRegistrationProof({
|
|
...proofInput,
|
|
registrationProof: signature,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
await verifyDeviceRegistrationProof({
|
|
...proofInput,
|
|
bootstrapToken: `pair_${"b".repeat(32)}.ABCDEF0123456789ABCD`,
|
|
registrationProof: signature,
|
|
}),
|
|
false,
|
|
);
|
|
|
|
const [repository, route, hostsPage, newHostPage, pairingForm] = await Promise.all([
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/internal/relay/register-device/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/hosts/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/hosts/new/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/hosts/new/PairingForm.tsx", import.meta.url), "utf8"),
|
|
]);
|
|
assert.match(repository, /existingIdentityHost \|\| input\.registrationProof\.trim\(\)/);
|
|
assert.match(repository, /host\.recovered/);
|
|
assert.match(route, /registration_proof/);
|
|
assert.match(hostsPage, /identity\.json 还在/);
|
|
assert.match(hostsPage, /身份文件已丢失/);
|
|
assert.match(newHostPage, /只有公开指纹不够/);
|
|
assert.match(pairingForm, /恢复原记录需要最新版 daemon/);
|
|
});
|
|
|
|
test("normalizes only the documented bootstrap shape and ignores spoofable proxy headers", () => {
|
|
const pairingId = `pair_${"a".repeat(32)}`;
|
|
assert.deepEqual(parseBootstrapToken(` ${pairingId}.abcdef1234567890abcd `), {
|
|
pairingId,
|
|
code: "ABCDEF1234567890ABCD",
|
|
});
|
|
assert.equal(normalizePairingCode(" abcdEF1234567890abcd "), "ABCDEF1234567890ABCD");
|
|
assert.throws(() => parseBootstrapToken(`${pairingId}.ABC.DEF`), /invalid_bootstrap_token/);
|
|
assert.equal(constantTimeEqualHex("aabb", "AABB"), true);
|
|
const direct = new Request("https://cloud.example/api/devices/register", {
|
|
headers: { "cf-connecting-ip": "203.0.113.7", "x-forwarded-for": "198.51.100.9" },
|
|
});
|
|
assert.equal(requestSource(direct, true), "203.0.113.7");
|
|
const spoofOnly = new Request("https://cloud.example/api/devices/register", {
|
|
headers: { "x-forwarded-for": "198.51.100.9" },
|
|
});
|
|
assert.throws(() => requestSource(spoofOnly, true), /trusted_source_unavailable/);
|
|
assert.equal(requestSource(spoofOnly, false), "local-development");
|
|
assert.equal(
|
|
rateWindowStart(new Date("2026-08-12T09:19:59.999Z")),
|
|
"2026-08-12T09:10:00.000Z",
|
|
);
|
|
});
|
|
|
|
test("atomically spends claim budgets and burns a successful pairing", async () => {
|
|
const db = new DatabaseSync(":memory:");
|
|
const [baseMigration, claimMigration, claimOwnershipMigration] = await Promise.all([
|
|
readFile(new URL("../drizzle/0000_condemned_legion.sql", import.meta.url), "utf8"),
|
|
readFile(new URL("../drizzle/0001_mushy_vance_astro.sql", import.meta.url), "utf8"),
|
|
readFile(new URL("../drizzle/0002_wild_ravenous.sql", import.meta.url), "utf8"),
|
|
]);
|
|
db.exec(baseMigration.replaceAll("--> statement-breakpoint", ""));
|
|
const now = "2026-08-12T09:10:00.000Z";
|
|
const expiry = "2026-08-12T09:20:00.000Z";
|
|
db.prepare(
|
|
`INSERT INTO accounts
|
|
(id, auth_subject, email, display_name, status, created_at, updated_at)
|
|
VALUES ('acct', 'subject', 'a@example.test', 'A', 'active', ?, ?)`,
|
|
).run(now, now);
|
|
db.exec(claimMigration.replaceAll("--> statement-breakpoint", ""));
|
|
db.exec(claimOwnershipMigration.replaceAll("--> statement-breakpoint", ""));
|
|
assert.equal(db.prepare("SELECT email FROM accounts WHERE id = 'acct'").get().email, "a@example.test");
|
|
db.prepare(
|
|
`INSERT INTO entitlement_grants
|
|
(id, account_id, source, capacity_slots, starts_at, state, reason, created_by)
|
|
VALUES ('grant_claim_test', 'acct', 'manual_exemption', NULL, ?, 'active',
|
|
'claim fixture invitation', 'test')`,
|
|
).run(now);
|
|
|
|
const rate = db.prepare(CONSUME_CLAIM_RATE_SQL);
|
|
const rateChanges = Array.from({ length: 21 }, () =>
|
|
Number(rate.run("source", now, now).changes),
|
|
);
|
|
assert.deepEqual(rateChanges, [...Array(20).fill(1), 0]);
|
|
|
|
db.prepare(
|
|
`INSERT INTO accounts
|
|
(id, auth_subject, email, display_name, status, created_at, updated_at)
|
|
VALUES ('acct_public', 'subject_public', 'public@example.test', 'Public', 'active', ?, ?)`,
|
|
).run(now, now);
|
|
db.prepare(
|
|
`INSERT INTO beta_programs
|
|
(id, state, capacity_slots, starts_at, ends_at, grace_days, created_by, created_at)
|
|
VALUES ('beta_claim_gate', 'active', NULL, ?, NULL, 7, 'test', ?)`,
|
|
).run(now, now);
|
|
const gatedPairingId = `pair_${"0".repeat(32)}`;
|
|
db.prepare(
|
|
`INSERT INTO pairing_requests
|
|
(id, account_id, requested_name, os, code_hash, status, expires_at, created_at)
|
|
VALUES (?, 'acct_public', 'Gated public host', 'linux', 'gated-hash', 'waiting', ?, ?)`,
|
|
).run(gatedPairingId, expiry, now);
|
|
assert.equal(
|
|
Number(db.prepare(CLAIM_HOST_SQL).run(
|
|
`host_${"0".repeat(32)}`,
|
|
"ed-public",
|
|
"x-public",
|
|
"public-fingerprint",
|
|
now,
|
|
now,
|
|
gatedPairingId,
|
|
"gated-hash",
|
|
now,
|
|
"linux",
|
|
now,
|
|
now,
|
|
now,
|
|
now,
|
|
null,
|
|
).changes),
|
|
0,
|
|
);
|
|
|
|
db.prepare(
|
|
`INSERT INTO pairing_requests
|
|
(id, account_id, requested_name, os, code_hash, status, expires_at, created_at)
|
|
VALUES ('pair_${"1".repeat(32)}', 'acct', 'Workstation', 'windows',
|
|
'good-hash', 'waiting', ?, ?)`,
|
|
).run(expiry, now);
|
|
const failed = db.prepare(RECORD_FAILED_CODE_SQL);
|
|
const failedChanges = Array.from({ length: 6 }, () =>
|
|
Number(failed.run(now, `pair_${"1".repeat(32)}`).changes),
|
|
);
|
|
assert.deepEqual(failedChanges, [1, 1, 1, 1, 1, 0]);
|
|
const locked = db.prepare(
|
|
"SELECT status, failed_attempts FROM pairing_requests WHERE id = ?",
|
|
).get(`pair_${"1".repeat(32)}`);
|
|
assert.equal(locked.status, "locked");
|
|
assert.equal(locked.failed_attempts, 5);
|
|
|
|
const pairingId = `pair_${"2".repeat(32)}`;
|
|
const hostId = `host_${"2".repeat(32)}`;
|
|
const credentialId = `credential_${"2".repeat(32)}`;
|
|
db.prepare(
|
|
`INSERT INTO pairing_requests
|
|
(id, account_id, requested_name, os, code_hash, status, expires_at, created_at)
|
|
VALUES (?, 'acct', 'Laptop', 'linux', 'claim-hash', 'waiting', ?, ?)`,
|
|
).run(pairingId, expiry, now);
|
|
const host = db.prepare(CLAIM_HOST_SQL);
|
|
const credential = db.prepare(CLAIM_CREDENTIAL_SQL);
|
|
const commit = db.prepare(COMMIT_PAIRING_CLAIM_SQL);
|
|
db.exec("BEGIN IMMEDIATE");
|
|
const first = [
|
|
Number(host.run(hostId, "ed", "x", "fingerprint", now, now, pairingId, "claim-hash", now, "linux", now, now, now, now, "0.2.6").changes),
|
|
Number(credential.run(credentialId, hostId, "token-hash", now, now, pairingId, "claim-hash", now, "linux", now, now, now, now, hostId, "fingerprint").changes),
|
|
Number(commit.run(hostId, now, now, "spent-1", pairingId, "claim-hash", now, "linux", now, now, now, now, credentialId, hostId).changes),
|
|
];
|
|
db.exec("COMMIT");
|
|
assert.deepEqual(first, [1, 1, 1]);
|
|
assert.equal(db.prepare("SELECT COUNT(*) AS count FROM hosts WHERE id = ?").get(hostId).count, 1);
|
|
assert.equal(db.prepare("SELECT daemon_version FROM hosts WHERE id = ?").get(hostId).daemon_version, "0.2.6");
|
|
assert.equal(db.prepare("SELECT COUNT(*) AS count FROM device_credentials WHERE host_id = ?").get(hostId).count, 1);
|
|
assert.deepEqual(
|
|
{ ...db.prepare("SELECT status, code_hash FROM pairing_requests WHERE id = ?").get(pairingId) },
|
|
{ status: "claimed", code_hash: "spent-1" },
|
|
);
|
|
const replay = [
|
|
Number(host.run(hostId, "ed", "x", "fingerprint", now, now, pairingId, "claim-hash", now, "linux", now, now, now, now, null).changes),
|
|
Number(credential.run(credentialId, hostId, "another-token", now, now, pairingId, "claim-hash", now, "linux", now, now, now, now, hostId, "fingerprint").changes),
|
|
Number(commit.run(hostId, now, now, "spent-replay", pairingId, "claim-hash", now, "linux", now, now, now, now, credentialId, hostId).changes),
|
|
];
|
|
assert.deepEqual(replay, [0, 0, 0]);
|
|
|
|
db.prepare(
|
|
"UPDATE hosts SET lifecycle = 'deactivated', slot_state = 'released', deactivated_at = ? WHERE id = ?",
|
|
).run(now, hostId);
|
|
db.prepare(
|
|
"UPDATE device_credentials SET status = 'revoked', revoked_at = ? WHERE id = ?",
|
|
).run(now, credentialId);
|
|
const reclaimPairingId = `pair_${"3".repeat(32)}`;
|
|
const reclaimCredentialId = `credential_${"3".repeat(32)}`;
|
|
db.prepare(
|
|
`INSERT INTO pairing_requests
|
|
(id, account_id, requested_name, os, code_hash, status, expires_at, created_at)
|
|
VALUES (?, 'acct', 'Reclaimed laptop', 'linux', 'reclaim-hash', 'waiting', ?, ?)`,
|
|
).run(reclaimPairingId, expiry, now);
|
|
db.exec("BEGIN IMMEDIATE");
|
|
const reclaimed = [
|
|
Number(host.run(`host_${"3".repeat(32)}`, "ed", "x", "fingerprint", now, now, reclaimPairingId, "reclaim-hash", now, "linux", now, now, now, now, null).changes),
|
|
Number(credential.run(reclaimCredentialId, hostId, "new-token-hash", now, now, reclaimPairingId, "reclaim-hash", now, "linux", now, now, now, now, hostId, "fingerprint").changes),
|
|
Number(commit.run(hostId, now, now, "spent-2", reclaimPairingId, "reclaim-hash", now, "linux", now, now, now, now, reclaimCredentialId, hostId).changes),
|
|
];
|
|
db.exec("COMMIT");
|
|
assert.deepEqual(reclaimed, [1, 1, 1]);
|
|
assert.equal(db.prepare("SELECT COUNT(*) AS count FROM hosts WHERE identity_fingerprint = ?").get("fingerprint").count, 1);
|
|
assert.equal(db.prepare("SELECT name FROM hosts WHERE id = ?").get(hostId).name, "Reclaimed laptop");
|
|
assert.equal(db.prepare("SELECT daemon_version FROM hosts WHERE id = ?").get(hostId).daemon_version, "0.2.6");
|
|
assert.equal(db.prepare("SELECT COUNT(*) AS count FROM device_credentials WHERE host_id = ?").get(hostId).count, 2);
|
|
|
|
db.prepare(
|
|
"UPDATE hosts SET lifecycle = 'deactivated', slot_state = 'released', deactivated_at = ? WHERE id = ?",
|
|
).run(now, hostId);
|
|
db.prepare(
|
|
"UPDATE device_credentials SET status = 'revoked', revoked_at = ? WHERE host_id = ? AND status = 'active'",
|
|
).run(now, hostId);
|
|
const competingPairs = ["4", "5"].map((digit) => ({
|
|
pairingId: `pair_${digit.repeat(32)}`,
|
|
credentialId: `credential_${digit.repeat(32)}`,
|
|
hash: `competing-${digit}`,
|
|
}));
|
|
for (const candidate of competingPairs) {
|
|
db.prepare(
|
|
`INSERT INTO pairing_requests
|
|
(id, account_id, requested_name, os, code_hash, status, expires_at, created_at)
|
|
VALUES (?, 'acct', ?, 'linux', ?, 'waiting', ?, ?)`,
|
|
).run(candidate.pairingId, `Competing ${candidate.hash}`, candidate.hash, expiry, now);
|
|
}
|
|
const [winnerCandidate, loserCandidate] = competingPairs;
|
|
const winnerClaim = [
|
|
Number(host.run(`host_${"4".repeat(32)}`, "ed", "x", "fingerprint", now, now, winnerCandidate.pairingId, winnerCandidate.hash, now, "linux", now, now, now, now, null).changes),
|
|
Number(credential.run(winnerCandidate.credentialId, hostId, "winner-token", now, now, winnerCandidate.pairingId, winnerCandidate.hash, now, "linux", now, now, now, now, hostId, "fingerprint").changes),
|
|
Number(commit.run(hostId, now, now, "spent-3", winnerCandidate.pairingId, winnerCandidate.hash, now, "linux", now, now, now, now, winnerCandidate.credentialId, hostId).changes),
|
|
];
|
|
const loserClaim = [
|
|
Number(host.run(`host_${"5".repeat(32)}`, "ed", "x", "fingerprint", now, now, loserCandidate.pairingId, loserCandidate.hash, now, "linux", now, now, now, now, null).changes),
|
|
Number(credential.run(loserCandidate.credentialId, hostId, "loser-token", now, now, loserCandidate.pairingId, loserCandidate.hash, now, "linux", now, now, now, now, hostId, "fingerprint").changes),
|
|
Number(commit.run(hostId, now, now, "spent-4", loserCandidate.pairingId, loserCandidate.hash, now, "linux", now, now, now, now, loserCandidate.credentialId, hostId).changes),
|
|
];
|
|
assert.deepEqual(winnerClaim, [1, 1, 1]);
|
|
assert.deepEqual(loserClaim, [0, 0, 0]);
|
|
assert.equal(db.prepare("SELECT status FROM pairing_requests WHERE id = ?").get(loserCandidate.pairingId).status, "waiting");
|
|
assert.equal(db.prepare("SELECT COUNT(*) AS count FROM device_credentials WHERE id = ?").get(loserCandidate.credentialId).count, 0);
|
|
db.close();
|
|
});
|
|
|
|
test("lets only the owning account cancel an unclaimed pairing and invalidates its code", async () => {
|
|
const db = new DatabaseSync(":memory:");
|
|
db.exec(`
|
|
CREATE TABLE pairing_requests (
|
|
id TEXT PRIMARY KEY,
|
|
account_id TEXT NOT NULL,
|
|
code_hash TEXT NOT NULL UNIQUE,
|
|
status TEXT NOT NULL,
|
|
expires_at TEXT NOT NULL
|
|
);
|
|
INSERT INTO pairing_requests VALUES
|
|
('pair_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'acct_a', 'hash-a', 'waiting', '2026-08-12T10:10:00.000Z'),
|
|
('pair_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'acct_b', 'hash-b', 'waiting', '2026-08-12T10:10:00.000Z'),
|
|
('pair_cccccccccccccccccccccccccccccccc', 'acct_a', 'hash-c', 'claimed', '2026-08-12T10:10:00.000Z');
|
|
`);
|
|
const cancel = db.prepare(CANCEL_PAIRING_SQL);
|
|
assert.equal(
|
|
Number(cancel.run("pair_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "acct_b", "tombstone-x").changes),
|
|
0,
|
|
);
|
|
assert.equal(
|
|
Number(cancel.run("pair_cccccccccccccccccccccccccccccccc", "acct_a", "tombstone-y").changes),
|
|
0,
|
|
);
|
|
assert.equal(
|
|
Number(cancel.run("pair_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "acct_a", "tombstone-a").changes),
|
|
1,
|
|
);
|
|
assert.deepEqual(
|
|
{ ...db.prepare("SELECT status, code_hash FROM pairing_requests WHERE id = ?").get("pair_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") },
|
|
{ status: "cancelled", code_hash: "tombstone-a" },
|
|
);
|
|
assert.equal(
|
|
Number(cancel.run("pair_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "acct_a", "tombstone-z").changes),
|
|
0,
|
|
);
|
|
assert.equal(
|
|
db.prepare("SELECT COUNT(*) AS count FROM pairing_requests WHERE account_id = 'acct_a' AND status = 'waiting'").get().count,
|
|
0,
|
|
);
|
|
db.close();
|
|
|
|
const [repository, route, button, hostsPage, pairingForm, stateModel] =
|
|
await Promise.all([
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/hosts/pairing/cancel/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/hosts/PairingCancelButton.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/hosts/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/hosts/new/PairingForm.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../docs/state-model.md", import.meta.url), "utf8"),
|
|
]);
|
|
const cancellation = repository.slice(
|
|
repository.indexOf("export async function cancelPairingRequest"),
|
|
repository.indexOf("function pairingClaimSecret"),
|
|
);
|
|
assert.match(cancellation, /WHERE id = \? AND account_id = \?/);
|
|
assert.match(cancellation, /pairing:cancel:\$\{input\.accountId\}/);
|
|
assert.match(cancellation, /'pairing\.cancelled'/);
|
|
assert.match(cancellation, /code_hash = \?/);
|
|
assert.doesNotMatch(cancellation, /bootstrapToken|rawCode/);
|
|
assert.match(route, /getCloudViewer/);
|
|
assert.match(route, /readJsonMutation/);
|
|
assert.match(route, /cache-control/);
|
|
assert.match(button, /最终状态以主机列表为准/);
|
|
assert.match(button, /\/api\/hosts\/pairing\/cancel/);
|
|
assert.match(hostsPage, /PairingCancelButton pairingId=\{pairing\.id\}/);
|
|
assert.match(pairingForm, /onCancelled/);
|
|
assert.match(stateModel, /若 daemon 已先认领,则取消失败/);
|
|
});
|
|
|
|
test("targets free exemptions by immutable account id", async () => {
|
|
const [repository, route, action] = await Promise.all([
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/admin/exemptions/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/admin/AdminActions.tsx", import.meta.url), "utf8"),
|
|
]);
|
|
assert.match(repository, /SELECT \* FROM accounts WHERE id = \?/);
|
|
assert.match(repository, /invalid_account_id/);
|
|
assert.match(route, /accountId/);
|
|
assert.match(action, /accountId/);
|
|
assert.match(action, /邮箱只用于核对/);
|
|
assert.doesNotMatch(`${repository}\n${route}\n${action}`, /accountEmail|lower\(email\)/);
|
|
});
|
|
|
|
test("reserves pairing capacity and the pending budget in one SQLite statement", () => {
|
|
const db = new DatabaseSync(":memory:");
|
|
db.exec(`
|
|
CREATE TABLE beta_programs (
|
|
id TEXT PRIMARY KEY, state TEXT NOT NULL, starts_at TEXT NOT NULL,
|
|
ends_at TEXT, capacity_slots INTEGER, created_at TEXT NOT NULL
|
|
);
|
|
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
|
|
);
|
|
CREATE TABLE launch_gates (
|
|
key TEXT PRIMARY KEY, priority TEXT NOT NULL, category TEXT NOT NULL,
|
|
title TEXT NOT NULL, status TEXT NOT NULL, owner TEXT, evidence_url TEXT,
|
|
notes TEXT NOT NULL, reviewed_at TEXT, updated_at TEXT NOT NULL
|
|
);
|
|
`);
|
|
const now = "2026-08-11T00:00:00.000Z";
|
|
const expiry = "2026-08-11T00:10:00.000Z";
|
|
const insertGate = db.prepare(
|
|
`INSERT INTO launch_gates
|
|
(key, priority, category, title, status, owner, evidence_url, notes, updated_at)
|
|
VALUES (?, 'P0', 'test', ?, 'passed', 'test owner', 'https://evidence.example.test/p0',
|
|
'verified fixture', ?)`,
|
|
);
|
|
for (const key of REQUIRED_PUBLIC_BETA_P0_KEYS) insertGate.run(key, key, now);
|
|
const reserve = db.prepare(RESERVE_PAIRING_SQL);
|
|
db.prepare(
|
|
"INSERT INTO beta_programs VALUES ('beta_old', 'active', ?, NULL, 10, '2026-08-10T00:00:00.000Z')",
|
|
).run(now);
|
|
db.prepare(
|
|
"INSERT INTO beta_programs VALUES ('beta_new', 'active', ?, NULL, 1, '2026-08-11T00:00:00.000Z')",
|
|
).run(now);
|
|
assert.equal(
|
|
Number(reserve.run("pair_1", "acct_a", "host 1", "linux", "hash_1", expiry, now).changes),
|
|
1,
|
|
);
|
|
assert.equal(
|
|
Number(reserve.run("pair_2", "acct_a", "host 2", "linux", "hash_2", expiry, now).changes),
|
|
0,
|
|
);
|
|
|
|
db.exec("DELETE FROM pairing_requests; DELETE FROM beta_programs;");
|
|
db.prepare(
|
|
"INSERT INTO beta_programs VALUES ('beta_unlimited', 'active', ?, NULL, NULL, '2026-08-11T00:00:00.000Z')",
|
|
).run(now);
|
|
const changes = Array.from({ length: 6 }, (_, index) =>
|
|
Number(
|
|
reserve.run(
|
|
`pair_${index + 10}`,
|
|
"acct_b",
|
|
`host ${index}`,
|
|
"windows",
|
|
`hash_${index + 10}`,
|
|
expiry,
|
|
now,
|
|
).changes,
|
|
),
|
|
);
|
|
assert.deepEqual(changes, [1, 1, 1, 1, 1, 0]);
|
|
|
|
db.exec("DELETE FROM pairing_requests; DELETE FROM beta_programs;");
|
|
db.prepare(
|
|
"INSERT INTO beta_programs VALUES ('beta_gated', 'active', ?, NULL, NULL, '2026-08-11T00:00:00.000Z')",
|
|
).run(now);
|
|
db.prepare("UPDATE launch_gates SET status = 'blocked' WHERE key = ?").run(
|
|
REQUIRED_PUBLIC_BETA_P0_KEYS[0],
|
|
);
|
|
assert.equal(
|
|
Number(reserve.run("pair_gated", "acct_invited", "gated host", "linux", "hash_gated", expiry, now).changes),
|
|
0,
|
|
);
|
|
db.prepare(
|
|
`INSERT INTO entitlement_grants
|
|
(account_id, state, starts_at, ends_at, revoked_at, capacity_slots)
|
|
VALUES ('acct_invited', 'active', ?, NULL, NULL, 1)`,
|
|
).run(now);
|
|
assert.equal(
|
|
Number(reserve.run("pair_invited", "acct_invited", "invited host", "linux", "hash_invited", expiry, now).changes),
|
|
1,
|
|
);
|
|
db.close();
|
|
});
|
|
|
|
test("fails the public beta gate closed when required P0 evidence is missing", () => {
|
|
assert.equal(countBlockedPublicBetaP0([]), REQUIRED_PUBLIC_BETA_P0_KEYS.length);
|
|
const complete = REQUIRED_PUBLIC_BETA_P0_KEYS.map((key) => ({
|
|
key,
|
|
priority: "P0",
|
|
status: "passed",
|
|
owner: "test owner",
|
|
notes: "verified fixture",
|
|
evidence_url: `https://evidence.example.test/${key}`,
|
|
}));
|
|
assert.equal(countBlockedPublicBetaP0(complete), 0);
|
|
assert.equal(countBlockedPublicBetaP0(complete.slice(1)), 1);
|
|
assert.equal(
|
|
countBlockedPublicBetaP0(complete.map((gate, index) => index ? gate : { ...gate, evidence_url: null })),
|
|
1,
|
|
);
|
|
});
|
|
|
|
test("changes all public beta claims when the active policy ends", async () => {
|
|
const active = getPublicBetaPresentation(true);
|
|
const ended = getPublicBetaPresentation(false);
|
|
assert.equal(active.priceValue, "¥0");
|
|
assert.equal(active.cardStatus, "当前有效");
|
|
assert.equal(ended.priceValue, "已结束");
|
|
assert.match(ended.subline, /不会自动扣款/);
|
|
assert.match(ended.comparison, /收费入口未开放/);
|
|
assert.equal(getBillingEntitlementPresentation("public_beta").title, "当前应付 ¥0");
|
|
assert.equal(getBillingEntitlementPresentation("grant").status, "闭测邀请");
|
|
assert.equal(getBillingEntitlementPresentation("none").title, "当前无免费权益");
|
|
assert.equal(
|
|
getBillingEntitlementPresentation("none", "gated").status,
|
|
"公开接入冻结",
|
|
);
|
|
|
|
const [home, pricing, shell, billing] = await Promise.all([
|
|
readFile(new URL("../app/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/pricing/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/components/Shells.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/billing/page.tsx", import.meta.url), "utf8"),
|
|
]);
|
|
assert.match(home, /getPublicBetaPresentation\(betaActive\)/);
|
|
assert.match(pricing, /getPublicBetaPresentation\(betaActive\)/);
|
|
assert.match(shell, /beta \? "公测免费" : "公测已结束"/);
|
|
assert.match(
|
|
billing,
|
|
/getBillingEntitlementPresentation\([\s\S]*snapshot\.entitlement\.mode,[\s\S]*snapshot\.entitlement\.publicBetaState/,
|
|
);
|
|
});
|
|
|
|
test("does not publish a future price promise in user-facing beta surfaces", async () => {
|
|
const paths = [
|
|
"../app/page.tsx",
|
|
"../app/pricing/page.tsx",
|
|
"../app/dashboard/billing/page.tsx",
|
|
"../README.md",
|
|
"../docs/commercial-contract.md",
|
|
];
|
|
const surfaces = (await Promise.all(
|
|
paths.map((path) => readFile(new URL(path, import.meta.url), "utf8")),
|
|
)).join("\n");
|
|
assert.doesNotMatch(surfaces, /¥\s*10|¥\s*100|未来(?:月付|年付)目录价/);
|
|
assert.match(surfaces, /收费.*以后再/);
|
|
assert.match(surfaces, /不(?:生成|创建)报价/);
|
|
});
|
|
|
|
test("keeps the persisted gate catalog complete and requires proof to unblock", async () => {
|
|
const [bootstrap, repository, gateCatalog, launchGates] = await Promise.all([
|
|
readFile(new URL("../db/bootstrap.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../db/launch-gates.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../docs/launch-gates.md", import.meta.url), "utf8"),
|
|
]);
|
|
for (const key of [
|
|
"host-lifecycle-recovery",
|
|
"incident-response",
|
|
"release-provenance",
|
|
"public-auth",
|
|
]) {
|
|
assert.match(gateCatalog, new RegExp(key));
|
|
}
|
|
assert.match(repository, /p0_not_applicable_forbidden/);
|
|
assert.match(repository, /gate_owner_required/);
|
|
assert.match(repository, /gate_evidence_notes_required/);
|
|
assert.match(repository, /gate_evidence_url_required/);
|
|
assert.match(gateCatalog, /hasPassingGateEvidence/);
|
|
assert.match(gateCatalog, /!hasPassingGateEvidence\(gate\)/);
|
|
assert.match(bootstrap, /launch_gate\.repaired/);
|
|
assert.match(gateCatalog, /\["billing-idempotency", "PAID"/);
|
|
assert.match(gateCatalog, /\["payment-provider", "PAID"/);
|
|
assert.match(bootstrap, /gateReconciliationStatements/);
|
|
assert.match(bootstrap, /launch_gate\.reclassified/);
|
|
assert.match(bootstrap, /price_catalog\.retired/);
|
|
assert.match(bootstrap, /status = 'retired'/);
|
|
assert.match(launchGates, /公开服务状态页.*已实现/);
|
|
assert.match(launchGates, /安全事件分级、自动告警、外部通知和值守升级/);
|
|
assert.match(launchGates, /国内个人用户身份/);
|
|
assert.match(launchGates, /PAID:未来决定收费后再处理/);
|
|
});
|
|
|
|
test.skip("legacy per-tenant provisioner contract was replaced by the shared Relay pool", async () => {
|
|
assert.equal(canQueueProvisioning("ensure", "requested"), true);
|
|
assert.equal(canQueueProvisioning("ensure", "ready"), true);
|
|
assert.equal(canQueueProvisioning("resume", "ready"), false);
|
|
assert.equal(
|
|
expectedRelayOrigin(`n-${"a".repeat(32)}`, "relay.example.cn"),
|
|
`https://n-${"a".repeat(32)}.relay.example.cn`,
|
|
);
|
|
|
|
const db = new DatabaseSync(":memory:");
|
|
const migrationNames = [
|
|
"0000_condemned_legion.sql",
|
|
"0001_mushy_vance_astro.sql",
|
|
"0002_wild_ravenous.sql",
|
|
"0003_medical_rocket_racer.sql",
|
|
"0004_loud_prodigy.sql",
|
|
"9000_provisioning_invariants.sql",
|
|
"9002_ready_credential_reconciliation.sql",
|
|
];
|
|
const migrations = await Promise.all(
|
|
migrationNames.map((name) =>
|
|
readFile(new URL(`../drizzle/${name}`, import.meta.url), "utf8"),
|
|
),
|
|
);
|
|
for (const migration of migrations) {
|
|
db.exec(migration.replaceAll("--> statement-breakpoint", ""));
|
|
}
|
|
const now = "2026-08-12T10:00:00.000Z";
|
|
const legacyTenantId = `tenant_${"b".repeat(32)}`;
|
|
db.prepare(
|
|
`INSERT INTO accounts
|
|
(id, auth_subject, email, display_name, status, created_at, updated_at)
|
|
VALUES ('legacy-acct', 'legacy-subject', 'legacy@example.test', 'Legacy', 'active', ?, ?)`,
|
|
).run(now, now);
|
|
db.prepare(
|
|
`INSERT INTO tenant_instances
|
|
(id, account_id, slug, lifecycle, desired_state, observed_state,
|
|
desired_generation, credential_revision, relay_ready, created_at, updated_at)
|
|
VALUES (?, 'legacy-acct', 'n-deadbeef', 'requested', 'requested', 'absent', 1, 0, 0, ?, ?)`,
|
|
).run(legacyTenantId, now, now);
|
|
const slugBackfill = await readFile(
|
|
new URL("../drizzle/9001_provisioning_slug_backfill.sql", import.meta.url),
|
|
"utf8",
|
|
);
|
|
db.exec(slugBackfill.replaceAll("--> statement-breakpoint", ""));
|
|
assert.equal(
|
|
db.prepare("SELECT slug FROM tenant_instances WHERE id = ?").get(legacyTenantId).slug,
|
|
`n-${"b".repeat(32)}`,
|
|
);
|
|
db.prepare(
|
|
`INSERT INTO accounts
|
|
(id, auth_subject, email, display_name, status, created_at, updated_at)
|
|
VALUES ('acct', 'subject', 'a@example.test', 'A', 'active', ?, ?)`,
|
|
).run(now, now);
|
|
db.prepare(
|
|
`INSERT INTO tenant_instances
|
|
(id, account_id, slug, lifecycle, desired_state, observed_state,
|
|
desired_generation, credential_revision, relay_ready, created_at, updated_at)
|
|
VALUES ('tenant', 'acct', ?, 'requested', 'requested', 'absent', 1, 1, 0, ?, ?)`,
|
|
).run(`n-${"a".repeat(32)}`, now, now);
|
|
db.prepare(
|
|
`INSERT INTO provisioning_operations
|
|
(id, tenant_id, operation, idempotency_key, correlation_id,
|
|
target_generation, credential_revision, status, requested_by, reason,
|
|
lifecycle_before, payload_version, attempt_count, max_attempts,
|
|
fence_epoch, created_at, updated_at)
|
|
VALUES ('op', 'tenant', 'ensure', 'idem_12345678', 'corr', 2, 1,
|
|
'requested', 'admin', 'beta runtime', 'requested', 1, 0, 5, 0, ?, ?)`,
|
|
).run(now, now);
|
|
assert.deepEqual(
|
|
{ ...db.prepare(
|
|
"SELECT lifecycle, desired_state, desired_generation, relay_ready FROM tenant_instances WHERE id = 'tenant'",
|
|
).get() },
|
|
{
|
|
lifecycle: "provisioning",
|
|
desired_state: "running",
|
|
desired_generation: 2,
|
|
relay_ready: 0,
|
|
},
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
db.prepare(
|
|
`INSERT INTO provisioning_operations
|
|
(id, tenant_id, operation, idempotency_key, correlation_id,
|
|
target_generation, credential_revision, status, requested_by, reason,
|
|
lifecycle_before, created_at, updated_at)
|
|
VALUES ('op2', 'tenant', 'ensure', 'idem_22345678', 'corr2', 3, 1,
|
|
'requested', 'admin', 'duplicate', 'provisioning', ?, ?)`,
|
|
).run(now, now),
|
|
/invalid_provisioning_transition|UNIQUE constraint failed/,
|
|
);
|
|
|
|
const firstLease = db.prepare(LEASE_OPERATION_SQL).get(
|
|
"worker-a",
|
|
"hash-a",
|
|
"2026-08-12T10:02:00.000Z",
|
|
now,
|
|
now,
|
|
now,
|
|
"tenant",
|
|
);
|
|
assert.equal(firstLease.attempt_count, 1);
|
|
assert.equal(firstLease.fence_epoch, 2001);
|
|
assert.equal(
|
|
db.prepare(LEASE_OPERATION_SQL).get(
|
|
"worker-b",
|
|
"hash-b",
|
|
"2026-08-12T10:02:00.000Z",
|
|
now,
|
|
now,
|
|
now,
|
|
"tenant",
|
|
),
|
|
undefined,
|
|
);
|
|
assert.equal(
|
|
db.prepare(HEARTBEAT_OPERATION_SQL).get(
|
|
"2026-08-12T10:03:00.000Z",
|
|
now,
|
|
"op",
|
|
"worker-a",
|
|
"hash-a",
|
|
2001,
|
|
now,
|
|
).lease_expires_at,
|
|
"2026-08-12T10:03:00.000Z",
|
|
);
|
|
|
|
db.prepare(
|
|
"UPDATE provisioning_operations SET lease_expires_at = '2026-08-12T09:59:00.000Z' WHERE id = 'op'",
|
|
).run();
|
|
const secondLease = db.prepare(LEASE_OPERATION_SQL).get(
|
|
"worker-b",
|
|
"hash-b",
|
|
"2026-08-12T10:04:00.000Z",
|
|
now,
|
|
now,
|
|
now,
|
|
"tenant",
|
|
);
|
|
assert.equal(secondLease.attempt_count, 2);
|
|
assert.equal(secondLease.fence_epoch, 2002);
|
|
assert.equal(
|
|
db.prepare(HEARTBEAT_OPERATION_SQL).get(
|
|
"2026-08-12T10:05:00.000Z",
|
|
now,
|
|
"op",
|
|
"worker-a",
|
|
"hash-a",
|
|
2001,
|
|
now,
|
|
),
|
|
undefined,
|
|
);
|
|
|
|
const completed = db.prepare(
|
|
`UPDATE provisioning_operations
|
|
SET status = 'succeeded', completion_hash = 'done', result_version = 1,
|
|
observed_generation = 2, result_runtime_ref = 'runtime://tenant',
|
|
result_runtime_version = 'v1', result_relay_origin = ?,
|
|
result_secret_bundle_ref = 'secret://tenant', health_status = 'healthy',
|
|
health_checked_at = ?, completed_at = ?, updated_at = ?
|
|
WHERE id = 'op' AND status = 'leased' AND lease_owner = 'worker-b'
|
|
AND lease_token_hash = 'hash-b' AND fence_epoch = 2002
|
|
RETURNING status`,
|
|
).get(`https://n-${"a".repeat(32)}.relay.example.cn`, now, now, now);
|
|
assert.equal(completed.status, "succeeded");
|
|
assert.deepEqual(
|
|
{ ...db.prepare(
|
|
"SELECT lifecycle, observed_state, active_generation, relay_ready FROM tenant_instances WHERE id = 'tenant'",
|
|
).get() },
|
|
{
|
|
lifecycle: "ready",
|
|
observed_state: "running",
|
|
active_generation: 2,
|
|
relay_ready: 0,
|
|
},
|
|
);
|
|
const relayOrigin = `https://n-${"a".repeat(32)}.relay.example.cn`;
|
|
const staleAttestation = db.prepare(ATTEST_RELAY_READY_SQL).get(
|
|
now,
|
|
now,
|
|
"tenant",
|
|
3,
|
|
3,
|
|
1,
|
|
relayOrigin,
|
|
"op",
|
|
"worker-b",
|
|
2002,
|
|
3,
|
|
1,
|
|
3,
|
|
relayOrigin,
|
|
);
|
|
assert.equal(staleAttestation, undefined);
|
|
assert.equal(
|
|
db.prepare("SELECT relay_ready FROM tenant_instances WHERE id = 'tenant'").get()
|
|
.relay_ready,
|
|
0,
|
|
);
|
|
const attested = db.prepare(ATTEST_RELAY_READY_SQL).get(
|
|
now,
|
|
now,
|
|
"tenant",
|
|
2,
|
|
2,
|
|
1,
|
|
relayOrigin,
|
|
"op",
|
|
"worker-b",
|
|
2002,
|
|
2,
|
|
1,
|
|
2,
|
|
relayOrigin,
|
|
);
|
|
assert.equal(attested.relay_ready, 1);
|
|
assert.equal(
|
|
db.prepare(
|
|
"SELECT COUNT(*) AS count FROM provisioning_operations WHERE lease_token_hash = 'hash-a'",
|
|
).get().count,
|
|
0,
|
|
);
|
|
db.close();
|
|
});
|
|
|
|
test.skip("legacy provisioner payload contract was replaced by Relay authorization snapshots", async () => {
|
|
const [repository, auth, adminPage, attestRoute] = await Promise.all([
|
|
readFile(new URL("../db/provisioning-repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/provisioner-auth.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/admin/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/provisioning/attest-relay/route.ts", import.meta.url), "utf8"),
|
|
]);
|
|
assert.match(repository, /credentialRevision/);
|
|
assert.match(repository, /tokenHash/);
|
|
assert.match(repository, /fenceEpoch/);
|
|
assert.match(repository, /relayReady: false/);
|
|
assert.match(repository, /runtime:\/\//);
|
|
assert.match(repository, /secret:\/\//);
|
|
assert.match(repository, /sensitive_failure_detail/);
|
|
assert.match(repository, /assertPrimaryProvisionerConfigured/);
|
|
assert.match(repository, /relay_attestation_incomplete/);
|
|
assert.match(repository, /ATTEST_RELAY_READY_SQL/);
|
|
assert.match(attestRoute, /requireProvisioner/);
|
|
assert.match(attestRoute, /noStoreJson/);
|
|
assert.doesNotMatch(repository, /tenant:\s*\{[\s\S]{0,500}email:/);
|
|
assert.ok(
|
|
repository.indexOf("if (replay) return replay") <
|
|
repository.indexOf("if (tenant.tombstoned_at)"),
|
|
"idempotency replay must run before mutable lifecycle checks",
|
|
);
|
|
const completion = repository.slice(
|
|
repository.indexOf("export async function completeProvisioningOperation"),
|
|
);
|
|
assert.ok(
|
|
completion.indexOf("if (terminal)") <
|
|
completion.indexOf("tenant.credential_revision !== operation.credential_revision"),
|
|
"terminal replay must not depend on later credential revisions",
|
|
);
|
|
assert.match(auth, /NEKONEST_CLOUD_PROVISIONER_SECRET/);
|
|
assert.doesNotMatch(auth, /PROVISIONER_SECRET_PREVIOUS/);
|
|
assert.match(adminPage, /relay_ready=false/);
|
|
const dashboard = await readFile(
|
|
new URL("../app/dashboard/page.tsx", import.meta.url),
|
|
"utf8",
|
|
);
|
|
assert.match(dashboard, /activation\.label/);
|
|
assert.match(dashboard, /relay_ready=false/);
|
|
assert.doesNotMatch(dashboard, /lifecycle === "ready" \? "已就绪"/);
|
|
});
|
|
|
|
test.skip("legacy tenant relay URL handoff was removed", () => {
|
|
const ready = {
|
|
lifecycle: "ready",
|
|
desiredState: "running",
|
|
observedState: "running",
|
|
desiredGeneration: 7,
|
|
activeGeneration: 7,
|
|
credentialRevision: 3,
|
|
relayReady: true,
|
|
relayOrigin: "https://n-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.relay.example.cn",
|
|
expectedRelayOrigin: "https://n-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.relay.example.cn",
|
|
tombstonedAt: null,
|
|
};
|
|
assert.deepEqual(deriveDeviceActivation(ready), {
|
|
state: "ready",
|
|
relayReady: true,
|
|
relayUrl: ready.expectedRelayOrigin,
|
|
retryAfterSeconds: null,
|
|
});
|
|
|
|
for (const changed of [
|
|
{ relayReady: false },
|
|
{ activeGeneration: 6 },
|
|
{ credentialRevision: 0 },
|
|
{ desiredState: "suspended" },
|
|
{ observedState: "absent" },
|
|
{ relayOrigin: "https://n-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.relay.example.cn" },
|
|
{ expectedRelayOrigin: null },
|
|
]) {
|
|
const result = deriveDeviceActivation({ ...ready, ...changed });
|
|
assert.equal(result.relayReady, false);
|
|
assert.equal(result.relayUrl, null);
|
|
}
|
|
|
|
assert.equal(
|
|
deriveDeviceActivation({ ...ready, tombstonedAt: "2026-08-12T12:00:00.000Z" }).state,
|
|
"deprovisioned",
|
|
);
|
|
assert.equal(deriveDeviceActivation(null).state, "awaiting_provisioning");
|
|
});
|
|
|
|
test.skip("legacy activation polling was removed in favor of one stable endpoint", async () => {
|
|
const [repository, bootstrapRoute, dashboard, hosts, handoff] = await Promise.all([
|
|
readFile(new URL("../db/repository.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/api/devices/bootstrap/route.ts", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/hosts/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../docs/daemon-relay-handoff.md", import.meta.url), "utf8"),
|
|
]);
|
|
assert.match(repository, /contract_version:\s*1/);
|
|
assert.match(repository, /activation_poll_path/);
|
|
assert.match(repository, /expectedRelayOrigin/);
|
|
assert.match(bootstrapRoute, /retry-after/);
|
|
assert.match(bootstrapRoute, /cache-control/);
|
|
assert.match(dashboard, /activation\.label/);
|
|
assert.match(hosts, /activation\.nextStep/);
|
|
assert.match(handoff, /relay_url/);
|
|
assert.match(handoff, /Authorization: Bearer/);
|
|
assert.match(handoff, /不得.*注册响应.*直接切换|不能.*注册响应.*直接切换/);
|
|
|
|
for (const state of [
|
|
"awaiting_provisioning",
|
|
"provisioning",
|
|
"awaiting_relay",
|
|
"ready",
|
|
"suspended",
|
|
"attention_required",
|
|
"deprovisioned",
|
|
"unavailable",
|
|
]) {
|
|
const copy = getActivationCopy(state);
|
|
assert.ok(copy.label.length > 0);
|
|
assert.ok(copy.detail.length > 0);
|
|
assert.ok(copy.nextStep.length > 0);
|
|
}
|
|
const firstProvisioning = getActivationCopy("awaiting_provisioning");
|
|
assert.match(firstProvisioning.nextStep, /自动排队/);
|
|
assert.doesNotMatch(firstProvisioning.nextStep, /等待管理员开通/);
|
|
});
|
|
|
|
test("gives beta users safe loading, offline, and route failure recovery states", async () => {
|
|
const [
|
|
connectivity,
|
|
routeStates,
|
|
dashboardError,
|
|
statusError,
|
|
dashboardLoading,
|
|
statusLoading,
|
|
shells,
|
|
styles,
|
|
plan,
|
|
stateModel,
|
|
] = await Promise.all([
|
|
readFile(new URL("../app/components/ConnectivityBanner.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/components/RouteStates.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/error.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/status/error.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/dashboard/loading.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/status/loading.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/components/Shells.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../app/globals.css", import.meta.url), "utf8"),
|
|
readFile(new URL("../docs/implementation-plan.md", import.meta.url), "utf8"),
|
|
readFile(new URL("../docs/state-model.md", import.meta.url), "utf8"),
|
|
]);
|
|
|
|
assert.match(connectivity, /navigator\.onLine/);
|
|
assert.match(connectivity, /addEventListener\("offline", handleOffline\)/);
|
|
assert.match(connectivity, /removeEventListener\("offline", handleOffline\)/);
|
|
assert.match(connectivity, /页面内容可能已经过期/);
|
|
assert.match(connectivity, /先核对状态,避免重复/);
|
|
assert.equal((shells.match(/<ConnectivityBanner \/>/g) ?? []).length, 2);
|
|
|
|
assert.match(routeStates, /aria-busy="true"/);
|
|
assert.match(routeStates, /aria-live="polite"/);
|
|
assert.match(routeStates, /onClick=\{reset\}/);
|
|
assert.match(routeStates, /href="\/status"/);
|
|
assert.match(routeStates, /不能证明你的主机或会话中继已经离线/);
|
|
assert.doesNotMatch(`${routeStates}\n${dashboardError}\n${statusError}`, /error\.(?:message|stack|digest)/);
|
|
assert.match(dashboardError, /没有猜测或沿用旧结果/);
|
|
assert.match(statusError, /不会显示推测的“服务正常”/);
|
|
assert.match(`${dashboardLoading}\n${statusLoading}`, /RouteLoadingState/);
|
|
assert.match(styles, /prefers-reduced-motion/);
|
|
assert.match(styles, /route-loading-lines span \{ animation: none; \}/);
|
|
assert.match(plan, /\[x\] 空、加载、失败、离线、待核实和无资格状态/);
|
|
assert.match(stateModel, /加载、离线和页面失败是客户端展示状态/);
|
|
});
|
|
|
|
test("derives an honest 30-day beta operations funnel from control-plane records", async () => {
|
|
const db = new DatabaseSync(":memory:");
|
|
db.exec(`
|
|
CREATE TABLE accounts (id TEXT PRIMARY KEY, created_at TEXT NOT NULL);
|
|
CREATE TABLE hosts (
|
|
id TEXT PRIMARY KEY, account_id TEXT NOT NULL, lifecycle TEXT NOT NULL,
|
|
claimed_at TEXT
|
|
);
|
|
CREATE TABLE pairing_requests (
|
|
id TEXT PRIMARY KEY, status TEXT NOT NULL, expires_at TEXT NOT NULL,
|
|
locked_at TEXT, created_at TEXT NOT NULL, claimed_at TEXT
|
|
);
|
|
CREATE TABLE pairing_claim_attempts (
|
|
id TEXT PRIMARY KEY, outcome TEXT NOT NULL, created_at TEXT NOT NULL
|
|
);
|
|
CREATE TABLE tenant_placements (
|
|
tenant_id TEXT PRIMARY KEY, state TEXT NOT NULL, created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL
|
|
);
|
|
CREATE TABLE beta_feedback (
|
|
id TEXT PRIMARY KEY, category TEXT NOT NULL, status TEXT NOT NULL,
|
|
created_at TEXT NOT NULL, resolved_at TEXT
|
|
);
|
|
CREATE TABLE beta_access_requests (
|
|
id TEXT PRIMARY KEY, account_id TEXT NOT NULL, status TEXT NOT NULL,
|
|
preferred_os TEXT NOT NULL, requested_slots INTEGER NOT NULL,
|
|
requested_at TEXT NOT NULL, resolved_at TEXT
|
|
);
|
|
`);
|
|
db.exec(`
|
|
INSERT INTO accounts VALUES
|
|
('acct_new', '2026-08-10T00:00:00.000Z'),
|
|
('acct_old', '2026-01-01T00:00:00.000Z');
|
|
INSERT INTO hosts VALUES
|
|
('host_1', 'acct_new', 'active', '2026-08-09T03:00:00.000Z');
|
|
INSERT INTO pairing_requests VALUES
|
|
('pair_claimed', 'claimed', '2026-08-10T00:10:00.000Z', NULL,
|
|
'2026-08-10T00:00:00.000Z', '2026-08-10T00:02:00.000Z'),
|
|
('pair_waiting', 'waiting', '2026-08-13T00:00:00.000Z', NULL,
|
|
'2026-08-11T00:00:00.000Z', NULL),
|
|
('pair_expired', 'waiting', '2026-08-11T01:00:00.000Z', '2026-08-11T00:30:00.000Z',
|
|
'2026-08-11T00:00:00.000Z', NULL),
|
|
('pair_old', 'claimed', '2026-01-01T00:10:00.000Z', NULL,
|
|
'2026-01-01T00:00:00.000Z', '2026-01-01T00:01:00.000Z');
|
|
INSERT INTO pairing_claim_attempts VALUES
|
|
('attempt_1', 'rejected', '2026-08-10T00:00:00.000Z'),
|
|
('attempt_2', 'rate_limited', '2026-08-10T00:01:00.000Z');
|
|
INSERT INTO tenant_placements VALUES
|
|
('tenant_1', 'active', '2026-08-10T00:00:00.000Z', '2026-08-10T00:05:00.000Z'),
|
|
('op_2', 'failed', '2026-08-11T00:00:00.000Z', '2026-08-11T00:01:00.000Z');
|
|
INSERT INTO beta_feedback VALUES
|
|
('feedback_1', 'connection_issue', 'resolved',
|
|
'2026-08-10T00:00:00.000Z', '2026-08-10T01:00:00.000Z'),
|
|
('feedback_2', 'bug', 'open', '2026-08-11T00:00:00.000Z', NULL);
|
|
INSERT INTO beta_access_requests VALUES
|
|
('access_1', 'acct_new', 'approved', 'windows', 2, '2026-08-09T00:00:00.000Z', '2026-08-09T02:00:00.000Z'),
|
|
('access_2', 'acct_old', 'declined', 'linux', 1, '2026-08-10T00:00:00.000Z', '2026-08-10T04:00:00.000Z'),
|
|
('access_3', 'acct_pending', 'requested', 'both', 3, '2026-08-11T00:00:00.000Z', NULL),
|
|
('access_4', 'acct_cancelled', 'cancelled', 'windows', 1, '2026-08-11T01:00:00.000Z', NULL),
|
|
('access_old', 'acct_old', 'approved', 'linux', 3, '2026-01-01T00:00:00.000Z', '2026-01-02T00:00:00.000Z');
|
|
`);
|
|
|
|
const now = "2026-08-12T00:00:00.000Z";
|
|
const cutoff = "2026-07-13T00:00:00.000Z";
|
|
const snapshot = deriveBetaOperationsSnapshot({
|
|
generatedAt: now,
|
|
accounts: { ...db.prepare(BETA_ACCOUNTS_SQL).get(cutoff) },
|
|
pairings: { ...db.prepare(BETA_PAIRINGS_SQL).get(now, now, now, cutoff) },
|
|
claimAttempts: { ...db.prepare(BETA_CLAIM_ATTEMPTS_SQL).get(cutoff) },
|
|
provisioning: { ...db.prepare(BETA_PROVISIONING_SQL).get(cutoff) },
|
|
support: { ...db.prepare(BETA_SUPPORT_SQL).get(cutoff) },
|
|
accessRequests: { ...db.prepare(BETA_ACCESS_REQUESTS_SQL).get(cutoff) },
|
|
});
|
|
|
|
assert.deepEqual(snapshot.accounts, {
|
|
total: 2,
|
|
newAccounts: 1,
|
|
withActiveHost: 1,
|
|
});
|
|
assert.equal(snapshot.pairings.created, 3);
|
|
assert.equal(snapshot.pairings.claimed, 1);
|
|
assert.equal(snapshot.pairings.waiting, 1);
|
|
assert.equal(snapshot.pairings.expired, 1);
|
|
assert.equal(snapshot.pairings.attentionRequired, 1);
|
|
assert.equal(snapshot.pairings.locked, 1);
|
|
assert.equal(snapshot.pairings.claimRatePercent, 33.3);
|
|
assert.equal(snapshot.pairings.averageClaimSeconds, 120);
|
|
assert.equal(snapshot.pairings.rejectedAttempts, 1);
|
|
assert.equal(snapshot.pairings.rateLimitedAttempts, 1);
|
|
assert.equal(snapshot.provisioning.successRatePercent, 50);
|
|
assert.equal(snapshot.provisioning.averageCompletionSeconds, 300);
|
|
assert.equal(snapshot.support.resolutionRatePercent, 50);
|
|
assert.equal(snapshot.support.averageResolutionSeconds, 3600);
|
|
assert.deepEqual(snapshot.accessRequests, {
|
|
submitted: 4,
|
|
requestedSlotDemand: 7,
|
|
averageRequestedSlots: 1.8,
|
|
windows: 2,
|
|
linux: 1,
|
|
both: 1,
|
|
pending: 1,
|
|
approved: 1,
|
|
declined: 1,
|
|
cancelled: 1,
|
|
decided: 2,
|
|
approvalRatePercent: 50,
|
|
averageReviewSeconds: 10800,
|
|
approvedWithPostApprovalClaim: 1,
|
|
postApprovalClaimRatePercent: 100,
|
|
});
|
|
assert.deepEqual(snapshot.unavailable, [
|
|
"relay_reconnect_rate",
|
|
"relay_latency",
|
|
"runtime_resource_cost",
|
|
"support_effort",
|
|
]);
|
|
|
|
const empty = deriveBetaOperationsSnapshot({
|
|
generatedAt: now,
|
|
accounts: {},
|
|
pairings: {},
|
|
claimAttempts: {},
|
|
provisioning: {},
|
|
support: {},
|
|
accessRequests: {},
|
|
});
|
|
assert.equal(empty.pairings.claimRatePercent, null);
|
|
assert.equal(empty.provisioning.successRatePercent, null);
|
|
assert.equal(empty.support.resolutionRatePercent, null);
|
|
assert.equal(empty.accessRequests.approvalRatePercent, null);
|
|
assert.equal(empty.accessRequests.averageRequestedSlots, null);
|
|
assert.equal(empty.accessRequests.postApprovalClaimRatePercent, null);
|
|
db.close();
|
|
|
|
const [admin, metricsDoc, plan] = await Promise.all([
|
|
readFile(new URL("../app/admin/page.tsx", import.meta.url), "utf8"),
|
|
readFile(new URL("../docs/beta-operations.md", import.meta.url), "utf8"),
|
|
readFile(new URL("../docs/implementation-plan.md", import.meta.url), "utf8"),
|
|
]);
|
|
assert.match(admin, /控制平面实数/);
|
|
assert.match(admin, /闭测申请/);
|
|
assert.match(admin, /申请批准率/);
|
|
assert.match(admin, /申请设备需求/);
|
|
assert.match(admin, /获批后认领率/);
|
|
assert.match(admin, /每账户最多/);
|
|
assert.match(admin, /只证明 daemon 已通过控制面鉴权/);
|
|
assert.match(admin, /不单独证明长连接、重连或 sealed 会话质量/);
|
|
assert.match(admin, /重连成功率、relay 延迟、运行时资源成本和实际支持工时/);
|
|
assert.match(metricsDoc, /不得读取或复制原生 coding-agent 会话/);
|
|
assert.match(metricsDoc, /不是人工工时/);
|
|
assert.match(plan, /真实 relay 接通后采集重连成功率/);
|
|
});
|