@inneranimalmedia/agentsam-sdk 2.6.5 → 2.6.7
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/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/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/native/agentsam-machine/Cargo.lock +426 -0
- package/native/agentsam-machine/Cargo.toml +9 -0
- package/native/agentsam-machine/cli/Cargo.toml +14 -0
- package/native/agentsam-machine/cli/src/main.rs +77 -0
- package/native/agentsam-machine/core/Cargo.toml +15 -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 +1086 -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 +51 -21
- 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-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/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/source-types.js +8 -0
- 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 +13 -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/skills/grok-auth/SKILL.md +110 -0
- package/skills/grok-auth/agentsam.skill.json +25 -0
- package/skills/grok-auth/references/grok-identity.md +64 -0
- package/skills/grok-auth/references/per-user-data.md +49 -0
- package/skills/grok-auth/references/prewired-and-env.md +54 -0
- package/skills/grok-auth/references/session-ui.md +133 -0
- package/skills/grok-auth/references/sign-in-methods.md +55 -0
- package/skills/grok-auth/references/wiring.md +71 -0
- package/skills/grok-building-games/SKILL.md +213 -0
- package/skills/grok-building-games/agentsam.skill.json +25 -0
- package/skills/grok-building-games/references/3d-libs.md +64 -0
- package/skills/grok-building-games/references/ai-pathfinding.md +122 -0
- package/skills/grok-building-games/references/audio.md +129 -0
- package/skills/grok-building-games/references/babylon.md +202 -0
- package/skills/grok-building-games/references/collision-physics.md +122 -0
- package/skills/grok-building-games/references/ecs-architecture.md +111 -0
- package/skills/grok-building-games/references/game-feel-juice.md +110 -0
- package/skills/grok-building-games/references/genres/board-card-chess.md +89 -0
- package/skills/grok-building-games/references/genres/endless-runner.md +83 -0
- package/skills/grok-building-games/references/genres/fps.md +105 -0
- package/skills/grok-building-games/references/genres/platformer-2d.md +97 -0
- package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +131 -0
- package/skills/grok-building-games/references/genres/racing-kart.md +106 -0
- package/skills/grok-building-games/references/genres/topdown-twin-stick.md +97 -0
- package/skills/grok-building-games/references/genres/tower-defense.md +84 -0
- package/skills/grok-building-games/references/genres/voxel-minecraft.md +89 -0
- package/skills/grok-building-games/references/input.md +139 -0
- package/skills/grok-building-games/references/phaser.md +277 -0
- package/skills/grok-building-games/references/procedural-generation.md +141 -0
- package/skills/grok-building-games/references/save-persistence.md +108 -0
- package/skills/grok-building-games/references/threejs-foundational.md +148 -0
- package/skills/grok-controls/SKILL.md +274 -0
- package/skills/grok-controls/agentsam.skill.json +25 -0
- package/skills/grok-design-ui/SKILL.md +122 -0
- package/skills/grok-design-ui/agentsam.skill.json +25 -0
- package/skills/grok-design-ui/references/animations.md +379 -0
- package/skills/grok-design-ui/references/performance.md +88 -0
- package/skills/grok-design-ui/references/refined-ui.md +384 -0
- package/skills/grok-design-ui/references/surfaces.md +247 -0
- package/skills/grok-design-ui/references/typography.md +123 -0
- package/skills/grok-game-animation-frames/SKILL.md +84 -0
- package/skills/grok-game-animation-frames/agentsam.skill.json +25 -0
- package/skills/grok-game-asset-core/SKILL.md +69 -0
- package/skills/grok-game-asset-core/agentsam.skill.json +25 -0
- package/skills/grok-game-character-consistency/SKILL.md +69 -0
- package/skills/grok-game-character-consistency/agentsam.skill.json +25 -0
- package/skills/grok-game-tilesets/SKILL.md +65 -0
- package/skills/grok-game-tilesets/agentsam.skill.json +25 -0
- package/skills/grok-game-ui-icons/SKILL.md +56 -0
- package/skills/grok-game-ui-icons/agentsam.skill.json +25 -0
- package/skills/grok-generate2dmap/LICENSE +21 -0
- package/skills/grok-generate2dmap/SKILL.md +120 -0
- package/skills/grok-generate2dmap/SOURCE.md +6 -0
- package/skills/grok-generate2dmap/agentsam.skill.json +25 -0
- package/skills/grok-generate2dmap/references/deliverables.md +101 -0
- package/skills/grok-generate2dmap/references/layered-map-contract.md +209 -0
- package/skills/grok-generate2dmap/references/map-strategies.md +341 -0
- package/skills/grok-generate2dmap/references/object-production-gate.md +24 -0
- package/skills/grok-generate2dmap/references/pipeline.md +149 -0
- package/skills/grok-generate2dmap/references/prop-pack-contract.md +174 -0
- package/skills/grok-generate2dmap/references/side-scroll-stages.md +29 -0
- package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +157 -0
- package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +369 -0
- package/skills/grok-generate2dsprite/LICENSE +21 -0
- package/skills/grok-generate2dsprite/SKILL.md +313 -0
- package/skills/grok-generate2dsprite/SOURCE.md +6 -0
- package/skills/grok-generate2dsprite/agentsam.skill.json +25 -0
- package/skills/grok-generate2dsprite/references/modes.md +124 -0
- package/skills/grok-generate2dsprite/references/prompt-rules.md +315 -0
- package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +1031 -0
- package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +109 -0
- package/skills/grok-imagine/SKILL.md +201 -0
- package/skills/grok-imagine/agentsam.skill.json +25 -0
- package/skills/grok-multiplayer-p2p/SKILL.md +111 -0
- package/skills/grok-multiplayer-p2p/agentsam.skill.json +25 -0
- package/skills/grok-multiplayer-p2p/references/react-binding.md +144 -0
- package/skills/grok-multiplayer-p2p/references/signaling-relay.md +269 -0
- package/skills/grok-neon/SKILL.md +157 -0
- package/skills/grok-neon/agentsam.skill.json +25 -0
- package/skills/grok-og/SKILL.md +102 -0
- package/skills/grok-og/agentsam.skill.json +25 -0
- package/skills/grok-og/references/brand-pass.md +53 -0
- package/skills/grok-og/references/custom-card.md +107 -0
- package/skills/grok-og/references/favicon-and-icons.md +48 -0
- package/skills/grok-og/references/og-type-contract.md +18 -0
- package/skills/grok-og/references/placeholder-card.md +21 -0
- package/skills/grok-og/references/x-banner.md +41 -0
- package/skills/grok-threejs/SKILL.md +67 -0
- package/skills/grok-threejs/agentsam.skill.json +25 -0
- package/skills/grok-threejs/references/llms-full.txt +2780 -0
- package/skills/grok-video2dsprite/LICENSE +21 -0
- package/skills/grok-video2dsprite/SKILL.md +236 -0
- package/skills/grok-video2dsprite/SOURCE.md +6 -0
- package/skills/grok-video2dsprite/agentsam.skill.json +25 -0
- package/skills/grok-video2dsprite/references/pipeline.md +90 -0
- package/skills/grok-video2dsprite/references/prompt-rules.md +63 -0
- package/skills/grok-video2dsprite/scripts/video2dsprite.py +490 -0
- package/skills/grok-xai-api/SKILL.md +152 -0
- package/skills/grok-xai-api/agentsam.skill.json +25 -0
- package/src/cli/command-catalog.js +46 -4
- package/src/cli/dispatch.js +1 -0
- package/src/cli.js +10 -0
- 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/knowledge.js +59 -2
- package/src/commands/machine-binary.js +103 -0
- package/src/commands/machine.js +137 -0
- package/src/commands/security.js +67 -4
- package/src/commands/setup.js +33 -16
- 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/lib/identity-scaffold.js +53 -13
- package/src/lib/setup/recipes.js +1 -1
- 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/security/logs.js +3 -0
- package/src/ui/cli/help.js +41 -0
- package/test/apps-scaffold-contract.test.mjs +3 -2
- package/test/cli/api-key-env-whoami.test.mjs +2 -2
- package/test/cli/catalog-authority.test.mjs +64 -0
- package/test/cli/machine-command.test.mjs +34 -0
- package/test/fixtures/project-authority/customer-app/.agentsam/app.json +5 -0
- package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +1 -0
- package/test/fixtures/project-authority/customer-app/wrangler.toml +17 -0
- package/test/integration/autorag-project-authority.integration.test.mjs +51 -0
- package/test/integration/autorag-runtime-discovery.test.mjs +107 -0
- package/test/integration/cms-app-scaffold.test.mjs +37 -31
- package/test/integration/cms-site-tenancy-contract.test.mjs +28 -17
- package/test/integration/codebaseindex-ingest.test.mjs +41 -0
- package/test/integration/database-hosted-honesty.test.mjs +49 -0
- package/test/integration/desktop-keychain-boundary.test.mjs +45 -0
- package/test/integration/hosted-work-host-authority.test.mjs +47 -0
- package/test/integration/inventory-eligibility.test.mjs +59 -0
- package/test/integration/local-provider-bridge.test.mjs +65 -0
- package/test/integration/local-studio-settings-production.test.mjs +40 -0
- package/test/integration/lockfile-sync.test.mjs +26 -0
- package/test/integration/provider-env-cli.test.mjs +13 -3
- package/test/integration/runtime-status.integration.test.mjs +16 -1
- package/test/integration/theme-package-registry.test.mjs +31 -0
- package/test/repository-snapshot-view.test.mjs +2 -2
- package/test/security.test.mjs +14 -0
- package/test/terminal-machine-identity.test.mjs +2 -2
- package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +0 -145
- package/packages/agentsam-nav/dist/Nav.d.ts +0 -43
- package/packages/agentsam-nav/dist/NavCollapsible.d.ts +0 -10
- package/packages/agentsam-nav/dist/NavContent.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavFooter.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavGroup.d.ts +0 -3
- package/packages/agentsam-nav/dist/NavHeader.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavMenu.d.ts +0 -22
- package/packages/agentsam-nav/dist/NavProvider.d.ts +0 -35
- package/packages/agentsam-nav/dist/NavTrigger.d.ts +0 -2
- package/packages/agentsam-nav/dist/Surfaces.d.ts +0 -41
- package/packages/agentsam-nav/dist/browser.d.ts +0 -11
- package/packages/agentsam-nav/dist/browser.global.js +0 -132
- package/packages/agentsam-nav/dist/browser.js +0 -613
- package/packages/agentsam-nav/dist/contracts.d.ts +0 -76
- package/packages/agentsam-nav/dist/index.d.ts +0 -11
- package/packages/agentsam-nav/dist/index.js +0 -614
- package/packages/agentsam-nav/dist/legacy.css +0 -83
- package/packages/agentsam-nav/dist/shell.css +0 -113
- package/packages/agentsam-nav/dist/theme.css +0 -113
- package/packages/agentsam-nav/dist/utils.d.ts +0 -1
- package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +0 -670
|
@@ -1,322 +1,23 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import {
|
|
5
|
-
IDENTITY_STORE_SCHEMA_VERSION,
|
|
6
|
-
IdentitySchemaError,
|
|
7
|
-
} from '../../contracts/identity-store.js';
|
|
8
|
-
import { newAccountIdentityId, newAuthEventId, newAuthUserId, newSessionId, nowUnix } from '../cloudflare-d1/ids.js';
|
|
9
|
-
import { SESSION_POLICY } from '../../core/constants.js';
|
|
10
|
-
|
|
11
|
-
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
-
export const SQLITE_MIGRATIONS_DIR = path.resolve(HERE, '../../../migrations/sqlite');
|
|
13
|
-
|
|
14
1
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* @param {{ prepare: Function }} db
|
|
19
|
-
* @param {{ includeOAuthServer?: boolean }} [opts]
|
|
2
|
+
* Local SQLite IdentityStore — portable identity_* schema, zero Cloudflare/IAM.
|
|
3
|
+
* Shares the portable store implementation because Node SQLite is exposed through
|
|
4
|
+
* the same prepare/bind/first/run shape as D1-shaped bindings.
|
|
20
5
|
*/
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
for (const file of files) {
|
|
32
|
-
const sql = fs.readFileSync(path.join(SQLITE_MIGRATIONS_DIR, file), 'utf8');
|
|
33
|
-
if (typeof db.exec === 'function') {
|
|
34
|
-
db.exec(sql);
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
// D1-shaped: run statement-by-statement (no multi-exec).
|
|
38
|
-
const stripped = sql.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
39
|
-
const statements = stripped
|
|
40
|
-
.split(';')
|
|
41
|
-
.map((s) => s.replace(/--[^\n]*/g, '').trim())
|
|
42
|
-
.filter(Boolean);
|
|
43
|
-
for (const statement of statements) {
|
|
44
|
-
await db.prepare(statement).run();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async function hashValue(value) {
|
|
50
|
-
const v = String(value || '').trim();
|
|
51
|
-
if (!v) return null;
|
|
52
|
-
const bytes = new TextEncoder().encode(v);
|
|
53
|
-
const digest = await crypto.subtle.digest('SHA-256', bytes);
|
|
54
|
-
return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
55
|
-
}
|
|
6
|
+
export {
|
|
7
|
+
applyPortableIdentityMigrations,
|
|
8
|
+
applySqliteIdentityMigrations,
|
|
9
|
+
PORTABLE_IDENTITY_MIGRATIONS_DIR,
|
|
10
|
+
SQLITE_MIGRATIONS_DIR,
|
|
11
|
+
resolveIdentitySchemaPack,
|
|
12
|
+
IDENTITY_SCHEMA_PACK_MANIFEST_PATH,
|
|
13
|
+
} from '../../../migrations/apply-portable.js';
|
|
56
14
|
|
|
57
|
-
|
|
58
|
-
let row;
|
|
59
|
-
try {
|
|
60
|
-
row = await db.prepare(
|
|
61
|
-
`SELECT value FROM identity_schema_meta WHERE key = 'schema_version' LIMIT 1`,
|
|
62
|
-
).bind().first();
|
|
63
|
-
} catch (err) {
|
|
64
|
-
throw new IdentitySchemaError(
|
|
65
|
-
'IDENTITY_SCHEMA_MIGRATION_REQUIRED',
|
|
66
|
-
'identity.core migrations not applied — run applySqliteIdentityMigrations()',
|
|
67
|
-
{ cause: String(err?.message || err) },
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
const version = Number(row?.value || 0);
|
|
71
|
-
if (version < IDENTITY_STORE_SCHEMA_VERSION) {
|
|
72
|
-
throw new IdentitySchemaError(
|
|
73
|
-
'IDENTITY_SCHEMA_MIGRATION_REQUIRED',
|
|
74
|
-
`identity schema_version=${version}, required=${IDENTITY_STORE_SCHEMA_VERSION}`,
|
|
75
|
-
{ version, required: IDENTITY_STORE_SCHEMA_VERSION },
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
15
|
+
import { createPortableIdentityStore } from '../portable-store.js';
|
|
79
16
|
|
|
80
17
|
/**
|
|
81
|
-
* Local SQLite IdentityStore — full offline identity, no Cloudflare/IAM.
|
|
82
18
|
* @param {{ prepare: Function }} db D1-shaped binding (see createLocalSqliteDatabase)
|
|
83
19
|
* @param {{ sessionTtlSeconds?: number, skipSchemaCheck?: boolean }} [options]
|
|
84
20
|
*/
|
|
85
21
|
export function createSqliteIdentityAdapter(db, options = {}) {
|
|
86
|
-
|
|
87
|
-
const sessionTtlSeconds = options.sessionTtlSeconds ?? SESSION_POLICY.browser.ttlSeconds;
|
|
88
|
-
let schemaReady = Boolean(options.skipSchemaCheck);
|
|
89
|
-
|
|
90
|
-
async function ensure() {
|
|
91
|
-
if (schemaReady) return;
|
|
92
|
-
await requireSchema(db);
|
|
93
|
-
schemaReady = true;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return Object.freeze({
|
|
97
|
-
schemaVersion: IDENTITY_STORE_SCHEMA_VERSION,
|
|
98
|
-
sessionTtlSeconds,
|
|
99
|
-
backend: 'sqlite',
|
|
100
|
-
|
|
101
|
-
async findUserByEmail(email) {
|
|
102
|
-
await ensure();
|
|
103
|
-
const row = await db.prepare(
|
|
104
|
-
`SELECT id, email, display_name, password_hash, salt, status, created_at, updated_at
|
|
105
|
-
FROM identity_users WHERE email = ? COLLATE NOCASE LIMIT 1`,
|
|
106
|
-
).bind(String(email || '').trim().toLowerCase()).first();
|
|
107
|
-
return row || null;
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
async findUserById(userId) {
|
|
111
|
-
await ensure();
|
|
112
|
-
const row = await db.prepare(
|
|
113
|
-
`SELECT id, email, display_name, password_hash, salt, status, created_at, updated_at
|
|
114
|
-
FROM identity_users WHERE id = ? LIMIT 1`,
|
|
115
|
-
).bind(userId).first();
|
|
116
|
-
return row || null;
|
|
117
|
-
},
|
|
118
|
-
|
|
119
|
-
async createUser({ email, passwordHash, salt, displayName }) {
|
|
120
|
-
await ensure();
|
|
121
|
-
const id = newAuthUserId();
|
|
122
|
-
const ts = nowUnix();
|
|
123
|
-
const normalizedEmail = String(email || '').trim().toLowerCase();
|
|
124
|
-
await db.prepare(
|
|
125
|
-
`INSERT INTO identity_users (id, email, display_name, password_hash, salt, status, created_at, updated_at)
|
|
126
|
-
VALUES (?, ?, ?, ?, ?, 'active', ?, ?)`,
|
|
127
|
-
).bind(id, normalizedEmail, displayName || null, passwordHash || null, salt || null, ts, ts).run();
|
|
128
|
-
return this.findUserById(id);
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
async updateUserPassword(userId, passwordHash, salt) {
|
|
132
|
-
await ensure();
|
|
133
|
-
const ts = nowUnix();
|
|
134
|
-
await db.prepare(
|
|
135
|
-
`UPDATE identity_users SET password_hash = ?, salt = ?, updated_at = ? WHERE id = ?`,
|
|
136
|
-
).bind(passwordHash, salt, ts, userId).run();
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
async findUserByProvider(provider, providerSubject) {
|
|
140
|
-
await ensure();
|
|
141
|
-
const row = await db.prepare(
|
|
142
|
-
`SELECT u.id, u.email, u.display_name, u.password_hash, u.salt, u.status, u.created_at, u.updated_at
|
|
143
|
-
FROM identity_external_accounts ea
|
|
144
|
-
JOIN identity_users u ON u.id = ea.user_id
|
|
145
|
-
WHERE ea.provider = ? AND ea.provider_subject = ?
|
|
146
|
-
LIMIT 1`,
|
|
147
|
-
).bind(provider, providerSubject).first();
|
|
148
|
-
return row || null;
|
|
149
|
-
},
|
|
150
|
-
|
|
151
|
-
async upsertProviderIdentity({ accountId, provider, providerSubject, email }) {
|
|
152
|
-
await ensure();
|
|
153
|
-
const existing = await db.prepare(
|
|
154
|
-
`SELECT id FROM identity_external_accounts WHERE provider = ? AND provider_subject = ? LIMIT 1`,
|
|
155
|
-
).bind(provider, providerSubject).first();
|
|
156
|
-
const ts = nowUnix();
|
|
157
|
-
if (existing?.id) {
|
|
158
|
-
await db.prepare(
|
|
159
|
-
`UPDATE identity_external_accounts SET user_id = ?, email = ?, updated_at = ? WHERE id = ?`,
|
|
160
|
-
).bind(accountId, email || null, ts, existing.id).run();
|
|
161
|
-
return existing.id;
|
|
162
|
-
}
|
|
163
|
-
const id = newAccountIdentityId();
|
|
164
|
-
await db.prepare(
|
|
165
|
-
`INSERT INTO identity_external_accounts (id, user_id, provider, provider_subject, email, created_at, updated_at)
|
|
166
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
167
|
-
).bind(id, accountId, provider, providerSubject, email || null, ts, ts).run();
|
|
168
|
-
return id;
|
|
169
|
-
},
|
|
170
|
-
|
|
171
|
-
async createSession({ userId, email, provider, providerSubject, displayName }) {
|
|
172
|
-
await ensure();
|
|
173
|
-
const id = newSessionId();
|
|
174
|
-
const ts = nowUnix();
|
|
175
|
-
const expiresAt = ts + sessionTtlSeconds;
|
|
176
|
-
await db.prepare(
|
|
177
|
-
`INSERT INTO identity_sessions
|
|
178
|
-
(id, user_id, email, provider, provider_subject, display_name, expires_at, created_at, last_active_at)
|
|
179
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
180
|
-
).bind(
|
|
181
|
-
id, userId, email || null, provider || 'email', providerSubject || null,
|
|
182
|
-
displayName || null, expiresAt, ts, ts,
|
|
183
|
-
).run();
|
|
184
|
-
return {
|
|
185
|
-
id, user_id: userId, email, provider: provider || 'email',
|
|
186
|
-
provider_subject: providerSubject || null, display_name: displayName || null,
|
|
187
|
-
expires_at: expiresAt, created_at: ts,
|
|
188
|
-
};
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
async getSession(sessionId) {
|
|
192
|
-
await ensure();
|
|
193
|
-
const row = await db.prepare(
|
|
194
|
-
`SELECT id, user_id, email, provider, provider_subject, display_name, expires_at, revoked_at, created_at, last_active_at
|
|
195
|
-
FROM identity_sessions WHERE id = ? LIMIT 1`,
|
|
196
|
-
).bind(sessionId).first();
|
|
197
|
-
if (!row || row.revoked_at || row.expires_at <= nowUnix()) return null;
|
|
198
|
-
return row;
|
|
199
|
-
},
|
|
200
|
-
|
|
201
|
-
async revokeSession(sessionId, reason = 'logout') {
|
|
202
|
-
await ensure();
|
|
203
|
-
const ts = nowUnix();
|
|
204
|
-
await db.prepare(
|
|
205
|
-
`UPDATE identity_sessions SET revoked_at = ?, last_active_at = ? WHERE id = ? AND revoked_at IS NULL`,
|
|
206
|
-
).bind(ts, ts, sessionId).run();
|
|
207
|
-
return { ok: true, reason };
|
|
208
|
-
},
|
|
209
|
-
|
|
210
|
-
async createOAuthTransaction({ state, provider, codeVerifier, returnTo, appId, ttlSeconds = 600 }) {
|
|
211
|
-
await ensure();
|
|
212
|
-
if (!appId) {
|
|
213
|
-
throw new IdentitySchemaError(
|
|
214
|
-
'OAUTH_TRANSACTION_APP_ID_REQUIRED',
|
|
215
|
-
'OAuth transactions must include app_id — refusing to create orphan auth state',
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
const ts = nowUnix();
|
|
219
|
-
await db.prepare(
|
|
220
|
-
`INSERT INTO identity_oauth_transactions
|
|
221
|
-
(state, provider, code_verifier, return_to, app_id, expires_at, created_at, consumed_at)
|
|
222
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, NULL)`,
|
|
223
|
-
).bind(state, provider, codeVerifier, returnTo || null, appId, ts + ttlSeconds, ts).run();
|
|
224
|
-
},
|
|
225
|
-
|
|
226
|
-
/** @deprecated Use createOAuthTransaction */
|
|
227
|
-
async saveOAuthState(input) {
|
|
228
|
-
return this.createOAuthTransaction({
|
|
229
|
-
...input,
|
|
230
|
-
returnTo: input.redirectTo ?? input.returnTo,
|
|
231
|
-
appId: input.appId,
|
|
232
|
-
});
|
|
233
|
-
},
|
|
234
|
-
|
|
235
|
-
async consumeOAuthTransaction(state) {
|
|
236
|
-
await ensure();
|
|
237
|
-
const row = await db.prepare(
|
|
238
|
-
`SELECT state, provider, code_verifier, return_to, app_id, expires_at, created_at, consumed_at
|
|
239
|
-
FROM identity_oauth_transactions WHERE state = ? LIMIT 1`,
|
|
240
|
-
).bind(state).first();
|
|
241
|
-
if (!row) return null;
|
|
242
|
-
const ts = nowUnix();
|
|
243
|
-
await db.prepare(
|
|
244
|
-
`UPDATE identity_oauth_transactions SET consumed_at = ? WHERE state = ?`,
|
|
245
|
-
).bind(ts, state).run();
|
|
246
|
-
await db.prepare(`DELETE FROM identity_oauth_transactions WHERE state = ?`).bind(state).run();
|
|
247
|
-
if (row.consumed_at) return null;
|
|
248
|
-
if (row.expires_at <= ts) return null;
|
|
249
|
-
if (!row.app_id) {
|
|
250
|
-
throw new IdentitySchemaError(
|
|
251
|
-
'IDENTITY_SCHEMA_MIGRATION_REQUIRED',
|
|
252
|
-
'OAuth transaction missing app_id — refuse silent pre-app_id semantics',
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
return {
|
|
256
|
-
state: row.state,
|
|
257
|
-
provider: row.provider,
|
|
258
|
-
code_verifier: row.code_verifier,
|
|
259
|
-
redirect_to: row.return_to,
|
|
260
|
-
return_to: row.return_to,
|
|
261
|
-
app_id: row.app_id,
|
|
262
|
-
expires_at: row.expires_at,
|
|
263
|
-
created_at: row.created_at,
|
|
264
|
-
consumed_at: ts,
|
|
265
|
-
};
|
|
266
|
-
},
|
|
267
|
-
|
|
268
|
-
/** @deprecated Use consumeOAuthTransaction */
|
|
269
|
-
async consumeOAuthState(state) {
|
|
270
|
-
return this.consumeOAuthTransaction(state);
|
|
271
|
-
},
|
|
272
|
-
|
|
273
|
-
async logAuthEvent({
|
|
274
|
-
userId, accountId, eventType, status = 'ok', provider,
|
|
275
|
-
session, capabilities, activity, client, metadata, request,
|
|
276
|
-
}) {
|
|
277
|
-
try {
|
|
278
|
-
await ensure();
|
|
279
|
-
const ip = request?.headers?.get?.('cf-connecting-ip') || request?.headers?.get?.('x-forwarded-for') || '';
|
|
280
|
-
const ua = request?.headers?.get?.('user-agent') || '';
|
|
281
|
-
const [ipHash, uaHash] = await Promise.all([hashValue(ip), hashValue(ua)]);
|
|
282
|
-
const envelope = {
|
|
283
|
-
...(metadata && typeof metadata === 'object' ? metadata : {}),
|
|
284
|
-
...(accountId ? { accountId } : {}),
|
|
285
|
-
...(session ? { session } : {}),
|
|
286
|
-
...(capabilities ? { capabilities } : {}),
|
|
287
|
-
...(activity ? { activity } : {}),
|
|
288
|
-
...(client ? { client } : {}),
|
|
289
|
-
};
|
|
290
|
-
await db.prepare(
|
|
291
|
-
`INSERT INTO identity_auth_events
|
|
292
|
-
(id, user_id, event_type, status, provider, metadata_json, ip_hash, user_agent_hash, created_at)
|
|
293
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
294
|
-
).bind(
|
|
295
|
-
newAuthEventId(), userId || null, eventType, status, provider || null,
|
|
296
|
-
JSON.stringify(envelope), ipHash, uaHash, nowUnix(),
|
|
297
|
-
).run();
|
|
298
|
-
} catch {
|
|
299
|
-
/* never break auth on audit failure */
|
|
300
|
-
}
|
|
301
|
-
},
|
|
302
|
-
|
|
303
|
-
async countAuthActivity(userId) {
|
|
304
|
-
await ensure();
|
|
305
|
-
if (!userId) return { loginCount: 0, activeSessionCount: 0, lastLoginAt: null };
|
|
306
|
-
const logins = await db.prepare(
|
|
307
|
-
`SELECT COUNT(*) AS c, MAX(created_at) AS last_at
|
|
308
|
-
FROM identity_auth_events
|
|
309
|
-
WHERE user_id = ? AND event_type = 'login' AND status = 'ok'`,
|
|
310
|
-
).bind(userId).first();
|
|
311
|
-
const sessions = await db.prepare(
|
|
312
|
-
`SELECT COUNT(*) AS c FROM identity_sessions
|
|
313
|
-
WHERE user_id = ? AND revoked_at IS NULL AND expires_at > ?`,
|
|
314
|
-
).bind(userId, nowUnix()).first();
|
|
315
|
-
return {
|
|
316
|
-
loginCount: Number(logins?.c || 0),
|
|
317
|
-
activeSessionCount: Number(sessions?.c || 0),
|
|
318
|
-
lastLoginAt: logins?.last_at != null ? Number(logins.last_at) : null,
|
|
319
|
-
};
|
|
320
|
-
},
|
|
321
|
-
});
|
|
22
|
+
return createPortableIdentityStore(db, { ...options, backend: 'sqlite' });
|
|
322
23
|
}
|
|
@@ -21,7 +21,6 @@ export const AGENTSAM_AUTH_ENV = Object.freeze({
|
|
|
21
21
|
googleClientId: 'GOOGLE_CLIENT_ID',
|
|
22
22
|
googleClientSecret: 'GOOGLE_CLIENT_SECRET',
|
|
23
23
|
googleDesktopClientId: 'GOOGLE_DESKTOP_CLIENT_ID',
|
|
24
|
-
googleDesktopClientSecret: 'GOOGLE_DESKTOP_CLIENT_SECRET',
|
|
25
24
|
githubClientId: 'GITHUB_CLIENT_ID',
|
|
26
25
|
githubClientSecret: 'GITHUB_CLIENT_SECRET',
|
|
27
26
|
cloudflareOauthClientId: 'CLOUDFLARE_OAUTH_CLIENT_ID',
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Portable IdentityStore contract.
|
|
3
|
-
* Adapters (SQLite, D1,
|
|
4
|
-
* imports Cloudflare/D1 APIs directly for product logic.
|
|
3
|
+
* Adapters (SQLite, portable D1, IAM-compat) implement this — the identity service
|
|
4
|
+
* never imports Cloudflare/D1 APIs directly for product logic.
|
|
5
|
+
*
|
|
6
|
+
* Company / native handoff / provider-connection behavior belong on this contract
|
|
7
|
+
* (not undocumented adapter-only magic). Password recovery remains a separate
|
|
8
|
+
* storage-agnostic service (createPasswordResetService + injected {get,put,delete});
|
|
9
|
+
* adapters supply user lookup / password update hooks, not a mandatory SQL reset table.
|
|
5
10
|
*/
|
|
6
11
|
|
|
7
12
|
/**
|
|
@@ -24,6 +29,7 @@
|
|
|
24
29
|
* @property {string|null} [provider]
|
|
25
30
|
* @property {string|null} [provider_subject]
|
|
26
31
|
* @property {string|null} [display_name]
|
|
32
|
+
* @property {'browser'|'desktop'} [type]
|
|
27
33
|
* @property {number} expires_at
|
|
28
34
|
* @property {number|null} [revoked_at]
|
|
29
35
|
* @property {number} created_at
|
|
@@ -37,6 +43,9 @@
|
|
|
37
43
|
* @property {string} code_verifier
|
|
38
44
|
* @property {string|null} [return_to]
|
|
39
45
|
* @property {string} app_id
|
|
46
|
+
* @property {'desktop'|string|null} [client_type]
|
|
47
|
+
* @property {string|null} [native_challenge]
|
|
48
|
+
* @property {string|null} [native_redirect]
|
|
40
49
|
* @property {number} expires_at
|
|
41
50
|
* @property {number} created_at
|
|
42
51
|
* @property {number|null} [consumed_at]
|
|
@@ -57,6 +66,37 @@
|
|
|
57
66
|
* @property {Request} [request]
|
|
58
67
|
*/
|
|
59
68
|
|
|
69
|
+
/**
|
|
70
|
+
* @typedef {object} CompanyProfile
|
|
71
|
+
* @property {string} id
|
|
72
|
+
* @property {string} slug
|
|
73
|
+
* @property {string} name
|
|
74
|
+
* @property {string|null} [legalName]
|
|
75
|
+
* @property {string|null} [logoUrl]
|
|
76
|
+
* @property {string|null} [faviconUrl]
|
|
77
|
+
* @property {string|null} [primaryColor]
|
|
78
|
+
* @property {string|null} [authBgColor]
|
|
79
|
+
* @property {string|null} [supportEmail]
|
|
80
|
+
* @property {string|null} [websiteUrl]
|
|
81
|
+
* @property {string|null} [tagline]
|
|
82
|
+
* @property {object} [meta]
|
|
83
|
+
* @property {number} [createdAt]
|
|
84
|
+
* @property {number} [updatedAt]
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @typedef {object} ProviderConnection
|
|
89
|
+
* @property {string} id
|
|
90
|
+
* @property {string} user_id
|
|
91
|
+
* @property {string} provider
|
|
92
|
+
* @property {string[]} granted_scopes
|
|
93
|
+
* @property {string} credential_ref
|
|
94
|
+
* @property {number|null} [expires_at]
|
|
95
|
+
* @property {boolean} [refreshable]
|
|
96
|
+
* @property {number} created_at
|
|
97
|
+
* @property {number} updated_at
|
|
98
|
+
*/
|
|
99
|
+
|
|
60
100
|
/**
|
|
61
101
|
* @typedef {object} IdentityStore
|
|
62
102
|
* @property {number} schemaVersion
|
|
@@ -66,21 +106,32 @@
|
|
|
66
106
|
* @property {(userId: string, passwordHash: string, salt: string) => Promise<void>} updateUserPassword
|
|
67
107
|
* @property {(provider: string, providerSubject: string) => Promise<IdentityUser|null>} findUserByProvider
|
|
68
108
|
* @property {(input: { accountId: string, provider: string, providerSubject: string, email?: string|null }) => Promise<string>} upsertProviderIdentity
|
|
69
|
-
* @property {(input: { userId: string, email?: string|null, provider?: string, providerSubject?: string|null, displayName?: string|null }) => Promise<IdentitySession>} createSession
|
|
109
|
+
* @property {(input: { userId: string, email?: string|null, provider?: string, providerSubject?: string|null, displayName?: string|null, type?: 'browser'|'desktop' }) => Promise<IdentitySession>} createSession
|
|
70
110
|
* @property {(sessionId: string) => Promise<IdentitySession|null>} getSession
|
|
71
111
|
* @property {(sessionId: string, reason?: string) => Promise<{ ok: true, reason: string }>} revokeSession
|
|
72
|
-
* @property {(input: { state: string, provider: string, codeVerifier: string, returnTo?: string|null, appId: string, ttlSeconds?: number }) => Promise<void>} createOAuthTransaction
|
|
112
|
+
* @property {(input: { state: string, provider: string, codeVerifier: string, returnTo?: string|null, appId: string, ttlSeconds?: number, clientType?: string, nativeChallenge?: string, nativeRedirect?: string }) => Promise<void>} createOAuthTransaction
|
|
73
113
|
* @property {(state: string) => Promise<OAuthTransaction|null>} consumeOAuthTransaction
|
|
74
114
|
* @property {(input: AuthEventInput) => Promise<void>} logAuthEvent
|
|
75
115
|
* @property {(userId: string) => Promise<{ loginCount: number, activeSessionCount: number, lastLoginAt: number|null }>} [countAuthActivity]
|
|
116
|
+
* @property {(input: { handoffHash: string, sessionId: string, challenge: string, ttlSeconds?: number }) => Promise<void>} createNativeHandoff
|
|
117
|
+
* @property {(handoffHash: string) => Promise<{ session_id: string, challenge: string }|null>} consumeNativeHandoff
|
|
118
|
+
* @property {(slug?: string) => Promise<CompanyProfile|null>} getCompanyBySlug
|
|
119
|
+
* @property {(hostname: string|null|undefined) => Promise<CompanyProfile|null>} getCompanyByHost
|
|
120
|
+
* @property {() => Promise<CompanyProfile|null>} getDefaultCompany
|
|
121
|
+
* @property {(input: object) => Promise<CompanyProfile|null>} upsertCompany
|
|
122
|
+
* @property {(input: { userId: string, provider: string, credentialRef: string, grantedScopes?: string[], expiresAt?: number|null, refreshable?: boolean }) => Promise<string>} upsertProviderConnection
|
|
123
|
+
* @property {(userId: string, provider: string) => Promise<ProviderConnection|null>} getProviderConnection
|
|
76
124
|
*/
|
|
77
125
|
|
|
78
|
-
|
|
126
|
+
/** Portable pack schema_version after 005_identity_company_native. */
|
|
127
|
+
export const IDENTITY_STORE_SCHEMA_VERSION = 2;
|
|
79
128
|
|
|
80
129
|
export const IDENTITY_PACKS = Object.freeze({
|
|
81
130
|
CORE: 'identity.core',
|
|
82
131
|
OAUTH_CLIENT: 'identity.oauth-client',
|
|
83
132
|
OAUTH_SERVER: 'identity.oauth-server',
|
|
133
|
+
/** Optional future — not part of portable core. Recovery stays KV/injected today. */
|
|
134
|
+
RECOVERY: 'identity.recovery',
|
|
84
135
|
});
|
|
85
136
|
|
|
86
137
|
/**
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stock sign-in options for OAuth / CMS editor first-run setup.
|
|
3
|
+
* user123 picks from these prepackaged providers when wiring auth.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** @typedef {'oauth' | 'oidc' | 'hosted_headers' | 'local'} StockSignInKind */
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {object} StockSignInOption
|
|
10
|
+
* @property {string} id
|
|
11
|
+
* @property {string} label
|
|
12
|
+
* @property {string} [shortLabel]
|
|
13
|
+
* @property {StockSignInKind} kind
|
|
14
|
+
* @property {'ready' | 'scaffold'} status
|
|
15
|
+
* @property {string} description
|
|
16
|
+
* @property {string[]} [aliases]
|
|
17
|
+
* @property {string[]} [requiredEnv]
|
|
18
|
+
* @property {string[]} [optionalEnv]
|
|
19
|
+
* @property {string} [implementation]
|
|
20
|
+
* @property {boolean} [cmsDefault]
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** @type {readonly StockSignInOption[]} */
|
|
24
|
+
export const STOCK_SIGN_IN_OPTIONS = Object.freeze([
|
|
25
|
+
{
|
|
26
|
+
id: 'cloudflare',
|
|
27
|
+
label: 'Cloudflare',
|
|
28
|
+
shortLabel: 'Cloudflare',
|
|
29
|
+
kind: 'oauth',
|
|
30
|
+
status: 'ready',
|
|
31
|
+
description: 'Sign in with Cloudflare account OAuth (PKCE-capable).',
|
|
32
|
+
requiredEnv: ['CLOUDFLARE_OAUTH_CLIENT_ID'],
|
|
33
|
+
optionalEnv: ['CLOUDFLARE_OAUTH_CLIENT_SECRET'],
|
|
34
|
+
implementation: 'src/providers/cloudflare',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'google',
|
|
38
|
+
label: 'Google',
|
|
39
|
+
shortLabel: 'Google',
|
|
40
|
+
kind: 'oauth',
|
|
41
|
+
status: 'ready',
|
|
42
|
+
description: 'Sign in with Google (browser OAuth confidential client).',
|
|
43
|
+
requiredEnv: ['GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET'],
|
|
44
|
+
implementation: 'src/providers/google',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'inneranimalmedia',
|
|
48
|
+
label: 'Inner Animal Media',
|
|
49
|
+
shortLabel: 'IAM',
|
|
50
|
+
kind: 'oidc',
|
|
51
|
+
status: 'ready',
|
|
52
|
+
description: 'Sign in with Inner Animal Media platform identity (OIDC).',
|
|
53
|
+
aliases: ['iam'],
|
|
54
|
+
requiredEnv: ['IAM_CLIENT_ID', 'IAM_CLIENT_SECRET'],
|
|
55
|
+
optionalEnv: ['IAM_OAUTH_ISSUER', 'IAM_ORIGIN'],
|
|
56
|
+
implementation: 'src/providers/iam',
|
|
57
|
+
cmsDefault: true,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 'chatgpt',
|
|
61
|
+
label: 'ChatGPT',
|
|
62
|
+
shortLabel: 'ChatGPT',
|
|
63
|
+
kind: 'hosted_headers',
|
|
64
|
+
status: 'ready',
|
|
65
|
+
description:
|
|
66
|
+
'Sign in via ChatGPT / OpenAI Apps SDK hosted identity (oai-authenticated headers → NormalizedExternalIdentity).',
|
|
67
|
+
aliases: ['openai', 'chatgpt-hosted'],
|
|
68
|
+
requiredEnv: [],
|
|
69
|
+
implementation: 'src/providers/chatgpt',
|
|
70
|
+
},
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
/** Canonical ids offered on CMS / OAuth prebuild pickers. */
|
|
74
|
+
export const CMS_STOCK_SIGN_IN_IDS = Object.freeze(
|
|
75
|
+
STOCK_SIGN_IN_OPTIONS.map((row) => row.id),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {string} id
|
|
80
|
+
* @returns {StockSignInOption | null}
|
|
81
|
+
*/
|
|
82
|
+
export function getStockSignInOption(id) {
|
|
83
|
+
const key = String(id || '')
|
|
84
|
+
.trim()
|
|
85
|
+
.toLowerCase()
|
|
86
|
+
.replace(/-/g, '_');
|
|
87
|
+
if (!key) return null;
|
|
88
|
+
if (key === 'iam') {
|
|
89
|
+
return STOCK_SIGN_IN_OPTIONS.find((row) => row.id === 'inneranimalmedia') || null;
|
|
90
|
+
}
|
|
91
|
+
if (key === 'openai' || key === 'chatgpt_hosted') {
|
|
92
|
+
return STOCK_SIGN_IN_OPTIONS.find((row) => row.id === 'chatgpt') || null;
|
|
93
|
+
}
|
|
94
|
+
return (
|
|
95
|
+
STOCK_SIGN_IN_OPTIONS.find((row) => row.id === key) ||
|
|
96
|
+
STOCK_SIGN_IN_OPTIONS.find((row) => (row.aliases || []).includes(String(id || '').trim().toLowerCase())) ||
|
|
97
|
+
null
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** @returns {StockSignInOption[]} */
|
|
102
|
+
export function listStockSignInOptions() {
|
|
103
|
+
return [...STOCK_SIGN_IN_OPTIONS];
|
|
104
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { SESSION_POLICY } from './session-policy.js';
|
|
8
8
|
|
|
9
|
-
export { SESSION_POLICY, clampAgentSessionTtl } from './session-policy.js';
|
|
9
|
+
export { SESSION_POLICY, clampAgentSessionTtl, shouldRenewDesktopSession } from './session-policy.js';
|
|
10
10
|
|
|
11
11
|
export const AUTH_COOKIE_NAME = 'session';
|
|
12
12
|
|
|
@@ -6,10 +6,24 @@
|
|
|
6
6
|
* Product routing does not live here.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
/** auth_sessions.type values written by this package. */
|
|
10
|
+
export const SESSION_TYPES = Object.freeze({
|
|
11
|
+
BROWSER: 'browser',
|
|
12
|
+
DESKTOP: 'desktop',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
/** Lifetime of the one-time code a native OAuth callback hands to the app. */
|
|
16
|
+
export const NATIVE_HANDOFF_TTL_SECONDS = 120;
|
|
17
|
+
|
|
9
18
|
export const SESSION_POLICY = Object.freeze({
|
|
10
19
|
browser: Object.freeze({
|
|
11
20
|
ttlSeconds: 30 * 24 * 60 * 60,
|
|
12
21
|
}),
|
|
22
|
+
/** Native app bearer session (OS keychain) — minted via the native OAuth handoff. */
|
|
23
|
+
desktop: Object.freeze({
|
|
24
|
+
ttlSeconds: 30 * 24 * 60 * 60,
|
|
25
|
+
renewWindowSeconds: 7 * 24 * 60 * 60,
|
|
26
|
+
}),
|
|
13
27
|
/** Temporary execution authority — not the user's Local Studio login. */
|
|
14
28
|
agent: Object.freeze({
|
|
15
29
|
minTtlSeconds: 60,
|
|
@@ -18,6 +32,23 @@ export const SESSION_POLICY = Object.freeze({
|
|
|
18
32
|
}),
|
|
19
33
|
});
|
|
20
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Desktop sessions are durable/revocable AgentSam sessions, not provider tokens.
|
|
37
|
+
* Renew only near expiry so normal app launches remain read-mostly.
|
|
38
|
+
*/
|
|
39
|
+
export function shouldRenewDesktopSession(session, nowSeconds) {
|
|
40
|
+
const now = Number.isFinite(Number(nowSeconds))
|
|
41
|
+
? Math.floor(Number(nowSeconds))
|
|
42
|
+
: Math.floor(Date.now() / 1000);
|
|
43
|
+
const expiresAt = Number(session?.expires_at);
|
|
44
|
+
return (
|
|
45
|
+
session?.type === SESSION_TYPES.DESKTOP
|
|
46
|
+
&& Number.isFinite(expiresAt)
|
|
47
|
+
&& expiresAt > now
|
|
48
|
+
&& expiresAt - now <= SESSION_POLICY.desktop.renewWindowSeconds
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
21
52
|
/**
|
|
22
53
|
* Clamp a requested agent/runtime grant TTL into policy bounds.
|
|
23
54
|
* @param {number|null|undefined} requestedSeconds
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>Sign in
|
|
7
|
+
<title>Sign in</title>
|
|
8
8
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap"
|
|
9
9
|
rel="stylesheet">
|
|
10
10
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
|
@@ -360,12 +360,12 @@
|
|
|
360
360
|
<div class="login-card">
|
|
361
361
|
<img
|
|
362
362
|
class="auth-logo"
|
|
363
|
-
src="/shared/
|
|
364
|
-
alt="
|
|
363
|
+
src="/shared/app-icon.png"
|
|
364
|
+
alt="Sign in"
|
|
365
365
|
/>
|
|
366
366
|
|
|
367
|
-
<h1 data-company-tagline>
|
|
368
|
-
<p class="subtitle" data-company-subtitle="signin">Sign in
|
|
367
|
+
<h1 data-company-tagline>Welcome</h1>
|
|
368
|
+
<p class="subtitle" data-company-subtitle="signin">Sign in</p>
|
|
369
369
|
<p id="registeredMsg" class="subtitle" style="color: #10B981; display: none; margin-top: -16px; margin-bottom: 16px;">Account created. Sign in below.</p>
|
|
370
370
|
<p id="resetMsg" class="subtitle" style="color: #10B981; display: none; margin-top: -16px; margin-bottom: 16px;">Password updated. Sign in with your new password.</p>
|
|
371
371
|
<p id="oauthErrorMsg" class="subtitle" style="color: #FF3B30; display: none; margin-top: -16px; margin-bottom: 16px;"></p>
|
|
@@ -451,7 +451,7 @@
|
|
|
451
451
|
</div>
|
|
452
452
|
|
|
453
453
|
<footer class="auth-min-footer" aria-label="Legal">
|
|
454
|
-
<span data-company-name>
|
|
454
|
+
<span data-company-name>App</span>
|
|
455
455
|
<span class="auth-min-footer-sep" aria-hidden="true">|</span>
|
|
456
456
|
<a href="/privacy">Privacy</a>
|
|
457
457
|
<span class="auth-min-footer-sep" aria-hidden="true">|</span>
|