@sellable/install
Version:
One-command installer for Sellable MCP in Claude Code, Codex, and Hermes
738 lines (711 loc) • 24.8 kB
JavaScript
import { createHash, randomUUID } from "node:crypto";
import {
chmodSync,
existsSync,
lstatSync,
mkdirSync,
readFileSync,
renameSync,
writeFileSync,
} from "node:fs";
import { dirname } from "node:path";
export const MODEL_AUTH_RUNTIME_SCHEMA = "sellable-agent-model-auth-runtime/v3";
export const MODEL_AUTH_LEGACY_RUNTIME_SCHEMA =
"sellable-agent-model-auth-runtime/v2";
export const MODEL_AUTH_READBACK_SCHEMA =
"sellable-agent-model-auth-readback/v3";
export const MODEL_AUTH_LEGACY_READBACK_SCHEMA =
"sellable-agent-model-auth-readback/v2";
export const MODEL_AUTH_MINIMUM_VALIDITY_MS = 20 * 60 * 1000;
export const MODEL_AUTH_PROVIDER = "openai-codex";
export const MODEL_AUTH_DEFAULT_MODEL = "gpt-6.1-sol";
export const MODEL_AUTH_REASONING_EFFORT = "high";
const LEGACY_MARKER_VERSION = 2;
const MARKER_VERSION = 3;
const SHA256 = /^[a-f0-9]{64}$/;
const FINGERPRINT = /^[a-f0-9]{16,64}$/;
const SAFE_ID = /^[A-Za-z0-9_.:-]{1,256}$/;
const MODEL_ID = /^~?[A-Za-z0-9][A-Za-z0-9._-]*\/[A-Za-z0-9][A-Za-z0-9._:-]*$/;
const FORBIDDEN_REFRESH_KEY = /^(?:refresh[_-]?token|id[_-]?token)$/i;
const LEGACY_SLOT_IDENTITIES = Object.freeze([
Object.freeze({ slotId: "dittto-primary", priority: 1 }),
Object.freeze({ slotId: "kaigo-secondary", priority: 2 }),
]);
const CURRENT_SLOT_IDENTITIES = Object.freeze([
Object.freeze({ slotId: "sellable-primary", priority: 1 }),
Object.freeze({ slotId: "dittto-secondary", priority: 2 }),
Object.freeze({ slotId: "kaigo-tertiary", priority: 3 }),
]);
const CURRENT_OPENROUTER_MODELS = Object.freeze([
Object.freeze({ id: "openai/gpt-5.6-luna", reasoningEffort: "max" }),
Object.freeze({ id: "deepseek/deepseek-v4-flash-0731" }),
Object.freeze({ id: "z-ai/glm-5.2" }),
Object.freeze({ id: "moonshotai/kimi-k3" }),
]);
const RUNTIME_KEYS = Object.freeze([
"schemaVersion",
"activationId",
"bundleGeneration",
"policyHash",
"credentialPoolStrategy",
"runtime",
"codex",
"openrouter",
]);
const RUNTIME_BEHAVIOR_KEYS = Object.freeze([
"apiMaxRetries",
"requestTimeoutSeconds",
]);
const SLOT_KEYS = Object.freeze([
"slotId",
"priority",
"accessToken",
"accountId",
"expiresAt",
"grantFingerprint",
]);
const OPENROUTER_KEYS = Object.freeze(["apiKey", "keyFingerprint", "models"]);
const MODEL_KEYS = Object.freeze(["id"]);
const MODEL_REASONING_KEYS = Object.freeze(["id", "reasoningEffort"]);
const MARKER_KEYS = Object.freeze([
"version",
"activationId",
"bundleGeneration",
"policyHash",
"sourceFingerprint",
"slots",
"openrouterKeyFingerprint",
"models",
]);
export class ModelAuthRuntimeError extends Error {
constructor(code) {
super(code);
this.name = "ModelAuthRuntimeError";
this.code = code;
}
}
function fail(code) {
throw new ModelAuthRuntimeError(code);
}
function isRecord(value) {
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
}
function exactKeys(value, keys) {
return (
isRecord(value) &&
Object.keys(value).sort().join("\0") === [...keys].sort().join("\0")
);
}
function bounded(value, minimum, maximum) {
return (
typeof value === "string" &&
value.length >= minimum &&
value.length <= maximum &&
!value.includes("\0")
);
}
function stableJson(value) {
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
if (isRecord(value)) {
return `{${Object.keys(value)
.sort()
.map((key) => `${JSON.stringify(key)}:${stableJson(value[key])}`)
.join(",")}}`;
}
return JSON.stringify(value);
}
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
function containsRuntimeRefreshOwnership(value) {
if (Array.isArray(value)) return value.some(containsRuntimeRefreshOwnership);
if (!isRecord(value)) return false;
return Object.entries(value).some(
([key, entry]) =>
FORBIDDEN_REFRESH_KEY.test(key) || containsRuntimeRefreshOwnership(entry)
);
}
function jwtExpiry(accessToken) {
try {
const parts = accessToken.split(".");
if (parts.length !== 3) return null;
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
return Number.isFinite(payload?.exp) ? Number(payload.exp) * 1000 : null;
} catch {
return null;
}
}
function assertRegularFileOrMissing(path) {
if (!existsSync(path)) return;
const entry = lstatSync(path);
if (entry.isSymbolicLink() || !entry.isFile())
fail("model_auth_store_rejected");
}
function atomicPrivateFile(path, bytes) {
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
writeFileSync(temporary, bytes, { flag: "wx", mode: 0o600 });
chmodSync(temporary, 0o600);
renameSync(temporary, path);
chmodSync(path, 0o600);
}
function projectionIdentity(value) {
return {
activationId: value.activationId,
bundleGeneration: value.bundleGeneration,
policyHash: value.policyHash,
slots: value.codex.map((slot) => ({
slotId: slot.slotId,
priority: slot.priority,
grantFingerprint: slot.grantFingerprint,
expiresAt: slot.expiresAt,
})),
openrouterKeyFingerprint: value.openrouter.keyFingerprint,
models: value.openrouter.models.map((model) =>
typeof model === "string" ? model : { ...model }
),
};
}
function markerFor(credential) {
return {
version:
credential.value.schemaVersion === MODEL_AUTH_RUNTIME_SCHEMA
? MARKER_VERSION
: LEGACY_MARKER_VERSION,
...credential.identity,
sourceFingerprint: credential.sourceFingerprint,
};
}
function parseMarker(path) {
assertRegularFileOrMissing(path);
if (!existsSync(path)) return null;
try {
const marker = JSON.parse(readFileSync(path, "utf8"));
if (
!exactKeys(marker, MARKER_KEYS) ||
![LEGACY_MARKER_VERSION, MARKER_VERSION].includes(marker.version) ||
!SAFE_ID.test(marker.activationId ?? "") ||
!Number.isSafeInteger(marker.bundleGeneration) ||
marker.bundleGeneration < 1 ||
!SHA256.test(marker.policyHash ?? "") ||
!FINGERPRINT.test(marker.sourceFingerprint ?? "") ||
!Array.isArray(marker.slots) ||
marker.slots.length !==
(marker.version === MARKER_VERSION ? CURRENT_SLOT_IDENTITIES.length : 2) ||
!FINGERPRINT.test(marker.openrouterKeyFingerprint ?? "") ||
!Array.isArray(marker.models) ||
marker.models.length < 1 ||
(marker.version === MARKER_VERSION &&
(marker.models.length !== CURRENT_OPENROUTER_MODELS.length ||
marker.models.some((model, index) => {
const expected = CURRENT_OPENROUTER_MODELS[index];
// Preserve the activated effort during a rolling max -> high update.
return index === 0
? !exactKeys(model, MODEL_REASONING_KEYS) ||
(model.id !== expected.id && !(index === 0 && model.id === "openai/gpt-6-luna")) ||
!["max", "high"].includes(model.reasoningEffort)
: stableJson(model) !== stableJson(expected);
})))
) {
return null;
}
return marker;
} catch {
return null;
}
}
function accessOnlyStoreFor(value) {
return {
version: 1,
credential_pool: {
"openai-codex": value.codex.map((slot) => ({
id: slot.slotId,
label: slot.slotId,
auth_type: "oauth",
priority: slot.priority,
source: "manual:device_code",
access_token: slot.accessToken,
account_id: slot.accountId,
expires_at: slot.expiresAt,
request_count: 0,
secret_fingerprint: slot.grantFingerprint,
})),
openrouter: [
{
id: "sellable-openrouter",
label: "sellable-openrouter",
auth_type: "api_key",
priority: 1,
source: "manual",
access_token: value.openrouter.apiKey,
base_url: "https://openrouter.ai/api/v1",
request_count: 0,
secret_fingerprint: value.openrouter.keyFingerprint,
},
],
},
active_provider: MODEL_AUTH_PROVIDER,
};
}
function essentialStoreMatches(path, credential) {
if (!existsSync(path)) return false;
try {
const stored = JSON.parse(readFileSync(path, "utf8"));
if (containsRuntimeRefreshOwnership(stored)) return false;
const codex = stored?.credential_pool?.[MODEL_AUTH_PROVIDER];
const openrouter = stored?.credential_pool?.openrouter;
if (
stored?.version !== 1 ||
stored?.active_provider !== MODEL_AUTH_PROVIDER ||
!Array.isArray(codex) ||
codex.length !== credential.value.codex.length ||
!Array.isArray(openrouter) ||
openrouter.length !== 1
) {
return false;
}
return (
codex.every((entry, index) => {
const expected = credential.value.codex[index];
return (
entry?.id === expected.slotId &&
entry?.priority === expected.priority &&
entry?.source === "manual:device_code" &&
entry?.auth_type === "oauth" &&
entry?.access_token === expected.accessToken &&
entry?.account_id === expected.accountId &&
entry?.expires_at === expected.expiresAt &&
entry?.secret_fingerprint === expected.grantFingerprint
);
}) &&
openrouter[0]?.id === "sellable-openrouter" &&
openrouter[0]?.auth_type === "api_key" &&
openrouter[0]?.access_token === credential.value.openrouter.apiKey &&
openrouter[0]?.secret_fingerprint ===
credential.value.openrouter.keyFingerprint
);
} catch {
return false;
}
}
export function parseModelAuthRuntimeCredential(secret, options = {}) {
if (
typeof secret !== "string" ||
!secret ||
Buffer.byteLength(secret, "utf8") > 64 * 1024
) {
fail("model_auth_projection_incomplete");
}
let value;
try {
value = JSON.parse(secret);
} catch {
fail("model_auth_projection_incomplete");
}
if (containsRuntimeRefreshOwnership(value)) {
fail("model_auth_runtime_refresh_ownership_rejected");
}
const isV2 = value?.schemaVersion === MODEL_AUTH_LEGACY_RUNTIME_SCHEMA;
const isV3 = value?.schemaVersion === MODEL_AUTH_RUNTIME_SCHEMA;
const expectedSlots = isV3
? CURRENT_SLOT_IDENTITIES
: LEGACY_SLOT_IDENTITIES;
if (
!exactKeys(value, RUNTIME_KEYS) ||
(!isV2 && !isV3) ||
value.credentialPoolStrategy !== "fill_first" ||
!SAFE_ID.test(value.activationId ?? "") ||
!Number.isSafeInteger(value.bundleGeneration) ||
value.bundleGeneration < 1 ||
!SHA256.test(value.policyHash ?? "") ||
!Array.isArray(value.codex) ||
value.codex.length !== expectedSlots.length ||
!exactKeys(value.runtime, RUNTIME_BEHAVIOR_KEYS) ||
!exactKeys(value.openrouter, OPENROUTER_KEYS)
) {
fail("model_auth_projection_incomplete");
}
if (
!Number.isInteger(value.runtime.apiMaxRetries) ||
value.runtime.apiMaxRetries < 0 ||
value.runtime.apiMaxRetries > 2 ||
!Number.isInteger(value.runtime.requestTimeoutSeconds) ||
value.runtime.requestTimeoutSeconds < 1 ||
value.runtime.requestTimeoutSeconds > 60
) {
fail("model_auth_projection_incomplete");
}
const nowValue = options.now ?? new Date();
const nowMs =
nowValue instanceof Date ? nowValue.getTime() : Number(nowValue);
if (!Number.isFinite(nowMs)) fail("model_auth_projection_incomplete");
for (const [index, slot] of value.codex.entries()) {
const expected = expectedSlots[index];
if (
!exactKeys(slot, SLOT_KEYS) ||
slot.slotId !== expected.slotId ||
slot.priority !== expected.priority ||
!bounded(slot.accessToken, 32, 32 * 1024) ||
!bounded(slot.accountId, 1, 512) ||
!bounded(slot.expiresAt, 10, 128) ||
!FINGERPRINT.test(slot.grantFingerprint ?? "")
) {
fail("model_auth_projection_incomplete");
}
const declaredExpiry = Date.parse(slot.expiresAt);
const embeddedExpiry = jwtExpiry(slot.accessToken);
if (
!Number.isFinite(declaredExpiry) ||
embeddedExpiry === null ||
// A provider expires_in estimate taken before its response can expire
// earlier than the JWT. Preserve that conservative lifetime; reject only
// estimates that overstate the token's validity beyond rounding tolerance.
declaredExpiry - embeddedExpiry > 1_000 ||
Math.min(declaredExpiry, embeddedExpiry) - nowMs <
MODEL_AUTH_MINIMUM_VALIDITY_MS
) {
fail("model_auth_projection_validity_insufficient");
}
}
if (
new Set(value.codex.map((slot) => slot.accountId)).size !==
expectedSlots.length ||
new Set(value.codex.map((slot) => slot.accessToken)).size !==
expectedSlots.length ||
new Set(value.codex.map((slot) => slot.grantFingerprint)).size !==
expectedSlots.length
) {
fail("model_auth_projection_incomplete");
}
if (
!bounded(value.openrouter.apiKey, 20, 4096) ||
!FINGERPRINT.test(value.openrouter.keyFingerprint ?? "") ||
!Array.isArray(value.openrouter.models) ||
value.openrouter.models.length < 1 ||
value.openrouter.models.length > 8 ||
(isV2
? value.openrouter.models.some(
(model) => typeof model !== "string" || !MODEL_ID.test(model)
) ||
new Set(value.openrouter.models).size !== value.openrouter.models.length
: value.openrouter.models.length !== CURRENT_OPENROUTER_MODELS.length)
) {
fail("model_auth_projection_incomplete");
}
if (isV3) {
for (const [index, model] of value.openrouter.models.entries()) {
const expected = CURRENT_OPENROUTER_MODELS[index];
const withReasoning = expected.reasoningEffort !== undefined;
if (
!exactKeys(model, withReasoning ? MODEL_REASONING_KEYS : MODEL_KEYS) ||
(model.id !== expected.id && !(index === 0 && model.id === "openai/gpt-6-luna")) ||
(withReasoning && !["max", "high"].includes(model.reasoningEffort))
) {
fail("model_auth_projection_incomplete");
}
}
}
const identity = projectionIdentity(value);
const store = accessOnlyStoreFor(value);
const sourceFingerprint = sha256(stableJson(identity)).slice(0, 16);
return Object.freeze({
provider: MODEL_AUTH_PROVIDER,
model: MODEL_AUTH_DEFAULT_MODEL,
reasoningEffort: MODEL_AUTH_REASONING_EFFORT,
activationId: value.activationId,
bundleGeneration: value.bundleGeneration,
policyHash: value.policyHash,
sourceFingerprint,
identity: Object.freeze(identity),
value: Object.freeze(value),
authJson: JSON.stringify(value),
hermesRootAuthJson: `${JSON.stringify(store, null, 2)}\n`,
testAccessToken: value.codex[0].accessToken,
});
}
export function modelAuthConfigOverlay(credential) {
if (!credential?.value || !SHA256.test(credential.policyHash ?? "")) {
fail("model_auth_projection_incomplete");
}
return Object.freeze({
// Phase 169 live Slack UAT showed that Hermes's default three inference
// attempts can keep a slow-but-open provider leg alive for five minutes.
// The ordered provider/model chain is the retry strategy for these
// runtimes, so bound each leg once and advance instead of retrying it.
agent: Object.freeze({
reasoning_effort: MODEL_AUTH_REASONING_EFFORT,
api_max_retries: credential.value.runtime.apiMaxRetries,
...(credential.value.schemaVersion === MODEL_AUTH_RUNTIME_SCHEMA
? {
reasoning_overrides: Object.freeze({
[credential.value.openrouter.models[0].id]: credential.value.openrouter.models[0].reasoningEffort,
}),
}
: {}),
}),
providers: Object.freeze({
"openai-codex": Object.freeze({
request_timeout_seconds: credential.value.runtime.requestTimeoutSeconds,
}),
openrouter: Object.freeze({
request_timeout_seconds: credential.value.runtime.requestTimeoutSeconds,
}),
}),
model: Object.freeze({
default: MODEL_AUTH_DEFAULT_MODEL,
provider: MODEL_AUTH_PROVIDER,
reasoning_effort: MODEL_AUTH_REASONING_EFFORT,
bundle_generation: credential.bundleGeneration,
policy_hash: credential.policyHash,
}),
credential_pool_strategies: Object.freeze({
"openai-codex": "fill_first",
openrouter: "fill_first",
}),
fallback_providers: Object.freeze(
credential.value.openrouter.models.map((entry) =>
Object.freeze({
provider: "openrouter",
model: typeof entry === "string" ? entry : entry.id,
})
)
),
});
}
export function reconcileHermesModelAuth({
authStorePath,
markerPath,
credential,
lifecycle,
}) {
if (
typeof authStorePath !== "string" ||
!authStorePath ||
typeof markerPath !== "string" ||
!markerPath ||
!credential?.value ||
!["ON", "OFF"].includes(lifecycle)
) {
fail("model_auth_store_rejected");
}
if (lifecycle === "OFF") {
return Object.freeze({
status: "desired_converged_materialization_pending_start",
materialized: false,
activationId: credential.activationId,
bundleGeneration: credential.bundleGeneration,
policyHash: credential.policyHash,
sourceFingerprint: credential.sourceFingerprint,
reseeded: false,
});
}
assertRegularFileOrMissing(authStorePath);
assertRegularFileOrMissing(markerPath);
const expectedMarker = markerFor(credential);
const priorMarker = parseMarker(markerPath);
const markerMatches = stableJson(priorMarker) === stableJson(expectedMarker);
const storeMatches = essentialStoreMatches(authStorePath, credential);
const reseeded = !markerMatches || !storeMatches;
if (reseeded) {
atomicPrivateFile(authStorePath, credential.hermesRootAuthJson);
atomicPrivateFile(
markerPath,
`${JSON.stringify(expectedMarker, null, 2)}\n`
);
} else {
chmodSync(authStorePath, 0o600);
chmodSync(markerPath, 0o600);
}
return Object.freeze({
status: "materialized_current",
materialized: true,
activationId: credential.activationId,
bundleGeneration: credential.bundleGeneration,
policyHash: credential.policyHash,
sourceFingerprint: credential.sourceFingerprint,
reseeded,
});
}
function safeRuntimeReason(value) {
return typeof value === "string" && /^[a-z0-9_.:-]{1,128}$/.test(value)
? value
: null;
}
function resetAt(value) {
if (typeof value === "string" && Number.isFinite(Date.parse(value))) {
return new Date(value).toISOString();
}
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
const milliseconds = value > 1_000_000_000_000 ? value : value * 1000;
return new Date(milliseconds).toISOString();
}
return null;
}
export function readModelAuthMaterialization({ authStorePath, markerPath }) {
assertRegularFileOrMissing(authStorePath);
const marker = parseMarker(markerPath);
const readbackSchema =
marker?.version === MARKER_VERSION
? MODEL_AUTH_READBACK_SCHEMA
: MODEL_AUTH_LEGACY_READBACK_SCHEMA;
if (!marker || !existsSync(authStorePath)) {
return Object.freeze({
schemaVersion: readbackSchema,
activationId: marker?.activationId ?? null,
bundleGeneration: marker?.bundleGeneration ?? null,
policyHash: marker?.policyHash ?? null,
provider: MODEL_AUTH_PROVIDER,
model: MODEL_AUTH_DEFAULT_MODEL,
fallbackDepth: marker?.models?.length ?? 0,
desiredStatus: marker ? "converged" : "unknown",
materializedStatus: "pending_start",
slots: Object.freeze([]),
openrouter: null,
activeProvider: null,
activeFallbackModelId: null,
});
}
let auth;
try {
auth = JSON.parse(readFileSync(authStorePath, "utf8"));
} catch {
fail("model_auth_store_rejected");
}
if (containsRuntimeRefreshOwnership(auth)) {
fail("model_auth_runtime_refresh_ownership_rejected");
}
const codex = auth?.credential_pool?.[MODEL_AUTH_PROVIDER];
const openrouter = auth?.credential_pool?.openrouter;
if (
!Array.isArray(codex) ||
![LEGACY_SLOT_IDENTITIES.length, CURRENT_SLOT_IDENTITIES.length].includes(
codex.length
) ||
codex.length !== marker.slots.length ||
!Array.isArray(openrouter)
) {
fail("model_auth_store_rejected");
}
const slots = codex.map((entry, index) => {
const expected =
marker.version === MARKER_VERSION
? CURRENT_SLOT_IDENTITIES[index]
: LEGACY_SLOT_IDENTITIES[index];
if (
entry?.id !== expected.slotId ||
entry?.priority !== expected.priority ||
!FINGERPRINT.test(entry?.secret_fingerprint ?? "") ||
!Number.isFinite(Date.parse(entry?.expires_at ?? ""))
) {
fail("model_auth_store_rejected");
}
const state = ["ok", "exhausted", "dead"].includes(entry.last_status)
? entry.last_status
: "ok";
return Object.freeze({
slotId: entry.id,
...(marker.version === MARKER_VERSION
? { priority: entry.priority }
: {}),
grantFingerprint: entry.secret_fingerprint,
expiresAt: new Date(entry.expires_at).toISOString(),
state,
lastErrorReason: safeRuntimeReason(entry.last_error_reason),
lastErrorResetAt: resetAt(entry.last_error_reset_at),
});
});
return Object.freeze({
schemaVersion: readbackSchema,
activationId: marker.activationId,
bundleGeneration: marker.bundleGeneration,
policyHash: marker.policyHash,
provider: MODEL_AUTH_PROVIDER,
model: MODEL_AUTH_DEFAULT_MODEL,
fallbackDepth: marker.models.length,
desiredStatus: "converged",
materializedStatus: "current",
slots: Object.freeze(slots),
openrouter: Object.freeze({
keyFingerprint: marker.openrouterKeyFingerprint,
state: ["ok", "exhausted", "dead"].includes(openrouter[0]?.last_status)
? openrouter[0].last_status
: "ok",
}),
activeProvider:
auth.active_provider === "openrouter"
? "openrouter"
: MODEL_AUTH_PROVIDER,
activeFallbackModelId:
auth.active_provider === "openrouter" &&
typeof auth.active_model === "string" &&
marker.models.some((model) =>
(typeof model === "string" ? model : model.id) === auth.active_model
)
? auth.active_model
: null,
...(marker.version === MARKER_VERSION
? {
models: Object.freeze(marker.models.map((model) => Object.freeze({ ...model }))),
reasoningOverrides: Object.freeze({
[marker.models[0].id]: marker.models[0].reasoningEffort,
}),
}
: {}),
});
}
/**
* @param {unknown} readback
* @param {{activationId: string, bundleGeneration: number, policyHash: string} | null} [expected]
*/
export function evaluateModelAuthReadback(readback, expected = null) {
const reject = (rejection) => ({ accepted: false, rejection });
if (!isRecord(readback)) return reject("readback_unparsable");
if (
![MODEL_AUTH_LEGACY_READBACK_SCHEMA, MODEL_AUTH_READBACK_SCHEMA].includes(
readback.schemaVersion
)
) {
return reject("readback_schema_mismatch");
}
if (readback.provider !== MODEL_AUTH_PROVIDER)
return reject("provider_mismatch");
if (readback.materializedStatus !== "current") {
return reject("materialization_pending_start");
}
if (expected && readback.activationId !== expected.activationId) {
return reject("activation_id_mismatch");
}
if (expected && readback.bundleGeneration !== expected.bundleGeneration) {
return reject("bundle_generation_mismatch");
}
if (expected && readback.policyHash !== expected.policyHash) {
return reject("policy_hash_mismatch");
}
const expectedSlotCount =
readback.schemaVersion === MODEL_AUTH_READBACK_SCHEMA ? 3 : 2;
if (
!Array.isArray(readback.slots) ||
readback.slots.length !== expectedSlotCount
) {
return reject("slot_pool_incomplete");
}
return { accepted: true, rejection: null };
}
/** Secret-free exact-image observation used by the bounded canary. */
export function modelAuthSelectionObservation(readback) {
const verdict = evaluateModelAuthReadback(readback);
if (!verdict.accepted) fail("model_auth_selection_observation_rejected");
const provider =
readback.activeProvider === "openrouter" ? "openrouter" : MODEL_AUTH_PROVIDER;
const modelId =
provider === "openrouter"
? readback.activeFallbackModelId
: MODEL_AUTH_DEFAULT_MODEL;
if (typeof modelId !== "string" || !modelId) {
fail("model_auth_selection_observation_rejected");
}
return Object.freeze({
provider,
modelId,
reasoningEffort:
readback.reasoningOverrides?.[modelId] ?? MODEL_AUTH_REASONING_EFFORT,
});
}