@inneranimalmedia/agentsam-sdk 2.6.2 → 2.6.3

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 (497) hide show
  1. package/AGENTSAM.md +45 -1
  2. package/README.md +80 -0
  3. package/apps/README.md +34 -0
  4. package/apps/cad-creator/README.md +728 -0
  5. package/apps/cad-creator/shared/cad/package.json +19 -0
  6. package/apps/cad-creator/shared/cad/src/domain/operations.ts +7 -0
  7. package/apps/cad-creator/shared/cad/src/domain/project-contract.d.ts +3 -0
  8. package/apps/cad-creator/shared/cad/src/domain/project-contract.js +75 -0
  9. package/apps/cad-creator/shared/cad/src/domain/project-tools.d.ts +1 -0
  10. package/apps/cad-creator/shared/cad/src/domain/project-tools.js +24 -0
  11. package/apps/cad-creator/shared/cad/src/domain/validation.ts +191 -0
  12. package/apps/cad-creator/shared/cad/src/index.ts +4 -0
  13. package/apps/cad-creator/shared/cad/src/robotics/types.ts +232 -0
  14. package/apps/cad-creator/shared/cad/src/types.ts +507 -0
  15. package/apps/cad-creator/shared/cad/tsconfig.json +14 -0
  16. package/docs/AUTORAG.md +58 -0
  17. package/docs/BRAND_INTELLIGENCE.md +30 -0
  18. package/docs/CLI_SHELL.md +4 -2
  19. package/docs/CMS_CONTEXTUAL_COMPOSER.md +38 -0
  20. package/docs/MERKLE.md +4 -0
  21. package/docs/PROJECT_CONFIG.md +3 -0
  22. package/docs/REPOSITORY_KNOWLEDGE.md +2 -0
  23. package/docs/THEME_REFINERY.md +120 -0
  24. package/docs/architecture/PROVIDER-TOOLS-AND-COMPACTION.md +60 -0
  25. package/docs/architecture/STORAGE.md +87 -0
  26. package/docs/cad-project-tools.md +69 -0
  27. package/docs/cms-scaffolding-pattern-reference.md +73 -0
  28. package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS-codex-tui-20260919.md +113 -0
  29. package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS.md +85 -0
  30. package/docs/plans/AGENTSAM-MCP-CLIENT-2026-09-19.md +181 -0
  31. package/docs/plans/ASBD-PORTABLE-WORKGRAPH-UI-DEFERRED.md +34 -0
  32. package/docs/plans/ASTRA-BRIEF-2026-09-18.md +258 -0
  33. package/docs/plans/MULTI-AGENT-SPRINTS-2026-09-19.md +373 -0
  34. package/docs/plans/NEXT-AGENT-HANDOFF.md +167 -0
  35. package/docs/plans/RECONCILIATION-2026-09-19.md +178 -0
  36. package/docs/plugins.md +43 -0
  37. package/docs/tools/README.md +57 -0
  38. package/docs/tools/agent-and-orchestration.md +49 -0
  39. package/docs/tools/browser-and-research.md +46 -0
  40. package/docs/tools/cloudflare-platform.md +32 -0
  41. package/docs/tools/cms.md +25 -0
  42. package/docs/tools/communications.md +41 -0
  43. package/docs/tools/database-and-storage.md +62 -0
  44. package/docs/tools/design-and-media.md +64 -0
  45. package/docs/tools/filesystem-and-code.md +55 -0
  46. package/docs/tools/github.md +56 -0
  47. package/docs/tools/integrations-and-misc.md +16 -0
  48. package/docs/tools/memory.md +21 -0
  49. package/docs/tools/terminal-and-execution.md +29 -0
  50. package/docs/tools/tickets-and-platform.md +30 -0
  51. package/migrations/d1/0001_agentsam_plugin_runtime.sql +177 -0
  52. package/migrations/d1/0002_agentsam_ticket_ownership.sql +8 -0
  53. package/migrations/d1/0002_dynamic_model_policies.sql +23 -0
  54. package/migrations/d1/0003_expand_tool_handler_families.sql +18 -0
  55. package/migrations/d1/0004_project_aware_retrieval_lanes.sql +24 -0
  56. package/migrations/d1/0005_portable_knowledge_identity.sql +104 -0
  57. package/migrations/d1/0006_repair_ops_trail_account_scope.sql +14 -0
  58. package/migrations/d1/0007_repair_ops_trail_agent_run_account.sql +13 -0
  59. package/migrations/d1/0008_backfill_knowledge_run_legacy_tenant.sql +14 -0
  60. package/migrations/d1/0009_normalize_cloudflare_plugin_installations.sql +137 -0
  61. package/migrations/runtime/0001_cli_runtime.sql +67 -0
  62. package/migrations/runtime/0002_project_sessions.sql +15 -0
  63. package/migrations/runtime/0003_provider_continuations.sql +8 -0
  64. package/package.json +92 -12
  65. package/packages/agentsam-brand/README.md +21 -0
  66. package/packages/agentsam-brand/package.json +22 -0
  67. package/packages/agentsam-brand/src/contract.js +59 -0
  68. package/packages/agentsam-brand/src/extract.js +126 -0
  69. package/packages/agentsam-brand/src/goap-actions.js +73 -0
  70. package/packages/agentsam-brand/src/index.js +48 -0
  71. package/packages/agentsam-brand/src/plan.js +115 -0
  72. package/packages/agentsam-brand/src/resolve.js +139 -0
  73. package/packages/agentsam-brand/src/scan.js +250 -0
  74. package/packages/agentsam-brand/test/brand-scan.test.mjs +106 -0
  75. package/packages/agentsam-contracts/README.md +23 -0
  76. package/packages/agentsam-contracts/package.json +32 -0
  77. package/packages/agentsam-contracts/src/adapter.ts +25 -0
  78. package/packages/agentsam-contracts/src/agent.ts +35 -0
  79. package/packages/agentsam-contracts/src/artifacts.ts +33 -0
  80. package/packages/agentsam-contracts/src/authority.ts +29 -0
  81. package/packages/agentsam-contracts/src/context.ts +16 -0
  82. package/packages/agentsam-contracts/src/errors.ts +46 -0
  83. package/packages/agentsam-contracts/src/events.ts +47 -0
  84. package/packages/agentsam-contracts/src/execution.ts +50 -0
  85. package/packages/agentsam-contracts/src/hooks.ts +40 -0
  86. package/packages/agentsam-contracts/src/identity.ts +16 -0
  87. package/packages/agentsam-contracts/src/index.ts +14 -0
  88. package/packages/agentsam-contracts/src/models.ts +9 -0
  89. package/packages/agentsam-contracts/src/providers.ts +33 -0
  90. package/packages/agentsam-contracts/src/repository.ts +64 -0
  91. package/packages/agentsam-contracts/src/tools.ts +98 -0
  92. package/packages/agentsam-contracts/test/contracts.test.mjs +16 -0
  93. package/packages/agentsam-contracts/test/errors-catalog.test.mjs +25 -0
  94. package/packages/agentsam-contracts/test/repository.test.mjs +18 -0
  95. package/packages/agentsam-contracts/tsconfig.json +12 -0
  96. package/packages/agentsam-errors/package.json +17 -0
  97. package/packages/agentsam-errors/src/adapters/anthropic.js +15 -0
  98. package/packages/agentsam-errors/src/adapters/cad.js +109 -0
  99. package/packages/agentsam-errors/src/adapters/cloudflare.js +21 -0
  100. package/packages/agentsam-errors/src/adapters/cursor.js +4 -0
  101. package/packages/agentsam-errors/src/adapters/device.js +38 -0
  102. package/packages/agentsam-errors/src/adapters/docker.js +28 -0
  103. package/packages/agentsam-errors/src/adapters/gcp.js +14 -0
  104. package/packages/agentsam-errors/src/adapters/github.js +22 -0
  105. package/packages/agentsam-errors/src/adapters/google.js +17 -0
  106. package/packages/agentsam-errors/src/adapters/index.js +55 -0
  107. package/packages/agentsam-errors/src/adapters/internal.js +40 -0
  108. package/packages/agentsam-errors/src/adapters/oauth.js +24 -0
  109. package/packages/agentsam-errors/src/adapters/openai.js +17 -0
  110. package/packages/agentsam-errors/src/adapters/process.js +35 -0
  111. package/packages/agentsam-errors/src/adapters/provider.js +114 -0
  112. package/packages/agentsam-errors/src/envelope.js +186 -0
  113. package/packages/agentsam-errors/src/error.js +24 -0
  114. package/packages/agentsam-errors/src/fingerprint.js +35 -0
  115. package/packages/agentsam-errors/src/index.js +10 -0
  116. package/packages/agentsam-errors/src/normalize.js +30 -0
  117. package/packages/agentsam-errors/src/redaction.js +52 -0
  118. package/packages/agentsam-errors/src/render.js +16 -0
  119. package/packages/agentsam-errors/src/retry.js +10 -0
  120. package/packages/agentsam-errors/src/transport.js +52 -0
  121. package/packages/agentsam-errors/src/vocabulary.js +320 -0
  122. package/packages/agentsam-errors/test/envelope.test.mjs +70 -0
  123. package/packages/agentsam-errors/test/providers.test.mjs +99 -0
  124. package/packages/agentsam-errors/test/redaction.test.mjs +21 -0
  125. package/packages/agentsam-errors/test/runtime-cad-device.test.mjs +76 -0
  126. package/packages/agentsam-errors/test/transport.test.mjs +46 -0
  127. package/packages/agentsam-knowledge/package.json +15 -0
  128. package/packages/agentsam-knowledge/src/autorag/index.js +64 -0
  129. package/packages/agentsam-knowledge/src/backends/index.js +26 -0
  130. package/packages/agentsam-knowledge/src/index.js +3 -0
  131. package/packages/agentsam-knowledge/src/providers/index.js +95 -0
  132. package/packages/agentsam-knowledge/test/autorag.test.mjs +42 -0
  133. package/packages/agentsam-nav/README.md +40 -0
  134. package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
  135. package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
  136. package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
  137. package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
  138. package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
  139. package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
  140. package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
  141. package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
  142. package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
  143. package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
  144. package/packages/agentsam-nav/dist/browser.d.ts +11 -0
  145. package/packages/agentsam-nav/dist/browser.global.js +132 -0
  146. package/packages/agentsam-nav/dist/browser.js +613 -0
  147. package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
  148. package/packages/agentsam-nav/dist/index.d.ts +11 -0
  149. package/packages/agentsam-nav/dist/index.js +614 -0
  150. package/packages/agentsam-nav/dist/legacy.css +83 -0
  151. package/packages/agentsam-nav/dist/shell.css +113 -0
  152. package/packages/agentsam-nav/dist/theme.css +113 -0
  153. package/packages/agentsam-nav/dist/utils.d.ts +1 -0
  154. package/packages/agentsam-nav/package.json +43 -0
  155. package/packages/agentsam-queue-control/README.md +107 -0
  156. package/packages/agentsam-queue-control/package.json +31 -0
  157. package/packages/agentsam-queue-control/schemas/job-envelope.schema.json +56 -0
  158. package/packages/agentsam-queue-control/src/adapters/cloudflare.js +152 -0
  159. package/packages/agentsam-queue-control/src/adapters/memory.js +38 -0
  160. package/packages/agentsam-queue-control/src/contracts.js +130 -0
  161. package/packages/agentsam-queue-control/src/control-plane.js +141 -0
  162. package/packages/agentsam-queue-control/src/dispatch.js +43 -0
  163. package/packages/agentsam-queue-control/src/index.js +7 -0
  164. package/packages/agentsam-queue-control/src/policy.js +88 -0
  165. package/packages/agentsam-queue-control/src/topology.js +66 -0
  166. package/packages/agentsam-queue-control/test/queue-control.test.mjs +100 -0
  167. package/packages/agentsam-repository/src/goap.js +718 -0
  168. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
  169. package/packages/agentsam-repository/src/index.js +5 -0
  170. package/packages/agentsam-repository/src/merkle/cloudflare-persistence.js +2 -2
  171. package/packages/agentsam-repository/src/tickets.js +184 -0
  172. package/packages/agentsam-repository/src/work-tracking.js +199 -0
  173. package/packages/agentsam-repository/src/workspace-state.js +176 -0
  174. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +152 -0
  175. package/packages/connectors/cloudflare/src/index.js +297 -15
  176. package/packages/connectors/cloudflare/src/owner.js +43 -40
  177. package/packages/connectors/cloudflare/src/routes.js +167 -26
  178. package/packages/connectors/cloudflare/tests/connector.test.mjs +112 -2
  179. package/packages/heuristic-theme/README.md +11 -0
  180. package/packages/heuristic-theme/package.json +25 -0
  181. package/packages/heuristic-theme/src/index.js +2 -0
  182. package/packages/heuristic-theme/src/registry.js +36 -0
  183. package/packages/heuristic-theme/src/theme.js +41 -0
  184. package/packages/heuristic-theme/test/theme.test.mjs +26 -0
  185. package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +64 -0
  186. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +96 -0
  187. package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +47 -0
  188. package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +74 -0
  189. package/packages/identity/.agentsam/features/oauth-login-portal/ui.json +35 -0
  190. package/packages/identity/package.json +3 -2
  191. package/packages/identity/src/adapters/cloudflare-d1/ids.js +4 -0
  192. package/packages/identity/src/adapters/cloudflare-d1/index.js +39 -1
  193. package/packages/identity/src/contracts/provider.js +3 -2
  194. package/packages/identity/src/frontend/auth-portal/pages/login.html +7 -0
  195. package/packages/identity/src/index.js +2 -0
  196. package/packages/identity/src/oauth/credentials.js +13 -0
  197. package/packages/identity/src/oauth/iam-platform.js +5 -5
  198. package/packages/identity/src/providers/cloudflare/index.js +19 -0
  199. package/packages/identity/src/providers/cloudflare/mapper.js +21 -0
  200. package/packages/identity/src/providers/cloudflare/oauth.js +48 -0
  201. package/packages/identity/src/providers/cloudflare/profile.js +28 -0
  202. package/packages/identity/src/providers/index.js +18 -2
  203. package/packages/identity/src/server/identity-service.js +13 -3
  204. package/packages/identity/src/server/worker-router.js +63 -8
  205. package/packages/identity/tests/identity-service.test.mjs +15 -0
  206. package/packages/providers/completeful/README.md +38 -0
  207. package/packages/providers/completeful/package.json +29 -0
  208. package/packages/providers/completeful/src/client.js +162 -0
  209. package/packages/providers/completeful/src/events.js +49 -0
  210. package/packages/providers/completeful/src/index.js +22 -0
  211. package/packages/providers/completeful/src/tools.js +579 -0
  212. package/packages/providers/completeful/src/webhooks.js +55 -0
  213. package/packages/providers/completeful/test/provider.test.mjs +196 -0
  214. package/packages/theme-church-site/README.md +10 -0
  215. package/packages/theme-church-site/package.json +30 -0
  216. package/packages/theme-church-site/src/harvest.json +14 -0
  217. package/packages/theme-church-site/src/index.js +84 -0
  218. package/packages/theme-church-site/test/theme.test.mjs +19 -0
  219. package/packages/theme-companions-site/README.md +10 -0
  220. package/packages/theme-companions-site/package.json +30 -0
  221. package/packages/theme-companions-site/src/harvest.json +12 -0
  222. package/packages/theme-companions-site/src/index.js +82 -0
  223. package/packages/theme-companions-site/test/theme.test.mjs +19 -0
  224. package/packages/theme-floors-site/README.md +10 -0
  225. package/packages/theme-floors-site/package.json +30 -0
  226. package/packages/theme-floors-site/src/harvest.json +14 -0
  227. package/packages/theme-floors-site/src/index.js +82 -0
  228. package/packages/theme-floors-site/test/theme.test.mjs +19 -0
  229. package/packages/theme-fuelnfree-site/README.md +10 -0
  230. package/packages/theme-fuelnfree-site/package.json +30 -0
  231. package/packages/theme-fuelnfree-site/src/harvest.json +13 -0
  232. package/packages/theme-fuelnfree-site/src/index.js +81 -0
  233. package/packages/theme-fuelnfree-site/test/theme.test.mjs +19 -0
  234. package/packages/theme-handyman-site/README.md +10 -0
  235. package/packages/theme-handyman-site/package.json +30 -0
  236. package/packages/theme-handyman-site/src/harvest.json +10 -0
  237. package/packages/theme-handyman-site/src/index.js +83 -0
  238. package/packages/theme-handyman-site/test/theme.test.mjs +19 -0
  239. package/packages/theme-insurance-site/README.md +10 -0
  240. package/packages/theme-insurance-site/package.json +30 -0
  241. package/packages/theme-insurance-site/src/harvest.json +10 -0
  242. package/packages/theme-insurance-site/src/index.js +83 -0
  243. package/packages/theme-insurance-site/test/theme.test.mjs +19 -0
  244. package/packages/theme-shinshu-site/README.md +10 -0
  245. package/packages/theme-shinshu-site/package.json +30 -0
  246. package/packages/theme-shinshu-site/src/harvest.json +12 -0
  247. package/packages/theme-shinshu-site/src/index.js +83 -0
  248. package/packages/theme-shinshu-site/test/theme.test.mjs +19 -0
  249. package/packages/work-graph/README.md +49 -0
  250. package/packages/work-graph/package.json +19 -0
  251. package/packages/work-graph/prototype/README.md +32 -0
  252. package/packages/work-graph/prototype/data/demo-workgraph.js +47 -0
  253. package/packages/work-graph/prototype/renderers/timeline-model.js +21 -0
  254. package/packages/work-graph/prototype/renderers/workgraph-runtime.js +38 -0
  255. package/packages/work-graph/prototype-gnantt.html +655 -0
  256. package/packages/work-graph/src/adapters/business/projects.js +23 -0
  257. package/packages/work-graph/src/adapters/engineering/git.js +22 -0
  258. package/packages/work-graph/src/adapters/engineering/mcp.js +22 -0
  259. package/packages/work-graph/src/index.js +76 -0
  260. package/packages/work-graph/src/renderers/gantt-model.js +11 -0
  261. package/packages/work-graph/src/renderers/timeline.js +16 -0
  262. package/packages/work-graph/test/work-graph.test.mjs +37 -0
  263. package/protocol/README.md +12 -0
  264. package/protocol/capabilities/cloudflare-cpu-audit-input.schema.json +30 -6
  265. package/protocol/capabilities/cloudflare-cpu-profile-input.schema.json +18 -4
  266. package/protocol/capabilities/cloudflare-wrangler-native-input.schema.json +59 -10
  267. package/protocol/capabilities/knowledge-search-input.schema.json +35 -0
  268. package/protocol/capabilities/manifest.json +163 -1
  269. package/protocol/capabilities/repository-audit-input.schema.json +39 -6
  270. package/protocol/capabilities/repository-snapshot-input.schema.json +15 -3
  271. package/protocol/capabilities/terminal-exec-input.schema.json +55 -0
  272. package/protocol/commerce/catalog.v1.json +50 -0
  273. package/protocol/errors/error-catalog.json +164 -0
  274. package/protocol/errors/error-envelope.schema.json +544 -0
  275. package/protocol/features/README.md +57 -0
  276. package/protocol/features/agentsam.feature.v1.schema.json +290 -0
  277. package/protocol/features/catalog.json +65 -0
  278. package/protocol/features/examples/provider-resend.feature.json +17 -0
  279. package/protocol/go/agentsam-go-runtime.v1.json +17 -0
  280. package/protocol/knowledge/LIFECYCLE.md +140 -0
  281. package/protocol/knowledge/README.md +4 -0
  282. package/protocol/presets/catalog.json +128 -19
  283. package/protocol/rpc/v1/errors.proto +24 -0
  284. package/protocol/theme-refinery/d1-reconciliation.md +48 -0
  285. package/protocol/theme-refinery/product-metadata.schema.json +27 -0
  286. package/protocol/theme-refinery/receipts/products-registry-batch-20260924.json +318 -0
  287. package/protocol/theme-refinery/receipts/theme-harvest-20260924.json +472 -0
  288. package/protocol/theme-refinery/reconciliation-receipt.schema.json +83 -0
  289. package/services/cad/server.py +249 -2
  290. package/src/agent/capability-adapter.js +15 -5
  291. package/src/agent/index.js +2 -1
  292. package/src/agent/model-turn.js +51 -0
  293. package/src/agent/responses-runner.js +304 -38
  294. package/src/capabilities/index.js +1 -0
  295. package/src/capabilities/terminal-exec.js +78 -0
  296. package/src/cli.js +117 -9
  297. package/src/cloudflare/index.js +6 -0
  298. package/src/cloudflare/runtime-status.js +393 -0
  299. package/src/cloudflare/wrangler.js +17 -1
  300. package/src/commands/app.js +106 -0
  301. package/src/commands/autorag.js +77 -0
  302. package/src/commands/brand.js +293 -0
  303. package/src/commands/cad.js +1 -0
  304. package/src/commands/connections.js +126 -29
  305. package/src/commands/context-economics.js +8 -0
  306. package/src/commands/db.js +7 -0
  307. package/src/commands/env.js +5 -4
  308. package/src/commands/eval.js +209 -14
  309. package/src/commands/go.js +365 -0
  310. package/src/commands/goap.js +176 -0
  311. package/src/commands/identity-init.js +27 -3
  312. package/src/commands/identity-protocol.js +195 -0
  313. package/src/commands/knowledge.js +64 -5
  314. package/src/commands/mcp.js +341 -0
  315. package/src/commands/merkle-persist.js +3 -1
  316. package/src/commands/merkle.js +18 -3
  317. package/src/commands/models.js +109 -23
  318. package/src/commands/plugins.js +175 -0
  319. package/src/commands/preferences.js +28 -8
  320. package/src/commands/product.js +53 -10
  321. package/src/commands/providers.js +118 -37
  322. package/src/commands/resume.js +9 -5
  323. package/src/commands/runtime-status.js +154 -0
  324. package/src/commands/shell.js +466 -55
  325. package/src/commands/status.js +82 -7
  326. package/src/commands/tunnel.js +228 -195
  327. package/src/commands/whoami.js +78 -6
  328. package/src/context/budget.js +6 -0
  329. package/src/context/index.js +2 -1
  330. package/src/context/project-card.js +75 -0
  331. package/src/errors/contract.js +34 -211
  332. package/src/errors/diagnostic.js +95 -51
  333. package/src/errors/index.js +6 -13
  334. package/src/eval/index.js +6 -0
  335. package/src/eval/live.js +439 -0
  336. package/src/features/resolve.js +242 -0
  337. package/src/go/build.js +108 -0
  338. package/src/go/cloudflare.js +207 -0
  339. package/src/go/contract.js +139 -0
  340. package/src/go/discover.js +96 -0
  341. package/src/go/index.js +13 -0
  342. package/src/go/receipts.js +77 -0
  343. package/src/go/registry.js +223 -0
  344. package/src/go/verify.js +31 -0
  345. package/src/index.js +100 -1
  346. package/src/knowledge/config.js +13 -5
  347. package/src/knowledge/engine.js +23 -8
  348. package/src/knowledge/index.js +1 -0
  349. package/src/knowledge/lane-registry.js +46 -0
  350. package/src/knowledge/providers/gemini.js +48 -8
  351. package/src/knowledge/service/client.js +13 -1
  352. package/src/knowledge/service/grpc-codec.js +156 -53
  353. package/src/knowledge/service/job-engine.js +133 -11
  354. package/src/knowledge/service/job-worker.js +34 -5
  355. package/src/knowledge/service/server.js +10 -1
  356. package/src/knowledge/store-discovery.js +77 -0
  357. package/src/lib/account-session.js +8 -2
  358. package/src/lib/agent-instructions.js +3 -0
  359. package/src/lib/auth.js +7 -3
  360. package/src/lib/cad/blender.js +42 -3
  361. package/src/lib/cad/d1-project-store.js +43 -0
  362. package/src/lib/cad/discovery.js +616 -0
  363. package/src/lib/cad/docker-executor.js +352 -0
  364. package/src/lib/cad/freecad.js +253 -0
  365. package/src/lib/cad/index.js +40 -0
  366. package/src/lib/cad/openscad.js +198 -0
  367. package/src/lib/cad/project-cli.d.ts +2 -0
  368. package/src/lib/cad/project-cli.js +21 -0
  369. package/src/lib/cad/project-contract.d.ts +3 -0
  370. package/src/lib/cad/project-contract.js +1 -0
  371. package/src/lib/cad/project-recipe.js +30 -0
  372. package/src/lib/cad/project-runtime.d.ts +2 -0
  373. package/src/lib/cad/project-runtime.js +53 -0
  374. package/src/lib/cad/project-store.js +25 -0
  375. package/src/lib/cad/project-workflows.js +31 -0
  376. package/src/lib/cad-docker.js +21 -2
  377. package/src/lib/cli-preferences.js +17 -2
  378. package/src/lib/core-client.js +37 -18
  379. package/src/lib/deploy/local-studio.js +6 -5
  380. package/src/lib/dockerize.js +3 -0
  381. package/src/lib/execution-approvals.js +1 -0
  382. package/src/lib/identity-scaffold.js +4 -1
  383. package/src/lib/knowledge-docker.js +9 -1
  384. package/src/lib/local-sessions.js +124 -34
  385. package/src/lib/local-status.js +35 -14
  386. package/src/lib/project-config.js +9 -0
  387. package/src/lib/provider-credentials.js +73 -11
  388. package/src/lib/scaffold/resolve-cloudflare-account.js +37 -0
  389. package/src/lib/scaffold/wizards/cms.js +2 -8
  390. package/src/lib/scaffold/wizards/worker-api.js +2 -8
  391. package/src/lib/slash-commands.js +9 -2
  392. package/src/local/migrations.js +109 -1
  393. package/src/local/runtime-store.js +31 -5
  394. package/src/local/sqlite.js +36 -1
  395. package/src/mcp/authority.js +348 -0
  396. package/src/mcp/client-adapters.js +431 -0
  397. package/src/mcp/client.js +172 -0
  398. package/src/mcp/index.js +47 -0
  399. package/src/mcp/telemetry.js +103 -0
  400. package/src/models/catalog.js +329 -51
  401. package/src/models/discovery.js +24 -4
  402. package/src/models/index.js +2 -0
  403. package/src/models/inventory-core.js +182 -0
  404. package/src/models/policy.js +20 -0
  405. package/src/plugins/cloudflare.js +103 -0
  406. package/src/plugins/completeful.js +69 -0
  407. package/src/plugins/contracts.js +86 -0
  408. package/src/plugins/index.js +11 -0
  409. package/src/plugins/registry.js +207 -0
  410. package/src/plugins/resource-scope.js +45 -0
  411. package/src/plugins/runtime.js +118 -0
  412. package/src/plugins/vectorize.js +31 -0
  413. package/src/progression/engine.js +171 -0
  414. package/src/progression/index.js +1 -0
  415. package/src/providers/cloudflare-chat.js +1 -1
  416. package/src/providers/gemini-generate-content.js +2 -1
  417. package/src/providers/openai-responses.js +45 -16
  418. package/src/providers/tool-schema.js +85 -0
  419. package/src/repository/index.js +29 -0
  420. package/src/rpc/generated/errors_pb.js +961 -1
  421. package/src/security/local-vault.js +415 -0
  422. package/src/security/process.js +20 -4
  423. package/src/status/actions.js +192 -0
  424. package/src/tools/hydrate.js +5 -1
  425. package/src/tools/index.js +7 -0
  426. package/src/tools/redact.js +64 -0
  427. package/src/tools/registry.js +83 -0
  428. package/src/tools/runtime.js +257 -0
  429. package/src/tools/search.js +21 -8
  430. package/src/ui/ansi.js +117 -3
  431. package/src/ui/cli/activity.js +76 -7
  432. package/src/ui/cli/footer.js +110 -9
  433. package/src/ui/cli/help.js +11 -4
  434. package/src/ui/wireframes.js +166 -0
  435. package/test/account-session.test.mjs +28 -0
  436. package/test/apps-scaffold-contract.test.mjs +16 -1
  437. package/test/capabilities.test.mjs +1 -1
  438. package/test/cli/eval-live.test.mjs +219 -0
  439. package/test/cli/go.test.mjs +71 -0
  440. package/test/cli/local-vault-and-provider-setup.test.mjs +268 -0
  441. package/test/cli/mcp-client.test.mjs +245 -0
  442. package/test/cli/runtime-ui.test.mjs +69 -2
  443. package/test/cli/status-actions.test.mjs +88 -0
  444. package/test/cli/wireframes-go-registry.test.mjs +54 -0
  445. package/test/cloudflare-connector.test.mjs +3 -6
  446. package/test/cloudflare-runtime.test.mjs +8 -1
  447. package/test/context.test.mjs +15 -0
  448. package/test/error-diagnostics.test.mjs +9 -0
  449. package/test/fixtures/cad/courtyard-house.json +208 -0
  450. package/test/go/cloudflare-probe.test.mjs +53 -0
  451. package/test/integration/app-command.test.mjs +55 -0
  452. package/test/integration/cad-discovery.test.mjs +158 -0
  453. package/test/integration/cad-docker-executor.test.mjs +249 -0
  454. package/test/integration/cad-execution.test.mjs +184 -0
  455. package/test/integration/cad-project-app.test.mjs +31 -0
  456. package/test/integration/cad-project-d1.test.mjs +25 -0
  457. package/test/integration/cad-project-native.test.mjs +24 -0
  458. package/test/integration/cad-project-workflow.test.mjs +9 -0
  459. package/test/integration/cad-project.test.mjs +82 -0
  460. package/test/integration/cli-help.test.mjs +4 -0
  461. package/test/integration/cms-site-tenancy-contract.test.mjs +256 -0
  462. package/test/integration/core-client.integration.test.mjs +55 -0
  463. package/test/integration/error-runtime-rpc.test.mjs +71 -0
  464. package/test/integration/features-resolve.test.mjs +128 -0
  465. package/test/integration/install-script.test.mjs +107 -0
  466. package/test/integration/inventory-core.test.mjs +53 -0
  467. package/test/integration/plugins-cloudflare.integration.test.mjs +28 -0
  468. package/test/integration/provider-env-cli.test.mjs +1 -1
  469. package/test/integration/runtime-migrations.test.mjs +6 -1
  470. package/test/integration/runtime-status.integration.test.mjs +211 -0
  471. package/test/integration/scaffold-cloudflare.test.mjs +46 -0
  472. package/test/integration/storage-architecture.test.mjs +154 -0
  473. package/test/integration/store-discovery.test.mjs +44 -0
  474. package/test/integration/terminal-exec.integration.test.mjs +86 -0
  475. package/test/integration/tool-runtime.test.mjs +124 -0
  476. package/test/integration/tool-schema.test.mjs +59 -0
  477. package/test/knowledge-service.test.mjs +4 -0
  478. package/test/local-sessions.test.mjs +11 -2
  479. package/test/local-studio-deploy.test.mjs +1 -1
  480. package/test/model-catalog.test.mjs +28 -1
  481. package/test/models.test.mjs +159 -5
  482. package/test/openai-responses.test.mjs +60 -0
  483. package/test/provider-credentials.test.mjs +15 -5
  484. package/test/responses-runner.test.mjs +321 -6
  485. package/test/shell.test.mjs +149 -4
  486. package/test/smoke.mjs +2 -2
  487. package/test/tools-search.test.mjs +33 -0
  488. package/test/unit/website-assets-bindings.test.mjs +60 -0
  489. package/test/whoami-resume.test.mjs +82 -3
  490. package/examples/gorilla-shell/README.md +0 -15
  491. package/src/lib/gorilla-template.js +0 -54
  492. package/templates/gorilla-shell/App.tsx +0 -639
  493. package/templates/gorilla-shell/README.md +0 -34
  494. package/templates/gorilla-shell/index.html +0 -15
  495. package/templates/gorilla-shell/main.jsx +0 -9
  496. package/templates/gorilla-shell/package.json +0 -19
  497. package/templates/gorilla-shell/vite.config.js +0 -21
@@ -0,0 +1,96 @@
1
+ {
2
+ "schema": "agentsam.feature.provider-catalog.v1",
3
+ "feature": "identity.oauth-login-portal",
4
+ "default_provider": "inneranimalmedia",
5
+ "providers": [
6
+ {
7
+ "id": "inneranimalmedia",
8
+ "aliases": ["iam"],
9
+ "oauth_provider_key": "iam",
10
+ "kind": "oidc",
11
+ "status": "ready",
12
+ "title": "Inner Animal Media platform identity",
13
+ "implementation": "src/providers/iam",
14
+ "capabilities": [
15
+ "identity.oauth.authorize",
16
+ "identity.oauth.callback",
17
+ "identity.profile.resolve"
18
+ ],
19
+ "required_configuration": [
20
+ "IAM_CLIENT_ID",
21
+ "IAM_CLIENT_SECRET"
22
+ ],
23
+ "notes": "Protocol/selection id is inneranimalmedia. OAuth/DB provider key remains iam."
24
+ },
25
+ {
26
+ "id": "google",
27
+ "kind": "oauth",
28
+ "status": "ready",
29
+ "implementation": "src/providers/google",
30
+ "capabilities": [
31
+ "identity.oauth.authorize",
32
+ "identity.oauth.callback",
33
+ "identity.profile.resolve"
34
+ ],
35
+ "required_configuration": [
36
+ "GOOGLE_CLIENT_ID",
37
+ "GOOGLE_CLIENT_SECRET"
38
+ ]
39
+ },
40
+ {
41
+ "id": "github",
42
+ "kind": "oauth",
43
+ "status": "ready",
44
+ "implementation": "src/providers/github",
45
+ "capabilities": [
46
+ "identity.oauth.authorize",
47
+ "identity.oauth.callback",
48
+ "identity.profile.resolve"
49
+ ],
50
+ "required_configuration": [
51
+ "GITHUB_CLIENT_ID",
52
+ "GITHUB_CLIENT_SECRET"
53
+ ]
54
+ },
55
+ {
56
+ "id": "gcp",
57
+ "kind": "oauth",
58
+ "status": "scaffold",
59
+ "implementation": "src/providers/gcp",
60
+ "capabilities": [
61
+ "identity.oauth.authorize",
62
+ "identity.profile.resolve"
63
+ ],
64
+ "notes": "Contract + authorize URL only — exchange not implemented."
65
+ },
66
+ {
67
+ "id": "email",
68
+ "kind": "password",
69
+ "status": "scaffold",
70
+ "implementation": "src/providers/email",
71
+ "capabilities": [
72
+ "identity.profile.resolve"
73
+ ],
74
+ "notes": "Password verification not yet implemented by the portable provider."
75
+ },
76
+ {
77
+ "id": "cloudflare",
78
+ "kind": "oauth",
79
+ "status": "ready",
80
+ "registered": true,
81
+ "implementation": "src/providers/cloudflare",
82
+ "capabilities": [
83
+ "identity.oauth.authorize",
84
+ "identity.oauth.callback",
85
+ "identity.profile.resolve"
86
+ ],
87
+ "required_configuration": [
88
+ "CLOUDFLARE_OAUTH_CLIENT_ID"
89
+ ],
90
+ "optional_configuration": [
91
+ "CLOUDFLARE_OAUTH_CLIENT_SECRET"
92
+ ],
93
+ "notes": "Registered in identityProviders. Client secret optional for PKCE-only clients."
94
+ }
95
+ ]
96
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "schema": "agentsam.feature.resources.v1",
3
+ "feature": "identity.oauth-login-portal",
4
+ "engine": "d1",
5
+ "migration_sources": [
6
+ "src/migrations/0001_identity_core.sql",
7
+ "src/migrations/0002_company.sql"
8
+ ],
9
+ "notes": "Migration files remain the schema authority. This JSON is an index/contract only.",
10
+ "tables": [
11
+ {
12
+ "name": "auth_users",
13
+ "purpose": "canonical user identity",
14
+ "source": "src/migrations/0001_identity_core.sql"
15
+ },
16
+ {
17
+ "name": "auth_sessions",
18
+ "purpose": "authenticated browser/session state",
19
+ "owner_column": "user_id",
20
+ "source": "src/migrations/0001_identity_core.sql"
21
+ },
22
+ {
23
+ "name": "account_identities",
24
+ "purpose": "external identity/provider mapping",
25
+ "owner_column": "account_id",
26
+ "source": "src/migrations/0001_identity_core.sql"
27
+ },
28
+ {
29
+ "name": "oauth_states",
30
+ "purpose": "short-lived OAuth/PKCE transaction state",
31
+ "sensitive": true,
32
+ "source": "src/migrations/0001_identity_core.sql"
33
+ },
34
+ {
35
+ "name": "password_reset_tokens",
36
+ "purpose": "password recovery token state",
37
+ "sensitive": true,
38
+ "owner_column": "user_id",
39
+ "source": "src/migrations/0001_identity_core.sql"
40
+ },
41
+ {
42
+ "name": "company",
43
+ "purpose": "auth portal/company branding",
44
+ "source": "src/migrations/0002_company.sql"
45
+ }
46
+ ]
47
+ }
@@ -0,0 +1,74 @@
1
+ {
2
+ "schema": "agentsam.feature.routes.v1",
3
+ "feature": "identity.oauth-login-portal",
4
+ "router": "src/server/worker-router.js",
5
+ "routes": [
6
+ {
7
+ "path": "/auth/login",
8
+ "kind": "page",
9
+ "access": "public",
10
+ "surface": "auth-portal"
11
+ },
12
+ {
13
+ "path": "/auth/signup",
14
+ "kind": "page",
15
+ "access": "public",
16
+ "surface": "auth-portal"
17
+ },
18
+ {
19
+ "path": "/auth/reset",
20
+ "kind": "page",
21
+ "access": "public",
22
+ "surface": "auth-portal"
23
+ },
24
+ {
25
+ "path": "/api/auth/login",
26
+ "method": "POST",
27
+ "kind": "api",
28
+ "access": "public"
29
+ },
30
+ {
31
+ "path": "/api/auth/signup",
32
+ "method": "POST",
33
+ "kind": "api",
34
+ "access": "public"
35
+ },
36
+ {
37
+ "path": "/api/oauth/google/start",
38
+ "kind": "api",
39
+ "access": "public",
40
+ "provider": "google"
41
+ },
42
+ {
43
+ "path": "/api/oauth/github/start",
44
+ "kind": "api",
45
+ "access": "public",
46
+ "provider": "github"
47
+ },
48
+ {
49
+ "path": "/api/oauth/iam/start",
50
+ "kind": "api",
51
+ "access": "public",
52
+ "provider": "inneranimalmedia",
53
+ "oauth_provider_key": "iam"
54
+ },
55
+ {
56
+ "path": "/api/oauth/cloudflare/start",
57
+ "kind": "api",
58
+ "access": "public",
59
+ "provider": "cloudflare"
60
+ },
61
+ {
62
+ "path": "/api/oauth/cloudflare/callback",
63
+ "kind": "api",
64
+ "access": "public",
65
+ "provider": "cloudflare"
66
+ }
67
+ ],
68
+ "sources": [
69
+ "src/frontend/auth-portal/README.md",
70
+ "src/oauth/README.md",
71
+ "src/oauth/redirect-paths.js",
72
+ "src/server/worker-router.js"
73
+ ]
74
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "schema": "agentsam.feature.ui.v1",
3
+ "feature": "identity.oauth-login-portal",
4
+ "surface": "auth-portal",
5
+ "assets": [
6
+ "src/frontend/auth-portal/pages/login.html",
7
+ "src/frontend/auth-portal/pages/signup.html",
8
+ "src/frontend/auth-portal/pages/reset.html",
9
+ "src/frontend/auth-portal/shared/company-branding.js"
10
+ ],
11
+ "customizable": [
12
+ "logo",
13
+ "colors",
14
+ "support info",
15
+ "company branding"
16
+ ],
17
+ "customizable_fields": [
18
+ "company.name",
19
+ "company.logo_url",
20
+ "company.favicon_url",
21
+ "company.primary_color",
22
+ "company.auth_bg_color",
23
+ "company.support_email",
24
+ "company.website_url",
25
+ "company.tagline"
26
+ ],
27
+ "behavior": {
28
+ "implementation": "packages/identity",
29
+ "host_supplies": "brand/runtime config"
30
+ },
31
+ "ownership": {
32
+ "implementation": "packages/identity",
33
+ "branding": "host"
34
+ }
35
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-sdk-identity",
3
- "version": "2.6.2",
3
+ "version": "2.6.3",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace \u2014 publish via root SDK)",
@@ -28,7 +28,8 @@
28
28
  "./contracts/external-identity": "./src/contracts/external-identity.js",
29
29
  "./contracts/auth-config": "./src/contracts/auth-config.js",
30
30
  "./oauth/callback": "./src/oauth/callback.js",
31
- "./frontend/auth-portal/*": "./src/frontend/auth-portal/*"
31
+ "./frontend/auth-portal/*": "./src/frontend/auth-portal/*",
32
+ "./providers/cloudflare": "./src/providers/cloudflare/index.js"
32
33
  },
33
34
  "scripts": {
34
35
  "test": "node --test tests/*.test.mjs",
@@ -10,6 +10,10 @@ export function newSessionId() {
10
10
  return crypto.randomUUID();
11
11
  }
12
12
 
13
+ export function newAuthEventId() {
14
+ return `aev_${crypto.randomUUID().replace(/-/g, '')}`;
15
+ }
16
+
13
17
  export function nowUnix() {
14
18
  return Math.floor(Date.now() / 1000);
15
19
  }
@@ -1,4 +1,4 @@
1
- import { newAccountIdentityId, newAuthUserId, newSessionId, nowUnix } from './ids.js';
1
+ import { newAccountIdentityId, newAuthUserId, newSessionId, newAuthEventId, nowUnix } from './ids.js';
2
2
  import { AUTH_SESSION_TTL_SECONDS } from '../../core/constants.js';
3
3
  import { DEFAULT_COMPANY_ID, DEFAULT_COMPANY_SLUG, normalizeCompanyRow } from '../../contracts/company.js';
4
4
 
@@ -12,6 +12,14 @@ import { DEFAULT_COMPANY_ID, DEFAULT_COMPANY_SLUG, normalizeCompanyRow } from '.
12
12
  * @param {D1Database} db
13
13
  * @param {{ sessionTtlSeconds?: number }} [options]
14
14
  */
15
+ async function hashValue(value) {
16
+ const v = String(value || '').trim();
17
+ if (!v) return null;
18
+ const bytes = new TextEncoder().encode(v);
19
+ const digest = await crypto.subtle.digest('SHA-256', bytes);
20
+ return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, '0')).join('');
21
+ }
22
+
15
23
  export function createCloudflareD1Adapter(db, options = {}) {
16
24
  if (!db?.prepare) {
17
25
  throw new Error('cloudflare_d1_adapter_requires_db_binding');
@@ -21,6 +29,36 @@ export function createCloudflareD1Adapter(db, options = {}) {
21
29
  return Object.freeze({
22
30
  sessionTtlSeconds,
23
31
 
32
+ /**
33
+ * Append-only login/logout/failed-attempt audit trail (auth_event_log).
34
+ * Never throws -- an observability write must not break a real auth flow.
35
+ * ip/userAgent are hashed (SHA-256) before storage, matching the
36
+ * ip_hash/user_agent_hash column names -- raw values are never persisted.
37
+ */
38
+ async logAuthEvent({ userId, eventType, status = 'ok', provider, metadata, request }) {
39
+ try {
40
+ const ip = request?.headers?.get?.('cf-connecting-ip') || request?.headers?.get?.('x-forwarded-for') || '';
41
+ const ua = request?.headers?.get?.('user-agent') || '';
42
+ const [ipHash, uaHash] = await Promise.all([hashValue(ip), hashValue(ua)]);
43
+ await db.prepare(
44
+ `INSERT INTO auth_event_log
45
+ (id, user_id, event_type, status, provider, metadata_json, ip_hash, user_agent_hash)
46
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
47
+ ).bind(
48
+ newAuthEventId(),
49
+ userId || null,
50
+ eventType,
51
+ status,
52
+ provider || null,
53
+ metadata ? JSON.stringify(metadata) : '{}',
54
+ ipHash,
55
+ uaHash,
56
+ ).run();
57
+ } catch {
58
+ // Never let audit logging break a real login/OAuth flow.
59
+ }
60
+ },
61
+
24
62
  async findUserByEmail(email) {
25
63
  const row = await db.prepare(
26
64
  `SELECT id, email, display_name, password_hash, salt, status, created_at, updated_at
@@ -1,9 +1,10 @@
1
- /** External identity provider contract. */
1
+ /** External identity provider contract — registry order is intentional. */
2
2
 
3
3
  export const IdentityProviders = Object.freeze([
4
4
  'email',
5
5
  'google',
6
6
  'github',
7
7
  'gcp',
8
- 'iam',
8
+ 'inneranimalmedia',
9
+ 'cloudflare',
9
10
  ]);
@@ -412,6 +412,9 @@
412
412
  <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.43 9.8 8.2 11.38.6.11.82-.26.82-.58 0-.29-.01-1.06-.01-2.08-3.34.73-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.09-.74.08-.73.08-.73 1.2.08 1.83 1.23 1.83 1.23 1.07 1.83 2.81 1.3 3.49.99.11-.78.42-1.3.76-1.6-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.12-.3-.54-1.52.12-3.18 0 0 1.01-.32 3.3 1.23a11.5 11.5 0 013-.41c1.02.01 2.05.14 3 .41 2.29-1.55 3.3-1.23 3.3-1.23.66 1.66.24 2.88.12 3.18.77.84 1.24 1.91 1.24 3.22 0 4.61-2.8 5.63-5.48 5.92.43.37.81 1.1.81 2.22 0 1.6-.01 2.89-.01 3.28 0 .32.21.69.83.57C20.57 21.79 24 17.3 24 12c0-6.63-5.37-12-12-12z"/></svg>
413
413
  Sign in with GitHub
414
414
  </a>
415
+ <a id="cloudflareSignIn" href="/api/oauth/cloudflare/start?next=/dashboard/agent" class="btn-primary" style="background: #F6821F; color: white; text-decoration: none; padding: 12px 24px; border-radius: 10px; font-weight: 600; font-size: 14px; border: 1px solid rgba(255,255,255,0.2); box-shadow: 0 4px 12px rgba(0,0,0,0.1); display: flex; align-items: center; justify-content: center; gap: 8px;">
416
+ Sign in with Cloudflare
417
+ </a>
415
418
  </div>
416
419
 
417
420
  <p class="signup-prompt">
@@ -479,6 +482,10 @@
479
482
  if (githubLink) {
480
483
  githubLink.href = '/api/oauth/github/start?next=' + encodeURIComponent(oauthDest);
481
484
  }
485
+ var cloudflareLink = document.getElementById('cloudflareSignIn');
486
+ if (cloudflareLink) {
487
+ cloudflareLink.href = '/api/oauth/cloudflare/start?next=' + encodeURIComponent(oauthDest);
488
+ }
482
489
  if (new URLSearchParams(window.location.search).get('cf_connect') === '1') {
483
490
  var cfN = document.getElementById('cfConnectNotice');
484
491
  if (cfN) cfN.style.display = 'block';
@@ -20,6 +20,7 @@ import {
20
20
  IamProvider,
21
21
  GcpProvider,
22
22
  EmailProvider,
23
+ CloudflareProvider,
23
24
  } from './providers/index.js';
24
25
 
25
26
  export {
@@ -38,6 +39,7 @@ export {
38
39
  IamProvider,
39
40
  GcpProvider,
40
41
  EmailProvider,
42
+ CloudflareProvider,
41
43
  };
42
44
 
43
45
  export * from './core/index.js';
@@ -82,6 +82,19 @@ export function resolveOAuthCredentialLane(env, provider) {
82
82
  }
83
83
  }
84
84
 
85
+ if (provider === 'cloudflare') {
86
+ // Reuses the same Worker secrets as the Local Studio Cloudflare resource
87
+ // connector (packages/connectors/cloudflare). clientSecret may be empty
88
+ // if that client is configured as PKCE-only (Token Authentication
89
+ // Method = None) — exchangeCloudflareCode() omits it in that case.
90
+ const clientId = String(env?.CLOUDFLARE_OAUTH_CLIENT_ID || '').trim();
91
+ const clientSecret = String(env?.CLOUDFLARE_OAUTH_CLIENT_SECRET || '').trim();
92
+ if (clientId) {
93
+ return { lane: 'byok_cloudflare', clientId, clientSecret, provider };
94
+ }
95
+ return null;
96
+ }
97
+
85
98
  // Default: Google/GitHub buttons route through IAM platform when minted.
86
99
  const iam = resolveIamPlatformCredentials(env);
87
100
  if (iam) {
@@ -19,7 +19,7 @@ import { normalizeIamIdentity } from '../providers/iam/mapper.js';
19
19
  * @param {Record<string, unknown>} env
20
20
  * @param {import('../adapters/cloudflare-d1/index.js').CloudflareD1Adapter} adapter
21
21
  */
22
- export async function iamPlatformOAuthStart(request, env, adapter) {
22
+ export async function iamPlatformOAuthStart(request, env, adapter, identity) {
23
23
  const creds = resolveIamPlatformCredentials(env);
24
24
  if (!creds) {
25
25
  return Response.json({ ok: false, error: 'iam_oauth_not_configured' }, 503);
@@ -29,9 +29,9 @@ export async function iamPlatformOAuthStart(request, env, adapter) {
29
29
  const state = randomOAuthState();
30
30
  const codeVerifier = pkceVerifier();
31
31
  const codeChallenge = await pkceChallenge(codeVerifier);
32
- const redirectTo = url.searchParams.get('next')
33
- || url.searchParams.get('return_to')
34
- || '/dashboard/cms';
32
+ const redirectTo = identity?.resolvePostLoginPath(
33
+ url.searchParams.get('next') || url.searchParams.get('return_to'),
34
+ ) || '/';
35
35
 
36
36
  await adapter.saveOAuthState({
37
37
  state,
@@ -107,7 +107,7 @@ export async function iamPlatformOAuthCallback(request, env, adapter, identity)
107
107
  displayName: normalized.name || normalized.email.split('@')[0] || 'User',
108
108
  });
109
109
 
110
- const redirectTo = saved.redirect_to || '/dashboard/cms';
110
+ const redirectTo = identity.resolvePostLoginPath(saved.redirect_to);
111
111
  const res = identity.buildLoginSuccessResponse(request, result.sessionId, redirectTo);
112
112
  const globeUrl = `${url.origin}${AUTH_LOGIN_PATH}?globe_exit=1&next=${encodeURIComponent(redirectTo)}`;
113
113
  return new Response(null, {
@@ -0,0 +1,19 @@
1
+ import { createIdentityProvider } from '../../provider-contract.js';
2
+ import { exchangeCloudflareCode, getCloudflareAuthUrl } from './oauth.js';
3
+ import { fetchCloudflareProfile } from './profile.js';
4
+ import { normalizeCloudflareIdentity } from './mapper.js';
5
+
6
+ export const CloudflareProvider = createIdentityProvider({
7
+ id: 'cloudflare',
8
+ authorizeUrl: getCloudflareAuthUrl,
9
+ exchangeCode: exchangeCloudflareCode,
10
+ getProfile: fetchCloudflareProfile,
11
+ normalizeIdentity: normalizeCloudflareIdentity,
12
+ });
13
+
14
+ export {
15
+ getCloudflareAuthUrl,
16
+ exchangeCloudflareCode,
17
+ fetchCloudflareProfile,
18
+ normalizeCloudflareIdentity,
19
+ };
@@ -0,0 +1,21 @@
1
+ import { normalizeExternalIdentity } from '../../contracts/external-identity.js';
2
+
3
+ /**
4
+ * @param {Record<string, unknown>|null|undefined} profile
5
+ */
6
+ export function normalizeCloudflareIdentity(profile) {
7
+ const raw = profile && typeof profile === 'object' ? profile : {};
8
+ const subject = String(raw.sub || raw.id || raw.user_id || raw.account_id || '').trim();
9
+ if (!subject) {
10
+ throw new Error('cloudflare_identity_requires_subject');
11
+ }
12
+ return normalizeExternalIdentity({
13
+ provider: 'cloudflare',
14
+ subject,
15
+ email: typeof raw.email === 'string' ? raw.email : null,
16
+ emailVerified: Boolean(raw.email),
17
+ name: typeof raw.name === 'string' ? raw.name : (typeof raw.display_name === 'string' ? raw.display_name : null),
18
+ avatar: null,
19
+ raw,
20
+ });
21
+ }
@@ -0,0 +1,48 @@
1
+ const CLOUDFLARE_AUTH_URL = 'https://dash.cloudflare.com/oauth2/auth';
2
+ const CLOUDFLARE_TOKEN_URL = 'https://dash.cloudflare.com/oauth2/token';
3
+
4
+ // Identity-only login should not request the full resource-access scope set
5
+ // used elsewhere for the Local Studio Cloudflare *connection* (deploy/d1/r2/etc).
6
+ // account-settings.read is enough to resolve the account for userinfo.
7
+ const CLOUDFLARE_LOGIN_SCOPE = 'account-settings.read offline_access';
8
+
9
+ /** @param {import('../../provider-contract.js').OAuthAuthorizeInput} input */
10
+ export function getCloudflareAuthUrl({ clientId, redirectUri, state, codeChallenge, scope } = {}) {
11
+ const url = new URL(CLOUDFLARE_AUTH_URL);
12
+ url.searchParams.set('client_id', clientId || '');
13
+ url.searchParams.set('redirect_uri', redirectUri || '');
14
+ url.searchParams.set('response_type', 'code');
15
+ url.searchParams.set('scope', scope || CLOUDFLARE_LOGIN_SCOPE);
16
+ url.searchParams.set('state', state || '');
17
+ if (codeChallenge) {
18
+ url.searchParams.set('code_challenge', codeChallenge);
19
+ url.searchParams.set('code_challenge_method', 'S256');
20
+ }
21
+ return url.toString();
22
+ }
23
+
24
+ /** @param {import('../../provider-contract.js').OAuthExchangeInput} input */
25
+ export async function exchangeCloudflareCode({ code, codeVerifier, clientId, clientSecret, redirectUri }) {
26
+ try {
27
+ const body = new URLSearchParams();
28
+ body.set('grant_type', 'authorization_code');
29
+ body.set('code', code || '');
30
+ body.set('code_verifier', codeVerifier || '');
31
+ body.set('client_id', clientId || '');
32
+ // client_secret is only sent when configured — the client may be a
33
+ // PKCE-only public client (Token Authentication Method = None), same
34
+ // pattern as the Local Studio resource connector.
35
+ if (clientSecret) body.set('client_secret', clientSecret);
36
+ body.set('redirect_uri', redirectUri || '');
37
+
38
+ const res = await fetch(CLOUDFLARE_TOKEN_URL, {
39
+ method: 'POST',
40
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
41
+ body,
42
+ });
43
+ if (!res.ok) return null;
44
+ return await res.json();
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
@@ -0,0 +1,28 @@
1
+ const CLOUDFLARE_USERINFO_URL = 'https://dash.cloudflare.com/oauth2/userinfo';
2
+
3
+ /**
4
+ * Fetch the authenticated Cloudflare user's identity.
5
+ * Response shape not fully verified against a live token yet — this reads
6
+ * defensively (sub/id/user_id, email, name) rather than assuming Cloudflare's
7
+ * exact OIDC field names. Confirm the real shape on first live login and
8
+ * tighten this if fields differ.
9
+ * @param {string} accessToken
10
+ */
11
+ export async function fetchCloudflareProfile(accessToken) {
12
+ try {
13
+ const res = await fetch(CLOUDFLARE_USERINFO_URL, {
14
+ headers: { Authorization: `Bearer ${accessToken}` },
15
+ });
16
+ if (!res.ok) return null;
17
+ const data = await res.json();
18
+ if (!data) return null;
19
+ return {
20
+ sub: data.sub || data.id || data.user_id || data.account_id || null,
21
+ email: data.email || null,
22
+ name: data.name || data.display_name || null,
23
+ raw: data,
24
+ };
25
+ } catch {
26
+ return null;
27
+ }
28
+ }
@@ -4,19 +4,28 @@ import { GithubProvider } from './github/index.js';
4
4
  import { GcpProvider } from './gcp/index.js';
5
5
  import { EmailProvider } from './email/index.js';
6
6
  import { IamProvider } from './iam/index.js';
7
+ import { CloudflareProvider } from './cloudflare/index.js';
7
8
 
8
- /** @type {Record<string, import('../provider-contract.js').IdentityProvider>} */
9
+ /**
10
+ * Active identity provider registry.
11
+ * `inneranimalmedia` is the canonical platform template id; `iam` remains a
12
+ * legacy lookup alias (OAuth/DB provider key on platform identities).
13
+ * @type {Record<string, import('../provider-contract.js').IdentityProvider>}
14
+ */
9
15
  export const identityProviders = Object.freeze({
10
16
  google: GoogleProvider,
11
17
  github: GithubProvider,
12
18
  gcp: GcpProvider,
13
19
  email: EmailProvider,
20
+ inneranimalmedia: IamProvider,
14
21
  iam: IamProvider,
22
+ cloudflare: CloudflareProvider,
15
23
  });
16
24
 
17
25
  /** @param {string} id */
18
26
  export function getIdentityProvider(id) {
19
27
  const key = String(id || '').trim().toLowerCase();
28
+ if (key === 'iam') return identityProviders.inneranimalmedia || identityProviders.iam || null;
20
29
  return identityProviders[key] || null;
21
30
  }
22
31
 
@@ -24,4 +33,11 @@ export function listIdentityProviders() {
24
33
  return IdentityProviders.map((id) => identityProviders[id]).filter(Boolean);
25
34
  }
26
35
 
27
- export { GoogleProvider, GithubProvider, GcpProvider, EmailProvider, IamProvider };
36
+ export {
37
+ GoogleProvider,
38
+ GithubProvider,
39
+ GcpProvider,
40
+ EmailProvider,
41
+ IamProvider,
42
+ CloudflareProvider,
43
+ };
@@ -1,4 +1,4 @@
1
- import { AUTH_COOKIE_NAME, AUTH_SESSION_TTL_SECONDS, DASHBOARD_AFTER_LOGIN_PATH } from '../core/constants.js';
1
+ import { AUTH_COOKIE_NAME, AUTH_SESSION_TTL_SECONDS } from '../core/constants.js';
2
2
  import { hashPassword, verifyPassword } from '../core/password-crypto.js';
3
3
  import { jsonResponse } from '../core/http-json.js';
4
4
  import { sanitizeBrowserNextPath } from '../core/browser-paths.js';
@@ -16,7 +16,16 @@ export function createIdentityService(config) {
16
16
  const adapter = config.adapter;
17
17
  if (!adapter) throw new Error('identity_service_requires_adapter');
18
18
  const cookieName = config.cookieName || AUTH_COOKIE_NAME;
19
- const defaultRedirect = config.defaultRedirect || DASHBOARD_AFTER_LOGIN_PATH;
19
+ // Direct sign-in has no navigation intent to restore. Land at the site root;
20
+ // protected routes always provide their own validated `next` path.
21
+ const defaultRedirect = sanitizeBrowserNextPath(config.defaultRedirect) || '/';
22
+
23
+ // OAuth state is durable and may outlive a deployment. Normalize both the
24
+ // incoming request value and a value read back from prior state so an old or
25
+ // malformed value can never become an open redirect.
26
+ function resolvePostLoginPath(nextPath) {
27
+ return sanitizeBrowserNextPath(nextPath) || defaultRedirect;
28
+ }
20
29
 
21
30
  function sessionCookieHeader(sessionId, requestUrl, maxAge = AUTH_SESSION_TTL_SECONDS) {
22
31
  const secure = new URL(requestUrl).protocol === 'https:';
@@ -127,7 +136,7 @@ export function createIdentityService(config) {
127
136
  },
128
137
 
129
138
  buildLoginSuccessResponse(request, sessionId, nextPath) {
130
- const redirect = sanitizeBrowserNextPath(nextPath) || defaultRedirect;
139
+ const redirect = resolvePostLoginPath(nextPath);
131
140
  return jsonResponse(
132
141
  { ok: true, redirect },
133
142
  200,
@@ -150,6 +159,7 @@ export function createIdentityService(config) {
150
159
 
151
160
  parseSessionId,
152
161
  sessionCookieHeader,
162
+ resolvePostLoginPath,
153
163
  });
154
164
  }
155
165