codex: expose auth broker pr preflight contract

This commit is contained in:
Codex
2026-05-21 14:04:33 +00:00
parent 7d80e2c259
commit dff355c5a4
6 changed files with 474 additions and 34 deletions
+24
View File
@@ -124,6 +124,17 @@ function brokerNeededResult(options: BrokerAdapterOptions): Record<string, unkno
message: "No auth broker endpoint is configured for this dry-run contract; runner env token coverage is reported only for migration diagnostics.",
tokenCoverage: runnerEnvTokenCoverage(),
brokerCoverage: brokerCoverage(options.endpoint),
authBroker: {
ok: false,
source: "broker/auth-broker-needed",
capability: "missing-token",
nextAction: "configure-auth-broker",
runnerEnvTokenRequired: false,
brokerIssuedTokenAvailable: false,
valuesRead: false,
valuesPrinted: false,
realPrCreateRequiresCommanderAuthorization: true,
},
next: [
"configure UNIDESK_AUTH_BROKER_URL or AUTH_BROKER_URL for broker-backed runner auth",
"keep GH_TOKEN/GITHUB_TOKEN out of ordinary runner env once broker mode is enabled",
@@ -185,6 +196,17 @@ function readyContract(options: BrokerAdapterOptions): Record<string, unknown> {
dryRun: true,
mutation: false,
capabilities: [...DEFAULT_CAPABILITIES],
authBroker: {
ok: true,
source: "auth-broker",
capability: "broker-issued-token",
nextAction: "use-auth-broker",
runnerEnvTokenRequired: false,
brokerIssuedTokenAvailable: true,
valuesRead: false,
valuesPrinted: false,
realPrCreateRequiresCommanderAuthorization: true,
},
tokenCoverage: {
ok: true,
source: "auth-broker",
@@ -199,9 +221,11 @@ function readyContract(options: BrokerAdapterOptions): Record<string, unknown> {
prCapabilityContract: {
targetBranch: options.base,
headBranch: options.head,
authSource: "broker-issued-token",
systemGhBinaryRequiredForWrites: false,
preflightCreatesPr: false,
preflightMergesPr: false,
realPrCreateRequiresCommanderAuthorization: true,
brokerProxy: {
ok: true,
operations: ["github.auth.status", "github.issue.read", "github.pr.read", "github.pr.create"],
+113 -23
View File
@@ -2418,6 +2418,51 @@ function compactUniDeskGhCliStatus(value: unknown): Record<string, unknown> {
};
}
function compactAuthBrokerRuntimeStatus(value: unknown): Record<string, unknown> {
const broker = asRecord(value);
const observed = broker !== null;
const capability = asRecord(broker?.capability);
const configured = broker?.configured === true || broker?.ok === true && broker?.source === "auth-broker";
const operations = Array.isArray(capability?.operations)
? capability.operations.map(String)
: ["github.auth.status", "github.issue.read", "github.pr.read", "github.pr.create"];
return {
ok: configured,
observed,
configured,
source: typeof broker?.source === "string" ? broker.source : configured ? "auth-broker" : "broker/auth-broker-needed",
endpointEnvKey: typeof broker?.endpointEnvKey === "string" ? broker.endpointEnvKey : null,
runnerEnvTokenRequired: broker?.runnerEnvTokenRequired === true,
credentialSource: typeof broker?.credentialSource === "string" ? broker.credentialSource : configured ? "broker-held-github-credential" : null,
failureKind: configured ? null : broker?.failureKind ?? "auth-missing",
degradedReason: configured ? null : broker?.degradedReason ?? "auth-broker-needed",
capability: {
source: typeof capability?.source === "string" ? capability.source : configured ? "broker-issued-token" : "missing-token",
githubRestAuth: capability?.githubRestAuth === true || configured,
operations,
systemGhBinaryRequiredForWrites: false,
preflightWritesRemote: false,
preflightCreatesPr: false,
preflightMergesPr: false,
realPrCreateRequiresCommanderAuthorization: true,
valuesPrinted: false,
},
nextAction: typeof broker?.nextAction === "string"
? broker.nextAction
: configured
? "use-auth-broker"
: "configure-auth-broker-or-env-token",
next: Array.isArray(broker?.next) ? broker.next.map(String) : configured
? ["keep PR preflight read-only; create a real PR only after commander authorization"]
: [
"configure UNIDESK_AUTH_BROKER_URL or AUTH_BROKER_URL for broker-backed runner auth",
"or inject GH_TOKEN/GITHUB_TOKEN into the Code Queue scheduler runtime secret until broker mode is live",
],
valuesRead: false,
valuesPrinted: false,
};
}
function compactAgentPortStatus(value: unknown): Record<string, unknown> {
const port = asRecord(value) ?? {};
return {
@@ -2428,43 +2473,80 @@ function compactAgentPortStatus(value: unknown): Record<string, unknown> {
};
}
function tokenCoverageStatus(credentials: Record<string, unknown>): Record<string, unknown> {
function tokenCoverageStatus(credentials: Record<string, unknown>, authBroker: Record<string, unknown>): Record<string, unknown> {
const ghTokenPresent = credentials.ghTokenPresent === true;
const githubTokenPresent = credentials.githubTokenPresent === true;
const anyEnvToken = ghTokenPresent || githubTokenPresent;
const anyGhCredentialStore = credentials.ghHostsConfigPresent === true || credentials.gitCredentialsPresent === true;
const authBrokerOk = authBroker.ok === true;
const effective = authBrokerOk || anyEnvToken;
const envSource = ghTokenPresent ? "GH_TOKEN" : githubTokenPresent ? "GITHUB_TOKEN" : null;
return {
ok: anyEnvToken,
source: ghTokenPresent ? "GH_TOKEN" : githubTokenPresent ? "GITHUB_TOKEN" : null,
ok: effective,
source: authBrokerOk ? "auth-broker" : envSource,
credentialSource: authBrokerOk ? "broker-issued-token" : anyEnvToken ? "env-token" : null,
ghTokenPresent,
githubTokenPresent,
ghCredentialStorePresent: anyGhCredentialStore,
runnerDisposition: anyEnvToken ? "ready" : "infra-blocked",
missing: anyEnvToken ? [] : ["GH_TOKEN", "GITHUB_TOKEN"],
scope: "scheduler-runner-env",
note: anyEnvToken
authBrokerPresent: authBrokerOk,
authBrokerSource: authBroker.source ?? null,
runnerEnvTokenRequired: !authBrokerOk,
runnerDisposition: effective ? "ready" : "infra-blocked",
missing: effective ? [] : ["GH_TOKEN", "GITHUB_TOKEN"],
envMissing: anyEnvToken ? [] : ["GH_TOKEN", "GITHUB_TOKEN"],
scope: authBrokerOk ? "broker-held-github-credential" : "scheduler-runner-env",
note: authBrokerOk
? "scheduler can use auth-broker for GitHub REST PR preflight without exposing GH_TOKEN/GITHUB_TOKEN to runner env"
: anyEnvToken
? "scheduler has a GitHub env token that can be forwarded to provider dev containers through CODE_QUEUE_REMOTE_CODEX_ENV_KEYS"
: "scheduler is missing GH_TOKEN/GITHUB_TOKEN; provider dev containers cannot receive a GitHub token even though CODE_QUEUE_REMOTE_CODEX_ENV_KEYS includes those keys",
: "scheduler is missing GH_TOKEN/GITHUB_TOKEN and auth-broker is not configured; provider dev containers cannot receive a GitHub token even though CODE_QUEUE_REMOTE_CODEX_ENV_KEYS includes those keys",
};
}
function authBrokerNeededStatus(tokenCoverage: Record<string, unknown>, systemGhBinary: Record<string, unknown>, unideskGhCli: Record<string, unknown>): Record<string, unknown> {
function authBrokerNeededStatus(tokenCoverage: Record<string, unknown>, runtimeAuthBroker: Record<string, unknown>, systemGhBinary: Record<string, unknown>, unideskGhCli: Record<string, unknown>): Record<string, unknown> {
const missing = Array.isArray(tokenCoverage.missing) ? tokenCoverage.missing.map(String) : [];
const needed = tokenCoverage.ok !== true;
const ready = tokenCoverage.ok === true;
const authBrokerReady = tokenCoverage.source === "auth-broker";
const needed = !ready;
const capability = asRecord(runtimeAuthBroker.capability) ?? {};
const capabilitySource = tokenCoverage.credentialSource ?? "missing-token";
const nextAction = authBrokerReady
? "use-auth-broker"
: ready
? "use-env-token-until-auth-broker-live"
: "configure-auth-broker-or-env-token";
return {
ok: !needed,
source: needed ? "broker/auth-broker-needed" : tokenCoverage.source ?? "runner-env-token",
ok: ready,
source: authBrokerReady ? "auth-broker" : needed ? "broker/auth-broker-needed" : tokenCoverage.source ?? "runner-env-token",
needed,
configured: false,
configured: runtimeAuthBroker.configured === true,
runnerDisposition: needed ? "infra-blocked" : "ready",
failureKind: needed ? "auth-missing" : null,
degradedReason: needed ? "auth-broker-needed" : null,
runnerEnvTokenRequiredWithoutBroker: true,
brokerCredentialSource: null,
runnerEnvTokenRequiredWithoutBroker: !authBrokerReady,
brokerCredentialSource: authBrokerReady ? runtimeAuthBroker.credentialSource ?? "broker-held-github-credential" : null,
capability: {
source: capabilitySource,
githubRestAuth: ready,
operations: Array.isArray(capability.operations)
? capability.operations.map(String)
: ["github.auth.status", "github.issue.read", "github.pr.read", "github.pr.create"],
systemGhBinaryRequiredForWrites: false,
unideskGhCliRequired: true,
preflightWritesRemote: false,
preflightCreatesPr: false,
preflightMergesPr: false,
realPrCreateRequiresCommanderAuthorization: true,
valuesPrinted: false,
},
nextAction,
valuesPrinted: false,
evidence: {
envTokenMissing: needed,
missing,
authBrokerObserved: runtimeAuthBroker.observed ?? false,
authBrokerConfigured: runtimeAuthBroker.configured ?? false,
authBrokerSource: runtimeAuthBroker.source ?? null,
systemGhBinaryOk: systemGhBinary.ok === true,
systemGhBinaryRequiredForWrites: false,
unideskGhCliObserved: unideskGhCli.observed ?? false,
@@ -2474,10 +2556,12 @@ function authBrokerNeededStatus(tokenCoverage: Record<string, unknown>, systemGh
},
next: needed
? [
"inject GH_TOKEN or GITHUB_TOKEN into the Code Queue scheduler runtime secret",
"or configure the planned auth-broker so PR preflight can use a broker-held GitHub credential without exposing runner env tokens",
"configure UNIDESK_AUTH_BROKER_URL or AUTH_BROKER_URL so PR preflight can use a broker-held GitHub credential without exposing runner env tokens",
"or inject GH_TOKEN/GITHUB_TOKEN into the Code Queue scheduler runtime secret until broker mode is live",
]
: [],
: authBrokerReady
? ["keep PR preflight read-only; create a real PR only after commander authorization"]
: ["env token path is ready; Auth Broker is still needed before removing runner env GitHub credentials"],
reference: "docs/reference/auth-broker.md#post-v1githubpr-preflight",
};
}
@@ -2486,6 +2570,7 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
const pull = asRecord(preflight.pullRequestDelivery) ?? {};
const tools = asRecord(pull.tools) ?? {};
const unideskGhCli = compactUniDeskGhCliStatus(pull.unideskGhCli);
const authBrokerRuntime = compactAuthBrokerRuntimeStatus(pull.authBroker);
const systemGhBinary = compactToolStatus(tools.gh);
const credentials = asRecord(pull.credentials) ?? {};
const git = asRecord(pull.git) ?? {};
@@ -2494,7 +2579,7 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
const proxy = asRecord(egress.proxy) ?? {};
const remote = asRecord(pull.remote);
const ports = asRecord(preflight.ports) ?? {};
const tokenCoverage = tokenCoverageStatus(credentials);
const tokenCoverage = tokenCoverageStatus(credentials, authBrokerRuntime);
const limitations = Array.isArray(pull.limitations) ? pull.limitations.map(String) : [];
const risks = Array.isArray(pull.risks) ? pull.risks.map(String) : [];
const ok = preflight.ok === true && tokenCoverage.ok === true;
@@ -2506,7 +2591,7 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
? "proxy-gap"
: null;
const degradedReason = failureKind === "auth-missing"
? "GH_TOKEN/GITHUB_TOKEN missing"
? "auth-broker-needed"
: failureKind === "git-remote-gap"
? "git remote probe failed"
: failureKind === "proxy-gap"
@@ -2529,12 +2614,15 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
pid: preflight.pid ?? null,
},
tokenCoverage,
authBroker: authBrokerNeededStatus(tokenCoverage, systemGhBinary, unideskGhCli),
authBroker: authBrokerNeededStatus(tokenCoverage, authBrokerRuntime, systemGhBinary, unideskGhCli),
prCapabilityContract: {
targetBranch,
tokenSource: tokenCoverage.source,
authSource: tokenCoverage.credentialSource,
realPrCreateRequiresCommanderAuthorization: true,
systemGhBinaryRequiredForWrites: false,
unideskGhCli,
authBroker: authBrokerRuntime,
pushDryRun: {
requested: options.pushDryRun,
ref: pushDryRunRef,
@@ -2624,8 +2712,10 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
risks,
runnerDisposition: ok ? "ready" : "infra-blocked",
recoveryHint: ok
? "Runner PR workflow has env-token coverage for the scheduler."
: "Inject GH_TOKEN or GITHUB_TOKEN into the Code Queue scheduler runtime secret for the target queue, then rerun this preflight before creating a PR.",
? tokenCoverage.source === "auth-broker"
? "Runner PR workflow has auth-broker coverage for GitHub REST preflight; real PR creation still requires commander authorization."
: "Runner PR workflow has env-token coverage for the scheduler."
: "Configure auth-broker or inject GH_TOKEN/GITHUB_TOKEN into the Code Queue scheduler runtime secret for the target queue, then rerun this preflight before creating a PR.",
commands: {
local: "bun scripts/cli.ts gh auth status --repo pikasTech/unidesk",
runner: "bun scripts/cli.ts codex pr-preflight --remote",