studiograph 1.3.47 → 1.3.48-beta.0
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 +117 -0
- package/dist/agent/agent-pool.js +287 -0
- package/dist/agent/agent-pool.js.map +1 -0
- 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 +113 -22
- package/dist/agent/orchestrator.js +573 -181
- package/dist/agent/orchestrator.js.map +1 -1
- package/dist/agent/prompts/entity-types-section.d.ts +36 -0
- package/dist/agent/prompts/entity-types-section.js +90 -0
- package/dist/agent/prompts/entity-types-section.js.map +1 -0
- package/dist/agent/prompts/system.md +148 -69
- 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/entity-schema.md +77 -433
- package/dist/agent/skills/interview/entity-templates.md +193 -0
- package/dist/agent/skills/interview/question-domains.md +391 -0
- package/dist/agent/skills/interview/skill.md +204 -0
- package/dist/agent/skills/schema-rules.md +54 -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 +7 -6
- package/dist/agent/tools/fs-tools.js +5 -4
- package/dist/agent/tools/fs-tools.js.map +1 -1
- package/dist/agent/tools/graph-tools.d.ts +21 -58
- package/dist/agent/tools/graph-tools.js +635 -332
- 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 -38
- 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.d.ts +18 -0
- package/dist/agent/tools/web-tools.js +283 -0
- package/dist/agent/tools/web-tools.js.map +1 -0
- 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/admin/folder.js +186 -0
- 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/commit.d.ts +1 -1
- package/dist/cli/commands/commit.js +24 -11
- package/dist/cli/commands/commit.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 +2 -2
- 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 +12 -4
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/orphans.js +14 -30
- package/dist/cli/commands/orphans.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 +142 -63
- package/dist/cli/commands/reset.js.map +1 -1
- package/dist/cli/commands/serve.js +209 -24
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/sync.d.ts +1 -1
- package/dist/cli/commands/sync.js +372 -202
- 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 -35
- 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 +33 -52
- package/dist/cli/setup-wizard.js +43 -68
- 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/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 +56 -0
- package/dist/core/embeds.js +103 -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 +53 -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 +140 -0
- package/dist/core/entity-types-catalog.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/graph.d.ts +675 -14
- package/dist/core/graph.js +2118 -314
- 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/schema-registry.d.ts +59 -0
- package/dist/core/schema-registry.js +198 -0
- 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/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 +598 -0
- package/dist/core/secrets/registry.js.map +1 -0
- package/dist/core/types.d.ts +77 -455
- package/dist/core/types.js +17 -3
- package/dist/core/types.js.map +1 -1
- package/dist/core/user-config.d.ts +75 -7
- package/dist/core/user-config.js +155 -7
- package/dist/core/user-config.js.map +1 -1
- package/dist/core/validation.d.ts +717 -1791
- package/dist/core/validation.js +357 -228
- package/dist/core/validation.js.map +1 -1
- package/dist/core/workspace-manager.d.ts +79 -12
- package/dist/core/workspace-manager.js +213 -73
- package/dist/core/workspace-manager.js.map +1 -1
- package/dist/core/workspace.d.ts +19 -5
- package/dist/core/workspace.js +69 -35
- 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 +94 -13
- package/dist/mcp/connector-manager.js +283 -62
- package/dist/mcp/connector-manager.js.map +1 -1
- package/dist/mcp/oauth-provider.d.ts +27 -33
- package/dist/mcp/oauth-provider.js +65 -134
- package/dist/mcp/oauth-provider.js.map +1 -1
- package/dist/mcp/oauth-registry.d.ts +62 -0
- package/dist/mcp/oauth-registry.js +85 -0
- package/dist/mcp/oauth-registry.js.map +1 -0
- package/dist/mcp/server.d.ts +11 -3
- package/dist/mcp/server.js +30 -5
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/state-signer.d.ts +41 -0
- package/dist/mcp/state-signer.js +120 -0
- package/dist/mcp/state-signer.js.map +1 -0
- package/dist/mcp/tools.d.ts +35 -2
- package/dist/mcp/tools.js +1051 -117
- package/dist/mcp/tools.js.map +1 -1
- package/dist/server/__tests__/helpers/graph-api.d.ts +18 -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/body-write-coordinator.d.ts +151 -0
- package/dist/server/body-write-coordinator.js +161 -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 +14 -3
- package/dist/server/index.js +451 -193
- package/dist/server/index.js.map +1 -1
- package/dist/server/middleware/sanitize.d.ts +46 -0
- package/dist/server/middleware/sanitize.js +171 -0
- package/dist/server/middleware/sanitize.js.map +1 -0
- package/dist/server/routes/asset-api.d.ts +10 -0
- package/dist/server/routes/asset-api.js +294 -0
- package/dist/server/routes/asset-api.js.map +1 -0
- 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.d.ts +3 -2
- package/dist/server/routes/auth-api.js +519 -38
- package/dist/server/routes/auth-api.js.map +1 -1
- package/dist/server/routes/capture-api.d.ts +18 -0
- package/dist/server/routes/capture-api.js +257 -0
- package/dist/server/routes/capture-api.js.map +1 -0
- package/dist/server/routes/chat.d.ts +4 -1
- package/dist/server/routes/chat.js +298 -88
- 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 +21 -0
- package/dist/server/routes/config-api.js +256 -0
- package/dist/server/routes/config-api.js.map +1 -0
- package/dist/server/routes/connectors-api.d.ts +17 -0
- package/dist/server/routes/connectors-api.js +410 -0
- package/dist/server/routes/connectors-api.js.map +1 -0
- package/dist/server/routes/event-ingest-api.d.ts +15 -0
- package/dist/server/routes/event-ingest-api.js +125 -0
- package/dist/server/routes/event-ingest-api.js.map +1 -0
- package/dist/server/routes/git-http.d.ts +3 -3
- package/dist/server/routes/git-http.js +86 -38
- package/dist/server/routes/git-http.js.map +1 -1
- package/dist/server/routes/graph-api-access.d.ts +35 -0
- package/dist/server/routes/graph-api-access.js +105 -0
- package/dist/server/routes/graph-api-access.js.map +1 -0
- package/dist/server/routes/graph-api.d.ts +3 -2
- package/dist/server/routes/graph-api.js +1321 -263
- 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/insights-api.d.ts +1 -2
- package/dist/server/routes/insights-api.js +149 -41
- 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 +22 -6
- package/dist/server/routes/mcp.js.map +1 -1
- package/dist/server/routes/permissions-api.d.ts +9 -2
- package/dist/server/routes/permissions-api.js +87 -30
- 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/url-api.d.ts +7 -0
- package/dist/server/routes/url-api.js +74 -0
- package/dist/server/routes/url-api.js.map +1 -0
- package/dist/server/routes/views-api.js +81 -7
- 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 +124 -35
- package/dist/server/routes/workspace-api.js.map +1 -1
- package/dist/server/routes/ws.d.ts +2 -1
- package/dist/server/routes/ws.js +64 -16
- 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 -15
- package/dist/server/session-manager.js.map +1 -1
- package/dist/server/ws-hub.d.ts +138 -14
- package/dist/server/ws-hub.js +0 -0
- package/dist/server/ws-hub.js.map +1 -1
- package/dist/server/yjs-manager.d.ts +285 -7
- package/dist/server/yjs-manager.js +907 -36
- 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 +146 -0
- package/dist/services/access-control.js.map +1 -0
- package/dist/services/asset-listing.d.ts +39 -0
- package/dist/services/asset-listing.js +125 -0
- package/dist/services/asset-listing.js.map +1 -0
- package/dist/services/asset-upload-service.d.ts +53 -0
- package/dist/services/asset-upload-service.js +201 -0
- package/dist/services/asset-upload-service.js.map +1 -0
- package/dist/services/assets/asset-index-service.d.ts +82 -0
- package/dist/services/assets/asset-index-service.js +167 -0
- package/dist/services/assets/asset-index-service.js.map +1 -0
- package/dist/services/assets/base.d.ts +44 -0
- package/dist/services/assets/base.js +55 -0
- package/dist/services/assets/base.js.map +1 -1
- package/dist/services/assets/index.d.ts +69 -1
- package/dist/services/assets/index.js +125 -0
- package/dist/services/assets/index.js.map +1 -1
- package/dist/services/assets/local.d.ts +12 -1
- package/dist/services/assets/local.js +100 -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 +34 -1
- package/dist/services/assets/r2.js +93 -1
- package/dist/services/assets/r2.js.map +1 -1
- package/dist/services/auth-service.d.ts +314 -36
- package/dist/services/auth-service.js +1126 -139
- package/dist/services/auth-service.js.map +1 -1
- package/dist/services/bookmark-import-service.d.ts +49 -0
- package/dist/services/bookmark-import-service.js +250 -0
- package/dist/services/bookmark-import-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/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 +161 -0
- package/dist/services/entity-mutations.js +296 -0
- package/dist/services/entity-mutations.js.map +1 -0
- package/dist/services/event-processor.d.ts +104 -0
- package/dist/services/event-processor.js +441 -0
- package/dist/services/event-processor.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 +54 -0
- package/dist/services/git.js +188 -54
- package/dist/services/git.js.map +1 -1
- package/dist/services/graph-maintenance.d.ts +42 -0
- package/dist/services/graph-maintenance.js +143 -0
- package/dist/services/graph-maintenance.js.map +1 -0
- package/dist/services/import-service.d.ts +45 -2
- package/dist/services/import-service.js +304 -100
- package/dist/services/import-service.js.map +1 -1
- package/dist/services/lint-service.js +9 -16
- package/dist/services/lint-service.js.map +1 -1
- package/dist/services/markdown.d.ts +12 -1
- package/dist/services/markdown.js +71 -6
- package/dist/services/markdown.js.map +1 -1
- package/dist/services/memory-service.d.ts +22 -14
- package/dist/services/memory-service.js +53 -35
- package/dist/services/memory-service.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/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/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/user-person-bridge.d.ts +118 -0
- package/dist/services/user-person-bridge.js +306 -0
- package/dist/services/user-person-bridge.js.map +1 -0
- package/dist/services/vector-service.d.ts +146 -6
- package/dist/services/vector-service.js +276 -13
- package/dist/services/vector-service.js.map +1 -1
- package/dist/services/workspace-access.d.ts +106 -0
- package/dist/services/workspace-access.js +149 -0
- package/dist/services/workspace-access.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.DDqq11xY.css +2 -0
- package/dist/web/_app/immutable/assets/12.DlIf1mKh.css +1 -0
- package/dist/web/_app/immutable/assets/13.7d-Q37wc.css +1 -0
- package/dist/web/_app/immutable/assets/14.CmLrbzZp.css +1 -0
- package/dist/web/_app/immutable/assets/2.CGK2ky-K.css +1 -0
- package/dist/web/_app/immutable/assets/3.CV0abekd.css +1 -0
- package/dist/web/_app/immutable/assets/4.fGsEpo95.css +1 -0
- package/dist/web/_app/immutable/assets/AgentOverlay.DqzjAOm4.css +1 -0
- package/dist/web/_app/immutable/assets/AssetManagerModal.BKJfPAPk.css +1 -0
- package/dist/web/_app/immutable/assets/CalendarView.bNewSxkH.css +1 -0
- package/dist/web/_app/immutable/assets/FolderMembersPanel.DX1oBeF_.css +1 -0
- package/dist/web/_app/immutable/assets/FolderMutationDialogs.BMRF6Z3z.css +1 -0
- package/dist/web/_app/immutable/assets/FolderPicker.B5KdvRYl.css +1 -0
- package/dist/web/_app/immutable/assets/GalleryView.DgvSjS0I.css +1 -0
- package/dist/web/_app/immutable/assets/GraphView.BJtGL9py.css +1 -0
- package/dist/web/_app/immutable/assets/KanbanView.D0QbZFd6.css +1 -0
- package/dist/web/_app/immutable/assets/Markdown.B4lW7Llh.css +1 -0
- package/dist/web/_app/immutable/assets/SettingsDialog.DYWYMFSO.css +1 -0
- package/dist/web/_app/immutable/assets/Spinner.UBfl0pab.css +1 -0
- package/dist/web/_app/immutable/assets/StopFilledAlt.clodJdp5.css +1 -0
- package/dist/web/_app/immutable/assets/TimelineView.DA-H6dvv.css +1 -0
- package/dist/web/_app/immutable/assets/WorkspaceView.BS1ildu7.css +1 -0
- package/dist/web/_app/immutable/assets/button.BlLm4Dg1.css +1 -0
- package/dist/web/_app/immutable/assets/formatting.B912lpdG.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.DCMVmy_Q.css +1 -0
- package/dist/web/_app/immutable/assets/realtime.DDCWxn3B.css +1 -0
- package/dist/web/_app/immutable/assets/sheet.DJPuqnTg.css +1 -0
- package/dist/web/_app/immutable/assets/speech-dictation.C5CYFhS1.css +1 -0
- package/dist/web/_app/immutable/chunks/0iDDDyaZ.js +1 -0
- package/dist/web/_app/immutable/chunks/2LgrBrpS2.js +2 -0
- package/dist/web/_app/immutable/chunks/3EfPAYzi2.js +1 -0
- package/dist/web/_app/immutable/chunks/7Bu427my2.js +184 -0
- package/dist/web/_app/immutable/chunks/96h3ktuk.js +1 -0
- package/dist/web/_app/immutable/chunks/A6FJA1AF.js +1 -0
- package/dist/web/_app/immutable/chunks/B-FAwCqe2.js +1 -0
- package/dist/web/_app/immutable/chunks/B-V5eMSw2.js +1 -0
- package/dist/web/_app/immutable/chunks/B-i9_YVM.js +1 -0
- package/dist/web/_app/immutable/chunks/B15-kvCe2.js +1 -0
- package/dist/web/_app/immutable/chunks/B1KZ7zY32.js +2 -0
- package/dist/web/_app/immutable/chunks/B4gpzeQ2.js +1 -0
- package/dist/web/_app/immutable/chunks/B6Lt-qaJ2.js +1 -0
- package/dist/web/_app/immutable/chunks/B7tbGyiU2.js +1 -0
- package/dist/web/_app/immutable/chunks/BBxt8lpa.js +1 -0
- package/dist/web/_app/immutable/chunks/BCaRi2AF.js +1 -0
- package/dist/web/_app/immutable/chunks/BJ6Z7eAM.js +2 -0
- package/dist/web/_app/immutable/chunks/BM_vIwVC.js +83 -0
- package/dist/web/_app/immutable/chunks/BQULA6er.js +4 -0
- package/dist/web/_app/immutable/chunks/BQW-EDgP2.js +224 -0
- package/dist/web/_app/immutable/chunks/BR6jMpLB.js +1 -0
- package/dist/web/_app/immutable/chunks/BVnuLlVg.js +1 -0
- package/dist/web/_app/immutable/chunks/BddNmQ8j.js +1 -0
- package/dist/web/_app/immutable/chunks/BeuunHPO.js +1 -0
- package/dist/web/_app/immutable/chunks/BhTmSo4n2.js +1 -0
- package/dist/web/_app/immutable/chunks/BikW7mty2.js +1 -0
- package/dist/web/_app/immutable/chunks/BkyFvJvz.js +1 -0
- package/dist/web/_app/immutable/chunks/BlyFGPFV.js +22 -0
- package/dist/web/_app/immutable/chunks/Bo5dghSu.js +3 -0
- package/dist/web/_app/immutable/chunks/BpPyho8Y.js +3 -0
- package/dist/web/_app/immutable/chunks/BsuvyNDN2.js +2 -0
- package/dist/web/_app/immutable/chunks/BuKi0vpu2.js +7 -0
- package/dist/web/_app/immutable/chunks/BuuYnIjE.js +1 -0
- package/dist/web/_app/immutable/chunks/By4lVKNC.js +2 -0
- package/dist/web/_app/immutable/chunks/ByQGCIwO.js +5 -0
- package/dist/web/_app/immutable/chunks/ByidpUhu.js +1 -0
- package/dist/web/_app/immutable/chunks/C35TIzaB.js +1 -0
- package/dist/web/_app/immutable/chunks/C5dM5op-.js +1 -0
- package/dist/web/_app/immutable/chunks/C6Nx0jpM.js +1 -0
- package/dist/web/_app/immutable/chunks/C6pVyOEl2.js +1 -0
- package/dist/web/_app/immutable/chunks/C80GKPZ9.js +1 -0
- package/dist/web/_app/immutable/chunks/C94TJqPI.js +1 -0
- package/dist/web/_app/immutable/chunks/C9PETsiT.js +1 -0
- package/dist/web/_app/immutable/chunks/CAuAQ81a2.js +1 -0
- package/dist/web/_app/immutable/chunks/CBnzSITi2.js +1 -0
- package/dist/web/_app/immutable/chunks/CC9p2p6w.js +1 -0
- package/dist/web/_app/immutable/chunks/CCLR-AJL2.js +185 -0
- package/dist/web/_app/immutable/chunks/CD0X7XPW.js +6 -0
- package/dist/web/_app/immutable/chunks/CDTjuBSm.js +1 -0
- package/dist/web/_app/immutable/chunks/CH-KYFIm.js +64 -0
- package/dist/web/_app/immutable/chunks/CHj8fObQ2.js +9 -0
- package/dist/web/_app/immutable/chunks/CK-UnH-n2.js +1 -0
- package/dist/web/_app/immutable/chunks/CKH5BEAh.js +1 -0
- package/dist/web/_app/immutable/chunks/CPSupDJp2.js +2 -0
- package/dist/web/_app/immutable/chunks/CSUrYOis.js +1 -0
- package/dist/web/_app/immutable/chunks/CYTTTma0.js +3 -0
- package/dist/web/_app/immutable/chunks/Cbaut_us2.js +1 -0
- package/dist/web/_app/immutable/chunks/CiIpSx5n2.js +1 -0
- package/dist/web/_app/immutable/chunks/CkLfUXwy.js +1 -0
- package/dist/web/_app/immutable/chunks/CokE4L8B2.js +1 -0
- package/dist/web/_app/immutable/chunks/CpLdnbh3.js +1 -0
- package/dist/web/_app/immutable/chunks/CvDrXJk9.js +1 -0
- package/dist/web/_app/immutable/chunks/D00MFB9_2.js +1 -0
- package/dist/web/_app/immutable/chunks/D41CbXmM.js +1 -0
- package/dist/web/_app/immutable/chunks/D5Hj-MPO2.js +1 -0
- package/dist/web/_app/immutable/chunks/D6nLEmZy2.js +1 -0
- package/dist/web/_app/immutable/chunks/D71ZlQBM2.js +2 -0
- package/dist/web/_app/immutable/chunks/D9ql9vXU.js +1 -0
- package/dist/web/_app/immutable/chunks/DAXW5iLp.js +1 -0
- package/dist/web/_app/immutable/chunks/DBzQ8LyQ2.js +2 -0
- package/dist/web/_app/immutable/chunks/DIb5rAPU2.js +1 -0
- package/dist/web/_app/immutable/chunks/DOmH4G9o.js +14 -0
- package/dist/web/_app/immutable/chunks/DQMWa2t72.js +1 -0
- package/dist/web/_app/immutable/chunks/DRsswX8S.js +1 -0
- package/dist/web/_app/immutable/chunks/DTCHhxD5.js +1 -0
- package/dist/web/_app/immutable/chunks/DUwgGBxa.js +1 -0
- package/dist/web/_app/immutable/chunks/DVcy5Pp82.js +1 -0
- package/dist/web/_app/immutable/chunks/DWygwzcO.js +1 -0
- package/dist/web/_app/immutable/chunks/DYXDRmoo.js +1 -0
- package/dist/web/_app/immutable/chunks/DZ-YyRVM.js +1 -0
- package/dist/web/_app/immutable/chunks/D_HVOuHV.js +1 -0
- package/dist/web/_app/immutable/chunks/DaoOQFPb.js +1 -0
- package/dist/web/_app/immutable/chunks/DdLkNvPf.js +23 -0
- package/dist/web/_app/immutable/chunks/DiMQob8p.js +1 -0
- package/dist/web/_app/immutable/chunks/DiQJ9DLy.js +1 -0
- package/dist/web/_app/immutable/chunks/DlORZqfE.js +1 -0
- package/dist/web/_app/immutable/chunks/DmeYl7eL.js +2 -0
- package/dist/web/_app/immutable/chunks/Dng3OcRd2.js +1 -0
- package/dist/web/_app/immutable/chunks/DoKMFfJd.js +1 -0
- package/dist/web/_app/immutable/chunks/DpzG2mVI2.js +1 -0
- package/dist/web/_app/immutable/chunks/DvJSCDuZ2.js +1 -0
- package/dist/web/_app/immutable/chunks/DvPuaTCl2.js +5 -0
- package/dist/web/_app/immutable/chunks/ItgU4ei5.js +1 -0
- package/dist/web/_app/immutable/chunks/JJDMrjj62.js +1 -0
- package/dist/web/_app/immutable/chunks/OTTMDMTW.js +1 -0
- package/dist/web/_app/immutable/chunks/RmiWpCin2.js +1 -0
- package/dist/web/_app/immutable/chunks/ZTiqmKJy2.js +1 -0
- package/dist/web/_app/immutable/chunks/ahC5WoXX2.js +1 -0
- package/dist/web/_app/immutable/chunks/e3SY5t2O2.js +2692 -0
- package/dist/web/_app/immutable/chunks/g09ZrevW.js +1 -0
- package/dist/web/_app/immutable/chunks/go8N1nWD2.js +3 -0
- package/dist/web/_app/immutable/chunks/nTAmRNKw2.js +1 -0
- package/dist/web/_app/immutable/chunks/oBQOivfH2.js +1 -0
- package/dist/web/_app/immutable/chunks/oUTRxd0f.js +1 -0
- package/dist/web/_app/immutable/chunks/s_7BJJYy.js +2 -0
- package/dist/web/_app/immutable/chunks/uuFM-ygL.js +1 -0
- package/dist/web/_app/immutable/chunks/v7me-ydg.js +2 -0
- package/dist/web/_app/immutable/chunks/xihTtKlq.js +1 -0
- package/dist/web/_app/immutable/chunks/zl16E4yc2.js +1 -0
- package/dist/web/_app/immutable/entry/app.CbuUtkoM.js +2 -0
- package/dist/web/_app/immutable/entry/start.DeZyKwOT.js +1 -0
- package/dist/web/_app/immutable/nodes/0.C4PMtdx9.js +2 -0
- package/dist/web/_app/immutable/nodes/1.BwVfPLMn.js +1 -0
- package/dist/web/_app/immutable/nodes/10.DPr_SYan.js +1 -0
- package/dist/web/_app/immutable/nodes/11.CJAmEchE.js +1 -0
- package/dist/web/_app/immutable/nodes/12.ChMWXPMk.js +1 -0
- package/dist/web/_app/immutable/nodes/13.8vOKq8ue.js +1 -0
- package/dist/web/_app/immutable/nodes/14.BOSNmj9h.js +1 -0
- package/dist/web/_app/immutable/nodes/2.7N4BLwhX.js +109 -0
- package/dist/web/_app/immutable/nodes/3.Cd-tx8Ej.js +2 -0
- package/dist/web/_app/immutable/nodes/4.DtuT-syy.js +14 -0
- package/dist/web/_app/immutable/nodes/5.YwNHOrkt.js +1 -0
- package/dist/web/_app/immutable/nodes/6.BSPlYQuq.js +1 -0
- package/dist/web/_app/immutable/nodes/7.DPXzwW0H.js +1 -0
- package/dist/web/_app/immutable/nodes/8.Dhpk7w3X.js +1 -0
- package/dist/web/_app/immutable/nodes/9.Dd4iAQN5.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 +54 -19
- package/dist/web/studiograph-logomark.svg +29 -0
- package/package.json +34 -14
- package/dist/agent/skills/enrich-entities.md +0 -136
- package/dist/agent/skills/obsidian-source-setup.md +0 -246
- package/dist/agent/skills/skill-loader.d.ts +0 -48
- package/dist/agent/skills/skill-loader.js +0 -166
- package/dist/agent/skills/skill-loader.js.map +0 -1
- package/dist/agent/skills/sync-configuration.md +0 -119
- package/dist/agent/skills/sync-setup.md +0 -82
- package/dist/agent/tools/sync-tools.d.ts +0 -35
- package/dist/agent/tools/sync-tools.js +0 -992
- package/dist/agent/tools/sync-tools.js.map +0 -1
- package/dist/auth/github.d.ts +0 -56
- package/dist/auth/github.js +0 -169
- package/dist/auth/github.js.map +0 -1
- package/dist/cli/commands/access.d.ts +0 -11
- package/dist/cli/commands/access.js +0 -156
- package/dist/cli/commands/access.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/auth.d.ts +0 -10
- package/dist/cli/commands/auth.js +0 -79
- package/dist/cli/commands/auth.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 +0 -187
- package/dist/cli/commands/collection.js.map +0 -1
- package/dist/cli/commands/enrich.d.ts +0 -11
- package/dist/cli/commands/enrich.js +0 -135
- package/dist/cli/commands/enrich.js.map +0 -1
- package/dist/cli/commands/graphrag.d.ts +0 -12
- package/dist/cli/commands/graphrag.js +0 -122
- package/dist/cli/commands/graphrag.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/members.d.ts +0 -11
- package/dist/cli/commands/members.js +0 -230
- package/dist/cli/commands/members.js.map +0 -1
- package/dist/cli/commands/org.d.ts +0 -10
- package/dist/cli/commands/org.js +0 -132
- package/dist/cli/commands/org.js.map +0 -1
- package/dist/cli/commands/provision.d.ts +0 -8
- package/dist/cli/commands/provision.js +0 -116
- package/dist/cli/commands/provision.js.map +0 -1
- package/dist/cli/commands/resolve.d.ts +0 -8
- package/dist/cli/commands/resolve.js +0 -85
- package/dist/cli/commands/resolve.js.map +0 -1
- package/dist/cli/commands/review.d.ts +0 -19
- package/dist/cli/commands/review.js +0 -128
- package/dist/cli/commands/review.js.map +0 -1
- package/dist/cli/commands/source.d.ts +0 -16
- package/dist/cli/commands/source.js +0 -159
- package/dist/cli/commands/source.js.map +0 -1
- package/dist/cli/commands/start.d.ts +0 -7
- package/dist/cli/commands/start.js +0 -589
- package/dist/cli/commands/start.js.map +0 -1
- package/dist/cli/commands/sync-collection.d.ts +0 -14
- package/dist/cli/commands/sync-collection.js +0 -355
- package/dist/cli/commands/sync-collection.js.map +0 -1
- package/dist/cli/commands/sync-entities.d.ts +0 -13
- package/dist/cli/commands/sync-entities.js +0 -242
- package/dist/cli/commands/sync-entities.js.map +0 -1
- package/dist/cli/commands/team.d.ts +0 -12
- package/dist/cli/commands/team.js +0 -185
- package/dist/cli/commands/team.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 -153
- 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/cli/sync-review-interactive.d.ts +0 -31
- package/dist/cli/sync-review-interactive.js +0 -393
- package/dist/cli/sync-review-interactive.js.map +0 -1
- package/dist/core/migration-runner.d.ts +0 -42
- package/dist/core/migration-runner.js +0 -232
- package/dist/core/migration-runner.js.map +0 -1
- package/dist/core/migration-types.d.ts +0 -101
- package/dist/core/migration-types.js +0 -21
- package/dist/core/migration-types.js.map +0 -1
- package/dist/core/migrations/20260219-formalize-memory-location.d.ts +0 -2
- package/dist/core/migrations/20260219-formalize-memory-location.js +0 -35
- package/dist/core/migrations/20260219-formalize-memory-location.js.map +0 -1
- package/dist/core/migrations/20260220-add-workspace-metadata.d.ts +0 -12
- package/dist/core/migrations/20260220-add-workspace-metadata.js +0 -65
- package/dist/core/migrations/20260220-add-workspace-metadata.js.map +0 -1
- package/dist/core/migrations/20260220-add-workspace-readme.d.ts +0 -11
- package/dist/core/migrations/20260220-add-workspace-readme.js +0 -82
- package/dist/core/migrations/20260220-add-workspace-readme.js.map +0 -1
- package/dist/core/migrations/20260220-migrate-yaml-to-json.d.ts +0 -9
- package/dist/core/migrations/20260220-migrate-yaml-to-json.js +0 -64
- package/dist/core/migrations/20260220-migrate-yaml-to-json.js.map +0 -1
- package/dist/core/migrations/index.d.ts +0 -11
- package/dist/core/migrations/index.js +0 -23
- package/dist/core/migrations/index.js.map +0 -1
- package/dist/integrations/asana.d.ts +0 -26
- package/dist/integrations/asana.js +0 -78
- package/dist/integrations/asana.js.map +0 -1
- package/dist/integrations/figma-local.d.ts +0 -16
- package/dist/integrations/figma-local.js +0 -10
- package/dist/integrations/figma-local.js.map +0 -1
- package/dist/integrations/figma.d.ts +0 -17
- package/dist/integrations/figma.js +0 -17
- package/dist/integrations/figma.js.map +0 -1
- package/dist/integrations/granola.d.ts +0 -24
- package/dist/integrations/granola.js +0 -60
- package/dist/integrations/granola.js.map +0 -1
- package/dist/integrations/linear.d.ts +0 -14
- package/dist/integrations/linear.js +0 -80
- package/dist/integrations/linear.js.map +0 -1
- package/dist/integrations/paper-local.d.ts +0 -14
- package/dist/integrations/paper-local.js +0 -10
- package/dist/integrations/paper-local.js.map +0 -1
- package/dist/integrations/paper.d.ts +0 -2
- package/dist/integrations/paper.js +0 -10
- package/dist/integrations/paper.js.map +0 -1
- package/dist/integrations/pipedrive.d.ts +0 -26
- package/dist/integrations/pipedrive.js +0 -97
- package/dist/integrations/pipedrive.js.map +0 -1
- package/dist/integrations/registry.d.ts +0 -15
- package/dist/integrations/registry.js +0 -27
- package/dist/integrations/registry.js.map +0 -1
- package/dist/integrations/types.d.ts +0 -38
- package/dist/integrations/types.js +0 -9
- 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/mcp/connectors/asana.d.ts +0 -2
- package/dist/mcp/connectors/asana.js +0 -20
- package/dist/mcp/connectors/asana.js.map +0 -1
- package/dist/mcp/connectors/definitions.d.ts +0 -45
- package/dist/mcp/connectors/definitions.js +0 -32
- package/dist/mcp/connectors/definitions.js.map +0 -1
- package/dist/mcp/connectors/figma.d.ts +0 -5
- package/dist/mcp/connectors/figma.js +0 -21
- package/dist/mcp/connectors/figma.js.map +0 -1
- package/dist/mcp/connectors/gdrive.d.ts +0 -2
- package/dist/mcp/connectors/gdrive.js +0 -20
- package/dist/mcp/connectors/gdrive.js.map +0 -1
- package/dist/mcp/connectors/granola.d.ts +0 -2
- package/dist/mcp/connectors/granola.js +0 -12
- package/dist/mcp/connectors/granola.js.map +0 -1
- package/dist/mcp/connectors/linear.d.ts +0 -2
- package/dist/mcp/connectors/linear.js +0 -19
- package/dist/mcp/connectors/linear.js.map +0 -1
- package/dist/mcp/connectors/obsidian.d.ts +0 -2
- package/dist/mcp/connectors/obsidian.js +0 -19
- package/dist/mcp/connectors/obsidian.js.map +0 -1
- package/dist/mcp/connectors/pipedrive.d.ts +0 -2
- package/dist/mcp/connectors/pipedrive.js +0 -20
- package/dist/mcp/connectors/pipedrive.js.map +0 -1
- package/dist/mcp/connectors/slack.d.ts +0 -2
- package/dist/mcp/connectors/slack.js +0 -21
- package/dist/mcp/connectors/slack.js.map +0 -1
- package/dist/mcp/server-oauth-provider.d.ts +0 -56
- package/dist/mcp/server-oauth-provider.js +0 -142
- package/dist/mcp/server-oauth-provider.js.map +0 -1
- package/dist/server/chrome/chrome.css +0 -691
- package/dist/server/chrome/chrome.js +0 -374
- package/dist/server/collab-authority.d.ts +0 -70
- package/dist/server/collab-authority.js +0 -218
- package/dist/server/collab-authority.js.map +0 -1
- package/dist/server/collab.d.ts +0 -29
- package/dist/server/collab.js +0 -195
- package/dist/server/collab.js.map +0 -1
- 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/collab.d.ts +0 -6
- package/dist/server/routes/collab.js +0 -10
- package/dist/server/routes/collab.js.map +0 -1
- package/dist/server/routes/git-api.d.ts +0 -9
- package/dist/server/routes/git-api.js +0 -82
- package/dist/server/routes/git-api.js.map +0 -1
- package/dist/server/routes/meeting-ingest-api.d.ts +0 -15
- package/dist/server/routes/meeting-ingest-api.js +0 -323
- package/dist/server/routes/meeting-ingest-api.js.map +0 -1
- package/dist/server/routes/sync-api.d.ts +0 -26
- package/dist/server/routes/sync-api.js +0 -814
- package/dist/server/routes/sync-api.js.map +0 -1
- package/dist/server/routes/webhook.d.ts +0 -14
- package/dist/server/routes/webhook.js +0 -102
- package/dist/server/routes/webhook.js.map +0 -1
- package/dist/services/github-provisioner.d.ts +0 -36
- package/dist/services/github-provisioner.js +0 -126
- package/dist/services/github-provisioner.js.map +0 -1
- package/dist/services/github-service.d.ts +0 -99
- package/dist/services/github-service.js +0 -310
- package/dist/services/github-service.js.map +0 -1
- package/dist/services/insights.d.ts +0 -38
- package/dist/services/insights.js +0 -246
- package/dist/services/insights.js.map +0 -1
- package/dist/services/sync/collection-sync.d.ts +0 -60
- package/dist/services/sync/collection-sync.js +0 -509
- package/dist/services/sync/collection-sync.js.map +0 -1
- package/dist/services/sync/commit.d.ts +0 -60
- package/dist/services/sync/commit.js +0 -354
- package/dist/services/sync/commit.js.map +0 -1
- package/dist/services/sync/context-index.d.ts +0 -69
- package/dist/services/sync/context-index.js +0 -280
- package/dist/services/sync/context-index.js.map +0 -1
- package/dist/services/sync/data-fetcher.d.ts +0 -31
- package/dist/services/sync/data-fetcher.js +0 -12
- package/dist/services/sync/data-fetcher.js.map +0 -1
- package/dist/services/sync/derive.d.ts +0 -34
- package/dist/services/sync/derive.js +0 -164
- package/dist/services/sync/derive.js.map +0 -1
- package/dist/services/sync/enrichment-state.d.ts +0 -31
- package/dist/services/sync/enrichment-state.js +0 -63
- package/dist/services/sync/enrichment-state.js.map +0 -1
- package/dist/services/sync/enrichment.d.ts +0 -25
- package/dist/services/sync/enrichment.js +0 -121
- package/dist/services/sync/enrichment.js.map +0 -1
- package/dist/services/sync/entity-refresh.d.ts +0 -30
- package/dist/services/sync/entity-refresh.js +0 -275
- package/dist/services/sync/entity-refresh.js.map +0 -1
- package/dist/services/sync/frontmatter-extractor.d.ts +0 -40
- package/dist/services/sync/frontmatter-extractor.js +0 -279
- package/dist/services/sync/frontmatter-extractor.js.map +0 -1
- package/dist/services/sync/graph-match-state.d.ts +0 -33
- package/dist/services/sync/graph-match-state.js +0 -61
- package/dist/services/sync/graph-match-state.js.map +0 -1
- package/dist/services/sync/graph-match.d.ts +0 -53
- package/dist/services/sync/graph-match.js +0 -316
- package/dist/services/sync/graph-match.js.map +0 -1
- package/dist/services/sync/graphrag-client.d.ts +0 -43
- package/dist/services/sync/graphrag-client.js +0 -94
- package/dist/services/sync/graphrag-client.js.map +0 -1
- package/dist/services/sync/graphrag-config.d.ts +0 -16
- package/dist/services/sync/graphrag-config.js +0 -39
- package/dist/services/sync/graphrag-config.js.map +0 -1
- package/dist/services/sync/graphrag-context.d.ts +0 -14
- package/dist/services/sync/graphrag-context.js +0 -109
- package/dist/services/sync/graphrag-context.js.map +0 -1
- package/dist/services/sync/graphrag-indexer.d.ts +0 -30
- package/dist/services/sync/graphrag-indexer.js +0 -358
- package/dist/services/sync/graphrag-indexer.js.map +0 -1
- package/dist/services/sync/llm.d.ts +0 -32
- package/dist/services/sync/llm.js +0 -115
- package/dist/services/sync/llm.js.map +0 -1
- package/dist/services/sync/mcp-client.d.ts +0 -71
- package/dist/services/sync/mcp-client.js +0 -299
- package/dist/services/sync/mcp-client.js.map +0 -1
- package/dist/services/sync/model-factory.d.ts +0 -13
- package/dist/services/sync/model-factory.js +0 -38
- package/dist/services/sync/model-factory.js.map +0 -1
- package/dist/services/sync/name-quality.d.ts +0 -31
- package/dist/services/sync/name-quality.js +0 -60
- package/dist/services/sync/name-quality.js.map +0 -1
- package/dist/services/sync/output-schemas.d.ts +0 -92
- package/dist/services/sync/output-schemas.js +0 -43
- package/dist/services/sync/output-schemas.js.map +0 -1
- package/dist/services/sync/prompts.d.ts +0 -19
- package/dist/services/sync/prompts.js +0 -128
- package/dist/services/sync/prompts.js.map +0 -1
- package/dist/services/sync/reconciler.d.ts +0 -48
- package/dist/services/sync/reconciler.js +0 -294
- package/dist/services/sync/reconciler.js.map +0 -1
- package/dist/services/sync/rest-client.d.ts +0 -40
- package/dist/services/sync/rest-client.js +0 -100
- package/dist/services/sync/rest-client.js.map +0 -1
- package/dist/services/sync/source-config.d.ts +0 -67
- package/dist/services/sync/source-config.js +0 -304
- package/dist/services/sync/source-config.js.map +0 -1
- package/dist/services/sync/source-definitions/asana.d.ts +0 -14
- package/dist/services/sync/source-definitions/asana.js +0 -42
- package/dist/services/sync/source-definitions/asana.js.map +0 -1
- package/dist/services/sync/source-definitions/definitions.d.ts +0 -8
- package/dist/services/sync/source-definitions/definitions.js +0 -8
- package/dist/services/sync/source-definitions/definitions.js.map +0 -1
- package/dist/services/sync/source-definitions/gdrive.d.ts +0 -16
- package/dist/services/sync/source-definitions/gdrive.js +0 -68
- package/dist/services/sync/source-definitions/gdrive.js.map +0 -1
- package/dist/services/sync/source-definitions/granola.d.ts +0 -2
- package/dist/services/sync/source-definitions/granola.js +0 -21
- package/dist/services/sync/source-definitions/granola.js.map +0 -1
- package/dist/services/sync/source-definitions/linear.d.ts +0 -2
- package/dist/services/sync/source-definitions/linear.js +0 -62
- package/dist/services/sync/source-definitions/linear.js.map +0 -1
- package/dist/services/sync/source-definitions/obsidian.d.ts +0 -2
- package/dist/services/sync/source-definitions/obsidian.js +0 -55
- package/dist/services/sync/source-definitions/obsidian.js.map +0 -1
- package/dist/services/sync/source-definitions/pipedrive.d.ts +0 -2
- package/dist/services/sync/source-definitions/pipedrive.js +0 -43
- package/dist/services/sync/source-definitions/pipedrive.js.map +0 -1
- package/dist/services/sync/staging.d.ts +0 -53
- package/dist/services/sync/staging.js +0 -130
- package/dist/services/sync/staging.js.map +0 -1
- package/dist/services/sync/structured-extractor.d.ts +0 -57
- package/dist/services/sync/structured-extractor.js +0 -584
- package/dist/services/sync/structured-extractor.js.map +0 -1
- package/dist/services/sync/sync-runner.d.ts +0 -32
- package/dist/services/sync/sync-runner.js +0 -195
- package/dist/services/sync/sync-runner.js.map +0 -1
- package/dist/services/sync/sync-state.d.ts +0 -43
- package/dist/services/sync/sync-state.js +0 -154
- package/dist/services/sync/sync-state.js.map +0 -1
- package/dist/services/sync/types.d.ts +0 -381
- package/dist/services/sync/types.js +0 -8
- package/dist/services/sync/types.js.map +0 -1
- package/dist/services/sync/unstructured-extractor.d.ts +0 -27
- package/dist/services/sync/unstructured-extractor.js +0 -185
- package/dist/services/sync/unstructured-extractor.js.map +0 -1
- package/dist/utils/merge-resolver.d.ts +0 -59
- package/dist/utils/merge-resolver.js +0 -303
- package/dist/utils/merge-resolver.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.DdizXOKi.css +0 -1
- package/dist/web/_app/immutable/assets/10.BUrHkYry.css +0 -1
- package/dist/web/_app/immutable/assets/2.n7-yW_Fs.css +0 -1
- package/dist/web/_app/immutable/assets/3.BtaZagnv.css +0 -1
- package/dist/web/_app/immutable/assets/4.DT7X0x5S.css +0 -1
- package/dist/web/_app/immutable/assets/5.DFeGxLYf.css +0 -1
- package/dist/web/_app/immutable/assets/6.CquhUpOu.css +0 -1
- package/dist/web/_app/immutable/assets/7.CjbDRbuG.css +0 -1
- package/dist/web/_app/immutable/assets/8.S1QdUGNM.css +0 -1
- package/dist/web/_app/immutable/assets/9.CT4xL4K3.css +0 -1
- package/dist/web/_app/immutable/assets/Copy.FS8bdfxr.css +0 -1
- package/dist/web/_app/immutable/assets/Toaster.rN8r_Hzv.css +0 -1
- package/dist/web/_app/immutable/assets/ViewToolbar.D-QW2oKe.css +0 -1
- package/dist/web/_app/immutable/assets/index.D6tMDJWk.css +0 -1
- package/dist/web/_app/immutable/chunks/37NdyH6G.js +0 -32
- package/dist/web/_app/immutable/chunks/4Hhzb6pv.js +0 -1
- package/dist/web/_app/immutable/chunks/72bZS3G9.js +0 -1
- package/dist/web/_app/immutable/chunks/7S2LGqoP.js +0 -2
- package/dist/web/_app/immutable/chunks/B-7hHz7B.js +0 -1
- package/dist/web/_app/immutable/chunks/B340SUKR.js +0 -1
- package/dist/web/_app/immutable/chunks/BB_5th5W.js +0 -3383
- package/dist/web/_app/immutable/chunks/BDoWDZaG.js +0 -1
- package/dist/web/_app/immutable/chunks/BFyl1ZHO.js +0 -1
- package/dist/web/_app/immutable/chunks/BS2rFAVq.js +0 -1
- package/dist/web/_app/immutable/chunks/BSsDC_p4.js +0 -1
- package/dist/web/_app/immutable/chunks/BTX2Jr8_.js +0 -1
- package/dist/web/_app/immutable/chunks/BWNY8zw6.js +0 -2
- package/dist/web/_app/immutable/chunks/BdPUVvAi.js +0 -1
- package/dist/web/_app/immutable/chunks/BmsJVLyy.js +0 -1
- package/dist/web/_app/immutable/chunks/BoAosqzE.js +0 -1
- package/dist/web/_app/immutable/chunks/Bs-tL5OR.js +0 -1
- package/dist/web/_app/immutable/chunks/Bsacq2UX.js +0 -1
- package/dist/web/_app/immutable/chunks/BuewkNdS.js +0 -4
- package/dist/web/_app/immutable/chunks/ByunV8un.js +0 -1
- package/dist/web/_app/immutable/chunks/C7VoTosa.js +0 -2
- package/dist/web/_app/immutable/chunks/CDV5Q7RN.js +0 -1
- package/dist/web/_app/immutable/chunks/CJ8__CWt.js +0 -1
- package/dist/web/_app/immutable/chunks/CJUKmosC.js +0 -5
- package/dist/web/_app/immutable/chunks/CSVbGg_b.js +0 -5
- package/dist/web/_app/immutable/chunks/CT6oIU-C.js +0 -1
- package/dist/web/_app/immutable/chunks/CTRxNfZk.js +0 -1
- package/dist/web/_app/immutable/chunks/CWQRQXxy.js +0 -1
- package/dist/web/_app/immutable/chunks/CXH6iFbA.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/CdeYcEuU.js +0 -1
- package/dist/web/_app/immutable/chunks/CmCtpZ1Y.js +0 -1
- package/dist/web/_app/immutable/chunks/CqkleIqs.js +0 -1
- package/dist/web/_app/immutable/chunks/CrdV0ttd.js +0 -1
- package/dist/web/_app/immutable/chunks/CscoF-YL.js +0 -18
- package/dist/web/_app/immutable/chunks/Cx4YdFMk.js +0 -1
- package/dist/web/_app/immutable/chunks/D7ZqAKi9.js +0 -3
- package/dist/web/_app/immutable/chunks/DGbA7IXh.js +0 -2
- package/dist/web/_app/immutable/chunks/DbbB6Up5.js +0 -1
- package/dist/web/_app/immutable/chunks/DnL9f0lc.js +0 -7
- package/dist/web/_app/immutable/chunks/DtM5cEDu.js +0 -1
- package/dist/web/_app/immutable/chunks/Eqahi7_S.js +0 -2
- package/dist/web/_app/immutable/chunks/FFlLQIiS.js +0 -1
- package/dist/web/_app/immutable/chunks/O9Eb9k00.js +0 -1
- package/dist/web/_app/immutable/chunks/PPVm8Dsz.js +0 -1
- package/dist/web/_app/immutable/chunks/QF8MAmnc.js +0 -1
- package/dist/web/_app/immutable/chunks/UjzxCpxn.js +0 -1
- package/dist/web/_app/immutable/chunks/WSUKABI_.js +0 -1
- package/dist/web/_app/immutable/chunks/Y90OgS-9.js +0 -1
- package/dist/web/_app/immutable/chunks/cLyZlkXv.js +0 -1
- package/dist/web/_app/immutable/chunks/iDtAARVW.js +0 -2
- package/dist/web/_app/immutable/chunks/oC_W7W7p.js +0 -1
- package/dist/web/_app/immutable/chunks/rJdWIgh-.js +0 -1
- package/dist/web/_app/immutable/chunks/tvOsokaa.js +0 -1
- package/dist/web/_app/immutable/chunks/uLEXaPwE.js +0 -1
- package/dist/web/_app/immutable/chunks/vSaooFHB.js +0 -1
- package/dist/web/_app/immutable/entry/app.DAR-mtfg.js +0 -2
- package/dist/web/_app/immutable/entry/start.xDnyRaR1.js +0 -1
- package/dist/web/_app/immutable/nodes/0.D0aV-Zro.js +0 -2
- package/dist/web/_app/immutable/nodes/1.C7QoM8qD.js +0 -1
- package/dist/web/_app/immutable/nodes/10.DrDOAjOD.js +0 -1
- package/dist/web/_app/immutable/nodes/2.B0OgNuKW.js +0 -168
- package/dist/web/_app/immutable/nodes/3.BZ4qHGZi.js +0 -1
- package/dist/web/_app/immutable/nodes/4.hm-mxuuj.js +0 -12
- package/dist/web/_app/immutable/nodes/5.Bdbt4fjx.js +0 -4
- package/dist/web/_app/immutable/nodes/6.BXrCI40c.js +0 -2
- package/dist/web/_app/immutable/nodes/7.Chd4i9bm.js +0 -2
- package/dist/web/_app/immutable/nodes/8.B8SF-aNs.js +0 -1
- package/dist/web/_app/immutable/nodes/9.YDeu-RnO.js +0 -1
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Login, logout, session verification, and auth status endpoints.
|
|
5
5
|
*/
|
|
6
|
+
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
7
|
+
import { isWorkspaceOwner } from '../../services/auth-service.js';
|
|
8
|
+
import { Workspace } from '../../core/workspace.js';
|
|
9
|
+
import { ensurePersonalFolder, archivePersonalFolder } from '../../services/personal-folder.js';
|
|
10
|
+
import { authUserToGitUser, ensurePersonForUser, findPersonRefForUser } from '../../services/user-person-bridge.js';
|
|
11
|
+
import * as access from '../../services/access-control.js';
|
|
6
12
|
// ── Login rate limiting ──
|
|
7
13
|
const MAX_ATTEMPTS = 5;
|
|
8
14
|
const LOCKOUT_MS = 15 * 60 * 1000; // 15 minutes
|
|
@@ -35,36 +41,251 @@ export function recordFailedAttempt(email) {
|
|
|
35
41
|
export function clearAttempts(email) {
|
|
36
42
|
loginAttempts.delete(email.toLowerCase());
|
|
37
43
|
}
|
|
38
|
-
function
|
|
44
|
+
function requireOwner(req, authService) {
|
|
39
45
|
const token = req.cookies?.['__sg_token'];
|
|
40
46
|
if (!token)
|
|
41
47
|
return null;
|
|
42
48
|
const user = authService.verifyToken(token);
|
|
43
|
-
if (!user || user.role
|
|
49
|
+
if (!user || !isWorkspaceOwner(user.role))
|
|
44
50
|
return null;
|
|
45
51
|
return user;
|
|
46
52
|
}
|
|
47
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Resolve the caller to an AuthUser. The global auth hook skips /api/auth/*
|
|
55
|
+
* so endpoints that need identity (like the token CRUD routes below) must
|
|
56
|
+
* look up credentials themselves.
|
|
57
|
+
*
|
|
58
|
+
* Accepted forms:
|
|
59
|
+
* - Cookie `__sg_token=<jwt>` (web UI)
|
|
60
|
+
* - `Authorization: Bearer <jwt>` (CLI with stored JWT)
|
|
61
|
+
* - `Authorization: Bearer <sg_…>` (CLI with API token)
|
|
62
|
+
*
|
|
63
|
+
* Mirrors the precedence the main API middleware uses elsewhere
|
|
64
|
+
* (src/server/index.ts) — needed so CLI commands like
|
|
65
|
+
* `studiograph admin transfer-ownership` can call /api/auth/* endpoints
|
|
66
|
+
* using the same Bearer sg_ token they use everywhere else.
|
|
67
|
+
*/
|
|
68
|
+
function requireUser(req, authService) {
|
|
69
|
+
const cookieToken = req.cookies?.['__sg_token'];
|
|
70
|
+
if (cookieToken) {
|
|
71
|
+
const user = authService.verifyToken(cookieToken);
|
|
72
|
+
if (user)
|
|
73
|
+
return user;
|
|
74
|
+
}
|
|
75
|
+
const authHeader = req.headers?.authorization;
|
|
76
|
+
if (authHeader?.startsWith('Bearer ')) {
|
|
77
|
+
const bearer = authHeader.slice('Bearer '.length).trim();
|
|
78
|
+
if (bearer.startsWith('sg_')) {
|
|
79
|
+
return authService.verifyApiToken(bearer);
|
|
80
|
+
}
|
|
81
|
+
// Treat anything else as a JWT — verifyToken returns null on invalid input.
|
|
82
|
+
return authService.verifyToken(bearer);
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
function managedCloudAuthConfig() {
|
|
87
|
+
return {
|
|
88
|
+
enabled: parseBoolean(process.env.STUDIOGRAPH_MANAGED_AUTH),
|
|
89
|
+
cloudUrl: process.env.STUDIOGRAPH_CLOUD_URL?.trim() ?? '',
|
|
90
|
+
orgId: process.env.STUDIOGRAPH_CLOUD_ORG_ID?.trim() ?? '',
|
|
91
|
+
workspaceId: process.env.STUDIOGRAPH_CLOUD_WORKSPACE_ID?.trim() ?? '',
|
|
92
|
+
token: process.env.STUDIOGRAPH_CLOUD_TOKEN?.trim() ?? '',
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function managedCloudLoginUrl(config) {
|
|
96
|
+
if (!config.cloudUrl || !config.orgId || !config.workspaceId)
|
|
97
|
+
return null;
|
|
98
|
+
const url = new URL('/auth/workspace', config.cloudUrl);
|
|
99
|
+
url.searchParams.set('orgId', config.orgId);
|
|
100
|
+
url.searchParams.set('workspaceId', config.workspaceId);
|
|
101
|
+
return url.toString();
|
|
102
|
+
}
|
|
103
|
+
function managedCloudLogoutUrl(config, returnTo) {
|
|
104
|
+
if (!config.cloudUrl)
|
|
105
|
+
return null;
|
|
106
|
+
const url = new URL('/auth/logout', config.cloudUrl);
|
|
107
|
+
if (returnTo)
|
|
108
|
+
url.searchParams.set('returnTo', returnTo);
|
|
109
|
+
return url.toString();
|
|
110
|
+
}
|
|
111
|
+
function requestOrigin(req) {
|
|
112
|
+
const rawHost = req.headers?.['x-forwarded-host'] ?? req.headers?.host;
|
|
113
|
+
const host = Array.isArray(rawHost) ? rawHost[0] : rawHost;
|
|
114
|
+
if (!host)
|
|
115
|
+
return null;
|
|
116
|
+
const rawProto = req.headers?.['x-forwarded-proto'];
|
|
117
|
+
const forwardedProto = Array.isArray(rawProto) ? rawProto[0] : rawProto;
|
|
118
|
+
const proto = typeof forwardedProto === 'string' && forwardedProto.trim()
|
|
119
|
+
? forwardedProto.split(',')[0].trim()
|
|
120
|
+
: 'http';
|
|
121
|
+
return `${proto}://${host}`;
|
|
122
|
+
}
|
|
123
|
+
function managedLogoutReturnTo(req) {
|
|
124
|
+
const origin = requestOrigin(req);
|
|
125
|
+
if (!origin)
|
|
126
|
+
return null;
|
|
127
|
+
const url = new URL('/login', origin);
|
|
128
|
+
url.searchParams.set('managedLogout', '1');
|
|
129
|
+
return url.toString();
|
|
130
|
+
}
|
|
131
|
+
function verifyCloudLoginToken(token, secret) {
|
|
132
|
+
const [payloadPart, signaturePart] = token.split('.');
|
|
133
|
+
if (!payloadPart || !signaturePart || token.split('.').length !== 2) {
|
|
134
|
+
throw new Error('Malformed login token');
|
|
135
|
+
}
|
|
136
|
+
const expected = hmacBase64Url(payloadPart, secret);
|
|
137
|
+
if (!constantTimeEqual(signaturePart, expected)) {
|
|
138
|
+
throw new Error('Invalid login token signature');
|
|
139
|
+
}
|
|
140
|
+
const claims = JSON.parse(Buffer.from(payloadPart, 'base64url').toString('utf8'));
|
|
141
|
+
if (claims.iss !== 'studiograph-cloud' || claims.aud !== 'studiograph-runtime') {
|
|
142
|
+
throw new Error('Invalid login token audience');
|
|
143
|
+
}
|
|
144
|
+
if (!claims.orgId || !claims.workspaceId || !claims.userId || !claims.email || !claims.displayName || !claims.role) {
|
|
145
|
+
throw new Error('Incomplete login token');
|
|
146
|
+
}
|
|
147
|
+
if (!['owner', 'admin', 'member'].includes(claims.role)) {
|
|
148
|
+
throw new Error('Invalid login token role');
|
|
149
|
+
}
|
|
150
|
+
const now = Math.floor(Date.now() / 1000);
|
|
151
|
+
if (typeof claims.exp !== 'number' || claims.exp < now) {
|
|
152
|
+
throw new Error('Login token has expired');
|
|
153
|
+
}
|
|
154
|
+
if (typeof claims.iat !== 'number' || claims.iat > now + 60) {
|
|
155
|
+
throw new Error('Login token was issued in the future');
|
|
156
|
+
}
|
|
157
|
+
return claims;
|
|
158
|
+
}
|
|
159
|
+
function runtimeRoleForCloudRole(cloudRole, existing, authService) {
|
|
160
|
+
if (existing?.role === 'owner')
|
|
161
|
+
return 'owner';
|
|
162
|
+
if (cloudRole === 'owner')
|
|
163
|
+
return 'owner';
|
|
164
|
+
if (!authService.getOwner() && cloudRole === 'admin')
|
|
165
|
+
return 'owner';
|
|
166
|
+
return 'member';
|
|
167
|
+
}
|
|
168
|
+
function grantManagedWorkspaceAccess(authService, workspaceManager, user, cloudRole) {
|
|
169
|
+
const folderRole = cloudRole === 'owner' || cloudRole === 'admin' ? 'admin' : 'editor';
|
|
170
|
+
for (const repo of workspaceManager.getAllRepoConfigs()) {
|
|
171
|
+
if (repo.personal)
|
|
172
|
+
continue;
|
|
173
|
+
const currentRole = authService.getFolderRole(user.id, repo.name);
|
|
174
|
+
if (currentRole === 'admin')
|
|
175
|
+
continue;
|
|
176
|
+
if (currentRole !== folderRole)
|
|
177
|
+
authService.grantFolderAccess(user.id, repo.name, folderRole);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function hmacBase64Url(value, secret) {
|
|
181
|
+
return createHmac('sha256', secret).update(value).digest('base64url');
|
|
182
|
+
}
|
|
183
|
+
function constantTimeEqual(a, b) {
|
|
184
|
+
const left = Buffer.from(a);
|
|
185
|
+
const right = Buffer.from(b);
|
|
186
|
+
return left.length === right.length && timingSafeEqual(left, right);
|
|
187
|
+
}
|
|
188
|
+
function parseBoolean(value) {
|
|
189
|
+
if (!value)
|
|
190
|
+
return false;
|
|
191
|
+
return ['1', 'true', 'yes', 'on'].includes(value.trim().toLowerCase());
|
|
192
|
+
}
|
|
193
|
+
export async function registerAuthApiRoutes(fastify, authService, workspacePath, workspaceManager, workspaceName) {
|
|
194
|
+
fastify.get('/api/cloud/auth/callback', async (req, reply) => {
|
|
195
|
+
const config = managedCloudAuthConfig();
|
|
196
|
+
if (!config.enabled)
|
|
197
|
+
return reply.status(404).send({ error: 'Managed cloud auth is not enabled' });
|
|
198
|
+
if (!config.token || !config.workspaceId) {
|
|
199
|
+
return reply.status(503).send({ error: 'Managed cloud auth is not configured' });
|
|
200
|
+
}
|
|
201
|
+
const { token } = req.query;
|
|
202
|
+
if (!token)
|
|
203
|
+
return reply.status(400).send({ error: 'Missing login token' });
|
|
204
|
+
try {
|
|
205
|
+
const claims = verifyCloudLoginToken(token, config.token);
|
|
206
|
+
if (claims.workspaceId !== config.workspaceId) {
|
|
207
|
+
return reply.status(403).send({ error: 'Login token was issued for a different workspace' });
|
|
208
|
+
}
|
|
209
|
+
if (config.orgId && claims.orgId !== config.orgId) {
|
|
210
|
+
return reply.status(403).send({ error: 'Login token was issued for a different organization' });
|
|
211
|
+
}
|
|
212
|
+
const existing = authService.findUserByEmail(claims.email);
|
|
213
|
+
const runtimeRole = runtimeRoleForCloudRole(claims.role, existing, authService);
|
|
214
|
+
const user = authService.upsertCloudManagedUser({
|
|
215
|
+
email: claims.email,
|
|
216
|
+
displayName: claims.displayName,
|
|
217
|
+
role: runtimeRole,
|
|
218
|
+
});
|
|
219
|
+
await ensurePersonalFolder(new Workspace(workspacePath), authService, user);
|
|
220
|
+
grantManagedWorkspaceAccess(authService, workspaceManager, user, claims.role);
|
|
221
|
+
workspaceManager.reloadConfig();
|
|
222
|
+
try {
|
|
223
|
+
const r = await ensurePersonForUser(workspaceManager, authService, user, authUserToGitUser(user));
|
|
224
|
+
if (r.action === 'skipped') {
|
|
225
|
+
console.warn(`[auth] cloud-managed user person bridge skipped: ${r.reason}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (err) {
|
|
229
|
+
console.warn('[auth] ensurePersonForUser failed during cloud login:', err?.message ?? err);
|
|
230
|
+
}
|
|
231
|
+
const secure = req.headers['x-forwarded-proto'] === 'https';
|
|
232
|
+
reply.setCookie('__sg_token', authService.createSessionToken(user), {
|
|
233
|
+
path: '/',
|
|
234
|
+
httpOnly: true,
|
|
235
|
+
sameSite: 'strict',
|
|
236
|
+
secure,
|
|
237
|
+
maxAge: 7 * 24 * 60 * 60,
|
|
238
|
+
});
|
|
239
|
+
return reply.redirect('/');
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
return reply.status(401).send({ error: err?.message || 'Invalid login token' });
|
|
243
|
+
}
|
|
244
|
+
});
|
|
48
245
|
// ── Admin user management ──
|
|
49
|
-
// GET /api/auth/users — list all users
|
|
246
|
+
// GET /api/auth/users — list all users. Any authenticated caller: folder
|
|
247
|
+
// admins need this to populate the share-dialog "Add members" candidates,
|
|
248
|
+
// and the comment @-mention surface needs the same shape.
|
|
249
|
+
// Mutating endpoints below (POST/DELETE/PATCH) stay owner-only.
|
|
50
250
|
fastify.get('/api/auth/users', async (req, reply) => {
|
|
51
|
-
const
|
|
52
|
-
if (!
|
|
53
|
-
return reply.status(
|
|
251
|
+
const user = requireUser(req, authService);
|
|
252
|
+
if (!user)
|
|
253
|
+
return reply.status(401).send({ error: 'Authentication required' });
|
|
54
254
|
return reply.send({ users: authService.listUsers() });
|
|
55
255
|
});
|
|
56
256
|
// POST /api/auth/users — create a new user (admin only)
|
|
57
257
|
fastify.post('/api/auth/users', async (req, reply) => {
|
|
58
|
-
const admin =
|
|
258
|
+
const admin = requireOwner(req, authService);
|
|
59
259
|
if (!admin)
|
|
60
|
-
return reply.status(403).send({ error: '
|
|
260
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
61
261
|
const { email, password, displayName, role } = req.body;
|
|
62
262
|
if (!email || !password) {
|
|
63
263
|
return reply.status(400).send({ error: 'Email and password are required' });
|
|
64
264
|
}
|
|
265
|
+
if (role && role !== 'owner' && role !== 'member') {
|
|
266
|
+
return reply.status(400).send({ error: `Invalid role "${role}" — must be "owner" or "member"` });
|
|
267
|
+
}
|
|
65
268
|
try {
|
|
66
269
|
const user = authService.createUser(email, password, displayName || email.split('@')[0], role || 'member');
|
|
67
|
-
|
|
270
|
+
await ensurePersonalFolder(new Workspace(workspacePath), authService, user);
|
|
271
|
+
workspaceManager.reloadConfig();
|
|
272
|
+
// Bridge the new auth account to a person entity (email-match an
|
|
273
|
+
// existing record or auto-provision one in the team repo). Non-fatal:
|
|
274
|
+
// a missing team repo should never block registration, but the
|
|
275
|
+
// caller still needs to know the bridge didn't take so the UI can
|
|
276
|
+
// surface a "your account is created but workspace-wide mentions /
|
|
277
|
+
// assignment won't reach you yet" hint.
|
|
278
|
+
let bridgeWarning;
|
|
279
|
+
try {
|
|
280
|
+
const r = await ensurePersonForUser(workspaceManager, authService, user, authUserToGitUser(user));
|
|
281
|
+
if (r.action === 'skipped')
|
|
282
|
+
bridgeWarning = `Person record not auto-provisioned (${r.reason}). Workspace owner needs to configure team_repo before mentions and "My Tasks" will resolve to this account.`;
|
|
283
|
+
}
|
|
284
|
+
catch (err) {
|
|
285
|
+
console.warn('[auth] ensurePersonForUser failed:', err?.message ?? err);
|
|
286
|
+
bridgeWarning = `Person record provisioning failed: ${err?.message ?? err}. Workspace owner can retry via the agent's link_person_to_user tool.`;
|
|
287
|
+
}
|
|
288
|
+
return reply.send({ user, ...(bridgeWarning ? { bridgeWarning } : {}) });
|
|
68
289
|
}
|
|
69
290
|
catch (err) {
|
|
70
291
|
return reply.status(400).send({ error: err.message });
|
|
@@ -72,9 +293,9 @@ export async function registerAuthApiRoutes(fastify, authService, workspaceName)
|
|
|
72
293
|
});
|
|
73
294
|
// DELETE /api/auth/users/:id — delete a user (admin only, cannot delete self or last admin)
|
|
74
295
|
fastify.delete('/api/auth/users/:id', async (req, reply) => {
|
|
75
|
-
const admin =
|
|
296
|
+
const admin = requireOwner(req, authService);
|
|
76
297
|
if (!admin)
|
|
77
|
-
return reply.status(403).send({ error: '
|
|
298
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
78
299
|
const userId = parseInt(req.params.id, 10);
|
|
79
300
|
if (isNaN(userId))
|
|
80
301
|
return reply.status(400).send({ error: 'Invalid user ID' });
|
|
@@ -84,17 +305,111 @@ export async function registerAuthApiRoutes(fastify, authService, workspaceName)
|
|
|
84
305
|
const target = users.find(u => u.id === userId);
|
|
85
306
|
if (!target)
|
|
86
307
|
return reply.status(404).send({ error: 'User not found' });
|
|
87
|
-
if (target.role === '
|
|
88
|
-
return reply.status(400).send({ error: 'Cannot delete the last
|
|
308
|
+
if (target.role === 'owner' && users.filter(u => u.role === 'owner').length <= 1) {
|
|
309
|
+
return reply.status(400).send({ error: 'Cannot delete the last workspace owner. Transfer ownership first.' });
|
|
310
|
+
}
|
|
311
|
+
// Transfer folders the target solely administers to the actor
|
|
312
|
+
// (the workspace owner performing this deletion) BEFORE the cascade
|
|
313
|
+
// delete — otherwise folder_access rows for those folders disappear
|
|
314
|
+
// and the folder is left with no admins.
|
|
315
|
+
//
|
|
316
|
+
// Personal folders (the target's "My Folder") are a sub-case: they
|
|
317
|
+
// transfer the same way, then get demoted to normal archive folders
|
|
318
|
+
// so the one-personal-folder-per-user invariant holds and the actor
|
|
319
|
+
// ends up with a plainly-named folder they own outright.
|
|
320
|
+
const workspace = new Workspace(workspacePath);
|
|
321
|
+
const preConfig = await workspace.loadConfig();
|
|
322
|
+
const targetPersonalFolders = preConfig.repos.filter(r => r.personal === true && r.owner_id === target.id);
|
|
323
|
+
const personalEntryCounts = new Map();
|
|
324
|
+
for (const p of targetPersonalFolders) {
|
|
325
|
+
try {
|
|
326
|
+
personalEntryCounts.set(p.name, workspaceManager.getGraph(p.name).listEntityIds().length);
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
personalEntryCounts.set(p.name, 0);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
const transferred = authService.transferFoldersOnDelete(target.id, admin.id);
|
|
333
|
+
// Capture the old name upfront: archivePersonalFolder mutates the
|
|
334
|
+
// RepoConfig in place (name/path change), so reading `p.name` after
|
|
335
|
+
// the await would return the new archive name.
|
|
336
|
+
const archived = [];
|
|
337
|
+
for (const p of targetPersonalFolders) {
|
|
338
|
+
const oldName = p.name;
|
|
339
|
+
if (!transferred.includes(oldName))
|
|
340
|
+
continue;
|
|
341
|
+
const { newName, newDisplayName } = await archivePersonalFolder(workspace, oldName, target.displayName, authService);
|
|
342
|
+
archived.push({
|
|
343
|
+
oldName,
|
|
344
|
+
newName,
|
|
345
|
+
newDisplayName,
|
|
346
|
+
entryCount: personalEntryCounts.get(oldName) ?? 0,
|
|
347
|
+
});
|
|
89
348
|
}
|
|
90
349
|
authService.deleteUser(target.email);
|
|
91
|
-
|
|
350
|
+
if (archived.length > 0)
|
|
351
|
+
workspaceManager.reloadConfig();
|
|
352
|
+
return reply.send({ ok: true, transferred, archived });
|
|
353
|
+
});
|
|
354
|
+
// GET /api/auth/users/:id/deletion-preview — show the actor what
|
|
355
|
+
// will transfer if they delete this user. Owner-gated. Returns entry
|
|
356
|
+
// counts and archive names so the confirmation UI can set expectations
|
|
357
|
+
// WITHOUT exposing the contents of the target's private folder. The
|
|
358
|
+
// preview is advisory; the DELETE endpoint is the source of truth.
|
|
359
|
+
fastify.get('/api/auth/users/:id/deletion-preview', async (req, reply) => {
|
|
360
|
+
const admin = requireOwner(req, authService);
|
|
361
|
+
if (!admin)
|
|
362
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
363
|
+
const userId = parseInt(req.params.id, 10);
|
|
364
|
+
if (isNaN(userId))
|
|
365
|
+
return reply.status(400).send({ error: 'Invalid user ID' });
|
|
366
|
+
if (admin.id === userId)
|
|
367
|
+
return reply.status(400).send({ error: 'Cannot preview deleting yourself' });
|
|
368
|
+
const target = authService.listUsers().find(u => u.id === userId);
|
|
369
|
+
if (!target)
|
|
370
|
+
return reply.status(404).send({ error: 'User not found' });
|
|
371
|
+
const workspace = new Workspace(workspacePath);
|
|
372
|
+
const config = await workspace.loadConfig();
|
|
373
|
+
// Mirror transferFoldersOnDelete's sole-admin rule so the preview
|
|
374
|
+
// matches the real delete. Personal folders are 1-member by nature,
|
|
375
|
+
// so they always qualify.
|
|
376
|
+
const targetAdminFolders = authService.getUserFolders(target.id)
|
|
377
|
+
.filter(f => authService.getFolderRole(target.id, f) === 'admin');
|
|
378
|
+
const soleAdminFolders = targetAdminFolders.filter(f => authService.getFolderAdmins(f).length === 1);
|
|
379
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
380
|
+
const personalFolders = config.repos.filter(r => r.personal === true && r.owner_id === target.id && soleAdminFolders.includes(r.name));
|
|
381
|
+
const sharedSoleAdmin = soleAdminFolders.filter(f => !personalFolders.some(p => p.name === f));
|
|
382
|
+
const personal = personalFolders.map(p => {
|
|
383
|
+
let entryCount = 0;
|
|
384
|
+
try {
|
|
385
|
+
entryCount = workspaceManager.getGraph(p.name).listEntityIds().length;
|
|
386
|
+
}
|
|
387
|
+
catch { /* skip */ }
|
|
388
|
+
return {
|
|
389
|
+
entryCount,
|
|
390
|
+
newDisplayName: `Archive: ${target.displayName} (${date})`,
|
|
391
|
+
};
|
|
392
|
+
});
|
|
393
|
+
const shared = sharedSoleAdmin.map(f => {
|
|
394
|
+
const repo = config.repos.find(r => r.name === f);
|
|
395
|
+
let entryCount = 0;
|
|
396
|
+
try {
|
|
397
|
+
entryCount = workspaceManager.getGraph(f).listEntityIds().length;
|
|
398
|
+
}
|
|
399
|
+
catch { /* skip */ }
|
|
400
|
+
return {
|
|
401
|
+
name: f,
|
|
402
|
+
displayName: repo?.display_name ?? f,
|
|
403
|
+
entryCount,
|
|
404
|
+
};
|
|
405
|
+
});
|
|
406
|
+
return reply.send({ personal, shared });
|
|
92
407
|
});
|
|
93
408
|
// PATCH /api/auth/users/:id/password — reset a user's password (admin only)
|
|
94
409
|
fastify.patch('/api/auth/users/:id/password', async (req, reply) => {
|
|
95
|
-
const admin =
|
|
410
|
+
const admin = requireOwner(req, authService);
|
|
96
411
|
if (!admin)
|
|
97
|
-
return reply.status(403).send({ error: '
|
|
412
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
98
413
|
const userId = parseInt(req.params.id, 10);
|
|
99
414
|
if (isNaN(userId))
|
|
100
415
|
return reply.status(400).send({ error: 'Invalid user ID' });
|
|
@@ -113,23 +428,116 @@ export async function registerAuthApiRoutes(fastify, authService, workspaceName)
|
|
|
113
428
|
return reply.status(400).send({ error: err.message });
|
|
114
429
|
}
|
|
115
430
|
});
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
431
|
+
// PATCH /api/auth/users/:id — update a member's profile (owner only).
|
|
432
|
+
// Currently accepts `email` and `displayName`; mirrors the existing
|
|
433
|
+
// password-reset pattern (owner-gated, no user notification).
|
|
434
|
+
fastify.patch('/api/auth/users/:id', async (req, reply) => {
|
|
435
|
+
const admin = requireOwner(req, authService);
|
|
119
436
|
if (!admin)
|
|
120
|
-
return reply.status(403).send({ error: '
|
|
121
|
-
const
|
|
122
|
-
|
|
437
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
438
|
+
const userId = parseInt(req.params.id, 10);
|
|
439
|
+
if (isNaN(userId))
|
|
440
|
+
return reply.status(400).send({ error: 'Invalid user ID' });
|
|
441
|
+
const { email, displayName } = req.body;
|
|
442
|
+
if (email === undefined && displayName === undefined) {
|
|
443
|
+
return reply.status(400).send({ error: 'Nothing to update' });
|
|
444
|
+
}
|
|
445
|
+
if (email !== undefined) {
|
|
446
|
+
const normalized = email.toLowerCase().trim();
|
|
447
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(normalized)) {
|
|
448
|
+
return reply.status(400).send({ error: 'Invalid email address' });
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
const target = authService.findUserById(userId);
|
|
452
|
+
if (!target)
|
|
453
|
+
return reply.status(404).send({ error: 'User not found' });
|
|
454
|
+
try {
|
|
455
|
+
const updated = authService.updateProfile(userId, { email, displayName });
|
|
456
|
+
return reply.send({ user: updated });
|
|
457
|
+
}
|
|
458
|
+
catch (err) {
|
|
459
|
+
// SQLite raises a UNIQUE constraint error on duplicate email.
|
|
460
|
+
if (String(err?.message ?? '').includes('UNIQUE')) {
|
|
461
|
+
return reply.status(409).send({ error: 'That email is already in use' });
|
|
462
|
+
}
|
|
463
|
+
return reply.status(400).send({ error: err.message });
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
// ── Per-user API tokens (used by MCP clients, CLI, and git HTTP) ──
|
|
467
|
+
// POST /api/auth/tokens — mint a new token for the authenticated user.
|
|
468
|
+
// Body: { name: string }. Returns the raw token once; only its hash is stored.
|
|
469
|
+
fastify.post('/api/auth/tokens', async (req, reply) => {
|
|
470
|
+
const user = requireUser(req, authService);
|
|
471
|
+
if (!user)
|
|
472
|
+
return reply.status(401).send({ error: 'Unauthorized' });
|
|
473
|
+
const { name } = (req.body ?? {});
|
|
474
|
+
if (!name || !name.trim()) {
|
|
475
|
+
return reply.status(400).send({ error: 'name is required' });
|
|
476
|
+
}
|
|
477
|
+
try {
|
|
478
|
+
const minted = authService.createApiToken(user.id, name);
|
|
479
|
+
return reply.status(201).send(minted);
|
|
480
|
+
}
|
|
481
|
+
catch (err) {
|
|
482
|
+
return reply.status(400).send({ error: err.message });
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
// GET /api/auth/tokens — list the authenticated user's tokens (metadata only).
|
|
486
|
+
fastify.get('/api/auth/tokens', async (req, reply) => {
|
|
487
|
+
const user = requireUser(req, authService);
|
|
488
|
+
if (!user)
|
|
489
|
+
return reply.status(401).send({ error: 'Unauthorized' });
|
|
490
|
+
return reply.send({ tokens: authService.listApiTokens(user.id) });
|
|
491
|
+
});
|
|
492
|
+
// DELETE /api/auth/tokens/:id — revoke one of the user's own tokens.
|
|
493
|
+
fastify.delete('/api/auth/tokens/:id', async (req, reply) => {
|
|
494
|
+
const user = requireUser(req, authService);
|
|
495
|
+
if (!user)
|
|
496
|
+
return reply.status(401).send({ error: 'Unauthorized' });
|
|
497
|
+
const tokenId = parseInt(req.params.id, 10);
|
|
498
|
+
if (isNaN(tokenId))
|
|
499
|
+
return reply.status(400).send({ error: 'Invalid token id' });
|
|
500
|
+
const ok = authService.revokeApiToken(tokenId, user.id);
|
|
501
|
+
if (!ok)
|
|
502
|
+
return reply.status(404).send({ error: 'Token not found' });
|
|
503
|
+
return reply.send({ ok: true });
|
|
123
504
|
});
|
|
124
505
|
// GET /api/auth/seed — export auth seed data (admin only, for remote pull)
|
|
506
|
+
// Phase 3: sanitized via the same registry-driven helper as
|
|
507
|
+
// /api/config/bundle. jwtSecret + deprecated apiKey are dropped before
|
|
508
|
+
// the response leaves the trust boundary.
|
|
125
509
|
fastify.get('/api/auth/seed', async (req, reply) => {
|
|
126
|
-
const admin =
|
|
510
|
+
const admin = requireOwner(req, authService);
|
|
127
511
|
if (!admin)
|
|
128
|
-
return reply.status(403).send({ error: '
|
|
129
|
-
|
|
512
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
513
|
+
const { sanitizeAuthSeed } = await import('../../core/secrets/bundle.js');
|
|
514
|
+
return reply.send(sanitizeAuthSeed(authService.getSeedData()));
|
|
515
|
+
});
|
|
516
|
+
// POST /api/auth/transfer-ownership — transfer ownership to another user (owner only).
|
|
517
|
+
// Accepts cookie OR Bearer sg_ token via requireUser (the CLI calls this
|
|
518
|
+
// through `studiograph admin transfer-ownership`).
|
|
519
|
+
fastify.post('/api/auth/transfer-ownership', async (req, reply) => {
|
|
520
|
+
const user = requireUser(req, authService);
|
|
521
|
+
if (!user)
|
|
522
|
+
return reply.status(401).send({ error: 'Unauthorized' });
|
|
523
|
+
if (user.role !== 'owner')
|
|
524
|
+
return reply.status(403).send({ error: 'Only the workspace owner can transfer ownership' });
|
|
525
|
+
const { targetUserId } = req.body;
|
|
526
|
+
if (!targetUserId)
|
|
527
|
+
return reply.status(400).send({ error: 'targetUserId is required' });
|
|
528
|
+
try {
|
|
529
|
+
authService.transferOwnership(user.id, targetUserId);
|
|
530
|
+
return reply.send({ ok: true });
|
|
531
|
+
}
|
|
532
|
+
catch (err) {
|
|
533
|
+
return reply.status(400).send({ error: err.message });
|
|
534
|
+
}
|
|
130
535
|
});
|
|
131
536
|
// POST /api/auth/login — authenticate and set session cookie
|
|
132
537
|
fastify.post('/api/auth/login', async (req, reply) => {
|
|
538
|
+
if (managedCloudAuthConfig().enabled) {
|
|
539
|
+
return reply.status(403).send({ error: 'Use Studiograph Cloud to sign in to this managed workspace' });
|
|
540
|
+
}
|
|
133
541
|
const { email, password } = req.body;
|
|
134
542
|
if (!email || !password) {
|
|
135
543
|
return reply.status(400).send({ error: 'Email and password are required' });
|
|
@@ -155,8 +563,8 @@ export async function registerAuthApiRoutes(fastify, authService, workspaceName)
|
|
|
155
563
|
maxAge: 7 * 24 * 60 * 60, // 7 days
|
|
156
564
|
});
|
|
157
565
|
// Include the token in the response body when requested via
|
|
158
|
-
// X-Return-Token header
|
|
159
|
-
//
|
|
566
|
+
// X-Return-Token header for API clients that can't use cookies
|
|
567
|
+
// across origins.
|
|
160
568
|
const returnToken = req.headers['x-return-token'] === '1';
|
|
161
569
|
return reply.send({
|
|
162
570
|
user: result.user,
|
|
@@ -164,37 +572,83 @@ export async function registerAuthApiRoutes(fastify, authService, workspaceName)
|
|
|
164
572
|
});
|
|
165
573
|
});
|
|
166
574
|
// POST /api/auth/logout — clear session cookie
|
|
167
|
-
fastify.post('/api/auth/logout', async (
|
|
575
|
+
fastify.post('/api/auth/logout', async (req, reply) => {
|
|
576
|
+
const cloudAuth = managedCloudAuthConfig();
|
|
168
577
|
reply.setCookie('__sg_token', '', {
|
|
169
578
|
path: '/',
|
|
170
579
|
httpOnly: true,
|
|
171
580
|
sameSite: 'strict',
|
|
172
581
|
maxAge: 0,
|
|
173
582
|
});
|
|
174
|
-
return reply.send({
|
|
583
|
+
return reply.send({
|
|
584
|
+
ok: true,
|
|
585
|
+
logoutUrl: cloudAuth.enabled
|
|
586
|
+
? managedCloudLogoutUrl(cloudAuth, managedLogoutReturnTo(req))
|
|
587
|
+
: undefined,
|
|
588
|
+
});
|
|
175
589
|
});
|
|
176
|
-
// GET /api/auth/me — verify current session
|
|
590
|
+
// GET /api/auth/me — verify current session. Also resolves the user's
|
|
591
|
+
// linked person entity (the auth↔person bridge) so the client gets both
|
|
592
|
+
// identifiers in one round-trip. `personRef` is null when the user has
|
|
593
|
+
// no linked entity (legacy, unprovisioned, or explicitly unlinked) OR
|
|
594
|
+
// when the linked entity lives in a repo the user no longer has read
|
|
595
|
+
// access to (would leak repo existence otherwise — see access-control).
|
|
177
596
|
fastify.get('/api/auth/me', async (req, reply) => {
|
|
178
|
-
|
|
179
|
-
|
|
597
|
+
// Resolve from the cookie JWT OR Authorization: Bearer (JWT / sg_ API
|
|
598
|
+
// token) via the shared requireUser helper. The global auth hook skips
|
|
599
|
+
// /api/auth/*, so without this the boot session check only honored the
|
|
600
|
+
// web cookie and rejected API-token callers (CLI, automation, the
|
|
601
|
+
// headless browser) even though they authenticate everywhere else.
|
|
602
|
+
const user = requireUser(req, authService);
|
|
603
|
+
if (!user) {
|
|
180
604
|
return reply.status(401).send({ error: 'Not authenticated' });
|
|
181
605
|
}
|
|
606
|
+
const rawRef = findPersonRefForUser(workspaceManager, user.handle);
|
|
607
|
+
const personRef = rawRef && access.hasRepoAccess(user, rawRef.repo, workspaceManager, authService)
|
|
608
|
+
? rawRef
|
|
609
|
+
: null;
|
|
610
|
+
return reply.send({ user, personRef });
|
|
611
|
+
});
|
|
612
|
+
// PATCH /api/auth/me — update current user's profile
|
|
613
|
+
fastify.patch('/api/auth/me', async (req, reply) => {
|
|
614
|
+
const token = req.cookies?.['__sg_token'];
|
|
615
|
+
if (!token)
|
|
616
|
+
return reply.status(401).send({ error: 'Not authenticated' });
|
|
182
617
|
const user = authService.verifyToken(token);
|
|
183
|
-
if (!user)
|
|
618
|
+
if (!user)
|
|
184
619
|
return reply.status(401).send({ error: 'Not authenticated' });
|
|
620
|
+
const { displayName, email, newPassword } = req.body;
|
|
621
|
+
if (newPassword) {
|
|
622
|
+
authService.updatePassword(user.email, newPassword);
|
|
185
623
|
}
|
|
186
|
-
|
|
624
|
+
const updated = authService.updateProfile(user.id, {
|
|
625
|
+
displayName: displayName !== undefined ? displayName : undefined,
|
|
626
|
+
email: email !== undefined ? email : undefined,
|
|
627
|
+
});
|
|
628
|
+
return reply.send({ user: updated });
|
|
629
|
+
});
|
|
630
|
+
// GET /api/auth/colors — accent colors for all users (for avatar rendering)
|
|
631
|
+
fastify.get('/api/auth/colors', async (_req, reply) => {
|
|
632
|
+
return reply.send({ colors: authService.getAllAccentColors() });
|
|
187
633
|
});
|
|
188
634
|
// GET /api/auth/status — public endpoint for login page
|
|
189
|
-
fastify.get('/api/auth/status', async (
|
|
635
|
+
fastify.get('/api/auth/status', async (req, reply) => {
|
|
636
|
+
const cloudAuth = managedCloudAuthConfig();
|
|
190
637
|
return reply.send({
|
|
191
638
|
authEnabled: authService.hasUsers(),
|
|
192
639
|
userCount: authService.getUserCount(),
|
|
193
640
|
workspaceName: workspaceName || undefined,
|
|
641
|
+
managedAuth: cloudAuth.enabled,
|
|
642
|
+
cloudUrl: cloudAuth.cloudUrl || undefined,
|
|
643
|
+
managedAuthLoginUrl: managedCloudLoginUrl(cloudAuth) || undefined,
|
|
644
|
+
managedAuthLogoutUrl: managedCloudLogoutUrl(cloudAuth, managedLogoutReturnTo(req)) || undefined,
|
|
194
645
|
});
|
|
195
646
|
});
|
|
196
647
|
// POST /api/auth/setup — create the first admin account (only works when no users exist)
|
|
197
648
|
fastify.post('/api/auth/setup', async (req, reply) => {
|
|
649
|
+
if (managedCloudAuthConfig().enabled) {
|
|
650
|
+
return reply.status(403).send({ error: 'Managed workspaces are set up from Studiograph Cloud' });
|
|
651
|
+
}
|
|
198
652
|
if (authService.hasUsers()) {
|
|
199
653
|
return reply.status(403).send({ error: 'Setup already completed' });
|
|
200
654
|
}
|
|
@@ -203,7 +657,34 @@ export async function registerAuthApiRoutes(fastify, authService, workspaceName)
|
|
|
203
657
|
return reply.status(400).send({ error: 'Email and password are required' });
|
|
204
658
|
}
|
|
205
659
|
try {
|
|
206
|
-
const user = authService.createUser(email, password, displayName || email.split('@')[0], '
|
|
660
|
+
const user = authService.createUser(email, password, displayName || email.split('@')[0], 'owner');
|
|
661
|
+
await ensurePersonalFolder(new Workspace(workspacePath), authService, user);
|
|
662
|
+
workspaceManager.reloadConfig();
|
|
663
|
+
// Grant the first owner folder-admin on every existing team folder.
|
|
664
|
+
// Without this, folders scaffolded by `studiograph init` before any
|
|
665
|
+
// user existed end up with zero folder_access rows, and
|
|
666
|
+
// `getAccessibleRepos()` filters them out of the sidebar — the first
|
|
667
|
+
// owner then sees an empty workspace despite the files being on disk.
|
|
668
|
+
// Personal folders are handled by ensurePersonalFolder above; skipping
|
|
669
|
+
// them here avoids granting the owner access to other users' personals.
|
|
670
|
+
for (const repo of workspaceManager.getAllRepoConfigs()) {
|
|
671
|
+
if (repo.personal)
|
|
672
|
+
continue;
|
|
673
|
+
authService.grantFolderAccess(user.id, repo.name, 'admin');
|
|
674
|
+
}
|
|
675
|
+
// First-owner bootstrap: auto-provision their person entity in the
|
|
676
|
+
// first non-private repo (the same one we just granted them admin on).
|
|
677
|
+
// Non-fatal — missing team repo logs a warning, doesn't block setup.
|
|
678
|
+
let setupBridgeWarning;
|
|
679
|
+
try {
|
|
680
|
+
const r = await ensurePersonForUser(workspaceManager, authService, user, authUserToGitUser(user));
|
|
681
|
+
if (r.action === 'skipped')
|
|
682
|
+
setupBridgeWarning = `Person record not auto-provisioned (${r.reason}). Configure team_repo in workspace settings to enable cross-repo "My Tasks" + mentions.`;
|
|
683
|
+
}
|
|
684
|
+
catch (err) {
|
|
685
|
+
console.warn('[auth] ensurePersonForUser failed during setup:', err?.message ?? err);
|
|
686
|
+
setupBridgeWarning = `Person record provisioning failed: ${err?.message ?? err}.`;
|
|
687
|
+
}
|
|
207
688
|
const result = authService.authenticate(email, password);
|
|
208
689
|
if (!result) {
|
|
209
690
|
return reply.status(500).send({ error: 'Failed to authenticate after setup' });
|
|
@@ -216,7 +697,7 @@ export async function registerAuthApiRoutes(fastify, authService, workspaceName)
|
|
|
216
697
|
secure,
|
|
217
698
|
maxAge: 7 * 24 * 60 * 60,
|
|
218
699
|
});
|
|
219
|
-
return reply.send({ user });
|
|
700
|
+
return reply.send({ user, ...(setupBridgeWarning ? { bridgeWarning: setupBridgeWarning } : {}) });
|
|
220
701
|
}
|
|
221
702
|
catch (err) {
|
|
222
703
|
return reply.status(400).send({ error: err.message });
|