@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
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
-- identity.core extension — company / brand + native handoff parity
|
|
2
|
+
-- Portable identity_* names only. Does not create IAM `company` / `accounts`.
|
|
3
|
+
-- Does NOT include password-reset tables — recovery remains storage-agnostic
|
|
4
|
+
-- (createPasswordResetService + injected {get,put,delete} store).
|
|
5
|
+
-- Upgrades schema_version 1 → 2. Safe to re-run (IF NOT EXISTS / ignorable ALTERs).
|
|
6
|
+
|
|
7
|
+
INSERT OR REPLACE INTO identity_schema_meta (key, value)
|
|
8
|
+
VALUES ('schema_version', '2');
|
|
9
|
+
|
|
10
|
+
INSERT OR IGNORE INTO identity_schema_meta (key, value)
|
|
11
|
+
VALUES ('pack_company_native', '1');
|
|
12
|
+
|
|
13
|
+
CREATE TABLE IF NOT EXISTS identity_companies (
|
|
14
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
15
|
+
slug TEXT NOT NULL,
|
|
16
|
+
name TEXT NOT NULL,
|
|
17
|
+
legal_name TEXT,
|
|
18
|
+
logo_url TEXT,
|
|
19
|
+
favicon_url TEXT,
|
|
20
|
+
primary_color TEXT,
|
|
21
|
+
auth_bg_color TEXT,
|
|
22
|
+
support_email TEXT,
|
|
23
|
+
website_url TEXT,
|
|
24
|
+
tagline TEXT,
|
|
25
|
+
meta_json TEXT,
|
|
26
|
+
created_at INTEGER NOT NULL,
|
|
27
|
+
updated_at INTEGER NOT NULL
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_identity_companies_slug
|
|
31
|
+
ON identity_companies(slug);
|
|
32
|
+
|
|
33
|
+
CREATE TABLE IF NOT EXISTS identity_native_handoffs (
|
|
34
|
+
handoff_hash TEXT PRIMARY KEY NOT NULL,
|
|
35
|
+
session_id TEXT NOT NULL,
|
|
36
|
+
challenge TEXT NOT NULL,
|
|
37
|
+
expires_at INTEGER NOT NULL,
|
|
38
|
+
created_at INTEGER NOT NULL,
|
|
39
|
+
consumed_at INTEGER,
|
|
40
|
+
FOREIGN KEY (session_id) REFERENCES identity_sessions(id)
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
CREATE INDEX IF NOT EXISTS idx_identity_native_handoffs_expires
|
|
44
|
+
ON identity_native_handoffs(expires_at);
|
|
45
|
+
|
|
46
|
+
-- Session type for browser vs desktop/native (default keeps existing rows as browser).
|
|
47
|
+
ALTER TABLE identity_sessions ADD COLUMN type TEXT NOT NULL DEFAULT 'browser';
|
|
48
|
+
|
|
49
|
+
-- Native OAuth transaction fields (optional on browser transactions).
|
|
50
|
+
ALTER TABLE identity_oauth_transactions ADD COLUMN client_type TEXT;
|
|
51
|
+
ALTER TABLE identity_oauth_transactions ADD COLUMN native_challenge TEXT;
|
|
52
|
+
ALTER TABLE identity_oauth_transactions ADD COLUMN native_redirect TEXT;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "@inneranimalmedia/agentsam-
|
|
3
|
-
"version": "2.6.
|
|
4
|
-
"private": true,
|
|
2
|
+
"name": "@inneranimalmedia/agentsam-identity",
|
|
3
|
+
"version": "2.6.7",
|
|
5
4
|
"type": "module",
|
|
6
|
-
"description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace
|
|
5
|
+
"description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace — publish via root SDK)",
|
|
7
6
|
"agentsam": {
|
|
8
7
|
"system": "identity",
|
|
9
8
|
"kind": "library",
|
|
@@ -27,10 +26,17 @@
|
|
|
27
26
|
"./contracts/provider": "./src/contracts/provider.js",
|
|
28
27
|
"./contracts/external-identity": "./src/contracts/external-identity.js",
|
|
29
28
|
"./contracts/auth-config": "./src/contracts/auth-config.js",
|
|
29
|
+
"./contracts/identity-store": "./src/contracts/identity-store.js",
|
|
30
30
|
"./oauth/callback": "./src/oauth/callback.js",
|
|
31
31
|
"./frontend/auth-portal/*": "./src/frontend/auth-portal/*",
|
|
32
32
|
"./providers/cloudflare": "./src/providers/cloudflare/index.js",
|
|
33
|
-
"./
|
|
33
|
+
"./providers/chatgpt": "./src/providers/chatgpt/index.js",
|
|
34
|
+
"./contracts/sign-in-options": "./src/contracts/sign-in-options.js",
|
|
35
|
+
"./oauth/consent-view": "./src/oauth/consent-view.js",
|
|
36
|
+
"./adapters/sqlite": "./src/adapters/sqlite/index.js",
|
|
37
|
+
"./adapters/portable-d1": "./src/adapters/portable-d1/index.js",
|
|
38
|
+
"./adapters/iam-compat": "./src/adapters/iam-compat/index.js",
|
|
39
|
+
"./adapters/cloudflare-d1": "./src/adapters/cloudflare-d1/index.js"
|
|
34
40
|
},
|
|
35
41
|
"scripts": {
|
|
36
42
|
"test": "node --test tests/*.test.mjs",
|
|
@@ -38,5 +44,20 @@
|
|
|
38
44
|
},
|
|
39
45
|
"engines": {
|
|
40
46
|
"node": ">=20"
|
|
41
|
-
}
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "git+https://github.com/SamPrimeaux/agentsam-sdk.git",
|
|
54
|
+
"directory": "packages/identity"
|
|
55
|
+
},
|
|
56
|
+
"files": [
|
|
57
|
+
"src",
|
|
58
|
+
"backend",
|
|
59
|
+
"migrations",
|
|
60
|
+
"schema",
|
|
61
|
+
"scripts"
|
|
62
|
+
]
|
|
42
63
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../../protocol/database/agentsam.schema-pack.v1.schema.json",
|
|
3
|
+
"schema": "agentsam.schema-pack.v1",
|
|
4
|
+
"id": "agentsam.identity",
|
|
5
|
+
"version": "2.0.0",
|
|
6
|
+
"pack_family": "agentsam.identity",
|
|
7
|
+
"components": [
|
|
8
|
+
"identity.core",
|
|
9
|
+
"identity.oauth-client",
|
|
10
|
+
"identity.oauth-server"
|
|
11
|
+
],
|
|
12
|
+
"component_dependencies": {
|
|
13
|
+
"identity.core": [],
|
|
14
|
+
"identity.oauth-client": ["identity.core"],
|
|
15
|
+
"identity.oauth-server": ["identity.core"]
|
|
16
|
+
},
|
|
17
|
+
"adapters": [
|
|
18
|
+
"sqlite",
|
|
19
|
+
"portable-d1",
|
|
20
|
+
"iam-compat"
|
|
21
|
+
],
|
|
22
|
+
"sql": {
|
|
23
|
+
"portable_dir": "migrations/sqlite",
|
|
24
|
+
"files": {
|
|
25
|
+
"identity.core": [
|
|
26
|
+
"001_identity_core.sql",
|
|
27
|
+
"005_identity_company_native.sql"
|
|
28
|
+
],
|
|
29
|
+
"identity.oauth-client": [
|
|
30
|
+
"002_identity_oauth_client.sql"
|
|
31
|
+
],
|
|
32
|
+
"identity.oauth-server": [
|
|
33
|
+
"003_identity_oauth_server.sql",
|
|
34
|
+
"004_identity_oauth_consent_catalog.sql"
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
"apply_order_fresh": [
|
|
38
|
+
"001_identity_core.sql",
|
|
39
|
+
"002_identity_oauth_client.sql",
|
|
40
|
+
"005_identity_company_native.sql"
|
|
41
|
+
],
|
|
42
|
+
"apply_order_upgrade_v1_to_v2": [
|
|
43
|
+
"005_identity_company_native.sql"
|
|
44
|
+
],
|
|
45
|
+
"optional_after_core": [
|
|
46
|
+
"003_identity_oauth_server.sql",
|
|
47
|
+
"004_identity_oauth_consent_catalog.sql"
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
"tables": {
|
|
51
|
+
"identity.core": [
|
|
52
|
+
"identity_schema_meta",
|
|
53
|
+
"identity_users",
|
|
54
|
+
"identity_external_accounts",
|
|
55
|
+
"identity_sessions",
|
|
56
|
+
"identity_auth_events",
|
|
57
|
+
"identity_app_registry",
|
|
58
|
+
"identity_route_registry",
|
|
59
|
+
"identity_companies",
|
|
60
|
+
"identity_native_handoffs"
|
|
61
|
+
],
|
|
62
|
+
"identity.oauth-client": [
|
|
63
|
+
"identity_oauth_transactions",
|
|
64
|
+
"identity_provider_connections"
|
|
65
|
+
],
|
|
66
|
+
"identity.oauth-server": [
|
|
67
|
+
"identity_oauth_clients",
|
|
68
|
+
"identity_oauth_authorization_codes",
|
|
69
|
+
"identity_oauth_access_tokens",
|
|
70
|
+
"identity_oauth_refresh_tokens",
|
|
71
|
+
"identity_oauth_resources",
|
|
72
|
+
"identity_oauth_scopes",
|
|
73
|
+
"identity_oauth_resource_scopes"
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
"table_patterns": ["identity_*"],
|
|
77
|
+
"seed_policy": "none",
|
|
78
|
+
"compatibility": {
|
|
79
|
+
"iam-compat": {
|
|
80
|
+
"owns_portable_schema": false,
|
|
81
|
+
"maps_onto": [
|
|
82
|
+
"accounts",
|
|
83
|
+
"auth_users",
|
|
84
|
+
"account_identities",
|
|
85
|
+
"auth_sessions",
|
|
86
|
+
"auth_event_log",
|
|
87
|
+
"identity_oauth_states",
|
|
88
|
+
"identity_native_handoffs",
|
|
89
|
+
"company"
|
|
90
|
+
],
|
|
91
|
+
"stable_alias": "createCloudflareD1Adapter"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"recovery": {
|
|
95
|
+
"authority": "createPasswordResetService",
|
|
96
|
+
"storage": "injected {get,put,delete} — not IdentityStore / not identity.core SQL",
|
|
97
|
+
"optional_future_pack": "identity.recovery"
|
|
98
|
+
},
|
|
99
|
+
"owner": "@inneranimalmedia/agentsam-sdk/identity",
|
|
100
|
+
"notes": "Pack family for portable IdentityStore. Component IDs remain the contract units. Portable SQL SSOT is migrations/sqlite/. IAM production tables are NOT this pack — use the iam-compat adapter against hosted schema. Secrets are credential_ref / vault references, never raw tokens in rows. Password recovery stays storage-agnostic."
|
|
101
|
+
}
|
|
@@ -59,14 +59,20 @@ function sanitizeUser(user) {
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
function cliArg(name) {
|
|
63
|
+
const i = process.argv.indexOf(name);
|
|
64
|
+
return i > 1 ? process.argv[i + 1] : undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
62
67
|
const request = await readStdin();
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
process.
|
|
68
|
-
|
|
69
|
-
);
|
|
68
|
+
const dbArg = cliArg('--db');
|
|
69
|
+
const manifestArg = cliArg('--manifest');
|
|
70
|
+
if (!dbArg || !manifestArg) {
|
|
71
|
+
process.stderr.write('usage: local-identity-bridge.mjs --db <sqlite path> --manifest <agentsam.app.json>\n');
|
|
72
|
+
process.exit(2);
|
|
73
|
+
}
|
|
74
|
+
const dbPath = path.resolve(dbArg);
|
|
75
|
+
const manifestPath = path.resolve(manifestArg);
|
|
70
76
|
|
|
71
77
|
fs.mkdirSync(path.dirname(dbPath), { recursive: true, mode: 0o700 });
|
|
72
78
|
const nativeDb = new DatabaseSync(dbPath);
|
|
@@ -119,15 +119,15 @@ function hubHtml(baseUrl) {
|
|
|
119
119
|
const PREVIEW_COMPANY = {
|
|
120
120
|
id: 'co_default',
|
|
121
121
|
slug: 'default',
|
|
122
|
-
name: '
|
|
123
|
-
legalName: '
|
|
124
|
-
logoUrl: '/shared/
|
|
122
|
+
name: 'Preview App',
|
|
123
|
+
legalName: 'Preview App',
|
|
124
|
+
logoUrl: '/shared/app-icon.png',
|
|
125
125
|
faviconUrl: null,
|
|
126
126
|
primaryColor: '#007AFF',
|
|
127
127
|
authBgColor: '#050508',
|
|
128
|
-
supportEmail: 'support@
|
|
129
|
-
websiteUrl: 'https://
|
|
130
|
-
tagline: '
|
|
128
|
+
supportEmail: 'support@example.com',
|
|
129
|
+
websiteUrl: 'https://example.com',
|
|
130
|
+
tagline: 'Welcome',
|
|
131
131
|
meta: {
|
|
132
132
|
privacyUrl: '/privacy',
|
|
133
133
|
termsUrl: '/terms',
|
|
@@ -1,403 +1,10 @@
|
|
|
1
|
-
import { SESSION_POLICY } from '../../core/constants.js';
|
|
2
|
-
import { IdentitySchemaError } from '../../contracts/identity-store.js';
|
|
3
|
-
import { IDENTITY_STORE_SCHEMA_VERSION } from '../../contracts/identity-store.js';
|
|
4
|
-
import { newAccountIdentityId, newAuthUserId, newSessionId, newAuthEventId, nowUnix } from './ids.js';
|
|
5
|
-
import { DEFAULT_COMPANY_ID, DEFAULT_COMPANY_SLUG, normalizeCompanyRow } from '../../contracts/company.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
1
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
2
|
+
* Stable compatibility export path.
|
|
3
|
+
* createCloudflareD1Adapter remains IAM-compat behavior
|
|
4
|
+
* (accounts, auth_users, auth_sessions, company, ...).
|
|
5
|
+
* Do NOT repoint this path at portable identity_* tables.
|
|
11
6
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* @param {{ sessionTtlSeconds?: number }} [options]
|
|
17
|
-
*/
|
|
18
|
-
async function hashValue(value) {
|
|
19
|
-
const v = String(value || '').trim();
|
|
20
|
-
if (!v) return null;
|
|
21
|
-
const bytes = new TextEncoder().encode(v);
|
|
22
|
-
const digest = await crypto.subtle.digest('SHA-256', bytes);
|
|
23
|
-
return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function createCloudflareD1Adapter(db, options = {}) {
|
|
27
|
-
if (!db?.prepare) {
|
|
28
|
-
throw new Error('cloudflare_d1_adapter_requires_db_binding');
|
|
29
|
-
}
|
|
30
|
-
const sessionTtlSeconds = options.sessionTtlSeconds ?? SESSION_POLICY.browser.ttlSeconds;
|
|
31
|
-
|
|
32
|
-
return Object.freeze({
|
|
33
|
-
schemaVersion: IDENTITY_STORE_SCHEMA_VERSION,
|
|
34
|
-
sessionTtlSeconds,
|
|
35
|
-
backend: 'cloudflare-d1',
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Append-only login/logout/failed-attempt audit trail (auth_event_log).
|
|
39
|
-
* Never throws — an observability write must not break a real auth flow.
|
|
40
|
-
* status remains the event outcome only ('ok' | 'failed').
|
|
41
|
-
* Richer context (session, capabilities, activity, client) goes in metadata_json.
|
|
42
|
-
* ip/userAgent are hashed (SHA-256) — raw values are never persisted.
|
|
43
|
-
*/
|
|
44
|
-
async logAuthEvent({
|
|
45
|
-
userId,
|
|
46
|
-
accountId,
|
|
47
|
-
eventType,
|
|
48
|
-
status = 'ok',
|
|
49
|
-
provider,
|
|
50
|
-
session,
|
|
51
|
-
capabilities,
|
|
52
|
-
activity,
|
|
53
|
-
client,
|
|
54
|
-
metadata,
|
|
55
|
-
request,
|
|
56
|
-
}) {
|
|
57
|
-
try {
|
|
58
|
-
const ip = request?.headers?.get?.('cf-connecting-ip') || request?.headers?.get?.('x-forwarded-for') || '';
|
|
59
|
-
const ua = request?.headers?.get?.('user-agent') || '';
|
|
60
|
-
const [ipHash, uaHash] = await Promise.all([hashValue(ip), hashValue(ua)]);
|
|
61
|
-
const envelope = {
|
|
62
|
-
...(metadata && typeof metadata === 'object' ? metadata : {}),
|
|
63
|
-
...(accountId ? { accountId } : {}),
|
|
64
|
-
...(session ? { session } : {}),
|
|
65
|
-
...(capabilities ? { capabilities } : {}),
|
|
66
|
-
...(activity ? { activity } : {}),
|
|
67
|
-
...(client ? { client } : {}),
|
|
68
|
-
};
|
|
69
|
-
await db.prepare(
|
|
70
|
-
`INSERT INTO auth_event_log
|
|
71
|
-
(id, user_id, event_type, status, provider, metadata_json, ip_hash, user_agent_hash)
|
|
72
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
73
|
-
).bind(
|
|
74
|
-
newAuthEventId(),
|
|
75
|
-
userId || null,
|
|
76
|
-
eventType,
|
|
77
|
-
status,
|
|
78
|
-
provider || null,
|
|
79
|
-
JSON.stringify(envelope),
|
|
80
|
-
ipHash,
|
|
81
|
-
uaHash,
|
|
82
|
-
).run();
|
|
83
|
-
} catch {
|
|
84
|
-
// Never let audit logging break a real login/OAuth flow.
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Account/session activity snapshot for auth receipts (not event outcome).
|
|
90
|
-
* @param {string} userId
|
|
91
|
-
*/
|
|
92
|
-
async countAuthActivity(userId) {
|
|
93
|
-
if (!userId) {
|
|
94
|
-
return { loginCount: 0, activeSessionCount: 0, lastLoginAt: null };
|
|
95
|
-
}
|
|
96
|
-
try {
|
|
97
|
-
const logins = await db.prepare(
|
|
98
|
-
`SELECT COUNT(*) AS c, MAX(created_at) AS last_at
|
|
99
|
-
FROM auth_event_log
|
|
100
|
-
WHERE user_id = ? AND event_type = 'login' AND status = 'ok'`,
|
|
101
|
-
).bind(userId).first();
|
|
102
|
-
const sessions = await db.prepare(
|
|
103
|
-
`SELECT COUNT(*) AS c FROM auth_sessions
|
|
104
|
-
WHERE user_id = ? AND revoked_at IS NULL AND expires_at > ?`,
|
|
105
|
-
).bind(userId, nowUnix()).first();
|
|
106
|
-
return {
|
|
107
|
-
loginCount: Number(logins?.c || 0),
|
|
108
|
-
activeSessionCount: Number(sessions?.c || 0),
|
|
109
|
-
lastLoginAt: logins?.last_at != null ? Number(logins.last_at) : null,
|
|
110
|
-
};
|
|
111
|
-
} catch {
|
|
112
|
-
return { loginCount: 0, activeSessionCount: 0, lastLoginAt: null };
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
async findUserByEmail(email) {
|
|
117
|
-
const row = await db.prepare(
|
|
118
|
-
`SELECT id, email, display_name, password_hash, salt, status, created_at, updated_at
|
|
119
|
-
FROM auth_users WHERE email = ? COLLATE NOCASE LIMIT 1`,
|
|
120
|
-
).bind(String(email || '').trim().toLowerCase()).first();
|
|
121
|
-
return row || null;
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
async findUserById(userId) {
|
|
125
|
-
const row = await db.prepare(
|
|
126
|
-
`SELECT id, email, display_name, password_hash, salt, status, created_at, updated_at
|
|
127
|
-
FROM auth_users WHERE id = ? LIMIT 1`,
|
|
128
|
-
).bind(userId).first();
|
|
129
|
-
return row || null;
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
async createUser({ email, passwordHash, salt, displayName }) {
|
|
133
|
-
const id = newAuthUserId();
|
|
134
|
-
const ts = nowUnix();
|
|
135
|
-
const normalizedEmail = String(email || '').trim().toLowerCase();
|
|
136
|
-
// accounts = SSOT; auth_users = login principal (1:1 id in portable scaffold).
|
|
137
|
-
await db.prepare(
|
|
138
|
-
`INSERT INTO accounts (id, email, display_name, status, created_at, updated_at)
|
|
139
|
-
VALUES (?, ?, ?, 'active', ?, ?)`,
|
|
140
|
-
).bind(id, normalizedEmail, displayName || null, ts, ts).run();
|
|
141
|
-
await db.prepare(
|
|
142
|
-
`INSERT INTO auth_users (id, email, display_name, password_hash, salt, status, created_at, updated_at)
|
|
143
|
-
VALUES (?, ?, ?, ?, ?, 'active', ?, ?)`,
|
|
144
|
-
).bind(id, normalizedEmail, displayName || null, passwordHash || null, salt || null, ts, ts).run();
|
|
145
|
-
return this.findUserById(id);
|
|
146
|
-
},
|
|
147
|
-
|
|
148
|
-
async updateUserPassword(userId, passwordHash, salt) {
|
|
149
|
-
const ts = nowUnix();
|
|
150
|
-
await db.prepare(
|
|
151
|
-
`UPDATE auth_users SET password_hash = ?, salt = ?, updated_at = ? WHERE id = ?`,
|
|
152
|
-
).bind(passwordHash, salt, ts, userId).run();
|
|
153
|
-
await db.prepare(
|
|
154
|
-
`UPDATE accounts SET updated_at = ? WHERE id = ?`,
|
|
155
|
-
).bind(ts, userId).run().catch(() => {});
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
async findUserByProvider(provider, providerSubject) {
|
|
159
|
-
const row = await db.prepare(
|
|
160
|
-
`SELECT u.id, u.email, u.display_name, u.password_hash, u.salt, u.status, u.created_at, u.updated_at
|
|
161
|
-
FROM account_identities ai
|
|
162
|
-
JOIN accounts a ON a.id = ai.account_id
|
|
163
|
-
JOIN auth_users u ON u.id = a.id
|
|
164
|
-
WHERE ai.provider = ? AND ai.provider_subject = ?
|
|
165
|
-
AND COALESCE(a.status, 'active') = 'active'
|
|
166
|
-
LIMIT 1`,
|
|
167
|
-
).bind(provider, providerSubject).first();
|
|
168
|
-
return row || null;
|
|
169
|
-
},
|
|
170
|
-
|
|
171
|
-
async upsertProviderIdentity({ accountId, provider, providerSubject, email }) {
|
|
172
|
-
// Ensure SSOT account row exists (OAuth may create identity before password user).
|
|
173
|
-
const ts = nowUnix();
|
|
174
|
-
const account = await db.prepare(
|
|
175
|
-
`SELECT id FROM accounts WHERE id = ? LIMIT 1`,
|
|
176
|
-
).bind(accountId).first();
|
|
177
|
-
if (!account?.id) {
|
|
178
|
-
const authUser = await this.findUserById(accountId);
|
|
179
|
-
if (!authUser) throw new Error('account_ssot_missing');
|
|
180
|
-
await db.prepare(
|
|
181
|
-
`INSERT INTO accounts (id, email, display_name, status, created_at, updated_at)
|
|
182
|
-
VALUES (?, ?, ?, 'active', ?, ?)`,
|
|
183
|
-
).bind(
|
|
184
|
-
accountId,
|
|
185
|
-
authUser.email,
|
|
186
|
-
authUser.display_name || null,
|
|
187
|
-
authUser.created_at || ts,
|
|
188
|
-
ts,
|
|
189
|
-
).run();
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const existing = await db.prepare(
|
|
193
|
-
`SELECT id FROM account_identities WHERE provider = ? AND provider_subject = ? LIMIT 1`,
|
|
194
|
-
).bind(provider, providerSubject).first();
|
|
195
|
-
if (existing?.id) {
|
|
196
|
-
await db.prepare(
|
|
197
|
-
`UPDATE account_identities SET account_id = ?, email = ?, updated_at = ? WHERE id = ?`,
|
|
198
|
-
).bind(accountId, email || null, ts, existing.id).run();
|
|
199
|
-
return existing.id;
|
|
200
|
-
}
|
|
201
|
-
const id = newAccountIdentityId();
|
|
202
|
-
await db.prepare(
|
|
203
|
-
`INSERT INTO account_identities (id, account_id, provider, provider_subject, email, created_at, updated_at)
|
|
204
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
205
|
-
).bind(id, accountId, provider, providerSubject, email || null, ts, ts).run();
|
|
206
|
-
return id;
|
|
207
|
-
},
|
|
208
|
-
|
|
209
|
-
async createSession({ userId, email, provider, providerSubject, displayName }) {
|
|
210
|
-
const id = newSessionId();
|
|
211
|
-
const ts = nowUnix();
|
|
212
|
-
const expiresAt = ts + sessionTtlSeconds;
|
|
213
|
-
await db.prepare(
|
|
214
|
-
`INSERT INTO auth_sessions
|
|
215
|
-
(id, user_id, email, provider, provider_subject, display_name, expires_at, created_at, last_active_at)
|
|
216
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
217
|
-
).bind(
|
|
218
|
-
id,
|
|
219
|
-
userId,
|
|
220
|
-
email || null,
|
|
221
|
-
provider || 'email',
|
|
222
|
-
providerSubject || null,
|
|
223
|
-
displayName || null,
|
|
224
|
-
expiresAt,
|
|
225
|
-
ts,
|
|
226
|
-
ts,
|
|
227
|
-
).run();
|
|
228
|
-
return {
|
|
229
|
-
id,
|
|
230
|
-
user_id: userId,
|
|
231
|
-
email,
|
|
232
|
-
provider: provider || 'email',
|
|
233
|
-
provider_subject: providerSubject || null,
|
|
234
|
-
display_name: displayName || null,
|
|
235
|
-
expires_at: expiresAt,
|
|
236
|
-
created_at: ts,
|
|
237
|
-
};
|
|
238
|
-
},
|
|
239
|
-
|
|
240
|
-
async getSession(sessionId) {
|
|
241
|
-
const row = await db.prepare(
|
|
242
|
-
`SELECT id, user_id, email, provider, provider_subject, display_name, expires_at, revoked_at, created_at, last_active_at
|
|
243
|
-
FROM auth_sessions WHERE id = ? LIMIT 1`,
|
|
244
|
-
).bind(sessionId).first();
|
|
245
|
-
if (!row) return null;
|
|
246
|
-
if (row.revoked_at) return null;
|
|
247
|
-
if (row.expires_at <= nowUnix()) return null;
|
|
248
|
-
return row;
|
|
249
|
-
},
|
|
250
|
-
|
|
251
|
-
async revokeSession(sessionId, reason = 'logout') {
|
|
252
|
-
const ts = nowUnix();
|
|
253
|
-
await db.prepare(
|
|
254
|
-
`UPDATE auth_sessions SET revoked_at = ?, last_active_at = ? WHERE id = ? AND revoked_at IS NULL`,
|
|
255
|
-
).bind(ts, ts, sessionId).run();
|
|
256
|
-
return { ok: true, reason };
|
|
257
|
-
},
|
|
258
|
-
|
|
259
|
-
async createOAuthTransaction({ state, provider, codeVerifier, returnTo, redirectTo, appId, ttlSeconds = 600 }) {
|
|
260
|
-
if (!appId) {
|
|
261
|
-
throw new IdentitySchemaError(
|
|
262
|
-
'OAUTH_TRANSACTION_APP_ID_REQUIRED',
|
|
263
|
-
'OAuth transactions must include app_id',
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
const ts = nowUnix();
|
|
267
|
-
const expiresAt = ts + ttlSeconds;
|
|
268
|
-
try {
|
|
269
|
-
await db.prepare(
|
|
270
|
-
`INSERT INTO identity_oauth_states
|
|
271
|
-
(state, provider, code_verifier, redirect_to, app_id, expires_at, created_at)
|
|
272
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
273
|
-
).bind(state, provider, codeVerifier, returnTo ?? redirectTo ?? null, appId, expiresAt, ts).run();
|
|
274
|
-
} catch (err) {
|
|
275
|
-
throw new IdentitySchemaError(
|
|
276
|
-
'IDENTITY_SCHEMA_MIGRATION_REQUIRED',
|
|
277
|
-
'identity_oauth_states.app_id required — apply migration 0015 (no silent pre-app_id fallback)',
|
|
278
|
-
{ cause: String(err?.message || err) },
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
},
|
|
282
|
-
|
|
283
|
-
/** @deprecated Use createOAuthTransaction */
|
|
284
|
-
async saveOAuthState(input) {
|
|
285
|
-
return this.createOAuthTransaction(input);
|
|
286
|
-
},
|
|
287
|
-
|
|
288
|
-
async consumeOAuthTransaction(state) {
|
|
289
|
-
let row;
|
|
290
|
-
try {
|
|
291
|
-
row = await db.prepare(
|
|
292
|
-
`SELECT state, provider, code_verifier, redirect_to, app_id, expires_at, created_at
|
|
293
|
-
FROM identity_oauth_states WHERE state = ? LIMIT 1`,
|
|
294
|
-
).bind(state).first();
|
|
295
|
-
} catch (err) {
|
|
296
|
-
throw new IdentitySchemaError(
|
|
297
|
-
'IDENTITY_SCHEMA_MIGRATION_REQUIRED',
|
|
298
|
-
'identity_oauth_states.app_id column missing — apply migration 0015',
|
|
299
|
-
{ cause: String(err?.message || err) },
|
|
300
|
-
);
|
|
301
|
-
}
|
|
302
|
-
if (!row) return null;
|
|
303
|
-
await db.prepare(`DELETE FROM identity_oauth_states WHERE state = ?`).bind(state).run();
|
|
304
|
-
if (row.expires_at <= nowUnix()) return null;
|
|
305
|
-
if (!row.app_id) {
|
|
306
|
-
throw new IdentitySchemaError(
|
|
307
|
-
'IDENTITY_SCHEMA_MIGRATION_REQUIRED',
|
|
308
|
-
'OAuth transaction missing app_id — refuse silent pre-app_id semantics',
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
return {
|
|
312
|
-
state: row.state,
|
|
313
|
-
provider: row.provider,
|
|
314
|
-
code_verifier: row.code_verifier,
|
|
315
|
-
redirect_to: row.redirect_to,
|
|
316
|
-
return_to: row.redirect_to,
|
|
317
|
-
app_id: row.app_id,
|
|
318
|
-
expires_at: row.expires_at,
|
|
319
|
-
created_at: row.created_at,
|
|
320
|
-
};
|
|
321
|
-
},
|
|
322
|
-
|
|
323
|
-
/** @deprecated Use consumeOAuthTransaction */
|
|
324
|
-
async consumeOAuthState(state) {
|
|
325
|
-
return this.consumeOAuthTransaction(state);
|
|
326
|
-
},
|
|
327
|
-
|
|
328
|
-
async getCompanyBySlug(slug = DEFAULT_COMPANY_SLUG) {
|
|
329
|
-
const row = await db.prepare(
|
|
330
|
-
`SELECT id, slug, name, legal_name, logo_url, favicon_url, primary_color, auth_bg_color,
|
|
331
|
-
support_email, website_url, tagline, meta_json, created_at, updated_at
|
|
332
|
-
FROM company WHERE slug = ? LIMIT 1`,
|
|
333
|
-
).bind(slug).first();
|
|
334
|
-
return normalizeCompanyRow(row);
|
|
335
|
-
},
|
|
336
|
-
|
|
337
|
-
async getDefaultCompany() {
|
|
338
|
-
const bySlug = await this.getCompanyBySlug(DEFAULT_COMPANY_SLUG);
|
|
339
|
-
if (bySlug) return bySlug;
|
|
340
|
-
const row = await db.prepare(
|
|
341
|
-
`SELECT id, slug, name, legal_name, logo_url, favicon_url, primary_color, auth_bg_color,
|
|
342
|
-
support_email, website_url, tagline, meta_json, created_at, updated_at
|
|
343
|
-
FROM company WHERE id = ? LIMIT 1`,
|
|
344
|
-
).bind(DEFAULT_COMPANY_ID).first();
|
|
345
|
-
return normalizeCompanyRow(row);
|
|
346
|
-
},
|
|
347
|
-
|
|
348
|
-
async upsertCompany(input) {
|
|
349
|
-
const ts = nowUnix();
|
|
350
|
-
const id = input.id || DEFAULT_COMPANY_ID;
|
|
351
|
-
const slug = input.slug || DEFAULT_COMPANY_SLUG;
|
|
352
|
-
const existing = await db.prepare(`SELECT id FROM company WHERE id = ? OR slug = ? LIMIT 1`)
|
|
353
|
-
.bind(id, slug).first();
|
|
354
|
-
const metaJson = input.meta ? JSON.stringify(input.meta) : (input.metaJson ?? null);
|
|
355
|
-
if (existing?.id) {
|
|
356
|
-
await db.prepare(
|
|
357
|
-
`UPDATE company SET
|
|
358
|
-
slug = ?, name = ?, legal_name = ?, logo_url = ?, favicon_url = ?,
|
|
359
|
-
primary_color = ?, auth_bg_color = ?, support_email = ?, website_url = ?,
|
|
360
|
-
tagline = ?, meta_json = ?, updated_at = ?
|
|
361
|
-
WHERE id = ?`,
|
|
362
|
-
).bind(
|
|
363
|
-
slug,
|
|
364
|
-
input.name,
|
|
365
|
-
input.legalName ?? null,
|
|
366
|
-
input.logoUrl ?? null,
|
|
367
|
-
input.faviconUrl ?? null,
|
|
368
|
-
input.primaryColor ?? null,
|
|
369
|
-
input.authBgColor ?? null,
|
|
370
|
-
input.supportEmail ?? null,
|
|
371
|
-
input.websiteUrl ?? null,
|
|
372
|
-
input.tagline ?? null,
|
|
373
|
-
metaJson,
|
|
374
|
-
ts,
|
|
375
|
-
existing.id,
|
|
376
|
-
).run();
|
|
377
|
-
return this.getCompanyBySlug(slug);
|
|
378
|
-
}
|
|
379
|
-
await db.prepare(
|
|
380
|
-
`INSERT INTO company
|
|
381
|
-
(id, slug, name, legal_name, logo_url, favicon_url, primary_color, auth_bg_color,
|
|
382
|
-
support_email, website_url, tagline, meta_json, created_at, updated_at)
|
|
383
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
384
|
-
).bind(
|
|
385
|
-
id,
|
|
386
|
-
slug,
|
|
387
|
-
input.name,
|
|
388
|
-
input.legalName ?? null,
|
|
389
|
-
input.logoUrl ?? null,
|
|
390
|
-
input.faviconUrl ?? null,
|
|
391
|
-
input.primaryColor ?? null,
|
|
392
|
-
input.authBgColor ?? null,
|
|
393
|
-
input.supportEmail ?? null,
|
|
394
|
-
input.websiteUrl ?? null,
|
|
395
|
-
input.tagline ?? null,
|
|
396
|
-
metaJson,
|
|
397
|
-
ts,
|
|
398
|
-
ts,
|
|
399
|
-
).run();
|
|
400
|
-
return this.getCompanyBySlug(slug);
|
|
401
|
-
},
|
|
402
|
-
});
|
|
403
|
-
}
|
|
7
|
+
export {
|
|
8
|
+
createIamCompatIdentityAdapter,
|
|
9
|
+
createCloudflareD1Adapter,
|
|
10
|
+
} from '../iam-compat/index.js';
|