@inneranimalmedia/agentsam-sdk 2.6.2 → 2.6.4
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 +51 -1
- package/README.md +95 -0
- package/apps/README.md +34 -0
- package/apps/cad-creator/README.md +728 -0
- package/apps/cad-creator/shared/cad/package.json +19 -0
- package/apps/cad-creator/shared/cad/src/domain/operations.ts +7 -0
- package/apps/cad-creator/shared/cad/src/domain/project-contract.d.ts +3 -0
- package/apps/cad-creator/shared/cad/src/domain/project-contract.js +75 -0
- package/apps/cad-creator/shared/cad/src/domain/project-tools.d.ts +1 -0
- package/apps/cad-creator/shared/cad/src/domain/project-tools.js +24 -0
- package/apps/cad-creator/shared/cad/src/domain/validation.ts +191 -0
- package/apps/cad-creator/shared/cad/src/index.ts +4 -0
- package/apps/cad-creator/shared/cad/src/robotics/types.ts +232 -0
- package/apps/cad-creator/shared/cad/src/types.ts +507 -0
- package/apps/cad-creator/shared/cad/tsconfig.json +14 -0
- package/bin/agentsam +16 -1
- package/docs/AUTORAG.md +58 -0
- package/docs/BRAND_INTELLIGENCE.md +30 -0
- package/docs/CLI_SHELL.md +4 -2
- package/docs/CMS_CONTEXTUAL_COMPOSER.md +38 -0
- package/docs/MERKLE.md +4 -0
- package/docs/PROJECT_CONFIG.md +3 -0
- package/docs/REPOSITORY_KNOWLEDGE.md +2 -0
- package/docs/THEME_REFINERY.md +120 -0
- package/docs/architecture/AGENTSAM_DISTRIBUTION_OWNERSHIP.md +176 -0
- package/docs/architecture/AGENTSAM_GO_RUNTIME.md +282 -0
- package/docs/architecture/CODEBASEINDEX_GUIDED_PATH.md +202 -0
- package/docs/architecture/FS_E2E_CLOSURE_RECEIPT.md +59 -0
- package/docs/architecture/LOCAL_FS_AUTHORITY.md +38 -0
- package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +28 -0
- package/docs/architecture/PLAN_CLI_AND_LOCAL_STUDIO_DESKTOP.md +96 -0
- package/docs/architecture/PROVIDER-TOOLS-AND-COMPACTION.md +60 -0
- package/docs/architecture/SAM_ACTIVITY_RECOVERY_RECEIPT.md +39 -0
- package/docs/architecture/SAM_DECISION_WORK_RECEIPT.md +54 -0
- package/docs/architecture/SAM_KERNEL.md +181 -0
- package/docs/architecture/SAM_MACHINE_NORMALIZATION_PRECOMMIT_REPORT.md +208 -0
- package/docs/architecture/SLASH_SKILLS_PORTABLE.md +116 -0
- package/docs/architecture/STORAGE.md +87 -0
- package/docs/architecture/fs-e2e-receipt.latest.json +42 -0
- package/docs/architecture/previews/codebaseindex-guided-path/CODEBASEINDEX_GUIDED_PATH.md +202 -0
- package/docs/architecture/previews/codebaseindex-guided-path/index.html +321 -0
- package/docs/cad-project-tools.md +69 -0
- package/docs/cms-scaffolding-pattern-reference.md +73 -0
- package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS-codex-tui-20260919.md +113 -0
- package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS.md +85 -0
- package/docs/plans/AGENTSAM-MCP-CLIENT-2026-09-19.md +181 -0
- package/docs/plans/ASBD-PORTABLE-WORKGRAPH-UI-DEFERRED.md +34 -0
- package/docs/plans/ASTRA-BRIEF-2026-09-18.md +258 -0
- package/docs/plans/MULTI-AGENT-SPRINTS-2026-09-19.md +373 -0
- package/docs/plans/NEXT-AGENT-HANDOFF.md +167 -0
- package/docs/plans/RECONCILIATION-2026-09-19.md +178 -0
- package/docs/plugins.md +43 -0
- package/docs/tools/README.md +57 -0
- package/docs/tools/agent-and-orchestration.md +49 -0
- package/docs/tools/browser-and-research.md +46 -0
- package/docs/tools/cloudflare-platform.md +32 -0
- package/docs/tools/cms.md +25 -0
- package/docs/tools/communications.md +41 -0
- package/docs/tools/database-and-storage.md +62 -0
- package/docs/tools/design-and-media.md +64 -0
- package/docs/tools/filesystem-and-code.md +55 -0
- package/docs/tools/github.md +56 -0
- package/docs/tools/integrations-and-misc.md +16 -0
- package/docs/tools/memory.md +21 -0
- package/docs/tools/terminal-and-execution.md +29 -0
- package/docs/tools/tickets-and-platform.md +30 -0
- package/migrations/d1/0001_agentsam_plugin_runtime.sql +177 -0
- package/migrations/d1/0002_agentsam_ticket_ownership.sql +8 -0
- package/migrations/d1/0002_dynamic_model_policies.sql +23 -0
- package/migrations/d1/0003_expand_tool_handler_families.sql +18 -0
- package/migrations/d1/0004_project_aware_retrieval_lanes.sql +24 -0
- package/migrations/d1/0005_portable_knowledge_identity.sql +104 -0
- package/migrations/d1/0006_repair_ops_trail_account_scope.sql +14 -0
- package/migrations/d1/0007_repair_ops_trail_agent_run_account.sql +13 -0
- package/migrations/d1/0008_backfill_knowledge_run_legacy_tenant.sql +14 -0
- package/migrations/d1/0009_normalize_cloudflare_plugin_installations.sql +137 -0
- package/migrations/d1/0010_portable_tickets_memory.sql +140 -0
- package/migrations/d1/0011_agentsam_skill_v2.sql +185 -0
- package/migrations/d1/0011b_agentsam_skill_v2_cutover.sql +22 -0
- package/migrations/d1/0011c_agentsam_skill_v2_backfill.sql +76 -0
- package/migrations/d1/0011d_agentsam_skill_v2_retrieval_revisions.sql +50 -0
- package/migrations/d1/0012_agentsam_tools_required_seed.sql +67 -0
- package/migrations/d1/0013_identity_oauth_states.sql +15 -0
- package/migrations/d1/0014_auth_event_log.sql +20 -0
- package/migrations/d1/0015_identity_oauth_state_app_id.sql +3 -0
- package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +16 -0
- package/migrations/runtime/0001_cli_runtime.sql +67 -0
- package/migrations/runtime/0002_project_sessions.sql +15 -0
- package/migrations/runtime/0003_provider_continuations.sql +8 -0
- package/migrations/sqlite/agentsam_skill_retrieval.portable.sql +42 -0
- package/package.json +107 -12
- package/packages/agentsam-brand/README.md +21 -0
- package/packages/agentsam-brand/package.json +22 -0
- package/packages/agentsam-brand/src/contract.js +59 -0
- package/packages/agentsam-brand/src/extract.js +126 -0
- package/packages/agentsam-brand/src/goap-actions.js +73 -0
- package/packages/agentsam-brand/src/index.js +48 -0
- package/packages/agentsam-brand/src/plan.js +115 -0
- package/packages/agentsam-brand/src/resolve.js +139 -0
- package/packages/agentsam-brand/src/scan.js +250 -0
- package/packages/agentsam-brand/test/brand-scan.test.mjs +106 -0
- package/packages/agentsam-contracts/README.md +23 -0
- package/packages/agentsam-contracts/package.json +32 -0
- package/packages/agentsam-contracts/src/adapter.ts +25 -0
- package/packages/agentsam-contracts/src/agent.ts +35 -0
- package/packages/agentsam-contracts/src/artifacts.ts +33 -0
- package/packages/agentsam-contracts/src/authority.ts +29 -0
- package/packages/agentsam-contracts/src/context.ts +16 -0
- package/packages/agentsam-contracts/src/errors.ts +62 -0
- package/packages/agentsam-contracts/src/events.ts +47 -0
- package/packages/agentsam-contracts/src/execution.ts +50 -0
- package/packages/agentsam-contracts/src/hooks.ts +40 -0
- package/packages/agentsam-contracts/src/identity.ts +16 -0
- package/packages/agentsam-contracts/src/index.ts +14 -0
- package/packages/agentsam-contracts/src/models.ts +9 -0
- package/packages/agentsam-contracts/src/providers.ts +33 -0
- package/packages/agentsam-contracts/src/repository.ts +64 -0
- package/packages/agentsam-contracts/src/tools.ts +98 -0
- package/packages/agentsam-contracts/test/contracts.test.mjs +16 -0
- package/packages/agentsam-contracts/test/errors-catalog.test.mjs +25 -0
- package/packages/agentsam-contracts/test/repository.test.mjs +18 -0
- package/packages/agentsam-contracts/tsconfig.json +12 -0
- package/packages/agentsam-errors/package.json +17 -0
- package/packages/agentsam-errors/src/adapters/anthropic.js +15 -0
- package/packages/agentsam-errors/src/adapters/cad.js +109 -0
- package/packages/agentsam-errors/src/adapters/cloudflare.js +21 -0
- package/packages/agentsam-errors/src/adapters/cursor.js +4 -0
- package/packages/agentsam-errors/src/adapters/device.js +38 -0
- package/packages/agentsam-errors/src/adapters/docker.js +28 -0
- package/packages/agentsam-errors/src/adapters/gcp.js +14 -0
- package/packages/agentsam-errors/src/adapters/github.js +22 -0
- package/packages/agentsam-errors/src/adapters/google.js +17 -0
- package/packages/agentsam-errors/src/adapters/index.js +55 -0
- package/packages/agentsam-errors/src/adapters/internal.js +40 -0
- package/packages/agentsam-errors/src/adapters/oauth.js +24 -0
- package/packages/agentsam-errors/src/adapters/openai.js +17 -0
- package/packages/agentsam-errors/src/adapters/process.js +35 -0
- package/packages/agentsam-errors/src/adapters/provider.js +114 -0
- package/packages/agentsam-errors/src/envelope.js +239 -0
- package/packages/agentsam-errors/src/error.js +24 -0
- package/packages/agentsam-errors/src/fingerprint.js +35 -0
- package/packages/agentsam-errors/src/index.js +11 -0
- package/packages/agentsam-errors/src/normalize.js +30 -0
- package/packages/agentsam-errors/src/recovery.js +301 -0
- package/packages/agentsam-errors/src/redaction.js +52 -0
- package/packages/agentsam-errors/src/render.js +16 -0
- package/packages/agentsam-errors/src/retry.js +10 -0
- package/packages/agentsam-errors/src/transport.js +52 -0
- package/packages/agentsam-errors/src/vocabulary.js +320 -0
- package/packages/agentsam-errors/test/envelope.test.mjs +70 -0
- package/packages/agentsam-errors/test/providers.test.mjs +99 -0
- package/packages/agentsam-errors/test/redaction.test.mjs +21 -0
- package/packages/agentsam-errors/test/runtime-cad-device.test.mjs +76 -0
- package/packages/agentsam-errors/test/transport.test.mjs +46 -0
- package/packages/agentsam-knowledge/package.json +15 -0
- package/packages/agentsam-knowledge/src/autorag/index.js +64 -0
- package/packages/agentsam-knowledge/src/backends/index.js +26 -0
- package/packages/agentsam-knowledge/src/index.js +3 -0
- package/packages/agentsam-knowledge/src/providers/index.js +107 -0
- package/packages/agentsam-knowledge/test/autorag.test.mjs +42 -0
- package/packages/agentsam-nav/README.md +40 -0
- package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
- package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
- package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
- package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
- package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
- package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
- package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
- package/packages/agentsam-nav/dist/browser.d.ts +11 -0
- package/packages/agentsam-nav/dist/browser.global.js +132 -0
- package/packages/agentsam-nav/dist/browser.js +613 -0
- package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
- package/packages/agentsam-nav/dist/index.d.ts +11 -0
- package/packages/agentsam-nav/dist/index.js +614 -0
- package/packages/agentsam-nav/dist/legacy.css +83 -0
- package/packages/agentsam-nav/dist/shell.css +113 -0
- package/packages/agentsam-nav/dist/theme.css +113 -0
- package/packages/agentsam-nav/dist/utils.d.ts +1 -0
- package/packages/agentsam-nav/package.json +43 -0
- package/packages/agentsam-queue-control/README.md +107 -0
- package/packages/agentsam-queue-control/package.json +31 -0
- package/packages/agentsam-queue-control/schemas/job-envelope.schema.json +56 -0
- package/packages/agentsam-queue-control/src/adapters/cloudflare.js +152 -0
- package/packages/agentsam-queue-control/src/adapters/memory.js +38 -0
- package/packages/agentsam-queue-control/src/contracts.js +130 -0
- package/packages/agentsam-queue-control/src/control-plane.js +141 -0
- package/packages/agentsam-queue-control/src/dispatch.js +43 -0
- package/packages/agentsam-queue-control/src/index.js +7 -0
- package/packages/agentsam-queue-control/src/policy.js +88 -0
- package/packages/agentsam-queue-control/src/topology.js +66 -0
- package/packages/agentsam-queue-control/test/queue-control.test.mjs +100 -0
- package/packages/agentsam-repository/src/goap.js +718 -0
- package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
- package/packages/agentsam-repository/src/index.js +5 -0
- package/packages/agentsam-repository/src/merkle/cloudflare-persistence.js +2 -2
- package/packages/agentsam-repository/src/tickets.js +184 -0
- package/packages/agentsam-repository/src/work-tracking.js +199 -0
- package/packages/agentsam-repository/src/workspace-state.js +176 -0
- package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +152 -0
- package/packages/connectors/cloudflare/src/index.js +297 -15
- package/packages/connectors/cloudflare/src/owner.js +43 -40
- package/packages/connectors/cloudflare/src/routes.js +176 -26
- package/packages/connectors/cloudflare/tests/connector.test.mjs +137 -2
- package/packages/heuristic-theme/README.md +11 -0
- package/packages/heuristic-theme/package.json +25 -0
- package/packages/heuristic-theme/src/index.js +2 -0
- package/packages/heuristic-theme/src/registry.js +36 -0
- package/packages/heuristic-theme/src/theme.js +41 -0
- package/packages/heuristic-theme/test/theme.test.mjs +26 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +64 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +96 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +47 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +83 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/ui.json +35 -0
- package/packages/identity/docs/PORTABLE_IDENTITY_ARCHITECTURE.md +50 -0
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +31 -0
- package/packages/identity/migrations/sqlite/001_identity_core.sql +99 -0
- package/packages/identity/migrations/sqlite/002_identity_oauth_client.sql +38 -0
- package/packages/identity/migrations/sqlite/003_identity_oauth_server.sql +64 -0
- package/packages/identity/package.json +4 -3
- package/packages/identity/src/adapters/cloudflare-d1/ids.js +4 -0
- package/packages/identity/src/adapters/cloudflare-d1/index.js +156 -18
- package/packages/identity/src/adapters/sqlite/index.js +319 -0
- package/packages/identity/src/app/verify-app.js +95 -0
- package/packages/identity/src/contracts/identity-store.js +115 -0
- package/packages/identity/src/contracts/provider.js +3 -2
- package/packages/identity/src/contracts/route-ids.js +30 -0
- package/packages/identity/src/contracts/route-projection.js +218 -0
- package/packages/identity/src/contracts/routes.js +11 -0
- package/packages/identity/src/core/browser-paths.js +4 -5
- package/packages/identity/src/core/constants.js +13 -8
- package/packages/identity/src/core/session-policy.js +32 -0
- package/packages/identity/src/frontend/auth-portal/pages/login.html +16 -9
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +3 -3
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +3 -3
- package/packages/identity/src/frontend/auth-portal/preview/dashboard-stub.html +1 -1
- package/packages/identity/src/index.js +27 -0
- package/packages/identity/src/oauth/README.md +10 -4
- package/packages/identity/src/oauth/credentials.js +31 -11
- package/packages/identity/src/oauth/finalize-inbound.js +1 -1
- package/packages/identity/src/oauth/iam-platform.js +13 -12
- package/packages/identity/src/oauth/redirect-paths.js +27 -36
- package/packages/identity/src/providers/cloudflare/index.js +19 -0
- package/packages/identity/src/providers/cloudflare/mapper.js +21 -0
- package/packages/identity/src/providers/cloudflare/oauth.js +48 -0
- package/packages/identity/src/providers/cloudflare/profile.js +28 -0
- package/packages/identity/src/providers/index.js +18 -2
- package/packages/identity/src/server/identity-service.js +35 -8
- package/packages/identity/src/server/mount-policy.js +30 -0
- package/packages/identity/src/server/post-auth.js +79 -0
- package/packages/identity/src/server/worker-router.js +153 -66
- package/packages/identity/tests/finalize-inbound-oauth.test.mjs +6 -6
- package/packages/identity/tests/iam-provider.test.mjs +1 -1
- package/packages/identity/tests/identity-service.test.mjs +47 -1
- package/packages/identity/tests/oauth-credentials.test.mjs +3 -1
- package/packages/identity/tests/portable-identity-architecture.test.mjs +157 -0
- package/packages/identity/tests/session-routes-policy.test.mjs +21 -0
- package/packages/providers/completeful/README.md +38 -0
- package/packages/providers/completeful/package.json +29 -0
- package/packages/providers/completeful/src/client.js +162 -0
- package/packages/providers/completeful/src/events.js +49 -0
- package/packages/providers/completeful/src/index.js +22 -0
- package/packages/providers/completeful/src/tools.js +579 -0
- package/packages/providers/completeful/src/webhooks.js +55 -0
- package/packages/providers/completeful/test/provider.test.mjs +196 -0
- package/packages/theme-church-site/README.md +10 -0
- package/packages/theme-church-site/package.json +31 -0
- package/packages/theme-church-site/src/harvest.json +14 -0
- package/packages/theme-church-site/src/index.js +85 -0
- package/packages/theme-church-site/test/theme.test.mjs +19 -0
- package/packages/theme-companions-site/README.md +10 -0
- package/packages/theme-companions-site/package.json +31 -0
- package/packages/theme-companions-site/src/harvest.json +12 -0
- package/packages/theme-companions-site/src/index.js +83 -0
- package/packages/theme-companions-site/test/theme.test.mjs +19 -0
- package/packages/theme-floors-site/README.md +10 -0
- package/packages/theme-floors-site/package.json +31 -0
- package/packages/theme-floors-site/src/harvest.json +14 -0
- package/packages/theme-floors-site/src/index.js +83 -0
- package/packages/theme-floors-site/test/theme.test.mjs +19 -0
- package/packages/theme-fuelnfree-site/README.md +10 -0
- package/packages/theme-fuelnfree-site/package.json +31 -0
- package/packages/theme-fuelnfree-site/src/harvest.json +13 -0
- package/packages/theme-fuelnfree-site/src/index.js +82 -0
- package/packages/theme-fuelnfree-site/test/theme.test.mjs +19 -0
- package/packages/theme-handyman-site/README.md +10 -0
- package/packages/theme-handyman-site/package.json +31 -0
- package/packages/theme-handyman-site/src/harvest.json +10 -0
- package/packages/theme-handyman-site/src/index.js +84 -0
- package/packages/theme-handyman-site/test/theme.test.mjs +19 -0
- package/packages/theme-insurance-site/README.md +10 -0
- package/packages/theme-insurance-site/package.json +31 -0
- package/packages/theme-insurance-site/src/harvest.json +10 -0
- package/packages/theme-insurance-site/src/index.js +84 -0
- package/packages/theme-insurance-site/test/theme.test.mjs +19 -0
- package/packages/theme-shinshu-site/README.md +10 -0
- package/packages/theme-shinshu-site/package.json +31 -0
- package/packages/theme-shinshu-site/src/harvest.json +12 -0
- package/packages/theme-shinshu-site/src/index.js +84 -0
- package/packages/theme-shinshu-site/test/theme.test.mjs +19 -0
- package/packages/work-graph/README.md +49 -0
- package/packages/work-graph/package.json +19 -0
- package/packages/work-graph/prototype/README.md +32 -0
- package/packages/work-graph/prototype/data/demo-workgraph.js +47 -0
- package/packages/work-graph/prototype/renderers/timeline-model.js +21 -0
- package/packages/work-graph/prototype/renderers/workgraph-runtime.js +38 -0
- package/packages/work-graph/prototype-gnantt.html +655 -0
- package/packages/work-graph/src/adapters/business/projects.js +23 -0
- package/packages/work-graph/src/adapters/engineering/git.js +22 -0
- package/packages/work-graph/src/adapters/engineering/mcp.js +22 -0
- package/packages/work-graph/src/index.js +76 -0
- package/packages/work-graph/src/renderers/gantt-model.js +11 -0
- package/packages/work-graph/src/renderers/timeline.js +16 -0
- package/packages/work-graph/test/work-graph.test.mjs +37 -0
- package/protocol/README.md +12 -0
- package/protocol/apps/agentsam.app.v1.schema.json +51 -0
- package/protocol/brand/brandpack.v1.schema.json +43 -0
- package/protocol/capabilities/cloudflare-cpu-audit-input.schema.json +30 -6
- package/protocol/capabilities/cloudflare-cpu-profile-input.schema.json +18 -4
- package/protocol/capabilities/cloudflare-wrangler-native-input.schema.json +59 -10
- package/protocol/capabilities/knowledge-search-input.schema.json +35 -0
- package/protocol/capabilities/manifest.json +163 -1
- package/protocol/capabilities/repository-audit-input.schema.json +39 -6
- package/protocol/capabilities/repository-snapshot-input.schema.json +15 -3
- package/protocol/capabilities/terminal-exec-input.schema.json +55 -0
- package/protocol/commerce/catalog.v1.json +50 -0
- package/protocol/credentials/issue.v1.schema.json +38 -0
- package/protocol/database/connection.v1.schema.json +41 -0
- package/protocol/embeddings/embedding-profile.v1.schema.json +20 -0
- package/protocol/errors/error-catalog.json +164 -0
- package/protocol/errors/error-envelope.schema.json +678 -0
- package/protocol/errors/recovery.v1.schema.json +50 -0
- package/protocol/features/README.md +57 -0
- package/protocol/features/agentsam.feature.v1.schema.json +290 -0
- package/protocol/features/catalog.json +65 -0
- package/protocol/features/examples/provider-resend.feature.json +17 -0
- package/protocol/go/agentsam-go-runtime.v1.json +17 -0
- package/protocol/knowledge/LIFECYCLE.md +140 -0
- package/protocol/knowledge/README.md +4 -0
- package/protocol/presets/catalog.json +128 -19
- package/protocol/rpc/v1/errors.proto +24 -0
- package/protocol/runtime/workspace-fs.v1.schema.json +71 -0
- package/protocol/sam/activity.v1.schema.json +48 -0
- package/protocol/sam/answer.v1.schema.json +35 -0
- package/protocol/sam/calibration.v1.schema.json +21 -0
- package/protocol/sam/decision-receipt.v1.schema.json +29 -0
- package/protocol/sam/evaluation.v1.schema.json +19 -0
- package/protocol/sam/operation.schema.json +66 -0
- package/protocol/sam/outcome.v1.schema.json +36 -0
- package/protocol/sam/question.v1.schema.json +26 -0
- package/protocol/sam/registry.seed.json +153 -0
- package/protocol/sam/result.schema.json +53 -0
- package/protocol/sam/state.v1.schema.json +23 -0
- package/protocol/skills/agentsam.interaction.v1.schema.json +50 -0
- package/protocol/skills/agentsam.skill.v1.schema.json +57 -0
- package/protocol/theme-refinery/d1-reconciliation.md +48 -0
- package/protocol/theme-refinery/product-metadata.schema.json +27 -0
- package/protocol/theme-refinery/receipts/products-registry-batch-20260924.json +318 -0
- package/protocol/theme-refinery/receipts/theme-harvest-20260924.json +472 -0
- package/protocol/theme-refinery/reconciliation-receipt.schema.json +83 -0
- package/protocol/ui/icon-registry.mjs +226 -0
- package/protocol/ui/icon.v1.schema.json +51 -0
- package/services/cad/server.py +249 -2
- package/skills/README.md +22 -9
- package/skills/agentsam-codebaseindex/SKILL.md +225 -0
- package/skills/catalog.json +14 -0
- package/src/agent/capability-adapter.js +15 -5
- package/src/agent/index.js +2 -1
- package/src/agent/model-turn.js +51 -0
- package/src/agent/responses-runner.js +304 -38
- package/src/capabilities/index.js +1 -0
- package/src/capabilities/terminal-exec.js +78 -0
- package/src/cli/command-catalog.js +130 -0
- package/src/cli/dispatch.js +48 -0
- package/src/cli.js +160 -10
- package/src/cloudflare/index.js +6 -0
- package/src/cloudflare/runtime-status.js +393 -0
- package/src/cloudflare/wrangler.js +17 -1
- package/src/commands/api-key.js +244 -0
- package/src/commands/app.js +138 -0
- package/src/commands/autorag.js +77 -0
- package/src/commands/brand.js +291 -0
- package/src/commands/cad.js +1 -0
- package/src/commands/codebaseindex.js +688 -0
- package/src/commands/connections.js +126 -29
- package/src/commands/context-economics.js +8 -0
- package/src/commands/db.js +7 -0
- package/src/commands/env.js +155 -27
- package/src/commands/eval.js +209 -14
- package/src/commands/go.js +678 -0
- package/src/commands/goap.js +176 -0
- package/src/commands/identity-init.js +27 -3
- package/src/commands/identity-protocol.js +195 -0
- package/src/commands/interaction-clack.js +115 -0
- package/src/commands/knowledge.js +64 -5
- package/src/commands/mcp.js +341 -0
- package/src/commands/merkle-persist.js +3 -1
- package/src/commands/merkle.js +18 -3
- package/src/commands/models.js +110 -24
- package/src/commands/plugins.js +175 -0
- package/src/commands/preferences.js +28 -8
- package/src/commands/product.js +53 -10
- package/src/commands/providers.js +173 -44
- package/src/commands/resume.js +9 -5
- package/src/commands/runtime-status.js +154 -0
- package/src/commands/shell.js +508 -56
- package/src/commands/skill.js +248 -0
- package/src/commands/skills.js +1 -1
- package/src/commands/start-local.js +4 -0
- package/src/commands/status.js +82 -7
- package/src/commands/tunnel.js +228 -195
- package/src/commands/whoami.js +156 -12
- package/src/context/budget.js +6 -0
- package/src/context/index.js +2 -1
- package/src/context/project-card.js +75 -0
- package/src/errors/contract.js +34 -211
- package/src/errors/diagnostic.js +95 -51
- package/src/errors/index.js +6 -13
- package/src/eval/index.js +6 -0
- package/src/eval/live.js +439 -0
- package/src/features/resolve.js +242 -0
- package/src/go/build.js +298 -0
- package/src/go/cloudflare.js +608 -0
- package/src/go/container.js +120 -0
- package/src/go/contract.js +144 -0
- package/src/go/discover.js +212 -0
- package/src/go/index.js +25 -0
- package/src/go/native-probe-runner.mjs +119 -0
- package/src/go/official-registry.js +280 -0
- package/src/go/official-release.js +10 -0
- package/src/go/receipts.js +144 -0
- package/src/go/verify.js +38 -0
- package/src/index.js +127 -1
- package/src/indexing/ingest/discover-models.js +298 -0
- package/src/indexing/ingest/inventory.js +243 -0
- package/src/indexing/ingest/job-graph.js +181 -0
- package/src/indexing/ingest/materials.js +210 -0
- package/src/knowledge/config.js +13 -5
- package/src/knowledge/engine.js +23 -8
- package/src/knowledge/index.js +1 -0
- package/src/knowledge/lane-registry.js +46 -0
- package/src/knowledge/providers/gemini.js +48 -8
- package/src/knowledge/service/client.js +13 -1
- package/src/knowledge/service/grpc-codec.js +156 -53
- package/src/knowledge/service/job-engine.js +133 -11
- package/src/knowledge/service/job-worker.js +34 -5
- package/src/knowledge/service/server.js +10 -1
- package/src/knowledge/store-discovery.js +77 -0
- package/src/lib/account-session.js +8 -2
- package/src/lib/agent-instructions.js +3 -0
- package/src/lib/auth.js +7 -3
- package/src/lib/cad/blender.js +42 -3
- package/src/lib/cad/d1-project-store.js +43 -0
- package/src/lib/cad/discovery.js +616 -0
- package/src/lib/cad/docker-executor.js +352 -0
- package/src/lib/cad/freecad.js +253 -0
- package/src/lib/cad/index.js +40 -0
- package/src/lib/cad/openscad.js +198 -0
- package/src/lib/cad/project-cli.d.ts +2 -0
- package/src/lib/cad/project-cli.js +21 -0
- package/src/lib/cad/project-contract.d.ts +3 -0
- package/src/lib/cad/project-contract.js +1 -0
- package/src/lib/cad/project-recipe.js +30 -0
- package/src/lib/cad/project-runtime.d.ts +2 -0
- package/src/lib/cad/project-runtime.js +53 -0
- package/src/lib/cad/project-store.js +25 -0
- package/src/lib/cad/project-workflows.js +31 -0
- package/src/lib/cad-docker.js +21 -2
- package/src/lib/cli-preferences.js +17 -2
- package/src/lib/core-client.js +37 -18
- package/src/lib/deploy/local-studio.js +6 -5
- package/src/lib/dockerize.js +3 -0
- package/src/lib/execution-approvals.js +1 -0
- package/src/lib/identity-scaffold.js +4 -1
- package/src/lib/knowledge-docker.js +9 -1
- package/src/lib/local-sessions.js +124 -34
- package/src/lib/local-status.js +35 -14
- package/src/lib/project-config.js +9 -0
- package/src/lib/provider-credentials.js +136 -32
- package/src/lib/scaffold/resolve-cloudflare-account.js +37 -0
- package/src/lib/scaffold/wizards/cms.js +2 -8
- package/src/lib/scaffold/wizards/worker-api.js +2 -8
- package/src/lib/slash-commands.js +10 -2
- package/src/local/migrations.js +109 -1
- package/src/local/runtime-store.js +31 -5
- package/src/local/sqlite.js +36 -1
- package/src/local-fs/capability.js +121 -0
- package/src/local-fs/freshness.js +75 -0
- package/src/local-fs/index.js +385 -0
- package/src/local-fs/paths.js +100 -0
- package/src/local-pty/server.js +295 -19
- package/src/mcp/authority.js +348 -0
- package/src/mcp/client-adapters.js +431 -0
- package/src/mcp/client.js +172 -0
- package/src/mcp/index.js +47 -0
- package/src/mcp/telemetry.js +103 -0
- package/src/models/ai-access-onboarding.js +112 -0
- package/src/models/catalog.js +329 -51
- package/src/models/discovery.js +34 -6
- package/src/models/index.js +2 -0
- package/src/models/inventory-core.js +190 -0
- package/src/models/policy.js +20 -0
- package/src/plugins/cloudflare.js +103 -0
- package/src/plugins/completeful.js +69 -0
- package/src/plugins/contracts.js +86 -0
- package/src/plugins/index.js +11 -0
- package/src/plugins/registry.js +207 -0
- package/src/plugins/resource-scope.js +45 -0
- package/src/plugins/runtime.js +118 -0
- package/src/plugins/vectorize.js +31 -0
- package/src/progression/engine.js +171 -0
- package/src/progression/index.js +1 -0
- package/src/providers/cloudflare-chat.js +1 -1
- package/src/providers/gemini-generate-content.js +2 -1
- package/src/providers/openai-responses.js +45 -16
- package/src/providers/tool-schema.js +85 -0
- package/src/repository/index.js +29 -0
- package/src/rpc/generated/errors_pb.js +961 -1
- package/src/sam/activity/index.js +183 -0
- package/src/sam/client.js +252 -0
- package/src/sam/decision/calibration.js +109 -0
- package/src/sam/decision/confidence.js +126 -0
- package/src/sam/decision/evaluate.js +157 -0
- package/src/sam/decision/evaluators/deterministic.js +341 -0
- package/src/sam/decision/evaluators/heuristic.js +61 -0
- package/src/sam/decision/evaluators/select.js +50 -0
- package/src/sam/decision/evaluators/semantic.js +149 -0
- package/src/sam/decision/hierarchical.js +61 -0
- package/src/sam/decision/index.js +53 -0
- package/src/sam/decision/policy.js +86 -0
- package/src/sam/decision/questions.js +120 -0
- package/src/sam/decision/receipt.js +148 -0
- package/src/sam/decision/state.js +117 -0
- package/src/sam/decision/types.js +22 -0
- package/src/sam/decision/validate.js +200 -0
- package/src/sam/define.js +51 -0
- package/src/sam/index.js +65 -0
- package/src/sam/operations/brand-scan.js +62 -0
- package/src/sam/operations/cad-blender-inspect.js +36 -0
- package/src/sam/operations/codebaseindex-ingest.js +49 -0
- package/src/sam/operations/decision-evaluate.js +59 -0
- package/src/sam/operations/planning-astar.js +77 -0
- package/src/sam/operations/planning-goap.js +60 -0
- package/src/sam/operations/repository-inspect.js +72 -0
- package/src/sam/operations/security-scan.js +33 -0
- package/src/sam/operations/terminal-exec.js +29 -0
- package/src/sam/planning/astar.js +311 -0
- package/src/sam/planning/goap.js +177 -0
- package/src/sam/planning/index.js +21 -0
- package/src/sam/planning/state.js +84 -0
- package/src/sam/registry.js +48 -0
- package/src/sam/result.js +77 -0
- package/src/sam/seed.js +44 -0
- package/src/sam/types.js +91 -0
- package/src/security/local-vault.js +415 -0
- package/src/security/process.js +20 -4
- package/src/skills/catalog.js +64 -0
- package/src/skills/content-resolver.js +124 -0
- package/src/skills/hosted-store.js +37 -0
- package/src/skills/index.js +29 -64
- package/src/skills/interaction.js +102 -0
- package/src/skills/local-store.js +228 -0
- package/src/skills/manifest.js +104 -0
- package/src/skills/metrics.js +31 -0
- package/src/skills/registry.js +184 -0
- package/src/skills/runtime.js +287 -0
- package/src/skills/slash.js +44 -0
- package/src/status/actions.js +192 -0
- package/src/tools/hydrate.js +5 -1
- package/src/tools/index.js +7 -0
- package/src/tools/redact.js +64 -0
- package/src/tools/registry.js +83 -0
- package/src/tools/runtime.js +257 -0
- package/src/tools/search.js +21 -8
- package/src/ui/ansi.js +117 -3
- package/src/ui/cli/activity.js +76 -7
- package/src/ui/cli/footer.js +110 -9
- package/src/ui/cli/help.js +96 -96
- package/src/ui/wireframes.js +166 -0
- package/test/account-session.test.mjs +28 -0
- package/test/apps-scaffold-contract.test.mjs +16 -1
- package/test/capabilities.test.mjs +1 -1
- package/test/cli/api-key-env-whoami.test.mjs +129 -0
- package/test/cli/codebaseindex-plan-ux.test.mjs +37 -0
- package/test/cli/eval-live.test.mjs +219 -0
- package/test/cli/go.test.mjs +128 -0
- package/test/cli/local-vault-and-provider-setup.test.mjs +268 -0
- package/test/cli/mcp-client.test.mjs +245 -0
- package/test/cli/runtime-ui.test.mjs +69 -2
- package/test/cli/skill-npm-and-env.test.mjs +52 -0
- package/test/cli/status-actions.test.mjs +88 -0
- package/test/cli/wireframes-go-registry.test.mjs +139 -0
- package/test/cloudflare-connector.test.mjs +3 -6
- package/test/cloudflare-runtime.test.mjs +8 -1
- package/test/context.test.mjs +15 -0
- package/test/error-diagnostics.test.mjs +9 -0
- package/test/fixtures/cad/courtyard-house.json +208 -0
- package/test/go/build-source-identity.test.mjs +31 -0
- package/test/go/cloudflare-probe.test.mjs +317 -0
- package/test/go/distribution.test.mjs +28 -0
- package/test/integration/ai-access-onboarding.test.mjs +47 -0
- package/test/integration/app-command.test.mjs +55 -0
- package/test/integration/cad-discovery.test.mjs +158 -0
- package/test/integration/cad-docker-executor.test.mjs +249 -0
- package/test/integration/cad-execution.test.mjs +184 -0
- package/test/integration/cad-project-app.test.mjs +31 -0
- package/test/integration/cad-project-d1.test.mjs +25 -0
- package/test/integration/cad-project-native.test.mjs +24 -0
- package/test/integration/cad-project-workflow.test.mjs +9 -0
- package/test/integration/cad-project.test.mjs +82 -0
- package/test/integration/cli-help.test.mjs +5 -1
- package/test/integration/cms-site-tenancy-contract.test.mjs +256 -0
- package/test/integration/codebaseindex-ingest.test.mjs +166 -0
- package/test/integration/core-client.integration.test.mjs +55 -0
- package/test/integration/error-runtime-rpc.test.mjs +71 -0
- package/test/integration/features-resolve.test.mjs +128 -0
- package/test/integration/icon-registry.test.mjs +67 -0
- package/test/integration/ingest-discover-models.test.mjs +30 -0
- package/test/integration/install-script.test.mjs +110 -0
- package/test/integration/inventory-core.test.mjs +53 -0
- package/test/integration/local-fs.test.mjs +113 -0
- package/test/integration/plugins-cloudflare.integration.test.mjs +28 -0
- package/test/integration/provider-env-cli.test.mjs +3 -2
- package/test/integration/runtime-migrations.test.mjs +6 -1
- package/test/integration/runtime-status.integration.test.mjs +211 -0
- package/test/integration/sam-activity-recovery.test.mjs +147 -0
- package/test/integration/sam-decision.test.mjs +584 -0
- package/test/integration/sam-kernel.test.mjs +99 -0
- package/test/integration/sam-planning-astar.test.mjs +279 -0
- package/test/integration/scaffold-cloudflare.test.mjs +46 -0
- package/test/integration/skill-runtime.test.mjs +240 -0
- package/test/integration/storage-architecture.test.mjs +154 -0
- package/test/integration/store-discovery.test.mjs +44 -0
- package/test/integration/studio-fs-pty-e2e.test.mjs +294 -0
- package/test/integration/terminal-exec.integration.test.mjs +86 -0
- package/test/integration/tool-runtime.test.mjs +124 -0
- package/test/integration/tool-schema.test.mjs +59 -0
- package/test/knowledge-service.test.mjs +4 -0
- package/test/local-sessions.test.mjs +11 -2
- package/test/local-studio-deploy.test.mjs +1 -1
- package/test/model-catalog.test.mjs +28 -1
- package/test/models.test.mjs +172 -11
- package/test/openai-responses.test.mjs +60 -0
- package/test/provider-credentials.test.mjs +15 -5
- package/test/responses-runner.test.mjs +321 -6
- package/test/shell.test.mjs +151 -6
- package/test/smoke.mjs +2 -2
- package/test/tools-search.test.mjs +33 -0
- package/test/unit/website-assets-bindings.test.mjs +60 -0
- package/test/whoami-resume.test.mjs +82 -3
- package/examples/gorilla-shell/README.md +0 -15
- package/src/lib/gorilla-template.js +0 -54
- package/templates/gorilla-shell/App.tsx +0 -639
- package/templates/gorilla-shell/README.md +0 -34
- package/templates/gorilla-shell/index.html +0 -15
- package/templates/gorilla-shell/main.jsx +0 -9
- package/templates/gorilla-shell/package.json +0 -19
- package/templates/gorilla-shell/vite.config.js +0 -21
|
@@ -21,12 +21,18 @@ npx wrangler secret put IAM_CLIENT_SECRET
|
|
|
21
21
|
|
|
22
22
|
These routes live in the **customer** worker (`handleIdentityWorkerRequest`):
|
|
23
23
|
|
|
24
|
-
1. `/api/oauth/
|
|
25
|
-
|
|
24
|
+
1. `/api/oauth/inneranimalmedia/start` → redirects to IAM AS (requires minted `IAM_CLIENT_*`)
|
|
25
|
+
- Legacy alias: `/api/oauth/iam/start`
|
|
26
|
+
2. `/api/oauth/google/start` → BYOK Google if `GOOGLE_*` set, else platform lane if minted, else 503
|
|
26
27
|
3. `/api/oauth/github/start` → same for GitHub
|
|
27
|
-
4. Callback: `/api/oauth/
|
|
28
|
+
4. Callback: `/api/oauth/inneranimalmedia/callback` (platform lane) or `/api/oauth/{google|github|cloudflare}/callback` (BYOK)
|
|
29
|
+
- Legacy alias: `/api/oauth/iam/callback`
|
|
28
30
|
|
|
29
|
-
Register
|
|
31
|
+
Register platform redirect URI on the IAM client:
|
|
32
|
+
|
|
33
|
+
`https://<customer-host>/api/oauth/inneranimalmedia/callback`
|
|
34
|
+
|
|
35
|
+
(Keep the legacy `/api/oauth/iam/callback` registered during migration.)
|
|
30
36
|
|
|
31
37
|
## IAM authorization server endpoints (issuer)
|
|
32
38
|
|
|
@@ -8,13 +8,17 @@ import { DEFAULT_IAM_ORIGIN, resolveIamOrigin } from '../contracts/auth-config.j
|
|
|
8
8
|
* — SECRET is wrangler secret put only (encryption is law, not luxury).
|
|
9
9
|
*
|
|
10
10
|
* Developer BYOK: GOOGLE_CLIENT_* / GITHUB_CLIENT_* when set for that provider
|
|
11
|
-
* take the /api/oauth/{provider}/start button; otherwise the button uses
|
|
11
|
+
* take the /api/oauth/{provider}/start button; otherwise the button uses the
|
|
12
|
+
* Inner Animal Media platform lane (`inneranimalmedia`).
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
/** @deprecated Use DEFAULT_IAM_ORIGIN from the auth configuration contract. */
|
|
15
16
|
export const DEFAULT_IAM_OAUTH_ISSUER = DEFAULT_IAM_ORIGIN;
|
|
16
17
|
export const IAM_PLATFORM_STATE_PROVIDER = 'iam_platform';
|
|
17
|
-
|
|
18
|
+
/** Canonical platform OAuth callback (protocol id = inneranimalmedia). */
|
|
19
|
+
export const IAM_PLATFORM_CALLBACK_PATH = '/api/oauth/inneranimalmedia/callback';
|
|
20
|
+
/** @deprecated Legacy path — still accepted; prefer IAM_PLATFORM_CALLBACK_PATH. */
|
|
21
|
+
export const IAM_PLATFORM_CALLBACK_PATH_LEGACY = '/api/oauth/iam/callback';
|
|
18
22
|
|
|
19
23
|
/**
|
|
20
24
|
* @param {Record<string, unknown> | null | undefined} env
|
|
@@ -42,9 +46,9 @@ export function requireIamPlatformCredentials(env) {
|
|
|
42
46
|
|
|
43
47
|
/**
|
|
44
48
|
* @param {Record<string, unknown> | null | undefined} env
|
|
45
|
-
* @param {'google' | 'github' | 'iam'} provider
|
|
49
|
+
* @param {'google' | 'github' | 'cloudflare' | 'inneranimalmedia' | 'iam'} provider
|
|
46
50
|
* @returns {{
|
|
47
|
-
* lane: 'iam_platform' | 'byok_google' | 'byok_github',
|
|
51
|
+
* lane: 'iam_platform' | 'byok_google' | 'byok_github' | 'byok_cloudflare',
|
|
48
52
|
* clientId: string,
|
|
49
53
|
* clientSecret: string,
|
|
50
54
|
* origin?: string,
|
|
@@ -53,7 +57,10 @@ export function requireIamPlatformCredentials(env) {
|
|
|
53
57
|
* } | null}
|
|
54
58
|
*/
|
|
55
59
|
export function resolveOAuthCredentialLane(env, provider) {
|
|
56
|
-
|
|
60
|
+
const key = String(provider || '').trim().toLowerCase();
|
|
61
|
+
|
|
62
|
+
// Protocol/selection id is inneranimalmedia; `iam` remains a legacy alias.
|
|
63
|
+
if (key === 'inneranimalmedia' || key === 'iam') {
|
|
57
64
|
const iam = resolveIamPlatformCredentials(env);
|
|
58
65
|
if (!iam) return null;
|
|
59
66
|
return {
|
|
@@ -62,24 +69,37 @@ export function resolveOAuthCredentialLane(env, provider) {
|
|
|
62
69
|
clientSecret: iam.clientSecret,
|
|
63
70
|
origin: iam.origin,
|
|
64
71
|
issuer: iam.issuer,
|
|
65
|
-
provider: '
|
|
72
|
+
provider: 'inneranimalmedia',
|
|
66
73
|
};
|
|
67
74
|
}
|
|
68
75
|
|
|
69
|
-
if (
|
|
76
|
+
if (key === 'google') {
|
|
70
77
|
const clientId = String(env?.GOOGLE_CLIENT_ID || '').trim();
|
|
71
78
|
const clientSecret = String(env?.GOOGLE_CLIENT_SECRET || '').trim();
|
|
72
79
|
if (clientId && clientSecret) {
|
|
73
|
-
return { lane: 'byok_google', clientId, clientSecret, provider };
|
|
80
|
+
return { lane: 'byok_google', clientId, clientSecret, provider: 'google' };
|
|
74
81
|
}
|
|
75
82
|
}
|
|
76
83
|
|
|
77
|
-
if (
|
|
84
|
+
if (key === 'github') {
|
|
78
85
|
const clientId = String(env?.GITHUB_CLIENT_ID || '').trim();
|
|
79
86
|
const clientSecret = String(env?.GITHUB_CLIENT_SECRET || '').trim();
|
|
80
87
|
if (clientId && clientSecret) {
|
|
81
|
-
return { lane: 'byok_github', clientId, clientSecret, provider };
|
|
88
|
+
return { lane: 'byok_github', clientId, clientSecret, provider: 'github' };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (key === 'cloudflare') {
|
|
93
|
+
// Reuses the same Worker secrets as the Local Studio Cloudflare resource
|
|
94
|
+
// connector (packages/connectors/cloudflare). clientSecret may be empty
|
|
95
|
+
// if that client is configured as PKCE-only (Token Authentication
|
|
96
|
+
// Method = None) — exchangeCloudflareCode() omits it in that case.
|
|
97
|
+
const clientId = String(env?.CLOUDFLARE_OAUTH_CLIENT_ID || '').trim();
|
|
98
|
+
const clientSecret = String(env?.CLOUDFLARE_OAUTH_CLIENT_SECRET || '').trim();
|
|
99
|
+
if (clientId) {
|
|
100
|
+
return { lane: 'byok_cloudflare', clientId, clientSecret, provider: 'cloudflare' };
|
|
82
101
|
}
|
|
102
|
+
return null;
|
|
83
103
|
}
|
|
84
104
|
|
|
85
105
|
// Default: Google/GitHub buttons route through IAM platform when minted.
|
|
@@ -91,7 +111,7 @@ export function resolveOAuthCredentialLane(env, provider) {
|
|
|
91
111
|
clientSecret: iam.clientSecret,
|
|
92
112
|
origin: iam.origin,
|
|
93
113
|
issuer: iam.issuer,
|
|
94
|
-
provider,
|
|
114
|
+
provider: 'inneranimalmedia',
|
|
95
115
|
};
|
|
96
116
|
}
|
|
97
117
|
|
|
@@ -51,7 +51,7 @@ export function createFinalizeInboundOAuth(ports) {
|
|
|
51
51
|
? String(input.supabaseUserId).trim()
|
|
52
52
|
: null;
|
|
53
53
|
const source = String(input?.source || `${provider}_oauth`).trim();
|
|
54
|
-
const pageContext = String(input?.pageContext || '/
|
|
54
|
+
const pageContext = String(input?.pageContext || '/').trim();
|
|
55
55
|
|
|
56
56
|
if (!ports.hasDatabase(env) || !oauthEmail || !provider || !providerUid) {
|
|
57
57
|
return /** @type {InboundOAuthFailure} */ ({ ok: false, error: 'provision_failed' });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IDENTITY_ROUTE_IDS } from '../contracts/route-ids.js';
|
|
2
2
|
import {
|
|
3
3
|
IAM_PLATFORM_CALLBACK_PATH,
|
|
4
4
|
IAM_PLATFORM_STATE_PROVIDER,
|
|
@@ -19,7 +19,7 @@ import { normalizeIamIdentity } from '../providers/iam/mapper.js';
|
|
|
19
19
|
* @param {Record<string, unknown>} env
|
|
20
20
|
* @param {import('../adapters/cloudflare-d1/index.js').CloudflareD1Adapter} adapter
|
|
21
21
|
*/
|
|
22
|
-
export async function iamPlatformOAuthStart(request, env, adapter) {
|
|
22
|
+
export async function iamPlatformOAuthStart(request, env, adapter, identity) {
|
|
23
23
|
const creds = resolveIamPlatformCredentials(env);
|
|
24
24
|
if (!creds) {
|
|
25
25
|
return Response.json({ ok: false, error: 'iam_oauth_not_configured' }, 503);
|
|
@@ -29,15 +29,16 @@ export async function iamPlatformOAuthStart(request, env, adapter) {
|
|
|
29
29
|
const state = randomOAuthState();
|
|
30
30
|
const codeVerifier = pkceVerifier();
|
|
31
31
|
const codeChallenge = await pkceChallenge(codeVerifier);
|
|
32
|
-
const redirectTo =
|
|
33
|
-
|| url.searchParams.get('return_to')
|
|
34
|
-
|
|
32
|
+
const redirectTo = identity?.resolvePostLoginPath(
|
|
33
|
+
url.searchParams.get('next') || url.searchParams.get('return_to'),
|
|
34
|
+
) || '/';
|
|
35
35
|
|
|
36
36
|
await adapter.saveOAuthState({
|
|
37
37
|
state,
|
|
38
38
|
provider: IAM_PLATFORM_STATE_PROVIDER,
|
|
39
39
|
codeVerifier,
|
|
40
40
|
redirectTo,
|
|
41
|
+
appId: identity?.app?.id || null,
|
|
41
42
|
});
|
|
42
43
|
|
|
43
44
|
const redirectUri = `${url.origin}${IAM_PLATFORM_CALLBACK_PATH}`;
|
|
@@ -67,15 +68,15 @@ export async function iamPlatformOAuthCallback(request, env, adapter, identity)
|
|
|
67
68
|
const err = url.searchParams.get('error');
|
|
68
69
|
|
|
69
70
|
if (err || !code || !state) {
|
|
70
|
-
return Response.redirect(`${url.origin}${
|
|
71
|
+
return Response.redirect(`${url.origin}${identity.routeRegistry.resolve(identity.app.id, IDENTITY_ROUTE_IDS.LOGIN)}?error=oauth_failed`, 302);
|
|
71
72
|
}
|
|
72
73
|
if (!creds) {
|
|
73
|
-
return Response.redirect(`${url.origin}${
|
|
74
|
+
return Response.redirect(`${url.origin}${identity.routeRegistry.resolve(identity.app.id, IDENTITY_ROUTE_IDS.LOGIN)}?error=iam_oauth_not_configured`, 302);
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
const saved = await adapter.consumeOAuthState(state);
|
|
77
78
|
if (!saved || saved.provider !== IAM_PLATFORM_STATE_PROVIDER) {
|
|
78
|
-
return Response.redirect(`${url.origin}${
|
|
79
|
+
return Response.redirect(`${url.origin}${identity.routeRegistry.resolve(identity.app.id, IDENTITY_ROUTE_IDS.LOGIN)}?error=state_mismatch`, 302);
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
const redirectUri = `${url.origin}${IAM_PLATFORM_CALLBACK_PATH}`;
|
|
@@ -88,7 +89,7 @@ export async function iamPlatformOAuthCallback(request, env, adapter, identity)
|
|
|
88
89
|
redirectUri,
|
|
89
90
|
});
|
|
90
91
|
if (!token?.access_token) {
|
|
91
|
-
return Response.redirect(`${url.origin}${
|
|
92
|
+
return Response.redirect(`${url.origin}${identity.routeRegistry.resolve(identity.app.id, IDENTITY_ROUTE_IDS.LOGIN)}?error=token_exchange_failed`, 302);
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
const profile = await fetchIamProfile({
|
|
@@ -97,7 +98,7 @@ export async function iamPlatformOAuthCallback(request, env, adapter, identity)
|
|
|
97
98
|
});
|
|
98
99
|
const normalized = profile ? normalizeIamIdentity(profile) : null;
|
|
99
100
|
if (!normalized?.subject || !normalized?.email) {
|
|
100
|
-
return Response.redirect(`${url.origin}${
|
|
101
|
+
return Response.redirect(`${url.origin}${identity.routeRegistry.resolve(identity.app.id, IDENTITY_ROUTE_IDS.LOGIN)}?error=userinfo_failed`, 302);
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
const result = await identity.provisionOAuthUser({
|
|
@@ -107,9 +108,9 @@ export async function iamPlatformOAuthCallback(request, env, adapter, identity)
|
|
|
107
108
|
displayName: normalized.name || normalized.email.split('@')[0] || 'User',
|
|
108
109
|
});
|
|
109
110
|
|
|
110
|
-
const redirectTo = saved.redirect_to
|
|
111
|
+
const redirectTo = identity.resolvePostLoginPath(saved.redirect_to);
|
|
111
112
|
const res = identity.buildLoginSuccessResponse(request, result.sessionId, redirectTo);
|
|
112
|
-
const globeUrl = `${url.origin}${
|
|
113
|
+
const globeUrl = `${url.origin}${identity.routeRegistry.resolve(identity.app.id, IDENTITY_ROUTE_IDS.LOGIN)}?globe_exit=1&next=${encodeURIComponent(redirectTo)}`;
|
|
113
114
|
return new Response(null, {
|
|
114
115
|
status: 302,
|
|
115
116
|
headers: {
|
|
@@ -1,29 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Post-OAuth redirect helpers — portable path policy with host injectables.
|
|
3
|
+
* Hosts MUST pass loginPath from their route projection (never hardcode).
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
import { sanitizeBrowserNextPath } from '../core/browser-paths.js';
|
|
7
|
+
import { IdentityRoutingError } from '../contracts/identity-store.js';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* @typedef {object} OAuthRedirectPathOptions
|
|
9
11
|
* @property {string} [authCookieName]
|
|
10
|
-
* @property {string}
|
|
12
|
+
* @property {string} loginPath concrete projection of identity.login
|
|
13
|
+
* @property {string} [fallback] only used when isAllowedLoginResumePath rejects; prefer omit
|
|
11
14
|
* @property {(path: string) => boolean} [isAllowedLoginResumePath]
|
|
12
15
|
* @property {(env: unknown, rawCookie: string) => Promise<string|null>} [resolveSessionIdFromCookie]
|
|
13
16
|
* @property {(env: unknown, sessionId: string, reason: string, userId: string|null) => Promise<void>} [revokeAuthSession]
|
|
14
17
|
*/
|
|
15
18
|
|
|
16
|
-
/**
|
|
17
|
-
* @param {OAuthRedirectPathOptions} options
|
|
18
|
-
*/
|
|
19
19
|
export function createOAuthRedirectHelpers(options = {}) {
|
|
20
20
|
const authCookieName = options.authCookieName ?? 'iam_session';
|
|
21
|
-
const
|
|
22
|
-
|
|
21
|
+
const loginPath = options.loginPath;
|
|
22
|
+
if (!loginPath || !String(loginPath).startsWith('/')) {
|
|
23
|
+
throw new IdentityRoutingError(
|
|
24
|
+
'AUTH_ROUTE_MISSING',
|
|
25
|
+
'createOAuthRedirectHelpers requires loginPath from route projection',
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
const isAllowedLoginResumePath = options.isAllowedLoginResumePath
|
|
29
|
+
?? ((path) => Boolean(sanitizeBrowserNextPath(path)));
|
|
23
30
|
const resolveSessionIdFromCookie = options.resolveSessionIdFromCookie;
|
|
24
31
|
const revokeAuthSession = options.revokeAuthSession;
|
|
25
32
|
|
|
26
|
-
/** Revoke browser cookie session before issuing a new login session. */
|
|
27
33
|
async function revokeIncomingCookieSession(request, env, reason = 'oauth_login_replaced') {
|
|
28
34
|
const cookie = request.headers.get('Cookie') || '';
|
|
29
35
|
const match = cookie.match(new RegExp(`(?:^|;\\s*)${authCookieName}=([^;]+)`));
|
|
@@ -45,48 +51,33 @@ export function createOAuthRedirectHelpers(options = {}) {
|
|
|
45
51
|
}
|
|
46
52
|
}
|
|
47
53
|
|
|
48
|
-
function
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (t.startsWith('/') && !t.startsWith('//') && !t.includes('://')) {
|
|
53
|
-
if (isAllowedLoginResumePath(t)) return t;
|
|
54
|
-
if (t.startsWith('/dashboard/settings/integrations')) return dashboardFallback;
|
|
55
|
-
if (!t.startsWith('/dashboard')) return dashboardFallback;
|
|
56
|
-
return t;
|
|
54
|
+
function safeLoginRedirectPath(_originBase, returnTo) {
|
|
55
|
+
const cleaned = sanitizeBrowserNextPath(returnTo);
|
|
56
|
+
if (!cleaned) {
|
|
57
|
+
throw new IdentityRoutingError('AUTH_DESTINATION_UNRESOLVED', 'return_to missing/invalid');
|
|
57
58
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const ob = new URL(originBase);
|
|
61
|
-
if (u.origin !== ob.origin) return dashboardFallback;
|
|
62
|
-
const p = u.pathname + (u.search || '');
|
|
63
|
-
if (p.startsWith('/dashboard/settings/integrations')) return dashboardFallback;
|
|
64
|
-
if (!p.startsWith('/dashboard')) return dashboardFallback;
|
|
65
|
-
return p;
|
|
66
|
-
} catch {
|
|
67
|
-
return dashboardFallback;
|
|
59
|
+
if (!isAllowedLoginResumePath(cleaned)) {
|
|
60
|
+
throw new IdentityRoutingError('AUTH_DESTINATION_UNRESOLVED', 'return_to not allowed', { returnTo: cleaned });
|
|
68
61
|
}
|
|
62
|
+
return cleaned;
|
|
69
63
|
}
|
|
70
64
|
|
|
71
65
|
function oauthPostLoginGlobeRedirectUrl(originBase, returnToFullUrl) {
|
|
72
|
-
let path
|
|
66
|
+
let path;
|
|
73
67
|
try {
|
|
74
68
|
const u = new URL(returnToFullUrl);
|
|
75
69
|
path = u.pathname + (u.search || '');
|
|
76
70
|
} catch {
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
if (!path.startsWith('/') || path.startsWith('//')) path = dashboardFallback;
|
|
80
|
-
if (path.startsWith('/dashboard/settings/integrations')) path = dashboardFallback;
|
|
81
|
-
if (!isAllowedLoginResumePath(path) && !path.startsWith('/dashboard')) {
|
|
82
|
-
path = dashboardFallback;
|
|
71
|
+
throw new IdentityRoutingError('AUTH_DESTINATION_UNRESOLVED', 'invalid returnToFullUrl');
|
|
83
72
|
}
|
|
84
|
-
|
|
73
|
+
path = safeLoginRedirectPath(originBase, path);
|
|
74
|
+
return `${originBase}${loginPath}?globe_exit=1&next=${encodeURIComponent(path)}`;
|
|
85
75
|
}
|
|
86
76
|
|
|
87
77
|
return {
|
|
88
78
|
revokeIncomingCookieSession,
|
|
89
|
-
safeDashboardLoginRedirectPath,
|
|
79
|
+
safeDashboardLoginRedirectPath: safeLoginRedirectPath,
|
|
80
|
+
safeLoginRedirectPath,
|
|
90
81
|
oauthPostLoginGlobeRedirectUrl,
|
|
91
82
|
};
|
|
92
83
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createIdentityProvider } from '../../provider-contract.js';
|
|
2
|
+
import { exchangeCloudflareCode, getCloudflareAuthUrl } from './oauth.js';
|
|
3
|
+
import { fetchCloudflareProfile } from './profile.js';
|
|
4
|
+
import { normalizeCloudflareIdentity } from './mapper.js';
|
|
5
|
+
|
|
6
|
+
export const CloudflareProvider = createIdentityProvider({
|
|
7
|
+
id: 'cloudflare',
|
|
8
|
+
authorizeUrl: getCloudflareAuthUrl,
|
|
9
|
+
exchangeCode: exchangeCloudflareCode,
|
|
10
|
+
getProfile: fetchCloudflareProfile,
|
|
11
|
+
normalizeIdentity: normalizeCloudflareIdentity,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
getCloudflareAuthUrl,
|
|
16
|
+
exchangeCloudflareCode,
|
|
17
|
+
fetchCloudflareProfile,
|
|
18
|
+
normalizeCloudflareIdentity,
|
|
19
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { normalizeExternalIdentity } from '../../contracts/external-identity.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {Record<string, unknown>|null|undefined} profile
|
|
5
|
+
*/
|
|
6
|
+
export function normalizeCloudflareIdentity(profile) {
|
|
7
|
+
const raw = profile && typeof profile === 'object' ? profile : {};
|
|
8
|
+
const subject = String(raw.sub || raw.id || raw.user_id || raw.account_id || '').trim();
|
|
9
|
+
if (!subject) {
|
|
10
|
+
throw new Error('cloudflare_identity_requires_subject');
|
|
11
|
+
}
|
|
12
|
+
return normalizeExternalIdentity({
|
|
13
|
+
provider: 'cloudflare',
|
|
14
|
+
subject,
|
|
15
|
+
email: typeof raw.email === 'string' ? raw.email : null,
|
|
16
|
+
emailVerified: Boolean(raw.email),
|
|
17
|
+
name: typeof raw.name === 'string' ? raw.name : (typeof raw.display_name === 'string' ? raw.display_name : null),
|
|
18
|
+
avatar: null,
|
|
19
|
+
raw,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const CLOUDFLARE_AUTH_URL = 'https://dash.cloudflare.com/oauth2/auth';
|
|
2
|
+
const CLOUDFLARE_TOKEN_URL = 'https://dash.cloudflare.com/oauth2/token';
|
|
3
|
+
|
|
4
|
+
// Identity-only login should not request the full resource-access scope set
|
|
5
|
+
// used elsewhere for the Local Studio Cloudflare *connection* (deploy/d1/r2/etc).
|
|
6
|
+
// account-settings.read is enough to resolve the account for userinfo.
|
|
7
|
+
const CLOUDFLARE_LOGIN_SCOPE = 'account-settings.read offline_access';
|
|
8
|
+
|
|
9
|
+
/** @param {import('../../provider-contract.js').OAuthAuthorizeInput} input */
|
|
10
|
+
export function getCloudflareAuthUrl({ clientId, redirectUri, state, codeChallenge, scope } = {}) {
|
|
11
|
+
const url = new URL(CLOUDFLARE_AUTH_URL);
|
|
12
|
+
url.searchParams.set('client_id', clientId || '');
|
|
13
|
+
url.searchParams.set('redirect_uri', redirectUri || '');
|
|
14
|
+
url.searchParams.set('response_type', 'code');
|
|
15
|
+
url.searchParams.set('scope', scope || CLOUDFLARE_LOGIN_SCOPE);
|
|
16
|
+
url.searchParams.set('state', state || '');
|
|
17
|
+
if (codeChallenge) {
|
|
18
|
+
url.searchParams.set('code_challenge', codeChallenge);
|
|
19
|
+
url.searchParams.set('code_challenge_method', 'S256');
|
|
20
|
+
}
|
|
21
|
+
return url.toString();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** @param {import('../../provider-contract.js').OAuthExchangeInput} input */
|
|
25
|
+
export async function exchangeCloudflareCode({ code, codeVerifier, clientId, clientSecret, redirectUri }) {
|
|
26
|
+
try {
|
|
27
|
+
const body = new URLSearchParams();
|
|
28
|
+
body.set('grant_type', 'authorization_code');
|
|
29
|
+
body.set('code', code || '');
|
|
30
|
+
body.set('code_verifier', codeVerifier || '');
|
|
31
|
+
body.set('client_id', clientId || '');
|
|
32
|
+
// client_secret is only sent when configured — the client may be a
|
|
33
|
+
// PKCE-only public client (Token Authentication Method = None), same
|
|
34
|
+
// pattern as the Local Studio resource connector.
|
|
35
|
+
if (clientSecret) body.set('client_secret', clientSecret);
|
|
36
|
+
body.set('redirect_uri', redirectUri || '');
|
|
37
|
+
|
|
38
|
+
const res = await fetch(CLOUDFLARE_TOKEN_URL, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
41
|
+
body,
|
|
42
|
+
});
|
|
43
|
+
if (!res.ok) return null;
|
|
44
|
+
return await res.json();
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const CLOUDFLARE_USERINFO_URL = 'https://dash.cloudflare.com/oauth2/userinfo';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Fetch the authenticated Cloudflare user's identity.
|
|
5
|
+
* Response shape not fully verified against a live token yet — this reads
|
|
6
|
+
* defensively (sub/id/user_id, email, name) rather than assuming Cloudflare's
|
|
7
|
+
* exact OIDC field names. Confirm the real shape on first live login and
|
|
8
|
+
* tighten this if fields differ.
|
|
9
|
+
* @param {string} accessToken
|
|
10
|
+
*/
|
|
11
|
+
export async function fetchCloudflareProfile(accessToken) {
|
|
12
|
+
try {
|
|
13
|
+
const res = await fetch(CLOUDFLARE_USERINFO_URL, {
|
|
14
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
15
|
+
});
|
|
16
|
+
if (!res.ok) return null;
|
|
17
|
+
const data = await res.json();
|
|
18
|
+
if (!data) return null;
|
|
19
|
+
return {
|
|
20
|
+
sub: data.sub || data.id || data.user_id || data.account_id || null,
|
|
21
|
+
email: data.email || null,
|
|
22
|
+
name: data.name || data.display_name || null,
|
|
23
|
+
raw: data,
|
|
24
|
+
};
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -4,19 +4,28 @@ import { GithubProvider } from './github/index.js';
|
|
|
4
4
|
import { GcpProvider } from './gcp/index.js';
|
|
5
5
|
import { EmailProvider } from './email/index.js';
|
|
6
6
|
import { IamProvider } from './iam/index.js';
|
|
7
|
+
import { CloudflareProvider } from './cloudflare/index.js';
|
|
7
8
|
|
|
8
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Active identity provider registry.
|
|
11
|
+
* `inneranimalmedia` is the canonical platform template id; `iam` remains a
|
|
12
|
+
* legacy lookup alias (OAuth/DB provider key on platform identities).
|
|
13
|
+
* @type {Record<string, import('../provider-contract.js').IdentityProvider>}
|
|
14
|
+
*/
|
|
9
15
|
export const identityProviders = Object.freeze({
|
|
10
16
|
google: GoogleProvider,
|
|
11
17
|
github: GithubProvider,
|
|
12
18
|
gcp: GcpProvider,
|
|
13
19
|
email: EmailProvider,
|
|
20
|
+
inneranimalmedia: IamProvider,
|
|
14
21
|
iam: IamProvider,
|
|
22
|
+
cloudflare: CloudflareProvider,
|
|
15
23
|
});
|
|
16
24
|
|
|
17
25
|
/** @param {string} id */
|
|
18
26
|
export function getIdentityProvider(id) {
|
|
19
27
|
const key = String(id || '').trim().toLowerCase();
|
|
28
|
+
if (key === 'iam') return identityProviders.inneranimalmedia || identityProviders.iam || null;
|
|
20
29
|
return identityProviders[key] || null;
|
|
21
30
|
}
|
|
22
31
|
|
|
@@ -24,4 +33,11 @@ export function listIdentityProviders() {
|
|
|
24
33
|
return IdentityProviders.map((id) => identityProviders[id]).filter(Boolean);
|
|
25
34
|
}
|
|
26
35
|
|
|
27
|
-
export {
|
|
36
|
+
export {
|
|
37
|
+
GoogleProvider,
|
|
38
|
+
GithubProvider,
|
|
39
|
+
GcpProvider,
|
|
40
|
+
EmailProvider,
|
|
41
|
+
IamProvider,
|
|
42
|
+
CloudflareProvider,
|
|
43
|
+
};
|
|
@@ -1,24 +1,48 @@
|
|
|
1
|
-
import { AUTH_COOKIE_NAME,
|
|
1
|
+
import { AUTH_COOKIE_NAME, SESSION_POLICY } from '../core/constants.js';
|
|
2
2
|
import { hashPassword, verifyPassword } from '../core/password-crypto.js';
|
|
3
3
|
import { jsonResponse } from '../core/http-json.js';
|
|
4
|
-
import {
|
|
4
|
+
import { resolvePostAuthDestination } from './post-auth.js';
|
|
5
|
+
import { IdentityRoutingError } from '../contracts/identity-store.js';
|
|
5
6
|
import { newAuthUserId } from '../adapters/cloudflare-d1/ids.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* @typedef {
|
|
9
|
+
* @typedef {import('../contracts/identity-store.js').IdentityStore} IdentityStore
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Server-side identity orchestration (Worker / Node). No secrets in client bundle.
|
|
13
|
-
*
|
|
14
|
+
* Hosts must supply `app` + `routeRegistry` — no platform "/" fallback.
|
|
15
|
+
*
|
|
16
|
+
* @param {{
|
|
17
|
+
* adapter: IdentityStore,
|
|
18
|
+
* cookieName?: string,
|
|
19
|
+
* app: { id: string },
|
|
20
|
+
* routeRegistry: ReturnType<import('../contracts/route-projection.js').createRouteRegistry>,
|
|
21
|
+
* }} config
|
|
14
22
|
*/
|
|
15
23
|
export function createIdentityService(config) {
|
|
16
24
|
const adapter = config.adapter;
|
|
17
25
|
if (!adapter) throw new Error('identity_service_requires_adapter');
|
|
18
26
|
const cookieName = config.cookieName || AUTH_COOKIE_NAME;
|
|
19
|
-
const
|
|
27
|
+
const app = config.app || null;
|
|
28
|
+
const routeRegistry = config.routeRegistry || null;
|
|
29
|
+
if (!app?.id || !routeRegistry) {
|
|
30
|
+
throw new IdentityRoutingError(
|
|
31
|
+
'AUTH_APP_UNRESOLVED',
|
|
32
|
+
'createIdentityService requires app + routeRegistry (no platform fallback)',
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
routeRegistry.assertAuthCapable(app.id);
|
|
36
|
+
|
|
37
|
+
function resolvePostLoginPath(nextPath) {
|
|
38
|
+
return resolvePostAuthDestination({
|
|
39
|
+
transaction: { return_to: nextPath, app_id: app.id },
|
|
40
|
+
app,
|
|
41
|
+
routeRegistry,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
20
44
|
|
|
21
|
-
function sessionCookieHeader(sessionId, requestUrl, maxAge =
|
|
45
|
+
function sessionCookieHeader(sessionId, requestUrl, maxAge = SESSION_POLICY.browser.ttlSeconds) {
|
|
22
46
|
const secure = new URL(requestUrl).protocol === 'https:';
|
|
23
47
|
const parts = [
|
|
24
48
|
`${cookieName}=${sessionId}`,
|
|
@@ -39,7 +63,9 @@ export function createIdentityService(config) {
|
|
|
39
63
|
|
|
40
64
|
return Object.freeze({
|
|
41
65
|
cookieName,
|
|
42
|
-
|
|
66
|
+
app,
|
|
67
|
+
routeRegistry,
|
|
68
|
+
defaultRedirect: resolvePostLoginPath(null),
|
|
43
69
|
|
|
44
70
|
async signup({ email, password, displayName }) {
|
|
45
71
|
const normalized = String(email || '').trim().toLowerCase();
|
|
@@ -127,7 +153,7 @@ export function createIdentityService(config) {
|
|
|
127
153
|
},
|
|
128
154
|
|
|
129
155
|
buildLoginSuccessResponse(request, sessionId, nextPath) {
|
|
130
|
-
const redirect =
|
|
156
|
+
const redirect = resolvePostLoginPath(nextPath);
|
|
131
157
|
return jsonResponse(
|
|
132
158
|
{ ok: true, redirect },
|
|
133
159
|
200,
|
|
@@ -150,6 +176,7 @@ export function createIdentityService(config) {
|
|
|
150
176
|
|
|
151
177
|
parseSessionId,
|
|
152
178
|
sessionCookieHeader,
|
|
179
|
+
resolvePostLoginPath,
|
|
153
180
|
});
|
|
154
181
|
}
|
|
155
182
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mount-level auth policy helpers (host applies; identity does not invent mounts).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {{ path: string, auth?: 'required'|'optional'|'public', spa?: boolean, shell?: string }} AppMount
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export function pathMatchesMount(pathname, mount) {
|
|
10
|
+
const base = String(mount?.path || '');
|
|
11
|
+
if (!base) return false;
|
|
12
|
+
const path = String(pathname || '');
|
|
13
|
+
return path === base || path.startsWith(`${base}/`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function resolveMountForPath(pathname, app) {
|
|
17
|
+
const mounts = Array.isArray(app?.routes?.mounts) ? app.routes.mounts : [];
|
|
18
|
+
let best = null;
|
|
19
|
+
for (const mount of mounts) {
|
|
20
|
+
if (!pathMatchesMount(pathname, mount)) continue;
|
|
21
|
+
if (!best || String(mount.path).length > String(best.path).length) best = mount;
|
|
22
|
+
}
|
|
23
|
+
return best;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function mountRequiresAuth(pathname, app) {
|
|
27
|
+
const mount = resolveMountForPath(pathname, app);
|
|
28
|
+
if (!mount) return false;
|
|
29
|
+
return (mount.auth || 'public') === 'required';
|
|
30
|
+
}
|