forgeos 0.1.0-alpha.4 → 0.1.0-alpha.40

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 (415) hide show
  1. package/.npmignore +10 -0
  2. package/AGENTS.md +142 -90
  3. package/CHANGELOG.md +418 -0
  4. package/LICENSE +21 -0
  5. package/README.md +67 -8
  6. package/adapters/go/README.md +23 -0
  7. package/adapters/go/go.mod +3 -0
  8. package/adapters/go/http.go +149 -0
  9. package/adapters/go/registry.go +234 -0
  10. package/adapters/go/types.go +136 -0
  11. package/adapters/java/README.md +68 -0
  12. package/adapters/java/pom.xml +34 -0
  13. package/adapters/java/src/main/java/dev/forgeos/adapter/Auth.java +20 -0
  14. package/adapters/java/src/main/java/dev/forgeos/adapter/Diagnostic.java +16 -0
  15. package/adapters/java/src/main/java/dev/forgeos/adapter/Entry.java +38 -0
  16. package/adapters/java/src/main/java/dev/forgeos/adapter/EntryKind.java +16 -0
  17. package/adapters/java/src/main/java/dev/forgeos/adapter/ErrorInfo.java +4 -0
  18. package/adapters/java/src/main/java/dev/forgeos/adapter/Forge.java +94 -0
  19. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeCall.java +12 -0
  20. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeContext.java +11 -0
  21. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHandler.java +8 -0
  22. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHttpHandler.java +179 -0
  23. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeRegistry.java +121 -0
  24. package/adapters/java/src/main/java/dev/forgeos/adapter/Json.java +14 -0
  25. package/adapters/java/src/main/java/dev/forgeos/adapter/Manifest.java +14 -0
  26. package/adapters/java/src/main/java/dev/forgeos/adapter/RequestEnvelope.java +6 -0
  27. package/adapters/java/src/main/java/dev/forgeos/adapter/ResponseEnvelope.java +25 -0
  28. package/adapters/java/src/main/java/dev/forgeos/adapter/Risk.java +18 -0
  29. package/adapters/java/src/main/java/dev/forgeos/adapter/Schemas.java +36 -0
  30. package/adapters/java/src/main/java/dev/forgeos/adapter/Service.java +65 -0
  31. package/adapters/java/src/main/java/dev/forgeos/adapter/TransactionMode.java +18 -0
  32. package/adapters/java/src/main/java/dev/forgeos/adapter/TypedForgeHandler.java +6 -0
  33. package/adapters/java-spring-boot-starter/README.md +32 -0
  34. package/adapters/java-spring-boot-starter/pom.xml +36 -0
  35. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeCommand.java +22 -0
  36. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeExternalService.java +15 -0
  37. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeQuery.java +16 -0
  38. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.java +18 -0
  39. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.java +16 -0
  40. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringRuntime.java +104 -0
  41. package/adapters/java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
  42. package/bin/forge.mjs +18 -0
  43. package/docs/cair-protocol.md +103 -0
  44. package/docs/changelog.md +534 -0
  45. package/docs/forge-protocol.md +189 -0
  46. package/examples/go-billing/go.mod +7 -0
  47. package/examples/go-billing/main.go +120 -0
  48. package/examples/java-billing/pom.xml +52 -0
  49. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/CreateInvoiceInput.java +4 -0
  50. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Invoice.java +11 -0
  51. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Main.java +127 -0
  52. package/package.json +31 -3
  53. package/schemas/forge-manifest.schema.json +57 -0
  54. package/src/forge/_generated/releaseManifest.json +1 -2
  55. package/src/forge/_generated/releaseManifest.ts +3 -3
  56. package/src/forge/agent-adapters/index.ts +1584 -125
  57. package/src/forge/agent-adapters/types.ts +224 -1
  58. package/src/forge/agent-memory/bridge.ts +1333 -0
  59. package/src/forge/agent-memory/context-pack.ts +277 -0
  60. package/src/forge/agent-memory/hook-runner.ts +312 -0
  61. package/src/forge/agent-memory/mcp.ts +224 -0
  62. package/src/forge/agent-memory/normalize.ts +498 -0
  63. package/src/forge/agent-memory/redaction.ts +103 -0
  64. package/src/forge/agent-memory/sources/claude-code.ts +51 -0
  65. package/src/forge/agent-memory/sources/codex-hook-runner.mjs +273 -0
  66. package/src/forge/agent-memory/sources/codex.ts +119 -0
  67. package/src/forge/agent-memory/sources/cursor.ts +35 -0
  68. package/src/forge/agent-memory/types.ts +204 -0
  69. package/src/forge/bench.ts +248 -0
  70. package/src/forge/brownfield-import/index.ts +801 -0
  71. package/src/forge/brownfield-import/types.ts +127 -0
  72. package/src/forge/cair/action-journal.ts +61 -0
  73. package/src/forge/cair/action-parser.ts +314 -0
  74. package/src/forge/cair/action-validator.ts +40 -0
  75. package/src/forge/cair/actions.ts +1818 -0
  76. package/src/forge/cair/format.ts +77 -0
  77. package/src/forge/cair/index.ts +106 -0
  78. package/src/forge/cair/query.ts +478 -0
  79. package/src/forge/cair/snapshot.ts +315 -0
  80. package/src/forge/cair/types.ts +248 -0
  81. package/src/forge/cli/ai.ts +339 -21
  82. package/src/forge/cli/auth.ts +348 -10
  83. package/src/forge/cli/authmd.ts +441 -0
  84. package/src/forge/cli/baseline.ts +112 -0
  85. package/src/forge/cli/build.ts +20 -4
  86. package/src/forge/cli/changed.ts +437 -0
  87. package/src/forge/cli/codex-app-server.ts +877 -0
  88. package/src/forge/cli/commands.ts +1620 -20
  89. package/src/forge/cli/db.ts +209 -2
  90. package/src/forge/cli/deploy.ts +887 -0
  91. package/src/forge/cli/deps.ts +82 -13
  92. package/src/forge/cli/dev.ts +961 -46
  93. package/src/forge/cli/docs.ts +265 -0
  94. package/src/forge/cli/doctor.ts +297 -0
  95. package/src/forge/cli/field-test.ts +329 -0
  96. package/src/forge/cli/handoff.ts +336 -0
  97. package/src/forge/cli/index.ts +1 -0
  98. package/src/forge/cli/last-run.ts +84 -0
  99. package/src/forge/cli/main.ts +107 -3
  100. package/src/forge/cli/new.ts +152 -13
  101. package/src/forge/cli/next-actions.ts +23 -0
  102. package/src/forge/cli/output.ts +389 -6
  103. package/src/forge/cli/parse.ts +1050 -34
  104. package/src/forge/cli/progress.ts +51 -0
  105. package/src/forge/cli/query.ts +32 -0
  106. package/src/forge/cli/release.ts +35 -11
  107. package/src/forge/cli/rls.ts +43 -4
  108. package/src/forge/cli/run.ts +41 -0
  109. package/src/forge/cli/security.ts +112 -0
  110. package/src/forge/cli/self-host.ts +56 -14
  111. package/src/forge/cli/studio.ts +2218 -0
  112. package/src/forge/cli/verify.ts +1455 -32
  113. package/src/forge/cli/windows.ts +23 -0
  114. package/src/forge/cli/workos.ts +1020 -0
  115. package/src/forge/compiler/agent-contract/build.ts +670 -64
  116. package/src/forge/compiler/agent-contract/types.ts +45 -2
  117. package/src/forge/compiler/ai-registry/parse.ts +71 -2
  118. package/src/forge/compiler/api-surface/build.ts +47 -0
  119. package/src/forge/compiler/app-graph/build.ts +112 -9
  120. package/src/forge/compiler/app-graph/extract.ts +107 -0
  121. package/src/forge/compiler/app-graph/module-graph.ts +73 -78
  122. package/src/forge/compiler/app-graph/parser.ts +24 -24
  123. package/src/forge/compiler/app-graph/profile.ts +26 -0
  124. package/src/forge/compiler/app-graph/versions.ts +1 -1
  125. package/src/forge/compiler/classifier/capabilities.ts +3 -2
  126. package/src/forge/compiler/classifier/classify.ts +32 -8
  127. package/src/forge/compiler/classifier/secrets.ts +3 -2
  128. package/src/forge/compiler/classifier/signals.ts +91 -1
  129. package/src/forge/compiler/client-sdk/build-manifest.ts +59 -0
  130. package/src/forge/compiler/client-sdk/render-client.ts +295 -13
  131. package/src/forge/compiler/data-graph/parse.ts +20 -4
  132. package/src/forge/compiler/data-graph/sql/ddl.ts +144 -31
  133. package/src/forge/compiler/data-graph/sql/serialize.ts +4 -0
  134. package/src/forge/compiler/data-graph/sql/types.ts +1 -0
  135. package/src/forge/compiler/diagnostics/codes.ts +30 -0
  136. package/src/forge/compiler/diagnostics/create.ts +21 -2
  137. package/src/forge/compiler/diagnostics/index.ts +2 -0
  138. package/src/forge/compiler/emitter/barrel.ts +3 -0
  139. package/src/forge/compiler/emitter/render.ts +9 -0
  140. package/src/forge/compiler/external-manifest/registry.ts +205 -0
  141. package/src/forge/compiler/external-manifest/types.ts +91 -0
  142. package/src/forge/compiler/external-manifest/validate.ts +373 -0
  143. package/src/forge/compiler/frontend-graph/build.ts +142 -14
  144. package/src/forge/compiler/integration/add.ts +618 -24
  145. package/src/forge/compiler/integration/plan.ts +43 -12
  146. package/src/forge/compiler/integration/render.ts +29 -0
  147. package/src/forge/compiler/integration/snapshot.ts +2 -0
  148. package/src/forge/compiler/integration/templates/convex.ts +70 -0
  149. package/src/forge/compiler/integration/templates/index.ts +1 -0
  150. package/src/forge/compiler/integration/templates/render.ts +38 -0
  151. package/src/forge/compiler/integration/templates/types.ts +3 -0
  152. package/src/forge/compiler/integration/templates/workos.ts +1219 -0
  153. package/src/forge/compiler/make-registry/build.ts +8 -9
  154. package/src/forge/compiler/orchestrator/fast-check.ts +4 -0
  155. package/src/forge/compiler/orchestrator/generate-lock.ts +14 -3
  156. package/src/forge/compiler/orchestrator/manifest.ts +1 -1
  157. package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
  158. package/src/forge/compiler/orchestrator/plan.ts +247 -10
  159. package/src/forge/compiler/orchestrator/profile.ts +65 -0
  160. package/src/forge/compiler/orchestrator/run.ts +97 -31
  161. package/src/forge/compiler/orchestrator/serialize.ts +33 -8
  162. package/src/forge/compiler/orchestrator/types.ts +1 -1
  163. package/src/forge/compiler/package-graph/compiler.ts +3 -1
  164. package/src/forge/compiler/package-graph/constants.ts +1 -1
  165. package/src/forge/compiler/package-manager/adapter.ts +4 -1
  166. package/src/forge/compiler/package-manager/commands.ts +4 -0
  167. package/src/forge/compiler/package-manager/executor.ts +30 -1
  168. package/src/forge/compiler/package-upgrades/planner.ts +155 -18
  169. package/src/forge/compiler/package-upgrades/types.ts +2 -0
  170. package/src/forge/compiler/policy-registry/build.ts +47 -2
  171. package/src/forge/compiler/policy-registry/parse.ts +32 -2
  172. package/src/forge/compiler/recipes/definitions.ts +63 -0
  173. package/src/forge/compiler/recipes/index.ts +2 -0
  174. package/src/forge/compiler/recipes/registry.ts +6 -0
  175. package/src/forge/compiler/test-graph/build.ts +11 -3
  176. package/src/forge/compiler/types/app-graph.ts +8 -2
  177. package/src/forge/compiler/types/cli.ts +75 -1
  178. package/src/forge/compiler/types/dev-manifest.ts +4 -0
  179. package/src/forge/compiler/types/emit.ts +2 -0
  180. package/src/forge/compiler/types/frontend-graph.ts +2 -2
  181. package/src/forge/compiler/types/integration.ts +1 -0
  182. package/src/forge/compiler/types/package-graph.ts +6 -0
  183. package/src/forge/compiler/types/policy-registry.ts +3 -1
  184. package/src/forge/delta/classifier.ts +52 -0
  185. package/src/forge/delta/explain.ts +238 -0
  186. package/src/forge/delta/git-observer.ts +43 -0
  187. package/src/forge/delta/ids.ts +44 -0
  188. package/src/forge/delta/index.ts +25 -0
  189. package/src/forge/delta/recorder.ts +540 -0
  190. package/src/forge/delta/redaction.ts +50 -0
  191. package/src/forge/delta/schema.ts +240 -0
  192. package/src/forge/delta/session.ts +142 -0
  193. package/src/forge/delta/status.ts +1202 -0
  194. package/src/forge/delta/store.ts +3284 -0
  195. package/src/forge/delta/timeline.ts +178 -0
  196. package/src/forge/dev/server.ts +808 -17
  197. package/src/forge/dev/types.ts +15 -1
  198. package/src/forge/dev/watch.ts +17 -7
  199. package/src/forge/dev-console/cycle.ts +280 -33
  200. package/src/forge/dev-console/types.ts +47 -1
  201. package/src/forge/impact/index.ts +204 -9
  202. package/src/forge/impact/types.ts +33 -1
  203. package/src/forge/intent/index.ts +35 -16
  204. package/src/forge/make/fields.ts +26 -0
  205. package/src/forge/make/index.ts +40 -6
  206. package/src/forge/make/templates.ts +155 -2
  207. package/src/forge/make/types.ts +2 -1
  208. package/src/forge/policy.ts +1 -1
  209. package/src/forge/react/index.ts +160 -2
  210. package/src/forge/refactor/index.ts +1 -0
  211. package/src/forge/repair/rules/index.ts +2 -2
  212. package/src/forge/review/index.ts +158 -12
  213. package/src/forge/review/types.ts +15 -0
  214. package/src/forge/runtime/auth/config.ts +17 -0
  215. package/src/forge/runtime/auth/evaluate.ts +15 -2
  216. package/src/forge/runtime/auth/resolve.ts +61 -6
  217. package/src/forge/runtime/auth/types.ts +1 -0
  218. package/src/forge/runtime/db/factory.ts +1 -3
  219. package/src/forge/runtime/db/generated-client.ts +13 -2
  220. package/src/forge/runtime/db/memory-adapter.ts +139 -32
  221. package/src/forge/runtime/db/pglite-adapter.ts +263 -2
  222. package/src/forge/runtime/db/postgres-adapter.ts +6 -3
  223. package/src/forge/runtime/executor.ts +129 -16
  224. package/src/forge/runtime/external/bridge.ts +649 -0
  225. package/src/forge/runtime/runner/run-entry.ts +16 -7
  226. package/src/forge/runtime/telemetry/buffer.ts +4 -1
  227. package/src/forge/runtime/telemetry/scrubber.ts +35 -5
  228. package/src/forge/runtime/webhooks/security.ts +12 -7
  229. package/src/forge/server.ts +17 -3
  230. package/src/forge/ui/index.ts +209 -0
  231. package/src/forge/ui/types.ts +1 -0
  232. package/src/forge/version.ts +1 -1
  233. package/src/forge/vue/index.ts +422 -0
  234. package/src/forge/workspace/baseline.ts +112 -0
  235. package/src/forge/workspace/change-summary.ts +250 -0
  236. package/src/forge/workspace/forge-cli.ts +42 -0
  237. package/src/forge/workspace/git-summary.ts +391 -0
  238. package/templates/agent-workroom/AGENTS.md +29 -0
  239. package/templates/agent-workroom/README.md +34 -0
  240. package/templates/agent-workroom/forge.config.ts +3 -0
  241. package/templates/agent-workroom/package.json +33 -0
  242. package/templates/agent-workroom/src/actions/indexAgentSignal.ts +10 -0
  243. package/templates/agent-workroom/src/commands/openWorkroom.ts +61 -0
  244. package/templates/agent-workroom/src/commands/recordAgentSignal.ts +119 -0
  245. package/templates/agent-workroom/src/commands/recordCheckRun.ts +52 -0
  246. package/templates/agent-workroom/src/forge/schema.ts +54 -0
  247. package/templates/agent-workroom/src/policies.ts +6 -0
  248. package/templates/agent-workroom/src/queries/listWorkrooms.ts +11 -0
  249. package/templates/agent-workroom/src/queries/liveWorkroom.ts +63 -0
  250. package/templates/agent-workroom/tsconfig.json +16 -0
  251. package/templates/agent-workroom/web/index.html +12 -0
  252. package/templates/agent-workroom/web/package.json +21 -0
  253. package/templates/agent-workroom/web/src/App.tsx +345 -0
  254. package/templates/agent-workroom/web/src/lib/forge.ts +13 -0
  255. package/templates/agent-workroom/web/src/main.tsx +13 -0
  256. package/templates/agent-workroom/web/src/styles.css +545 -0
  257. package/templates/agent-workroom/web/tsconfig.json +27 -0
  258. package/templates/b2b-support-web/package.json +1 -0
  259. package/templates/b2b-support-web/web/package.json +1 -1
  260. package/templates/minimal-web/package.json +1 -1
  261. package/templates/minimal-web/web/package.json +2 -2
  262. package/templates/nuxt-web/.vscode/settings.json +14 -0
  263. package/templates/nuxt-web/README.md +30 -0
  264. package/templates/nuxt-web/forge.config.ts +3 -0
  265. package/templates/nuxt-web/package.json +33 -0
  266. package/templates/nuxt-web/src/actions/logNoteCreated.ts +11 -0
  267. package/templates/nuxt-web/src/commands/createNote.ts +26 -0
  268. package/templates/nuxt-web/src/forge/schema.ts +12 -0
  269. package/templates/nuxt-web/src/policies.ts +6 -0
  270. package/templates/nuxt-web/src/queries/listNotes.ts +8 -0
  271. package/templates/nuxt-web/src/queries/liveNotes.ts +8 -0
  272. package/templates/nuxt-web/tsconfig.json +17 -0
  273. package/templates/nuxt-web/web/app.vue +67 -0
  274. package/templates/nuxt-web/web/components/LiveNotes.vue +89 -0
  275. package/templates/nuxt-web/web/components/NoteComposer.vue +100 -0
  276. package/templates/nuxt-web/web/composables/forge.ts +13 -0
  277. package/templates/nuxt-web/web/composables/useNotes.ts +24 -0
  278. package/templates/nuxt-web/web/nuxt.config.ts +11 -0
  279. package/templates/nuxt-web/web/package.json +18 -0
  280. package/templates/nuxt-web/web/plugins/forge.client.ts +10 -0
  281. package/templates/nuxt-web/web/plugins/forge.server.ts +10 -0
  282. package/templates/nuxt-web/web/server/api/forge-health.get.ts +7 -0
  283. package/templates/nuxt-web/web/tsconfig.json +6 -0
  284. package/src/forge/_generated/actionSubscriptions.json +0 -2
  285. package/src/forge/_generated/actionSubscriptions.ts +0 -10
  286. package/src/forge/_generated/agentAdapterManifest.json +0 -2
  287. package/src/forge/_generated/agentAdapterManifest.ts +0 -73
  288. package/src/forge/_generated/agentContract.json +0 -2
  289. package/src/forge/_generated/agentContract.ts +0 -7829
  290. package/src/forge/_generated/agentQuickstart.md +0 -34
  291. package/src/forge/_generated/agentTools.json +0 -2
  292. package/src/forge/_generated/agentTools.md +0 -16
  293. package/src/forge/_generated/agentTools.ts +0 -12
  294. package/src/forge/_generated/aiContext.ts +0 -125
  295. package/src/forge/_generated/aiModels.json +0 -2
  296. package/src/forge/_generated/aiModels.ts +0 -51
  297. package/src/forge/_generated/aiProviders.json +0 -2
  298. package/src/forge/_generated/aiProviders.ts +0 -23
  299. package/src/forge/_generated/aiRegistry.json +0 -2
  300. package/src/forge/_generated/aiRegistry.ts +0 -31
  301. package/src/forge/_generated/api.json +0 -2
  302. package/src/forge/_generated/api.ts +0 -8
  303. package/src/forge/_generated/appGraph.json +0 -2
  304. package/src/forge/_generated/appGraph.ts +0 -14919
  305. package/src/forge/_generated/appMap.md +0 -55
  306. package/src/forge/_generated/artifactManifest.json +0 -2
  307. package/src/forge/_generated/artifactManifest.ts +0 -7
  308. package/src/forge/_generated/authClaims.json +0 -2
  309. package/src/forge/_generated/authClaims.ts +0 -13
  310. package/src/forge/_generated/authConfig.json +0 -2
  311. package/src/forge/_generated/authConfig.ts +0 -17
  312. package/src/forge/_generated/authContext.ts +0 -23
  313. package/src/forge/_generated/authRegistry.json +0 -2
  314. package/src/forge/_generated/authRegistry.ts +0 -25
  315. package/src/forge/_generated/buildInfo.json +0 -2
  316. package/src/forge/_generated/buildInfo.ts +0 -9
  317. package/src/forge/_generated/capabilityMap.json +0 -2
  318. package/src/forge/_generated/capabilityMap.md +0 -15
  319. package/src/forge/_generated/capabilityMap.ts +0 -17
  320. package/src/forge/_generated/client.ts +0 -282
  321. package/src/forge/_generated/clientApi.ts +0 -9
  322. package/src/forge/_generated/clientManifest.json +0 -2
  323. package/src/forge/_generated/clientManifest.ts +0 -39
  324. package/src/forge/_generated/clientTypes.ts +0 -78
  325. package/src/forge/_generated/configRegistry.json +0 -2
  326. package/src/forge/_generated/configRegistry.ts +0 -4
  327. package/src/forge/_generated/dataGraph.json +0 -2
  328. package/src/forge/_generated/dataGraph.ts +0 -8
  329. package/src/forge/_generated/db.json +0 -2
  330. package/src/forge/_generated/db.ts +0 -2
  331. package/src/forge/_generated/dbSecurityManifest.json +0 -2
  332. package/src/forge/_generated/dbSecurityManifest.ts +0 -15
  333. package/src/forge/_generated/dbSessionContext.json +0 -2
  334. package/src/forge/_generated/dbSessionContext.ts +0 -39
  335. package/src/forge/_generated/deployManifest.json +0 -2
  336. package/src/forge/_generated/deployManifest.ts +0 -14
  337. package/src/forge/_generated/devManifest.json +0 -2
  338. package/src/forge/_generated/devManifest.ts +0 -62
  339. package/src/forge/_generated/envSchema.json +0 -2
  340. package/src/forge/_generated/envSchema.ts +0 -59
  341. package/src/forge/_generated/frontendGraph.json +0 -2
  342. package/src/forge/_generated/frontendGraph.ts +0 -27
  343. package/src/forge/_generated/importGuards.json +0 -2
  344. package/src/forge/_generated/importGuards.ts +0 -686
  345. package/src/forge/_generated/index.ts +0 -68
  346. package/src/forge/_generated/liveProductionManifest.json +0 -2
  347. package/src/forge/_generated/liveProductionManifest.ts +0 -23
  348. package/src/forge/_generated/liveProtocol.json +0 -2
  349. package/src/forge/_generated/liveProtocol.ts +0 -21
  350. package/src/forge/_generated/liveQueryRegistry.json +0 -2
  351. package/src/forge/_generated/liveQueryRegistry.ts +0 -9
  352. package/src/forge/_generated/liveTransportConfig.json +0 -2
  353. package/src/forge/_generated/liveTransportConfig.ts +0 -19
  354. package/src/forge/_generated/makeRegistry.json +0 -2
  355. package/src/forge/_generated/makeRegistry.ts +0 -177
  356. package/src/forge/_generated/makeTemplates.json +0 -2
  357. package/src/forge/_generated/makeTemplates.ts +0 -66
  358. package/src/forge/_generated/mockMap.json +0 -2
  359. package/src/forge/_generated/mockMap.ts +0 -7
  360. package/src/forge/_generated/operationPlaybooks.md +0 -167
  361. package/src/forge/_generated/packageGraph.json +0 -2
  362. package/src/forge/_generated/packageGraph.ts +0 -249334
  363. package/src/forge/_generated/packageUpgradeRegistry.json +0 -2
  364. package/src/forge/_generated/packageUpgradeRegistry.ts +0 -15
  365. package/src/forge/_generated/permissionMatrix.json +0 -2
  366. package/src/forge/_generated/permissionMatrix.ts +0 -7
  367. package/src/forge/_generated/policyRegistry.json +0 -2
  368. package/src/forge/_generated/policyRegistry.ts +0 -11
  369. package/src/forge/_generated/queryRegistry.json +0 -2
  370. package/src/forge/_generated/queryRegistry.ts +0 -9
  371. package/src/forge/_generated/react.d.ts +0 -22
  372. package/src/forge/_generated/react.ts +0 -29
  373. package/src/forge/_generated/reactManifest.json +0 -2
  374. package/src/forge/_generated/reactManifest.ts +0 -19
  375. package/src/forge/_generated/rlsPolicies.json +0 -2
  376. package/src/forge/_generated/rlsPolicies.sql +0 -34
  377. package/src/forge/_generated/rlsPolicies.ts +0 -6
  378. package/src/forge/_generated/runtimeGraph.json +0 -2
  379. package/src/forge/_generated/runtimeGraph.ts +0 -8
  380. package/src/forge/_generated/runtimeMatrix.json +0 -2
  381. package/src/forge/_generated/runtimeMatrix.ts +0 -334130
  382. package/src/forge/_generated/runtimeRegistry.ts +0 -2
  383. package/src/forge/_generated/runtimeRules.md +0 -91
  384. package/src/forge/_generated/secretRegistry.json +0 -2
  385. package/src/forge/_generated/secretRegistry.ts +0 -50
  386. package/src/forge/_generated/secretsContext.ts +0 -11
  387. package/src/forge/_generated/serverApi.ts +0 -10
  388. package/src/forge/_generated/sourceMapManifest.json +0 -2
  389. package/src/forge/_generated/sourceMapManifest.ts +0 -7
  390. package/src/forge/_generated/sqlPlan.json +0 -2
  391. package/src/forge/_generated/sqlPlan.ts +0 -88
  392. package/src/forge/_generated/subscriptionManifest.json +0 -2
  393. package/src/forge/_generated/subscriptionManifest.ts +0 -7
  394. package/src/forge/_generated/symbolicationManifest.json +0 -2
  395. package/src/forge/_generated/symbolicationManifest.ts +0 -17
  396. package/src/forge/_generated/telemetryRegistry.json +0 -2
  397. package/src/forge/_generated/telemetryRegistry.ts +0 -9
  398. package/src/forge/_generated/telemetrySinks.json +0 -2
  399. package/src/forge/_generated/telemetrySinks.ts +0 -11
  400. package/src/forge/_generated/tenantScope.json +0 -2
  401. package/src/forge/_generated/tenantScope.ts +0 -8
  402. package/src/forge/_generated/testGraph.json +0 -2
  403. package/src/forge/_generated/testGraph.ts +0 -3430
  404. package/src/forge/_generated/testPlanRegistry.json +0 -2
  405. package/src/forge/_generated/testPlanRegistry.ts +0 -33
  406. package/src/forge/_generated/uiRoutes.json +0 -2
  407. package/src/forge/_generated/uiRoutes.ts +0 -16
  408. package/src/forge/_generated/uiScenarios.json +0 -2
  409. package/src/forge/_generated/uiScenarios.ts +0 -30
  410. package/src/forge/_generated/uiTestManifest.json +0 -2
  411. package/src/forge/_generated/uiTestManifest.ts +0 -27
  412. package/src/forge/_generated/workflowRegistry.json +0 -2
  413. package/src/forge/_generated/workflowRegistry.ts +0 -9
  414. package/src/forge/_generated/workflowSubscriptions.json +0 -2
  415. package/src/forge/_generated/workflowSubscriptions.ts +0 -10
@@ -4,18 +4,30 @@ import {
4
4
  FORGE_AUTH_INVALID_AUDIENCE,
5
5
  FORGE_AUTH_JWKS_FAILED,
6
6
  } from "../compiler/diagnostics/codes.ts";
7
- import { loadAuthConfigFromEnv } from "../runtime/auth/config.ts";
7
+ import { loadAuthConfigFromEnv, type AuthClaimsMapping } from "../runtime/auth/config.ts";
8
8
  import { mapClaimsToAuthContext } from "../runtime/auth/claims.ts";
9
9
  import { ForgeAuthError } from "../runtime/auth/errors.ts";
10
10
  import { verifyJwtToken } from "../runtime/auth/verifier.ts";
11
+ import { loadSecretRegistry } from "../runtime/secrets/check.ts";
12
+ import { existsSync } from "node:fs";
13
+ import { join } from "node:path";
14
+ import { normalizeForgeCliCommandsInValue } from "../workspace/forge-cli.ts";
15
+ import {
16
+ collectExpectedResourceTypes,
17
+ collectPolicyPermissions,
18
+ missingValues,
19
+ parseSeedFile,
20
+ } from "./workos.ts";
11
21
 
12
- export type AuthSubcommand = "check" | "config" | "decode" | "test-token" | "jwks" | "prove";
22
+ export type AuthSubcommand = "check" | "config" | "decode" | "test-token" | "jwks" | "prove" | "status";
13
23
 
14
24
  export interface AuthCommandOptions {
15
25
  subcommand: AuthSubcommand;
16
26
  workspaceRoot: string;
17
27
  json: boolean;
18
28
  token?: string;
29
+ prod?: boolean;
30
+ scenario?: string;
19
31
  }
20
32
 
21
33
  export interface AuthCommandResult {
@@ -26,10 +38,40 @@ export interface AuthCommandResult {
26
38
  exitCode: 0 | 1;
27
39
  }
28
40
 
29
- function validateConfig(workspaceRoot: string): AuthCommandResult {
30
- const config = loadAuthConfigFromEnv(workspaceRoot);
31
- const errors: { code: string; message: string }[] = [];
41
+ function detectWorkOS(workspaceRoot: string, claims: AuthClaimsMapping) {
42
+ const secretRegistry = loadSecretRegistry(workspaceRoot);
43
+ const secretNames = new Set((secretRegistry?.secrets ?? []).map((secret) => secret.name));
44
+ const detected =
45
+ secretNames.has("WORKOS_API_KEY") ||
46
+ secretNames.has("WORKOS_CLIENT_ID") ||
47
+ claims.tenantId === "organization_id";
48
+ const expectedClaims = {
49
+ userId: "sub",
50
+ email: "email",
51
+ tenantId: "organization_id",
52
+ role: "role",
53
+ roles: "roles",
54
+ permissions: "permissions",
55
+ };
56
+ const claimStatus = Object.entries(expectedClaims).map(([name, expected]) => ({
57
+ name,
58
+ expected,
59
+ actual: claims[name as keyof AuthClaimsMapping],
60
+ ok: claims[name as keyof AuthClaimsMapping] === expected,
61
+ }));
62
+ return {
63
+ detected,
64
+ requiredSecretsRegistered: ["WORKOS_API_KEY", "WORKOS_CLIENT_ID", "WORKOS_COOKIE_PASSWORD"].every((name) =>
65
+ secretNames.has(name)
66
+ ),
67
+ webhookSecretRegistered: secretNames.has("WORKOS_WEBHOOK_SECRET"),
68
+ expectedClaims,
69
+ claimStatus,
70
+ };
71
+ }
32
72
 
73
+ function configErrors(config: ReturnType<typeof loadAuthConfigFromEnv>): { code: string; message: string }[] {
74
+ const errors: { code: string; message: string }[] = [];
33
75
  if ((config.mode === "jwt" || config.mode === "oidc") && !config.issuer) {
34
76
  errors.push({
35
77
  code: FORGE_AUTH_INVALID_ISSUER,
@@ -48,6 +90,183 @@ function validateConfig(workspaceRoot: string): AuthCommandResult {
48
90
  message: "FORGE_AUTH_JWKS_URI is required for jwt auth",
49
91
  });
50
92
  }
93
+ return errors;
94
+ }
95
+
96
+ function buildAuthPosture(workspaceRoot: string) {
97
+ const config = loadAuthConfigFromEnv(workspaceRoot);
98
+ const productionMode = config.mode === "jwt" || config.mode === "oidc";
99
+ const errors = configErrors(config);
100
+ const configReady = errors.length === 0;
101
+ const classification = config.mode === "dev-headers"
102
+ ? "local-dev"
103
+ : config.mode === "disabled"
104
+ ? "unauthenticated"
105
+ : configReady
106
+ ? "production-ready"
107
+ : "production-incomplete";
108
+ const reason = productionMode
109
+ ? configReady
110
+ ? "jwt/oidc production auth configuration is present"
111
+ : "jwt/oidc production auth is selected but required settings are missing"
112
+ : config.mode === "disabled"
113
+ ? "auth is disabled; this is not suitable for public production traffic"
114
+ : "dev-headers auth is local-only and is not real production authentication";
115
+ return normalizeForgeCliCommandsInValue(workspaceRoot, {
116
+ schemaVersion: "0.1.0",
117
+ mode: config.mode,
118
+ classification,
119
+ localOnly: config.mode === "dev-headers",
120
+ productionReady: productionMode && configReady,
121
+ requiresTenant: config.requiresTenant,
122
+ bearerHeader: productionMode ? "Authorization: Bearer <token>" : null,
123
+ tenantClaim: config.claims.tenantId ?? "tenant_id",
124
+ environment: {
125
+ current: classification,
126
+ localDevelopment: config.mode === "dev-headers",
127
+ publicProduction: productionMode && configReady,
128
+ warning: reason,
129
+ },
130
+ localDevHeaders: config.mode === "dev-headers"
131
+ ? {
132
+ acceptedHeaders: [
133
+ "x-forge-user-id",
134
+ "x-forge-tenant-id",
135
+ "x-forge-role",
136
+ "x-forge-roles",
137
+ "x-forge-permissions",
138
+ ],
139
+ scope: "forge dev, tests, and local agent workflows only",
140
+ neverProduction: true,
141
+ }
142
+ : null,
143
+ productionRequirements: {
144
+ requiredMode: "jwt or oidc",
145
+ bearerHeader: "Authorization: Bearer <token>",
146
+ requiredEnv: [
147
+ "FORGE_AUTH_MODE",
148
+ "FORGE_AUTH_ISSUER",
149
+ "FORGE_AUTH_AUDIENCE",
150
+ config.mode === "oidc" ? "OIDC discovery at FORGE_AUTH_ISSUER" : "FORGE_AUTH_JWKS_URI",
151
+ ],
152
+ proofCommand: "forge auth prove --prod --token <jwt> --json",
153
+ },
154
+ productionChecklist: [
155
+ { item: "auth mode is jwt or oidc", ok: productionMode },
156
+ { item: "FORGE_AUTH_ISSUER configured", ok: Boolean(config.issuer) },
157
+ { item: "FORGE_AUTH_AUDIENCE configured", ok: Boolean(config.audience) },
158
+ { item: "FORGE_AUTH_JWKS_URI or OIDC discovery configured", ok: config.mode === "oidc" || Boolean(config.jwksUri) },
159
+ { item: "tenant claim mapped", ok: Boolean(config.claims.tenantId) },
160
+ { item: "permission claim mapped", ok: Boolean(config.claims.permissions) },
161
+ { item: "dev-headers disabled for public runtime", ok: config.mode !== "dev-headers" },
162
+ ],
163
+ reason,
164
+ nextActions: productionMode
165
+ ? configReady
166
+ ? ["forge auth prove --prod --token <jwt> --json", "forge serve --json"]
167
+ : ["forge auth check --json", "configure FORGE_AUTH_ISSUER, FORGE_AUTH_AUDIENCE, and FORGE_AUTH_JWKS_URI or OIDC issuer"]
168
+ : ["set FORGE_AUTH_MODE=jwt or oidc for production", "forge auth prove --prod --token <jwt> --json"],
169
+ });
170
+ }
171
+
172
+ function permissionSubsetForRestrictedTenant(permissions: string[]): string[] {
173
+ const readonly = permissions.filter((permission) =>
174
+ /(^|[:._-])(read|list|view|inspect|search)($|[:._-])/.test(permission)
175
+ );
176
+ if (readonly.length > 0) return readonly;
177
+ return permissions.slice(0, Math.max(1, Math.floor(permissions.length / 2)));
178
+ }
179
+
180
+ function buildMultiTenantProof(workspaceRoot: string, workos: ReturnType<typeof detectWorkOS>, requiresTenant: boolean) {
181
+ const rootSeedPresent = existsSync(join(workspaceRoot, "workos-seed.yml"));
182
+ const generatedSeedPresent = existsSync(join(workspaceRoot, "src/forge/_generated/integrations/workos/workos-seed.yml"));
183
+ const authMdPresent = existsSync(join(workspaceRoot, "public/auth.md"));
184
+ const metadataPresent = existsSync(join(workspaceRoot, "public/.well-known/oauth-protected-resource"));
185
+ const activePermissions = collectPolicyPermissions(workspaceRoot);
186
+ const expectedResourceTypes = collectExpectedResourceTypes(workspaceRoot);
187
+ const seed = parseSeedFile(workspaceRoot);
188
+ const missingSeedPermissions = missingValues(activePermissions, seed.permissions);
189
+ const missingSeedResources = missingValues(expectedResourceTypes, seed.resourceTypes);
190
+ const acmePermissions = activePermissions;
191
+ const globexPermissions = permissionSubsetForRestrictedTenant(activePermissions);
192
+ const permissionVocabularyPresent = workos.detected && workos.claimStatus.some((claim) => claim.name === "permissions" && claim.ok);
193
+ const checks = [
194
+ {
195
+ id: "tenant-claim",
196
+ ok: requiresTenant && workos.claimStatus.some((claim) => claim.name === "tenantId" && claim.ok),
197
+ evidence: "Forge tenant claim maps to WorkOS organization_id and tenant auth is required.",
198
+ },
199
+ {
200
+ id: "permission-claim",
201
+ ok: activePermissions.length > 0 && permissionVocabularyPresent,
202
+ evidence: activePermissions.length > 0
203
+ ? `Forge permissions claim maps to WorkOS permissions: ${activePermissions.join(", ")}.`
204
+ : "No active policy permissions were found in the generated policy registry.",
205
+ },
206
+ {
207
+ id: "seed-organizations",
208
+ ok: rootSeedPresent || generatedSeedPresent,
209
+ evidence: rootSeedPresent
210
+ ? "workos-seed.yml exists at app root."
211
+ : generatedSeedPresent
212
+ ? "generated WorkOS seed exists."
213
+ : "no WorkOS seed file found at app root or in generated integrations.",
214
+ },
215
+ {
216
+ id: "seed-permission-coverage",
217
+ ok: activePermissions.length > 0 && missingSeedPermissions.length === 0,
218
+ evidence: activePermissions.length === 0
219
+ ? "No active policy permissions were found in the generated policy registry."
220
+ : missingSeedPermissions.length === 0
221
+ ? `seed covers active app permission(s): ${activePermissions.join(", ")}`
222
+ : `seed missing active app permission(s): ${missingSeedPermissions.join(", ")}`,
223
+ },
224
+ {
225
+ id: "seed-resource-coverage",
226
+ ok: missingSeedResources.length === 0,
227
+ evidence: missingSeedResources.length === 0
228
+ ? `seed covers expected app resource type(s): ${expectedResourceTypes.join(", ") || "none required"}`
229
+ : `seed missing expected app resource type(s): ${missingSeedResources.join(", ")}`,
230
+ },
231
+ {
232
+ id: "agent-auth-metadata",
233
+ ok: authMdPresent && metadataPresent,
234
+ evidence: "public/auth.md and protected resource metadata are present.",
235
+ },
236
+ ];
237
+ return normalizeForgeCliCommandsInValue(workspaceRoot, {
238
+ scenario: "multi-tenant",
239
+ ok: checks.every((check) => check.ok),
240
+ claims: {
241
+ acme: { organization_id: "org_acme", role: "owner", permissions: acmePermissions },
242
+ globex: { organization_id: "org_globex", role: "member", permissions: globexPermissions },
243
+ },
244
+ appContract: {
245
+ activePermissions,
246
+ expectedResourceTypes,
247
+ seedPath: seed.path,
248
+ seedPermissions: seed.permissions,
249
+ seedResourceTypes: seed.resourceTypes,
250
+ },
251
+ invariants: [
252
+ "Acme and Globex must use different organization_id claim values.",
253
+ "Tenant-scoped reads must include the active organization_id.",
254
+ "Tenant-scoped writes must verify the resource tenant before mutation.",
255
+ "Role-only UI affordances are not sufficient; policies must use the app's generated permission vocabulary.",
256
+ ],
257
+ checks,
258
+ nextActions: [
259
+ "forge workos doctor --json",
260
+ "forge workos seed --file workos-seed.yml --dry-run --json",
261
+ "run an HTTP E2E with Acme and Globex tokens before production",
262
+ ],
263
+ });
264
+ }
265
+
266
+ function validateConfig(workspaceRoot: string): AuthCommandResult {
267
+ const config = loadAuthConfigFromEnv(workspaceRoot);
268
+ const errors = configErrors(config);
269
+ const workos = detectWorkOS(workspaceRoot, config.claims);
51
270
 
52
271
  return {
53
272
  ok: errors.length === 0,
@@ -60,6 +279,8 @@ function validateConfig(workspaceRoot: string): AuthCommandResult {
60
279
  algorithms: config.algorithms,
61
280
  claims: config.claims,
62
281
  requiresTenant: config.requiresTenant,
282
+ authPosture: buildAuthPosture(workspaceRoot),
283
+ workos,
63
284
  errors,
64
285
  },
65
286
  error: errors[0],
@@ -69,6 +290,7 @@ function validateConfig(workspaceRoot: string): AuthCommandResult {
69
290
 
70
291
  function publicConfig(workspaceRoot: string): AuthCommandResult {
71
292
  const config = loadAuthConfigFromEnv(workspaceRoot);
293
+ const workos = detectWorkOS(workspaceRoot, config.claims);
72
294
  return {
73
295
  ok: true,
74
296
  mode: config.mode,
@@ -80,6 +302,8 @@ function publicConfig(workspaceRoot: string): AuthCommandResult {
80
302
  algorithms: config.algorithms,
81
303
  claims: config.claims,
82
304
  requiresTenant: config.requiresTenant,
305
+ authPosture: buildAuthPosture(workspaceRoot),
306
+ workos,
83
307
  },
84
308
  exitCode: 0,
85
309
  };
@@ -160,22 +384,76 @@ async function testToken(
160
384
  export async function runAuthCommand(
161
385
  options: AuthCommandOptions,
162
386
  ): Promise<AuthCommandResult> {
387
+ if (options.subcommand === "status") {
388
+ const posture = buildAuthPosture(options.workspaceRoot);
389
+ return {
390
+ ok: true,
391
+ mode: posture.mode,
392
+ data: posture,
393
+ exitCode: 0,
394
+ };
395
+ }
163
396
  if (options.subcommand === "check") {
164
- return validateConfig(options.workspaceRoot);
397
+ const checked = validateConfig(options.workspaceRoot);
398
+ if (!options.prod) {
399
+ return checked;
400
+ }
401
+ const posture = buildAuthPosture(options.workspaceRoot);
402
+ const productionReady = posture.productionReady === true;
403
+ return {
404
+ ok: checked.ok && productionReady,
405
+ mode: checked.mode,
406
+ data: {
407
+ ...(checked.data && typeof checked.data === "object" ? checked.data as Record<string, unknown> : {}),
408
+ production: true,
409
+ authPosture: posture,
410
+ productionCheck: {
411
+ ok: productionReady,
412
+ reason: posture.reason,
413
+ requiredMode: "jwt or oidc",
414
+ localOnlyModeRejected: posture.localOnly === true,
415
+ },
416
+ },
417
+ error: productionReady
418
+ ? checked.error
419
+ : { code: "FORGE_AUTH_MODE_INVALID", message: "production auth requires FORGE_AUTH_MODE=jwt or oidc; dev-headers is local-only" },
420
+ exitCode: checked.ok && productionReady ? 0 : 1,
421
+ };
165
422
  }
166
423
  if (options.subcommand === "prove") {
167
424
  const checked = validateConfig(options.workspaceRoot);
168
425
  const config = loadAuthConfigFromEnv(options.workspaceRoot);
426
+ const workos = detectWorkOS(options.workspaceRoot, config.claims);
169
427
  const productionMode = config.mode === "jwt" || config.mode === "oidc";
428
+ const workosClaimsOk = workos.claimStatus.every((claim) => claim.ok);
429
+ const posture = buildAuthPosture(options.workspaceRoot);
430
+ const tokenProof = options.token ? await testToken(options.workspaceRoot, options.token) : null;
431
+ const prodError = options.prod && !productionMode
432
+ ? { code: "FORGE_AUTH_MODE_INVALID", message: "forge auth prove --prod requires FORGE_AUTH_MODE=jwt or oidc" }
433
+ : options.prod && !options.token
434
+ ? { code: "FORGE_AUTH_MISSING_TOKEN", message: "forge auth prove --prod requires --token" }
435
+ : options.prod && tokenProof && !tokenProof.ok
436
+ ? tokenProof.error
437
+ : undefined;
438
+ const proofOk = checked.ok && (!options.prod || (productionMode && tokenProof?.ok === true));
439
+ const multiTenantProof = options.scenario === "multi-tenant"
440
+ ? buildMultiTenantProof(options.workspaceRoot, workos, config.requiresTenant)
441
+ : null;
442
+ const scenarioOk = !multiTenantProof || multiTenantProof.ok;
170
443
  return {
171
- ok: checked.ok,
444
+ ok: proofOk && scenarioOk,
172
445
  mode: config.mode,
173
446
  data: {
174
447
  schemaVersion: "0.1.0",
175
448
  kind: "auth-proof",
176
- ok: checked.ok,
449
+ ok: proofOk,
177
450
  mode: config.mode,
178
451
  productionReady: productionMode && checked.ok,
452
+ prod: options.prod === true,
453
+ scenario: options.scenario ?? null,
454
+ authPosture: posture,
455
+ ...(tokenProof ? { tokenProof: tokenProof.ok ? tokenProof.data : tokenProof.error } : {}),
456
+ ...(multiTenantProof ? { multiTenantProof } : {}),
179
457
  invariants: [
180
458
  {
181
459
  id: "INV-001",
@@ -191,11 +469,27 @@ export async function runAuthCommand(
191
469
  status: checked.ok ? "passed" : "failed",
192
470
  evidence: checked.data,
193
471
  },
472
+ {
473
+ id: "INV-WORKOS-001",
474
+ name: "WorkOS adapter claim mapping is explicit when WorkOS is present",
475
+ status: !workos.detected ? "not-applicable" : workosClaimsOk ? "passed" : "failed",
476
+ evidence: workos.claimStatus,
477
+ },
478
+ {
479
+ id: "INV-WORKOS-002",
480
+ name: "WorkOS required secret names are registered without values",
481
+ status: !workos.detected ? "not-applicable" : workos.requiredSecretsRegistered ? "passed" : "failed",
482
+ evidence: {
483
+ required: ["WORKOS_API_KEY", "WORKOS_CLIENT_ID", "WORKOS_COOKIE_PASSWORD"],
484
+ webhookSecretRegistered: workos.webhookSecretRegistered,
485
+ },
486
+ },
194
487
  ],
488
+ workos,
195
489
  checkedAt: "deterministic",
196
490
  },
197
- error: checked.error,
198
- exitCode: checked.exitCode,
491
+ error: prodError ?? checked.error,
492
+ exitCode: proofOk && scenarioOk ? 0 : 1,
199
493
  };
200
494
  }
201
495
  if (options.subcommand === "config") {
@@ -225,7 +519,51 @@ export function formatAuthJson(result: AuthCommandResult): string {
225
519
  return `${JSON.stringify(result, null, 2)}\n`;
226
520
  }
227
521
 
522
+ function authPostureFromResult(result: AuthCommandResult): Record<string, unknown> | null {
523
+ const data = result.data && typeof result.data === "object" ? result.data as Record<string, unknown> : {};
524
+ const direct = data.schemaVersion === "0.1.0" && "classification" in data ? data : null;
525
+ const nested = data.authPosture && typeof data.authPosture === "object"
526
+ ? data.authPosture as Record<string, unknown>
527
+ : null;
528
+ return direct ?? nested;
529
+ }
530
+
228
531
  export function formatAuthHuman(result: AuthCommandResult): string {
532
+ const posture = authPostureFromResult(result);
533
+ if (posture) {
534
+ const classification = typeof posture.classification === "string" ? posture.classification : result.mode;
535
+ const reason = typeof posture.reason === "string" ? posture.reason : result.error?.message;
536
+ const nextActions = Array.isArray(posture.nextActions) ? posture.nextActions.filter((item): item is string => typeof item === "string") : [];
537
+ const lines = [
538
+ `Auth ${result.mode}: ${result.ok ? "ok" : "failed"} (${classification})`,
539
+ `Production ready: ${posture.productionReady === true ? "yes" : "no"}`,
540
+ ...(reason ? [`Reason: ${reason}`] : []),
541
+ ];
542
+ const localDevHeaders = posture.localDevHeaders && typeof posture.localDevHeaders === "object"
543
+ ? posture.localDevHeaders as Record<string, unknown>
544
+ : null;
545
+ const acceptedHeaders = Array.isArray(localDevHeaders?.acceptedHeaders)
546
+ ? localDevHeaders.acceptedHeaders.filter((item): item is string => typeof item === "string")
547
+ : posture.localOnly === true || result.mode === "dev-headers"
548
+ ? [
549
+ "x-forge-user-id",
550
+ "x-forge-tenant-id",
551
+ "x-forge-role",
552
+ "x-forge-roles",
553
+ "x-forge-permissions",
554
+ ]
555
+ : [];
556
+ if (acceptedHeaders.length > 0) {
557
+ lines.push("Local dev headers:", ...acceptedHeaders.map((header) => ` ${header}`));
558
+ }
559
+ if (!result.ok && result.error) {
560
+ lines.push(`${result.error.code}: ${result.error.message}`);
561
+ }
562
+ if (nextActions.length > 0) {
563
+ lines.push("", "Next:", ...nextActions.map((action) => ` ${action}`));
564
+ }
565
+ return `${lines.join("\n")}\n`;
566
+ }
229
567
  if (!result.ok) {
230
568
  return `Auth ${result.mode}: failed\n${result.error?.code}: ${result.error?.message}\n`;
231
569
  }