studiograph 1.3.48-next.21 → 1.3.48-next.211
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/README.md +26 -16
- package/dist/agent/agent-pool.d.ts +87 -3
- package/dist/agent/agent-pool.js +188 -15
- package/dist/agent/agent-pool.js.map +1 -1
- package/dist/agent/followups.d.ts +34 -0
- package/dist/agent/followups.js +52 -0
- package/dist/agent/followups.js.map +1 -0
- package/dist/agent/orchestrator.d.ts +101 -4
- package/dist/agent/orchestrator.js +464 -66
- package/dist/agent/orchestrator.js.map +1 -1
- package/dist/agent/prompts/entity-types-section.d.ts +34 -0
- package/dist/agent/prompts/entity-types-section.js +76 -0
- package/dist/agent/prompts/entity-types-section.js.map +1 -0
- package/dist/agent/prompts/system.md +112 -54
- package/dist/agent/skill-loader.d.ts +30 -17
- package/dist/agent/skill-loader.js +63 -30
- package/dist/agent/skill-loader.js.map +1 -1
- package/dist/agent/skills/artifact-canvas/skill.md +152 -0
- package/dist/agent/skills/entity-schema.md +75 -431
- package/dist/agent/skills/interview/entity-templates.md +38 -37
- package/dist/agent/skills/interview/question-domains.md +54 -49
- package/dist/agent/skills/interview/skill.md +84 -16
- package/dist/agent/skills/schema-rules.md +28 -28
- package/dist/agent/tools/artifact-tools.d.ts +124 -0
- package/dist/agent/tools/artifact-tools.js +207 -0
- package/dist/agent/tools/artifact-tools.js.map +1 -0
- package/dist/agent/tools/capture-tools.d.ts +31 -0
- package/dist/agent/tools/capture-tools.js +40 -0
- package/dist/agent/tools/capture-tools.js.map +1 -0
- package/dist/agent/tools/folder-tools.d.ts +47 -0
- package/dist/agent/tools/folder-tools.js +249 -0
- package/dist/agent/tools/folder-tools.js.map +1 -0
- package/dist/agent/tools/fs-tools.d.ts +6 -5
- package/dist/agent/tools/fs-tools.js +5 -5
- package/dist/agent/tools/fs-tools.js.map +1 -1
- package/dist/agent/tools/graph-tools.d.ts +48 -72
- package/dist/agent/tools/graph-tools.js +852 -329
- package/dist/agent/tools/graph-tools.js.map +1 -1
- package/dist/agent/tools/history-tools.d.ts +95 -0
- package/dist/agent/tools/history-tools.js +461 -0
- package/dist/agent/tools/history-tools.js.map +1 -0
- package/dist/agent/tools/load-skill.d.ts +6 -5
- package/dist/agent/tools/load-skill.js +3 -3
- package/dist/agent/tools/load-skill.js.map +1 -1
- package/dist/agent/tools/ops-tools.d.ts +5 -4
- package/dist/agent/tools/ops-tools.js +130 -236
- package/dist/agent/tools/ops-tools.js.map +1 -1
- package/dist/agent/tools/permission-tools.d.ts +87 -17
- package/dist/agent/tools/permission-tools.js +233 -43
- package/dist/agent/tools/permission-tools.js.map +1 -1
- package/dist/agent/tools/tool-loader.js +5 -4
- package/dist/agent/tools/tool-loader.js.map +1 -1
- package/dist/agent/tools/web-tools.js +58 -9
- package/dist/agent/tools/web-tools.js.map +1 -1
- package/dist/cli/commands/about.d.ts +1 -0
- package/dist/cli/commands/about.js +55 -3
- package/dist/cli/commands/about.js.map +1 -1
- package/dist/cli/commands/admin/audit-workspace.d.ts +23 -0
- package/dist/cli/commands/admin/audit-workspace.js +133 -0
- package/dist/cli/commands/admin/audit-workspace.js.map +1 -0
- package/dist/cli/commands/admin/audit.d.ts +21 -0
- package/dist/cli/commands/admin/audit.js +174 -0
- package/dist/cli/commands/admin/audit.js.map +1 -0
- package/dist/cli/commands/admin/backup.d.ts +54 -0
- package/dist/cli/commands/admin/backup.js +207 -0
- package/dist/cli/commands/admin/backup.js.map +1 -0
- package/dist/cli/commands/admin/folder.d.ts +11 -0
- package/dist/cli/commands/{collection.js → admin/folder.js} +33 -32
- package/dist/cli/commands/admin/folder.js.map +1 -0
- package/dist/cli/commands/admin/index.d.ts +16 -0
- package/dist/cli/commands/admin/index.js +46 -0
- package/dist/cli/commands/admin/index.js.map +1 -0
- package/dist/cli/commands/admin/migrate-assets.d.ts +53 -0
- package/dist/cli/commands/admin/migrate-assets.js +184 -0
- package/dist/cli/commands/admin/migrate-assets.js.map +1 -0
- package/dist/cli/commands/admin/migrate.d.ts +56 -0
- package/dist/cli/commands/admin/migrate.js +263 -0
- package/dist/cli/commands/admin/migrate.js.map +1 -0
- package/dist/cli/commands/admin/restore.d.ts +24 -0
- package/dist/cli/commands/admin/restore.js +228 -0
- package/dist/cli/commands/admin/restore.js.map +1 -0
- package/dist/cli/commands/admin/secrets.d.ts +23 -0
- package/dist/cli/commands/admin/secrets.js +256 -0
- package/dist/cli/commands/admin/secrets.js.map +1 -0
- package/dist/cli/commands/admin/settings.d.ts +28 -0
- package/dist/cli/commands/admin/settings.js +284 -0
- package/dist/cli/commands/admin/settings.js.map +1 -0
- package/dist/cli/commands/admin/token.d.ts +42 -0
- package/dist/cli/commands/admin/token.js +126 -0
- package/dist/cli/commands/admin/token.js.map +1 -0
- package/dist/cli/commands/admin/transfer-ownership.d.ts +15 -0
- package/dist/cli/commands/admin/transfer-ownership.js +106 -0
- package/dist/cli/commands/admin/transfer-ownership.js.map +1 -0
- package/dist/cli/commands/admin/user.d.ts +11 -0
- package/dist/cli/commands/admin/user.js +187 -0
- package/dist/cli/commands/admin/user.js.map +1 -0
- package/dist/cli/commands/clone.d.ts +25 -3
- package/dist/cli/commands/clone.js +142 -36
- package/dist/cli/commands/clone.js.map +1 -1
- package/dist/cli/commands/config.d.ts +23 -107
- package/dist/cli/commands/config.js +52 -260
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/connector.d.ts +10 -13
- package/dist/cli/commands/connector.js +16 -58
- package/dist/cli/commands/connector.js.map +1 -1
- package/dist/cli/commands/deploy.js +215 -68
- package/dist/cli/commands/deploy.js.map +1 -1
- package/dist/cli/commands/index.js +5 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.js +10 -30
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/mcp.js +54 -6
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/r2.d.ts +3 -0
- package/dist/cli/commands/r2.js +223 -204
- package/dist/cli/commands/r2.js.map +1 -1
- package/dist/cli/commands/redeploy.js +65 -12
- package/dist/cli/commands/redeploy.js.map +1 -1
- package/dist/cli/commands/reset.d.ts +22 -6
- package/dist/cli/commands/reset.js +132 -34
- package/dist/cli/commands/reset.js.map +1 -1
- package/dist/cli/commands/serve.js +231 -26
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/sync.d.ts +1 -1
- package/dist/cli/commands/sync.js +237 -227
- package/dist/cli/commands/sync.js.map +1 -1
- package/dist/cli/crypto-bundle.d.ts +39 -0
- package/dist/cli/crypto-bundle.js +94 -0
- package/dist/cli/crypto-bundle.js.map +1 -0
- package/dist/cli/index.js +24 -26
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/railway-pin.d.ts +68 -0
- package/dist/cli/railway-pin.js +96 -0
- package/dist/cli/railway-pin.js.map +1 -0
- package/dist/cli/railway-provisioning.d.ts +53 -0
- package/dist/cli/railway-provisioning.js +85 -0
- package/dist/cli/railway-provisioning.js.map +1 -0
- package/dist/cli/setup-wizard.d.ts +30 -49
- package/dist/cli/setup-wizard.js +39 -40
- package/dist/cli/setup-wizard.js.map +1 -1
- package/dist/core/accent-palette.d.ts +22 -0
- package/dist/core/accent-palette.js +47 -0
- package/dist/core/accent-palette.js.map +1 -0
- package/dist/core/artifact-asset-urls.d.ts +51 -0
- package/dist/core/artifact-asset-urls.js +79 -0
- package/dist/core/artifact-asset-urls.js.map +1 -0
- package/dist/core/artifact-bundle.d.ts +69 -0
- package/dist/core/artifact-bundle.js +305 -0
- package/dist/core/artifact-bundle.js.map +1 -0
- package/dist/core/artifact-escape.d.ts +5 -0
- package/dist/core/artifact-escape.js +26 -0
- package/dist/core/artifact-escape.js.map +1 -0
- package/dist/core/artifact-export.d.ts +17 -0
- package/dist/core/artifact-export.js +529 -0
- package/dist/core/artifact-export.js.map +1 -0
- package/dist/core/cell-anchor.d.ts +29 -0
- package/dist/core/cell-anchor.js +53 -0
- package/dist/core/cell-anchor.js.map +1 -0
- package/dist/core/comment-anchor.d.ts +41 -0
- package/dist/core/comment-anchor.js +147 -0
- package/dist/core/comment-anchor.js.map +1 -0
- package/dist/core/commit-messages.d.ts +57 -0
- package/dist/core/commit-messages.js +85 -0
- package/dist/core/commit-messages.js.map +1 -0
- package/dist/core/embeds.d.ts +96 -0
- package/dist/core/embeds.js +196 -0
- package/dist/core/embeds.js.map +1 -0
- package/dist/core/entity-body-templates.d.ts +21 -0
- package/dist/core/entity-body-templates.js +67 -0
- package/dist/core/entity-body-templates.js.map +1 -0
- package/dist/core/entity-types-catalog.d.ts +65 -0
- package/dist/core/entity-types-catalog.js +142 -0
- package/dist/core/entity-types-catalog.js.map +1 -0
- package/dist/core/field-library.d.ts +62 -0
- package/dist/core/field-library.js +129 -0
- package/dist/core/field-library.js.map +1 -0
- package/dist/core/folder-paths.d.ts +41 -0
- package/dist/core/folder-paths.js +95 -0
- package/dist/core/folder-paths.js.map +1 -0
- package/dist/core/folder-sidecar.d.ts +36 -0
- package/dist/core/folder-sidecar.js +91 -0
- package/dist/core/folder-sidecar.js.map +1 -0
- package/dist/core/format-registry.d.ts +170 -0
- package/dist/core/format-registry.js +412 -0
- package/dist/core/format-registry.js.map +1 -0
- package/dist/core/graph.d.ts +773 -14
- package/dist/core/graph.js +2269 -308
- package/dist/core/graph.js.map +1 -1
- package/dist/core/history-diff.d.ts +35 -0
- package/dist/core/history-diff.js +114 -0
- package/dist/core/history-diff.js.map +1 -0
- package/dist/core/refs.d.ts +41 -0
- package/dist/core/refs.js +80 -0
- package/dist/core/refs.js.map +1 -0
- package/dist/core/schema-registry.d.ts +66 -0
- package/dist/core/schema-registry.js +198 -37
- package/dist/core/schema-registry.js.map +1 -1
- package/dist/core/schemas/connector.d.ts +67 -0
- package/dist/core/schemas/connector.js +100 -0
- package/dist/core/schemas/connector.js.map +1 -0
- package/dist/core/schemas/workspace.d.ts +122 -0
- package/dist/core/schemas/workspace.js +211 -0
- package/dist/core/schemas/workspace.js.map +1 -0
- package/dist/core/secrets/SecretStore.d.ts +77 -0
- package/dist/core/secrets/SecretStore.js +13 -0
- package/dist/core/secrets/SecretStore.js.map +1 -0
- package/dist/core/secrets/SettingsResolver.d.ts +54 -0
- package/dist/core/secrets/SettingsResolver.js +80 -0
- package/dist/core/secrets/SettingsResolver.js.map +1 -0
- package/dist/core/secrets/SettingsStore.d.ts +30 -0
- package/dist/core/secrets/SettingsStore.js +9 -0
- package/dist/core/secrets/SettingsStore.js.map +1 -0
- package/dist/core/secrets/SqliteEncryptedStore.d.ts +90 -0
- package/dist/core/secrets/SqliteEncryptedStore.js +598 -0
- package/dist/core/secrets/SqliteEncryptedStore.js.map +1 -0
- package/dist/core/secrets/audit.d.ts +36 -0
- package/dist/core/secrets/audit.js +60 -0
- package/dist/core/secrets/audit.js.map +1 -0
- package/dist/core/secrets/auth-db-migration.d.ts +129 -0
- package/dist/core/secrets/auth-db-migration.js +653 -0
- package/dist/core/secrets/auth-db-migration.js.map +1 -0
- package/dist/core/secrets/bundle.d.ts +141 -0
- package/dist/core/secrets/bundle.js +435 -0
- package/dist/core/secrets/bundle.js.map +1 -0
- package/dist/core/secrets/dual-write.d.ts +81 -0
- package/dist/core/secrets/dual-write.js +247 -0
- package/dist/core/secrets/dual-write.js.map +1 -0
- package/dist/core/secrets/encryption.d.ts +44 -0
- package/dist/core/secrets/encryption.js +97 -0
- package/dist/core/secrets/encryption.js.map +1 -0
- package/dist/core/secrets/index.d.ts +49 -0
- package/dist/core/secrets/index.js +74 -0
- package/dist/core/secrets/index.js.map +1 -0
- package/dist/core/secrets/master-key.d.ts +38 -0
- package/dist/core/secrets/master-key.js +122 -0
- package/dist/core/secrets/master-key.js.map +1 -0
- package/dist/core/secrets/probes/anthropic.d.ts +98 -0
- package/dist/core/secrets/probes/anthropic.js +300 -0
- package/dist/core/secrets/probes/anthropic.js.map +1 -0
- package/dist/core/secrets/probes/brave.d.ts +9 -0
- package/dist/core/secrets/probes/brave.js +15 -0
- package/dist/core/secrets/probes/brave.js.map +1 -0
- package/dist/core/secrets/probes/r2.d.ts +15 -0
- package/dist/core/secrets/probes/r2.js +14 -0
- package/dist/core/secrets/probes/r2.js.map +1 -0
- package/dist/core/secrets/probes/tavily.d.ts +18 -0
- package/dist/core/secrets/probes/tavily.js +58 -0
- package/dist/core/secrets/probes/tavily.js.map +1 -0
- package/dist/core/secrets/probes/voyage.d.ts +13 -0
- package/dist/core/secrets/probes/voyage.js +52 -0
- package/dist/core/secrets/probes/voyage.js.map +1 -0
- package/dist/core/secrets/r2-structural-migration.d.ts +39 -0
- package/dist/core/secrets/r2-structural-migration.js +109 -0
- package/dist/core/secrets/r2-structural-migration.js.map +1 -0
- package/dist/core/secrets/read-flip.d.ts +59 -0
- package/dist/core/secrets/read-flip.js +87 -0
- package/dist/core/secrets/read-flip.js.map +1 -0
- package/dist/core/secrets/registry.d.ts +188 -0
- package/dist/core/secrets/registry.js +616 -0
- package/dist/core/secrets/registry.js.map +1 -0
- package/dist/core/types.d.ts +77 -483
- package/dist/core/types.js +25 -3
- package/dist/core/types.js.map +1 -1
- package/dist/core/user-config.d.ts +75 -12
- package/dist/core/user-config.js +155 -14
- package/dist/core/user-config.js.map +1 -1
- package/dist/core/validation.d.ts +786 -1373
- package/dist/core/validation.js +458 -147
- package/dist/core/validation.js.map +1 -1
- package/dist/core/workspace-manager.d.ts +87 -14
- package/dist/core/workspace-manager.js +222 -94
- package/dist/core/workspace-manager.js.map +1 -1
- package/dist/core/workspace.d.ts +19 -5
- package/dist/core/workspace.js +67 -39
- package/dist/core/workspace.js.map +1 -1
- package/dist/mcp/comment-virtual-entity.d.ts +36 -0
- package/dist/mcp/comment-virtual-entity.js +71 -0
- package/dist/mcp/comment-virtual-entity.js.map +1 -0
- package/dist/mcp/connector-manager.d.ts +72 -2
- package/dist/mcp/connector-manager.js +211 -32
- package/dist/mcp/connector-manager.js.map +1 -1
- package/dist/mcp/oauth-provider.d.ts +0 -5
- package/dist/mcp/oauth-provider.js +10 -22
- package/dist/mcp/oauth-provider.js.map +1 -1
- package/dist/mcp/oauth-registry.d.ts +46 -8
- package/dist/mcp/oauth-registry.js +52 -13
- package/dist/mcp/oauth-registry.js.map +1 -1
- package/dist/mcp/server-discovery.d.ts +73 -0
- package/dist/mcp/server-discovery.js +164 -0
- package/dist/mcp/server-discovery.js.map +1 -0
- package/dist/mcp/server.d.ts +24 -3
- package/dist/mcp/server.js +53 -10
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/state-signer.d.ts +62 -0
- package/dist/mcp/state-signer.js +205 -0
- package/dist/mcp/state-signer.js.map +1 -0
- package/dist/mcp/stdio-proxy.d.ts +67 -0
- package/dist/mcp/stdio-proxy.js +149 -0
- package/dist/mcp/stdio-proxy.js.map +1 -0
- package/dist/mcp/tools.d.ts +65 -2
- package/dist/mcp/tools.js +1772 -124
- package/dist/mcp/tools.js.map +1 -1
- package/dist/server/__tests__/helpers/graph-api.d.ts +16 -0
- package/dist/server/__tests__/helpers/graph-api.js +16 -0
- package/dist/server/__tests__/helpers/graph-api.js.map +1 -0
- package/dist/server/artifact-asset-mint.d.ts +41 -0
- package/dist/server/artifact-asset-mint.js +59 -0
- package/dist/server/artifact-asset-mint.js.map +1 -0
- package/dist/server/asset-index-queue.d.ts +98 -0
- package/dist/server/asset-index-queue.js +193 -0
- package/dist/server/asset-index-queue.js.map +1 -0
- package/dist/server/body-write-coordinator.d.ts +161 -0
- package/dist/server/body-write-coordinator.js +182 -0
- package/dist/server/body-write-coordinator.js.map +1 -0
- package/dist/server/cloud-billing-flow.d.ts +32 -0
- package/dist/server/cloud-billing-flow.js +75 -0
- package/dist/server/cloud-billing-flow.js.map +1 -0
- package/dist/server/commit-audit.d.ts +26 -0
- package/dist/server/commit-audit.js +30 -0
- package/dist/server/commit-audit.js.map +1 -0
- package/dist/server/index.d.ts +29 -3
- package/dist/server/index.js +657 -269
- package/dist/server/index.js.map +1 -1
- package/dist/server/middleware/sanitize.d.ts +46 -0
- package/dist/server/middleware/sanitize.js +182 -0
- package/dist/server/middleware/sanitize.js.map +1 -0
- package/dist/server/routes/artifact-export-api.d.ts +11 -0
- package/dist/server/routes/artifact-export-api.js +159 -0
- package/dist/server/routes/artifact-export-api.js.map +1 -0
- package/dist/server/routes/asset-api.d.ts +76 -1
- package/dist/server/routes/asset-api.js +761 -61
- package/dist/server/routes/asset-api.js.map +1 -1
- package/dist/server/routes/audit-api.d.ts +24 -0
- package/dist/server/routes/audit-api.js +117 -0
- package/dist/server/routes/audit-api.js.map +1 -0
- package/dist/server/routes/auth-api.js +532 -63
- package/dist/server/routes/auth-api.js.map +1 -1
- package/dist/server/routes/capture-api.d.ts +10 -3
- package/dist/server/routes/capture-api.js +213 -25
- package/dist/server/routes/capture-api.js.map +1 -1
- package/dist/server/routes/chat-sessions-api.d.ts +13 -0
- package/dist/server/routes/chat-sessions-api.js +455 -0
- package/dist/server/routes/chat-sessions-api.js.map +1 -0
- package/dist/server/routes/chat.d.ts +35 -1
- package/dist/server/routes/chat.js +699 -54
- package/dist/server/routes/chat.js.map +1 -1
- package/dist/server/routes/comments-api.d.ts +15 -0
- package/dist/server/routes/comments-api.js +444 -0
- package/dist/server/routes/comments-api.js.map +1 -0
- package/dist/server/routes/config-api.d.ts +3 -2
- package/dist/server/routes/config-api.js +179 -49
- package/dist/server/routes/config-api.js.map +1 -1
- package/dist/server/routes/connectors-api.js +177 -42
- package/dist/server/routes/connectors-api.js.map +1 -1
- package/dist/server/routes/event-ingest-api.d.ts +15 -0
- package/dist/server/routes/{meeting-ingest-api.js → event-ingest-api.js} +35 -20
- package/dist/server/routes/event-ingest-api.js.map +1 -0
- package/dist/server/routes/field-library-api.d.ts +28 -0
- package/dist/server/routes/field-library-api.js +126 -0
- package/dist/server/routes/field-library-api.js.map +1 -0
- package/dist/server/routes/git-http.d.ts +2 -2
- package/dist/server/routes/git-http.js +86 -39
- package/dist/server/routes/git-http.js.map +1 -1
- package/dist/server/routes/graph-api-access.d.ts +57 -0
- package/dist/server/routes/graph-api-access.js +112 -0
- package/dist/server/routes/graph-api-access.js.map +1 -0
- package/dist/server/routes/graph-api.d.ts +1 -1
- package/dist/server/routes/graph-api.js +1455 -325
- package/dist/server/routes/graph-api.js.map +1 -1
- package/dist/server/routes/health.d.ts +18 -0
- package/dist/server/routes/health.js +74 -0
- package/dist/server/routes/health.js.map +1 -0
- package/dist/server/routes/import-batch.d.ts +24 -0
- package/dist/server/routes/import-batch.js +33 -0
- package/dist/server/routes/import-batch.js.map +1 -0
- package/dist/server/routes/insights-api.d.ts +9 -2
- package/dist/server/routes/insights-api.js +355 -61
- package/dist/server/routes/insights-api.js.map +1 -1
- package/dist/server/routes/mcp.d.ts +7 -3
- package/dist/server/routes/mcp.js +24 -8
- package/dist/server/routes/mcp.js.map +1 -1
- package/dist/server/routes/oauth-api.d.ts +67 -0
- package/dist/server/routes/oauth-api.js +421 -0
- package/dist/server/routes/oauth-api.js.map +1 -0
- package/dist/server/routes/permissions-api.d.ts +9 -2
- package/dist/server/routes/permissions-api.js +87 -31
- package/dist/server/routes/permissions-api.js.map +1 -1
- package/dist/server/routes/r2-api.d.ts +25 -0
- package/dist/server/routes/r2-api.js +276 -0
- package/dist/server/routes/r2-api.js.map +1 -0
- package/dist/server/routes/secrets-api.d.ts +36 -0
- package/dist/server/routes/secrets-api.js +308 -0
- package/dist/server/routes/secrets-api.js.map +1 -0
- package/dist/server/routes/settings-api.d.ts +29 -0
- package/dist/server/routes/settings-api.js +180 -0
- package/dist/server/routes/settings-api.js.map +1 -0
- package/dist/server/routes/share-api.d.ts +32 -0
- package/dist/server/routes/share-api.js +234 -0
- package/dist/server/routes/share-api.js.map +1 -0
- package/dist/server/routes/views-api.js +51 -0
- package/dist/server/routes/views-api.js.map +1 -1
- package/dist/server/routes/workspace-api.d.ts +2 -1
- package/dist/server/routes/workspace-api.js +142 -23
- package/dist/server/routes/workspace-api.js.map +1 -1
- package/dist/server/routes/ws.d.ts +3 -2
- package/dist/server/routes/ws.js +68 -17
- package/dist/server/routes/ws.js.map +1 -1
- package/dist/server/session-manager.d.ts +48 -5
- package/dist/server/session-manager.js +182 -14
- package/dist/server/session-manager.js.map +1 -1
- package/dist/server/ws-hub.d.ts +124 -37
- package/dist/server/ws-hub.js +0 -0
- package/dist/server/ws-hub.js.map +1 -1
- package/dist/server/yjs-manager.d.ts +278 -7
- package/dist/server/yjs-manager.js +830 -38
- package/dist/server/yjs-manager.js.map +1 -1
- package/dist/server/yjs-persistence.d.ts +165 -0
- package/dist/server/yjs-persistence.js +557 -0
- package/dist/server/yjs-persistence.js.map +1 -0
- package/dist/server/yjs-text-diff.d.ts +32 -0
- package/dist/server/yjs-text-diff.js +61 -0
- package/dist/server/yjs-text-diff.js.map +1 -0
- package/dist/services/access-control.d.ts +73 -0
- package/dist/services/access-control.js +165 -0
- package/dist/services/access-control.js.map +1 -0
- package/dist/services/artifact-asset-token.d.ts +69 -0
- package/dist/services/artifact-asset-token.js +94 -0
- package/dist/services/artifact-asset-token.js.map +1 -0
- package/dist/services/artifact-library-sources.d.ts +3 -0
- package/dist/services/artifact-library-sources.js +44 -0
- package/dist/services/artifact-library-sources.js.map +1 -0
- package/dist/services/artifact-render-export.d.ts +97 -0
- package/dist/services/artifact-render-export.js +467 -0
- package/dist/services/artifact-render-export.js.map +1 -0
- package/dist/services/asset-caption-service.d.ts +103 -0
- package/dist/services/asset-caption-service.js +186 -0
- package/dist/services/asset-caption-service.js.map +1 -0
- package/dist/services/asset-delete-authz.d.ts +31 -0
- package/dist/services/asset-delete-authz.js +61 -0
- package/dist/services/asset-delete-authz.js.map +1 -0
- package/dist/services/asset-finalize-service.d.ts +58 -0
- package/dist/services/asset-finalize-service.js +216 -0
- package/dist/services/asset-finalize-service.js.map +1 -0
- package/dist/services/asset-import-service.d.ts +111 -0
- package/dist/services/asset-import-service.js +394 -0
- package/dist/services/asset-import-service.js.map +1 -0
- package/dist/services/asset-index-sweep.d.ts +95 -0
- package/dist/services/asset-index-sweep.js +249 -0
- package/dist/services/asset-index-sweep.js.map +1 -0
- package/dist/services/asset-lifecycle-check.d.ts +22 -0
- package/dist/services/asset-lifecycle-check.js +80 -0
- package/dist/services/asset-lifecycle-check.js.map +1 -0
- package/dist/services/asset-listing.d.ts +72 -0
- package/dist/services/asset-listing.js +321 -0
- package/dist/services/asset-listing.js.map +1 -0
- package/dist/services/asset-presign-service.d.ts +68 -0
- package/dist/services/asset-presign-service.js +124 -0
- package/dist/services/asset-presign-service.js.map +1 -0
- package/dist/services/asset-sidecar-service.d.ts +28 -0
- package/dist/services/asset-sidecar-service.js +79 -0
- package/dist/services/asset-sidecar-service.js.map +1 -0
- package/dist/services/asset-upload-errors.d.ts +41 -0
- package/dist/services/asset-upload-errors.js +45 -0
- package/dist/services/asset-upload-errors.js.map +1 -0
- package/dist/services/asset-upload-service.d.ts +56 -0
- package/dist/services/asset-upload-service.js +200 -0
- package/dist/services/asset-upload-service.js.map +1 -0
- package/dist/services/asset-upload-token.d.ts +58 -0
- package/dist/services/asset-upload-token.js +75 -0
- package/dist/services/asset-upload-token.js.map +1 -0
- package/dist/services/assets/asset-index-service.d.ts +127 -0
- package/dist/services/assets/asset-index-service.js +227 -0
- package/dist/services/assets/asset-index-service.js.map +1 -0
- package/dist/services/assets/base.d.ts +128 -2
- package/dist/services/assets/base.js +98 -1
- package/dist/services/assets/base.js.map +1 -1
- package/dist/services/assets/index.d.ts +114 -1
- package/dist/services/assets/index.js +221 -0
- package/dist/services/assets/index.js.map +1 -1
- package/dist/services/assets/local.d.ts +16 -1
- package/dist/services/assets/local.js +110 -1
- package/dist/services/assets/local.js.map +1 -1
- package/dist/services/assets/r2-sync.d.ts +88 -0
- package/dist/services/assets/r2-sync.js +412 -0
- package/dist/services/assets/r2-sync.js.map +1 -0
- package/dist/services/assets/r2.d.ts +87 -1
- package/dist/services/assets/r2.js +203 -1
- package/dist/services/assets/r2.js.map +1 -1
- package/dist/services/auth-service.d.ts +312 -45
- package/dist/services/auth-service.js +1011 -195
- package/dist/services/auth-service.js.map +1 -1
- package/dist/services/chat-session-service.d.ts +188 -0
- package/dist/services/chat-session-service.js +512 -0
- package/dist/services/chat-session-service.js.map +1 -0
- package/dist/services/cloud-inference-billing.d.ts +64 -0
- package/dist/services/cloud-inference-billing.js +313 -0
- package/dist/services/cloud-inference-billing.js.map +1 -0
- package/dist/services/comment-service.d.ts +97 -0
- package/dist/services/comment-service.js +341 -0
- package/dist/services/comment-service.js.map +1 -0
- package/dist/services/comment-virtual-entity.d.ts +36 -0
- package/dist/services/comment-virtual-entity.js +71 -0
- package/dist/services/comment-virtual-entity.js.map +1 -0
- package/dist/services/convert-service.d.ts +64 -0
- package/dist/services/convert-service.js +68 -0
- package/dist/services/convert-service.js.map +1 -0
- package/dist/services/csv-service.d.ts +22 -17
- package/dist/services/csv-service.js +55 -92
- package/dist/services/csv-service.js.map +1 -1
- package/dist/services/entity-mutations.d.ts +213 -0
- package/dist/services/entity-mutations.js +380 -0
- package/dist/services/entity-mutations.js.map +1 -0
- package/dist/services/{meeting-processor.d.ts → event-processor.d.ts} +15 -8
- package/dist/services/{meeting-processor.js → event-processor.js} +124 -65
- package/dist/services/event-processor.js.map +1 -0
- package/dist/services/extract/docx.d.ts +1 -0
- package/dist/services/extract/docx.js +233 -0
- package/dist/services/extract/docx.js.map +1 -0
- package/dist/services/extract/index.d.ts +9 -0
- package/dist/services/extract/index.js +10 -0
- package/dist/services/extract/index.js.map +1 -0
- package/dist/services/extract/pdf.d.ts +13 -0
- package/dist/services/extract/pdf.js +69 -0
- package/dist/services/extract/pdf.js.map +1 -0
- package/dist/services/folder-creation.d.ts +33 -0
- package/dist/services/folder-creation.js +103 -0
- package/dist/services/folder-creation.js.map +1 -0
- package/dist/services/git.d.ts +58 -0
- package/dist/services/git.js +194 -55
- package/dist/services/git.js.map +1 -1
- package/dist/services/graph-maintenance.js +4 -4
- package/dist/services/graph-maintenance.js.map +1 -1
- package/dist/services/import-service.d.ts +51 -2
- package/dist/services/import-service.js +254 -107
- package/dist/services/import-service.js.map +1 -1
- package/dist/services/lint-service.js +10 -17
- package/dist/services/lint-service.js.map +1 -1
- package/dist/services/markdown.d.ts +12 -1
- package/dist/services/markdown.js +77 -9
- package/dist/services/markdown.js.map +1 -1
- package/dist/services/mention-detector.d.ts +23 -0
- package/dist/services/mention-detector.js +47 -0
- package/dist/services/mention-detector.js.map +1 -0
- package/dist/services/model-capabilities.d.ts +41 -0
- package/dist/services/model-capabilities.js +107 -0
- package/dist/services/model-capabilities.js.map +1 -0
- package/dist/services/notification-broadcast.d.ts +32 -0
- package/dist/services/notification-broadcast.js +38 -0
- package/dist/services/notification-broadcast.js.map +1 -0
- package/dist/services/notification-service.d.ts +41 -0
- package/dist/services/notification-service.js +100 -0
- package/dist/services/notification-service.js.map +1 -0
- package/dist/services/oauth-server-store.d.ts +147 -0
- package/dist/services/oauth-server-store.js +319 -0
- package/dist/services/oauth-server-store.js.map +1 -0
- package/dist/services/orphan-service.js +2 -2
- package/dist/services/orphan-service.js.map +1 -1
- package/dist/services/personal-folder.d.ts +40 -0
- package/dist/services/personal-folder.js +101 -0
- package/dist/services/personal-folder.js.map +1 -0
- package/dist/services/scratch-asset-promote.d.ts +57 -0
- package/dist/services/scratch-asset-promote.js +95 -0
- package/dist/services/scratch-asset-promote.js.map +1 -0
- package/dist/services/scratch-attachment-service.d.ts +196 -0
- package/dist/services/scratch-attachment-service.js +347 -0
- package/dist/services/scratch-attachment-service.js.map +1 -0
- package/dist/services/share-link-service.d.ts +57 -0
- package/dist/services/share-link-service.js +142 -0
- package/dist/services/share-link-service.js.map +1 -0
- package/dist/services/user-person-bridge.d.ts +136 -0
- package/dist/services/user-person-bridge.js +340 -0
- package/dist/services/user-person-bridge.js.map +1 -0
- package/dist/services/vector-service.d.ts +282 -5
- package/dist/services/vector-service.js +585 -29
- package/dist/services/vector-service.js.map +1 -1
- package/dist/services/workspace-access.d.ts +108 -0
- package/dist/services/workspace-access.js +149 -0
- package/dist/services/workspace-access.js.map +1 -0
- package/dist/services/workspace-assets-folder.d.ts +46 -0
- package/dist/services/workspace-assets-folder.js +75 -0
- package/dist/services/workspace-assets-folder.js.map +1 -0
- package/dist/utils/git.d.ts +17 -2
- package/dist/utils/git.js +23 -7
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/log.d.ts +42 -0
- package/dist/utils/log.js +137 -0
- package/dist/utils/log.js.map +1 -0
- package/dist/utils/preflight.js +2 -2
- package/dist/utils/preflight.js.map +1 -1
- package/dist/utils/version-checker.d.ts +12 -19
- package/dist/utils/version-checker.js +14 -104
- package/dist/utils/version-checker.js.map +1 -1
- package/dist/web/_app/immutable/assets/0.Bs_z3Z86.css +2 -0
- package/dist/web/_app/immutable/assets/12.DlIf1mKh.css +1 -0
- package/dist/web/_app/immutable/assets/14.7d-Q37wc.css +1 -0
- package/dist/web/_app/immutable/assets/15.BwBFdc1D.css +1 -0
- package/dist/web/_app/immutable/assets/16.CmLrbzZp.css +1 -0
- package/dist/web/_app/immutable/assets/17.DcuK5ZVm.css +1 -0
- package/dist/web/_app/immutable/assets/2.DATnR31c.css +1 -0
- package/dist/web/_app/immutable/assets/3.Cz4H8n_O.css +1 -0
- package/dist/web/_app/immutable/assets/4.aDHteTDy.css +1 -0
- package/dist/web/_app/immutable/assets/6.CF1i5Bon.css +1 -0
- package/dist/web/_app/immutable/assets/ArtifactEntityView.C4ooklFD.css +1 -0
- package/dist/web/_app/immutable/assets/AssetLibraryPicker.BOFW0MvF.css +1 -0
- package/dist/web/_app/immutable/assets/BulkActionsBar.cmKvHzRK.css +1 -0
- package/dist/web/_app/immutable/assets/CalendarView.lBCvS3X5.css +1 -0
- package/dist/web/_app/immutable/assets/CodeMirrorEditor.D6hf2pNJ.css +1 -0
- package/dist/web/_app/immutable/assets/CopyField.DVGZtw4U.css +1 -0
- package/dist/web/_app/immutable/assets/FolderMembersPanel.kiYnDFHu.css +1 -0
- package/dist/web/_app/immutable/assets/FolderMutationDialogs.BMRF6Z3z.css +1 -0
- package/dist/web/_app/immutable/assets/FolderPicker.Cp46GHe2.css +1 -0
- package/dist/web/_app/immutable/assets/GalleryView.WBGxxUQc.css +1 -0
- package/dist/web/_app/immutable/assets/GraphView.BJtGL9py.css +1 -0
- package/dist/web/_app/immutable/assets/KanbanView.BOaI5KFL.css +1 -0
- package/dist/web/_app/immutable/assets/Link.vV0ne105.css +1 -0
- package/dist/web/_app/immutable/assets/Markdown.BZnsSOSf.css +1 -0
- package/dist/web/_app/immutable/assets/Rail.ilusFgD4.css +1 -0
- package/dist/web/_app/immutable/assets/SettingsDialog.D7-BO6S_.css +1 -0
- package/dist/web/_app/immutable/assets/Spinner.UBfl0pab.css +1 -0
- package/dist/web/_app/immutable/assets/StopFilledAlt.fNlDN65D.css +1 -0
- package/dist/web/_app/immutable/assets/TimelineView.xAZBJhHw.css +1 -0
- package/dist/web/_app/immutable/assets/WorkspaceView.C8ErUJAY.css +1 -0
- package/dist/web/_app/immutable/assets/button.BlLm4Dg1.css +1 -0
- package/dist/web/_app/immutable/assets/history-summary.LpmHXasl.css +1 -0
- package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-400-normal.CvHOgSBP.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-400-normal.DMJ8VG8y.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-500-normal.CB9ihrfo.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-500-normal.DSY6xOcd.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-italic.CZTNEAuW.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-italic.CsGl1sm0.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-normal.CDDApCn2.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-normal.CYLoc0-x.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-italic.BNK2_mGO.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-italic.DpEwFAQM.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-normal.6ng42L7E.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-normal.BgVn5rGT.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-600-normal.Cu4Hd6ag.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-600-normal.CuJfVYMP.woff2 +0 -0
- package/dist/web/_app/immutable/assets/inline-list.cqga56xT.css +1 -0
- package/dist/web/_app/immutable/assets/list-columns.BgnafZ4K.css +1 -0
- package/dist/web/_app/immutable/assets/realtime.DDCWxn3B.css +1 -0
- package/dist/web/_app/immutable/assets/select.B90KUqR4.css +1 -0
- package/dist/web/_app/immutable/assets/sheet.RF9RBmml.css +1 -0
- package/dist/web/_app/immutable/chunks/22qYtvr82.js +1 -0
- package/dist/web/_app/immutable/chunks/2f1VclTm.js +1 -0
- package/dist/web/_app/immutable/chunks/4xgUPoGj2.js +2 -0
- package/dist/web/_app/immutable/chunks/5CYQk4xR.js +1 -0
- package/dist/web/_app/immutable/chunks/6S9WOky52.js +1 -0
- package/dist/web/_app/immutable/chunks/9K8VREGP.js +1 -0
- package/dist/web/_app/immutable/chunks/B-n5q6ku.js +1 -0
- package/dist/web/_app/immutable/chunks/B0p2fSEV2.js +1 -0
- package/dist/web/_app/immutable/chunks/B2oi87jG.js +2 -0
- package/dist/web/_app/immutable/chunks/B5Rb52QU.js +1 -0
- package/dist/web/_app/immutable/chunks/B6Lt-qaJ.js +1 -0
- package/dist/web/_app/immutable/chunks/B6O-q2CN.js +1 -0
- package/dist/web/_app/immutable/chunks/B6qeIQZz.js +2 -0
- package/dist/web/_app/immutable/chunks/B9KfEsQw2.js +1 -0
- package/dist/web/_app/immutable/chunks/BB-RSeXQ.js +1 -0
- package/dist/web/_app/immutable/chunks/BCQQzpbj.js +1 -0
- package/dist/web/_app/immutable/chunks/BGdzd-Tc.js +1 -0
- package/dist/web/_app/immutable/chunks/BLs1h0Rh2.js +1 -0
- package/dist/web/_app/immutable/chunks/BPzV_xOS2.js +1 -0
- package/dist/web/_app/immutable/chunks/BT2C6q8n.js +1 -0
- package/dist/web/_app/immutable/chunks/BUesbLq2.js +1 -0
- package/dist/web/_app/immutable/chunks/BUrnwOw4.js +2 -0
- package/dist/web/_app/immutable/chunks/BV-iCKqa.js +1 -0
- package/dist/web/_app/immutable/chunks/BVCJtXyc.js +1 -0
- package/dist/web/_app/immutable/chunks/BY9a3GSt.js +6 -0
- package/dist/web/_app/immutable/chunks/BZi3uKF4.js +1 -0
- package/dist/web/_app/immutable/chunks/BbfHGU9n2.js +1 -0
- package/dist/web/_app/immutable/chunks/Bbqu2-5G2.js +1 -0
- package/dist/web/_app/immutable/chunks/BbsX1Slr.js +3 -0
- package/dist/web/_app/immutable/chunks/BcwjqHaZ2.js +1 -0
- package/dist/web/_app/immutable/chunks/BizeEpTx.js +2 -0
- package/dist/web/_app/immutable/chunks/BlgjVmFM2.js +14 -0
- package/dist/web/_app/immutable/chunks/BocSRgv12.js +1 -0
- package/dist/web/_app/immutable/chunks/BojBYqc3.js +1 -0
- package/dist/web/_app/immutable/chunks/BpCG9m962.js +1 -0
- package/dist/web/_app/immutable/chunks/BqvnBg_y.js +1 -0
- package/dist/web/_app/immutable/chunks/BsT0J1QD.js +1 -0
- package/dist/web/_app/immutable/chunks/BsW72fyR2.js +1 -0
- package/dist/web/_app/immutable/chunks/Bti_XKwx.js +2692 -0
- package/dist/web/_app/immutable/chunks/Bua97Had2.js +2 -0
- package/dist/web/_app/immutable/chunks/BuhW5Fr0.js +689 -0
- package/dist/web/_app/immutable/chunks/Bx74EEyn2.js +1 -0
- package/dist/web/_app/immutable/chunks/BxPN0T61.js +1 -0
- package/dist/web/_app/immutable/chunks/Bz9lrgGs.js +1 -0
- package/dist/web/_app/immutable/chunks/BzaxZ6j12.js +1 -0
- package/dist/web/_app/immutable/chunks/C1B4xDs0.js +1 -0
- package/dist/web/_app/immutable/chunks/C1trcC8M.js +7 -0
- package/dist/web/_app/immutable/chunks/C9tvkk7Y2.js +22 -0
- package/dist/web/_app/immutable/chunks/CBQjdDZf.js +1 -0
- package/dist/web/_app/immutable/chunks/CDeazMFW2.js +2 -0
- package/dist/web/_app/immutable/chunks/CEahbtnP.js +1 -0
- package/dist/web/_app/immutable/chunks/CGjVCd0e.js +8 -0
- package/dist/web/_app/immutable/chunks/CICK9maP.js +1 -0
- package/dist/web/_app/immutable/chunks/CIoNEHQ82.js +184 -0
- package/dist/web/_app/immutable/chunks/CP8_U450.js +1 -0
- package/dist/web/_app/immutable/chunks/CQ1eQ93t2.js +6 -0
- package/dist/web/_app/immutable/chunks/CUFQMEBn2.js +1 -0
- package/dist/web/_app/immutable/chunks/CYEYDNwO2.js +1 -0
- package/dist/web/_app/immutable/chunks/CYyIP7kP2.js +66 -0
- package/dist/web/_app/immutable/chunks/CZgFaimi2.js +83 -0
- package/dist/web/_app/immutable/chunks/CZqvCTCv.js +1 -0
- package/dist/web/_app/immutable/chunks/CcI9jYBV.js +1 -0
- package/dist/web/_app/immutable/chunks/CcWaWbrI2.js +1 -0
- package/dist/web/_app/immutable/chunks/CdtzRVZK.js +1 -0
- package/dist/web/_app/immutable/chunks/CfYG72Hc.js +1 -0
- package/dist/web/_app/immutable/chunks/Ch1kmm3J2.js +1 -0
- package/dist/web/_app/immutable/chunks/CmSSN61R2.js +1 -0
- package/dist/web/_app/immutable/chunks/Cqm5wAin.js +1 -0
- package/dist/web/_app/immutable/chunks/CuYPXpWU.js +1 -0
- package/dist/web/_app/immutable/chunks/CvSEodTA.js +1 -0
- package/dist/web/_app/immutable/chunks/CvqqrTrj.js +1 -0
- package/dist/web/_app/immutable/chunks/CwAmWt6h.js +1 -0
- package/dist/web/_app/immutable/chunks/CwP3Oa7F.js +1 -0
- package/dist/web/_app/immutable/chunks/CyTluew1.js +2 -0
- package/dist/web/_app/immutable/chunks/CzXdOgVl2.js +7 -0
- package/dist/web/_app/immutable/chunks/D0IAituJ.js +1 -0
- package/dist/web/_app/immutable/chunks/D0W7c6Sg.js +185 -0
- package/dist/web/_app/immutable/chunks/D0rBhnqB2.js +1 -0
- package/dist/web/_app/immutable/chunks/D1-GZSN1.js +1 -0
- package/dist/web/_app/immutable/chunks/D1yvtriI.js +1 -0
- package/dist/web/_app/immutable/chunks/D25NMRpl.js +1 -0
- package/dist/web/_app/immutable/chunks/D8wZ2xul.js +4 -0
- package/dist/web/_app/immutable/chunks/DA3HEX3X.js +1 -0
- package/dist/web/_app/immutable/chunks/DD9wj4ca2.js +1 -0
- package/dist/web/_app/immutable/chunks/DJ1YeiJL2.js +1 -0
- package/dist/web/_app/immutable/chunks/DKFZnpVC.js +5 -0
- package/dist/web/_app/immutable/chunks/DKJl40hl.js +1 -0
- package/dist/web/_app/immutable/chunks/DPUVu0T0.js +1 -0
- package/dist/web/_app/immutable/chunks/DQMWa2t7.js +1 -0
- package/dist/web/_app/immutable/chunks/DXsFrDer2.js +1 -0
- package/dist/web/_app/immutable/chunks/DYc5KW3F.js +1 -0
- package/dist/web/_app/immutable/chunks/DZcTwXBW.js +1 -0
- package/dist/web/_app/immutable/chunks/DcPrzUMJ.js +1 -0
- package/dist/web/_app/immutable/chunks/DdPO8kRu2.js +2 -0
- package/dist/web/_app/immutable/chunks/DeOXyJZw2.js +1 -0
- package/dist/web/_app/immutable/chunks/DfufUFR1.js +2 -0
- package/dist/web/_app/immutable/chunks/DiQg3ing.js +1 -0
- package/dist/web/_app/immutable/chunks/DjIqa1_y.js +2 -0
- package/dist/web/_app/immutable/chunks/DkJ1dkxV2.js +1 -0
- package/dist/web/_app/immutable/chunks/Dl63IUnH2.js +224 -0
- package/dist/web/_app/immutable/chunks/DmFdD6zT.js +1 -0
- package/dist/web/_app/immutable/chunks/Dn3R8S-U.js +1 -0
- package/dist/web/_app/immutable/chunks/DpNr1GQ2.js +1 -0
- package/dist/web/_app/immutable/chunks/DpVNDHXz.js +2 -0
- package/dist/web/_app/immutable/chunks/DuxziNnw.js +1 -0
- package/dist/web/_app/immutable/chunks/Dv3A3Wcj.js +1 -0
- package/dist/web/_app/immutable/chunks/FuiJnZG0.js +1 -0
- package/dist/web/_app/immutable/chunks/Izkulod7.js +1 -0
- package/dist/web/_app/immutable/chunks/KZY6ongq2.js +2 -0
- package/dist/web/_app/immutable/chunks/LYL8znYR2.js +23 -0
- package/dist/web/_app/immutable/chunks/PhN6tXuJ2.js +1 -0
- package/dist/web/_app/immutable/chunks/PyLyCpuL.js +1 -0
- package/dist/web/_app/immutable/chunks/RK4gCWN0.js +2 -0
- package/dist/web/_app/immutable/chunks/VsBngTf4.js +2 -0
- package/dist/web/_app/immutable/chunks/XcWejFm_.js +5 -0
- package/dist/web/_app/immutable/chunks/al_nidE9.js +1 -0
- package/dist/web/_app/immutable/chunks/e50-izZO2.js +1 -0
- package/dist/web/_app/immutable/chunks/hG-QCarB.js +1 -0
- package/dist/web/_app/immutable/chunks/hStvCHkX.js +1 -0
- package/dist/web/_app/immutable/chunks/iJVY9p0y.js +3 -0
- package/dist/web/_app/immutable/chunks/kNaey6uv.js +1 -0
- package/dist/web/_app/immutable/chunks/pIXNe0C1.js +1 -0
- package/dist/web/_app/immutable/chunks/pNSRq_1B.js +2 -0
- package/dist/web/_app/immutable/chunks/qwr5boV8.js +1 -0
- package/dist/web/_app/immutable/chunks/rjjyuGhb.js +1 -0
- package/dist/web/_app/immutable/chunks/sg-T-FoN.js +1 -0
- package/dist/web/_app/immutable/chunks/uBgoVlsx.js +3 -0
- package/dist/web/_app/immutable/chunks/ulshNz6x.js +2 -0
- package/dist/web/_app/immutable/chunks/xY0c-UfG.js +3 -0
- package/dist/web/_app/immutable/chunks/xeNvx4Bl2.js +1 -0
- package/dist/web/_app/immutable/chunks/xihTtKlq.js +1 -0
- package/dist/web/_app/immutable/entry/app.pNUW-q4U.js +2 -0
- package/dist/web/_app/immutable/entry/start.DxGtIGG_.js +1 -0
- package/dist/web/_app/immutable/nodes/0.D6ZCY_R6.js +2 -0
- package/dist/web/_app/immutable/nodes/1.BryH3TNr.js +1 -0
- package/dist/web/_app/immutable/nodes/10.CMZMvR17.js +1 -0
- package/dist/web/_app/immutable/nodes/11.QHx_JShx.js +1 -0
- package/dist/web/_app/immutable/nodes/12.CiRWbb4X.js +1 -0
- package/dist/web/_app/immutable/nodes/13.CYrHXCA8.js +1 -0
- package/dist/web/_app/immutable/nodes/14.K18eIE5Z.js +1 -0
- package/dist/web/_app/immutable/nodes/15.DxgnZ61h.js +1 -0
- package/dist/web/_app/immutable/nodes/16.Dn6iuWIo.js +1 -0
- package/dist/web/_app/immutable/nodes/17.viwS7vTR.js +77 -0
- package/dist/web/_app/immutable/nodes/2.BQkQ_uUM.js +122 -0
- package/dist/web/_app/immutable/nodes/3.B4pqXsqq.js +6 -0
- package/dist/web/_app/immutable/nodes/4.CKXEgIAP.js +11 -0
- package/dist/web/_app/immutable/nodes/5.A2TASl4Q.js +1 -0
- package/dist/web/_app/immutable/nodes/6.DaIRO3SI.js +6 -0
- package/dist/web/_app/immutable/nodes/7.ga2UvFm-.js +1 -0
- package/dist/web/_app/immutable/nodes/8.BTEWT81u.js +1 -0
- package/dist/web/_app/immutable/nodes/9.BVxo0E0c.js +1 -0
- package/dist/web/_app/version.json +1 -1
- package/dist/web/favicon-16.png +0 -0
- package/dist/web/favicon-180.png +0 -0
- package/dist/web/favicon-32.png +0 -0
- package/dist/web/favicon-48.png +0 -0
- package/dist/web/favicon-512.png +0 -0
- package/dist/web/favicon.ico +0 -0
- package/dist/web/favicon.svg +8 -0
- package/dist/web/index.html +56 -21
- package/dist/web/studiograph-logomark.svg +29 -0
- package/package.json +35 -14
- package/dist/agent/skills/enrich-entities.md +0 -136
- package/dist/agent/skills/sync-configuration.md +0 -119
- package/dist/agent/skills/sync-setup.md +0 -82
- package/dist/agent/tools/message-tools.d.ts +0 -42
- package/dist/agent/tools/message-tools.js +0 -106
- package/dist/agent/tools/message-tools.js.map +0 -1
- package/dist/cli/commands/app.d.ts +0 -7
- package/dist/cli/commands/app.js +0 -268
- package/dist/cli/commands/app.js.map +0 -1
- package/dist/cli/commands/clear.d.ts +0 -5
- package/dist/cli/commands/clear.js +0 -36
- package/dist/cli/commands/clear.js.map +0 -1
- package/dist/cli/commands/collection.d.ts +0 -10
- package/dist/cli/commands/collection.js.map +0 -1
- package/dist/cli/commands/join.d.ts +0 -9
- package/dist/cli/commands/join.js +0 -255
- package/dist/cli/commands/join.js.map +0 -1
- package/dist/cli/commands/start.d.ts +0 -7
- package/dist/cli/commands/start.js +0 -584
- package/dist/cli/commands/start.js.map +0 -1
- package/dist/cli/commands/update.d.ts +0 -8
- package/dist/cli/commands/update.js +0 -155
- package/dist/cli/commands/update.js.map +0 -1
- package/dist/cli/commands/user.d.ts +0 -7
- package/dist/cli/commands/user.js +0 -175
- package/dist/cli/commands/user.js.map +0 -1
- package/dist/cli/scaffolding.d.ts +0 -12
- package/dist/cli/scaffolding.js +0 -397
- package/dist/cli/scaffolding.js.map +0 -1
- package/dist/integrations/registry.d.ts +0 -8
- package/dist/integrations/registry.js +0 -7
- package/dist/integrations/registry.js.map +0 -1
- package/dist/integrations/types.d.ts +0 -43
- package/dist/integrations/types.js +0 -5
- package/dist/integrations/types.js.map +0 -1
- package/dist/lib/lib/utils.d.ts +0 -2
- package/dist/lib/lib/utils.js +0 -6
- package/dist/lib/lib/utils.js.map +0 -1
- package/dist/server/chrome/chrome.css +0 -691
- package/dist/server/chrome/chrome.js +0 -374
- package/dist/server/commit-scheduler.d.ts +0 -39
- package/dist/server/commit-scheduler.js +0 -113
- package/dist/server/commit-scheduler.js.map +0 -1
- package/dist/server/plugin-loader.d.ts +0 -53
- package/dist/server/plugin-loader.js +0 -155
- package/dist/server/plugin-loader.js.map +0 -1
- package/dist/server/routes/meeting-ingest-api.d.ts +0 -14
- package/dist/server/routes/meeting-ingest-api.js.map +0 -1
- package/dist/server/routes/messages-api.d.ts +0 -15
- package/dist/server/routes/messages-api.js +0 -385
- package/dist/server/routes/messages-api.js.map +0 -1
- package/dist/services/batch-processor.d.ts +0 -49
- package/dist/services/batch-processor.js +0 -166
- package/dist/services/batch-processor.js.map +0 -1
- package/dist/services/briefing.d.ts +0 -26
- package/dist/services/briefing.js +0 -230
- package/dist/services/briefing.js.map +0 -1
- package/dist/services/heartbeat.d.ts +0 -28
- package/dist/services/heartbeat.js +0 -183
- package/dist/services/heartbeat.js.map +0 -1
- package/dist/services/image-import-service.d.ts +0 -24
- package/dist/services/image-import-service.js +0 -108
- package/dist/services/image-import-service.js.map +0 -1
- package/dist/services/insights.d.ts +0 -38
- package/dist/services/insights.js +0 -269
- package/dist/services/insights.js.map +0 -1
- package/dist/services/meeting-processor.js.map +0 -1
- package/dist/services/message-service.d.ts +0 -68
- package/dist/services/message-service.js +0 -220
- package/dist/services/message-service.js.map +0 -1
- package/dist/utils/workspace-config.d.ts +0 -8
- package/dist/utils/workspace-config.js +0 -22
- package/dist/utils/workspace-config.js.map +0 -1
- package/dist/web/_app/immutable/assets/0.uPSqtsC5.css +0 -1
- package/dist/web/_app/immutable/assets/11.2jzI3cZY.css +0 -1
- package/dist/web/_app/immutable/assets/12.CT4xL4K3.css +0 -1
- package/dist/web/_app/immutable/assets/13.BUrHkYry.css +0 -1
- package/dist/web/_app/immutable/assets/2.DpQWr6q6.css +0 -1
- package/dist/web/_app/immutable/assets/3.BxdqT7zi.css +0 -1
- package/dist/web/_app/immutable/assets/4.DdNqjd0T.css +0 -1
- package/dist/web/_app/immutable/assets/5.DFeGxLYf.css +0 -1
- package/dist/web/_app/immutable/assets/6.DXZr_rI_.css +0 -1
- package/dist/web/_app/immutable/assets/GraphView.D9ePpZez.css +0 -1
- package/dist/web/_app/immutable/assets/Toaster.rN8r_Hzv.css +0 -1
- package/dist/web/_app/immutable/assets/ViewToolbar.BWE03S64.css +0 -1
- package/dist/web/_app/immutable/assets/WorkspaceView.CgGDi_Zb.css +0 -1
- package/dist/web/_app/immutable/assets/wikilinks.CzMBkUMB.css +0 -1
- package/dist/web/_app/immutable/chunks/-jG4Obyh.js +0 -4
- package/dist/web/_app/immutable/chunks/2nrc8f_O.js +0 -1
- package/dist/web/_app/immutable/chunks/7S2LGqoP.js +0 -2
- package/dist/web/_app/immutable/chunks/8Q3ZJIYu.js +0 -1
- package/dist/web/_app/immutable/chunks/B8ydT5xX.js +0 -2
- package/dist/web/_app/immutable/chunks/BB_5th5W.js +0 -3383
- package/dist/web/_app/immutable/chunks/BEn6N5c2.js +0 -1
- package/dist/web/_app/immutable/chunks/BFNNbCAM.js +0 -1
- package/dist/web/_app/immutable/chunks/BFZZEUd5.js +0 -1
- package/dist/web/_app/immutable/chunks/BGk8kfOE.js +0 -2
- package/dist/web/_app/immutable/chunks/BIBCr278.js +0 -1
- package/dist/web/_app/immutable/chunks/BPCkkwqe.js +0 -1
- package/dist/web/_app/immutable/chunks/BhlvzGQx.js +0 -1
- package/dist/web/_app/immutable/chunks/BlMknQeF.js +0 -1
- package/dist/web/_app/immutable/chunks/BpjqrlCg.js +0 -1
- package/dist/web/_app/immutable/chunks/BrebtJNG.js +0 -18
- package/dist/web/_app/immutable/chunks/ByBZ7JIT.js +0 -1
- package/dist/web/_app/immutable/chunks/Bz0ZjVQE.js +0 -2
- package/dist/web/_app/immutable/chunks/BzJTZOK2.js +0 -1
- package/dist/web/_app/immutable/chunks/C0LVZhvn.js +0 -1
- package/dist/web/_app/immutable/chunks/C3uBrOS5.js +0 -1
- package/dist/web/_app/immutable/chunks/C8R1sDpW.js +0 -1
- package/dist/web/_app/immutable/chunks/CDRHrs0g.js +0 -1
- package/dist/web/_app/immutable/chunks/CN5_py1I.js +0 -1
- package/dist/web/_app/immutable/chunks/CPne482a.js +0 -1
- package/dist/web/_app/immutable/chunks/CSVbGg_b.js +0 -5
- package/dist/web/_app/immutable/chunks/CWyU-seV.js +0 -1
- package/dist/web/_app/immutable/chunks/CX_61fY8.js +0 -5
- package/dist/web/_app/immutable/chunks/CYrVHOHA.js +0 -1
- package/dist/web/_app/immutable/chunks/ChsiIm-E.js +0 -1
- package/dist/web/_app/immutable/chunks/CojKppbh.js +0 -1
- package/dist/web/_app/immutable/chunks/CqkleIqs.js +0 -1
- package/dist/web/_app/immutable/chunks/CtYLtD7K.js +0 -1
- package/dist/web/_app/immutable/chunks/D-HDy5qS.js +0 -1
- package/dist/web/_app/immutable/chunks/D5aIYSkd.js +0 -1
- package/dist/web/_app/immutable/chunks/DBBXARVf.js +0 -1
- package/dist/web/_app/immutable/chunks/DFYOFE3o.js +0 -1
- package/dist/web/_app/immutable/chunks/DKaafS50.js +0 -1
- package/dist/web/_app/immutable/chunks/DUMOo1Pn.js +0 -1
- package/dist/web/_app/immutable/chunks/DWX9f6AF.js +0 -1
- package/dist/web/_app/immutable/chunks/DY8-EONP.js +0 -1
- package/dist/web/_app/immutable/chunks/DkoHPElM.js +0 -1
- package/dist/web/_app/immutable/chunks/DnL9f0lc.js +0 -7
- package/dist/web/_app/immutable/chunks/DsnmJJEf.js +0 -1
- package/dist/web/_app/immutable/chunks/DujahU3W.js +0 -1
- package/dist/web/_app/immutable/chunks/FBn-ES5k.js +0 -1
- package/dist/web/_app/immutable/chunks/HQpwSOb3.js +0 -1
- package/dist/web/_app/immutable/chunks/KyjzlWRN.js +0 -2
- package/dist/web/_app/immutable/chunks/PPVm8Dsz.js +0 -1
- package/dist/web/_app/immutable/chunks/UwYfmrPx.js +0 -2
- package/dist/web/_app/immutable/chunks/W25ZVI8L.js +0 -2
- package/dist/web/_app/immutable/chunks/WSUKABI_.js +0 -1
- package/dist/web/_app/immutable/chunks/XjsuEnNE.js +0 -5
- package/dist/web/_app/immutable/chunks/ZD6ARAtb.js +0 -1
- package/dist/web/_app/immutable/chunks/pBTf4stg.js +0 -2
- package/dist/web/_app/immutable/chunks/rGIarcnp.js +0 -1
- package/dist/web/_app/immutable/chunks/vxEtkL8z.js +0 -1
- package/dist/web/_app/immutable/chunks/wDIGUaoU.js +0 -3
- package/dist/web/_app/immutable/entry/app.ZHiTM8WS.js +0 -2
- package/dist/web/_app/immutable/entry/start.C9-FfAVc.js +0 -1
- package/dist/web/_app/immutable/nodes/0.D92Orz8k.js +0 -2
- package/dist/web/_app/immutable/nodes/1.BMdyglM_.js +0 -1
- package/dist/web/_app/immutable/nodes/10.BilVDHSL.js +0 -1
- package/dist/web/_app/immutable/nodes/11.CS9E0Hic.js +0 -1
- package/dist/web/_app/immutable/nodes/12.D3BOxYzG.js +0 -1
- package/dist/web/_app/immutable/nodes/13.CClMKYtN.js +0 -1
- package/dist/web/_app/immutable/nodes/2.C8KKElPL.js +0 -267
- package/dist/web/_app/immutable/nodes/3.C5n5uiWU.js +0 -5
- package/dist/web/_app/immutable/nodes/4.DcGVvgiL.js +0 -11
- package/dist/web/_app/immutable/nodes/5.DxIjnFQO.js +0 -4
- package/dist/web/_app/immutable/nodes/6.lkh6kKLj.js +0 -1
- package/dist/web/_app/immutable/nodes/7.Bg7SbfhA.js +0 -1
- package/dist/web/_app/immutable/nodes/8.DcXWCNBE.js +0 -1
- package/dist/web/_app/immutable/nodes/9.Cefi8Jfm.js +0 -1
|
@@ -3,8 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Login, logout, session verification, and auth status endpoints.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
7
|
+
import { isWorkspaceOwner } from '../../services/auth-service.js';
|
|
7
8
|
import { Workspace } from '../../core/workspace.js';
|
|
9
|
+
import { ensurePersonalFolder, archivePersonalFolder } from '../../services/personal-folder.js';
|
|
10
|
+
import { ensureWorkspaceAssetsFolder } from '../../services/workspace-assets-folder.js';
|
|
11
|
+
import { authUserToGitUser, ensurePersonForUser, findPersonRefForUser, linkChosenPersonToUser, BridgeError } from '../../services/user-person-bridge.js';
|
|
12
|
+
import * as access from '../../services/access-control.js';
|
|
13
|
+
import { safeReturnTo } from './oauth-api.js';
|
|
8
14
|
// ── Login rate limiting ──
|
|
9
15
|
const MAX_ATTEMPTS = 5;
|
|
10
16
|
const LOCKOUT_MS = 15 * 60 * 1000; // 15 minutes
|
|
@@ -37,53 +43,237 @@ export function recordFailedAttempt(email) {
|
|
|
37
43
|
export function clearAttempts(email) {
|
|
38
44
|
loginAttempts.delete(email.toLowerCase());
|
|
39
45
|
}
|
|
40
|
-
function
|
|
46
|
+
function requireOwner(req, authService) {
|
|
41
47
|
const token = req.cookies?.['__sg_token'];
|
|
42
48
|
if (!token)
|
|
43
49
|
return null;
|
|
44
50
|
const user = authService.verifyToken(token);
|
|
45
|
-
if (!user || !
|
|
51
|
+
if (!user || !isWorkspaceOwner(user.role))
|
|
46
52
|
return null;
|
|
47
53
|
return user;
|
|
48
54
|
}
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the caller to an AuthUser. The global auth hook skips /api/auth/*
|
|
57
|
+
* so endpoints that need identity (like the token CRUD routes below) must
|
|
58
|
+
* look up credentials themselves.
|
|
59
|
+
*
|
|
60
|
+
* Accepted forms:
|
|
61
|
+
* - Cookie `__sg_token=<jwt>` (web UI)
|
|
62
|
+
* - `Authorization: Bearer <jwt>` (CLI with stored JWT)
|
|
63
|
+
* - `Authorization: Bearer <sg_…>` (CLI with API token)
|
|
64
|
+
*
|
|
65
|
+
* Mirrors the precedence the main API middleware uses elsewhere
|
|
66
|
+
* (src/server/index.ts) — needed so CLI commands like
|
|
67
|
+
* `studiograph admin transfer-ownership` can call /api/auth/* endpoints
|
|
68
|
+
* using the same Bearer sg_ token they use everywhere else.
|
|
69
|
+
*/
|
|
70
|
+
function requireUser(req, authService) {
|
|
71
|
+
const cookieToken = req.cookies?.['__sg_token'];
|
|
72
|
+
if (cookieToken) {
|
|
73
|
+
const user = authService.verifyToken(cookieToken);
|
|
74
|
+
if (user)
|
|
75
|
+
return user;
|
|
76
|
+
}
|
|
77
|
+
const authHeader = req.headers?.authorization;
|
|
78
|
+
if (authHeader?.startsWith('Bearer ')) {
|
|
79
|
+
const bearer = authHeader.slice('Bearer '.length).trim();
|
|
80
|
+
if (bearer.startsWith('sg_')) {
|
|
81
|
+
return authService.verifyApiToken(bearer);
|
|
82
|
+
}
|
|
83
|
+
// Treat anything else as a JWT — verifyToken returns null on invalid input.
|
|
84
|
+
return authService.verifyToken(bearer);
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
function managedCloudAuthConfig() {
|
|
89
|
+
return {
|
|
90
|
+
enabled: parseBoolean(process.env.STUDIOGRAPH_MANAGED_AUTH),
|
|
91
|
+
cloudUrl: process.env.STUDIOGRAPH_CLOUD_URL?.trim() ?? '',
|
|
92
|
+
orgId: process.env.STUDIOGRAPH_CLOUD_ORG_ID?.trim() ?? '',
|
|
93
|
+
workspaceId: process.env.STUDIOGRAPH_CLOUD_WORKSPACE_ID?.trim() ?? '',
|
|
94
|
+
token: process.env.STUDIOGRAPH_CLOUD_TOKEN?.trim() ?? '',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function managedCloudLoginUrl(config) {
|
|
98
|
+
if (!config.cloudUrl || !config.orgId || !config.workspaceId)
|
|
99
|
+
return null;
|
|
100
|
+
const url = new URL('/auth/workspace', config.cloudUrl);
|
|
101
|
+
url.searchParams.set('orgId', config.orgId);
|
|
102
|
+
url.searchParams.set('workspaceId', config.workspaceId);
|
|
103
|
+
return url.toString();
|
|
104
|
+
}
|
|
105
|
+
function managedCloudLogoutUrl(config, returnTo) {
|
|
106
|
+
if (!config.cloudUrl)
|
|
107
|
+
return null;
|
|
108
|
+
const url = new URL('/auth/logout', config.cloudUrl);
|
|
109
|
+
if (returnTo)
|
|
110
|
+
url.searchParams.set('returnTo', returnTo);
|
|
111
|
+
return url.toString();
|
|
112
|
+
}
|
|
113
|
+
function requestOrigin(req) {
|
|
114
|
+
const rawHost = req.headers?.['x-forwarded-host'] ?? req.headers?.host;
|
|
115
|
+
const host = Array.isArray(rawHost) ? rawHost[0] : rawHost;
|
|
116
|
+
if (!host)
|
|
117
|
+
return null;
|
|
118
|
+
const rawProto = req.headers?.['x-forwarded-proto'];
|
|
119
|
+
const forwardedProto = Array.isArray(rawProto) ? rawProto[0] : rawProto;
|
|
120
|
+
const proto = typeof forwardedProto === 'string' && forwardedProto.trim()
|
|
121
|
+
? forwardedProto.split(',')[0].trim()
|
|
122
|
+
: 'http';
|
|
123
|
+
return `${proto}://${host}`;
|
|
124
|
+
}
|
|
125
|
+
function managedLogoutReturnTo(req) {
|
|
126
|
+
const origin = requestOrigin(req);
|
|
127
|
+
if (!origin)
|
|
128
|
+
return null;
|
|
129
|
+
const url = new URL('/login', origin);
|
|
130
|
+
url.searchParams.set('managedLogout', '1');
|
|
131
|
+
return url.toString();
|
|
132
|
+
}
|
|
133
|
+
function verifyCloudLoginToken(token, secret) {
|
|
134
|
+
const [payloadPart, signaturePart] = token.split('.');
|
|
135
|
+
if (!payloadPart || !signaturePart || token.split('.').length !== 2) {
|
|
136
|
+
throw new Error('Malformed login token');
|
|
137
|
+
}
|
|
138
|
+
const expected = hmacBase64Url(payloadPart, secret);
|
|
139
|
+
if (!constantTimeEqual(signaturePart, expected)) {
|
|
140
|
+
throw new Error('Invalid login token signature');
|
|
141
|
+
}
|
|
142
|
+
const claims = JSON.parse(Buffer.from(payloadPart, 'base64url').toString('utf8'));
|
|
143
|
+
if (claims.iss !== 'studiograph-cloud' || claims.aud !== 'studiograph-runtime') {
|
|
144
|
+
throw new Error('Invalid login token audience');
|
|
145
|
+
}
|
|
146
|
+
if (!claims.orgId || !claims.workspaceId || !claims.userId || !claims.email || !claims.displayName || !claims.role) {
|
|
147
|
+
throw new Error('Incomplete login token');
|
|
148
|
+
}
|
|
149
|
+
if (!['owner', 'admin', 'member'].includes(claims.role)) {
|
|
150
|
+
throw new Error('Invalid login token role');
|
|
151
|
+
}
|
|
152
|
+
const now = Math.floor(Date.now() / 1000);
|
|
153
|
+
if (typeof claims.exp !== 'number' || claims.exp < now) {
|
|
154
|
+
throw new Error('Login token has expired');
|
|
155
|
+
}
|
|
156
|
+
if (typeof claims.iat !== 'number' || claims.iat > now + 60) {
|
|
157
|
+
throw new Error('Login token was issued in the future');
|
|
158
|
+
}
|
|
159
|
+
return claims;
|
|
160
|
+
}
|
|
161
|
+
function runtimeRoleForCloudRole(cloudRole, existing, authService) {
|
|
162
|
+
if (existing?.role === 'owner')
|
|
163
|
+
return 'owner';
|
|
164
|
+
if (cloudRole === 'owner')
|
|
165
|
+
return 'owner';
|
|
166
|
+
if (!authService.getOwner() && cloudRole === 'admin')
|
|
167
|
+
return 'owner';
|
|
168
|
+
return 'member';
|
|
169
|
+
}
|
|
170
|
+
function grantManagedWorkspaceAccess(authService, workspaceManager, user, cloudRole) {
|
|
171
|
+
const folderRole = cloudRole === 'owner' || cloudRole === 'admin' ? 'admin' : 'editor';
|
|
172
|
+
for (const repo of workspaceManager.getAllRepoConfigs()) {
|
|
173
|
+
if (repo.personal)
|
|
174
|
+
continue;
|
|
175
|
+
const currentRole = authService.getFolderRole(user.id, repo.name);
|
|
176
|
+
if (currentRole === 'admin')
|
|
177
|
+
continue;
|
|
178
|
+
if (currentRole !== folderRole)
|
|
179
|
+
authService.grantFolderAccess(user.id, repo.name, folderRole);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function hmacBase64Url(value, secret) {
|
|
183
|
+
return createHmac('sha256', secret).update(value).digest('base64url');
|
|
184
|
+
}
|
|
185
|
+
function constantTimeEqual(a, b) {
|
|
186
|
+
const left = Buffer.from(a);
|
|
187
|
+
const right = Buffer.from(b);
|
|
188
|
+
return left.length === right.length && timingSafeEqual(left, right);
|
|
189
|
+
}
|
|
190
|
+
function parseBoolean(value) {
|
|
191
|
+
if (!value)
|
|
192
|
+
return false;
|
|
193
|
+
return ['1', 'true', 'yes', 'on'].includes(value.trim().toLowerCase());
|
|
62
194
|
}
|
|
63
195
|
export async function registerAuthApiRoutes(fastify, authService, workspacePath, workspaceManager, workspaceName) {
|
|
196
|
+
fastify.get('/api/cloud/auth/callback', async (req, reply) => {
|
|
197
|
+
const config = managedCloudAuthConfig();
|
|
198
|
+
if (!config.enabled)
|
|
199
|
+
return reply.status(404).send({ error: 'Managed cloud auth is not enabled' });
|
|
200
|
+
if (!config.token || !config.workspaceId) {
|
|
201
|
+
return reply.status(503).send({ error: 'Managed cloud auth is not configured' });
|
|
202
|
+
}
|
|
203
|
+
const { token } = req.query;
|
|
204
|
+
if (!token)
|
|
205
|
+
return reply.status(400).send({ error: 'Missing login token' });
|
|
206
|
+
try {
|
|
207
|
+
const claims = verifyCloudLoginToken(token, config.token);
|
|
208
|
+
if (claims.workspaceId !== config.workspaceId) {
|
|
209
|
+
return reply.status(403).send({ error: 'Login token was issued for a different workspace' });
|
|
210
|
+
}
|
|
211
|
+
if (config.orgId && claims.orgId !== config.orgId) {
|
|
212
|
+
return reply.status(403).send({ error: 'Login token was issued for a different organization' });
|
|
213
|
+
}
|
|
214
|
+
const existing = authService.findUserByEmail(claims.email);
|
|
215
|
+
const runtimeRole = runtimeRoleForCloudRole(claims.role, existing, authService);
|
|
216
|
+
const user = authService.upsertCloudManagedUser({
|
|
217
|
+
email: claims.email,
|
|
218
|
+
displayName: claims.displayName,
|
|
219
|
+
role: runtimeRole,
|
|
220
|
+
});
|
|
221
|
+
await ensurePersonalFolder(new Workspace(workspacePath), authService, user);
|
|
222
|
+
grantManagedWorkspaceAccess(authService, workspaceManager, user, claims.role);
|
|
223
|
+
workspaceManager.reloadConfig();
|
|
224
|
+
// No person auto-provisioning here: task assignment + "My Tasks" key on the
|
|
225
|
+
// account identity (`[[user:<id>]]`), so a person entity is optional and
|
|
226
|
+
// never a precondition. Users add a profile explicitly from Settings → Profile.
|
|
227
|
+
const secure = req.headers['x-forwarded-proto'] === 'https';
|
|
228
|
+
reply.setCookie('__sg_token', authService.createSessionToken(user), {
|
|
229
|
+
path: '/',
|
|
230
|
+
httpOnly: true,
|
|
231
|
+
sameSite: 'lax',
|
|
232
|
+
secure,
|
|
233
|
+
maxAge: 7 * 24 * 60 * 60,
|
|
234
|
+
});
|
|
235
|
+
// Honor a returnTo echoed back through the cloud round-trip (used by the
|
|
236
|
+
// OAuth authorize → /login bounce so consent resumes after cloud auth).
|
|
237
|
+
// safeReturnTo enforces same-origin: root-relative path only, rejecting
|
|
238
|
+
// absolute/protocol-relative URLs, backslash-normalized off-origin, and
|
|
239
|
+
// control chars.
|
|
240
|
+
const returnTo = safeReturnTo(req.query.returnTo);
|
|
241
|
+
return reply.redirect(returnTo);
|
|
242
|
+
}
|
|
243
|
+
catch (err) {
|
|
244
|
+
return reply.status(401).send({ error: err?.message || 'Invalid login token' });
|
|
245
|
+
}
|
|
246
|
+
});
|
|
64
247
|
// ── Admin user management ──
|
|
65
|
-
// GET /api/auth/users — list all users
|
|
248
|
+
// GET /api/auth/users — list all users. Any authenticated caller: folder
|
|
249
|
+
// admins need this to populate the share-dialog "Add members" candidates,
|
|
250
|
+
// and the comment @-mention surface needs the same shape.
|
|
251
|
+
// Mutating endpoints below (POST/DELETE/PATCH) stay owner-only.
|
|
66
252
|
fastify.get('/api/auth/users', async (req, reply) => {
|
|
67
|
-
const
|
|
68
|
-
if (!
|
|
69
|
-
return reply.status(
|
|
253
|
+
const user = requireUser(req, authService);
|
|
254
|
+
if (!user)
|
|
255
|
+
return reply.status(401).send({ error: 'Authentication required' });
|
|
70
256
|
return reply.send({ users: authService.listUsers() });
|
|
71
257
|
});
|
|
72
258
|
// POST /api/auth/users — create a new user (admin only)
|
|
73
259
|
fastify.post('/api/auth/users', async (req, reply) => {
|
|
74
|
-
const admin =
|
|
260
|
+
const admin = requireOwner(req, authService);
|
|
75
261
|
if (!admin)
|
|
76
|
-
return reply.status(403).send({ error: '
|
|
262
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
77
263
|
const { email, password, displayName, role } = req.body;
|
|
78
264
|
if (!email || !password) {
|
|
79
265
|
return reply.status(400).send({ error: 'Email and password are required' });
|
|
80
266
|
}
|
|
81
|
-
if (role
|
|
82
|
-
return reply.status(400).send({ error:
|
|
267
|
+
if (role && role !== 'owner' && role !== 'member') {
|
|
268
|
+
return reply.status(400).send({ error: `Invalid role "${role}" — must be "owner" or "member"` });
|
|
83
269
|
}
|
|
84
270
|
try {
|
|
85
271
|
const user = authService.createUser(email, password, displayName || email.split('@')[0], role || 'member');
|
|
86
|
-
await
|
|
272
|
+
await ensurePersonalFolder(new Workspace(workspacePath), authService, user);
|
|
273
|
+
workspaceManager.reloadConfig();
|
|
274
|
+
// No person auto-provisioning: assignment + "My Tasks" key on the account
|
|
275
|
+
// identity (`[[user:<id>]]`), so a person entity is optional. Users add a
|
|
276
|
+
// profile to the graph explicitly from Settings → Profile.
|
|
87
277
|
return reply.send({ user });
|
|
88
278
|
}
|
|
89
279
|
catch (err) {
|
|
@@ -92,9 +282,9 @@ export async function registerAuthApiRoutes(fastify, authService, workspacePath,
|
|
|
92
282
|
});
|
|
93
283
|
// DELETE /api/auth/users/:id — delete a user (admin only, cannot delete self or last admin)
|
|
94
284
|
fastify.delete('/api/auth/users/:id', async (req, reply) => {
|
|
95
|
-
const admin =
|
|
285
|
+
const admin = requireOwner(req, authService);
|
|
96
286
|
if (!admin)
|
|
97
|
-
return reply.status(403).send({ error: '
|
|
287
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
98
288
|
const userId = parseInt(req.params.id, 10);
|
|
99
289
|
if (isNaN(userId))
|
|
100
290
|
return reply.status(400).send({ error: 'Invalid user ID' });
|
|
@@ -104,20 +294,111 @@ export async function registerAuthApiRoutes(fastify, authService, workspacePath,
|
|
|
104
294
|
const target = users.find(u => u.id === userId);
|
|
105
295
|
if (!target)
|
|
106
296
|
return reply.status(404).send({ error: 'User not found' });
|
|
107
|
-
if (target.role === 'owner') {
|
|
108
|
-
return reply.status(400).send({ error: 'Cannot delete workspace owner. Transfer ownership first.' });
|
|
297
|
+
if (target.role === 'owner' && users.filter(u => u.role === 'owner').length <= 1) {
|
|
298
|
+
return reply.status(400).send({ error: 'Cannot delete the last workspace owner. Transfer ownership first.' });
|
|
299
|
+
}
|
|
300
|
+
// Transfer folders the target solely administers to the actor
|
|
301
|
+
// (the workspace owner performing this deletion) BEFORE the cascade
|
|
302
|
+
// delete — otherwise folder_access rows for those folders disappear
|
|
303
|
+
// and the folder is left with no admins.
|
|
304
|
+
//
|
|
305
|
+
// Personal folders (the target's "My Folder") are a sub-case: they
|
|
306
|
+
// transfer the same way, then get demoted to normal archive folders
|
|
307
|
+
// so the one-personal-folder-per-user invariant holds and the actor
|
|
308
|
+
// ends up with a plainly-named folder they own outright.
|
|
309
|
+
const workspace = new Workspace(workspacePath);
|
|
310
|
+
const preConfig = await workspace.loadConfig();
|
|
311
|
+
const targetPersonalFolders = preConfig.repos.filter(r => r.personal === true && r.owner_id === target.id);
|
|
312
|
+
const personalEntryCounts = new Map();
|
|
313
|
+
for (const p of targetPersonalFolders) {
|
|
314
|
+
try {
|
|
315
|
+
personalEntryCounts.set(p.name, workspaceManager.getGraph(p.name).listEntityIds().length);
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
personalEntryCounts.set(p.name, 0);
|
|
319
|
+
}
|
|
109
320
|
}
|
|
110
|
-
|
|
111
|
-
|
|
321
|
+
const transferred = authService.transferFoldersOnDelete(target.id, admin.id);
|
|
322
|
+
// Capture the old name upfront: archivePersonalFolder mutates the
|
|
323
|
+
// RepoConfig in place (name/path change), so reading `p.name` after
|
|
324
|
+
// the await would return the new archive name.
|
|
325
|
+
const archived = [];
|
|
326
|
+
for (const p of targetPersonalFolders) {
|
|
327
|
+
const oldName = p.name;
|
|
328
|
+
if (!transferred.includes(oldName))
|
|
329
|
+
continue;
|
|
330
|
+
const { newName, newDisplayName } = await archivePersonalFolder(workspace, oldName, target.displayName, authService);
|
|
331
|
+
archived.push({
|
|
332
|
+
oldName,
|
|
333
|
+
newName,
|
|
334
|
+
newDisplayName,
|
|
335
|
+
entryCount: personalEntryCounts.get(oldName) ?? 0,
|
|
336
|
+
});
|
|
112
337
|
}
|
|
113
338
|
authService.deleteUser(target.email);
|
|
114
|
-
|
|
339
|
+
if (archived.length > 0)
|
|
340
|
+
workspaceManager.reloadConfig();
|
|
341
|
+
return reply.send({ ok: true, transferred, archived });
|
|
342
|
+
});
|
|
343
|
+
// GET /api/auth/users/:id/deletion-preview — show the actor what
|
|
344
|
+
// will transfer if they delete this user. Owner-gated. Returns entry
|
|
345
|
+
// counts and archive names so the confirmation UI can set expectations
|
|
346
|
+
// WITHOUT exposing the contents of the target's private folder. The
|
|
347
|
+
// preview is advisory; the DELETE endpoint is the source of truth.
|
|
348
|
+
fastify.get('/api/auth/users/:id/deletion-preview', async (req, reply) => {
|
|
349
|
+
const admin = requireOwner(req, authService);
|
|
350
|
+
if (!admin)
|
|
351
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
352
|
+
const userId = parseInt(req.params.id, 10);
|
|
353
|
+
if (isNaN(userId))
|
|
354
|
+
return reply.status(400).send({ error: 'Invalid user ID' });
|
|
355
|
+
if (admin.id === userId)
|
|
356
|
+
return reply.status(400).send({ error: 'Cannot preview deleting yourself' });
|
|
357
|
+
const target = authService.listUsers().find(u => u.id === userId);
|
|
358
|
+
if (!target)
|
|
359
|
+
return reply.status(404).send({ error: 'User not found' });
|
|
360
|
+
const workspace = new Workspace(workspacePath);
|
|
361
|
+
const config = await workspace.loadConfig();
|
|
362
|
+
// Mirror transferFoldersOnDelete's sole-admin rule so the preview
|
|
363
|
+
// matches the real delete. Personal folders are 1-member by nature,
|
|
364
|
+
// so they always qualify.
|
|
365
|
+
const targetAdminFolders = authService.getUserFolders(target.id)
|
|
366
|
+
.filter(f => authService.getFolderRole(target.id, f) === 'admin');
|
|
367
|
+
const soleAdminFolders = targetAdminFolders.filter(f => authService.getFolderAdmins(f).length === 1);
|
|
368
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
369
|
+
const personalFolders = config.repos.filter(r => r.personal === true && r.owner_id === target.id && soleAdminFolders.includes(r.name));
|
|
370
|
+
const sharedSoleAdmin = soleAdminFolders.filter(f => !personalFolders.some(p => p.name === f));
|
|
371
|
+
const personal = personalFolders.map(p => {
|
|
372
|
+
let entryCount = 0;
|
|
373
|
+
try {
|
|
374
|
+
entryCount = workspaceManager.getGraph(p.name).listEntityIds().length;
|
|
375
|
+
}
|
|
376
|
+
catch { /* skip */ }
|
|
377
|
+
return {
|
|
378
|
+
entryCount,
|
|
379
|
+
newDisplayName: `Archive: ${target.displayName} (${date})`,
|
|
380
|
+
};
|
|
381
|
+
});
|
|
382
|
+
const shared = sharedSoleAdmin.map(f => {
|
|
383
|
+
const repo = config.repos.find(r => r.name === f);
|
|
384
|
+
let entryCount = 0;
|
|
385
|
+
try {
|
|
386
|
+
entryCount = workspaceManager.getGraph(f).listEntityIds().length;
|
|
387
|
+
}
|
|
388
|
+
catch { /* skip */ }
|
|
389
|
+
return {
|
|
390
|
+
name: f,
|
|
391
|
+
displayName: repo?.display_name ?? f,
|
|
392
|
+
entryCount,
|
|
393
|
+
};
|
|
394
|
+
});
|
|
395
|
+
return reply.send({ personal, shared });
|
|
115
396
|
});
|
|
116
397
|
// PATCH /api/auth/users/:id/password — reset a user's password (admin only)
|
|
117
398
|
fastify.patch('/api/auth/users/:id/password', async (req, reply) => {
|
|
118
|
-
const admin =
|
|
399
|
+
const admin = requireOwner(req, authService);
|
|
119
400
|
if (!admin)
|
|
120
|
-
return reply.status(403).send({ error: '
|
|
401
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
121
402
|
const userId = parseInt(req.params.id, 10);
|
|
122
403
|
if (isNaN(userId))
|
|
123
404
|
return reply.status(400).send({ error: 'Invalid user ID' });
|
|
@@ -136,28 +417,99 @@ export async function registerAuthApiRoutes(fastify, authService, workspacePath,
|
|
|
136
417
|
return reply.status(400).send({ error: err.message });
|
|
137
418
|
}
|
|
138
419
|
});
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
|
|
420
|
+
// PATCH /api/auth/users/:id — update a member's profile (owner only).
|
|
421
|
+
// Currently accepts `email` and `displayName`; mirrors the existing
|
|
422
|
+
// password-reset pattern (owner-gated, no user notification).
|
|
423
|
+
fastify.patch('/api/auth/users/:id', async (req, reply) => {
|
|
424
|
+
const admin = requireOwner(req, authService);
|
|
142
425
|
if (!admin)
|
|
143
|
-
return reply.status(403).send({ error: '
|
|
144
|
-
const
|
|
145
|
-
|
|
426
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
427
|
+
const userId = parseInt(req.params.id, 10);
|
|
428
|
+
if (isNaN(userId))
|
|
429
|
+
return reply.status(400).send({ error: 'Invalid user ID' });
|
|
430
|
+
const { email, displayName } = req.body;
|
|
431
|
+
if (email === undefined && displayName === undefined) {
|
|
432
|
+
return reply.status(400).send({ error: 'Nothing to update' });
|
|
433
|
+
}
|
|
434
|
+
if (email !== undefined) {
|
|
435
|
+
const normalized = email.toLowerCase().trim();
|
|
436
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(normalized)) {
|
|
437
|
+
return reply.status(400).send({ error: 'Invalid email address' });
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
const target = authService.findUserById(userId);
|
|
441
|
+
if (!target)
|
|
442
|
+
return reply.status(404).send({ error: 'User not found' });
|
|
443
|
+
try {
|
|
444
|
+
const updated = authService.updateProfile(userId, { email, displayName });
|
|
445
|
+
return reply.send({ user: updated });
|
|
446
|
+
}
|
|
447
|
+
catch (err) {
|
|
448
|
+
// SQLite raises a UNIQUE constraint error on duplicate email.
|
|
449
|
+
if (String(err?.message ?? '').includes('UNIQUE')) {
|
|
450
|
+
return reply.status(409).send({ error: 'That email is already in use' });
|
|
451
|
+
}
|
|
452
|
+
return reply.status(400).send({ error: err.message });
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
// ── Per-user API tokens (used by MCP clients, CLI, and git HTTP) ──
|
|
456
|
+
// POST /api/auth/tokens — mint a new token for the authenticated user.
|
|
457
|
+
// Body: { name: string }. Returns the raw token once; only its hash is stored.
|
|
458
|
+
fastify.post('/api/auth/tokens', async (req, reply) => {
|
|
459
|
+
const user = requireUser(req, authService);
|
|
460
|
+
if (!user)
|
|
461
|
+
return reply.status(401).send({ error: 'Unauthorized' });
|
|
462
|
+
const { name } = (req.body ?? {});
|
|
463
|
+
if (!name || !name.trim()) {
|
|
464
|
+
return reply.status(400).send({ error: 'name is required' });
|
|
465
|
+
}
|
|
466
|
+
try {
|
|
467
|
+
const minted = authService.createApiToken(user.id, name);
|
|
468
|
+
return reply.status(201).send(minted);
|
|
469
|
+
}
|
|
470
|
+
catch (err) {
|
|
471
|
+
return reply.status(400).send({ error: err.message });
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
// GET /api/auth/tokens — list the authenticated user's tokens (metadata only).
|
|
475
|
+
fastify.get('/api/auth/tokens', async (req, reply) => {
|
|
476
|
+
const user = requireUser(req, authService);
|
|
477
|
+
if (!user)
|
|
478
|
+
return reply.status(401).send({ error: 'Unauthorized' });
|
|
479
|
+
return reply.send({ tokens: authService.listApiTokens(user.id) });
|
|
480
|
+
});
|
|
481
|
+
// DELETE /api/auth/tokens/:id — revoke one of the user's own tokens.
|
|
482
|
+
fastify.delete('/api/auth/tokens/:id', async (req, reply) => {
|
|
483
|
+
const user = requireUser(req, authService);
|
|
484
|
+
if (!user)
|
|
485
|
+
return reply.status(401).send({ error: 'Unauthorized' });
|
|
486
|
+
const tokenId = parseInt(req.params.id, 10);
|
|
487
|
+
if (isNaN(tokenId))
|
|
488
|
+
return reply.status(400).send({ error: 'Invalid token id' });
|
|
489
|
+
const ok = authService.revokeApiToken(tokenId, user.id);
|
|
490
|
+
if (!ok)
|
|
491
|
+
return reply.status(404).send({ error: 'Token not found' });
|
|
492
|
+
return reply.send({ ok: true });
|
|
146
493
|
});
|
|
147
494
|
// GET /api/auth/seed — export auth seed data (admin only, for remote pull)
|
|
495
|
+
// Phase 3: sanitized via the same registry-driven helper as
|
|
496
|
+
// /api/config/bundle. jwtSecret + deprecated apiKey are dropped before
|
|
497
|
+
// the response leaves the trust boundary.
|
|
148
498
|
fastify.get('/api/auth/seed', async (req, reply) => {
|
|
149
|
-
const admin =
|
|
499
|
+
const admin = requireOwner(req, authService);
|
|
150
500
|
if (!admin)
|
|
151
|
-
return reply.status(403).send({ error: '
|
|
152
|
-
|
|
501
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
502
|
+
const { sanitizeAuthSeed } = await import('../../core/secrets/bundle.js');
|
|
503
|
+
return reply.send(sanitizeAuthSeed(authService.getSeedData()));
|
|
153
504
|
});
|
|
154
|
-
// POST /api/auth/transfer-ownership — transfer ownership to another user (owner only)
|
|
505
|
+
// POST /api/auth/transfer-ownership — transfer ownership to another user (owner only).
|
|
506
|
+
// Accepts cookie OR Bearer sg_ token via requireUser (the CLI calls this
|
|
507
|
+
// through `studiograph admin transfer-ownership`).
|
|
155
508
|
fastify.post('/api/auth/transfer-ownership', async (req, reply) => {
|
|
156
|
-
const
|
|
157
|
-
if (!
|
|
509
|
+
const user = requireUser(req, authService);
|
|
510
|
+
if (!user)
|
|
158
511
|
return reply.status(401).send({ error: 'Unauthorized' });
|
|
159
|
-
|
|
160
|
-
if (!user || user.role !== 'owner')
|
|
512
|
+
if (user.role !== 'owner')
|
|
161
513
|
return reply.status(403).send({ error: 'Only the workspace owner can transfer ownership' });
|
|
162
514
|
const { targetUserId } = req.body;
|
|
163
515
|
if (!targetUserId)
|
|
@@ -172,6 +524,9 @@ export async function registerAuthApiRoutes(fastify, authService, workspacePath,
|
|
|
172
524
|
});
|
|
173
525
|
// POST /api/auth/login — authenticate and set session cookie
|
|
174
526
|
fastify.post('/api/auth/login', async (req, reply) => {
|
|
527
|
+
if (managedCloudAuthConfig().enabled) {
|
|
528
|
+
return reply.status(403).send({ error: 'Use Studiograph Cloud to sign in to this managed workspace' });
|
|
529
|
+
}
|
|
175
530
|
const { email, password } = req.body;
|
|
176
531
|
if (!email || !password) {
|
|
177
532
|
return reply.status(400).send({ error: 'Email and password are required' });
|
|
@@ -192,13 +547,17 @@ export async function registerAuthApiRoutes(fastify, authService, workspacePath,
|
|
|
192
547
|
reply.setCookie('__sg_token', result.token, {
|
|
193
548
|
path: '/',
|
|
194
549
|
httpOnly: true,
|
|
195
|
-
|
|
550
|
+
// Lax (not Strict): sent on top-level GET navigations initiated cross-site
|
|
551
|
+
// — e.g. the OAuth /oauth/authorize redirect from Claude's connector — so an
|
|
552
|
+
// already-logged-in user isn't bounced to a redundant login. Still withheld
|
|
553
|
+
// on cross-site POSTs/subresources (the CSRF-dangerous cases).
|
|
554
|
+
sameSite: 'lax',
|
|
196
555
|
secure,
|
|
197
556
|
maxAge: 7 * 24 * 60 * 60, // 7 days
|
|
198
557
|
});
|
|
199
558
|
// Include the token in the response body when requested via
|
|
200
|
-
// X-Return-Token header
|
|
201
|
-
//
|
|
559
|
+
// X-Return-Token header for API clients that can't use cookies
|
|
560
|
+
// across origins.
|
|
202
561
|
const returnToken = req.headers['x-return-token'] === '1';
|
|
203
562
|
return reply.send({
|
|
204
563
|
user: result.user,
|
|
@@ -206,26 +565,107 @@ export async function registerAuthApiRoutes(fastify, authService, workspacePath,
|
|
|
206
565
|
});
|
|
207
566
|
});
|
|
208
567
|
// POST /api/auth/logout — clear session cookie
|
|
209
|
-
fastify.post('/api/auth/logout', async (
|
|
568
|
+
fastify.post('/api/auth/logout', async (req, reply) => {
|
|
569
|
+
const cloudAuth = managedCloudAuthConfig();
|
|
210
570
|
reply.setCookie('__sg_token', '', {
|
|
211
571
|
path: '/',
|
|
212
572
|
httpOnly: true,
|
|
213
|
-
sameSite: '
|
|
573
|
+
sameSite: 'lax',
|
|
214
574
|
maxAge: 0,
|
|
215
575
|
});
|
|
216
|
-
return reply.send({
|
|
576
|
+
return reply.send({
|
|
577
|
+
ok: true,
|
|
578
|
+
logoutUrl: cloudAuth.enabled
|
|
579
|
+
? managedCloudLogoutUrl(cloudAuth, managedLogoutReturnTo(req))
|
|
580
|
+
: undefined,
|
|
581
|
+
});
|
|
217
582
|
});
|
|
218
|
-
// GET /api/auth/me — verify current session
|
|
583
|
+
// GET /api/auth/me — verify current session. Also resolves the user's
|
|
584
|
+
// linked person entity (the auth↔person bridge) so the client gets both
|
|
585
|
+
// identifiers in one round-trip. `personRef` is null when the user has
|
|
586
|
+
// no linked entity (legacy, unprovisioned, or explicitly unlinked) OR
|
|
587
|
+
// when the linked entity lives in a repo the user no longer has read
|
|
588
|
+
// access to (would leak repo existence otherwise — see access-control).
|
|
219
589
|
fastify.get('/api/auth/me', async (req, reply) => {
|
|
220
|
-
|
|
221
|
-
|
|
590
|
+
// Resolve from the cookie JWT OR Authorization: Bearer (JWT / sg_ API
|
|
591
|
+
// token) via the shared requireUser helper. The global auth hook skips
|
|
592
|
+
// /api/auth/*, so without this the boot session check only honored the
|
|
593
|
+
// web cookie and rejected API-token callers (CLI, automation, the
|
|
594
|
+
// headless browser) even though they authenticate everywhere else.
|
|
595
|
+
const user = requireUser(req, authService);
|
|
596
|
+
if (!user) {
|
|
222
597
|
return reply.status(401).send({ error: 'Not authenticated' });
|
|
223
598
|
}
|
|
224
|
-
const
|
|
225
|
-
|
|
599
|
+
const rawRef = findPersonRefForUser(workspaceManager, user.handle);
|
|
600
|
+
const personRef = rawRef && access.hasRepoAccess(user, rawRef.repo, workspaceManager, authService)
|
|
601
|
+
? rawRef
|
|
602
|
+
: null;
|
|
603
|
+
return reply.send({ user, personRef });
|
|
604
|
+
});
|
|
605
|
+
// POST /api/auth/me/person-link — self-service link of the user↔person
|
|
606
|
+
// bridge for the CURRENT user. Two modes:
|
|
607
|
+
// - body `{ entityId }` → link that SPECIFIC person the user picked
|
|
608
|
+
// (the home CTA / Profile "which record is you?" picker).
|
|
609
|
+
// - no body → auto: email-match an existing record, else create one
|
|
610
|
+
// (ensurePersonForUser).
|
|
611
|
+
//
|
|
612
|
+
// Self-scoped — the user can only stamp THEIR OWN handle onto an UNLINKED
|
|
613
|
+
// person they can read — so it safely bypasses the owner-only gate that
|
|
614
|
+
// guards generic user_handle writes (that gate exists to stop a member
|
|
615
|
+
// claiming ANOTHER user's identity; linking yourself isn't that, and it
|
|
616
|
+
// confers no privileges — auth role comes from the account, not the entity).
|
|
617
|
+
fastify.post('/api/auth/me/person-link', async (req, reply) => {
|
|
618
|
+
const user = requireUser(req, authService);
|
|
619
|
+
if (!user)
|
|
226
620
|
return reply.status(401).send({ error: 'Not authenticated' });
|
|
621
|
+
const chosenId = typeof req.body?.entityId === 'string' ? req.body.entityId.trim() : '';
|
|
622
|
+
// Idempotent / conflict: already linked?
|
|
623
|
+
const existing = findPersonRefForUser(workspaceManager, user.handle);
|
|
624
|
+
if (existing) {
|
|
625
|
+
// Same record (or no specific request) → no-op success. A DIFFERENT
|
|
626
|
+
// record → you're already linked; refuse rather than create a 2nd link.
|
|
627
|
+
if (!chosenId || existing.entityId === chosenId) {
|
|
628
|
+
return reply.send({ action: 'already-linked', personRef: existing });
|
|
629
|
+
}
|
|
630
|
+
return reply.status(409).send({
|
|
631
|
+
error: `Your account is already linked to ${existing.repo}/${existing.entityId}. Unlink it first to link a different record.`,
|
|
632
|
+
code: 'ALREADY_LINKED_ELSEWHERE',
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
// Mode 1 — link a specific, user-picked person.
|
|
636
|
+
if (chosenId) {
|
|
637
|
+
const target = workspaceManager.findEntityByTypeAndId('person', chosenId);
|
|
638
|
+
// Collapse "not found" and "can't read it" into one 404 so we don't leak
|
|
639
|
+
// the existence of records in folders the caller can't access.
|
|
640
|
+
if (!target || !access.hasRepoAccess(user, target.repoName, workspaceManager, authService)) {
|
|
641
|
+
return reply.status(404).send({ error: `No person entry "${chosenId}" you can link.`, code: 'PERSON_NOT_FOUND' });
|
|
642
|
+
}
|
|
643
|
+
try {
|
|
644
|
+
// Self-scoped link (own handle, unlinked target) — guards live in the
|
|
645
|
+
// bridge helper; it throws BridgeError on conflict.
|
|
646
|
+
await linkChosenPersonToUser(workspaceManager, user, { repo: target.repoName, entityId: chosenId }, authUserToGitUser(user));
|
|
647
|
+
return reply.send({ action: 'linked', personRef: { repo: target.repoName, entityId: chosenId } });
|
|
648
|
+
}
|
|
649
|
+
catch (err) {
|
|
650
|
+
if (err instanceof BridgeError)
|
|
651
|
+
return reply.status(409).send({ error: err.message, code: err.code, ...err.details });
|
|
652
|
+
return reply.status(500).send({ error: err?.message ?? 'Failed to link person record' });
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
// Mode 2 — auto (email-match an existing record, else create one).
|
|
656
|
+
try {
|
|
657
|
+
const r = await ensurePersonForUser(workspaceManager, authService, user, authUserToGitUser(user));
|
|
658
|
+
if (r.action === 'skipped') {
|
|
659
|
+
return reply.status(409).send({
|
|
660
|
+
error: `Could not create a person record (${r.reason}). Ask a workspace owner to designate a shared folder.`,
|
|
661
|
+
code: 'BRIDGE_SKIPPED',
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
return reply.send({ action: r.action, personRef: r.ref });
|
|
665
|
+
}
|
|
666
|
+
catch (err) {
|
|
667
|
+
return reply.status(500).send({ error: err?.message ?? 'Failed to link person record' });
|
|
227
668
|
}
|
|
228
|
-
return reply.send({ user });
|
|
229
669
|
});
|
|
230
670
|
// PATCH /api/auth/me — update current user's profile
|
|
231
671
|
fastify.patch('/api/auth/me', async (req, reply) => {
|
|
@@ -250,15 +690,23 @@ export async function registerAuthApiRoutes(fastify, authService, workspacePath,
|
|
|
250
690
|
return reply.send({ colors: authService.getAllAccentColors() });
|
|
251
691
|
});
|
|
252
692
|
// GET /api/auth/status — public endpoint for login page
|
|
253
|
-
fastify.get('/api/auth/status', async (
|
|
693
|
+
fastify.get('/api/auth/status', async (req, reply) => {
|
|
694
|
+
const cloudAuth = managedCloudAuthConfig();
|
|
254
695
|
return reply.send({
|
|
255
696
|
authEnabled: authService.hasUsers(),
|
|
256
697
|
userCount: authService.getUserCount(),
|
|
257
698
|
workspaceName: workspaceName || undefined,
|
|
699
|
+
managedAuth: cloudAuth.enabled,
|
|
700
|
+
cloudUrl: cloudAuth.cloudUrl || undefined,
|
|
701
|
+
managedAuthLoginUrl: managedCloudLoginUrl(cloudAuth) || undefined,
|
|
702
|
+
managedAuthLogoutUrl: managedCloudLogoutUrl(cloudAuth, managedLogoutReturnTo(req)) || undefined,
|
|
258
703
|
});
|
|
259
704
|
});
|
|
260
705
|
// POST /api/auth/setup — create the first admin account (only works when no users exist)
|
|
261
706
|
fastify.post('/api/auth/setup', async (req, reply) => {
|
|
707
|
+
if (managedCloudAuthConfig().enabled) {
|
|
708
|
+
return reply.status(403).send({ error: 'Managed workspaces are set up from Studiograph Cloud' });
|
|
709
|
+
}
|
|
262
710
|
if (authService.hasUsers()) {
|
|
263
711
|
return reply.status(403).send({ error: 'Setup already completed' });
|
|
264
712
|
}
|
|
@@ -268,7 +716,28 @@ export async function registerAuthApiRoutes(fastify, authService, workspacePath,
|
|
|
268
716
|
}
|
|
269
717
|
try {
|
|
270
718
|
const user = authService.createUser(email, password, displayName || email.split('@')[0], 'owner');
|
|
271
|
-
|
|
719
|
+
const setupWorkspace = new Workspace(workspacePath);
|
|
720
|
+
await ensurePersonalFolder(setupWorkspace, authService, user);
|
|
721
|
+
// Provision the reserved workspace-wide "Assets" store once, at first-run
|
|
722
|
+
// setup. Existing workspaces backfill lazily on first asset upload
|
|
723
|
+
// (resolveWorkspaceAssetsRepo) — never via a boot sweep.
|
|
724
|
+
await ensureWorkspaceAssetsFolder(setupWorkspace);
|
|
725
|
+
workspaceManager.reloadConfig();
|
|
726
|
+
// Grant the first owner folder-admin on every existing team folder.
|
|
727
|
+
// Without this, folders scaffolded by `studiograph init` before any
|
|
728
|
+
// user existed end up with zero folder_access rows, and
|
|
729
|
+
// `getAccessibleRepos()` filters them out of the sidebar — the first
|
|
730
|
+
// owner then sees an empty workspace despite the files being on disk.
|
|
731
|
+
// Personal folders are handled by ensurePersonalFolder above; skipping
|
|
732
|
+
// them here avoids granting the owner access to other users' personals.
|
|
733
|
+
for (const repo of workspaceManager.getAllRepoConfigs()) {
|
|
734
|
+
if (repo.personal)
|
|
735
|
+
continue;
|
|
736
|
+
authService.grantFolderAccess(user.id, repo.name, 'admin');
|
|
737
|
+
}
|
|
738
|
+
// No first-owner person auto-provisioning: assignment + "My Tasks" key on
|
|
739
|
+
// the account identity (`[[user:<id>]]`). The owner adds their profile to
|
|
740
|
+
// the graph explicitly from Settings → Profile if they want one.
|
|
272
741
|
const result = authService.authenticate(email, password);
|
|
273
742
|
if (!result) {
|
|
274
743
|
return reply.status(500).send({ error: 'Failed to authenticate after setup' });
|
|
@@ -277,7 +746,7 @@ export async function registerAuthApiRoutes(fastify, authService, workspacePath,
|
|
|
277
746
|
reply.setCookie('__sg_token', result.token, {
|
|
278
747
|
path: '/',
|
|
279
748
|
httpOnly: true,
|
|
280
|
-
sameSite: '
|
|
749
|
+
sameSite: 'lax',
|
|
281
750
|
secure,
|
|
282
751
|
maxAge: 7 * 24 * 60 * 60,
|
|
283
752
|
});
|