sneakoscope 8.1.2 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -58
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/fast-inline.js +5 -51
- package/dist/cli/command-manifest-lite.js +2 -1
- package/dist/cli/command-registry.js +2 -1
- package/dist/cli/global-mode-router.js +1 -1
- package/dist/cli/install-helpers-codex-lb-config.js +112 -914
- package/dist/cli/install-helpers-codex-lb-shared.js +3 -44
- package/dist/cli/install-helpers-install-support.js +4 -20
- package/dist/cli/install-helpers.js +36 -2716
- package/dist/cli/router.js +9 -9
- package/dist/commands/bridge-command-output.js +111 -0
- package/dist/commands/bridge.js +320 -0
- package/dist/commands/codex-app.js +39 -123
- package/dist/commands/doctor-helpers.js +380 -0
- package/dist/commands/doctor-profile.js +3 -0
- package/dist/commands/doctor.js +114 -873
- package/dist/commands/mad-sks.js +0 -4
- package/dist/config/skills-manifest.json +1 -1
- package/dist/core/agents/agent-effort-policy.js +11 -21
- package/dist/core/agents/agent-recursion-guard.js +26 -0
- package/dist/core/agents/agent-runner-codex-exec.js +7 -9
- package/dist/core/architecture-hardening/contracts/contracts.js +225 -161
- package/dist/core/architecture-hardening/state/state-service.js +49 -13
- package/dist/core/auto-review.js +15 -9
- package/dist/core/codex/codex-config-guard.js +8 -0
- package/dist/core/codex-adapter.js +8 -10
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +7 -29
- package/dist/core/codex-app/codex-app-launcher.js +10 -12
- package/dist/core/codex-app/codex-app-restart.js +10 -12
- package/dist/core/codex-app/menubar/constants.js +2 -5
- package/dist/core/codex-app/menubar/global-install.js +3 -2
- package/dist/core/codex-app/menubar/installer/result.js +23 -0
- package/dist/core/codex-app/menubar/installer/runtime.js +28 -0
- package/dist/core/codex-app/menubar/installer.js +5 -96
- package/dist/core/codex-app/menubar/migration.js +1 -42
- package/dist/core/codex-app/openrouter-provider.js +0 -78
- package/dist/core/codex-app.js +97 -360
- package/dist/core/codex-control/codex-app-server-runtime-env.js +8 -28
- package/dist/core/codex-control/codex-current-image-path-real-probe.js +2 -3
- package/dist/core/codex-control/codex-current-web-search-probe.js +2 -3
- package/dist/core/codex-control/codex-sdk-adapter.js +5 -48
- package/dist/core/codex-control/codex-task-runner.js +16 -60
- package/dist/core/codex-control/desktop-bridge-launch-guard.js +227 -0
- package/dist/core/codex-exec-output-schema.js +11 -13
- package/dist/core/codex-lb/bridge-contracts.js +2 -0
- package/dist/core/codex-lb/bridge-runtime-validation/capability.js +104 -0
- package/dist/core/codex-lb/bridge-runtime-validation/catalog.js +52 -0
- package/dist/core/codex-lb/bridge-runtime-validation/shared.js +109 -0
- package/dist/core/codex-lb/bridge-runtime-validation/status.js +250 -0
- package/dist/core/codex-lb/bridge-runtime-validation.js +106 -0
- package/dist/core/codex-lb/capability-runner.js +505 -201
- package/dist/core/codex-lb/codex-lb-env.js +179 -12
- package/dist/core/codex-lb/combined-catalog/builder.js +86 -0
- package/dist/core/codex-lb/combined-catalog/contracts.js +5 -0
- package/dist/core/codex-lb/combined-catalog/normalize.js +170 -0
- package/dist/core/codex-lb/combined-catalog/persistence.js +207 -0
- package/dist/core/codex-lb/combined-catalog/shared.js +12 -0
- package/dist/core/codex-lb/combined-catalog/storage.js +171 -0
- package/dist/core/codex-lb/combined-catalog.js +12 -0
- package/dist/core/codex-lb/desktop-bridge/client.js +4 -1
- package/dist/core/codex-lb/desktop-bridge/header-policy.js +48 -63
- package/dist/core/codex-lb/desktop-bridge/http-forward.js +115 -83
- package/dist/core/codex-lb/desktop-bridge/launchd.js +20 -13
- package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +4 -1
- package/dist/core/codex-lb/desktop-bridge/security.js +381 -267
- package/dist/core/codex-lb/desktop-bridge/server.js +148 -19
- package/dist/core/codex-lb/desktop-bridge/state.js +56 -70
- package/dist/core/codex-lb/desktop-bridge/types.js +6 -1
- package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +281 -106
- package/dist/core/codex-lb/desktop-bridge-migration/historical-config.js +245 -0
- package/dist/core/codex-lb/desktop-bridge-migration/historical-toml.js +56 -0
- package/dist/core/codex-lb/desktop-bridge-migration/metadata.js +73 -0
- package/dist/core/codex-lb/desktop-bridge-migration/receipt.js +52 -0
- package/dist/core/codex-lb/desktop-bridge-migration/retired-runtime-cleanup.js +106 -0
- package/dist/core/codex-lb/desktop-bridge-migration/types.js +1 -0
- package/dist/core/codex-lb/desktop-bridge-migration.js +238 -0
- package/dist/core/codex-lb/desktop-controller-v3/catalog.js +257 -0
- package/dist/core/codex-lb/desktop-controller-v3/diagnostics.js +62 -0
- package/dist/core/codex-lb/desktop-controller-v3/lifecycle-commands.js +203 -0
- package/dist/core/codex-lb/desktop-controller-v3/live-probes.js +293 -0
- package/dist/core/codex-lb/desktop-controller-v3/preflight-probes.js +144 -0
- package/dist/core/codex-lb/desktop-controller-v3/provider-commands.js +182 -0
- package/dist/core/codex-lb/desktop-controller-v3/shared.js +279 -0
- package/dist/core/codex-lb/desktop-controller-v3/status.js +269 -0
- package/dist/core/codex-lb/desktop-controller-v3/types.js +1 -0
- package/dist/core/codex-lb/desktop-controller-v3/verification.js +89 -0
- package/dist/core/codex-lb/desktop-controller-v3.js +67 -0
- package/dist/core/codex-lb/desktop-controller.js +2 -1730
- package/dist/core/codex-lb/desktop-service.js +462 -627
- package/dist/core/codex-lb/migration-receipt.js +560 -118
- package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +37 -53
- package/dist/core/codex-lb/probes/bridge-probe.js +125 -64
- package/dist/core/codex-lb/probes/catalog-probe.js +36 -136
- package/dist/core/codex-lb/probes/computer-use-probe.js +63 -39
- package/dist/core/codex-lb/probes/image-generation-probe.js +98 -41
- package/dist/core/codex-lb/probes/probe-evidence.js +32 -33
- package/dist/core/codex-lb/probes/voice-realtime-probe.js +69 -43
- package/dist/core/codex-lb/provider-credentials/configuration.js +127 -0
- package/dist/core/codex-lb/provider-credentials/locks.js +11 -0
- package/dist/core/codex-lb/provider-credentials/private-snapshot.js +28 -0
- package/dist/core/codex-lb/provider-credentials/removal.js +33 -0
- package/dist/core/codex-lb/provider-credentials/resolution.js +59 -0
- package/dist/core/codex-lb/provider-credentials/runtime.js +55 -0
- package/dist/core/codex-lb/provider-credentials/types.js +1 -0
- package/dist/core/codex-lb/provider-credentials/validation-store.js +137 -0
- package/dist/core/codex-lb/provider-credentials.js +5 -0
- package/dist/core/codex-lb/provider-registry.js +323 -0
- package/dist/core/codex-lb/provider-route-policy.js +118 -0
- package/dist/core/codex-lb/request-route-resolver.js +172 -0
- package/dist/core/codex-lb/route-index.js +148 -0
- package/dist/core/codex-lb/trusted-deep-evidence.js +158 -286
- package/dist/core/commands/basic-cli.js +1 -1
- package/dist/core/commands/check-command.js +3 -10
- package/dist/core/commands/gate-result-contract.js +10 -14
- package/dist/core/commands/intent-normalization/normalizer.js +1 -1
- package/dist/core/commands/mad-sks-command.js +2 -6
- package/dist/core/commands/release-command.js +11 -1
- package/dist/core/commands/telegram-command.js +46 -6
- package/dist/core/doctor/doctor-readiness-matrix.js +9 -7
- package/dist/core/doctor/skill-legacy-surface.js +5 -5
- package/dist/core/evidence/v2/evidence-key.js +30 -3
- package/dist/core/feature-fixtures.js +8 -1
- package/dist/core/feature-registry.js +3 -2
- package/dist/core/hooks-runtime/stop-finalization.js +11 -1
- package/dist/core/hooks-runtime/subagent-context.js +15 -1
- package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +1 -1
- package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
- package/dist/core/hooks-runtime.js +73 -87
- package/dist/core/image-ux-review/imagegen-adapter.js +108 -94
- package/dist/core/image-ux-review/real-callout-extractor.js +144 -14
- package/dist/core/imagegen/desktop-bridge-imagegen-target.js +77 -0
- package/dist/core/imagegen/imagegen-capability.js +43 -151
- package/dist/core/init/skills/filesystem.js +89 -0
- package/dist/core/init/skills/inventory.js +97 -0
- package/dist/core/init/skills/manifest.js +151 -0
- package/dist/core/init/skills.js +5 -325
- package/dist/core/init.js +0 -63
- package/dist/core/install/installed-package-smoke.js +1 -1
- package/dist/core/managed-assets/managed-assets-manifest.js +0 -1
- package/dist/core/policy/latest-version-guidance.js +15 -2
- package/dist/core/preflight/parallel-preflight-engine.js +27 -51
- package/dist/core/provider/provider-badge.js +9 -4
- package/dist/core/provider/provider-context.js +57 -107
- package/dist/core/providers/openrouter/openrouter-account.js +3 -1
- package/dist/core/providers/openrouter/openrouter-secret-store.js +91 -22
- package/dist/core/release/desktop-bridge-release-evidence.js +457 -0
- package/dist/core/release/gate-manifest.js +0 -1
- package/dist/core/release/main-push-guard.js +13 -0
- package/dist/core/release/main-push-receipt.js +11 -0
- package/dist/core/release/physical-release-gates.js +664 -61
- package/dist/core/release/publish-preflight.js +3 -3
- package/dist/core/release/release-gate-batch-runner.js +19 -6
- package/dist/core/release/release-gate-dag.js +33 -6
- package/dist/core/release/release-gate-node.js +1 -3
- package/dist/core/release/release-gate-output-contract.js +55 -0
- package/dist/core/release/release-pack-contract.js +1 -1
- package/dist/core/release/release-pack-receipt.js +209 -8
- package/dist/core/release/release-real-contract.js +1 -1
- package/dist/core/release/stage-publish.js +106 -28
- package/dist/core/retention/temp-lease.js +204 -0
- package/dist/core/retention.js +18 -195
- package/dist/core/routes.js +1 -2
- package/dist/core/safety/intent-contract/intent-contract.js +3 -3
- package/dist/core/subagents/naruto-host-credentials.js +6 -1
- package/dist/core/subagents/official-subagent-config.js +27 -9
- package/dist/core/subagents/official-subagent-runner.js +14 -31
- package/dist/core/subagents/wave-lifecycle.js +36 -8
- package/dist/core/subagents/wave-parent-guidance.js +2 -1
- package/dist/core/telegram/doctor.js +2 -2
- package/dist/core/telegram/liveness.js +10 -4
- package/dist/core/triwiki/context-graph/compiler/index.js +18 -18
- package/dist/core/update/update-migration-state/fast-mode-config.js +172 -0
- package/dist/core/update/update-migration-state/session-state-split.js +247 -0
- package/dist/core/update/update-migration-state/simple-stages.js +46 -0
- package/dist/core/update/update-migration-state.js +4 -481
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +28 -4
- package/dist/native/sks-menubar/Sources/OperationModels.swift +112 -2
- package/dist/native/sks-menubar/Sources/ProviderRouteExplanation.swift +21 -0
- package/dist/native/sks-menubar/Sources/ProvidersBridgeCatalog.swift +140 -0
- package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +107 -470
- package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +27 -197
- package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +335 -269
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +233 -437
- package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +16 -7
- package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +39 -9
- package/dist/native/sks-menubar/Sources/TelegramSupport.swift +56 -0
- package/dist/scripts/canonical-test-runner.js +7 -1
- package/dist/scripts/check-runtime-schemas.js +7 -2
- package/dist/scripts/codex-sdk-real-smoke-check.js +3 -1
- package/dist/scripts/desktop-bridge-capabilities-check.js +123 -0
- package/dist/scripts/{codex-lb-desktop-bridge-latency-check.js → desktop-bridge-latency-check.js} +61 -16
- package/dist/scripts/desktop-bridge-real-evidence-check.js +64 -0
- package/dist/scripts/{codex-lb-desktop-bridge-check.js → desktop-bridge-transport-check.js} +92 -155
- package/dist/scripts/desktop-bridge-transport-client.js +116 -0
- package/dist/scripts/desktop-bridge-unification-check.js +276 -0
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +12 -8
- package/dist/scripts/gate-policy-audit-check.js +52 -2
- package/dist/scripts/provider-badge-context-check.js +55 -12
- package/dist/scripts/publish-preflight.js +1 -2
- package/dist/scripts/release-affected-selector-check.js +1 -2
- package/dist/scripts/release-aggressive-resource-governor-check.js +1 -1
- package/dist/scripts/release-cache-glob-hashing-check.js +1 -0
- package/dist/scripts/release-cache-version-neutral-fixture-check.js +1 -0
- package/dist/scripts/release-full-parallelism-blackbox.js +1 -1
- package/dist/scripts/release-gate-batch-runner-check.js +9 -0
- package/dist/scripts/release-gate-dag-runner-check.js +6 -0
- package/dist/scripts/release-gate-dag-runner.js +4 -2
- package/dist/scripts/release-metadata-check.js +16 -3
- package/dist/scripts/release-pack-receipt.js +29 -6
- package/dist/scripts/release-physical-gates-check.js +39 -0
- package/dist/scripts/release-real-check.js +7 -5
- package/package.json +6 -8
- package/release-gates.v2.json +156 -157
- package/runtime-required-scripts.json +11 -11
- package/schemas/codex/desktop-bridge-status-v3.schema.json +286 -0
- package/schemas/codex/desktop-capabilities-v3.schema.json +198 -0
- package/schemas/release/release-gate-node.schema.json +2 -3
- package/dist/cli/codex-lb-setup-warning-output.js +0 -17
- package/dist/cli/install-helpers-codex-lb-chain.js +0 -529
- package/dist/commands/codex-lb.js +0 -1232
- package/dist/core/architecture-hardening/migration/migration.js +0 -111
- package/dist/core/codex-app/auxiliary-oauth-policy.js +0 -36
- package/dist/core/codex-app/catalog-compat/catalog-service.js +0 -104
- package/dist/core/codex-app/child-policy/child-policy.js +0 -35
- package/dist/core/codex-app/desktop-routing-snapshot.js +0 -233
- package/dist/core/codex-app/glm-model-profile.js +0 -1
- package/dist/core/codex-app/glm-profile-installer.js +0 -191
- package/dist/core/codex-app/glm-profile-schema.js +0 -42
- package/dist/core/codex-app/multi-provider-router.js +0 -391
- package/dist/core/codex-app/openrouter-activate.js +0 -405
- package/dist/core/codex-app/openrouter-model-catalog.js +0 -217
- package/dist/core/codex-app/provider-child-policy.js +0 -64
- package/dist/core/codex-app/provider-mode.js +0 -91
- package/dist/core/codex-app/provider-session-policy.js +0 -85
- package/dist/core/codex-app/session-policy/session-pinning.js +0 -68
- package/dist/core/codex-control/codex-lb-launch-recovery.js +0 -319
- package/dist/core/codex-lb/codex-lb-setup.js +0 -293
- package/dist/core/codex-lb/codex-lb-tool-catalog.js +0 -456
- package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +0 -290
- package/dist/core/codex-lb/desktop-center-credentials.js +0 -1083
- package/dist/core/codex-lb/desktop-mode.js +0 -32
- package/dist/core/codex-lb/desktop-real-evidence.js +0 -168
- package/dist/core/codex-lb/legacy-migration.js +0 -576
- package/dist/core/codex-lb/native-openai-transport/transport.js +0 -68
- package/dist/core/codex-lb/provider-routing/provider-router.js +0 -58
- package/dist/core/codex-lb/routing-truth.js +0 -327
- package/dist/core/imagegen/codex-lb-imagegen-target.js +0 -92
- package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +0 -118
- package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +0 -17
- package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +0 -331
- package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +0 -260
- package/dist/scripts/codex-lb-catalog-passthrough-check.js +0 -120
- package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +0 -169
- package/dist/scripts/codex-lb-desktop-capabilities-check.js +0 -287
- package/dist/scripts/codex-lb-desktop-real-evidence-check.js +0 -123
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +0 -114
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +0 -152
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +0 -231
package/dist/commands/mad-sks.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { madHighCommand } from '../core/commands/mad-sks-command.js';
|
|
2
|
-
import { maybePromptCodexUpdateForLaunch, maybePromptCodexLbSetupForLaunch, maybePromptSksUpdateForLaunch } from '../cli/install-helpers.js';
|
|
3
2
|
import { PACKAGE_VERSION } from '../core/fsx.js';
|
|
4
3
|
export async function run(_command, args = []) {
|
|
5
4
|
return madHighCommand(['--mad-sks', ...args], {
|
|
6
|
-
maybePromptSksUpdateForLaunch,
|
|
7
|
-
maybePromptCodexUpdateForLaunch,
|
|
8
|
-
maybePromptCodexLbSetupForLaunch,
|
|
9
5
|
packageVersion: PACKAGE_VERSION
|
|
10
6
|
});
|
|
11
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { codexModelEffortCapability } from '../codex-control/codex-model-capabilities.js';
|
|
2
|
-
import {
|
|
2
|
+
import { OPENROUTER_DEFAULT_MODEL } from '../codex-app/openrouter-provider.js';
|
|
3
3
|
import { managedOfficialSubagentRoleByName } from '../managed-assets/managed-assets-manifest.js';
|
|
4
4
|
import { isNarutoGpt56Model } from '../provider/model-router.js';
|
|
5
5
|
import { decideSubagentModel, subagentModelProfile } from '../subagents/model-policy.js';
|
|
@@ -231,13 +231,13 @@ export function decideAgentWorkerModel(input = {}) {
|
|
|
231
231
|
const risky = HIGH_SIGNAL_RE.test(text) || XHIGH_SIGNAL_RE.test(text);
|
|
232
232
|
const simple = SIMPLE_CODE_MOD_RE.test(simpleText) && !HIGH_SIGNAL_RE.test(simpleText) && !XHIGH_SIGNAL_RE.test(simpleText);
|
|
233
233
|
if (glmMain) {
|
|
234
|
-
const
|
|
234
|
+
const openRouterEffort = openRouterWorkerEffort({ effort, risky, simple });
|
|
235
235
|
return {
|
|
236
|
-
model:
|
|
237
|
-
model_reasoning_effort:
|
|
238
|
-
model_tier: `glm-5.2-${
|
|
239
|
-
model_profile:
|
|
240
|
-
reason: `
|
|
236
|
+
model: OPENROUTER_DEFAULT_MODEL,
|
|
237
|
+
model_reasoning_effort: openRouterEffort,
|
|
238
|
+
model_tier: `glm-5.2-${openRouterEffort === 'none' ? 'minimal' : openRouterEffort}`,
|
|
239
|
+
model_profile: desktopBridgeOpenRouterProfile(openRouterEffort),
|
|
240
|
+
reason: `desktop_bridge_openrouter_${openRouterEffort}_worker`
|
|
241
241
|
};
|
|
242
242
|
}
|
|
243
243
|
const modelEffort = risky || effort === 'high' || effort === 'xhigh'
|
|
@@ -259,11 +259,11 @@ function safeProfileSegment(value) {
|
|
|
259
259
|
}
|
|
260
260
|
function isGlmWorkerMode(mainModel) {
|
|
261
261
|
const model = String(mainModel || '').trim().toLowerCase();
|
|
262
|
-
return model ===
|
|
262
|
+
return model === OPENROUTER_DEFAULT_MODEL
|
|
263
263
|
|| model === 'glm-5.2'
|
|
264
264
|
|| model === 'glm5.2';
|
|
265
265
|
}
|
|
266
|
-
function
|
|
266
|
+
function openRouterWorkerEffort(input) {
|
|
267
267
|
if (input.effort === 'xhigh')
|
|
268
268
|
return 'xhigh';
|
|
269
269
|
if (input.risky || input.effort === 'high')
|
|
@@ -272,16 +272,6 @@ function glmWorkerEffort(input) {
|
|
|
272
272
|
return 'minimal';
|
|
273
273
|
return 'low';
|
|
274
274
|
}
|
|
275
|
-
function
|
|
276
|
-
|
|
277
|
-
return 'sks-openrouter-xhigh';
|
|
278
|
-
if (effort === 'high')
|
|
279
|
-
return 'sks-openrouter-high';
|
|
280
|
-
if (effort === 'medium')
|
|
281
|
-
return 'sks-openrouter-medium';
|
|
282
|
-
if (effort === 'low')
|
|
283
|
-
return 'sks-openrouter-low';
|
|
284
|
-
if (effort === 'none')
|
|
285
|
-
return 'sks-openrouter-default';
|
|
286
|
-
return 'sks-openrouter-minimal';
|
|
275
|
+
function desktopBridgeOpenRouterProfile(effort) {
|
|
276
|
+
return `desktop-bridge-openrouter-${effort}`;
|
|
287
277
|
}
|
|
@@ -74,6 +74,32 @@ export function scanAgentTextForRecursion(text) {
|
|
|
74
74
|
warning: violations.length ? 'agent_worker_recursion_attempt_blocked' : null
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
+
export function agentWorkerHookRecursionDecision(state = {}, payload = {}, command = '') {
|
|
78
|
+
if (!agentWorkerHookContext(state, payload))
|
|
79
|
+
return null;
|
|
80
|
+
const guard = scanAgentTextForRecursion(command);
|
|
81
|
+
if (guard.ok)
|
|
82
|
+
return null;
|
|
83
|
+
return {
|
|
84
|
+
decision: 'block',
|
|
85
|
+
permissionDecision: 'deny',
|
|
86
|
+
reason: `Agent command recursion guard blocked nested SKS route command in Codex PreToolUse hook: ${guard.violations.join(', ')}`
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export function agentWorkerHookContext(state = {}, payload = {}) {
|
|
90
|
+
const env = {
|
|
91
|
+
...(payload.env || {}),
|
|
92
|
+
...(payload.tool_input?.env || {}),
|
|
93
|
+
...(payload.toolInput?.env || {}),
|
|
94
|
+
...(payload.input?.env || {}),
|
|
95
|
+
...(payload.tool?.input?.env || {})
|
|
96
|
+
};
|
|
97
|
+
void state;
|
|
98
|
+
return Boolean(String(env.SKS_AGENT_WORKER || '') === '1'
|
|
99
|
+
|| String(env.SKS_DISABLE_ROUTE_RECURSION || '') === '1'
|
|
100
|
+
|| payload.agent_worker === true
|
|
101
|
+
|| payload.agentWorker === true);
|
|
102
|
+
}
|
|
77
103
|
export function assertNoAgentRecursion(text) {
|
|
78
104
|
const result = scanAgentTextForRecursion(text);
|
|
79
105
|
if (!result.ok)
|
|
@@ -4,7 +4,7 @@ import { managedProxyEnvForChild } from '../codex/managed-proxy-env.js';
|
|
|
4
4
|
import { agentWorkerEnv, validateAgentWorkerResult } from './agent-worker-pipeline.js';
|
|
5
5
|
import { fastModeEnv, resolveFastModePolicy } from './fast-mode-policy.js';
|
|
6
6
|
import { buildCodexExecArgs } from '../codex/codex-cli-syntax-builder.js';
|
|
7
|
-
import {
|
|
7
|
+
import { desktopBridgeLaunchBlockedProcessResult, withDesktopBridgeCliLaunchGuard } from '../codex-control/desktop-bridge-launch-guard.js';
|
|
8
8
|
import { prepareCodexAppServerRuntimeEnv } from '../codex-control/codex-app-server-runtime-env.js';
|
|
9
9
|
export function buildCodexExecAgentArgs(agent, prompt, opts = {}) {
|
|
10
10
|
const resultFile = opts.resultFile || defaultCodexResultFile(agent, opts);
|
|
@@ -78,16 +78,14 @@ export async function runCodexExecAgent(agent, slice, opts = {}) {
|
|
|
78
78
|
const runtimeEnv = await prepareCodexAppServerRuntimeEnv({ env: effectiveEnv });
|
|
79
79
|
const proxyEnv = managedProxyEnvForChild(runtimeEnv);
|
|
80
80
|
const execute = opts.runProcessImpl || runProcess;
|
|
81
|
-
const guarded = await
|
|
81
|
+
const guarded = await withDesktopBridgeCliLaunchGuard({
|
|
82
82
|
root: opts.cwd || process.cwd(),
|
|
83
83
|
env: runtimeEnv,
|
|
84
|
-
cliArgs: command.args.slice(0, -1)
|
|
85
|
-
|
|
86
|
-
...(opts.recoveryTimeoutMs === undefined ? {} : { timeoutMs: opts.recoveryTimeoutMs })
|
|
87
|
-
}, () => execute(opts.codexBin || 'codex', command.args, { cwd: opts.cwd || process.cwd(), env: { ...runtimeEnv, ...proxyEnv, ...fastModeEnv(fastPolicy), ...workerEnv }, timeoutMs: opts.timeoutMs || 30 * 60 * 1000, maxOutputBytes: 256 * 1024, stdoutFile, stderrFile }));
|
|
84
|
+
cliArgs: command.args.slice(0, -1)
|
|
85
|
+
}, (sanitizedEnv) => execute(opts.codexBin || 'codex', command.args, { cwd: opts.cwd || process.cwd(), env: { ...sanitizedEnv, ...proxyEnv, ...fastModeEnv(fastPolicy), ...workerEnv }, timeoutMs: opts.timeoutMs || 30 * 60 * 1000, maxOutputBytes: 256 * 1024, stdoutFile, stderrFile }));
|
|
88
86
|
const result = guarded.launched
|
|
89
87
|
? guarded.value
|
|
90
|
-
:
|
|
88
|
+
: desktopBridgeLaunchBlockedProcessResult(guarded.desktopBridgeLaunchGuard);
|
|
91
89
|
const report = await writeCodexProcessReport(opts.agentRoot || opts.cwd || process.cwd(), agent, {
|
|
92
90
|
project_hash: opts.projectHash || agent.project_hash || agent.root_hash || null,
|
|
93
91
|
command: [opts.codexBin || 'codex', ...command.args],
|
|
@@ -113,7 +111,7 @@ export async function runCodexExecAgent(agent, slice, opts = {}) {
|
|
|
113
111
|
stderr_bytes: result.stderrBytes,
|
|
114
112
|
truncated: result.truncated,
|
|
115
113
|
timed_out: result.timedOut,
|
|
116
|
-
|
|
114
|
+
desktop_bridge_launch_guard: guarded.desktopBridgeLaunchGuard,
|
|
117
115
|
dry_run: false
|
|
118
116
|
});
|
|
119
117
|
if (result.code === 0) {
|
|
@@ -138,7 +136,7 @@ export async function runCodexExecAgent(agent, slice, opts = {}) {
|
|
|
138
136
|
return { ...validated, status: 'blocked', blockers: [...validated.blockers, 'codex_exec_result_schema_invalid'] };
|
|
139
137
|
}
|
|
140
138
|
}
|
|
141
|
-
return validateAgentWorkerResult({ mission_id: opts.missionId || opts.mission_id || '', agent_id: agent.id, session_id: agent.session_id, persona_id: agent.persona_id || agent.id, task_slice_id: slice?.id || '', status: result.code === 0 ? 'done' : 'failed', backend: 'codex-exec', summary: result.stdout.slice(-1000) || result.stderr.slice(-1000), artifacts: [command.resultFile, report], blockers: result.code === 0 ? ['codex_exec_output_last_message_missing_or_invalid'] : [...(guarded.launched ? [] : guarded.
|
|
139
|
+
return validateAgentWorkerResult({ mission_id: opts.missionId || opts.mission_id || '', agent_id: agent.id, session_id: agent.session_id, persona_id: agent.persona_id || agent.id, task_slice_id: slice?.id || '', status: result.code === 0 ? 'done' : 'failed', backend: 'codex-exec', summary: result.stdout.slice(-1000) || result.stderr.slice(-1000), artifacts: [command.resultFile, report], blockers: result.code === 0 ? ['codex_exec_output_last_message_missing_or_invalid'] : [...(guarded.launched ? [] : guarded.desktopBridgeLaunchGuard.blockers), 'codex_exec_exit_' + result.code], confidence: 'verified_partial', unverified: result.code === 0 ? ['codex-exec stdout fallback; resultFile JSON missing or invalid'] : [], writes: [], source_intelligence_refs: agent.source_intelligence_refs || null, goal_mode_ref: agent.goal_mode_ref || null, codex_child_report: { desktop_bridge_launch_guard: guarded.desktopBridgeLaunchGuard }, verification: { status: result.code === 0 ? 'partial' : 'failed', checks: ['codex-exec-exit-code', 'codex-exec-process-report', 'codex-exec-output-last-message'] } });
|
|
142
140
|
}
|
|
143
141
|
function workerNoMcpDefault(agent, opts = {}, sandbox = 'read-only') {
|
|
144
142
|
if (opts.noMcp !== undefined)
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
+
import { BRIDGE_PROVIDER_IDS } from '../../codex-lb/bridge-contracts.js';
|
|
3
|
+
import { canonicalizeBridgeModelId, normalizeBridgeUpstreamModelId } from '../../codex-lb/route-index.js';
|
|
2
4
|
import { canonicalJson } from '../../json/canonical.js';
|
|
3
|
-
export const ARCHITECTURE_HARDENING_CONTRACT_VERSION = 'sks.architecture-hardening.
|
|
5
|
+
export const ARCHITECTURE_HARDENING_CONTRACT_VERSION = 'sks.architecture-hardening.contracts.v2';
|
|
6
|
+
export const MAX_AUDIT_PROJECTION_DEPTH = 32;
|
|
4
7
|
export class ArchitectureContractError extends Error {
|
|
5
8
|
code;
|
|
6
9
|
constructor(code) {
|
|
@@ -9,185 +12,246 @@ export class ArchitectureContractError extends Error {
|
|
|
9
12
|
this.code = code;
|
|
10
13
|
}
|
|
11
14
|
}
|
|
12
|
-
const
|
|
13
|
-
|
|
15
|
+
const HISTORICAL_SESSION_PIN_KEYS = [
|
|
16
|
+
'schema',
|
|
17
|
+
'session_id',
|
|
18
|
+
'mode',
|
|
19
|
+
'model',
|
|
20
|
+
'credential_class',
|
|
21
|
+
'allowed_models',
|
|
22
|
+
'lb_affinity_token_hash',
|
|
23
|
+
'child_policy_hash',
|
|
24
|
+
'catalog_version',
|
|
25
|
+
'parent_session_id'
|
|
26
|
+
];
|
|
27
|
+
const CURRENT_SESSION_PIN_KEYS = [
|
|
28
|
+
'thread_id',
|
|
29
|
+
'provider_id',
|
|
30
|
+
'public_model',
|
|
31
|
+
'upstream_model',
|
|
32
|
+
'catalog_generation',
|
|
33
|
+
'route_policy_generation',
|
|
34
|
+
'created_at'
|
|
35
|
+
];
|
|
36
|
+
const PROVIDERS = new Set(BRIDGE_PROVIDER_IDS);
|
|
14
37
|
const PROHIBITED_AUDIT_FIELDS = new Set([
|
|
38
|
+
'account_id',
|
|
15
39
|
'api_key',
|
|
16
|
-
'secret',
|
|
17
40
|
'authorization',
|
|
18
|
-
'
|
|
19
|
-
'
|
|
41
|
+
'client_secret',
|
|
42
|
+
'cookie',
|
|
20
43
|
'credential_fingerprint',
|
|
44
|
+
'password',
|
|
21
45
|
'refresh_token',
|
|
46
|
+
'request_body',
|
|
47
|
+
'secret',
|
|
48
|
+
'set_cookie',
|
|
22
49
|
'access_token'
|
|
23
50
|
]);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
return '
|
|
28
|
-
if (
|
|
29
|
-
return '
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
const models = stringArray(row.allowed_models, 'provider_policy_allowed_models_invalid');
|
|
51
|
-
if (models.length !== new Set(models).size || models.some((model) => !model.trim()))
|
|
52
|
-
fail('provider_policy_allowed_models_invalid');
|
|
53
|
-
if (!safeHash(row.child_policy_hash))
|
|
54
|
-
fail('provider_policy_child_hash_invalid');
|
|
55
|
-
if (!safeVersion(row.catalog_version))
|
|
56
|
-
fail('provider_policy_catalog_version_invalid');
|
|
57
|
-
return value;
|
|
58
|
-
}
|
|
59
|
-
export function validateArchitectureConfiguration(value) {
|
|
60
|
-
const row = objectRecord(value, 'architecture_configuration_invalid');
|
|
61
|
-
exactKeys(row, ['schema', 'policy', 'credential', 'catalog', 'features'], 'architecture_configuration_unknown_field');
|
|
62
|
-
if (row.schema !== 'sks.architecture-configuration.v1')
|
|
63
|
-
fail('architecture_configuration_schema_invalid');
|
|
64
|
-
parseProviderPolicySnapshot(row.policy);
|
|
65
|
-
validateCredentialReadiness(row.credential);
|
|
66
|
-
if (row.catalog !== null)
|
|
67
|
-
validateCatalogSnapshot(row.catalog);
|
|
68
|
-
if (!Array.isArray(row.features))
|
|
69
|
-
fail('architecture_configuration_features_invalid');
|
|
70
|
-
for (const feature of row.features)
|
|
71
|
-
validateFeatureCompatibility(feature);
|
|
72
|
-
assertSafeAuditProjection(value);
|
|
73
|
-
return value;
|
|
74
|
-
}
|
|
75
|
-
export function assertProviderPolicyCompatible(expected, actual) {
|
|
76
|
-
parseProviderPolicySnapshot(expected);
|
|
77
|
-
parseProviderPolicySnapshot(actual);
|
|
78
|
-
if (expected.mode !== actual.mode)
|
|
79
|
-
fail('provider_policy_mode_mismatch');
|
|
80
|
-
if (expected.credential_class !== actual.credential_class)
|
|
81
|
-
fail('provider_policy_credential_mismatch');
|
|
82
|
-
if (expected.child_policy_hash !== actual.child_policy_hash)
|
|
83
|
-
fail('provider_policy_child_mismatch');
|
|
84
|
-
if (expected.catalog_version !== actual.catalog_version)
|
|
85
|
-
fail('provider_policy_catalog_mismatch');
|
|
86
|
-
if (canonicalJson([...expected.allowed_models].sort()) !== canonicalJson([...actual.allowed_models].sort())) {
|
|
87
|
-
fail('provider_policy_model_allowlist_mismatch');
|
|
51
|
+
export function decodeHistoricalSessionPinV1(value, context) {
|
|
52
|
+
const row = record(value);
|
|
53
|
+
if (!row || row.schema !== 'sks.session-pin.v1')
|
|
54
|
+
return decodeFailure('historical_session_pin_invalid');
|
|
55
|
+
if (!hasExactKeys(row, HISTORICAL_SESSION_PIN_KEYS))
|
|
56
|
+
return decodeFailure('historical_session_pin_unknown_field');
|
|
57
|
+
const provider = historicalProvider(row.mode);
|
|
58
|
+
if (!provider)
|
|
59
|
+
return decodeFailure('historical_session_pin_mode_unsupported');
|
|
60
|
+
if (row.credential_class !== credentialClassForProvider(provider)) {
|
|
61
|
+
return decodeFailure('historical_session_pin_credential_mismatch');
|
|
62
|
+
}
|
|
63
|
+
const sessionId = safeIdentifier(row.session_id);
|
|
64
|
+
const publicModel = canonicalizeBridgeModelId(row.model);
|
|
65
|
+
if (!sessionId || !publicModel)
|
|
66
|
+
return decodeFailure('historical_session_pin_model_invalid');
|
|
67
|
+
const allowedModels = canonicalModelArray(row.allowed_models);
|
|
68
|
+
if (!allowedModels || !allowedModels.includes(publicModel)) {
|
|
69
|
+
return decodeFailure('historical_session_pin_model_not_allowed');
|
|
70
|
+
}
|
|
71
|
+
if (!safeHash(row.child_policy_hash)
|
|
72
|
+
|| (row.lb_affinity_token_hash !== null && !safeHash(row.lb_affinity_token_hash))) {
|
|
73
|
+
return decodeFailure('historical_session_pin_hash_invalid');
|
|
74
|
+
}
|
|
75
|
+
if (row.lb_affinity_token_hash !== null || row.parent_session_id !== null) {
|
|
76
|
+
return decodeFailure('historical_session_pin_semantics_unrepresentable');
|
|
88
77
|
}
|
|
78
|
+
if (!validDecodeContext(context))
|
|
79
|
+
return decodeFailure('historical_session_pin_context_invalid');
|
|
80
|
+
if (provider !== context.current_provider_id)
|
|
81
|
+
return decodeFailure('historical_session_pin_provider_mismatch');
|
|
82
|
+
if (row.catalog_version !== context.current_catalog_generation) {
|
|
83
|
+
return decodeFailure('historical_session_pin_catalog_stale');
|
|
84
|
+
}
|
|
85
|
+
if (row.child_policy_hash !== context.expected_child_policy_hash) {
|
|
86
|
+
return decodeFailure('historical_session_pin_child_policy_mismatch');
|
|
87
|
+
}
|
|
88
|
+
const pin = {
|
|
89
|
+
thread_id: sessionId,
|
|
90
|
+
provider_id: provider,
|
|
91
|
+
public_model: publicModel,
|
|
92
|
+
upstream_model: context.current_upstream_model,
|
|
93
|
+
catalog_generation: context.current_catalog_generation,
|
|
94
|
+
route_policy_generation: context.current_route_policy_generation,
|
|
95
|
+
created_at: context.created_at
|
|
96
|
+
};
|
|
97
|
+
return validateCurrentProviderSessionPin(pin)
|
|
98
|
+
? { ok: true, pin, blocker: null }
|
|
99
|
+
: decodeFailure('current_session_pin_invalid');
|
|
89
100
|
}
|
|
90
|
-
export function
|
|
101
|
+
export function validateCurrentProviderSessionPin(value) {
|
|
102
|
+
const row = record(value);
|
|
103
|
+
if (!row || !hasExactKeys(row, CURRENT_SESSION_PIN_KEYS))
|
|
104
|
+
return false;
|
|
105
|
+
const publicModel = canonicalizeBridgeModelId(row.public_model);
|
|
106
|
+
const upstreamModel = normalizeBridgeUpstreamModelId(row.upstream_model);
|
|
107
|
+
return Boolean(safeIdentifier(row.thread_id)
|
|
108
|
+
&& PROVIDERS.has(String(row.provider_id))
|
|
109
|
+
&& publicModel
|
|
110
|
+
&& publicModel === row.public_model
|
|
111
|
+
&& upstreamModel
|
|
112
|
+
&& upstreamModel === row.upstream_model
|
|
113
|
+
&& safeGeneration(row.catalog_generation)
|
|
114
|
+
&& safeGeneration(row.route_policy_generation)
|
|
115
|
+
&& validIso(row.created_at));
|
|
116
|
+
}
|
|
117
|
+
export function createSafeAuditProjection(value) {
|
|
91
118
|
const ancestors = new WeakSet();
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
119
|
+
return projectAuditValue(value, 0, ancestors);
|
|
120
|
+
}
|
|
121
|
+
export function assertSafeAuditProjection(value) {
|
|
122
|
+
createSafeAuditProjection(value);
|
|
123
|
+
}
|
|
124
|
+
export function stableArchitectureHash(value) {
|
|
125
|
+
const projection = createSafeAuditProjection(value);
|
|
126
|
+
return createHash('sha256').update(canonicalJson(projection)).digest('hex');
|
|
127
|
+
}
|
|
128
|
+
export function jsonRoundTrip(value) {
|
|
129
|
+
return JSON.parse(JSON.stringify(createSafeAuditProjection(value)));
|
|
130
|
+
}
|
|
131
|
+
function projectAuditValue(value, depth, ancestors) {
|
|
132
|
+
if (depth > MAX_AUDIT_PROJECTION_DEPTH)
|
|
133
|
+
fail('audit_projection_depth_exceeded');
|
|
134
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
135
|
+
return value;
|
|
136
|
+
if (typeof value === 'number') {
|
|
137
|
+
if (!Number.isFinite(value))
|
|
138
|
+
fail('audit_projection_number_invalid');
|
|
139
|
+
return Object.is(value, -0) ? 0 : value;
|
|
140
|
+
}
|
|
141
|
+
if (typeof value !== 'object')
|
|
142
|
+
fail('audit_projection_value_unsupported');
|
|
143
|
+
if (ancestors.has(value))
|
|
144
|
+
fail('audit_projection_cycle');
|
|
145
|
+
ancestors.add(value);
|
|
146
|
+
try {
|
|
147
|
+
if (Array.isArray(value)) {
|
|
148
|
+
const ownKeys = Reflect.ownKeys(value);
|
|
149
|
+
if (ownKeys.some((key) => typeof key === 'symbol'
|
|
150
|
+
|| (key !== 'length' && !/^(0|[1-9][0-9]*)$/.test(key)))) {
|
|
151
|
+
fail('audit_projection_array_property_unsupported');
|
|
105
152
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
fail('audit_projection_cycle');
|
|
112
|
-
ancestors.add(current);
|
|
113
|
-
try {
|
|
114
|
-
for (const [key, item] of Object.entries(current)) {
|
|
115
|
-
if (PROHIBITED_AUDIT_FIELDS.has(key.toLowerCase()))
|
|
116
|
-
fail('audit_projection_prohibited_field');
|
|
117
|
-
visit(item, depth + 1);
|
|
153
|
+
const projected = [];
|
|
154
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
155
|
+
if (!Object.prototype.hasOwnProperty.call(value, index))
|
|
156
|
+
fail('audit_projection_sparse_array');
|
|
157
|
+
projected.push(projectAuditValue(value[index], depth + 1, ancestors));
|
|
118
158
|
}
|
|
159
|
+
return projected;
|
|
119
160
|
}
|
|
120
|
-
|
|
121
|
-
|
|
161
|
+
const prototype = Object.getPrototypeOf(value);
|
|
162
|
+
if (prototype !== Object.prototype && prototype !== null)
|
|
163
|
+
fail('audit_projection_object_unsupported');
|
|
164
|
+
if (Object.getOwnPropertySymbols(value).length > 0)
|
|
165
|
+
fail('audit_projection_symbol_key');
|
|
166
|
+
const projected = {};
|
|
167
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
168
|
+
for (const key of Object.keys(descriptors).sort()) {
|
|
169
|
+
const descriptor = descriptors[key];
|
|
170
|
+
if (!descriptor.enumerable)
|
|
171
|
+
continue;
|
|
172
|
+
if (!('value' in descriptor))
|
|
173
|
+
fail('audit_projection_accessor_unsupported');
|
|
174
|
+
if (isSensitiveAuditField(key))
|
|
175
|
+
fail('audit_projection_prohibited_field');
|
|
176
|
+
projected[key] = projectAuditValue(descriptor.value, depth + 1, ancestors);
|
|
122
177
|
}
|
|
123
|
-
|
|
124
|
-
|
|
178
|
+
return projected;
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
ancestors.delete(value);
|
|
182
|
+
}
|
|
125
183
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
function safeVersion(value) {
|
|
186
|
-
return typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/.test(value);
|
|
184
|
+
function isSensitiveAuditField(key) {
|
|
185
|
+
const normalized = key.trim()
|
|
186
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
187
|
+
.toLowerCase()
|
|
188
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
189
|
+
.replace(/^_+|_+$/g, '');
|
|
190
|
+
if (PROHIBITED_AUDIT_FIELDS.has(normalized))
|
|
191
|
+
return true;
|
|
192
|
+
return [...PROHIBITED_AUDIT_FIELDS].some((field) => normalized.endsWith(`_${field}`));
|
|
193
|
+
}
|
|
194
|
+
function validDecodeContext(context) {
|
|
195
|
+
return PROVIDERS.has(String(context.current_provider_id))
|
|
196
|
+
&& normalizeBridgeUpstreamModelId(context.current_upstream_model) === context.current_upstream_model
|
|
197
|
+
&& safeGeneration(context.current_catalog_generation)
|
|
198
|
+
&& safeGeneration(context.current_route_policy_generation)
|
|
199
|
+
&& safeHash(context.expected_child_policy_hash)
|
|
200
|
+
&& validIso(context.created_at);
|
|
201
|
+
}
|
|
202
|
+
function historicalProvider(value) {
|
|
203
|
+
return value === 'codex-lb' || value === 'openrouter' ? value : null;
|
|
204
|
+
}
|
|
205
|
+
function credentialClassForProvider(provider) {
|
|
206
|
+
return provider === 'codex-lb' ? 'codex-lb-api-key' : 'openrouter-api-key';
|
|
207
|
+
}
|
|
208
|
+
function canonicalModelArray(value) {
|
|
209
|
+
if (!Array.isArray(value) || value.length > 10_000)
|
|
210
|
+
return null;
|
|
211
|
+
const models = [];
|
|
212
|
+
for (const entry of value) {
|
|
213
|
+
const model = canonicalizeBridgeModelId(entry);
|
|
214
|
+
if (!model || model !== entry || models.includes(model))
|
|
215
|
+
return null;
|
|
216
|
+
models.push(model);
|
|
217
|
+
}
|
|
218
|
+
return models;
|
|
219
|
+
}
|
|
220
|
+
function record(value) {
|
|
221
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
222
|
+
? value
|
|
223
|
+
: null;
|
|
224
|
+
}
|
|
225
|
+
function hasExactKeys(row, expected) {
|
|
226
|
+
const keys = Object.keys(row);
|
|
227
|
+
const allowed = new Set(expected);
|
|
228
|
+
return keys.length === expected.length
|
|
229
|
+
&& keys.every((key) => allowed.has(key))
|
|
230
|
+
&& expected.every((key) => Object.prototype.hasOwnProperty.call(row, key));
|
|
231
|
+
}
|
|
232
|
+
function safeIdentifier(value) {
|
|
233
|
+
if (typeof value !== 'string')
|
|
234
|
+
return null;
|
|
235
|
+
const text = value.trim();
|
|
236
|
+
return text && text.length <= 240 && /^[A-Za-z0-9][A-Za-z0-9._:-]*$/.test(text) ? text : null;
|
|
237
|
+
}
|
|
238
|
+
function safeGeneration(value) {
|
|
239
|
+
return typeof value === 'string'
|
|
240
|
+
&& value.length > 0
|
|
241
|
+
&& value.length <= 240
|
|
242
|
+
&& /^[A-Za-z0-9][A-Za-z0-9._:-]*$/.test(value);
|
|
187
243
|
}
|
|
188
244
|
function safeHash(value) {
|
|
189
245
|
return typeof value === 'string' && /^[a-f0-9]{64}$/.test(value);
|
|
190
246
|
}
|
|
247
|
+
function validIso(value) {
|
|
248
|
+
return typeof value === 'string'
|
|
249
|
+
&& Number.isFinite(Date.parse(value))
|
|
250
|
+
&& new Date(value).toISOString() === value;
|
|
251
|
+
}
|
|
252
|
+
function decodeFailure(blocker) {
|
|
253
|
+
return { ok: false, pin: null, blocker };
|
|
254
|
+
}
|
|
191
255
|
function fail(code) {
|
|
192
256
|
throw new ArchitectureContractError(code);
|
|
193
257
|
}
|