@quantiya/codevibe-core 2.0.1 → 2.0.2

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.
Files changed (282) hide show
  1. package/dist/__tests__/prompt-parser.test.d.ts +1 -0
  2. package/dist/adapter/registry.d.ts +69 -2
  3. package/dist/appsync/__tests__/appsync-client-event-source-filter.test.d.ts +1 -0
  4. package/dist/appsync/__tests__/appsync-client-task-group.test.d.ts +1 -0
  5. package/dist/appsync/__tests__/cleanup-subscription.test.d.ts +1 -0
  6. package/dist/appsync/__tests__/coerce-awsjson-and-review-summary.test.d.ts +1 -0
  7. package/dist/appsync/__tests__/cp1f-quorum-sdk.test.d.ts +1 -0
  8. package/dist/appsync/__tests__/event-throttle.test.d.ts +1 -0
  9. package/dist/appsync/appsync-client.d.ts +621 -10
  10. package/dist/appsync/event-throttle.d.ts +28 -0
  11. package/dist/appsync/index.d.ts +3 -0
  12. package/dist/appsync/queries.d.ts +19 -0
  13. package/dist/audit-keys/index.d.ts +32 -0
  14. package/dist/auth/auth-service.d.ts +32 -2
  15. package/dist/auth/auth-telemetry.d.ts +19 -1
  16. package/dist/auth/index.d.ts +1 -0
  17. package/dist/companion-mode/persist-preference.d.ts +1 -1
  18. package/dist/config/config.d.ts +8 -1
  19. package/dist/continuation/__tests__/dirty-state-collector.test.d.ts +1 -0
  20. package/dist/continuation/__tests__/integration.test.d.ts +1 -0
  21. package/dist/continuation/__tests__/packet-reader.test.d.ts +1 -0
  22. package/dist/continuation/__tests__/packet-writer.test.d.ts +1 -0
  23. package/dist/continuation/__tests__/parity.test.d.ts +1 -0
  24. package/dist/continuation/__tests__/status-cli.test.d.ts +1 -0
  25. package/dist/continuation/dirty-state-collector.d.ts +46 -0
  26. package/dist/continuation/index.d.ts +8 -0
  27. package/dist/continuation/packet-reader.d.ts +33 -0
  28. package/dist/continuation/packet-writer.d.ts +86 -0
  29. package/dist/continuation/types.d.ts +239 -0
  30. package/dist/credential-broker/__tests__/broker.test.d.ts +1 -0
  31. package/dist/credential-broker/__tests__/canonical.test.d.ts +1 -0
  32. package/dist/credential-broker/__tests__/scrubber.test.d.ts +1 -0
  33. package/dist/credential-broker/__tests__/upstream-client.test.d.ts +1 -0
  34. package/dist/credential-broker/__tests__/vendor-key-store.test.d.ts +1 -0
  35. package/dist/credential-broker/audit-sink.d.ts +69 -0
  36. package/dist/credential-broker/broker-config.d.ts +39 -0
  37. package/dist/credential-broker/broker-token.d.ts +123 -0
  38. package/dist/credential-broker/broker.d.ts +165 -0
  39. package/dist/credential-broker/canonical.d.ts +119 -0
  40. package/dist/credential-broker/index.d.ts +15 -0
  41. package/dist/credential-broker/scrubber.d.ts +45 -0
  42. package/dist/credential-broker/types.d.ts +141 -0
  43. package/dist/credential-broker/upstream-client.d.ts +20 -0
  44. package/dist/credential-broker/vendor-key-store.d.ts +54 -0
  45. package/dist/index.d.ts +6 -1
  46. package/dist/index.js +427 -124
  47. package/dist/keychain/__tests__/keychain-backend.test.d.ts +1 -0
  48. package/dist/keychain/keychain-backend.d.ts +82 -0
  49. package/dist/local-executor/__tests__/agentic-disposable-repo.test.d.ts +1 -0
  50. package/dist/local-executor/__tests__/agentic-resolve.test.d.ts +1 -0
  51. package/dist/local-executor/__tests__/agentic-resolver-flag.test.d.ts +1 -0
  52. package/dist/local-executor/__tests__/class-a-sign.test.d.ts +1 -0
  53. package/dist/local-executor/__tests__/class1-reconcilers.test.d.ts +1 -0
  54. package/dist/local-executor/__tests__/class2-resolver.test.d.ts +1 -0
  55. package/dist/local-executor/__tests__/confined-model-caller.test.d.ts +1 -0
  56. package/dist/local-executor/__tests__/conflict-classifier.test.d.ts +1 -0
  57. package/dist/local-executor/__tests__/conflict-resolution-durable-store.test.d.ts +1 -0
  58. package/dist/local-executor/__tests__/conflict-resolution-store.test.d.ts +1 -0
  59. package/dist/local-executor/__tests__/cp1f-quorum-consumer.test.d.ts +1 -0
  60. package/dist/local-executor/__tests__/cp7-audit-writer.test.d.ts +1 -0
  61. package/dist/local-executor/__tests__/durable-store.test.d.ts +1 -0
  62. package/dist/local-executor/__tests__/git-lock-retry.test.d.ts +1 -0
  63. package/dist/local-executor/__tests__/implementor-argv.test.d.ts +1 -0
  64. package/dist/local-executor/__tests__/local-executor-teams.test.d.ts +1 -0
  65. package/dist/local-executor/__tests__/merge-conflict-extract.test.d.ts +1 -0
  66. package/dist/local-executor/__tests__/merge-conflict-git.integration.test.d.ts +1 -0
  67. package/dist/local-executor/__tests__/merge-conflict-resolve-agentic.integration.test.d.ts +1 -0
  68. package/dist/local-executor/__tests__/merge-conflict-resolve.integration.test.d.ts +1 -0
  69. package/dist/local-executor/__tests__/merge-journal-store.test.d.ts +1 -0
  70. package/dist/local-executor/__tests__/merge-train-agentic-recovery.integration.test.d.ts +1 -0
  71. package/dist/local-executor/__tests__/merge-train-w3.integration.test.d.ts +1 -0
  72. package/dist/local-executor/__tests__/merge-train-waveb.integration.test.d.ts +1 -0
  73. package/dist/local-executor/__tests__/merge-train.test.d.ts +1 -0
  74. package/dist/local-executor/__tests__/promote-wal-store.test.d.ts +1 -0
  75. package/dist/local-executor/__tests__/revert-reconcile.test.d.ts +1 -0
  76. package/dist/local-executor/__tests__/revert-runner.test.d.ts +1 -0
  77. package/dist/local-executor/__tests__/shared-contract-detector.test.d.ts +1 -0
  78. package/dist/local-executor/__tests__/substrate-engage.test.d.ts +1 -0
  79. package/dist/local-executor/__tests__/team-execution-flag.test.d.ts +1 -0
  80. package/dist/local-executor/__tests__/track-registry.test.d.ts +1 -0
  81. package/dist/local-executor/__tests__/wb2-review-bundle.test.d.ts +1 -0
  82. package/dist/local-executor/__tests__/wb2-substrate-spawn.live.test.d.ts +1 -0
  83. package/dist/local-executor/__tests__/workspace-shadow.test.d.ts +1 -0
  84. package/dist/local-executor/__tests__/worktree-merge.test.d.ts +1 -0
  85. package/dist/local-executor/agentic-disposable-repo.d.ts +52 -0
  86. package/dist/local-executor/agentic-resolve.d.ts +54 -0
  87. package/dist/local-executor/agentic-resolver-flag.d.ts +9 -0
  88. package/dist/local-executor/authority.d.ts +33 -1
  89. package/dist/local-executor/class-a-emit.d.ts +3 -1
  90. package/dist/local-executor/class-a-sign.d.ts +57 -0
  91. package/dist/local-executor/class-b-consumer.d.ts +159 -4
  92. package/dist/local-executor/class-b-verify.d.ts +30 -0
  93. package/dist/local-executor/class1-reconcilers.d.ts +58 -0
  94. package/dist/local-executor/class2-resolver.d.ts +74 -0
  95. package/dist/local-executor/confined-model-caller.d.ts +39 -0
  96. package/dist/local-executor/conflict-classifier.d.ts +21 -0
  97. package/dist/local-executor/conflict-resolution-durable-store.d.ts +61 -0
  98. package/dist/local-executor/conflict-resolution-store.d.ts +210 -0
  99. package/dist/local-executor/conflict-types.d.ts +86 -0
  100. package/dist/local-executor/cp7-audit-writer.d.ts +152 -0
  101. package/dist/local-executor/durable-store.d.ts +334 -0
  102. package/dist/local-executor/git-lock-retry.d.ts +40 -0
  103. package/dist/local-executor/hook-bridge.d.ts +1 -1
  104. package/dist/local-executor/implementor-argv.d.ts +183 -0
  105. package/dist/local-executor/index.d.ts +44 -3
  106. package/dist/local-executor/local-executor-impl.d.ts +645 -4
  107. package/dist/local-executor/merge-conflict-extract.d.ts +34 -0
  108. package/dist/local-executor/merge-conflict-resolve.d.ts +101 -0
  109. package/dist/local-executor/merge-journal-store.d.ts +311 -0
  110. package/dist/local-executor/merge-train.d.ts +713 -0
  111. package/dist/local-executor/promote-wal-store.d.ts +301 -0
  112. package/dist/local-executor/resolution-set-index.d.ts +51 -0
  113. package/dist/local-executor/revert-reconcile.d.ts +89 -0
  114. package/dist/local-executor/revert-runner.d.ts +17 -0
  115. package/dist/local-executor/shared-contract-detector.d.ts +57 -0
  116. package/dist/local-executor/spawn.d.ts +29 -1
  117. package/dist/local-executor/task-group-types.d.ts +346 -0
  118. package/dist/local-executor/team-execution-flag.d.ts +21 -0
  119. package/dist/local-executor/track-registry.d.ts +50 -0
  120. package/dist/local-executor/types.d.ts +238 -4
  121. package/dist/local-executor/wb2-review-bundle.d.ts +59 -0
  122. package/dist/local-executor/workspace-shadow.d.ts +290 -0
  123. package/dist/local-executor/worktree-merge.d.ts +601 -0
  124. package/dist/local-model/__tests__/installer.test.d.ts +1 -0
  125. package/dist/local-model/__tests__/manager.test.d.ts +1 -0
  126. package/dist/local-model/__tests__/ollama.test.d.ts +1 -0
  127. package/dist/local-model/__tests__/runtime.test.d.ts +1 -0
  128. package/dist/local-model/__tests__/state.test.d.ts +1 -0
  129. package/dist/local-model/manager.d.ts +119 -0
  130. package/dist/local-model/ollama.d.ts +27 -0
  131. package/dist/local-model/runtime.d.ts +27 -0
  132. package/dist/local-model/state.d.ts +32 -0
  133. package/dist/orchestration/detect-agents.d.ts +15 -2
  134. package/dist/orchestration/setup-types.d.ts +2 -1
  135. package/dist/orchestration-shell/__tests__/attachments.test.d.ts +1 -0
  136. package/dist/orchestration-shell/__tests__/audit-browser.test.d.ts +1 -0
  137. package/dist/orchestration-shell/__tests__/audited-path-fixes.test.d.ts +1 -0
  138. package/dist/orchestration-shell/__tests__/bracketed-paste.test.d.ts +1 -0
  139. package/dist/orchestration-shell/__tests__/cli-group-halt-wiring.test.d.ts +1 -0
  140. package/dist/orchestration-shell/__tests__/cli-orchestration-session-bootstrap.test.d.ts +1 -0
  141. package/dist/orchestration-shell/__tests__/cli-probe-group-status.test.d.ts +1 -0
  142. package/dist/orchestration-shell/__tests__/cli-quorum-loop-tier.test.d.ts +1 -0
  143. package/dist/orchestration-shell/__tests__/cli-verdict-classifier-wiring.test.d.ts +1 -0
  144. package/dist/orchestration-shell/__tests__/context-store.test.d.ts +1 -0
  145. package/dist/orchestration-shell/__tests__/cp10-585-accept-echo-target.test.d.ts +1 -0
  146. package/dist/orchestration-shell/__tests__/cp10-585-loop.test.d.ts +1 -0
  147. package/dist/orchestration-shell/__tests__/cp10-585-prompts.test.d.ts +1 -0
  148. package/dist/orchestration-shell/__tests__/cp12-w2b-team-loop.test.d.ts +1 -0
  149. package/dist/orchestration-shell/__tests__/cp12-w4-team-recovery.test.d.ts +1 -0
  150. package/dist/orchestration-shell/__tests__/cp1f-quorum-loop.test.d.ts +1 -0
  151. package/dist/orchestration-shell/__tests__/cp606-team-track-user-resolved.test.d.ts +1 -0
  152. package/dist/orchestration-shell/__tests__/cp7-reviewer-substrate.test.d.ts +1 -0
  153. package/dist/orchestration-shell/__tests__/declared-test-runner.test.d.ts +1 -0
  154. package/dist/orchestration-shell/__tests__/familiarize-routing.test.d.ts +1 -0
  155. package/dist/orchestration-shell/__tests__/gate-decision-submit.test.d.ts +1 -0
  156. package/dist/orchestration-shell/__tests__/gate-details-panel.test.d.ts +1 -0
  157. package/dist/orchestration-shell/__tests__/gate-verdict-details-dispatch.test.d.ts +1 -0
  158. package/dist/orchestration-shell/__tests__/group-decision-submit.test.d.ts +1 -0
  159. package/dist/orchestration-shell/__tests__/image-attach-e2e.test.d.ts +1 -0
  160. package/dist/orchestration-shell/__tests__/input-bar-autocomplete.test.d.ts +1 -0
  161. package/dist/orchestration-shell/__tests__/live-region-cap.test.d.ts +1 -0
  162. package/dist/orchestration-shell/__tests__/live-static-order.test.d.ts +1 -0
  163. package/dist/orchestration-shell/__tests__/model-cli.test.d.ts +1 -0
  164. package/dist/orchestration-shell/__tests__/non-gate-prompt-routing.test.d.ts +1 -0
  165. package/dist/orchestration-shell/__tests__/orchestration-app-group-decision-transport.test.d.ts +1 -0
  166. package/dist/orchestration-shell/__tests__/orchestration-app-layout.test.d.ts +1 -0
  167. package/dist/orchestration-shell/__tests__/reissue-team-retained-spec.test.d.ts +1 -0
  168. package/dist/orchestration-shell/__tests__/review-summary-render.test.d.ts +1 -0
  169. package/dist/orchestration-shell/__tests__/reviewer-wizard.test.d.ts +1 -0
  170. package/dist/orchestration-shell/__tests__/reviewers-format.test.d.ts +1 -0
  171. package/dist/orchestration-shell/__tests__/root-discovery.test.d.ts +1 -0
  172. package/dist/orchestration-shell/__tests__/serialize-submissions.test.d.ts +1 -0
  173. package/dist/orchestration-shell/__tests__/slash-suggest.test.d.ts +1 -0
  174. package/dist/orchestration-shell/__tests__/status-format.test.d.ts +1 -0
  175. package/dist/orchestration-shell/__tests__/task-progress.test.d.ts +1 -0
  176. package/dist/orchestration-shell/__tests__/team-decompose-routing.test.d.ts +1 -0
  177. package/dist/orchestration-shell/__tests__/team-decompose-types.test.d.ts +1 -0
  178. package/dist/orchestration-shell/__tests__/team-decompose.test.d.ts +1 -0
  179. package/dist/orchestration-shell/__tests__/team-e2e-smoke.test.d.ts +1 -0
  180. package/dist/orchestration-shell/__tests__/tier2-reviewer-selection.test.d.ts +1 -0
  181. package/dist/orchestration-shell/__tests__/web-browsing.test.d.ts +1 -0
  182. package/dist/orchestration-shell/attachments.d.ts +152 -0
  183. package/dist/orchestration-shell/audit-browser.d.ts +115 -0
  184. package/dist/orchestration-shell/audit-runner.d.ts +59 -0
  185. package/dist/orchestration-shell/bracketed-paste.d.ts +26 -0
  186. package/dist/orchestration-shell/cli.d.ts +336 -1
  187. package/dist/orchestration-shell/cli.js +39318 -3436
  188. package/dist/orchestration-shell/components/AuditLogPanel.d.ts +11 -0
  189. package/dist/orchestration-shell/components/ConversationPane.d.ts +7 -1
  190. package/dist/orchestration-shell/components/GateDetailsPanel.d.ts +57 -0
  191. package/dist/orchestration-shell/components/GatePanelEntry.d.ts +9 -0
  192. package/dist/orchestration-shell/components/GatePromptEntry.d.ts +7 -0
  193. package/dist/orchestration-shell/components/InputBar.d.ts +17 -3
  194. package/dist/orchestration-shell/components/LiveProgressLine.d.ts +8 -0
  195. package/dist/orchestration-shell/components/MultiTrackStatusNode.d.ts +8 -0
  196. package/dist/orchestration-shell/components/OrchestrationApp.d.ts +81 -15
  197. package/dist/orchestration-shell/components/ReviewerSetupWizard.d.ts +24 -0
  198. package/dist/orchestration-shell/components/StatusBar.d.ts +15 -2
  199. package/dist/orchestration-shell/context-store.d.ts +389 -0
  200. package/dist/orchestration-shell/declared-test-runner.d.ts +84 -0
  201. package/dist/orchestration-shell/emit-shell-event.d.ts +1 -1
  202. package/dist/orchestration-shell/gate-decision-submit.d.ts +245 -0
  203. package/dist/orchestration-shell/gate-prompts.d.ts +361 -3
  204. package/dist/orchestration-shell/index.d.ts +613 -1
  205. package/dist/orchestration-shell/ink-runtime.d.ts +21 -1
  206. package/dist/orchestration-shell/live-region-cap.d.ts +70 -0
  207. package/dist/orchestration-shell/live-static-order.d.ts +22 -0
  208. package/dist/orchestration-shell/non-tty-fallback.d.ts +21 -0
  209. package/dist/orchestration-shell/quorum-loop.d.ts +1900 -0
  210. package/dist/orchestration-shell/root-discovery.d.ts +25 -0
  211. package/dist/orchestration-shell/route-browse.d.ts +20 -0
  212. package/dist/orchestration-shell/slash-router.d.ts +20 -1
  213. package/dist/orchestration-shell/slash-routes/continuation.d.ts +71 -0
  214. package/dist/orchestration-shell/slash-routes/reviewers.d.ts +41 -0
  215. package/dist/orchestration-shell/slash-suggest.d.ts +29 -0
  216. package/dist/orchestration-shell/status-format.d.ts +59 -0
  217. package/dist/orchestration-shell/task-progress.d.ts +122 -0
  218. package/dist/orchestration-shell/team-decompose.d.ts +196 -0
  219. package/dist/orchestration-shell/types.d.ts +363 -3
  220. package/dist/orchestration-shell/vendor/ink-parse-keypress.d.ts +42 -0
  221. package/dist/orchestration-shell/web/extract.d.ts +11 -0
  222. package/dist/orchestration-shell/web/fetch.d.ts +15 -0
  223. package/dist/orchestration-shell/web/ip.d.ts +26 -0
  224. package/dist/orchestration-shell/web/sanitize.d.ts +14 -0
  225. package/dist/orchestration-shell/web/search.d.ts +16 -0
  226. package/dist/planner/__tests__/local-gemma.test.d.ts +1 -0
  227. package/dist/planner/index.d.ts +2 -0
  228. package/dist/planner/local-advisory.d.ts +84 -0
  229. package/dist/planner/local-gemma.d.ts +23 -0
  230. package/dist/planner/types.d.ts +16 -6
  231. package/dist/reviewer/__tests__/antigravity-provider.test.d.ts +1 -0
  232. package/dist/reviewer/__tests__/claude-provider-json.test.d.ts +1 -0
  233. package/dist/reviewer/__tests__/cp7-reviewer-sandbox.test.d.ts +1 -0
  234. package/dist/reviewer/__tests__/output-parser-classifier-helpers.test.d.ts +1 -0
  235. package/dist/reviewer/__tests__/verdict-classifier.test.d.ts +1 -0
  236. package/dist/reviewer/index.d.ts +2 -0
  237. package/dist/reviewer/output-parser.d.ts +48 -12
  238. package/dist/reviewer/provider.d.ts +107 -3
  239. package/dist/reviewer/providers/__tests__/failure-classifier.test.d.ts +1 -0
  240. package/dist/reviewer/providers/antigravity.d.ts +49 -0
  241. package/dist/reviewer/providers/claude.d.ts +19 -4
  242. package/dist/reviewer/providers/codex.d.ts +47 -5
  243. package/dist/reviewer/providers/failure-classifier.d.ts +26 -0
  244. package/dist/reviewer/providers/gemini.d.ts +5 -4
  245. package/dist/reviewer/registry.d.ts +5 -5
  246. package/dist/reviewer/subprocess.d.ts +37 -0
  247. package/dist/reviewer/token-usage.d.ts +32 -0
  248. package/dist/reviewer/types.d.ts +5 -5
  249. package/dist/reviewer/verdict-classifier.d.ts +62 -0
  250. package/dist/session/__tests__/prepare-event-timestamp.test.d.ts +1 -0
  251. package/dist/session/index.d.ts +1 -0
  252. package/dist/session/prepare-event-timestamp.d.ts +30 -0
  253. package/dist/substrate/__tests__/docker.test.d.ts +1 -0
  254. package/dist/substrate/__tests__/forwarder.test.d.ts +1 -0
  255. package/dist/substrate/__tests__/git-proxy.test.d.ts +1 -0
  256. package/dist/substrate/__tests__/sandbox-exec.test.d.ts +1 -0
  257. package/dist/substrate/__tests__/substrate-e2e.integration.test.d.ts +1 -0
  258. package/dist/substrate/command-runner.d.ts +19 -0
  259. package/dist/substrate/docker.d.ts +134 -0
  260. package/dist/substrate/errors.d.ts +33 -0
  261. package/dist/substrate/forwarder.d.ts +67 -0
  262. package/dist/substrate/git-proxy.d.ts +35 -0
  263. package/dist/substrate/index.d.ts +12 -0
  264. package/dist/substrate/relay-script.d.ts +27 -0
  265. package/dist/substrate/sandbox-exec.d.ts +116 -0
  266. package/dist/substrate/types.d.ts +218 -0
  267. package/dist/substrate-launch/__tests__/apikey-bootstrap.test.d.ts +1 -0
  268. package/dist/substrate-launch/__tests__/creditless-loop.integration.test.d.ts +1 -0
  269. package/dist/substrate-launch/__tests__/engage-substrate.test.d.ts +1 -0
  270. package/dist/substrate-launch/__tests__/fallback-ladder.test.d.ts +1 -0
  271. package/dist/substrate-launch/__tests__/le-env-scrub.test.d.ts +1 -0
  272. package/dist/substrate-launch/__tests__/sanitized-env.test.d.ts +1 -0
  273. package/dist/substrate-launch/apikey-bootstrap.d.ts +84 -0
  274. package/dist/substrate-launch/engage-substrate.d.ts +102 -0
  275. package/dist/substrate-launch/fallback-ladder.d.ts +49 -0
  276. package/dist/substrate-launch/index.d.ts +12 -0
  277. package/dist/substrate-launch/le-env-scrub.d.ts +77 -0
  278. package/dist/substrate-launch/sanitized-env.d.ts +73 -0
  279. package/dist/types/auth.d.ts +6 -1
  280. package/dist/types/events.d.ts +3 -1
  281. package/dist/types/reviewer.d.ts +6 -6
  282. package/package.json +7 -3
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The five CP-7 audit kinds (§3.5), in their snake_case wire form — the
3
+ * exact strings the `AuditEventKind` enum serializes as and the
4
+ * `audit-keys` discriminator constants use. Defined here (not imported
5
+ * from a Rust-mirrored module) because W1 only needs the broker-side
6
+ * wire kinds; W3 wires these to the real `AuditEventKind` enum + NAPI
7
+ * `parse_audit_kind`.
8
+ *
9
+ * Note: only `model_call`, `model_call_result`, `model_context_scrubbed`,
10
+ * and `broker_credential_loaded` are broker-emitted. `egress_denied` is
11
+ * emitted by the substrate's egress proxy (§3.5, W2/W3) — it is included
12
+ * in the union for completeness of the CP-7 audit taxonomy but the broker
13
+ * never emits it.
14
+ */
15
+ export type AuditKindCp7 = "model_call" | "model_call_result" | "egress_denied" | "model_context_scrubbed" | "broker_credential_loaded";
16
+ /**
17
+ * The strict audit sink the broker emits through (§3.5).
18
+ *
19
+ * Per §3.5: the sender transmits `{kind, payload}` and BLOCKS for the
20
+ * LE's durable ACK. A resolved `{ ack }` means the row is durably on
21
+ * disk (the gated effect — the upstream forward — may proceed for a
22
+ * pre-forward row). A resolved `{ nack }` means the durable write failed
23
+ * (the broker fails closed: 503, no forward). A rejected/timed-out promise
24
+ * is treated by the broker exactly like a NACK (fail closed on a
25
+ * pre-forward row).
26
+ */
27
+ export interface StrictAuditSink {
28
+ emit(kind: AuditKindCp7, payload: Record<string, unknown>): Promise<{
29
+ ack: string;
30
+ } | {
31
+ nack: string;
32
+ }>;
33
+ }
34
+ /**
35
+ * A recorded emit, surfaced by {@link StubStrictAuditSink} for test
36
+ * assertions (the real LE emitter exposes nothing comparable — this is a
37
+ * test seam only).
38
+ */
39
+ export interface RecordedAuditEmit {
40
+ kind: AuditKindCp7;
41
+ payload: Record<string, unknown>;
42
+ }
43
+ /**
44
+ * In-memory deterministic `StrictAuditSink` for unit tests + the injected
45
+ * default until W3. Every `emit` ACKs with a deterministic
46
+ * `stub-ack-<n>` id and records the `{kind, payload}` for assertions.
47
+ *
48
+ * Two test hooks (both default off so the happy path is deterministic):
49
+ * - `nackKinds`: any kind in this set NACKs instead of ACKing — exercises
50
+ * the audit-before-effect 503 path.
51
+ * - `failKinds`: any kind in this set REJECTS the promise — exercises the
52
+ * "IPC error / timeout treated as fail-closed" path.
53
+ */
54
+ export declare class StubStrictAuditSink implements StrictAuditSink {
55
+ private readonly opts;
56
+ readonly emitted: RecordedAuditEmit[];
57
+ private counter;
58
+ constructor(opts?: {
59
+ nackKinds?: ReadonlyArray<AuditKindCp7>;
60
+ failKinds?: ReadonlyArray<AuditKindCp7>;
61
+ });
62
+ emit(kind: AuditKindCp7, payload: Record<string, unknown>): Promise<{
63
+ ack: string;
64
+ } | {
65
+ nack: string;
66
+ }>;
67
+ /** All emitted rows of a given kind (test helper). */
68
+ ofKind(kind: AuditKindCp7): RecordedAuditEmit[];
69
+ }
@@ -0,0 +1,39 @@
1
+ import type { VendorProvider } from "./types";
2
+ /**
3
+ * Per-provider wire facts the broker synthesizes on the upstream call.
4
+ */
5
+ export interface ProviderConfig {
6
+ /** Upstream origin (scheme + host) the broker forwards to. */
7
+ readonly upstreamBaseUrl: string;
8
+ /** The canonical upstream path for this provider's model route. */
9
+ readonly upstreamPath: "/v1/messages" | "/v1/responses";
10
+ /**
11
+ * Headers the broker synthesizes on EVERY upstream call — overriding
12
+ * whatever the agent supplied. `content-type` is always normalized to
13
+ * `application/json` (the only carried-through content type, §3.4).
14
+ */
15
+ readonly synthesizedHeaders: Readonly<Record<string, string>>;
16
+ /**
17
+ * The EXACT allowlist of `anthropic-beta` (or provider equivalent)
18
+ * tokens the broker will pass through. A request carrying a beta token
19
+ * outside this set is rejected (400) — header VALUES are agent-
20
+ * controlled and can carry data (Codex R2). Empty for OpenAI (no beta
21
+ * header is forwarded).
22
+ */
23
+ readonly betaTokenAllowlist: ReadonlySet<string>;
24
+ /**
25
+ * The name of the agent-supplied beta header this provider honors
26
+ * (lowercased), or `null` if the provider has none. Used by the
27
+ * canonical constructor to find the agent's beta tokens to validate.
28
+ */
29
+ readonly betaHeaderName: string | null;
30
+ }
31
+ /**
32
+ * Resolve the locked wire facts for a provider. Pure data — no I/O.
33
+ */
34
+ export declare function getProviderConfig(provider: VendorProvider): ProviderConfig;
35
+ /**
36
+ * Map an inbound broker route path to the vendor provider it gateways.
37
+ * `/v1/messages` → Anthropic, `/v1/responses` → OpenAI.
38
+ */
39
+ export declare function providerForPath(path: string): VendorProvider | null;
@@ -0,0 +1,123 @@
1
+ import type { BrokerToken } from "./types";
2
+ /**
3
+ * Mints + holds the current per-session broker token, and authenticates
4
+ * inbound agent→broker tokens against it. A new token replaces the prior
5
+ * one (single active token per session); `authenticate` accepts ONLY the
6
+ * current, unexpired value — every other value (including a just-rotated
7
+ * old token) is rejected, which the broker maps to the only 401 it emits.
8
+ */
9
+ /**
10
+ * A grace-rotation handle (Finding 3). `rotateWithGrace` returns this; the LE
11
+ * passes it back to {@link BrokerTokenMinter.commitRotation} /
12
+ * {@link BrokerTokenMinter.rollbackRotation}. The `generation` GENERATION-BINDS
13
+ * the commit/rollback to the SPECIFIC rotation that produced it: a stale handle
14
+ * (from a rotation already superseded by a newer one) is rejected, so a slow
15
+ * commit/rollback cannot clobber a newer in-flight rotation's token.
16
+ */
17
+ export interface RotationHandle {
18
+ readonly token: BrokerToken;
19
+ readonly generation: number;
20
+ }
21
+ export declare class BrokerTokenMinter {
22
+ private readonly ttlMs;
23
+ private current;
24
+ /**
25
+ * During a rotation the PRIOR token stays acceptable until the LE confirms
26
+ * the apiKeyHelper file holds the NEW token (`commitRotation`). This closes
27
+ * the 401-loop window the contract forbids (Stage-2 M-3): if we invalidated
28
+ * the prior token BEFORE the file refresh landed, the agent's file would hold
29
+ * a now-rejected token until the next refresh. With the grace token, BOTH the
30
+ * new and the prior token authenticate until the write is confirmed.
31
+ */
32
+ private graceToken;
33
+ /**
34
+ * Finding 3 — generation counter, bumped on every successful grace rotation.
35
+ * Commit/rollback are bound to the generation of the rotation they belong to;
36
+ * a stale (superseded) commit/rollback is a no-op. The generation also gates
37
+ * OVERLAPPING rotations: `rotateWithGrace` REJECTS (returns null) while a grace
38
+ * is still pending, so two near-concurrent rotations can never chain
39
+ * grace→grace and strand the file token.
40
+ */
41
+ private generation;
42
+ constructor(ttlMs?: number);
43
+ /** Mint (or rotate) the session's broker token; returns the new token. */
44
+ mint(now?: number): BrokerToken;
45
+ /**
46
+ * M-3 — SAFE rotation. Mint a NEW current token but KEEP the prior token
47
+ * valid (as a grace token) so there is no window where the agent's file (which
48
+ * still holds the prior token until the LE rewrites it) is rejected. The LE
49
+ * MUST call {@link commitRotation} AFTER it confirms the helper file now holds
50
+ * the new token (drops the grace token), or {@link rollbackRotation} if the
51
+ * file write FAILED (restores the prior token as current and discards the new
52
+ * one — the agent's file is still valid, fail-closed, no dead token).
53
+ *
54
+ * Finding 3 — OVERLAP REJECTION: returns null when a grace rotation is already
55
+ * pending (not yet committed/rolled back). Chaining grace→grace would make the
56
+ * SECOND rotation's grace token be the FIRST rotation's new token (not the
57
+ * file-resident prior token); if the first refresh then writes its token and
58
+ * commits, the file token could be left unauthenticated. By refusing to start a
59
+ * second rotation until the first settles, BOTH tokens that ever authenticate
60
+ * are {file-resident prior, new} — the file token is never stranded.
61
+ *
62
+ * Returns the {@link RotationHandle} for the new token, or null if the broker
63
+ * has no current token yet (nothing to rotate) OR a rotation is in-flight.
64
+ */
65
+ rotateWithGrace(now?: number): RotationHandle | null;
66
+ /**
67
+ * Confirm the helper file now holds the new token — drop the grace token so
68
+ * the prior token stops authenticating (single-active-token restored).
69
+ *
70
+ * Finding 3 — generation-bound: a commit whose `generation` does not match the
71
+ * current generation is STALE (a newer rotation/mint superseded it) and is a
72
+ * NO-OP, so it cannot drop a newer rotation's grace token.
73
+ */
74
+ commitRotation(handle?: RotationHandle): void;
75
+ /**
76
+ * The file refresh FAILED — roll back: restore the prior (grace) token as
77
+ * current and discard the just-minted new token. The agent's file still holds
78
+ * the prior token, which is once again the sole active token → no dead-token
79
+ * window. No-op if there is no pending grace rotation.
80
+ *
81
+ * Finding 3 — generation-bound: a rollback whose `generation` does not match
82
+ * the current generation is STALE and a NO-OP, so a late rollback from a
83
+ * superseded rotation cannot revert a newer rotation's token.
84
+ */
85
+ rollbackRotation(handle?: RotationHandle): void;
86
+ /** Whether a rotation is mid-flight (grace token still accepted). Test seam. */
87
+ hasPendingGrace(): boolean;
88
+ /** The current token, or null if none minted yet. */
89
+ get(): BrokerToken | null;
90
+ /**
91
+ * EVERY broker-token value that `authenticate()` would currently accept — the
92
+ * CURRENT token plus, during a mid-flight grace rotation, the PRIOR (grace)
93
+ * token. Used by the broker's self-credential guard so it scrubs ALL tokens a
94
+ * model-bound field could be carrying, not just `get()` (Stage-2 MEDIUM): the
95
+ * prior token still authenticates during the grace window AND is still resident
96
+ * in the agent's helper file, so a model-bound field echoing it is a live-token
97
+ * leak the guard must redact. Values are returned only (the actual scrub +
98
+ * commit/rollback gate is the caller's); a stale/expired grace token is NOT
99
+ * included (it can no longer authenticate, so it is not a live secret).
100
+ *
101
+ * NOTE: this does NOT filter on `expiresAtMs` — `authenticate()` rejects an
102
+ * expired token, but an expired-yet-still-resident token in the helper file is
103
+ * still a secret-shaped value the guard should keep out of model-bound content;
104
+ * we err toward scrubbing both held values whenever they are non-null. (An
105
+ * expired token cannot be USED, but redacting it is strictly safer and never
106
+ * wrong — the guard only ever removes a value, never adds one.)
107
+ */
108
+ acceptedValues(): string[];
109
+ /**
110
+ * Authenticate an inbound agent→broker token. True for the current, unexpired
111
+ * token value OR (during a mid-flight rotation) the unexpired grace token —
112
+ * the latter keeps the agent's pre-refresh file valid until the LE confirms
113
+ * the file rewrite (M-3 no-rejection-window contract). A missing / stale /
114
+ * expired / mismatched token → false (the broker returns 401 — the ONLY 401
115
+ * it emits, §3.2).
116
+ *
117
+ * Constant-time-ish compare is unnecessary for a loopback-only local
118
+ * token, but we still avoid leaking via early-return on length.
119
+ */
120
+ authenticate(token: string | undefined, now?: number): boolean;
121
+ /** Zeroize the held token (broker teardown). */
122
+ clear(): void;
123
+ }
@@ -0,0 +1,165 @@
1
+ import { type StrictAuditSink } from "./audit-sink";
2
+ import { getProviderConfig } from "./broker-config";
3
+ import { type RotationHandle } from "./broker-token";
4
+ import { type BrokerRequest, type BrokerResponse, type BrokerToken, type ModelGatewayBroker, type UpstreamClient, type VendorKeyStore, type VendorProvider } from "./types";
5
+ /**
6
+ * Construction-time dependencies. All injectable so W1 unit-tests run
7
+ * against stubs (no network, deterministic audit ACKs). Defaults wire the
8
+ * real keychain store + a deterministic stub audit sink (the real strict
9
+ * sink is W3). `upstreamClient` has NO default — a network client is out
10
+ * of W1 scope, so the broker MUST be given one (tests pass a stub).
11
+ */
12
+ export interface BrokerDeps {
13
+ /** Orchestration task_id = the audit scope (§3.5), passed at session start. */
14
+ taskId: string;
15
+ /** Injected upstream HTTP client (no real network in W1). */
16
+ upstreamClient: UpstreamClient;
17
+ /** Vendor-key store (defaults to the keychain-backed store, §3.3). */
18
+ vendorKeyStore?: VendorKeyStore;
19
+ /** Strict audit sink (defaults to the in-memory stub until W3, §3.5). */
20
+ auditSink?: StrictAuditSink;
21
+ }
22
+ /**
23
+ * The local model-gateway broker (§3.2). One per session on
24
+ * `127.0.0.1:<ephemeral>`. Holds the upstream credential in-process only
25
+ * (zeroized on `stop()`), authenticates the agent's broker token, builds
26
+ * a canonical upstream request, scrubs secrets (I2), enforces audit-
27
+ * before-effect via the injected `StrictAuditSink`, and forwards.
28
+ */
29
+ export declare class LocalModelGatewayBroker implements ModelGatewayBroker, VendorKeyStore {
30
+ private readonly taskId;
31
+ private readonly upstreamClient;
32
+ private readonly vendorKeyStore;
33
+ private readonly auditSink;
34
+ private readonly tokenMinter;
35
+ private readonly brokerId;
36
+ private server;
37
+ private boundAddr;
38
+ /** In-process cache of upstream vendor keys (zeroized on stop()). */
39
+ private upstreamKeys;
40
+ /** Latest `credential_issuance_id` per provider (for the model_call FK). */
41
+ private issuanceIds;
42
+ private issuanceCounter;
43
+ constructor(deps: BrokerDeps);
44
+ /**
45
+ * Start the per-session HTTP gateway on an ephemeral loopback port + mint
46
+ * the session's broker token. Resolves the bound `127.0.0.1:<port>`.
47
+ */
48
+ start(): Promise<{
49
+ hostBrokerAddr: string;
50
+ }>;
51
+ /** Liveness — the LE waits for this before launching the agent. */
52
+ healthz(): Promise<boolean>;
53
+ /**
54
+ * Tear down: close the HTTP server, ZEROIZE the in-process upstream
55
+ * credentials, and clear the broker token. Idempotent.
56
+ */
57
+ stop(): Promise<void>;
58
+ /** The current broker token (for the agent's apiKeyHelper bootstrap). */
59
+ currentBrokerToken(): BrokerToken | null;
60
+ /**
61
+ * Re-mint (rotate) the broker token and return the new value. The LE calls
62
+ * this periodically (well within the TTL) + rewrites the apiKeyHelper token
63
+ * file so a long-running session never hits an expired-token 401 loop.
64
+ *
65
+ * M-3 — this is a GRACE rotation: the NEW token becomes current but the PRIOR
66
+ * token KEEPS authenticating until the LE confirms the helper file holds the
67
+ * new token (then calls {@link commitBrokerTokenRotation}). This closes the
68
+ * 401-loop window: there is NEVER a moment where the agent's file (which holds
69
+ * the prior token until the rewrite lands) is rejected. If the file rewrite
70
+ * FAILS, the LE calls {@link rollbackBrokerTokenRotation} to restore the prior
71
+ * token as the sole active one (fail-closed — no dead token left in the file).
72
+ * Returns null if the broker is stopped OR a rotation is already in-flight
73
+ * (Finding 3 overlap guard — the minter refuses a second concurrent rotation).
74
+ * The returned {@link RotationHandle} MUST be passed back to
75
+ * {@link commitBrokerTokenRotation} / {@link rollbackBrokerTokenRotation} so a
76
+ * stale (superseded) commit/rollback cannot clobber a newer rotation.
77
+ */
78
+ rotateBrokerToken(): RotationHandle | null;
79
+ /**
80
+ * Confirm a grace rotation: the helper file now holds the new token, so the
81
+ * prior (grace) token stops authenticating (single-active-token restored).
82
+ * Generation-bound (Finding 3): pass the {@link RotationHandle} from the
83
+ * matching {@link rotateBrokerToken}; a stale handle is a no-op.
84
+ */
85
+ commitBrokerTokenRotation(handle?: RotationHandle): void;
86
+ /**
87
+ * Roll back a grace rotation whose file rewrite FAILED: the prior token is
88
+ * restored as current (still in the agent's file, still valid) and the new
89
+ * token is discarded. No dead-token window. Generation-bound (Finding 3): pass
90
+ * the {@link RotationHandle} from the matching {@link rotateBrokerToken}.
91
+ */
92
+ rollbackBrokerTokenRotation(handle?: RotationHandle): void;
93
+ getVendorKey(provider: VendorProvider): Promise<string | null>;
94
+ setVendorKey(provider: VendorProvider, key: string): Promise<void>;
95
+ /**
96
+ * Handle one broker request (§3.2). The pure, transport-agnostic core —
97
+ * the HTTP server (`handleHttp`) adapts node req/res onto this. Route
98
+ * table check first (everything else → 403), then broker-token auth on
99
+ * the two POSTs (the ONLY 401 is an invalid agent→broker token), then
100
+ * the per-provider gateway (§3.3/§3.4/§3.5).
101
+ */
102
+ handle(req: BrokerRequest): Promise<BrokerResponse>;
103
+ private gateway;
104
+ /**
105
+ * Load the vendor key, caching it in-process, and emit
106
+ * `broker_credential_loaded` (§3.5) on each keychain load — with a
107
+ * `key_fingerprint` (sha256 prefix) and a fresh `credential_issuance_id`,
108
+ * NEVER the key. The credential-loaded audit is best-effort (it does not
109
+ * gate the forward — the `model_call` row does); a lost load-audit is a
110
+ * forensic gap, not an unsafe effect.
111
+ */
112
+ private loadVendorKey;
113
+ private lastIssuanceId;
114
+ /**
115
+ * Map an upstream response to the agent-facing status (§3.2). An upstream
116
+ * 401/403 (bad/expired vendor key) → 502 (NOT a pass-through 401, which
117
+ * would loop the agent's token-refresh hook). Every other status carries
118
+ * through; the body is the upstream JSON on success.
119
+ */
120
+ private mapUpstream;
121
+ /**
122
+ * Best-effort extraction of the requested model name for the audit row.
123
+ *
124
+ * OWN-property check ONLY (Codex W1 R3 prototype-pollution class). The
125
+ * body originates from `JSON.parse`, so a `{"__proto__":{"model":"<secret>"}}`
126
+ * payload could leave an INHERITED `model` on the prototype chain. A bare
127
+ * `"model" in body` / `body.model` would WALK the chain and read that
128
+ * injected secret straight into the durable `model_call.model` audit row
129
+ * (exfil). `Object.hasOwn` + an own-only read see ONLY a real top-level
130
+ * `$.model`; an inherited one is invisible → audited `model` is `"unknown"`,
131
+ * never the leaked value. (This is also fed the POST-scrub body, so even a
132
+ * real secret-shaped own `$.model` is already redacted by the scrubber —
133
+ * Codex W1 R1; the own-only read closes the inherited-property variant.)
134
+ */
135
+ private extractModel;
136
+ /** Best-effort token/cost extraction from an upstream response body. */
137
+ private extractUsage;
138
+ /**
139
+ * Emit a PRE-FORWARD (gated) audit row and BLOCK for a durable ACK
140
+ * (§3.5 audit-before-effect). Returns true ONLY on `{ack}`; a `{nack}`,
141
+ * a rejected promise (IPC failure), or any thrown error → false (the
142
+ * caller fails closed: 503, no forward). A security audit cannot
143
+ * silently drop.
144
+ */
145
+ private emitGated;
146
+ /**
147
+ * Emit a BEST-EFFORT audit row (`model_call_result` post-response,
148
+ * `broker_credential_loaded`). Losing it is a cost-tracking / forensic
149
+ * gap, never a security-invariant violation — so it never gates an
150
+ * effect and swallows nack/error.
151
+ */
152
+ private emitBestEffort;
153
+ /**
154
+ * Adapt a node HTTP request/response onto `handle`. Extracts the broker
155
+ * token (Anthropic `x-api-key` / `authorization: Bearer`; OpenAI
156
+ * `authorization: Bearer`), the agent headers/query/content-type, and the
157
+ * JSON body, then writes the `BrokerResponse` back. A malformed JSON body
158
+ * on a model POST → 400 (outside the canonical shape).
159
+ */
160
+ private handleHttp;
161
+ private extractBrokerToken;
162
+ private readBody;
163
+ private writeJson;
164
+ }
165
+ export { getProviderConfig };
@@ -0,0 +1,119 @@
1
+ import type { BrokerRequest, VendorProvider } from "./types";
2
+ /**
3
+ * The agent-supplied request, as the §3.2 `BrokerRequest` carries it.
4
+ * `headers` / `query` are OPTIONAL on the wire type but, when present,
5
+ * the canonical constructor DROPS them all (only an exact-allowlist beta
6
+ * token survives). They are accepted on the inbound shape solely so the
7
+ * gateway can assert it dropped them (conformance-testable).
8
+ */
9
+ export interface CanonicalInput {
10
+ provider: VendorProvider;
11
+ /** The agent's raw inbound request. */
12
+ request: BrokerRequest;
13
+ /**
14
+ * Agent-supplied headers (lowercased keys), if the transport surfaced
15
+ * any. The canonical constructor drops all of them except an exact-
16
+ * allowlist beta token.
17
+ */
18
+ agentHeaders?: Readonly<Record<string, string>>;
19
+ /** Agent-supplied query string params, if any. ALL are dropped. */
20
+ agentQuery?: Readonly<Record<string, string>>;
21
+ /** Agent-declared content type, if the transport surfaced it. */
22
+ agentContentType?: string;
23
+ }
24
+ /**
25
+ * A constructed, canonical upstream request — everything the broker needs
26
+ * to forward, with the agent's raw envelope discarded. `model_call_id` is
27
+ * allocated here (§3.4) so a request that is scrubbed-then-rejected still
28
+ * has a stable id for its audit row.
29
+ */
30
+ export interface CanonicalRequest {
31
+ provider: VendorProvider;
32
+ /** Absolute upstream URL (origin + canonical path), synthesized from config. */
33
+ upstreamUrl: string;
34
+ /**
35
+ * The upstream headers the broker synthesized — vendor/version +
36
+ * content-type + any exact-allowlist beta token. The upstream CREDENTIAL
37
+ * is injected separately at forward time (§3.3), NOT here.
38
+ */
39
+ headers: Record<string, string>;
40
+ /** The carried-through model-bound JSON body (the only surviving surface). */
41
+ body: unknown;
42
+ /** Per-forward id, allocated at construction (§3.4 / §3.5). */
43
+ modelCallId: string;
44
+ /** SHA-256 of the ORIGINAL pre-scrub body (§3.5 `request_sha256`). */
45
+ requestSha256: string;
46
+ }
47
+ /**
48
+ * A 400-class rejection (request outside the canonical shape). Carries a
49
+ * non-revealing reason for the broker's error envelope.
50
+ */
51
+ export declare class CanonicalRejectError extends Error {
52
+ readonly reason: string;
53
+ constructor(reason: string);
54
+ }
55
+ /**
56
+ * Compute the SHA-256 hex of the request body over a STABLE serialization
57
+ * of the ORIGINAL (pre-scrub) bytes. Uses `JSON.stringify` of the parsed
58
+ * body so the digest is independent of incidental whitespace, and is
59
+ * computed before any redaction so a scrub never changes it (§3.5).
60
+ */
61
+ export declare function requestSha256(body: unknown): string;
62
+ /**
63
+ * Build the canonical upstream request (§3.4 step 0). Rejects (throws
64
+ * `CanonicalRejectError` → 400) anything outside the canonical shape:
65
+ * non-JSON content type, a body that isn't a JSON object, or a non-
66
+ * allowlisted beta token. DROPS the agent's auth / every other header /
67
+ * all query params silently (they simply do not survive into the result).
68
+ */
69
+ export declare function buildCanonicalRequest(input: CanonicalInput): CanonicalRequest;
70
+ /**
71
+ * One general secret-shaped KEY the guard redacted (Codex W1 R4). Mirrors a
72
+ * scrubber `ScrubFinding`: the broker emits one `model_context_scrubbed` row
73
+ * per entry, carrying the PLACEHOLDER path + pattern class, NEVER the raw key.
74
+ */
75
+ export interface GuardKeyScrub {
76
+ /** Canonical JSONPath of the redacted KEY's location (placeholder, leak-free). */
77
+ readonly field: string;
78
+ /** The non-revealing pattern class (always `secret_object_key`). */
79
+ readonly patternClass: string;
80
+ }
81
+ /**
82
+ * §3.4 step 1 — self-credential guard, and the AUTHORITATIVE object-key
83
+ * redactor for the whole request path. Two responsibilities:
84
+ *
85
+ * (a) Assert the broker's own upstream key / the broker token never appear
86
+ * in any model-bound field — as a string VALUE *or* as an object KEY
87
+ * (defense-in-depth: redact + tell the caller so it audits via
88
+ * `model_context_scrubbed`). Self-cred VALUE → `[REDACTED-SELF-CRED]`;
89
+ * self-cred KEY → `[REDACTED-SELF-CRED-KEY]-<n>` (Codex W1 R2).
90
+ *
91
+ * (b) Redact ANY *general* secret-shaped object KEY (`keyIsSecret`, the
92
+ * scrubber's predicate) to `[REDACTED-CP7-KEY]-<n>` — even when it is
93
+ * NOT a self-credential. This runs FIRST (before the §3.4-step-2
94
+ * scrubber and before any leaked-path is recorded), so NO JSONPath the
95
+ * guard builds — for its OWN key redactions, or for a self-cred VALUE
96
+ * nested *beneath* such a key — can ever carry a raw secret key.
97
+ *
98
+ * (b) is the Codex W1 R4 fix. Before it, a self-cred value nested under a
99
+ * non-self-cred secret-shaped key (e.g. `{ "sk-ant-EXFIL…": { trigger:
100
+ * "<broker-token>" } }`) made the guard record `field =
101
+ * "$['sk-ant-EXFIL…'].trigger"` BEFORE the downstream scrubber's key
102
+ * redaction could fire — landing the raw key verbatim in a durable
103
+ * `model_context_scrubbed` row. Making the guard the single, FIRST key
104
+ * redactor closes that seam: every secret-shaped key (self-cred OR general)
105
+ * is a placeholder before any path is built, in either pass.
106
+ *
107
+ * Returns the redacted body, the `leakedPaths` where a SELF-credential was
108
+ * found (`pattern_class: self_credential`), and `keyScrubs` for general
109
+ * secret-shaped keys (`pattern_class: secret_object_key`). Every recorded
110
+ * path uses a PLACEHOLDER for any redacted key, never the raw key — so the
111
+ * audit surface is leak-free. The downstream scrubber sees only placeholder
112
+ * keys (never re-redacts them) and remains a value scrubber + a backstop key
113
+ * redactor should coverage ever diverge.
114
+ */
115
+ export declare function selfCredentialGuard(body: unknown, secrets: ReadonlyArray<string>): {
116
+ body: unknown;
117
+ leakedPaths: string[];
118
+ keyScrubs: GuardKeyScrub[];
119
+ };
@@ -0,0 +1,15 @@
1
+ export type { VendorProvider, BrokerRouteMethod, BrokerRoute, BrokerStatus, BrokerRequest, BrokerResponse, ModelGatewayBroker, VendorKeyStore, BrokerToken, UpstreamResponse, UpstreamClient, } from "./types";
2
+ export { BROKER_ROUTES } from "./types";
3
+ export { LocalModelGatewayBroker } from "./broker";
4
+ export type { BrokerDeps } from "./broker";
5
+ export { FetchUpstreamClient } from "./upstream-client";
6
+ export type { StrictAuditSink, AuditKindCp7, RecordedAuditEmit } from "./audit-sink";
7
+ export { StubStrictAuditSink } from "./audit-sink";
8
+ export { KeychainVendorKeyStore } from "./vendor-key-store";
9
+ export { BrokerTokenMinter, type RotationHandle } from "./broker-token";
10
+ export { buildCanonicalRequest, selfCredentialGuard, requestSha256, CanonicalRejectError, } from "./canonical";
11
+ export type { CanonicalInput, CanonicalRequest } from "./canonical";
12
+ export { scrubRequestBody } from "./scrubber";
13
+ export type { ScrubFinding, ScrubResult } from "./scrubber";
14
+ export { getProviderConfig, providerForPath } from "./broker-config";
15
+ export type { ProviderConfig } from "./broker-config";
@@ -0,0 +1,45 @@
1
+ /**
2
+ * A single scrub finding — surfaced so the broker emits one
3
+ * `model_context_scrubbed` audit row per (field, pattern_class). NEVER
4
+ * carries the secret value.
5
+ */
6
+ export interface ScrubFinding {
7
+ /** Canonical JSONPath of the field that was scrubbed, e.g. `$.messages[0].content`. */
8
+ readonly field: string;
9
+ /** The non-revealing pattern class (e.g. `anthropic_api_key`). */
10
+ readonly patternClass: string;
11
+ }
12
+ /**
13
+ * Result of scrubbing one request body.
14
+ */
15
+ export interface ScrubResult {
16
+ /** A DEEP-CLONED, redacted copy of the body (the original is untouched). */
17
+ readonly scrubbed: unknown;
18
+ /** One finding per (field, pattern_class) hit; empty if nothing matched. */
19
+ readonly findings: ScrubFinding[];
20
+ }
21
+ /**
22
+ * Does this object-key NAME itself match a high-confidence secret shape?
23
+ * A key like `"sk-ant-…"` carries the secret AS the key — value-only
24
+ * scrubbing would forward it verbatim (exfil out the one allow-listed
25
+ * egress) and a JSONPath built from it would embed the raw secret in an
26
+ * audit row. Reuses the SAME `SECRET_PATTERNS` so key + value coverage
27
+ * evolve together (no separate key schema). Read-only `.test()` (lastIndex
28
+ * is reset each side because the regexes are global/stateful).
29
+ *
30
+ * EXPORTED (Codex W1 R4): the self-credential guard (`canonical.ts`) runs
31
+ * BEFORE this scrubber and is the AUTHORITATIVE key redactor — it imports
32
+ * this predicate so a general secret-shaped KEY is replaced with a
33
+ * placeholder before ANY JSONPath is built, in either pass. Sharing this one
34
+ * function keeps the guard's and the scrubber's key coverage identical (no
35
+ * second key schema to drift).
36
+ */
37
+ export declare function keyIsSecret(key: string): boolean;
38
+ /**
39
+ * The I2 scrubber (§3.4 step 2). Walks the model-bound request JSON,
40
+ * redacts high-confidence secret shapes in every string, and reports each
41
+ * scrub by canonical JSONPath + pattern class (never the value). The
42
+ * returned `scrubbed` body is a deep clone — the caller keeps the
43
+ * original to compute `request_sha256` over the PRE-scrub bytes (§3.5).
44
+ */
45
+ export declare function scrubRequestBody(body: unknown): ScrubResult;