Compare commits

...
Author SHA1 Message Date
dev-driver 661a66e126 test: what would outrank a Claude seat's own token is named, with its remedy, before the seat moves 2026-10-25 05:46:34 +00:00
dev-driver 8854a217b9 feat(claude): a seat's own subscription token file, kept by reference and read as Claude starts
A Claude seat can carry { label, tokenFile } (nodes.claude_token_ref). Its managed launch reads the
file in the launch script, after the environment is reduced, so the token reaches only that Claude
process and never OpenRig's records, the launch command or argv. An unreadable or empty file stops
the launch rather than run Claude on the config dir's stored login.
2026-10-25 05:40:37 +00:00
dev-driver d584b49003 test: a Claude seat's own subscription token file reaches only its Claude process, by reference 2026-10-25 05:38:22 +00:00
9 changed files with 235 additions and 2 deletions

No files matched your search

+2
View File
@@ -12,6 +12,7 @@ import { streamRetentionFloorSchema } from "./migrations/131_stream_retention_fl
import { seatRuntimeSwitchesSchema } from "./migrations/132_seat_runtime_switches.js";
import { streamReaderActionsSchema } from "./migrations/133_stream_reader_actions.js";
import { seatIdentityProcessEvidenceSchema } from "./migrations/135_seat_identity_process_evidence.js";
import { nodeClaudeTokenRefSchema } from "./migrations/136_node_claude_token_ref.js";
import { bindingsSessionsSchema } from "./migrations/002_bindings_sessions.js";
import { eventsSchema } from "./migrations/003_events.js";
import { snapshotsSchema } from "./migrations/004_snapshots.js";
@@ -269,4 +270,5 @@ export const ALL_MIGRATIONS: Migration[] = [
streamReaderActionsSchema,
claudeTokenReadingsSchema,
seatIdentityProcessEvidenceSchema,
nodeClaudeTokenRefSchema,
];
@@ -0,0 +1,9 @@
import type { Migration } from "../migrate.js";
// A Claude seat's own subscription credential, as a reference only: { label, tokenFile } JSON. Never the token.
export const nodeClaudeTokenRefSchema: Migration = {
name: "136_node_claude_token_ref.sql",
sql: `
ALTER TABLE nodes ADD COLUMN claude_token_ref TEXT;
`,
};
@@ -12,6 +12,7 @@ import { parseClaudePermissionModes } from "./permission-drift.js";
import { validateNativePermissionSelection } from "./native-permission-selection.js";
import { seatLaunchAdditionsForLaunch } from "./seat-launch-additions.js";
import { effectiveRuntimeHome } from "./seat-runtime-home.js";
import { claudeSeatTokenStep, readClaudeSeatTokenRef } from "./claude-seat-token.js";
export interface ClaudeLaunchTarget {
nodeId: string;
@@ -246,6 +247,10 @@ export class ClaudeManagedLaunch {
const otherwise = (key: string) => selectedKeys.includes(key) ? "" : ` else unset ${key};`;
const terminal = terminalKeys.map(key => `if [ -n "\${${key}-}" ]; then export ${key};${otherwise(key)} fi`);
terminal.push(`if [ -n "$${WAYLAND_DISPLAY_VAR}" ]; then export WAYLAND_DISPLAY="$${WAYLAND_DISPLAY_VAR}";${otherwise("WAYLAND_DISPLAY")} fi`);
// A seat's own subscription token (rig provider switch --seat) is read from its file as Claude starts, after the
// environment is reduced, so the value never passes through OpenRig; an unreadable file stops the launch.
const tokenRef = readClaudeSeatTokenRef(this.db, target.nodeId);
const tokenStep = tokenRef ? `${claudeSeatTokenStep(tokenRef, shellQuote)} && ` : "";
return Object.freeze({ assertCurrent, configDir: context.configDir, executable: context.executable, executableIsScript: context.executableIsScript, command: (args: readonly string[], launchEnv: Readonly<Record<string, string>> = {}) => {
assertCurrent();
const launch = Object.entries(launchEnv).map(([key, value]) => `export ${shellQuote(`${key}=${value}`)}`);
@@ -258,7 +263,7 @@ export class ClaudeManagedLaunch {
const clear = `__openrig_remove=$(/usr/bin/env -0 | /usr/bin/env -i ${shellQuote(process.execPath)} -e ${shellQuote(removalArgs)}) && eval "$__openrig_remove"`;
return `${WAYLAND_DISPLAY_ASSIGNMENT}; cd ${shellQuote(cwd)} && {
${[...assignments, ...forwarded, ...seatForwarded, ...projectForwarded, ...terminal, ...launch].join("\n")}
${clear} && exec /usr/bin/env "$@" ${[shellQuote(context.executable), ...args.map(shellQuote)].join(" ")}
${clear} && ${tokenStep}exec /usr/bin/env "$@" ${[shellQuote(context.executable), ...args.map(shellQuote)].join(" ")}
}`;
} });
}
@@ -0,0 +1,48 @@
import type Database from "better-sqlite3";
import path from "node:path";
/** A Claude seat's own subscription credential: an operator label and an absolute token-file path. A reference only: the
* launch script reads the file when Claude starts, so the value never passes through OpenRig. The label is the
* operator's name for it, not an account the provider observed. */
export interface ClaudeSeatTokenRef {
label: string;
tokenFile: string;
}
const LABEL_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]{0,63}$/;
/** Why a label or token-file path can't be a seat's reference, or null when it can. */
export function claudeSeatTokenRefProblem(ref: ClaudeSeatTokenRef): string | null {
if (!LABEL_RE.test(ref.label)) return "the label must start with a letter or digit, then use letters, digits, '.', '_', '@' or '-' (at most 64)";
if (!path.isAbsolute(ref.tokenFile) || /[\0\n\r]/.test(ref.tokenFile)) return "the token file must be an absolute path on one line";
return null;
}
/** The stored reference, or null when it's absent or unreadable. */
export function parseClaudeSeatTokenRef(value: unknown): ClaudeSeatTokenRef | null {
if (typeof value !== "string" || value === "") return null;
try {
const { label, tokenFile } = JSON.parse(value) as { label?: unknown; tokenFile?: unknown };
if (typeof label !== "string" || typeof tokenFile !== "string") return null;
return claudeSeatTokenRefProblem({ label, tokenFile }) === null ? { label, tokenFile } : null;
} catch {
return null;
}
}
/** A seat's reference, read where a launch needs it; null before the column exists. */
export function readClaudeSeatTokenRef(db: Database.Database, nodeId: string): ClaudeSeatTokenRef | null {
const columns = db.prepare("PRAGMA table_info(nodes)").all() as Array<{ name: string }>;
if (!columns.some((column) => column.name === "claude_token_ref")) return null;
const row = db.prepare("SELECT claude_token_ref AS ref FROM nodes WHERE id = ?").get(nodeId) as { ref?: unknown } | undefined;
return parseClaudeSeatTokenRef(row?.ref);
}
/** The launch-script step that gives Claude the seat's token, read from its file as Claude starts. When the file can't be
* read (or is empty), the step fails and Claude isn't started, rather than run on the config dir's stored login. */
export function claudeSeatTokenStep(ref: ClaudeSeatTokenRef, quote: (value: string) => string): string {
const refusal = `OpenRig: this seat's Claude token file (${ref.label}) can't be read: ${ref.tokenFile}. Claude wasn't started, `
+ "so it doesn't run on another login. Fix the file, or choose another with rig provider switch.";
return `{ CLAUDE_CODE_OAUTH_TOKEN=$(/bin/cat -- ${quote(ref.tokenFile)} 2>/dev/null) && [ -n "$CLAUDE_CODE_OAUTH_TOKEN" ] `
+ `&& export CLAUDE_CODE_OAUTH_TOKEN || { printf '%s\\n' ${quote(refusal)} >&2; false; }; }`;
}
@@ -7,6 +7,7 @@ import { deriveComposeProjectName } from "./compose-project-name.js";
import type { ClaudeManagedBlockFile } from "./managed-blocks.js";
import { mergeSeatEnv, parseStoredSeatEnv, type SeatEnv } from "./seat-env.js";
import { withoutIgnoredRuntimeHomes } from "./seat-runtime-home.js";
import { parseClaudeSeatTokenRef, type ClaudeSeatTokenRef } from "./claude-seat-token.js";
import type {
Rig,
Node,
@@ -588,6 +589,13 @@ export class RigRepository {
return result.changes > 0;
}
/** A Claude seat's own subscription credential, by reference only; null clears it. */
setNodeClaudeTokenRef(nodeId: string, ref: ClaudeSeatTokenRef | null): boolean {
if (!this.hasNodeColumn("claude_token_ref")) return false;
return this.db.prepare("UPDATE nodes SET claude_token_ref = ? WHERE id = ?")
.run(ref ? JSON.stringify({ label: ref.label, tokenFile: ref.tokenFile }) : null, nodeId).changes > 0;
}
/** Persist the resolved Advisor; null removes a previous spec's selection. */
setNodeAdvisor(nodeId: string, advisor: string | null): boolean {
if (!this.hasNodeColumn("advisor")) return false;
@@ -845,6 +853,7 @@ export class RigRepository {
advisor: row.advisor ?? null,
effortChoice: row.effort_choice ?? null,
codexConfigProfile: row.codex_config_profile ?? null,
claudeTokenRef: parseClaudeSeatTokenRef(row.claude_token_ref),
permissionPolicy: row.permission_policy ?? null,
env: parseStoredSeatEnv(row.env_json),
cwd: row.cwd,
@@ -937,6 +946,7 @@ interface NodeRow {
advisor?: string | null;
effort_choice?: string | null;
codex_config_profile?: string | null;
claude_token_ref?: string | null;
permission_policy?: string | null;
env_json?: string | null;
cwd: string | null;
+2
View File
@@ -39,6 +39,8 @@ export interface Node {
/** OPR.0.7.0.7: the seat's explicit effort choice (rig seat set-effort); null = none. */
effortChoice?: string | null;
codexConfigProfile?: string | null;
/** A Claude seat's own subscription credential, as a reference (operator label and token-file path); null = none. */
claudeTokenRef?: { label: string; tokenFile: string } | null;
/** OPR.0.4.8.3 Seam B: attached permission_policy REF (builtin:<name> or spec-relative custom
* path), or null when none is attached (= the floor). */
permissionPolicy?: string | null;
@@ -0,0 +1,70 @@
import { afterEach, describe, expect, it } from "vitest";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import Database from "better-sqlite3";
import { ClaudeManagedLaunch } from "../src/domain/claude-managed-launch.js";
// Before a Claude seat moves to its own subscription token, OpenRig finds what Claude Code would rank above that token
// (a cloud provider, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_API_KEY, an apiKeyHelper): in the seat's launch environment and in the
// settings files it loads. It names each one and its remedy, edits nothing, and says what it couldn't read.
const cleanup: Array<() => void> = [];
afterEach(() => { for (const f of cleanup.splice(0)) f(); });
function fixture(opts: { daemonEnv?: Record<string, string>; memberEnv?: Record<string, string>; worktree?: boolean } = {}) {
const root = mkdtempSync(path.join(tmpdir(), "claude-precedence-"));
cleanup.push(() => rmSync(root, { recursive: true, force: true }));
const home = path.join(root, "home"), main = path.join(root, "main"), cwd = opts.worktree ? path.join(root, "wt") : main;
for (const dir of [home, main, cwd, path.join(home, ".claude"), path.join(cwd, ".claude"), path.join(main, ".claude"), path.join(main, ".git", "worktrees", "wt")]) {
mkdirSync(dir, { recursive: true });
}
if (opts.worktree) writeFileSync(path.join(cwd, ".git"), `gitdir: ${path.join(main, ".git", "worktrees", "wt")}\n`);
const db = new Database(":memory:"); cleanup.push(() => { db.close(); });
db.exec(`CREATE TABLE rigs(id TEXT, env_json TEXT);
CREATE TABLE nodes(id TEXT, rig_id TEXT, runtime TEXT, cwd TEXT, env_json TEXT);
CREATE TABLE bindings(id TEXT, node_id TEXT, tmux_session TEXT, tmux_pane TEXT);
CREATE TABLE occupant_tenures(node_id TEXT, generation_uuid TEXT, generation_ordinal INTEGER);`);
db.prepare("INSERT INTO rigs VALUES ('rig', NULL)").run();
db.prepare("INSERT INTO nodes VALUES ('node', 'rig', 'claude-code', ?, ?)").run(cwd, opts.memberEnv ? JSON.stringify(opts.memberEnv) : null);
db.exec("INSERT INTO bindings VALUES ('b', 'node', 'seat@rig', '%1'); INSERT INTO occupant_tenures VALUES ('node', 'gen', 1)");
const managed = new ClaudeManagedLaunch(db, { PATH: "/usr/bin:/bin", HOME: home, ...opts.daemonEnv }, {}, async () => undefined);
return { managed, home, main, cwd };
}
describe("what would outrank a Claude seat's own subscription token", () => {
it("names each one in the launch environment and the settings files the seat loads, with its remedy", async () => {
const f = fixture({ daemonEnv: { ANTHROPIC_AUTH_TOKEN: "x" }, memberEnv: { ANTHROPIC_API_KEY: "y" }, worktree: true });
writeFileSync(path.join(f.home, ".claude", "settings.json"), JSON.stringify({ apiKeyHelper: "/usr/local/bin/key" }));
writeFileSync(path.join(f.cwd, ".claude", "settings.json"), JSON.stringify({ env: { CLAUDE_CODE_USE_BEDROCK: "1" } }));
// In a worktree, Claude Code reads the local settings at the main checkout's root.
writeFileSync(path.join(f.main, ".claude", "settings.local.json"), JSON.stringify({ env: { ANTHROPIC_API_KEY: "z" } }));
const found = await f.managed.credentialPrecedence("node");
expect(found.conflicts.map((c) => [c.name, c.source])).toEqual([
["ANTHROPIC_AUTH_TOKEN", "the daemon's environment, which every managed Claude launch receives"],
["ANTHROPIC_API_KEY", "this seat's env: (member or rig) or a one-off launch name"],
["apiKeyHelper", `user settings ${path.join(f.home, ".claude", "settings.json")}`],
["CLAUDE_CODE_USE_BEDROCK", `the env block of project settings ${path.join(f.cwd, ".claude", "settings.json")}`],
["ANTHROPIC_API_KEY", `the env block of project local settings ${path.join(f.main, ".claude", "settings.local.json")}`],
]);
for (const conflict of found.conflicts) expect(conflict.remedy.length).toBeGreaterThan(0);
// Values are never reported, only names and where they come from.
expect(JSON.stringify(found)).not.toMatch(/"(x|y|z)"/);
});
it("finds nothing on a seat with none, and says what it couldn't read", async () => {
const f = fixture();
writeFileSync(path.join(f.cwd, ".claude", "settings.json"), JSON.stringify({ env: { FOO: "1" }, model: "opus" }));
const found = await f.managed.credentialPrecedence("node");
expect(found.conflicts).toEqual([]);
expect(found.checked).toContain("the launch environment");
expect(found.notChecked).toEqual(["managed settings (a managed-settings.json file, MDM or the server)"]);
});
it("a settings file that isn't valid JSON is named as not checked, never as clear", async () => {
const f = fixture();
writeFileSync(path.join(f.home, ".claude", "settings.json"), "{ not json");
const found = await f.managed.credentialPrecedence("node");
expect(found.notChecked).toContain(`user settings ${path.join(f.home, ".claude", "settings.json")} (not valid JSON)`);
});
});
@@ -0,0 +1,86 @@
import { afterEach, describe, expect, it } from "vitest";
import { chmodSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { execFile } from "node:child_process";
import { promisify } from "node:util";
import Database from "better-sqlite3";
import { ClaudeManagedLaunch } from "../src/domain/claude-managed-launch.js";
import { RigRepository } from "../src/domain/rig-repository.js";
import { createFullTestDb } from "./helpers/test-app.js";
// A Claude seat can be given its own subscription credential: an operator label and a token file. The managed launch
// reads the file when Claude starts, so the value never passes through OpenRig (its records, the launch command, argv or
// logs), and Claude doesn't start on another login when the file can't be read.
const exec = promisify(execFile);
const cleanup: Array<() => void> = [];
afterEach(() => { for (const f of cleanup.splice(0)) f(); });
const SYNTHETIC = "synthetic-fixture-value-not-a-credential";
function fixture(ref?: { label: string; tokenFile: string }) {
const root = mkdtempSync(path.join(tmpdir(), "claude-seat-token-"));
cleanup.push(() => rmSync(root, { recursive: true, force: true }));
const bin = path.join(root, "bin"), home = path.join(root, "home"), cwd = path.join(root, "work");
for (const dir of [bin, home, cwd]) mkdirSync(dir);
const claude = path.join(bin, "claude");
writeFileSync(claude, `#!/bin/sh
if [ "$1" = --help ]; then printf '%s\\n' '--permission-mode <mode> (choices: "auto", "default")'; exit 0; fi
printf '{"TOKEN":"%s"}' "\${CLAUDE_CODE_OAUTH_TOKEN-absent}"
`);
chmodSync(claude, 0o700);
const db = new Database(":memory:"); cleanup.push(() => { db.close(); });
db.exec(`CREATE TABLE rigs(id TEXT, env_json TEXT);
CREATE TABLE nodes(id TEXT, rig_id TEXT, runtime TEXT, cwd TEXT, env_json TEXT, claude_token_ref TEXT);
CREATE TABLE bindings(id TEXT, node_id TEXT, tmux_session TEXT, tmux_pane TEXT);
CREATE TABLE occupant_tenures(node_id TEXT, generation_uuid TEXT, generation_ordinal INTEGER);`);
db.prepare("INSERT INTO rigs VALUES ('rig', NULL)").run();
db.prepare("INSERT INTO nodes VALUES ('node', 'rig', 'claude-code', ?, NULL, ?)").run(cwd, ref ? JSON.stringify(ref) : null);
db.exec("INSERT INTO bindings VALUES ('b', 'node', 'seat@rig', '%1'); INSERT INTO occupant_tenures VALUES ('node', 'gen', 1)");
const managed = new ClaudeManagedLaunch(db, { PATH: `${bin}:/usr/bin:/bin`, HOME: home }, {}, async () => undefined);
const command = async () => (await managed.prepare({ nodeId: "node", session: "seat@rig", pane: "%1" }, "auto")).command(["--permission-mode", "auto"]);
const run = (cmd: string) => exec("/bin/sh", ["-c", cmd], { env: { PATH: "/usr/bin:/bin" }, timeout: 5000 });
return { root, command, run };
}
describe.skipIf(process.platform === "win32")("a Claude seat's own subscription token file", () => {
it("reaches only that seat's Claude process; the value never enters the launch command", async () => {
const root = mkdtempSync(path.join(tmpdir(), "claude-seat-token-file-")); cleanup.push(() => rmSync(root, { recursive: true, force: true }));
const tokenFile = path.join(root, "claude-work.token");
writeFileSync(tokenFile, `${SYNTHETIC}\n`, { mode: 0o600 });
const f = fixture({ label: "work", tokenFile });
const command = await f.command();
expect(command).not.toContain(SYNTHETIC);
expect(command).toContain(tokenFile);
expect(JSON.parse((await f.run(command)).stdout)).toEqual({ TOKEN: SYNTHETIC });
});
it("doesn't start Claude when the token file can't be read, and says why", async () => {
const f = fixture({ label: "work", tokenFile: path.join(tmpdir(), "no-such-dir-claude-seat-token", "claude-work.token") });
const result = await f.run(await f.command()).then(
({ stdout, stderr }) => ({ code: 0, stdout, stderr }),
(err: { code?: number; stdout?: string; stderr?: string }) => ({ code: err.code ?? -1, stdout: err.stdout ?? "", stderr: err.stderr ?? "" }));
expect(result.code).not.toBe(0);
expect(result.stdout).toBe("");
expect(result.stderr).toContain("token file (work) can't be read");
});
it("a seat without one launches exactly as before", async () => {
const f = fixture();
const command = await f.command();
expect(command).not.toContain("CLAUDE_CODE_OAUTH_TOKEN");
expect(JSON.parse((await f.run(command)).stdout)).toEqual({ TOKEN: "absent" });
});
it("is kept on the seat as a reference only, and can be cleared", () => {
const db = createFullTestDb(); cleanup.push(() => db.close());
const repo = new RigRepository(db);
const rig = repo.createRig("token-rig");
const node = repo.addNode(rig.id, "owner", { runtime: "claude-code" });
const read = () => repo.getRig(rig.id)?.nodes.find((n) => n.id === node.id)?.claudeTokenRef ?? null;
expect(repo.setNodeClaudeTokenRef(node.id, { label: "work", tokenFile: "/secrets/claude-work.token" })).toBe(true);
expect(read()).toEqual({ label: "work", tokenFile: "/secrets/claude-work.token" });
expect(repo.setNodeClaudeTokenRef(node.id, null)).toBe(true);
expect(read()).toBeNull();
});
});
+2 -1
View File
@@ -3,6 +3,7 @@ import { terminalPolicySchema } from "../../src/db/migrations/128_terminal_polic
import { seatRuntimeSwitchesSchema } from "../../src/db/migrations/132_seat_runtime_switches.js";
import { seatIdentityPanePidSchema } from "../../src/db/migrations/119_seat_identity_pane_pid.js";
import { seatIdentityProcessEvidenceSchema } from "../../src/db/migrations/135_seat_identity_process_evidence.js";
import { nodeClaudeTokenRefSchema } from "../../src/db/migrations/136_node_claude_token_ref.js";
import { rigStartupLayersSchema } from "../../src/db/migrations/121_rig_startup_layers.js";
import { humanOperatingModesSchema } from "../../src/db/migrations/122_human_operating_modes.js";
import { queueDelegatedDecisionSchema } from "../../src/db/migrations/123_queue_delegated_decision.js";
@@ -145,7 +146,7 @@ import fs from "node:fs";
/** Seam B R6: the canonical full-fixture migration list, exported so file-backed
* DB-reopen tests migrate IDENTICALLY to createFullTestDb. */
export const migrationsForFullTestDb = [coreSchema, bindingsSessionsSchema, eventsSchema, snapshotsSchema, checkpointsSchema, resumeMetadataSchema, nodeSpecFieldsSchema, packagesSchema, installJournalSchema, journalSeqSchema, bootstrapSchema, discoverySchema, discoveryFkFix, agentspecRebootSchema, startupContextSchema, chatMessagesSchema, podNamespaceSchema, contextUsageSchema, externalCliAttachmentSchema, rigServicesSchema, seatHandoverObservabilitySchema, nodeCodexConfigProfileSchema, nodePermissionPolicySchema, rigPermissionPolicySchema, nodePolicyProvenanceSchema, rigPolicyProvenanceSchema, streamItemsSchema, queueItemsSchema, queueTransitionsSchema, rigPolicySchema, rigArchiveSchema, resumeProvenanceSchema, resumeVerificationSchema, seatIdentityVerdictsSchema, selfHostIdentitySchema, occupantTenuresSchema, daemonLifecycleSchema, watchdogJobsSchema, occupantGenerationStampsSchema, projectionManifestSchema, watchdogTargetGenerationSchema, appliedLaunchObservationsSchema, appliedLaunchObservationInvalidationsSchema, threadSeatMapSchema, queueTransitionWakesSchema, nodeSessionSourceSchema, scopedOperatingPostureSchema, humanNotificationIntentSchema, reviewReadIndexesSchema, inventoryEventIndexesSchema, rigClaudeManagedBlockFileSchema, nodePermissionSelectionsSchema, humanReplyToSchema, humanQuestionsSchema, nodeEffortSchema, rigNonInterruptiveSchema, rigInstallRootSchema, threadPartMapSchema, queueTransitionsQitemIdOrderSchema, queueItemsRecoveryTagsSchema, resumeRotationSchema, sessionStopIntentSchema, nodeEffortChoiceSchema, modePostureCoexistSchema, seatEnvSchema, appliedLaunchDaemonOptOutSchema, sessionCommunityHarnessSchema, threadSeatMapChannelKeySchema, queueItemWakeInputBoxSchema, providerAccountReadingsSchema, humanQuietWindowsSchema, seatIdentityPanePidSchema, seatIdentityProcessEvidenceSchema, rigStartupLayersSchema, humanOperatingModesSchema, queueDelegatedDecisionSchema, nodeAdvisorSchema, operationCorrelationSchema, terminalPolicySchema, seatRuntimeSwitchesSchema, claudeTokenReadingsSchema];
export const migrationsForFullTestDb = [coreSchema, bindingsSessionsSchema, eventsSchema, snapshotsSchema, checkpointsSchema, resumeMetadataSchema, nodeSpecFieldsSchema, packagesSchema, installJournalSchema, journalSeqSchema, bootstrapSchema, discoverySchema, discoveryFkFix, agentspecRebootSchema, startupContextSchema, chatMessagesSchema, podNamespaceSchema, contextUsageSchema, externalCliAttachmentSchema, rigServicesSchema, seatHandoverObservabilitySchema, nodeCodexConfigProfileSchema, nodePermissionPolicySchema, rigPermissionPolicySchema, nodePolicyProvenanceSchema, rigPolicyProvenanceSchema, streamItemsSchema, queueItemsSchema, queueTransitionsSchema, rigPolicySchema, rigArchiveSchema, resumeProvenanceSchema, resumeVerificationSchema, seatIdentityVerdictsSchema, selfHostIdentitySchema, occupantTenuresSchema, daemonLifecycleSchema, watchdogJobsSchema, occupantGenerationStampsSchema, projectionManifestSchema, watchdogTargetGenerationSchema, appliedLaunchObservationsSchema, appliedLaunchObservationInvalidationsSchema, threadSeatMapSchema, queueTransitionWakesSchema, nodeSessionSourceSchema, scopedOperatingPostureSchema, humanNotificationIntentSchema, reviewReadIndexesSchema, inventoryEventIndexesSchema, rigClaudeManagedBlockFileSchema, nodePermissionSelectionsSchema, humanReplyToSchema, humanQuestionsSchema, nodeEffortSchema, rigNonInterruptiveSchema, rigInstallRootSchema, threadPartMapSchema, queueTransitionsQitemIdOrderSchema, queueItemsRecoveryTagsSchema, resumeRotationSchema, sessionStopIntentSchema, nodeEffortChoiceSchema, modePostureCoexistSchema, seatEnvSchema, appliedLaunchDaemonOptOutSchema, sessionCommunityHarnessSchema, threadSeatMapChannelKeySchema, queueItemWakeInputBoxSchema, providerAccountReadingsSchema, humanQuietWindowsSchema, seatIdentityPanePidSchema, seatIdentityProcessEvidenceSchema, rigStartupLayersSchema, humanOperatingModesSchema, queueDelegatedDecisionSchema, nodeAdvisorSchema, operationCorrelationSchema, terminalPolicySchema, seatRuntimeSwitchesSchema, claudeTokenReadingsSchema, nodeClaudeTokenRefSchema];
/**
* P24 — the DECLARED exclusions for {@link migrationsForFullTestDb}. That list is deliberately a