@inneranimalmedia/agentsam-sdk 2.6.5 → 2.6.8
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 +29 -0
- package/README.md +37 -0
- package/apps/README.md +5 -0
- package/apps/cad-creator/README.md +4 -4
- package/apps/cad-creator/shared/cad/package.json +1 -1
- package/apps/client-cms-editor/AGENTS.md +12 -7
- package/apps/client-cms-editor/README.md +76 -48
- package/apps/client-cms-editor/agentsam.app.json +26 -9
- package/apps/client-cms-editor/backend/package.json +20 -3
- package/apps/client-cms-editor/backend/src/api/client.ts +134 -101
- package/apps/client-cms-editor/backend/src/index.ts +1 -1
- package/apps/client-cms-editor/backend/src/model.ts +11 -115
- package/apps/client-cms-editor/backend/src/preview/bridge.ts +1 -1
- package/apps/client-cms-editor/backend/tsconfig.json +6 -1
- package/apps/client-cms-editor/bin/agentsam-cms.js +262 -0
- package/apps/client-cms-editor/bin/agentsam-cms.mjs +2 -228
- package/apps/client-cms-editor/frontend/package.json +16 -7
- package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +9 -41
- package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +19 -174
- package/apps/client-cms-editor/frontend/src/adapters/heuristic.ts +29 -0
- package/apps/client-cms-editor/frontend/src/adapters/http.ts +628 -0
- package/apps/client-cms-editor/frontend/src/adapters/memory.ts +510 -0
- package/apps/client-cms-editor/frontend/src/editor/CmsEditor.tsx +213 -0
- package/apps/client-cms-editor/frontend/src/editor/CmsEditorProvider.tsx +20 -0
- package/apps/client-cms-editor/frontend/src/editor/canvas/PreviewCanvas.tsx +53 -0
- package/apps/client-cms-editor/frontend/src/{CmsEditor.tsx → editor/legacy/CmsEditorPrototype.tsx} +52 -23
- package/apps/client-cms-editor/frontend/src/editor/useCmsEditorController.ts +218 -0
- package/apps/client-cms-editor/frontend/src/index.ts +19 -5
- package/apps/client-cms-editor/frontend/src/lib/agent-host.ts +24 -0
- package/apps/client-cms-editor/frontend/src/main.tsx +82 -8
- package/apps/client-cms-editor/frontend/src/mount.tsx +92 -30
- package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +1 -1
- package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +8 -8
- package/apps/client-cms-editor/frontend/src/styles/studio.css +55 -3
- package/apps/client-cms-editor/frontend/tsconfig.json +12 -1
- package/apps/client-cms-editor/frontend/vite.config.ts +12 -0
- package/apps/client-cms-editor/package-lock.json +973 -134
- package/apps/client-cms-editor/package.json +118 -6
- package/apps/client-cms-editor/reference/harvest/HARVEST_RECEIPT.json +201 -0
- package/apps/client-cms-editor/reference/harvest/PROVENANCE_HISTORY.txt +10 -0
- package/apps/client-cms-editor/reference/harvest/README.md +8 -0
- package/apps/client-cms-editor/reference/harvest/plans/ARCHIVE-INTAKE.md +135 -0
- package/apps/client-cms-editor/reference/harvest/plans/CHATGPT-IDENTITY-HARVEST.md +83 -0
- package/apps/client-cms-editor/reference/harvest/plans/CMS-EDITOR-HARVEST.md +166 -0
- package/apps/client-cms-editor/reference/harvest/plans/HARVEST-INDEX.md +196 -0
- package/apps/client-cms-editor/reference/harvest/plans/INNERANIMALS-CONTENT-001.md +137 -0
- package/apps/client-cms-editor/reference/harvest/plans/NO-IMPLICIT-SIDE-EFFECTS.md +87 -0
- package/apps/client-cms-editor/reference/harvest/plans/STOREFRONT-SURFACE-MAP.md +140 -0
- package/apps/client-cms-editor/reference/harvest/plans/THEME-INNERANIMALS-HARVEST.md +137 -0
- package/apps/client-cms-editor/reference/harvest/plans/TOOLING-LAB.md +63 -0
- package/apps/client-cms-editor/reference/harvest/plans/harvest-manifest.json +97 -0
- package/apps/client-cms-editor/reference/harvest/plans/local-cms-harvest-schema.sql +328 -0
- package/apps/client-cms-editor/shared/cms/package.json +17 -7
- package/apps/client-cms-editor/shared/cms/src/adapter.ts +204 -0
- package/apps/client-cms-editor/shared/cms/src/agent-context.ts +7 -5
- package/apps/client-cms-editor/shared/cms/src/editor-types.ts +32 -0
- package/apps/client-cms-editor/shared/cms/src/host.ts +82 -0
- package/apps/client-cms-editor/shared/cms/src/index.ts +4 -0
- package/apps/client-cms-editor/shared/cms/src/map.ts +115 -0
- package/apps/client-cms-editor/shared/cms/src/starter-pack.ts +158 -0
- package/contracts/source-types.v1.json +353 -0
- package/docs/CMS_CONTEXTUAL_COMPOSER.md +1 -1
- package/docs/PRODUCT_LIFECYCLE.md +566 -0
- package/docs/REPO_FILE_MAP.txt +132 -0
- package/docs/THEME_REFINERY.md +2 -2
- package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +40 -20
- package/docs/content-studio/REVISION_GATE_2026-09-27.md +1 -1
- package/docs/plans/LOCAL_STUDIO_DESKTOP_RELEASE_2026-09-29.md +150 -0
- package/migrations/d1/0017_identity_native_oauth.sql +21 -0
- package/migrations/d1/0018_goap_control_plane_remaster.sql +40 -0
- package/migrations/d1/0019_agentsam_agent_run_plan_todo.sql +14 -0
- package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +20 -9
- package/migrations/runtime/0002_goap_blackboard_v1.sql +15 -0
- package/migrations/runtime/0004_agent_run_plan_linkage.sql +8 -0
- package/native/agentsam-machine/Cargo.lock +426 -0
- package/native/agentsam-machine/Cargo.toml +9 -0
- package/native/agentsam-machine/cli/Cargo.toml +21 -0
- package/native/agentsam-machine/cli/README.md +21 -0
- package/native/agentsam-machine/cli/src/main.rs +77 -0
- package/native/agentsam-machine/core/Cargo.toml +22 -0
- package/native/agentsam-machine/core/README.md +14 -0
- package/native/agentsam-machine/core/build.rs +33 -0
- package/native/agentsam-machine/core/contracts/source-types.v1.json +353 -0
- package/native/agentsam-machine/core/src/assets.rs +790 -0
- package/native/agentsam-machine/core/src/bound.rs +298 -0
- package/native/agentsam-machine/core/src/enrich.rs +706 -0
- package/native/agentsam-machine/core/src/frontend.rs +442 -0
- package/native/agentsam-machine/core/src/lib.rs +1092 -0
- package/native/agentsam-machine/core/src/liquid.rs +528 -0
- package/native/agentsam-machine/core/src/source_types.rs +78 -0
- package/package.json +64 -24
- package/packages/agentsam-brand/README.md +1 -1
- package/packages/agentsam-brand/package.json +4 -4
- package/packages/agentsam-brand/src/index.js +1 -1
- package/packages/agentsam-contracts/package.json +13 -3
- package/packages/agentsam-contracts/src/tools.ts +22 -0
- package/packages/agentsam-errors/package.json +13 -3
- package/packages/agentsam-errors/src/index.js +1 -0
- package/packages/agentsam-errors/src/tool.js +56 -0
- package/packages/agentsam-errors/test/tool.test.mjs +58 -0
- package/packages/agentsam-goap/README.md +52 -0
- package/packages/agentsam-goap/package.json +37 -0
- package/packages/agentsam-goap/src/adapters/d1-sqlite.js +570 -0
- package/packages/agentsam-goap/src/adapters/memory.js +199 -0
- package/packages/agentsam-goap/src/contracts.js +226 -0
- package/packages/agentsam-goap/src/control-plane.js +112 -0
- package/packages/agentsam-goap/src/errors.js +157 -0
- package/packages/agentsam-goap/src/index.js +5 -0
- package/packages/agentsam-goap/src/world.js +202 -0
- package/packages/agentsam-goap/test/goap-control-plane.test.mjs +245 -0
- package/packages/agentsam-goap/test/world.test.mjs +79 -0
- package/packages/agentsam-knowledge/package.json +18 -4
- package/packages/agentsam-knowledge/src/autorag/index.js +10 -3
- package/packages/agentsam-knowledge/src/backends/index.js +33 -1
- package/packages/agentsam-knowledge/test/autorag.test.mjs +60 -1
- package/packages/agentsam-nav/dist/browser.global.js +21 -18
- package/packages/agentsam-nav/dist/browser.js +6807 -130
- package/packages/agentsam-nav/dist/index.js +6799 -122
- package/packages/agentsam-nav/package.json +24 -6
- package/packages/agentsam-queue-control/README.md +1 -1
- package/packages/agentsam-queue-control/package.json +7 -2
- package/packages/agentsam-rapid-rust/src/main.rs +1 -1
- package/packages/agentsam-repository/package.json +13 -3
- package/packages/agentsam-repository/src/goap.js +13 -14
- package/packages/agentsam-repository/src/source-types.js +8 -0
- package/packages/agentsam-repository/src/tickets.js +15 -22
- package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +19 -8
- package/packages/agentsam-vault/package.json +14 -4
- package/packages/agentsam-workbench/package.json +15 -4
- package/packages/agentsam-workbench/src/agent/ToolPermissionRequest.tsx +94 -0
- package/packages/agentsam-workbench/src/agent/index.ts +2 -0
- package/packages/agentsam-workbench/src/agent/tool-permission.css +134 -0
- package/packages/connectors/cloudflare/package.json +15 -3
- package/packages/connectors/cloudflare/src/api-client.js +3 -2
- package/packages/connectors/cloudflare/src/families/vectorize.js +127 -0
- package/packages/connectors/cloudflare/src/index.js +1 -0
- package/packages/heuristic-theme/README.md +2 -2
- package/packages/heuristic-theme/package.json +8 -3
- package/packages/heuristic-theme/src/registry.js +2 -2
- package/packages/heuristic-theme/src/theme.js +1 -1
- package/packages/heuristic-theme/test/theme.test.mjs +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +27 -7
- package/packages/identity/README.md +2 -2
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +18 -15
- package/packages/identity/migrations/apply-portable.js +109 -0
- package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +1 -1
- package/packages/identity/migrations/sqlite/005_identity_company_native.sql +52 -0
- package/packages/identity/package.json +27 -6
- package/packages/identity/schema/agentsam.identity/manifest.json +101 -0
- package/packages/identity/scripts/local-identity-bridge.mjs +13 -7
- package/packages/identity/scripts/preview-auth-portal.mjs +6 -6
- package/packages/identity/src/adapters/cloudflare-d1/index.js +8 -401
- package/packages/identity/src/adapters/iam-compat/index.js +540 -0
- package/packages/identity/src/adapters/portable-d1/index.js +18 -0
- package/packages/identity/src/adapters/portable-store.js +479 -0
- package/packages/identity/src/adapters/sqlite/index.js +13 -312
- package/packages/identity/src/contracts/auth-config.js +0 -1
- package/packages/identity/src/contracts/identity-store.js +56 -5
- package/packages/identity/src/contracts/provider.js +1 -0
- package/packages/identity/src/contracts/sign-in-options.js +104 -0
- package/packages/identity/src/core/constants.js +1 -1
- package/packages/identity/src/core/session-policy.js +31 -0
- package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -6
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +5 -5
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +5 -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 +6 -37
- package/packages/identity/src/index.js +28 -1
- package/packages/identity/src/migrations/README.md +23 -23
- package/packages/identity/src/oauth/README.md +1 -1
- package/packages/identity/src/oauth/credentials.js +10 -11
- package/packages/identity/src/oauth/google-desktop-exchange.js +195 -27
- package/packages/identity/src/oauth/iam-platform.js +21 -9
- package/packages/identity/src/oauth/native-handoff.js +136 -0
- package/packages/identity/src/providers/chatgpt/headers.js +65 -0
- package/packages/identity/src/providers/chatgpt/index.js +86 -0
- package/packages/identity/src/providers/chatgpt/mapper.js +43 -0
- package/packages/identity/src/providers/chatgpt/paths.js +45 -0
- package/packages/identity/src/providers/github/oauth.js +1 -2
- package/packages/identity/src/providers/github/profile.js +16 -2
- package/packages/identity/src/providers/index.js +11 -3
- package/packages/identity/src/server/identity-service.js +2 -1
- package/packages/identity/src/server/worker-router.js +71 -18
- package/packages/identity/tests/chatgpt-provider.test.mjs +75 -0
- package/packages/identity/tests/google-desktop-identity-login.test.mjs +210 -0
- package/packages/identity/tests/identity-init-scaffold.test.mjs +15 -4
- package/packages/identity/tests/lane1-identity-store-parity.test.mjs +527 -0
- package/packages/identity/tests/lane1-packed-consumer.test.mjs +175 -0
- package/packages/identity/tests/native-oauth-handoff.test.mjs +292 -0
- package/packages/identity/tests/oauth-credentials.test.mjs +4 -4
- package/packages/identity/tests/preview-auth-portal.test.mjs +4 -2
- package/packages/identity/tests/session-routes-policy.test.mjs +13 -1
- package/packages/identity/tests/worker-runtime-boundary.test.mjs +11 -0
- package/packages/providers/completeful/package.json +7 -2
- package/packages/theme-church-site/package.json +17 -6
- package/packages/theme-church-site/src/harvest.json +4 -2
- package/packages/theme-church-site/src/index.js +7 -3
- package/packages/theme-church-site/test/theme.test.mjs +4 -2
- package/packages/theme-companions-site/package.json +17 -6
- package/packages/theme-companions-site/src/harvest.json +4 -2
- package/packages/theme-companions-site/src/index.js +7 -3
- package/packages/theme-companions-site/test/theme.test.mjs +4 -2
- package/packages/theme-floors-site/package.json +17 -6
- package/packages/theme-floors-site/src/harvest.json +4 -2
- package/packages/theme-floors-site/src/index.js +7 -3
- package/packages/theme-floors-site/test/theme.test.mjs +4 -2
- package/packages/theme-fuelnfree-site/package.json +17 -6
- package/packages/theme-fuelnfree-site/src/harvest.json +4 -2
- package/packages/theme-fuelnfree-site/src/index.js +7 -3
- package/packages/theme-fuelnfree-site/test/theme.test.mjs +4 -2
- package/packages/theme-handyman-site/package.json +17 -6
- package/packages/theme-handyman-site/src/harvest.json +4 -2
- package/packages/theme-handyman-site/src/index.js +7 -3
- package/packages/theme-handyman-site/test/theme.test.mjs +4 -2
- package/packages/theme-insurance-site/package.json +17 -6
- package/packages/theme-insurance-site/src/harvest.json +4 -2
- package/packages/theme-insurance-site/src/index.js +7 -3
- package/packages/theme-insurance-site/test/theme.test.mjs +4 -2
- package/packages/theme-scenes/README.md +1 -1
- package/packages/theme-scenes/package.json +4 -3
- package/packages/theme-scenes/src/registry.js +187 -0
- package/packages/theme-shinshu-site/package.json +17 -6
- package/packages/theme-shinshu-site/src/harvest.json +4 -2
- package/packages/theme-shinshu-site/src/index.js +7 -3
- package/packages/theme-shinshu-site/test/theme.test.mjs +4 -2
- package/packages/work-graph/package.json +14 -4
- package/protocol/FILEMETA_V1.md +2 -2
- package/protocol/capabilities/manifest.json +1 -1
- package/protocol/database/agentsam.schema-pack.v1.schema.json +72 -0
- package/protocol/presets/catalog.json +2 -2
- package/protocol/theme-refinery/lineage-registry.json +105 -0
- package/protocol/theme-refinery/product-metadata.schema.json +21 -1
- package/python/agentsam_sdk/repository/intelligence/discovery.py +27 -2
- package/python/agentsam_sdk/repository/intelligence/git.py +4 -0
- package/python/tests/test_repository_intelligence.py +30 -0
- package/src/cli/command-catalog.js +48 -5
- package/src/cli/dispatch.js +1 -0
- package/src/cli.js +20 -1
- package/src/cloudflare/runtime-status.js +2 -1
- package/src/commands/autorag.js +67 -13
- package/src/commands/cheat-sheet.js +29 -4
- package/src/commands/codebaseindex.js +45 -2
- package/src/commands/goap-world.js +134 -0
- package/src/commands/goap.js +11 -4
- package/src/commands/knowledge.js +59 -2
- package/src/commands/machine-binary.js +109 -0
- package/src/commands/machine-runtime.js +266 -0
- package/src/commands/machine.js +208 -0
- package/src/commands/package.js +530 -0
- package/src/commands/plan-ledger.js +370 -0
- package/src/commands/plan.js +183 -0
- package/src/commands/security.js +67 -4
- package/src/commands/setup.js +33 -16
- package/src/commands/skill.js +78 -17
- package/src/commands/status.js +8 -1
- package/src/features/resolve.js +1 -0
- package/src/knowledge/engine.js +21 -2
- package/src/knowledge/runtime-discovery.js +127 -0
- package/src/knowledge/source.js +1 -1
- package/src/lib/identity-scaffold.js +53 -13
- package/src/lib/setup/recipes.js +1 -1
- package/src/lib/slash-commands.js +1 -1
- package/src/local/runtime-store.js +24 -2
- package/src/local/sqlite.js +17 -0
- package/src/models/discovery.js +40 -22
- package/src/models/inventory-core.d.ts +105 -0
- package/src/models/inventory-core.js +54 -6
- package/src/sam/operations/package-audit.js +41 -0
- package/src/sam/seed.js +2 -0
- package/src/security/logs.js +3 -0
- package/src/ui/cli/help.js +41 -0
- package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +0 -145
- package/test/account-session.test.mjs +0 -101
- package/test/agent-capabilities.test.mjs +0 -67
- package/test/app-authority-context.test.mjs +0 -32
- package/test/app-building-skills.test.mjs +0 -61
- package/test/apps-scaffold-contract.test.mjs +0 -114
- package/test/blender-cad.test.mjs +0 -146
- package/test/cad-docker.test.mjs +0 -96
- package/test/capabilities.test.mjs +0 -133
- package/test/cli/api-key-env-whoami.test.mjs +0 -129
- package/test/cli/codebaseindex-plan-ux.test.mjs +0 -37
- package/test/cli/eval-live.test.mjs +0 -219
- package/test/cli/go.test.mjs +0 -128
- package/test/cli/local-vault-and-provider-setup.test.mjs +0 -268
- package/test/cli/mcp-client.test.mjs +0 -256
- package/test/cli/preferences-runtime.test.mjs +0 -11
- package/test/cli/runtime-persist.test.mjs +0 -56
- package/test/cli/runtime-ui.test.mjs +0 -141
- package/test/cli/rust-command.test.mjs +0 -21
- package/test/cli/skill-npm-and-env.test.mjs +0 -52
- package/test/cli/status-actions.test.mjs +0 -88
- package/test/cli/wireframes-go-registry.test.mjs +0 -139
- package/test/cli-preferences.test.mjs +0 -46
- package/test/cloudflare-connector.test.mjs +0 -93
- package/test/cloudflare-runtime.test.mjs +0 -82
- package/test/context.test.mjs +0 -159
- package/test/credentials-audit.test.mjs +0 -113
- package/test/deploy-health-scan.test.mjs +0 -95
- package/test/deploy-receipt.test.mjs +0 -91
- package/test/dockerize.test.mjs +0 -93
- package/test/error-diagnostics.test.mjs +0 -124
- package/test/eval-context.test.mjs +0 -37
- package/test/execution-approvals.test.mjs +0 -27
- package/test/fixtures/cad/courtyard-house.json +0 -208
- package/test/fixtures/knowledge-rpc-worker.mjs +0 -16
- package/test/gcloud-auth.test.mjs +0 -111
- package/test/go/build-source-identity.test.mjs +0 -31
- package/test/go/cloudflare-probe.test.mjs +0 -317
- package/test/go/distribution.test.mjs +0 -28
- package/test/google-cloud-connection.test.mjs +0 -83
- package/test/google-cloud-inventory.test.mjs +0 -64
- package/test/indexing-provider.test.mjs +0 -29
- package/test/init-options.test.mjs +0 -35
- package/test/integration/ai-access-onboarding.test.mjs +0 -47
- package/test/integration/app-command.test.mjs +0 -85
- package/test/integration/cad-discovery.test.mjs +0 -158
- package/test/integration/cad-docker-executor.test.mjs +0 -249
- package/test/integration/cad-execution.test.mjs +0 -184
- package/test/integration/cad-project-app.test.mjs +0 -31
- package/test/integration/cad-project-d1.test.mjs +0 -25
- package/test/integration/cad-project-native.test.mjs +0 -24
- package/test/integration/cad-project-workflow.test.mjs +0 -9
- package/test/integration/cad-project.test.mjs +0 -85
- package/test/integration/cli-help.test.mjs +0 -41
- package/test/integration/cms-app-scaffold.test.mjs +0 -71
- package/test/integration/cms-site-tenancy-contract.test.mjs +0 -257
- package/test/integration/codebaseindex-ingest.test.mjs +0 -214
- package/test/integration/core-client.integration.test.mjs +0 -55
- package/test/integration/error-runtime-rpc.test.mjs +0 -71
- package/test/integration/features-resolve.test.mjs +0 -147
- package/test/integration/icon-registry.test.mjs +0 -67
- package/test/integration/ingest-discover-models.test.mjs +0 -30
- package/test/integration/inspect-path-cli.test.mjs +0 -46
- package/test/integration/install-script.test.mjs +0 -110
- package/test/integration/inventory-core.test.mjs +0 -53
- package/test/integration/inventory-evidence.test.mjs +0 -125
- package/test/integration/knowledge-rpc.test.mjs +0 -112
- package/test/integration/local-fs.test.mjs +0 -113
- package/test/integration/merkle-cli.test.mjs +0 -61
- package/test/integration/merkle-persistence-identity.test.mjs +0 -48
- package/test/integration/plugins-cloudflare.integration.test.mjs +0 -28
- package/test/integration/provider-env-cli.test.mjs +0 -50
- package/test/integration/provider-factory.test.mjs +0 -197
- package/test/integration/repository-company-graph.test.mjs +0 -90
- package/test/integration/runtime-migrations.test.mjs +0 -87
- package/test/integration/runtime-status.integration.test.mjs +0 -212
- package/test/integration/sam-activity-recovery.test.mjs +0 -147
- package/test/integration/sam-decision.test.mjs +0 -584
- package/test/integration/sam-kernel.test.mjs +0 -99
- package/test/integration/sam-planning-astar.test.mjs +0 -279
- package/test/integration/scaffold-cloudflare.test.mjs +0 -46
- package/test/integration/skill-runtime.test.mjs +0 -240
- package/test/integration/storage-architecture.test.mjs +0 -154
- package/test/integration/store-discovery.test.mjs +0 -44
- package/test/integration/studio-fs-pty-e2e.test.mjs +0 -294
- package/test/integration/terminal-exec.integration.test.mjs +0 -86
- package/test/integration/tool-runtime.test.mjs +0 -124
- package/test/integration/tool-schema.test.mjs +0 -59
- package/test/jr-dev-skill.test.mjs +0 -26
- package/test/knowledge-context-pack.test.mjs +0 -19
- package/test/knowledge-postgres.test.mjs +0 -40
- package/test/knowledge-service.test.mjs +0 -110
- package/test/knowledge.test.mjs +0 -206
- package/test/live/terminal-transport.live.test.mjs +0 -24
- package/test/local-sessions.test.mjs +0 -57
- package/test/local-studio-deploy.test.mjs +0 -83
- package/test/loopback-oauth.test.mjs +0 -53
- package/test/merkle-render.test.mjs +0 -31
- package/test/mini.test.mjs +0 -140
- package/test/model-catalog.test.mjs +0 -70
- package/test/models.test.mjs +0 -309
- package/test/npm10-lock.test.mjs +0 -29
- package/test/ollama.test.mjs +0 -137
- package/test/open-url.test.mjs +0 -64
- package/test/openai-responses.test.mjs +0 -155
- package/test/portable-context.test.mjs +0 -94
- package/test/project-config.test.mjs +0 -81
- package/test/project-rules.test.mjs +0 -44
- package/test/provider-credentials.test.mjs +0 -106
- package/test/rehydrate.test.mjs +0 -25
- package/test/release-hygiene.test.mjs +0 -42
- package/test/repository-snapshot-view.test.mjs +0 -112
- package/test/responses-runner.test.mjs +0 -465
- package/test/runtime-activity.test.mjs +0 -98
- package/test/sdk-worker-contract.test.mjs +0 -72
- package/test/security.test.mjs +0 -252
- package/test/setup-planner.test.mjs +0 -74
- package/test/setup-runtime.test.mjs +0 -51
- package/test/shell.test.mjs +0 -281
- package/test/skills.test.mjs +0 -22
- package/test/smoke.mjs +0 -122
- package/test/telemetry.test.mjs +0 -79
- package/test/terminal/local-pty.mock.test.mjs +0 -153
- package/test/terminal-machine-identity.test.mjs +0 -88
- package/test/theme-portability.test.mjs +0 -14
- package/test/tools-search.test.mjs +0 -73
- package/test/unit/website-assets-bindings.test.mjs +0 -60
- package/test/whoami-resume.test.mjs +0 -157
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>Reset password
|
|
7
|
+
<title>Reset password</title>
|
|
8
8
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap"
|
|
9
9
|
rel="stylesheet">
|
|
10
10
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
|
@@ -280,8 +280,8 @@
|
|
|
280
280
|
<div class="login-card">
|
|
281
281
|
<img
|
|
282
282
|
class="auth-logo"
|
|
283
|
-
src="/shared/
|
|
284
|
-
alt="
|
|
283
|
+
src="/shared/app-icon.png"
|
|
284
|
+
alt="Sign in"
|
|
285
285
|
style="width:120px;height:120px;object-fit:contain;display:block;margin:0 auto 20px;"
|
|
286
286
|
/>
|
|
287
287
|
|
|
@@ -290,7 +290,7 @@
|
|
|
290
290
|
<p class="subtitle">We'll send you a secure verification code.</p>
|
|
291
291
|
|
|
292
292
|
<div class="email-note">
|
|
293
|
-
You'll receive an email from <strong data-company-support-email>support@
|
|
293
|
+
You'll receive an email from <strong data-company-support-email>support@example.com</strong>.<br>
|
|
294
294
|
Check your inbox and spam folder.
|
|
295
295
|
</div>
|
|
296
296
|
|
|
@@ -365,7 +365,7 @@
|
|
|
365
365
|
</div>
|
|
366
366
|
|
|
367
367
|
<footer class="auth-min-footer" aria-label="Legal">
|
|
368
|
-
<span data-company-name>
|
|
368
|
+
<span data-company-name>App</span>
|
|
369
369
|
<span class="auth-min-footer-sep" aria-hidden="true">|</span>
|
|
370
370
|
<a href="/privacy">Privacy</a>
|
|
371
371
|
<span class="auth-min-footer-sep" aria-hidden="true">|</span>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>Sign up
|
|
7
|
+
<title>Sign up</title>
|
|
8
8
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap"
|
|
9
9
|
rel="stylesheet">
|
|
10
10
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
|
@@ -398,12 +398,12 @@
|
|
|
398
398
|
<div class="login-card">
|
|
399
399
|
<img
|
|
400
400
|
class="auth-logo"
|
|
401
|
-
src="/shared/
|
|
402
|
-
alt="
|
|
401
|
+
src="/shared/app-icon.png"
|
|
402
|
+
alt="Sign in"
|
|
403
403
|
/>
|
|
404
404
|
|
|
405
405
|
<h1>Create account</h1>
|
|
406
|
-
<p class="subtitle" data-company-subtitle="signup">
|
|
406
|
+
<p class="subtitle" data-company-subtitle="signup">Create an account</p>
|
|
407
407
|
<p id="registeredMsg" class="subtitle" style="color: #10B981; display: none; margin-top: -16px; margin-bottom: 16px;">Account created. Sign in below.</p>
|
|
408
408
|
<p id="oauthErrorMsg" class="subtitle" style="color: #FF3B30; display: none; margin-top: -16px; margin-bottom: 16px;"></p>
|
|
409
409
|
<p id="cfConnectNotice" class="subtitle" style="color: #fdba74; display: none; margin-top: -12px; margin-bottom: 12px; font-size: 12px; line-height: 1.45; text-align: center; max-width: 320px;">Sign in with Google, GitHub, or Supabase first, then connect Cloudflare from Integrations.</p>
|
|
@@ -485,7 +485,7 @@
|
|
|
485
485
|
</div>
|
|
486
486
|
|
|
487
487
|
<footer class="auth-min-footer" aria-label="Legal">
|
|
488
|
-
<span data-company-name>
|
|
488
|
+
<span data-company-name>App</span>
|
|
489
489
|
<span class="auth-min-footer-sep" aria-hidden="true">|</span>
|
|
490
490
|
<a href="/privacy">Privacy</a>
|
|
491
491
|
<span class="auth-min-footer-sep" aria-hidden="true">|</span>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auth portal branding from D1 `company` via GET /api/company.
|
|
3
|
-
* Static HTML keeps portable
|
|
3
|
+
* Static HTML keeps neutral portable defaults as fallback when host branding is unavailable.
|
|
4
4
|
*/
|
|
5
5
|
(function () {
|
|
6
6
|
var SUBTITLE_PREFIX = {
|
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
var invoke = getInvoke();
|
|
13
13
|
if (!invoke) return;
|
|
14
14
|
|
|
15
|
-
var APP_ID = 'local-studio';
|
|
16
|
-
var SESSION_ACCOUNT = 'identity_session';
|
|
17
15
|
var originalFetch = window.fetch.bind(window);
|
|
18
16
|
|
|
19
17
|
async function callIdentity(payload) {
|
|
@@ -27,29 +25,6 @@
|
|
|
27
25
|
return body;
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
async function getSessionId() {
|
|
31
|
-
return await invoke('secure_store_get', {
|
|
32
|
-
appId: APP_ID,
|
|
33
|
-
account: SESSION_ACCOUNT,
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function setSessionId(sessionId) {
|
|
38
|
-
await invoke('secure_store_set', {
|
|
39
|
-
appId: APP_ID,
|
|
40
|
-
account: SESSION_ACCOUNT,
|
|
41
|
-
value: String(sessionId || ''),
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async function clearSessionId() {
|
|
46
|
-
try {
|
|
47
|
-
await invoke('secure_store_delete', {
|
|
48
|
-
appId: APP_ID,
|
|
49
|
-
account: SESSION_ACCOUNT,
|
|
50
|
-
});
|
|
51
|
-
} catch {}
|
|
52
|
-
}
|
|
53
28
|
|
|
54
29
|
function jsonResponse(body, status) {
|
|
55
30
|
return new Response(JSON.stringify(body), {
|
|
@@ -87,9 +62,9 @@
|
|
|
87
62
|
|
|
88
63
|
if (url.pathname === '/api/company') {
|
|
89
64
|
return jsonResponse({
|
|
90
|
-
name: '
|
|
91
|
-
tagline: '
|
|
92
|
-
logoUrl: '/shared/
|
|
65
|
+
name: 'App',
|
|
66
|
+
tagline: 'Welcome',
|
|
67
|
+
logoUrl: '/shared/app-icon.png',
|
|
93
68
|
authBgColor: '#050508',
|
|
94
69
|
});
|
|
95
70
|
}
|
|
@@ -103,7 +78,6 @@
|
|
|
103
78
|
password: loginBody.password,
|
|
104
79
|
next: loginBody.next || '/agentsam',
|
|
105
80
|
});
|
|
106
|
-
await setSessionId(login.session_id);
|
|
107
81
|
notifyAuthenticated(login);
|
|
108
82
|
return jsonResponse({ ok: true, user: login.user, redirect: '/agentsam' });
|
|
109
83
|
} catch (error) {
|
|
@@ -121,7 +95,6 @@
|
|
|
121
95
|
displayName: signupBody.name || signupBody.displayName || signupBody.display_name,
|
|
122
96
|
next: signupBody.next || '/agentsam',
|
|
123
97
|
});
|
|
124
|
-
await setSessionId(signup.session_id);
|
|
125
98
|
notifyAuthenticated(signup);
|
|
126
99
|
return jsonResponse({ ok: true, user: signup.user, redirect: '/agentsam' });
|
|
127
100
|
} catch (error) {
|
|
@@ -159,13 +132,9 @@
|
|
|
159
132
|
}
|
|
160
133
|
|
|
161
134
|
if (url.pathname === '/api/auth/logout') {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
await callIdentity({ op: 'logout', session_id: sessionId });
|
|
166
|
-
} catch {}
|
|
167
|
-
}
|
|
168
|
-
await clearSessionId();
|
|
135
|
+
try {
|
|
136
|
+
await callIdentity({ op: 'logout' });
|
|
137
|
+
} catch {}
|
|
169
138
|
return jsonResponse({ ok: true });
|
|
170
139
|
}
|
|
171
140
|
|
|
@@ -21,7 +21,21 @@ import {
|
|
|
21
21
|
GcpProvider,
|
|
22
22
|
EmailProvider,
|
|
23
23
|
CloudflareProvider,
|
|
24
|
+
ChatGptProvider,
|
|
24
25
|
} from './providers/index.js';
|
|
26
|
+
import {
|
|
27
|
+
STOCK_SIGN_IN_OPTIONS,
|
|
28
|
+
CMS_STOCK_SIGN_IN_IDS,
|
|
29
|
+
listStockSignInOptions,
|
|
30
|
+
getStockSignInOption,
|
|
31
|
+
} from './contracts/sign-in-options.js';
|
|
32
|
+
import {
|
|
33
|
+
createChatGptCmsAuthHost,
|
|
34
|
+
normalizeChatGptIdentity,
|
|
35
|
+
readChatGptUserFromHeaders,
|
|
36
|
+
chatGPTSignInPath,
|
|
37
|
+
chatGPTSignOutPath,
|
|
38
|
+
} from './providers/chatgpt/index.js';
|
|
25
39
|
|
|
26
40
|
export {
|
|
27
41
|
IdentityContractVersion,
|
|
@@ -40,6 +54,16 @@ export {
|
|
|
40
54
|
GcpProvider,
|
|
41
55
|
EmailProvider,
|
|
42
56
|
CloudflareProvider,
|
|
57
|
+
ChatGptProvider,
|
|
58
|
+
STOCK_SIGN_IN_OPTIONS,
|
|
59
|
+
CMS_STOCK_SIGN_IN_IDS,
|
|
60
|
+
listStockSignInOptions,
|
|
61
|
+
getStockSignInOption,
|
|
62
|
+
createChatGptCmsAuthHost,
|
|
63
|
+
normalizeChatGptIdentity,
|
|
64
|
+
readChatGptUserFromHeaders,
|
|
65
|
+
chatGPTSignInPath,
|
|
66
|
+
chatGPTSignOutPath,
|
|
43
67
|
};
|
|
44
68
|
|
|
45
69
|
export * from './core/index.js';
|
|
@@ -88,11 +112,14 @@ export {
|
|
|
88
112
|
handleGoogleDesktopExchangeRequest,
|
|
89
113
|
resolveGoogleExchangeSecret,
|
|
90
114
|
} from './oauth/google-desktop-exchange.js';
|
|
91
|
-
export { createCloudflareD1Adapter } from './adapters/cloudflare-d1/index.js';
|
|
115
|
+
export { createCloudflareD1Adapter, createIamCompatIdentityAdapter } from './adapters/cloudflare-d1/index.js';
|
|
92
116
|
export {
|
|
93
117
|
createSqliteIdentityAdapter,
|
|
94
118
|
applySqliteIdentityMigrations,
|
|
119
|
+
applyPortableIdentityMigrations,
|
|
120
|
+
resolveIdentitySchemaPack,
|
|
95
121
|
} from './adapters/sqlite/index.js';
|
|
122
|
+
export { createPortableD1IdentityAdapter } from './adapters/portable-d1/index.js';
|
|
96
123
|
export { createIdentityService } from './server/identity-service.js';
|
|
97
124
|
export { handleIdentityWorkerRequest } from './server/worker-router.js';
|
|
98
125
|
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
# Identity
|
|
1
|
+
# Identity migrations under `src/migrations/` — IAM-compat scaffold / history
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**This tree is NOT the portable customer D1 authority.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
| Path | Authority |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `packages/identity/migrations/sqlite/` | **Portable** `identity_*` SQL SSOT (`agentsam.identity` pack) |
|
|
8
|
+
| `packages/identity/src/migrations/` | **IAM-shaped** scaffold / history (accounts, auth_users, company, …) |
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
# local
|
|
9
|
-
wrangler d1 execute <database_name> --local --file=migrations/0001_identity_core.sql
|
|
10
|
+
## When to use which
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
| Audience | Adapter | Schema |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| New customer clean D1 / local SQLite | `createSqliteIdentityAdapter` / `createPortableD1IdentityAdapter` | Portable pack via `applyPortableIdentityMigrations` |
|
|
15
|
+
| Existing InnerAnimalMedia / Local Studio hosted DB | `createIamCompatIdentityAdapter` (`createCloudflareD1Adapter` alias) | Live IAM tables — do not rename for portability |
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Existing scaffolds missing `accounts`: also apply `0003_accounts_ssot.sql`.
|
|
18
|
-
|
|
19
|
-
## Tables
|
|
17
|
+
## IAM-shaped tables in this directory
|
|
20
18
|
|
|
21
19
|
| Table | Purpose |
|
|
22
20
|
|-------|---------|
|
|
23
|
-
| `accounts` |
|
|
24
|
-
| `auth_users` | Login principal
|
|
25
|
-
| `auth_sessions` | Browser sessions |
|
|
26
|
-
| `account_identities` | IdP linkage
|
|
27
|
-
| `oauth_states` | PKCE/state
|
|
28
|
-
| `password_reset_tokens` |
|
|
29
|
-
| `company` |
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
| `accounts` | Account SSOT on hosted IAM |
|
|
22
|
+
| `auth_users` | Login principal |
|
|
23
|
+
| `auth_sessions` | Browser/desktop sessions |
|
|
24
|
+
| `account_identities` | IdP linkage |
|
|
25
|
+
| `oauth_states` | Historical PKCE/state (note: missing `app_id` vs portable invariant) |
|
|
26
|
+
| `password_reset_tokens` | Historical SQL reset tokens — runtime recovery uses KV/`createPasswordResetService` |
|
|
27
|
+
| `company` | Hosted branding table |
|
|
28
|
+
|
|
29
|
+
New generic scaffolds must be generated from the **portable** `agentsam.identity` pack, not by copying this tree as “portable D1.”
|
|
30
|
+
|
|
31
|
+
Preserve these files for IAM-compat fixtures and historical feature resources. Do not delete until Lane 1 parity is proven and call sites no longer need them.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|------|----------|------|
|
|
5
5
|
| **IAM platform (default)** | `IAM_CLIENT_ID` + `IAM_CLIENT_SECRET` | Minted at install/build for every customer worker |
|
|
6
6
|
| Developer Google (web) | `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` | Takes `/api/oauth/google/start` when set |
|
|
7
|
-
| Google Desktop / CLI | `GOOGLE_DESKTOP_CLIENT_ID`
|
|
7
|
+
| Google Desktop / CLI | `GOOGLE_DESKTOP_CLIENT_ID` | Public Authorization Code + PKCE with loopback redirect; no desktop secret |
|
|
8
8
|
| Developer GitHub | `GITHUB_CLIENT_ID` + `GITHUB_CLIENT_SECRET` | Takes `/api/oauth/github/start` when set |
|
|
9
9
|
| Cloudflare sign-in | `CLOUDFLARE_OAUTH_CLIENT_ID` (+ optional secret) | Takes `/api/oauth/cloudflare/start` when set |
|
|
10
10
|
|
|
@@ -89,12 +89,11 @@ export function resolveOAuthCredentialLane(env, provider) {
|
|
|
89
89
|
|
|
90
90
|
if (key === 'google_desktop') {
|
|
91
91
|
const clientId = String(env?.GOOGLE_DESKTOP_CLIENT_ID || '').trim();
|
|
92
|
-
const clientSecret = String(env?.GOOGLE_DESKTOP_CLIENT_SECRET || '').trim();
|
|
93
92
|
if (clientId) {
|
|
94
93
|
return {
|
|
95
94
|
lane: 'byok_google_desktop',
|
|
96
95
|
clientId,
|
|
97
|
-
clientSecret,
|
|
96
|
+
clientSecret: '',
|
|
98
97
|
provider: 'google_desktop',
|
|
99
98
|
};
|
|
100
99
|
}
|
|
@@ -122,18 +121,18 @@ export function resolveOAuthCredentialLane(env, provider) {
|
|
|
122
121
|
return null;
|
|
123
122
|
}
|
|
124
123
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
if (key === 'chatgpt' || key === 'openai' || key === 'chatgpt_hosted') {
|
|
125
|
+
// Hosted Apps SDK identity — no OAuth client secret. Selection is always
|
|
126
|
+
// available; runtime proof comes from oai-authenticated-* request headers.
|
|
128
127
|
return {
|
|
129
|
-
lane: '
|
|
130
|
-
clientId:
|
|
131
|
-
clientSecret:
|
|
132
|
-
|
|
133
|
-
issuer: iam.issuer,
|
|
134
|
-
provider: 'inneranimalmedia',
|
|
128
|
+
lane: 'hosted_chatgpt',
|
|
129
|
+
clientId: String(env?.CHATGPT_APP_ID || env?.OPENAI_APP_ID || 'chatgpt-hosted').trim(),
|
|
130
|
+
clientSecret: '',
|
|
131
|
+
provider: 'chatgpt',
|
|
135
132
|
};
|
|
136
133
|
}
|
|
137
134
|
|
|
135
|
+
// Provider selection is fail-closed. A Google or GitHub button must never
|
|
136
|
+
// silently become InnerAnimalMedia/IAM. IAM remains an explicit provider.
|
|
138
137
|
return null;
|
|
139
138
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { fetchGoogleProfile } from '../providers/google/profile.js';
|
|
2
|
+
import { SESSION_TYPES } from '../core/session-policy.js';
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Server-side Google token exchange for CLI / desktop PKCE.
|
|
3
6
|
*
|
|
4
|
-
* Desktop/"installed" OAuth clients
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* Desktop/"installed" OAuth clients are public PKCE clients. Some Google
|
|
8
|
+
* installed-app credentials still include a provider-issued client_secret.
|
|
9
|
+
* That value is not a confidentiality boundary, but if Google requires it for
|
|
10
|
+
* token exchange the service may keep it in GOOGLE_DESKTOP_CLIENT_SECRET.
|
|
11
|
+
* Hosted web OAuth remains confidential and uses GOOGLE_CLIENT_SECRET.
|
|
8
12
|
*/
|
|
9
13
|
|
|
10
14
|
const GOOGLE_TOKEN_URL = 'https://oauth2.googleapis.com/token';
|
|
@@ -40,17 +44,18 @@ export function resolveGoogleExchangeSecret(env, clientId) {
|
|
|
40
44
|
const id = clean(clientId);
|
|
41
45
|
const desktopId = clean(env?.GOOGLE_DESKTOP_CLIENT_ID);
|
|
42
46
|
const webId = clean(env?.GOOGLE_CLIENT_ID);
|
|
43
|
-
const desktopSecret = clean(env?.GOOGLE_DESKTOP_CLIENT_SECRET);
|
|
44
47
|
const webSecret = clean(env?.GOOGLE_CLIENT_SECRET);
|
|
48
|
+
const desktopSecret = clean(env?.GOOGLE_DESKTOP_CLIENT_SECRET);
|
|
45
49
|
|
|
46
|
-
if (id && desktopId && id === desktopId && desktopSecret) {
|
|
47
|
-
return { clientId: id, clientSecret: desktopSecret, mode: 'desktop_with_optional_secret' };
|
|
48
|
-
}
|
|
49
50
|
if (id && webId && id === webId && webSecret) {
|
|
50
51
|
return { clientId: id, clientSecret: webSecret, mode: 'web_confidential' };
|
|
51
52
|
}
|
|
52
53
|
if (id && desktopId && id === desktopId) {
|
|
53
|
-
return {
|
|
54
|
+
return {
|
|
55
|
+
clientId: id,
|
|
56
|
+
clientSecret: desktopSecret || null,
|
|
57
|
+
mode: 'desktop_public_pkce',
|
|
58
|
+
};
|
|
54
59
|
}
|
|
55
60
|
return { clientId: id || null, clientSecret: null, mode: 'unknown_client' };
|
|
56
61
|
}
|
|
@@ -135,24 +140,6 @@ export async function handleGoogleDesktopExchangeRequest(request, env, opts = {}
|
|
|
135
140
|
});
|
|
136
141
|
|
|
137
142
|
const detail = String(result.data?.error_description || result.data?.error || '');
|
|
138
|
-
if (
|
|
139
|
-
!result.ok
|
|
140
|
-
&& /client_secret/i.test(detail)
|
|
141
|
-
&& resolved.mode === 'desktop_public_pkce'
|
|
142
|
-
&& !resolved.clientSecret
|
|
143
|
-
) {
|
|
144
|
-
return json({
|
|
145
|
-
ok: false,
|
|
146
|
-
error: 'desktop_client_requires_secret',
|
|
147
|
-
detail,
|
|
148
|
-
remediation: [
|
|
149
|
-
'In Google Cloud Console create OAuth client type Desktop app (no secret) and set GOOGLE_DESKTOP_CLIENT_ID to that client id.',
|
|
150
|
-
'Or if this client id is a Web app, put its secret on the Worker: wrangler secret put GOOGLE_DESKTOP_CLIENT_SECRET',
|
|
151
|
-
'Web browser login continues to use GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET.',
|
|
152
|
-
],
|
|
153
|
-
}, 502);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
143
|
if (!result.ok) {
|
|
157
144
|
return json({
|
|
158
145
|
ok: false,
|
|
@@ -171,3 +158,184 @@ export async function handleGoogleDesktopExchangeRequest(request, env, opts = {}
|
|
|
171
158
|
exchange_mode: resolved.mode,
|
|
172
159
|
});
|
|
173
160
|
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
export const GOOGLE_DESKTOP_LOGIN_EXCHANGE_PATH = '/api/oauth/google/desktop-login-exchange';
|
|
164
|
+
const GOOGLE_ID_TOKEN_INFO_URL = 'https://oauth2.googleapis.com/tokeninfo';
|
|
165
|
+
|
|
166
|
+
async function verifyGoogleDesktopIdToken(idToken, clientId, fetchImpl = fetch) {
|
|
167
|
+
const url = new URL(GOOGLE_ID_TOKEN_INFO_URL);
|
|
168
|
+
url.searchParams.set('id_token', clean(idToken));
|
|
169
|
+
const response = await fetchImpl(url, {
|
|
170
|
+
headers: { Accept: 'application/json' },
|
|
171
|
+
});
|
|
172
|
+
const data = await response.json().catch(() => ({}));
|
|
173
|
+
if (!response.ok) {
|
|
174
|
+
return {
|
|
175
|
+
ok: false,
|
|
176
|
+
error: 'google_id_token_invalid',
|
|
177
|
+
detail: clean(data.error_description || data.error),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const audience = clean(data.aud);
|
|
182
|
+
const issuer = clean(data.iss);
|
|
183
|
+
const expiresAt = Number(data.exp || 0);
|
|
184
|
+
const emailVerified = data.email_verified === true || String(data.email_verified) === 'true';
|
|
185
|
+
|
|
186
|
+
if (audience !== clean(clientId)) {
|
|
187
|
+
return { ok: false, error: 'google_id_token_audience_mismatch' };
|
|
188
|
+
}
|
|
189
|
+
if (!['accounts.google.com', 'https://accounts.google.com'].includes(issuer)) {
|
|
190
|
+
return { ok: false, error: 'google_id_token_issuer_invalid' };
|
|
191
|
+
}
|
|
192
|
+
if (!Number.isFinite(expiresAt) || expiresAt <= Math.floor(Date.now() / 1000)) {
|
|
193
|
+
return { ok: false, error: 'google_id_token_expired' };
|
|
194
|
+
}
|
|
195
|
+
if (!emailVerified) {
|
|
196
|
+
return { ok: false, error: 'google_email_not_verified' };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return { ok: true, data };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Google Desktop account identity handoff.
|
|
204
|
+
*
|
|
205
|
+
* The installed app is the public OAuth client. It performs Google
|
|
206
|
+
* Authorization Code + PKCE + loopback; this endpoint receives the one-time
|
|
207
|
+
* code + verifier, performs the provider token exchange, validates the Google
|
|
208
|
+
* ID token against GOOGLE_DESKTOP_CLIENT_ID, resolves the profile, and mints
|
|
209
|
+
* the normal AgentSam desktop session. No Google access token is persisted in
|
|
210
|
+
* the desktop app for identity-only sign-in.
|
|
211
|
+
*/
|
|
212
|
+
export async function handleGoogleDesktopLoginExchangeRequest(request, env, opts = {}) {
|
|
213
|
+
if (request.method !== 'POST') {
|
|
214
|
+
return json({ ok: false, error: 'method_not_allowed' }, 405);
|
|
215
|
+
}
|
|
216
|
+
const identity = opts.identity;
|
|
217
|
+
const adapter = opts.adapter;
|
|
218
|
+
if (!identity || !adapter) {
|
|
219
|
+
return json({ ok: false, error: 'identity_service_unavailable' }, 503);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
let payload = {};
|
|
223
|
+
try {
|
|
224
|
+
payload = await request.json();
|
|
225
|
+
} catch {
|
|
226
|
+
return json({ ok: false, error: 'invalid_json' }, 400);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
let accessToken = clean(payload.access_token || payload.accessToken);
|
|
230
|
+
let idToken = clean(payload.id_token || payload.idToken);
|
|
231
|
+
const clientId = clean(payload.client_id || payload.clientId);
|
|
232
|
+
|
|
233
|
+
const desktopId = clean(env?.GOOGLE_DESKTOP_CLIENT_ID);
|
|
234
|
+
if (!desktopId || !clientId || clientId !== desktopId) {
|
|
235
|
+
return json({ ok: false, error: 'google_desktop_client_id_required' }, 403);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!accessToken || !idToken) {
|
|
239
|
+
const code = clean(payload.code);
|
|
240
|
+
const codeVerifier = clean(payload.code_verifier || payload.codeVerifier);
|
|
241
|
+
const redirectUri = clean(payload.redirect_uri || payload.redirectUri);
|
|
242
|
+
if (!code || !codeVerifier || !redirectUri) {
|
|
243
|
+
return json({
|
|
244
|
+
ok: false,
|
|
245
|
+
error: 'code_code_verifier_redirect_uri_required',
|
|
246
|
+
}, 400);
|
|
247
|
+
}
|
|
248
|
+
if (!isLoopbackRedirect(redirectUri)) {
|
|
249
|
+
return json({ ok: false, error: 'redirect_uri_must_be_loopback' }, 400);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const resolved = resolveGoogleExchangeSecret(env, clientId);
|
|
253
|
+
const exchanged = await exchangeGoogleAuthorizationCode({
|
|
254
|
+
code,
|
|
255
|
+
codeVerifier,
|
|
256
|
+
clientId,
|
|
257
|
+
redirectUri,
|
|
258
|
+
clientSecret: resolved.clientSecret,
|
|
259
|
+
fetchImpl: opts.fetchImpl || fetch,
|
|
260
|
+
});
|
|
261
|
+
if (!exchanged.ok) {
|
|
262
|
+
return json({
|
|
263
|
+
ok: false,
|
|
264
|
+
error: 'google_token_exchange_failed',
|
|
265
|
+
detail: clean(
|
|
266
|
+
exchanged.data?.error_description
|
|
267
|
+
|| exchanged.data?.error
|
|
268
|
+
|| ('http_' + exchanged.status),
|
|
269
|
+
),
|
|
270
|
+
}, 502);
|
|
271
|
+
}
|
|
272
|
+
accessToken = clean(exchanged.data?.access_token);
|
|
273
|
+
idToken = clean(exchanged.data?.id_token);
|
|
274
|
+
if (!accessToken || !idToken) {
|
|
275
|
+
return json({ ok: false, error: 'google_token_payload_incomplete' }, 502);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const verified = await verifyGoogleDesktopIdToken(
|
|
280
|
+
idToken,
|
|
281
|
+
clientId,
|
|
282
|
+
opts.fetchImpl || fetch,
|
|
283
|
+
);
|
|
284
|
+
if (!verified.ok) {
|
|
285
|
+
return json({
|
|
286
|
+
ok: false,
|
|
287
|
+
error: verified.error,
|
|
288
|
+
detail: verified.detail || null,
|
|
289
|
+
}, 401);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const profile = opts.fetchProfile
|
|
293
|
+
? await opts.fetchProfile(accessToken)
|
|
294
|
+
: await fetchGoogleProfile(accessToken);
|
|
295
|
+
if (!profile?.sub) {
|
|
296
|
+
return json({ ok: false, error: 'google_userinfo_failed' }, 502);
|
|
297
|
+
}
|
|
298
|
+
if (clean(verified.data.sub) && clean(verified.data.sub) !== clean(profile.sub)) {
|
|
299
|
+
return json({ ok: false, error: 'google_subject_mismatch' }, 401);
|
|
300
|
+
}
|
|
301
|
+
if (
|
|
302
|
+
clean(verified.data.email) &&
|
|
303
|
+
clean(profile.email) &&
|
|
304
|
+
clean(verified.data.email).toLowerCase() !== clean(profile.email).toLowerCase()
|
|
305
|
+
) {
|
|
306
|
+
return json({ ok: false, error: 'google_email_mismatch' }, 401);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const provisioned = await identity.provisionOAuthUser({
|
|
310
|
+
provider: 'google',
|
|
311
|
+
providerSubject: String(profile.sub),
|
|
312
|
+
email: profile.email || verified.data.email || null,
|
|
313
|
+
displayName: profile.name || profile.email || verified.data.email || null,
|
|
314
|
+
sessionType: SESSION_TYPES.DESKTOP,
|
|
315
|
+
});
|
|
316
|
+
const user = await adapter.findUserById(provisioned.authUserId);
|
|
317
|
+
await adapter.logAuthEvent?.({
|
|
318
|
+
userId: provisioned.authUserId,
|
|
319
|
+
eventType: 'login',
|
|
320
|
+
status: 'ok',
|
|
321
|
+
provider: 'google',
|
|
322
|
+
request,
|
|
323
|
+
metadata: {
|
|
324
|
+
session_type: SESSION_TYPES.DESKTOP,
|
|
325
|
+
oauth_client_type: 'desktop_public_pkce',
|
|
326
|
+
},
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
return json({
|
|
330
|
+
ok: true,
|
|
331
|
+
authenticated: true,
|
|
332
|
+
session_id: provisioned.sessionId,
|
|
333
|
+
expires_at: provisioned.session?.expires_at ?? null,
|
|
334
|
+
user: user ? {
|
|
335
|
+
id: user.id,
|
|
336
|
+
email: user.email ?? null,
|
|
337
|
+
displayName: user.display_name ?? profile.name ?? null,
|
|
338
|
+
} : null,
|
|
339
|
+
exchange_mode: 'desktop_public_pkce_native_exchange',
|
|
340
|
+
});
|
|
341
|
+
}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
resolveIamPlatformCredentials,
|
|
6
6
|
} from './credentials.js';
|
|
7
7
|
import { pkceChallenge, pkceVerifier, randomOAuthState } from './pkce.js';
|
|
8
|
+
import { finishOAuthLogin, parseNativeStart, sessionTypeForTransaction } from './native-handoff.js';
|
|
8
9
|
import {
|
|
9
10
|
exchangeIamCode,
|
|
10
11
|
getIamAuthUrl,
|
|
@@ -33,12 +34,23 @@ export async function iamPlatformOAuthStart(request, env, adapter, identity) {
|
|
|
33
34
|
url.searchParams.get('next') || url.searchParams.get('return_to'),
|
|
34
35
|
) || '/';
|
|
35
36
|
|
|
37
|
+
const nativeStart = parseNativeStart(url, env);
|
|
38
|
+
if (nativeStart.error) {
|
|
39
|
+
return Response.json({ ok: false, error: nativeStart.error }, { status: 400 });
|
|
40
|
+
}
|
|
36
41
|
await adapter.saveOAuthState({
|
|
37
42
|
state,
|
|
38
43
|
provider: IAM_PLATFORM_STATE_PROVIDER,
|
|
39
44
|
codeVerifier,
|
|
40
45
|
redirectTo,
|
|
41
46
|
appId: identity?.app?.id || null,
|
|
47
|
+
...(nativeStart.native
|
|
48
|
+
? {
|
|
49
|
+
clientType: nativeStart.clientType,
|
|
50
|
+
nativeChallenge: nativeStart.nativeChallenge,
|
|
51
|
+
nativeRedirect: nativeStart.nativeRedirect,
|
|
52
|
+
}
|
|
53
|
+
: {}),
|
|
42
54
|
});
|
|
43
55
|
|
|
44
56
|
const redirectUri = `${url.origin}${IAM_PLATFORM_CALLBACK_PATH}`;
|
|
@@ -106,17 +118,17 @@ export async function iamPlatformOAuthCallback(request, env, adapter, identity)
|
|
|
106
118
|
providerSubject: normalized.subject,
|
|
107
119
|
email: normalized.email,
|
|
108
120
|
displayName: normalized.name || normalized.email.split('@')[0] || 'User',
|
|
121
|
+
sessionType: sessionTypeForTransaction(saved),
|
|
109
122
|
});
|
|
110
123
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
},
|
|
124
|
+
return finishOAuthLogin({
|
|
125
|
+
request,
|
|
126
|
+
env,
|
|
127
|
+
identity,
|
|
128
|
+
adapter,
|
|
129
|
+
saved,
|
|
130
|
+
result,
|
|
131
|
+
loginPath: identity.routeRegistry.resolve(identity.app.id, IDENTITY_ROUTE_IDS.LOGIN),
|
|
120
132
|
});
|
|
121
133
|
}
|
|
122
134
|
|