@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.
- package/AGENTSAM.md +11 -0
- package/README.md +15 -9
- package/apps/client-cms-editor/AGENTS.md +12 -0
- package/apps/client-cms-editor/IMPORT_PROVENANCE.json +8 -0
- package/apps/client-cms-editor/README.md +72 -0
- package/apps/client-cms-editor/agentsam.app.json +57 -0
- package/apps/client-cms-editor/backend/README.md +5 -0
- package/apps/client-cms-editor/backend/package.json +22 -0
- package/apps/client-cms-editor/backend/src/api/client.ts +200 -0
- package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +145 -0
- package/apps/client-cms-editor/backend/src/index.ts +6 -0
- package/apps/client-cms-editor/backend/src/model.ts +115 -0
- package/apps/client-cms-editor/backend/src/preview/bridge.ts +79 -0
- package/apps/client-cms-editor/backend/src/preview/urls.ts +55 -0
- package/apps/client-cms-editor/backend/src/routing/cms-route.js +293 -0
- package/apps/client-cms-editor/backend/src/routing/index.js +10 -0
- package/apps/client-cms-editor/backend/src/storefront.ts +52 -0
- package/apps/client-cms-editor/backend/tsconfig.json +15 -0
- package/apps/client-cms-editor/backend/worker/index.js +34 -0
- package/apps/client-cms-editor/backend/wrangler.jsonc +11 -0
- package/apps/client-cms-editor/bin/agentsam-cms.mjs +229 -0
- package/apps/client-cms-editor/frontend/index.html +12 -0
- package/apps/client-cms-editor/frontend/package.json +33 -0
- package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +188 -0
- package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +191 -0
- package/apps/client-cms-editor/frontend/src/CmsEditor.tsx +1345 -0
- package/apps/client-cms-editor/frontend/src/env.d.ts +14 -0
- package/apps/client-cms-editor/frontend/src/index.ts +8 -0
- package/apps/client-cms-editor/frontend/src/lib/content-safety.ts +63 -0
- package/apps/client-cms-editor/frontend/src/main.tsx +17 -0
- package/apps/client-cms-editor/frontend/src/mount.tsx +51 -0
- package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +214 -0
- package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +1739 -0
- package/apps/client-cms-editor/frontend/src/styles/studio.css +106 -0
- package/apps/client-cms-editor/frontend/src/surfaces/CmsDashboard.tsx +313 -0
- package/apps/client-cms-editor/frontend/src/surfaces/CmsGuidedChatHero.tsx +121 -0
- package/apps/client-cms-editor/frontend/src/surfaces/CmsHubPage.tsx +132 -0
- package/apps/client-cms-editor/frontend/src/surfaces/CmsSiteSwitcher.tsx +176 -0
- package/apps/client-cms-editor/frontend/src/surfaces/index.ts +5 -0
- package/apps/client-cms-editor/frontend/src/surfaces/types.ts +48 -0
- package/apps/client-cms-editor/frontend/tsconfig.json +25 -0
- package/apps/client-cms-editor/frontend/vite.config.ts +13 -0
- package/apps/client-cms-editor/package-lock.json +3832 -0
- package/apps/client-cms-editor/package.json +23 -0
- package/apps/client-cms-editor/reference/DONOR_README.md +52 -0
- package/apps/client-cms-editor/reference/DONOR_package-lock.json +1253 -0
- package/apps/client-cms-editor/reference/DONOR_tsconfig.json +15 -0
- package/apps/client-cms-editor/shared/cms/package.json +21 -0
- package/apps/client-cms-editor/shared/cms/src/agent-context.ts +35 -0
- package/apps/client-cms-editor/shared/cms/src/cloudflare-bindings.ts +51 -0
- package/apps/client-cms-editor/shared/cms/src/editor-types.ts +58 -0
- package/apps/client-cms-editor/shared/cms/src/index.ts +5 -0
- package/apps/client-cms-editor/shared/cms/src/publication.ts +24 -0
- package/apps/client-cms-editor/shared/cms/src/routes.ts +11 -0
- package/apps/client-cms-editor/shared/cms/tsconfig.json +12 -0
- package/bin/agentsam-rapid-rust +36 -0
- package/docs/AUTH_IDENTITY_CONTRACT.md +2 -0
- package/docs/MACHINE_INTELLIGENCE.md +120 -0
- package/docs/WINDOWS_RUNTIME_INSTALL.md +30 -0
- package/docs/architecture/AGENTSAM_APPLICATION_CONTRACT.md +188 -0
- package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +151 -0
- package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +12 -4
- package/docs/architecture/R2_SLUG_NAMESPACE.md +20 -0
- package/docs/architecture/WORK_PRODUCT_EXTRACTION.md +97 -0
- package/docs/brand/AGENT_SAM_ICON_GRAMMAR.md +70 -0
- package/docs/content-studio/HOST_MOUNT_CHECKLIST.md +71 -0
- package/docs/content-studio/REVISION_GATE_2026-09-27.md +501 -0
- package/docs/contracts/capability-install-planner.md +67 -0
- package/docs/contracts/environment-vocabulary.md +195 -0
- package/docs/contracts/google-cloud-oauth-setup.md +199 -0
- package/docs/local-studio/WORKMODE_DONOR_NOTES.md +1 -1
- package/docs/plans/LOCAL-STUDIO-GRADUATION-2026-09-26.md +290 -0
- package/docs/plans/LOCAL-STUDIO-REAL-APP-CONTRACT-ADDENDUM-2026-09-27.md +394 -0
- package/docs/plans/MACHINE-FIRST-APPS-TUI-2026-09-24.md +227 -0
- package/docs/plans/TOMORROW-EXTENSIVE-TODO-2026-09-26.md +221 -0
- package/docs/plans/TOMORROW-MACHINE-FIRST-BRIEFING.md +145 -0
- package/docs/plans/UNIVERSAL-INGEST-MACHINE-FIRST-2026-09-24.md +215 -0
- package/docs/plugins.md +2 -2
- package/docs/product/AGENTSAM_PRODUCT_EXPERIENCE_STANDARD.md +280 -0
- package/docs/product/LOCAL_STUDIO_DESKTOP_EXPERIENCE.md +139 -0
- package/docs/product/README.md +8 -0
- package/docs/rapid-rust-wasm.md +35 -0
- package/migrations/d1/0016_cloudflare_oauth_user_oauth_tokens_ssot.sql +14 -0
- package/package.json +73 -14
- package/packages/agentsam-brand/README.md +106 -11
- package/packages/agentsam-brand/bin/agentsam-brand.mjs +9 -0
- package/packages/agentsam-brand/package.json +39 -7
- package/packages/agentsam-brand/src/adapters/cloudflare-images.js +453 -0
- package/packages/agentsam-brand/src/adapters/cloudflare-r2.js +74 -0
- package/packages/agentsam-brand/src/adapters/d1-registry.js +26 -0
- package/packages/agentsam-brand/src/adapters/filesystem.js +59 -0
- package/packages/agentsam-brand/src/adapters/memory.js +31 -0
- package/packages/agentsam-brand/src/cli/controller.js +503 -0
- package/packages/agentsam-brand/src/cli/wizard.js +526 -0
- package/packages/agentsam-brand/src/core/capabilities.js +201 -0
- package/packages/agentsam-brand/src/core/derivatives.js +211 -0
- package/packages/agentsam-brand/src/core/errors.js +12 -0
- package/packages/agentsam-brand/src/core/ingest.js +195 -0
- package/packages/agentsam-brand/src/core/inspect.js +109 -0
- package/packages/agentsam-brand/src/core/keys.js +83 -0
- package/packages/agentsam-brand/src/core/naming.js +142 -0
- package/packages/agentsam-brand/src/core/optimize.js +316 -0
- package/packages/agentsam-brand/src/core/pack.js +305 -0
- package/packages/agentsam-brand/src/core/plan.js +276 -0
- package/packages/agentsam-brand/src/core/preview.js +159 -0
- package/packages/agentsam-brand/src/core/processors/cloudflare.js +68 -0
- package/packages/agentsam-brand/src/core/processors/contract.js +203 -0
- package/packages/agentsam-brand/src/core/processors/index.js +148 -0
- package/packages/agentsam-brand/src/core/processors/native.js +82 -0
- package/packages/agentsam-brand/src/core/processors/sharp.js +113 -0
- package/packages/agentsam-brand/src/core/processors/squoosh-binary.js +195 -0
- package/packages/agentsam-brand/src/core/promote.js +288 -0
- package/packages/agentsam-brand/src/core/receipts.js +155 -0
- package/packages/agentsam-brand/src/core/v2/compile.js +280 -0
- package/packages/agentsam-brand/src/core/v2/derivatives-semantic.js +207 -0
- package/packages/agentsam-brand/src/core/v2/ingest-graph.js +387 -0
- package/packages/agentsam-brand/src/core/v2/roles.js +180 -0
- package/packages/agentsam-brand/src/core/v2/schema.js +209 -0
- package/packages/agentsam-brand/src/core/v2/templates.js +114 -0
- package/packages/agentsam-brand/src/index.js +193 -36
- package/packages/agentsam-brand/src/presets/app-icon.json +16 -0
- package/packages/agentsam-brand/src/presets/favicon.json +17 -0
- package/packages/agentsam-brand/src/presets/hero.json +12 -0
- package/packages/agentsam-brand/src/presets/index.js +40 -0
- package/packages/agentsam-brand/src/presets/logo.json +12 -0
- package/packages/agentsam-brand/src/presets/model.json +8 -0
- package/packages/agentsam-brand/src/presets/og-image.json +10 -0
- package/packages/agentsam-brand/src/presets/product-shot.json +11 -0
- package/packages/agentsam-brand/src/presets/social-image.json +10 -0
- package/packages/agentsam-brand/src/presets/web-image.json +10 -0
- package/packages/agentsam-contracts/src/artifacts.ts +41 -0
- package/packages/agentsam-knowledge/src/autorag/index.js +1 -1
- package/packages/agentsam-knowledge/src/providers/index.js +6 -4
- package/packages/agentsam-knowledge/src/providers/ollama-endpoint.js +31 -0
- package/packages/agentsam-knowledge/test/autorag.test.mjs +22 -1
- package/packages/agentsam-nav/package.json +2 -2
- package/packages/agentsam-rapid-rust/Cargo.lock +344 -0
- package/packages/agentsam-rapid-rust/Cargo.toml +18 -0
- package/packages/agentsam-rapid-rust/README.md +5 -0
- package/packages/agentsam-rapid-rust/src/main.rs +718 -0
- package/packages/agentsam-rapid-rust/templates/api/Cargo.toml.tmpl +18 -0
- package/packages/agentsam-rapid-rust/templates/api/src/lib.rs.tmpl +17 -0
- package/packages/agentsam-rapid-rust/templates/common/README.md.tmpl +22 -0
- package/packages/agentsam-rapid-rust/templates/common/package.json.tmpl +12 -0
- package/packages/agentsam-rapid-rust/templates/common/wrangler.toml.tmpl +6 -0
- package/packages/agentsam-rapid-rust/templates/crypto-auth/Cargo.toml.tmpl +21 -0
- package/packages/agentsam-rapid-rust/templates/crypto-auth/src/lib.rs.tmpl +32 -0
- package/packages/agentsam-rapid-rust/templates/data-processor/Cargo.toml.tmpl +18 -0
- package/packages/agentsam-rapid-rust/templates/data-processor/src/lib.rs.tmpl +41 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/Cargo.toml.tmpl +9 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/core/Cargo.toml.tmpl +7 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/core/src/lib.rs.tmpl +23 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/worker/Cargo.toml.tmpl +12 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/worker/src/lib.rs.tmpl +16 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/wrangler.toml.tmpl +6 -0
- package/packages/agentsam-repository/src/index.js +1 -0
- package/packages/agentsam-repository/src/merkle/semantic.js +3 -10
- package/packages/agentsam-repository/src/source-types.js +85 -0
- package/packages/agentsam-vault/README.md +96 -0
- package/packages/agentsam-vault/package.json +32 -0
- package/packages/agentsam-vault/src/contracts/credential.d.ts +78 -0
- package/packages/agentsam-vault/src/contracts/credential.js +132 -0
- package/packages/agentsam-vault/src/crypto/aes-gcm.d.ts +30 -0
- package/packages/agentsam-vault/src/crypto/aes-gcm.js +107 -0
- package/packages/agentsam-vault/src/crypto/oauth-envelope.js +150 -0
- package/packages/agentsam-vault/src/index.d.ts +9 -0
- package/packages/agentsam-vault/src/index.js +27 -0
- package/packages/agentsam-vault/src/providers/registry.js +90 -0
- package/packages/agentsam-vault/src/runtime/resolver.js +77 -0
- package/packages/agentsam-workbench/README.md +24 -0
- package/packages/agentsam-workbench/package.json +38 -0
- package/packages/agentsam-workbench/src/agent/AgentPanel.tsx +41 -0
- package/packages/agentsam-workbench/src/agent/ArtifactCard.tsx +9 -0
- package/packages/agentsam-workbench/src/agent/Composer.tsx +102 -0
- package/packages/agentsam-workbench/src/agent/ConnectedAgentPanel.tsx +194 -0
- package/packages/agentsam-workbench/src/agent/ContextualComposer.tsx +788 -0
- package/packages/agentsam-workbench/src/agent/GoalStatusStrip.tsx +38 -0
- package/packages/agentsam-workbench/src/agent/MiniAgentSam.tsx +86 -0
- package/packages/agentsam-workbench/src/agent/ModelSelect.tsx +19 -0
- package/packages/agentsam-workbench/src/agent/Thread.tsx +56 -0
- package/packages/agentsam-workbench/src/agent/ToolReceipt.tsx +11 -0
- package/packages/agentsam-workbench/src/agent/contextual-composer.css +611 -0
- package/packages/agentsam-workbench/src/agent/index.ts +10 -0
- package/packages/agentsam-workbench/src/agent/mini-agentsam.css +12 -0
- package/packages/agentsam-workbench/src/browser/BrowserFrame.tsx +37 -0
- package/packages/agentsam-workbench/src/browser/index.ts +1 -0
- package/packages/agentsam-workbench/src/index.ts +6 -0
- package/packages/agentsam-workbench/src/project-control.css +160 -0
- package/packages/agentsam-workbench/src/projects/ProjectsSurface.tsx +131 -0
- package/packages/agentsam-workbench/src/projects/index.ts +1 -0
- package/packages/agentsam-workbench/src/shell/Breadcrumb.tsx +35 -0
- package/packages/agentsam-workbench/src/shell/ResizableStage.tsx +99 -0
- package/packages/agentsam-workbench/src/shell/SidePanel.tsx +5 -0
- package/packages/agentsam-workbench/src/shell/index.ts +4 -0
- package/packages/agentsam-workbench/src/shell/surfaceRegistry.ts +29 -0
- package/packages/agentsam-workbench/src/terminal/TerminalSurface.tsx +5 -0
- package/packages/agentsam-workbench/src/terminal/index.ts +1 -0
- package/packages/agentsam-workbench/src/timeline/GanttBoard.tsx +258 -0
- package/packages/agentsam-workbench/src/timeline/index.ts +1 -0
- package/packages/agentsam-workbench/tsconfig.json +13 -0
- package/packages/connectors/cloudflare/OAUTH_STORAGE_AUDIT.md +53 -0
- package/packages/connectors/cloudflare/package.json +3 -1
- package/packages/connectors/cloudflare/src/api-client.js +279 -0
- package/packages/connectors/cloudflare/src/capabilities.js +585 -0
- package/packages/connectors/cloudflare/src/credential.js +318 -0
- package/packages/connectors/cloudflare/src/families/brand-protection.js +123 -0
- package/packages/connectors/cloudflare/src/families/keyless.js +114 -0
- package/packages/connectors/cloudflare/src/families/pages.js +151 -0
- package/packages/connectors/cloudflare/src/families/scanner.js +123 -0
- package/packages/connectors/cloudflare/src/families/snippets.js +207 -0
- package/packages/connectors/cloudflare/src/families/tag-gateway.js +46 -0
- package/packages/connectors/cloudflare/src/families/tags.js +124 -0
- package/packages/connectors/cloudflare/src/families/token-validation.js +95 -0
- package/packages/connectors/cloudflare/src/families/workflows.js +156 -0
- package/packages/connectors/cloudflare/src/index.js +102 -265
- package/packages/connectors/cloudflare/src/oauth-persist.js +336 -0
- package/packages/connectors/cloudflare/src/owner.js +42 -12
- package/packages/connectors/cloudflare/src/permission-options.js +1064 -0
- package/packages/connectors/cloudflare/src/routes.js +309 -144
- package/packages/connectors/cloudflare/src/scope-catalog.js +345 -0
- package/packages/connectors/cloudflare/src/vault.js +2 -2
- package/packages/connectors/cloudflare/tests/capabilities.test.mjs +276 -0
- package/packages/connectors/cloudflare/tests/connector.test.mjs +26 -30
- package/packages/connectors/cloudflare/tests/oauth-persist.test.mjs +125 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +22 -2
- package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +10 -4
- package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +20 -0
- package/packages/identity/README.md +1 -1
- package/packages/identity/backend/README.md +1 -1
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +3 -2
- package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +48 -0
- package/packages/identity/package.json +4 -3
- package/packages/identity/scripts/local-identity-bridge.mjs +184 -0
- package/packages/identity/scripts/preview-auth-portal.mjs +7 -7
- package/packages/identity/src/adapters/cloudflare-d1/index.js +31 -2
- package/packages/identity/src/adapters/sqlite/index.js +4 -1
- package/packages/identity/src/contracts/auth-config.js +28 -8
- package/packages/identity/src/contracts/external-identity.js +1 -1
- package/packages/identity/src/contracts/provider.js +1 -0
- package/packages/identity/src/frontend/auth-portal/README.md +2 -1
- package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -5
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +6 -5
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +6 -5
- package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
- package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +207 -0
- package/packages/identity/src/index.js +16 -0
- package/packages/identity/src/migrations/0001_identity_core.sql +19 -2
- package/packages/identity/src/migrations/0003_accounts_ssot.sql +20 -0
- package/packages/identity/src/migrations/README.md +5 -2
- package/packages/identity/src/oauth/README.md +10 -5
- package/packages/identity/src/oauth/consent-view.js +388 -0
- package/packages/identity/src/oauth/credentials.js +31 -11
- package/packages/identity/src/oauth/google-desktop-exchange.js +173 -0
- package/packages/identity/src/providers/cloudflare/oauth.js +3 -4
- package/packages/identity/src/providers/cloudflare/profile.js +49 -14
- package/packages/identity/src/providers/iam/index.js +27 -5
- package/packages/identity/src/server/identity-service.js +31 -2
- package/packages/identity/src/server/worker-router.js +111 -81
- package/packages/identity/tests/auth-config.test.mjs +3 -2
- package/packages/identity/tests/identity-init-scaffold.test.mjs +3 -0
- package/packages/identity/tests/identity-service.test.mjs +16 -0
- package/packages/identity/tests/native-session-worker.test.mjs +64 -0
- package/packages/identity/tests/oauth-consent-view.test.mjs +106 -0
- package/packages/identity/tests/oauth-credentials.test.mjs +17 -4
- package/packages/identity/tests/oauth-presets-accounts-ssot.test.mjs +58 -0
- package/packages/identity/tests/preview-auth-portal.test.mjs +3 -3
- package/packages/runtime-protocol/src/index.js +154 -0
- package/packages/theme-scenes/README.md +164 -0
- package/packages/theme-scenes/package.json +53 -0
- package/packages/theme-scenes/src/blocks/index.js +30 -0
- package/packages/theme-scenes/src/contracts/index.js +286 -0
- package/packages/theme-scenes/src/demos/index.js +65 -0
- package/packages/theme-scenes/src/index.js +75 -0
- package/packages/theme-scenes/src/presets/index.js +263 -0
- package/packages/theme-scenes/src/runtime/compile.js +119 -0
- package/packages/theme-scenes/src/scenes/index.js +146 -0
- package/packages/theme-scenes/src/shell/index.js +47 -0
- package/packages/theme-scenes/src/themes/index.js +129 -0
- package/packages/theme-scenes/src/visuals/index.js +41 -0
- package/packages/theme-scenes/test/theme-scenes.test.mjs +179 -0
- package/packages/work-graph/src/index.js +34 -1
- package/packages/work-graph/src/renderers/gantt-model.js +24 -0
- package/packages/work-graph/test/work-graph.test.mjs +27 -7
- package/protocol/README.md +15 -7
- package/protocol/apps/agentsam.app.v1.schema.json +89 -7
- package/protocol/apps/agentsam.host-install.v1.schema.json +36 -0
- package/protocol/assets/README.md +9 -0
- package/protocol/assets/asset-record.v1.schema.json +64 -0
- package/protocol/runtime/agentsam.runtime.v1.schema.json +75 -0
- package/protocol/scoring/README.md +10 -0
- package/protocol/scoring/scorecard.v1.schema.json +65 -0
- package/protocol/ui/icon-registry.mjs +1 -0
- package/registry/cms-rust-machine-20260928/installable-products.json +31 -0
- package/registry/cms-rust-machine-20260928/manifest.json +22 -0
- package/registry/cms-rust-machine-20260928/migration.sql +237 -0
- package/registry/cms-rust-machine-20260928/receipt.json +21 -0
- package/registry/cms-rust-machine-20260928/receipt.sql +27 -0
- package/scripts/build_rapid_rust_cli.py +83 -0
- package/src/attachments/index.js +6 -0
- package/src/attachments/intake.js +235 -0
- package/src/capabilities/repository-snapshot.js +19 -2
- package/src/cli/command-catalog.js +8 -0
- package/src/cli.js +182 -26
- package/src/commands/account-auth.js +94 -8
- package/src/commands/app.js +307 -3
- package/src/commands/billing.js +127 -0
- package/src/commands/brand.js +74 -60
- package/src/commands/cheat-sheet.js +154 -0
- package/src/commands/cloudflare-login.js +222 -0
- package/src/commands/cloudflare.js +453 -23
- package/src/commands/codebaseindex.js +6 -1
- package/src/commands/compute.js +4 -0
- package/src/commands/connections.js +11 -5
- package/src/commands/credentials.js +116 -0
- package/src/commands/gcloud-auth.js +427 -0
- package/src/commands/google-cloud.js +375 -0
- package/src/commands/identity-init.js +2 -2
- package/src/commands/mcp.js +226 -33
- package/src/commands/ollama.js +3 -2
- package/src/commands/plugins.js +7 -2
- package/src/commands/product.js +36 -0
- package/src/commands/runtime-status.js +28 -9
- package/src/commands/runtime.js +313 -0
- package/src/commands/rust.js +24 -0
- package/src/commands/setup.js +279 -0
- package/src/commands/shell.js +16 -3
- package/src/commands/start-local.js +2 -2
- package/src/commands/terminal.js +171 -0
- package/src/commands/update.js +140 -0
- package/src/commands/whoami.js +329 -65
- package/src/features/resolve.js +1 -0
- package/src/index.js +4 -0
- package/src/indexing/ingest/inventory.js +254 -19
- package/src/indexing/ingest/materials.js +3 -9
- package/src/indexing/ingest/style-evidence.js +181 -0
- package/src/knowledge/source.js +3 -3
- package/src/lib/account-session.js +11 -4
- package/src/lib/app-authority.js +172 -0
- package/src/lib/auth.js +94 -21
- package/src/lib/core-client.js +5 -6
- package/src/lib/credentials-audit.js +451 -0
- package/src/lib/deploy/health.js +24 -6
- package/src/lib/detect-context.js +7 -1
- package/src/lib/google-cloud-connection.js +270 -0
- package/src/lib/google-cloud-inventory.js +385 -0
- package/src/lib/google-desktop-oauth.js +372 -0
- package/src/lib/google-studio-brokered-oauth.js +158 -0
- package/src/lib/identity-scaffold.js +24 -6
- package/src/lib/init-options.js +192 -0
- package/src/lib/local-scaffold.js +48 -16
- package/src/lib/provider-command-remediation.js +308 -0
- package/src/lib/provider-credentials.js +8 -0
- package/src/lib/scaffold/index.js +8 -2
- package/src/lib/scaffold/mcp-server.js +43 -0
- package/src/lib/scaffold/templates/mcp-server/index.js +397 -0
- package/src/lib/scaffold/templates/mcp-server/presets.js +39 -0
- package/src/lib/scaffold/wizards/cms.js +93 -0
- package/src/lib/scaffold/wizards/mcp-server.js +61 -0
- package/src/lib/setup/contract.js +26 -0
- package/src/lib/setup/discover.js +116 -0
- package/src/lib/setup/execute.js +205 -0
- package/src/lib/setup/planner.js +134 -0
- package/src/lib/setup/recipes.js +235 -0
- package/src/lib/setup/runtime-persist.js +197 -0
- package/src/lib/setup/runtime.js +394 -0
- package/src/lib/slash-commands.js +2 -0
- package/src/lib/terminal/machine-identity.js +95 -0
- package/src/lib/terminal-local.js +164 -0
- package/src/lib/terminal-scopes.js +52 -0
- package/src/lib/whoami-capabilities.js +184 -0
- package/src/local-pty/server.js +34 -5
- package/src/mcp/authority.js +58 -108
- package/src/mcp/client-adapters.js +68 -144
- package/src/mcp/client.js +142 -122
- package/src/mcp/cloudflare-bundles.js +225 -0
- package/src/mcp/index.js +12 -0
- package/src/plugins/cloudflare.js +1 -1
- package/src/providers/ollama-chat.js +2 -1
- package/src/sam/types.js +27 -2
- package/src/security/inventory.js +12 -2
- package/src/security/local-vault.js +2 -0
- package/src/security/scan.js +1 -1
- package/test/account-session.test.mjs +3 -3
- package/test/app-authority-context.test.mjs +32 -0
- package/test/cli/codebaseindex-plan-ux.test.mjs +1 -1
- package/test/cli/mcp-client.test.mjs +21 -10
- package/test/cli/runtime-persist.test.mjs +56 -0
- package/test/cli/rust-command.test.mjs +21 -0
- package/test/credentials-audit.test.mjs +113 -0
- package/test/deploy-health-scan.test.mjs +29 -1
- package/test/gcloud-auth.test.mjs +111 -0
- package/test/google-cloud-connection.test.mjs +83 -0
- package/test/google-cloud-inventory.test.mjs +64 -0
- package/test/init-options.test.mjs +35 -0
- package/test/integration/app-command.test.mjs +30 -0
- package/test/integration/cad-project.test.mjs +4 -1
- package/test/integration/cms-app-scaffold.test.mjs +71 -0
- package/test/integration/cms-site-tenancy-contract.test.mjs +3 -2
- package/test/integration/codebaseindex-ingest.test.mjs +48 -0
- package/test/integration/features-resolve.test.mjs +30 -11
- package/test/integration/inspect-path-cli.test.mjs +46 -0
- package/test/integration/inventory-evidence.test.mjs +125 -0
- package/test/integration/runtime-status.integration.test.mjs +2 -1
- package/test/knowledge.test.mjs +35 -1
- package/test/loopback-oauth.test.mjs +53 -0
- package/test/ollama.test.mjs +22 -0
- package/test/security.test.mjs +23 -0
- package/test/setup-planner.test.mjs +74 -0
- package/test/setup-runtime.test.mjs +51 -0
- package/test/terminal/local-pty.mock.test.mjs +3 -1
- package/test/terminal-machine-identity.test.mjs +88 -0
- package/test/whoami-resume.test.mjs +27 -6
- package/packages/agentsam-brand/test/brand-scan.test.mjs +0 -106
- package/packages/work-graph/prototype/README.md +0 -32
- package/packages/work-graph/prototype/data/demo-workgraph.js +0 -47
- package/packages/work-graph/prototype/renderers/timeline-model.js +0 -21
- package/packages/work-graph/prototype/renderers/workgraph-runtime.js +0 -38
- 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
|
|
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
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
);
|
|
83
|
-
|
|
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
|
|
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: '
|
|
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(
|
|
171
|
-
const insert = calls.find((call) => call.sql.includes('INSERT INTO
|
|
172
|
-
assert.ok(insert);
|
|
173
|
-
|
|
174
|
-
assert.
|
|
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": "
|
|
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.
|
|
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": "
|
|
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": "
|
|
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`.
|
|
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` |
|
|
9
|
-
|
|
|
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.
|
|
3
|
+
"version": "2.6.5",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
|
-
"description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace
|
|
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
|
|
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: '
|
|
123
|
-
legalName: '
|
|
124
|
-
logoUrl: '
|
|
125
|
-
faviconUrl:
|
|
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: '
|
|
129
|
-
websiteUrl: 'https://
|
|
128
|
+
supportEmail: 'support@agentsam.dev',
|
|
129
|
+
websiteUrl: 'https://agentsam.dev',
|
|
130
130
|
tagline: 'Instant Access',
|
|
131
131
|
meta: {
|
|
132
132
|
privacyUrl: '/privacy',
|