@inneranimalmedia/agentsam-sdk 2.6.4 → 2.6.5

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 (418) hide show
  1. package/AGENTSAM.md +11 -0
  2. package/README.md +15 -9
  3. package/apps/client-cms-editor/AGENTS.md +12 -0
  4. package/apps/client-cms-editor/IMPORT_PROVENANCE.json +8 -0
  5. package/apps/client-cms-editor/README.md +72 -0
  6. package/apps/client-cms-editor/agentsam.app.json +57 -0
  7. package/apps/client-cms-editor/backend/README.md +5 -0
  8. package/apps/client-cms-editor/backend/package.json +22 -0
  9. package/apps/client-cms-editor/backend/src/api/client.ts +200 -0
  10. package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +145 -0
  11. package/apps/client-cms-editor/backend/src/index.ts +6 -0
  12. package/apps/client-cms-editor/backend/src/model.ts +115 -0
  13. package/apps/client-cms-editor/backend/src/preview/bridge.ts +79 -0
  14. package/apps/client-cms-editor/backend/src/preview/urls.ts +55 -0
  15. package/apps/client-cms-editor/backend/src/routing/cms-route.js +293 -0
  16. package/apps/client-cms-editor/backend/src/routing/index.js +10 -0
  17. package/apps/client-cms-editor/backend/src/storefront.ts +52 -0
  18. package/apps/client-cms-editor/backend/tsconfig.json +15 -0
  19. package/apps/client-cms-editor/backend/worker/index.js +34 -0
  20. package/apps/client-cms-editor/backend/wrangler.jsonc +11 -0
  21. package/apps/client-cms-editor/bin/agentsam-cms.mjs +229 -0
  22. package/apps/client-cms-editor/frontend/index.html +12 -0
  23. package/apps/client-cms-editor/frontend/package.json +33 -0
  24. package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +188 -0
  25. package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +191 -0
  26. package/apps/client-cms-editor/frontend/src/CmsEditor.tsx +1345 -0
  27. package/apps/client-cms-editor/frontend/src/env.d.ts +14 -0
  28. package/apps/client-cms-editor/frontend/src/index.ts +8 -0
  29. package/apps/client-cms-editor/frontend/src/lib/content-safety.ts +63 -0
  30. package/apps/client-cms-editor/frontend/src/main.tsx +17 -0
  31. package/apps/client-cms-editor/frontend/src/mount.tsx +51 -0
  32. package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +214 -0
  33. package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +1739 -0
  34. package/apps/client-cms-editor/frontend/src/styles/studio.css +106 -0
  35. package/apps/client-cms-editor/frontend/src/surfaces/CmsDashboard.tsx +313 -0
  36. package/apps/client-cms-editor/frontend/src/surfaces/CmsGuidedChatHero.tsx +121 -0
  37. package/apps/client-cms-editor/frontend/src/surfaces/CmsHubPage.tsx +132 -0
  38. package/apps/client-cms-editor/frontend/src/surfaces/CmsSiteSwitcher.tsx +176 -0
  39. package/apps/client-cms-editor/frontend/src/surfaces/index.ts +5 -0
  40. package/apps/client-cms-editor/frontend/src/surfaces/types.ts +48 -0
  41. package/apps/client-cms-editor/frontend/tsconfig.json +25 -0
  42. package/apps/client-cms-editor/frontend/vite.config.ts +13 -0
  43. package/apps/client-cms-editor/package-lock.json +3832 -0
  44. package/apps/client-cms-editor/package.json +23 -0
  45. package/apps/client-cms-editor/reference/DONOR_README.md +52 -0
  46. package/apps/client-cms-editor/reference/DONOR_package-lock.json +1253 -0
  47. package/apps/client-cms-editor/reference/DONOR_tsconfig.json +15 -0
  48. package/apps/client-cms-editor/shared/cms/package.json +21 -0
  49. package/apps/client-cms-editor/shared/cms/src/agent-context.ts +35 -0
  50. package/apps/client-cms-editor/shared/cms/src/cloudflare-bindings.ts +51 -0
  51. package/apps/client-cms-editor/shared/cms/src/editor-types.ts +58 -0
  52. package/apps/client-cms-editor/shared/cms/src/index.ts +5 -0
  53. package/apps/client-cms-editor/shared/cms/src/publication.ts +24 -0
  54. package/apps/client-cms-editor/shared/cms/src/routes.ts +11 -0
  55. package/apps/client-cms-editor/shared/cms/tsconfig.json +12 -0
  56. package/bin/agentsam-rapid-rust +36 -0
  57. package/docs/AUTH_IDENTITY_CONTRACT.md +2 -0
  58. package/docs/MACHINE_INTELLIGENCE.md +120 -0
  59. package/docs/WINDOWS_RUNTIME_INSTALL.md +30 -0
  60. package/docs/architecture/AGENTSAM_APPLICATION_CONTRACT.md +188 -0
  61. package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +151 -0
  62. package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +12 -4
  63. package/docs/architecture/R2_SLUG_NAMESPACE.md +20 -0
  64. package/docs/architecture/WORK_PRODUCT_EXTRACTION.md +97 -0
  65. package/docs/brand/AGENT_SAM_ICON_GRAMMAR.md +70 -0
  66. package/docs/content-studio/HOST_MOUNT_CHECKLIST.md +71 -0
  67. package/docs/content-studio/REVISION_GATE_2026-09-27.md +501 -0
  68. package/docs/contracts/capability-install-planner.md +67 -0
  69. package/docs/contracts/environment-vocabulary.md +195 -0
  70. package/docs/contracts/google-cloud-oauth-setup.md +199 -0
  71. package/docs/local-studio/WORKMODE_DONOR_NOTES.md +1 -1
  72. package/docs/plans/LOCAL-STUDIO-GRADUATION-2026-09-26.md +290 -0
  73. package/docs/plans/LOCAL-STUDIO-REAL-APP-CONTRACT-ADDENDUM-2026-09-27.md +394 -0
  74. package/docs/plans/MACHINE-FIRST-APPS-TUI-2026-09-24.md +227 -0
  75. package/docs/plans/TOMORROW-EXTENSIVE-TODO-2026-09-26.md +221 -0
  76. package/docs/plans/TOMORROW-MACHINE-FIRST-BRIEFING.md +145 -0
  77. package/docs/plans/UNIVERSAL-INGEST-MACHINE-FIRST-2026-09-24.md +215 -0
  78. package/docs/plugins.md +2 -2
  79. package/docs/product/AGENTSAM_PRODUCT_EXPERIENCE_STANDARD.md +280 -0
  80. package/docs/product/LOCAL_STUDIO_DESKTOP_EXPERIENCE.md +139 -0
  81. package/docs/product/README.md +8 -0
  82. package/docs/rapid-rust-wasm.md +35 -0
  83. package/migrations/d1/0016_cloudflare_oauth_user_oauth_tokens_ssot.sql +14 -0
  84. package/package.json +73 -14
  85. package/packages/agentsam-brand/README.md +106 -11
  86. package/packages/agentsam-brand/bin/agentsam-brand.mjs +9 -0
  87. package/packages/agentsam-brand/package.json +39 -7
  88. package/packages/agentsam-brand/src/adapters/cloudflare-images.js +453 -0
  89. package/packages/agentsam-brand/src/adapters/cloudflare-r2.js +74 -0
  90. package/packages/agentsam-brand/src/adapters/d1-registry.js +26 -0
  91. package/packages/agentsam-brand/src/adapters/filesystem.js +59 -0
  92. package/packages/agentsam-brand/src/adapters/memory.js +31 -0
  93. package/packages/agentsam-brand/src/cli/controller.js +503 -0
  94. package/packages/agentsam-brand/src/cli/wizard.js +526 -0
  95. package/packages/agentsam-brand/src/core/capabilities.js +201 -0
  96. package/packages/agentsam-brand/src/core/derivatives.js +211 -0
  97. package/packages/agentsam-brand/src/core/errors.js +12 -0
  98. package/packages/agentsam-brand/src/core/ingest.js +195 -0
  99. package/packages/agentsam-brand/src/core/inspect.js +109 -0
  100. package/packages/agentsam-brand/src/core/keys.js +83 -0
  101. package/packages/agentsam-brand/src/core/naming.js +142 -0
  102. package/packages/agentsam-brand/src/core/optimize.js +316 -0
  103. package/packages/agentsam-brand/src/core/pack.js +305 -0
  104. package/packages/agentsam-brand/src/core/plan.js +276 -0
  105. package/packages/agentsam-brand/src/core/preview.js +159 -0
  106. package/packages/agentsam-brand/src/core/processors/cloudflare.js +68 -0
  107. package/packages/agentsam-brand/src/core/processors/contract.js +203 -0
  108. package/packages/agentsam-brand/src/core/processors/index.js +148 -0
  109. package/packages/agentsam-brand/src/core/processors/native.js +82 -0
  110. package/packages/agentsam-brand/src/core/processors/sharp.js +113 -0
  111. package/packages/agentsam-brand/src/core/processors/squoosh-binary.js +195 -0
  112. package/packages/agentsam-brand/src/core/promote.js +288 -0
  113. package/packages/agentsam-brand/src/core/receipts.js +155 -0
  114. package/packages/agentsam-brand/src/core/v2/compile.js +280 -0
  115. package/packages/agentsam-brand/src/core/v2/derivatives-semantic.js +207 -0
  116. package/packages/agentsam-brand/src/core/v2/ingest-graph.js +387 -0
  117. package/packages/agentsam-brand/src/core/v2/roles.js +180 -0
  118. package/packages/agentsam-brand/src/core/v2/schema.js +209 -0
  119. package/packages/agentsam-brand/src/core/v2/templates.js +114 -0
  120. package/packages/agentsam-brand/src/index.js +193 -36
  121. package/packages/agentsam-brand/src/presets/app-icon.json +16 -0
  122. package/packages/agentsam-brand/src/presets/favicon.json +17 -0
  123. package/packages/agentsam-brand/src/presets/hero.json +12 -0
  124. package/packages/agentsam-brand/src/presets/index.js +40 -0
  125. package/packages/agentsam-brand/src/presets/logo.json +12 -0
  126. package/packages/agentsam-brand/src/presets/model.json +8 -0
  127. package/packages/agentsam-brand/src/presets/og-image.json +10 -0
  128. package/packages/agentsam-brand/src/presets/product-shot.json +11 -0
  129. package/packages/agentsam-brand/src/presets/social-image.json +10 -0
  130. package/packages/agentsam-brand/src/presets/web-image.json +10 -0
  131. package/packages/agentsam-contracts/src/artifacts.ts +41 -0
  132. package/packages/agentsam-knowledge/src/autorag/index.js +1 -1
  133. package/packages/agentsam-knowledge/src/providers/index.js +6 -4
  134. package/packages/agentsam-knowledge/src/providers/ollama-endpoint.js +31 -0
  135. package/packages/agentsam-knowledge/test/autorag.test.mjs +22 -1
  136. package/packages/agentsam-nav/package.json +2 -2
  137. package/packages/agentsam-rapid-rust/Cargo.lock +344 -0
  138. package/packages/agentsam-rapid-rust/Cargo.toml +18 -0
  139. package/packages/agentsam-rapid-rust/README.md +5 -0
  140. package/packages/agentsam-rapid-rust/src/main.rs +718 -0
  141. package/packages/agentsam-rapid-rust/templates/api/Cargo.toml.tmpl +18 -0
  142. package/packages/agentsam-rapid-rust/templates/api/src/lib.rs.tmpl +17 -0
  143. package/packages/agentsam-rapid-rust/templates/common/README.md.tmpl +22 -0
  144. package/packages/agentsam-rapid-rust/templates/common/package.json.tmpl +12 -0
  145. package/packages/agentsam-rapid-rust/templates/common/wrangler.toml.tmpl +6 -0
  146. package/packages/agentsam-rapid-rust/templates/crypto-auth/Cargo.toml.tmpl +21 -0
  147. package/packages/agentsam-rapid-rust/templates/crypto-auth/src/lib.rs.tmpl +32 -0
  148. package/packages/agentsam-rapid-rust/templates/data-processor/Cargo.toml.tmpl +18 -0
  149. package/packages/agentsam-rapid-rust/templates/data-processor/src/lib.rs.tmpl +41 -0
  150. package/packages/agentsam-rapid-rust/templates/shared-core/Cargo.toml.tmpl +9 -0
  151. package/packages/agentsam-rapid-rust/templates/shared-core/core/Cargo.toml.tmpl +7 -0
  152. package/packages/agentsam-rapid-rust/templates/shared-core/core/src/lib.rs.tmpl +23 -0
  153. package/packages/agentsam-rapid-rust/templates/shared-core/worker/Cargo.toml.tmpl +12 -0
  154. package/packages/agentsam-rapid-rust/templates/shared-core/worker/src/lib.rs.tmpl +16 -0
  155. package/packages/agentsam-rapid-rust/templates/shared-core/wrangler.toml.tmpl +6 -0
  156. package/packages/agentsam-repository/src/index.js +1 -0
  157. package/packages/agentsam-repository/src/merkle/semantic.js +3 -10
  158. package/packages/agentsam-repository/src/source-types.js +85 -0
  159. package/packages/agentsam-vault/README.md +96 -0
  160. package/packages/agentsam-vault/package.json +32 -0
  161. package/packages/agentsam-vault/src/contracts/credential.d.ts +78 -0
  162. package/packages/agentsam-vault/src/contracts/credential.js +132 -0
  163. package/packages/agentsam-vault/src/crypto/aes-gcm.d.ts +30 -0
  164. package/packages/agentsam-vault/src/crypto/aes-gcm.js +107 -0
  165. package/packages/agentsam-vault/src/crypto/oauth-envelope.js +150 -0
  166. package/packages/agentsam-vault/src/index.d.ts +9 -0
  167. package/packages/agentsam-vault/src/index.js +27 -0
  168. package/packages/agentsam-vault/src/providers/registry.js +90 -0
  169. package/packages/agentsam-vault/src/runtime/resolver.js +77 -0
  170. package/packages/agentsam-workbench/README.md +24 -0
  171. package/packages/agentsam-workbench/package.json +38 -0
  172. package/packages/agentsam-workbench/src/agent/AgentPanel.tsx +41 -0
  173. package/packages/agentsam-workbench/src/agent/ArtifactCard.tsx +9 -0
  174. package/packages/agentsam-workbench/src/agent/Composer.tsx +102 -0
  175. package/packages/agentsam-workbench/src/agent/ConnectedAgentPanel.tsx +194 -0
  176. package/packages/agentsam-workbench/src/agent/ContextualComposer.tsx +788 -0
  177. package/packages/agentsam-workbench/src/agent/GoalStatusStrip.tsx +38 -0
  178. package/packages/agentsam-workbench/src/agent/MiniAgentSam.tsx +86 -0
  179. package/packages/agentsam-workbench/src/agent/ModelSelect.tsx +19 -0
  180. package/packages/agentsam-workbench/src/agent/Thread.tsx +56 -0
  181. package/packages/agentsam-workbench/src/agent/ToolReceipt.tsx +11 -0
  182. package/packages/agentsam-workbench/src/agent/contextual-composer.css +611 -0
  183. package/packages/agentsam-workbench/src/agent/index.ts +10 -0
  184. package/packages/agentsam-workbench/src/agent/mini-agentsam.css +12 -0
  185. package/packages/agentsam-workbench/src/browser/BrowserFrame.tsx +37 -0
  186. package/packages/agentsam-workbench/src/browser/index.ts +1 -0
  187. package/packages/agentsam-workbench/src/index.ts +6 -0
  188. package/packages/agentsam-workbench/src/project-control.css +160 -0
  189. package/packages/agentsam-workbench/src/projects/ProjectsSurface.tsx +131 -0
  190. package/packages/agentsam-workbench/src/projects/index.ts +1 -0
  191. package/packages/agentsam-workbench/src/shell/Breadcrumb.tsx +35 -0
  192. package/packages/agentsam-workbench/src/shell/ResizableStage.tsx +99 -0
  193. package/packages/agentsam-workbench/src/shell/SidePanel.tsx +5 -0
  194. package/packages/agentsam-workbench/src/shell/index.ts +4 -0
  195. package/packages/agentsam-workbench/src/shell/surfaceRegistry.ts +29 -0
  196. package/packages/agentsam-workbench/src/terminal/TerminalSurface.tsx +5 -0
  197. package/packages/agentsam-workbench/src/terminal/index.ts +1 -0
  198. package/packages/agentsam-workbench/src/timeline/GanttBoard.tsx +258 -0
  199. package/packages/agentsam-workbench/src/timeline/index.ts +1 -0
  200. package/packages/agentsam-workbench/tsconfig.json +13 -0
  201. package/packages/connectors/cloudflare/OAUTH_STORAGE_AUDIT.md +53 -0
  202. package/packages/connectors/cloudflare/package.json +3 -1
  203. package/packages/connectors/cloudflare/src/api-client.js +279 -0
  204. package/packages/connectors/cloudflare/src/capabilities.js +585 -0
  205. package/packages/connectors/cloudflare/src/credential.js +318 -0
  206. package/packages/connectors/cloudflare/src/families/brand-protection.js +123 -0
  207. package/packages/connectors/cloudflare/src/families/keyless.js +114 -0
  208. package/packages/connectors/cloudflare/src/families/pages.js +151 -0
  209. package/packages/connectors/cloudflare/src/families/scanner.js +123 -0
  210. package/packages/connectors/cloudflare/src/families/snippets.js +207 -0
  211. package/packages/connectors/cloudflare/src/families/tag-gateway.js +46 -0
  212. package/packages/connectors/cloudflare/src/families/tags.js +124 -0
  213. package/packages/connectors/cloudflare/src/families/token-validation.js +95 -0
  214. package/packages/connectors/cloudflare/src/families/workflows.js +156 -0
  215. package/packages/connectors/cloudflare/src/index.js +102 -265
  216. package/packages/connectors/cloudflare/src/oauth-persist.js +336 -0
  217. package/packages/connectors/cloudflare/src/owner.js +42 -12
  218. package/packages/connectors/cloudflare/src/permission-options.js +1064 -0
  219. package/packages/connectors/cloudflare/src/routes.js +309 -144
  220. package/packages/connectors/cloudflare/src/scope-catalog.js +345 -0
  221. package/packages/connectors/cloudflare/src/vault.js +2 -2
  222. package/packages/connectors/cloudflare/tests/capabilities.test.mjs +276 -0
  223. package/packages/connectors/cloudflare/tests/connector.test.mjs +26 -30
  224. package/packages/connectors/cloudflare/tests/oauth-persist.test.mjs +125 -0
  225. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +22 -2
  226. package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +10 -4
  227. package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +20 -0
  228. package/packages/identity/README.md +1 -1
  229. package/packages/identity/backend/README.md +1 -1
  230. package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +3 -2
  231. package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +48 -0
  232. package/packages/identity/package.json +4 -3
  233. package/packages/identity/scripts/local-identity-bridge.mjs +184 -0
  234. package/packages/identity/scripts/preview-auth-portal.mjs +7 -7
  235. package/packages/identity/src/adapters/cloudflare-d1/index.js +31 -2
  236. package/packages/identity/src/adapters/sqlite/index.js +4 -1
  237. package/packages/identity/src/contracts/auth-config.js +28 -8
  238. package/packages/identity/src/contracts/external-identity.js +1 -1
  239. package/packages/identity/src/contracts/provider.js +1 -0
  240. package/packages/identity/src/frontend/auth-portal/README.md +2 -1
  241. package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -5
  242. package/packages/identity/src/frontend/auth-portal/pages/reset.html +6 -5
  243. package/packages/identity/src/frontend/auth-portal/pages/signup.html +6 -5
  244. package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
  245. package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +207 -0
  246. package/packages/identity/src/index.js +16 -0
  247. package/packages/identity/src/migrations/0001_identity_core.sql +19 -2
  248. package/packages/identity/src/migrations/0003_accounts_ssot.sql +20 -0
  249. package/packages/identity/src/migrations/README.md +5 -2
  250. package/packages/identity/src/oauth/README.md +10 -5
  251. package/packages/identity/src/oauth/consent-view.js +388 -0
  252. package/packages/identity/src/oauth/credentials.js +31 -11
  253. package/packages/identity/src/oauth/google-desktop-exchange.js +173 -0
  254. package/packages/identity/src/providers/cloudflare/oauth.js +3 -4
  255. package/packages/identity/src/providers/cloudflare/profile.js +49 -14
  256. package/packages/identity/src/providers/iam/index.js +27 -5
  257. package/packages/identity/src/server/identity-service.js +31 -2
  258. package/packages/identity/src/server/worker-router.js +111 -81
  259. package/packages/identity/tests/auth-config.test.mjs +3 -2
  260. package/packages/identity/tests/identity-init-scaffold.test.mjs +3 -0
  261. package/packages/identity/tests/identity-service.test.mjs +16 -0
  262. package/packages/identity/tests/native-session-worker.test.mjs +64 -0
  263. package/packages/identity/tests/oauth-consent-view.test.mjs +106 -0
  264. package/packages/identity/tests/oauth-credentials.test.mjs +17 -4
  265. package/packages/identity/tests/oauth-presets-accounts-ssot.test.mjs +58 -0
  266. package/packages/identity/tests/preview-auth-portal.test.mjs +3 -3
  267. package/packages/runtime-protocol/src/index.js +154 -0
  268. package/packages/theme-scenes/README.md +164 -0
  269. package/packages/theme-scenes/package.json +53 -0
  270. package/packages/theme-scenes/src/blocks/index.js +30 -0
  271. package/packages/theme-scenes/src/contracts/index.js +286 -0
  272. package/packages/theme-scenes/src/demos/index.js +65 -0
  273. package/packages/theme-scenes/src/index.js +75 -0
  274. package/packages/theme-scenes/src/presets/index.js +263 -0
  275. package/packages/theme-scenes/src/runtime/compile.js +119 -0
  276. package/packages/theme-scenes/src/scenes/index.js +146 -0
  277. package/packages/theme-scenes/src/shell/index.js +47 -0
  278. package/packages/theme-scenes/src/themes/index.js +129 -0
  279. package/packages/theme-scenes/src/visuals/index.js +41 -0
  280. package/packages/theme-scenes/test/theme-scenes.test.mjs +179 -0
  281. package/packages/work-graph/src/index.js +34 -1
  282. package/packages/work-graph/src/renderers/gantt-model.js +24 -0
  283. package/packages/work-graph/test/work-graph.test.mjs +27 -7
  284. package/protocol/README.md +15 -7
  285. package/protocol/apps/agentsam.app.v1.schema.json +89 -7
  286. package/protocol/apps/agentsam.host-install.v1.schema.json +36 -0
  287. package/protocol/assets/README.md +9 -0
  288. package/protocol/assets/asset-record.v1.schema.json +64 -0
  289. package/protocol/runtime/agentsam.runtime.v1.schema.json +75 -0
  290. package/protocol/scoring/README.md +10 -0
  291. package/protocol/scoring/scorecard.v1.schema.json +65 -0
  292. package/protocol/ui/icon-registry.mjs +1 -0
  293. package/registry/cms-rust-machine-20260928/installable-products.json +31 -0
  294. package/registry/cms-rust-machine-20260928/manifest.json +22 -0
  295. package/registry/cms-rust-machine-20260928/migration.sql +237 -0
  296. package/registry/cms-rust-machine-20260928/receipt.json +21 -0
  297. package/registry/cms-rust-machine-20260928/receipt.sql +27 -0
  298. package/scripts/build_rapid_rust_cli.py +83 -0
  299. package/src/attachments/index.js +6 -0
  300. package/src/attachments/intake.js +235 -0
  301. package/src/capabilities/repository-snapshot.js +19 -2
  302. package/src/cli/command-catalog.js +8 -0
  303. package/src/cli.js +182 -26
  304. package/src/commands/account-auth.js +94 -8
  305. package/src/commands/app.js +307 -3
  306. package/src/commands/billing.js +127 -0
  307. package/src/commands/brand.js +74 -60
  308. package/src/commands/cheat-sheet.js +154 -0
  309. package/src/commands/cloudflare-login.js +222 -0
  310. package/src/commands/cloudflare.js +453 -23
  311. package/src/commands/codebaseindex.js +6 -1
  312. package/src/commands/compute.js +4 -0
  313. package/src/commands/connections.js +11 -5
  314. package/src/commands/credentials.js +116 -0
  315. package/src/commands/gcloud-auth.js +427 -0
  316. package/src/commands/google-cloud.js +375 -0
  317. package/src/commands/identity-init.js +2 -2
  318. package/src/commands/mcp.js +226 -33
  319. package/src/commands/ollama.js +3 -2
  320. package/src/commands/plugins.js +7 -2
  321. package/src/commands/product.js +36 -0
  322. package/src/commands/runtime-status.js +28 -9
  323. package/src/commands/runtime.js +313 -0
  324. package/src/commands/rust.js +24 -0
  325. package/src/commands/setup.js +279 -0
  326. package/src/commands/shell.js +16 -3
  327. package/src/commands/start-local.js +2 -2
  328. package/src/commands/terminal.js +171 -0
  329. package/src/commands/update.js +140 -0
  330. package/src/commands/whoami.js +329 -65
  331. package/src/features/resolve.js +1 -0
  332. package/src/index.js +4 -0
  333. package/src/indexing/ingest/inventory.js +254 -19
  334. package/src/indexing/ingest/materials.js +3 -9
  335. package/src/indexing/ingest/style-evidence.js +181 -0
  336. package/src/knowledge/source.js +3 -3
  337. package/src/lib/account-session.js +11 -4
  338. package/src/lib/app-authority.js +172 -0
  339. package/src/lib/auth.js +94 -21
  340. package/src/lib/core-client.js +5 -6
  341. package/src/lib/credentials-audit.js +451 -0
  342. package/src/lib/deploy/health.js +24 -6
  343. package/src/lib/detect-context.js +7 -1
  344. package/src/lib/google-cloud-connection.js +270 -0
  345. package/src/lib/google-cloud-inventory.js +385 -0
  346. package/src/lib/google-desktop-oauth.js +372 -0
  347. package/src/lib/google-studio-brokered-oauth.js +158 -0
  348. package/src/lib/identity-scaffold.js +24 -6
  349. package/src/lib/init-options.js +192 -0
  350. package/src/lib/local-scaffold.js +48 -16
  351. package/src/lib/provider-command-remediation.js +308 -0
  352. package/src/lib/provider-credentials.js +8 -0
  353. package/src/lib/scaffold/index.js +8 -2
  354. package/src/lib/scaffold/mcp-server.js +43 -0
  355. package/src/lib/scaffold/templates/mcp-server/index.js +397 -0
  356. package/src/lib/scaffold/templates/mcp-server/presets.js +39 -0
  357. package/src/lib/scaffold/wizards/cms.js +93 -0
  358. package/src/lib/scaffold/wizards/mcp-server.js +61 -0
  359. package/src/lib/setup/contract.js +26 -0
  360. package/src/lib/setup/discover.js +116 -0
  361. package/src/lib/setup/execute.js +205 -0
  362. package/src/lib/setup/planner.js +134 -0
  363. package/src/lib/setup/recipes.js +235 -0
  364. package/src/lib/setup/runtime-persist.js +197 -0
  365. package/src/lib/setup/runtime.js +394 -0
  366. package/src/lib/slash-commands.js +2 -0
  367. package/src/lib/terminal/machine-identity.js +95 -0
  368. package/src/lib/terminal-local.js +164 -0
  369. package/src/lib/terminal-scopes.js +52 -0
  370. package/src/lib/whoami-capabilities.js +184 -0
  371. package/src/local-pty/server.js +34 -5
  372. package/src/mcp/authority.js +58 -108
  373. package/src/mcp/client-adapters.js +68 -144
  374. package/src/mcp/client.js +142 -122
  375. package/src/mcp/cloudflare-bundles.js +225 -0
  376. package/src/mcp/index.js +12 -0
  377. package/src/plugins/cloudflare.js +1 -1
  378. package/src/providers/ollama-chat.js +2 -1
  379. package/src/sam/types.js +27 -2
  380. package/src/security/inventory.js +12 -2
  381. package/src/security/local-vault.js +2 -0
  382. package/src/security/scan.js +1 -1
  383. package/test/account-session.test.mjs +3 -3
  384. package/test/app-authority-context.test.mjs +32 -0
  385. package/test/cli/codebaseindex-plan-ux.test.mjs +1 -1
  386. package/test/cli/mcp-client.test.mjs +21 -10
  387. package/test/cli/runtime-persist.test.mjs +56 -0
  388. package/test/cli/rust-command.test.mjs +21 -0
  389. package/test/credentials-audit.test.mjs +113 -0
  390. package/test/deploy-health-scan.test.mjs +29 -1
  391. package/test/gcloud-auth.test.mjs +111 -0
  392. package/test/google-cloud-connection.test.mjs +83 -0
  393. package/test/google-cloud-inventory.test.mjs +64 -0
  394. package/test/init-options.test.mjs +35 -0
  395. package/test/integration/app-command.test.mjs +30 -0
  396. package/test/integration/cad-project.test.mjs +4 -1
  397. package/test/integration/cms-app-scaffold.test.mjs +71 -0
  398. package/test/integration/cms-site-tenancy-contract.test.mjs +3 -2
  399. package/test/integration/codebaseindex-ingest.test.mjs +48 -0
  400. package/test/integration/features-resolve.test.mjs +30 -11
  401. package/test/integration/inspect-path-cli.test.mjs +46 -0
  402. package/test/integration/inventory-evidence.test.mjs +125 -0
  403. package/test/integration/runtime-status.integration.test.mjs +2 -1
  404. package/test/knowledge.test.mjs +35 -1
  405. package/test/loopback-oauth.test.mjs +53 -0
  406. package/test/ollama.test.mjs +22 -0
  407. package/test/security.test.mjs +23 -0
  408. package/test/setup-planner.test.mjs +74 -0
  409. package/test/setup-runtime.test.mjs +51 -0
  410. package/test/terminal/local-pty.mock.test.mjs +3 -1
  411. package/test/terminal-machine-identity.test.mjs +88 -0
  412. package/test/whoami-resume.test.mjs +27 -6
  413. package/packages/agentsam-brand/test/brand-scan.test.mjs +0 -106
  414. package/packages/work-graph/prototype/README.md +0 -32
  415. package/packages/work-graph/prototype/data/demo-workgraph.js +0 -47
  416. package/packages/work-graph/prototype/renderers/timeline-model.js +0 -21
  417. package/packages/work-graph/prototype/renderers/workgraph-runtime.js +0 -38
  418. package/packages/work-graph/prototype-gnantt.html +0 -655
@@ -52,16 +52,7 @@ describe('cloudflare connector', () => {
52
52
  });
53
53
 
54
54
  it('keeps connector return paths same-origin', async () => {
55
- const calls = [];
56
- const DB = {
57
- prepare(sql) {
58
- return {
59
- args: [],
60
- bind(...args) { this.args = args; return this; },
61
- async run() { calls.push({ sql, args: this.args }); return { success: true }; },
62
- };
63
- },
64
- };
55
+ const oauthState = new Map();
65
56
  const response = await handleCloudflareConnectionRequest(
66
57
  new Request('https://agentsam.example/api/connections/cloudflare/start?return_to=https://untrusted.example/after', {
67
58
  headers: {
@@ -70,19 +61,17 @@ describe('cloudflare connector', () => {
70
61
  },
71
62
  }),
72
63
  {
73
- DB,
64
+ oauthState,
74
65
  fixtureSessions: new Map([['fixture', 'user_123']]),
75
66
  CLOUDFLARE_OAUTH_CLIENT_ID: 'real-client-id',
76
67
  },
77
68
  );
78
69
  assert.equal(response.status, 200);
79
- assert.equal(
80
- calls.some((call) => call.sql.includes('DELETE FROM agentsam_cloudflare_oauth_state WHERE created_at < unixepoch() - 600')),
81
- true,
82
- );
83
- const stateInsert = calls.find((call) => call.sql.includes('INSERT INTO agentsam_cloudflare_oauth_state'));
84
- assert.ok(stateInsert);
85
- assert.equal(stateInsert.args.at(-1), null);
70
+ const body = await response.json();
71
+ assert.equal(body.ok, true);
72
+ assert.equal(oauthState.size, 1);
73
+ const stored = [...oauthState.values()][0];
74
+ assert.equal(stored.returnTo, '');
86
75
  });
87
76
 
88
77
  it('redirects browser starts to Cloudflare authorization', async () => {
@@ -108,9 +97,15 @@ describe('cloudflare connector', () => {
108
97
  });
109
98
 
110
99
  it('consumes callback state and stores only encrypted OAuth tokens', async () => {
111
- const now = Math.floor(Date.now() / 1000);
112
100
  const calls = [];
113
- const statements = [];
101
+ const oauthState = new Map([
102
+ ['state_123', {
103
+ ownerId: 'user_123',
104
+ verifier: 'verifier',
105
+ returnTo: '',
106
+ createdAt: Math.floor(Date.now() / 1000),
107
+ }],
108
+ ]);
114
109
  const DB = {
115
110
  prepare(sql) {
116
111
  const statement = {
@@ -121,9 +116,6 @@ describe('cloudflare connector', () => {
121
116
  return this;
122
117
  },
123
118
  async first() {
124
- if (sql.includes('agentsam_cloudflare_oauth_state')) {
125
- return { owner_id: 'user_123', code_verifier: 'verifier', created_at: now };
126
- }
127
119
  return null;
128
120
  },
129
121
  async run() {
@@ -131,7 +123,6 @@ describe('cloudflare connector', () => {
131
123
  return { success: true };
132
124
  },
133
125
  };
134
- statements.push(statement);
135
126
  return statement;
136
127
  },
137
128
  async batch(batchStatements) {
@@ -146,7 +137,7 @@ describe('cloudflare connector', () => {
146
137
  return new Response(JSON.stringify({
147
138
  access_token: 'access-plaintext',
148
139
  refresh_token: 'refresh-plaintext',
149
- account_id: 'account_123',
140
+ account_id: 'abc123abc123abc123abc123abc123ab',
150
141
  scope: 'd1.read workers-scripts.write',
151
142
  expires_in: 3600,
152
143
  }), { status: 200, headers: { 'content-type': 'application/json' } });
@@ -157,6 +148,7 @@ describe('cloudflare connector', () => {
157
148
  new Request('https://agentsam.example/api/connections/cloudflare/callback?code=code_123&state=state_123'),
158
149
  {
159
150
  DB,
151
+ oauthState,
160
152
  CLOUDFLARE_OAUTH_CLIENT_ID: 'real-client-id',
161
153
  CLOUDFLARE_OAUTH_CLIENT_SECRET: 'obsolete-secret-must-not-be-sent',
162
154
  VAULT_MASTER_KEY: '01234567890123456789012345678901',
@@ -167,11 +159,15 @@ describe('cloudflare connector', () => {
167
159
  response.headers.get('location'),
168
160
  'https://agentsam.example/settings/integrations?connection=cloudflare&result=connected',
169
161
  );
170
- assert.equal(calls.some((call) => call.sql.includes('DELETE FROM agentsam_cloudflare_oauth_state')), true);
171
- const insert = calls.find((call) => call.sql.includes('INSERT INTO agentsam_cloudflare_connections'));
172
- assert.ok(insert);
173
- assert.notEqual(insert.args[4], 'access-plaintext');
174
- assert.notEqual(insert.args[5], 'refresh-plaintext');
162
+ assert.equal(oauthState.has('state_123'), false);
163
+ const insert = calls.find((call) => call.sql.includes('INSERT INTO user_oauth_tokens'));
164
+ assert.ok(insert, 'expected user_oauth_tokens insert (SSOT)');
165
+ // With vault: plaintext args are null; ciphertext is not plaintext tokens.
166
+ assert.equal(insert.args[3], null); // access_token plaintext
167
+ assert.equal(insert.args[4], null); // refresh_token plaintext
168
+ assert.notEqual(insert.args[5], 'access-plaintext'); // access_token_encrypted
169
+ assert.notEqual(insert.args[6], 'refresh-plaintext'); // refresh_token_encrypted
170
+ assert.equal(calls.some((call) => call.sql.includes('agentsam_cloudflare_connections')), false);
175
171
  } finally {
176
172
  globalThis.fetch = originalFetch;
177
173
  }
@@ -0,0 +1,125 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, it } from 'node:test';
3
+ import {
4
+ resolveCloudflareAccountId,
5
+ unionScopes,
6
+ upsertCloudflareUserOauthToken,
7
+ } from '../src/oauth-persist.js';
8
+
9
+ describe('oauth-persist spine', () => {
10
+ it('unions scopes without duplicates', () => {
11
+ assert.deepEqual(
12
+ unionScopes(['d1.read', 'offline_access'], ['d1.read', 'workers-scripts.write']).sort(),
13
+ ['d1.read', 'offline_access', 'workers-scripts.write'].sort(),
14
+ );
15
+ });
16
+
17
+ it('requires explicit selection when Cloudflare exposes multiple accounts', async () => {
18
+ const result = await resolveCloudflareAccountId('token', {
19
+ fetchImpl: async () => ({
20
+ ok: true,
21
+ async json() {
22
+ return {
23
+ result: [
24
+ { id: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', name: 'A' },
25
+ { id: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', name: 'B' },
26
+ ],
27
+ };
28
+ },
29
+ }),
30
+ });
31
+ assert.equal(result?.error, 'cloudflare_account_selection_required');
32
+ assert.equal(result?.accounts?.length, 2);
33
+ });
34
+
35
+ it('rejects provider labels and synthetic values as account identifiers', async () => {
36
+ const result = await upsertCloudflareUserOauthToken(
37
+ { DB: { prepare() { throw new Error('should not query'); } } },
38
+ { userId: 'au_1', accessToken: 'token', accountId: 'Cloudflare' },
39
+ );
40
+ assert.equal(result.ok, false);
41
+ assert.equal(result.error, 'cloudflare_account_identifier_required');
42
+ });
43
+
44
+ it('upserts with client_id provenance and scope union (no connected_via_app)', async () => {
45
+ const rows = new Map();
46
+ const sqlSeen = [];
47
+ const env = {
48
+ VAULT_MASTER_KEY: 'test-vault-material',
49
+ DB: {
50
+ prepare(sql) {
51
+ sqlSeen.push(String(sql));
52
+ return {
53
+ bind(...args) {
54
+ return {
55
+ async first() {
56
+ if (String(sql).includes('SELECT')) {
57
+ return rows.get(`${args[0]}|${args[2]}`) || null;
58
+ }
59
+ return null;
60
+ },
61
+ async run() {
62
+ if (String(sql).includes('INSERT')) {
63
+ // Encrypted-only path: plaintext [3]/[4] are null; ciphertext [5]/[6].
64
+ const key = `${args[0]}|${args[2]}`;
65
+ const prior = rows.get(key);
66
+ rows.set(key, {
67
+ scopes: args[7],
68
+ scope: args[7],
69
+ metadata_json: args[11],
70
+ access_token: args[3],
71
+ refresh_token: args[4],
72
+ created_at: prior?.created_at || args[12],
73
+ });
74
+ }
75
+ return { success: true };
76
+ },
77
+ };
78
+ },
79
+ };
80
+ },
81
+ },
82
+ };
83
+
84
+ const r1 = await upsertCloudflareUserOauthToken(env, {
85
+ userId: 'au_1',
86
+ accessToken: 'tok1',
87
+ scopes: 'd1.read offline_access',
88
+ accountId: 'abc123abc123abc123abc123abc123ab',
89
+ clientId: 'c0704bd7a7aab7216b362603e1985499',
90
+ capabilitySet: ['cloudflare.d1'],
91
+ });
92
+ assert.equal(r1.ok, true);
93
+ assert.equal(r1.status, 'connected');
94
+ assert.equal(r1.provenance.connected_via_client_id, 'c0704bd7a7aab7216b362603e1985499');
95
+ assert.equal(r1.provenance.connected_via_app, undefined);
96
+
97
+ rows.set('au_1|abc123abc123abc123abc123abc123ab', {
98
+ scopes: 'd1.read offline_access',
99
+ scope: 'd1.read offline_access',
100
+ metadata_json: JSON.stringify({
101
+ cloudflare_account_id: 'abc123abc123abc123abc123abc123ab',
102
+ connected_via_client_id: 'c0704bd7a7aab7216b362603e1985499',
103
+ connected_via_app: 'should_be_stripped',
104
+ }),
105
+ access_token: 'tok1',
106
+ refresh_token: null,
107
+ created_at: 1,
108
+ });
109
+
110
+ const r2 = await upsertCloudflareUserOauthToken(env, {
111
+ userId: 'au_1',
112
+ accessToken: 'tok2',
113
+ scopes: 'workers-scripts.write',
114
+ accountId: 'abc123abc123abc123abc123abc123ab',
115
+ clientId: 'c0704bd7a7aab7216b362603e1985499',
116
+ capabilitySet: ['cloudflare.workers'],
117
+ });
118
+ assert.equal(r2.ok, true);
119
+ assert.ok(r2.scopes.includes('d1.read'));
120
+ assert.ok(r2.scopes.includes('workers-scripts.write'));
121
+ const upsertSql = sqlSeen.find((sql) => sql.includes('ON CONFLICT(user_id, provider, account_identifier)'));
122
+ assert.match(upsertSql || '', /last_refresh_error_code = NULL/);
123
+ assert.match(upsertSql || '', /refresh_failure_count = 0/);
124
+ });
125
+ });
@@ -35,7 +35,27 @@
35
35
  "required_configuration": [
36
36
  "GOOGLE_CLIENT_ID",
37
37
  "GOOGLE_CLIENT_SECRET"
38
- ]
38
+ ],
39
+ "notes": "Web browser OAuth (confidential client). For Desktop/CLI PKCE use google_desktop."
40
+ },
41
+ {
42
+ "id": "google_desktop",
43
+ "aliases": ["google-desktop"],
44
+ "kind": "oauth",
45
+ "status": "ready",
46
+ "implementation": "src/providers/google",
47
+ "capabilities": [
48
+ "identity.oauth.authorize",
49
+ "identity.oauth.desktop_exchange",
50
+ "identity.profile.resolve"
51
+ ],
52
+ "required_configuration": [
53
+ "GOOGLE_DESKTOP_CLIENT_ID"
54
+ ],
55
+ "optional_configuration": [
56
+ "GOOGLE_DESKTOP_CLIENT_SECRET"
57
+ ],
58
+ "notes": "Desktop/public PKCE client (Console type Desktop app — no secret). Worker brokers POST /api/oauth/google/desktop-exchange for loopback redirects. Optional GOOGLE_DESKTOP_CLIENT_SECRET only if the client id was mis-typed as Web."
39
59
  },
40
60
  {
41
61
  "id": "github",
@@ -90,7 +110,7 @@
90
110
  "optional_configuration": [
91
111
  "CLOUDFLARE_OAUTH_CLIENT_SECRET"
92
112
  ],
93
- "notes": "Registered in identityProviders. Client secret optional for PKCE-only clients."
113
+ "notes": "Cloudflare sign-in (same Worker secrets as the Cloudflare resource connector). Client secret optional for PKCE-only clients (Token Authentication Method = None)."
94
114
  }
95
115
  ]
96
116
  }
@@ -4,13 +4,19 @@
4
4
  "engine": "d1",
5
5
  "migration_sources": [
6
6
  "src/migrations/0001_identity_core.sql",
7
- "src/migrations/0002_company.sql"
7
+ "src/migrations/0002_company.sql",
8
+ "src/migrations/0003_accounts_ssot.sql"
8
9
  ],
9
- "notes": "Migration files remain the schema authority. This JSON is an index/contract only.",
10
+ "notes": "Migration files remain the schema authority. accounts is the account SSOT; account_identities is IdP linkage only.",
10
11
  "tables": [
12
+ {
13
+ "name": "accounts",
14
+ "purpose": "account SSOT (row of record)",
15
+ "source": "src/migrations/0001_identity_core.sql"
16
+ },
11
17
  {
12
18
  "name": "auth_users",
13
- "purpose": "canonical user identity",
19
+ "purpose": "login principal (1:1 with accounts.id in portable scaffold)",
14
20
  "source": "src/migrations/0001_identity_core.sql"
15
21
  },
16
22
  {
@@ -21,7 +27,7 @@
21
27
  },
22
28
  {
23
29
  "name": "account_identities",
24
- "purpose": "external identity/provider mapping",
30
+ "purpose": "IdP linkage only (provider + subject → accounts.id) — not the account SSOT",
25
31
  "owner_column": "account_id",
26
32
  "source": "src/migrations/0001_identity_core.sql"
27
33
  },
@@ -39,12 +39,32 @@
39
39
  "access": "public",
40
40
  "provider": "google"
41
41
  },
42
+ {
43
+ "path": "/api/oauth/google/callback",
44
+ "kind": "api",
45
+ "access": "public",
46
+ "provider": "google"
47
+ },
48
+ {
49
+ "path": "/api/oauth/google/desktop-exchange",
50
+ "method": "POST",
51
+ "kind": "api",
52
+ "access": "public",
53
+ "provider": "google_desktop",
54
+ "notes": "CLI/desktop PKCE broker — loopback redirect_uri only"
55
+ },
42
56
  {
43
57
  "path": "/api/oauth/github/start",
44
58
  "kind": "api",
45
59
  "access": "public",
46
60
  "provider": "github"
47
61
  },
62
+ {
63
+ "path": "/api/oauth/github/callback",
64
+ "kind": "api",
65
+ "access": "public",
66
+ "provider": "github"
67
+ },
48
68
  {
49
69
  "path": "/api/oauth/inneranimalmedia/start",
50
70
  "kind": "api",
@@ -20,7 +20,7 @@ identity.login(request); // alpha: throws until Identity Service adapter is wi
20
20
  identity.session.fromRequest(request); // alpha: throws until adapter is wired
21
21
  ```
22
22
 
23
- **Alpha scope:** contracts, D1 adapter, Worker router, `agentsam identity init` scaffold (`app/frontend` + `backend` + migrations), and `agentsam identity preview`. Default OAuth: minted `IAM_CLIENT_ID` + `IAM_CLIENT_SECRET`. Developer Google/GitHub BYOK still supported when those env pairs are set.
23
+ **Alpha scope:** contracts, D1 adapter, Worker router, `agentsam identity init` scaffold (`app/frontend` + `backend` + migrations), and `agentsam identity preview`. Default OAuth: minted `IAM_CLIENT_ID` + `IAM_CLIENT_SECRET`. BYOK options: Google web, Google Desktop (`GOOGLE_DESKTOP_CLIENT_ID`), GitHub, Cloudflare (`CLOUDFLARE_OAUTH_CLIENT_*`). **Account SSOT:** `accounts` (not `account_identities` — that table is IdP linkage only).
24
24
 
25
25
  ## Layout
26
26
 
@@ -11,7 +11,7 @@ Worker-side identity: providers, OAuth finalize, sessions, adapters.
11
11
  | `oauth/callback.js` | `src/core/auth/oauth-finalize.js` → `finalizeInboundOAuth` | **bulletproof path** |
12
12
  | `oauth/authorize.js` | `src/api/auth.js` OAuth start handlers | PKCE + state — next sprint |
13
13
  | `core/session-service.js` | `src/core/auth.js` | cookie, `createLoginSession`, revoke |
14
- | `core/account-linking.js` | `ensureIdentityPlaneBeforeSession`, `ensureAppUser` | account_identities |
14
+ | `core/account-linking.js` | `ensureIdentityPlaneBeforeSession`, `ensureAppUser` | **accounts** SSOT + account_identities (IdP link) |
15
15
  | `adapters/inneranimalmedia/*` | D1 writes in auth side-effects | tenant/workspace stays adapter-only |
16
16
 
17
17
  ## Rule
@@ -5,8 +5,9 @@ The D1 adapter maps existing hosted table names without requiring a big-bang ren
5
5
 
6
6
  | Portable (SQLite) | Hosted D1 (current) | Notes |
7
7
  |---|---|---|
8
- | `identity_users` | `auth_users` | Same columns |
9
- | `identity_external_accounts` | `account_identities` | `user_id` ↔ `account_id` |
8
+ | `identity_users` / account plane | **`accounts`** | **Account SSOT** — row of record |
9
+ | login principal | `auth_users` | 1:1 with `accounts.id` in portable scaffold |
10
+ | `identity_external_accounts` | `account_identities` | IdP linkage only (`account_id` → `accounts.id`) — never the account SSOT |
10
11
  | `identity_sessions` | `auth_sessions` | Same columns |
11
12
  | `identity_auth_events` | `auth_event_log` | Same columns |
12
13
  | `identity_oauth_transactions` | `identity_oauth_states` → migrate to `identity_oauth_transactions` | Requires `app_id NOT NULL`; no silent pre-app_id fallback |
@@ -0,0 +1,48 @@
1
+ -- identity.oauth-server consent catalog.
2
+ -- Issuer branding remains owned by the portable company table.
3
+
4
+ INSERT OR IGNORE INTO identity_schema_meta (key, value)
5
+ VALUES ('pack_oauth_consent_catalog', '1');
6
+
7
+ CREATE TABLE IF NOT EXISTS identity_oauth_resources (
8
+ id TEXT PRIMARY KEY NOT NULL,
9
+ audience TEXT NOT NULL UNIQUE,
10
+ resource_type TEXT NOT NULL DEFAULT 'mcp',
11
+ display_name TEXT NOT NULL,
12
+ description TEXT,
13
+ logo_url TEXT,
14
+ homepage_url TEXT,
15
+ metadata_json TEXT NOT NULL DEFAULT '{}',
16
+ is_active INTEGER NOT NULL DEFAULT 1 CHECK (is_active IN (0,1)),
17
+ created_at INTEGER NOT NULL,
18
+ updated_at INTEGER NOT NULL
19
+ );
20
+
21
+ CREATE TABLE IF NOT EXISTS identity_oauth_scopes (
22
+ scope TEXT PRIMARY KEY NOT NULL,
23
+ label TEXT NOT NULL,
24
+ description TEXT NOT NULL,
25
+ category TEXT NOT NULL DEFAULT 'general',
26
+ sensitivity TEXT NOT NULL DEFAULT 'normal'
27
+ CHECK (sensitivity IN ('normal','elevated','sensitive')),
28
+ is_active INTEGER NOT NULL DEFAULT 1 CHECK (is_active IN (0,1)),
29
+ sort_order INTEGER NOT NULL DEFAULT 50,
30
+ created_at INTEGER NOT NULL,
31
+ updated_at INTEGER NOT NULL
32
+ );
33
+
34
+ CREATE TABLE IF NOT EXISTS identity_oauth_resource_scopes (
35
+ resource_id TEXT NOT NULL,
36
+ scope TEXT NOT NULL,
37
+ required INTEGER NOT NULL DEFAULT 0 CHECK (required IN (0,1)),
38
+ sort_order INTEGER NOT NULL DEFAULT 50,
39
+ PRIMARY KEY (resource_id, scope),
40
+ FOREIGN KEY (resource_id) REFERENCES identity_oauth_resources(id) ON DELETE CASCADE,
41
+ FOREIGN KEY (scope) REFERENCES identity_oauth_scopes(scope) ON DELETE CASCADE
42
+ );
43
+
44
+ CREATE INDEX IF NOT EXISTS idx_identity_oauth_resources_active
45
+ ON identity_oauth_resources(is_active, resource_type);
46
+
47
+ CREATE INDEX IF NOT EXISTS idx_identity_oauth_resource_scopes_sort
48
+ ON identity_oauth_resource_scopes(resource_id, sort_order, scope);
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-sdk-identity",
3
- "version": "2.6.4",
3
+ "version": "2.6.5",
4
4
  "private": true,
5
5
  "type": "module",
6
- "description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace — publish via root SDK)",
6
+ "description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace \u2014 publish via root SDK)",
7
7
  "agentsam": {
8
8
  "system": "identity",
9
9
  "kind": "library",
@@ -29,7 +29,8 @@
29
29
  "./contracts/auth-config": "./src/contracts/auth-config.js",
30
30
  "./oauth/callback": "./src/oauth/callback.js",
31
31
  "./frontend/auth-portal/*": "./src/frontend/auth-portal/*",
32
- "./providers/cloudflare": "./src/providers/cloudflare/index.js"
32
+ "./providers/cloudflare": "./src/providers/cloudflare/index.js",
33
+ "./oauth/consent-view": "./src/oauth/consent-view.js"
33
34
  },
34
35
  "scripts": {
35
36
  "test": "node --test tests/*.test.mjs",
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import process from 'node:process';
5
+ import { DatabaseSync } from 'node:sqlite';
6
+ import {
7
+ applySqliteIdentityMigrations,
8
+ createSqliteIdentityAdapter,
9
+ } from '../src/adapters/sqlite/index.js';
10
+ import {
11
+ createRouteRegistry,
12
+ projectionFromAppManifest,
13
+ } from '../src/contracts/route-projection.js';
14
+ import { createIdentityService } from '../src/server/identity-service.js';
15
+ import { hashPassword } from '../src/core/password-crypto.js';
16
+
17
+ function readStdin() {
18
+ return new Promise((resolve, reject) => {
19
+ let body = '';
20
+ process.stdin.setEncoding('utf8');
21
+ process.stdin.on('data', (chunk) => { body += chunk; });
22
+ process.stdin.on('end', () => {
23
+ try { resolve(body.trim() ? JSON.parse(body) : {}); }
24
+ catch (error) { reject(error); }
25
+ });
26
+ process.stdin.on('error', reject);
27
+ });
28
+ }
29
+
30
+ function wrapDatabase(database, filePath) {
31
+ return {
32
+ filePath,
33
+ prepare(sql) {
34
+ const statement = database.prepare(sql);
35
+ const bound = (values = []) => ({
36
+ async run() { return statement.run(...values); },
37
+ async first() { return statement.get(...values) ?? null; },
38
+ async all() { return { results: statement.all(...values) }; },
39
+ });
40
+ return {
41
+ bind(...values) { return bound(values); },
42
+ async run() { return statement.run(); },
43
+ async first() { return statement.get() ?? null; },
44
+ async all() { return { results: statement.all() }; },
45
+ };
46
+ },
47
+ exec(sql) { database.exec(sql); },
48
+ close() { database.close(); },
49
+ };
50
+ }
51
+
52
+ function sanitizeUser(user) {
53
+ if (!user) return null;
54
+ return {
55
+ id: user.id,
56
+ email: user.email,
57
+ display_name: user.display_name ?? null,
58
+ status: user.status ?? null,
59
+ };
60
+ }
61
+
62
+ const request = await readStdin();
63
+ const dbPath = path.resolve(
64
+ process.env.AGENTSAM_IDENTITY_DB || '.agentsam/data/local-studio-identity.sqlite',
65
+ );
66
+ const manifestPath = path.resolve(
67
+ process.env.AGENTSAM_IDENTITY_APP_MANIFEST
68
+ || new URL('../../../apps/local-studio/agentsam.app.json', import.meta.url).pathname,
69
+ );
70
+
71
+ fs.mkdirSync(path.dirname(dbPath), { recursive: true, mode: 0o700 });
72
+ const nativeDb = new DatabaseSync(dbPath);
73
+ try {
74
+ if (process.platform !== 'win32') {
75
+ try { fs.chmodSync(dbPath, 0o600); } catch {}
76
+ }
77
+ const db = wrapDatabase(nativeDb, dbPath);
78
+ await applySqliteIdentityMigrations(db);
79
+ const adapter = createSqliteIdentityAdapter(db);
80
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
81
+ const routeRegistry = createRouteRegistry([projectionFromAppManifest(manifest)]);
82
+ const identity = createIdentityService({
83
+ adapter,
84
+ app: { id: manifest.id },
85
+ routeRegistry,
86
+ });
87
+
88
+ let result;
89
+ switch (request.op) {
90
+ case 'status': {
91
+ const sessionId = String(request.session_id || '').trim();
92
+ if (!sessionId) {
93
+ result = { ok: true, authenticated: false, user: null };
94
+ break;
95
+ }
96
+ const session = await identity.sessionFromRequest(new Request('http://local.identity/session', {
97
+ headers: { Authorization: `Bearer ${sessionId}` },
98
+ }));
99
+ result = {
100
+ ok: true,
101
+ authenticated: Boolean(session),
102
+ user: sanitizeUser(session?.user),
103
+ };
104
+ break;
105
+ }
106
+
107
+ case 'login': {
108
+ const login = await identity.loginWithPassword({
109
+ email: request.email,
110
+ password: request.password,
111
+ });
112
+ result = login.ok
113
+ ? {
114
+ ok: true,
115
+ authenticated: true,
116
+ session_id: login.sessionId,
117
+ user: sanitizeUser(login.user),
118
+ redirect: identity.resolvePostLoginPath(request.next || null),
119
+ }
120
+ : login;
121
+ break;
122
+ }
123
+
124
+ case 'signup': {
125
+ const signup = await identity.signup({
126
+ email: request.email,
127
+ password: request.password,
128
+ displayName: request.display_name,
129
+ });
130
+ result = signup.ok
131
+ ? {
132
+ ok: true,
133
+ authenticated: true,
134
+ session_id: signup.sessionId,
135
+ user: sanitizeUser(signup.user),
136
+ redirect: identity.resolvePostLoginPath(request.next || null),
137
+ }
138
+ : signup;
139
+ break;
140
+ }
141
+
142
+ case 'logout': {
143
+ const sessionId = String(request.session_id || '').trim();
144
+ if (sessionId) {
145
+ await identity.logout(new Request('http://local.identity/logout', {
146
+ headers: { Authorization: `Bearer ${sessionId}` },
147
+ }));
148
+ }
149
+ result = { ok: true };
150
+ break;
151
+ }
152
+
153
+ case 'reset_password': {
154
+ const email = String(request.email || '').trim().toLowerCase();
155
+ const password = String(request.password || '');
156
+ if (!email || password.length < 8) {
157
+ result = { ok: false, error: 'email_and_valid_password_required' };
158
+ break;
159
+ }
160
+ const user = await adapter.findUserByEmail(email);
161
+ if (!user) {
162
+ result = { ok: false, error: 'account_not_found' };
163
+ break;
164
+ }
165
+ const { saltHex, hashHex } = await hashPassword(password);
166
+ await adapter.updateUserPassword(user.id, hashHex, saltHex);
167
+ result = { ok: true };
168
+ break;
169
+ }
170
+
171
+ default:
172
+ result = { ok: false, error: 'unsupported_identity_operation' };
173
+ }
174
+
175
+ process.stdout.write(JSON.stringify(result));
176
+ } catch (error) {
177
+ process.stdout.write(JSON.stringify({
178
+ ok: false,
179
+ error: error?.message || String(error),
180
+ }));
181
+ process.exitCode = 1;
182
+ } finally {
183
+ try { nativeDb.close(); } catch {}
184
+ }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Local static preview for IAM auth portal HTML (1:1 paths: /auth/login, /auth/signup, /auth/reset).
3
+ * Local static preview for the portable AgentSam auth portal HTML (1:1 paths: /auth/login, /auth/signup, /auth/reset).
4
4
  * API routes are stubbed so forms and globe-exit transitions work without a Worker.
5
5
  */
6
6
  import http from 'node:http';
@@ -119,14 +119,14 @@ function hubHtml(baseUrl) {
119
119
  const PREVIEW_COMPANY = {
120
120
  id: 'co_default',
121
121
  slug: 'default',
122
- name: 'Inner Animal Media',
123
- legalName: 'Inner Animals LLC',
124
- logoUrl: 'https://imagedelivery.net/g7wf09fCONpnidkRnR_5vw/527ab85a-01bb-4125-57bb-694fe8be8700/public',
125
- faviconUrl: 'https://inneranimalmedia.com/favicon.ico',
122
+ name: 'AgentSam',
123
+ legalName: 'AgentSam',
124
+ logoUrl: '/shared/agentsam-mark.svg',
125
+ faviconUrl: null,
126
126
  primaryColor: '#007AFF',
127
127
  authBgColor: '#050508',
128
- supportEmail: 'hey@inneranimalmedia.com',
129
- websiteUrl: 'https://inneranimalmedia.com',
128
+ supportEmail: 'support@agentsam.dev',
129
+ websiteUrl: 'https://agentsam.dev',
130
130
  tagline: 'Instant Access',
131
131
  meta: {
132
132
  privacyUrl: '/privacy',