@segmentstream/ontology 0.0.0-stage → 0.92.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/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README.md +1655 -2
- package/dist/action.d.ts +193 -0
- package/dist/action.js +41 -0
- package/dist/agent-chat.d.ts +44 -0
- package/dist/agent-chat.js +91 -0
- package/dist/agent-task-contract.d.ts +64 -0
- package/dist/agent-task-contract.js +15 -0
- package/dist/agent-task.d.ts +39 -0
- package/dist/agent-task.js +112 -0
- package/dist/analyze.d.ts +215 -0
- package/dist/analyze.js +2438 -0
- package/dist/app-feedback.d.ts +167 -0
- package/dist/app-feedback.js +176 -0
- package/dist/authoring-input.d.ts +3 -0
- package/dist/authoring-input.js +107 -0
- package/dist/authoring-names.d.ts +4 -0
- package/dist/authoring-names.js +13 -0
- package/dist/authoring-records.d.ts +35 -0
- package/dist/authoring-records.js +264 -0
- package/dist/authoring.d.ts +15 -0
- package/dist/authoring.js +331 -0
- package/dist/bin/check.d.ts +30 -0
- package/dist/bin/check.js +99 -0
- package/dist/bin/load.d.ts +48 -0
- package/dist/bin/load.js +139 -0
- package/dist/bin/main.d.ts +31 -0
- package/dist/bin/main.js +121 -0
- package/dist/bin/migrate.d.ts +57 -0
- package/dist/bin/migrate.js +170 -0
- package/dist/bin/output.d.ts +31 -0
- package/dist/bin/output.js +84 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +31 -0
- package/dist/blob.d.ts +52 -0
- package/dist/blob.js +87 -0
- package/dist/channel-session.d.ts +16 -0
- package/dist/channel-session.js +16 -0
- package/dist/chat.d.ts +43 -0
- package/dist/chat.js +34 -0
- package/dist/confirmation.d.ts +46 -0
- package/dist/confirmation.js +41 -0
- package/dist/connection.d.ts +213 -0
- package/dist/connection.js +289 -0
- package/dist/deployment.d.ts +35 -0
- package/dist/deployment.js +76 -0
- package/dist/diagnostics.d.ts +27 -0
- package/dist/diagnostics.js +106 -0
- package/dist/emails.d.ts +70 -0
- package/dist/emails.js +221 -0
- package/dist/entity.d.ts +331 -0
- package/dist/entity.js +153 -0
- package/dist/errors.d.ts +154 -0
- package/dist/errors.js +109 -0
- package/dist/feedback-config.d.ts +24 -0
- package/dist/feedback-config.js +126 -0
- package/dist/files.d.ts +39 -0
- package/dist/files.js +4 -0
- package/dist/groups.d.ts +95 -0
- package/dist/groups.js +280 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.js +70 -0
- package/dist/internal/diagnostics.js +594 -0
- package/dist/legacy.d.ts +160 -0
- package/dist/legacy.js +270 -0
- package/dist/manifest-compatibility.d.ts +8 -0
- package/dist/manifest-compatibility.js +87 -0
- package/dist/manifest.d.ts +3329 -0
- package/dist/manifest.js +757 -0
- package/dist/me.d.ts +46 -0
- package/dist/me.js +109 -0
- package/dist/metric-filters.d.ts +48 -0
- package/dist/metric-filters.js +252 -0
- package/dist/metric-routes.d.ts +132 -0
- package/dist/metric-routes.js +498 -0
- package/dist/metric.d.ts +172 -0
- package/dist/metric.js +132 -0
- package/dist/migrate/apply.d.ts +94 -0
- package/dist/migrate/apply.js +526 -0
- package/dist/migrate/errors.d.ts +46 -0
- package/dist/migrate/errors.js +38 -0
- package/dist/migrate/index.d.ts +10 -0
- package/dist/migrate/index.js +7 -0
- package/dist/migrate/model.d.ts +2311 -0
- package/dist/migrate/model.js +148 -0
- package/dist/migrate/plan.d.ts +51 -0
- package/dist/migrate/plan.js +1856 -0
- package/dist/migrate/preview.d.ts +13 -0
- package/dist/migrate/preview.js +65 -0
- package/dist/migrate/storage.d.ts +226 -0
- package/dist/migrate/storage.js +774 -0
- package/dist/model-metrics.d.ts +22 -0
- package/dist/model-metrics.js +545 -0
- package/dist/names.d.ts +49 -0
- package/dist/names.js +110 -0
- package/dist/navigation-artifact.d.ts +13 -0
- package/dist/navigation-artifact.js +11 -0
- package/dist/navigation-catalog.d.ts +55 -0
- package/dist/navigation-catalog.js +297 -0
- package/dist/nitro-navigation.d.ts +3 -0
- package/dist/nitro-navigation.js +64 -0
- package/dist/nitro-workflows.d.ts +108 -0
- package/dist/nitro-workflows.js +286 -0
- package/dist/nitro.d.ts +40 -0
- package/dist/nitro.js +50 -0
- package/dist/ontology.d.ts +41 -0
- package/dist/ontology.js +46 -0
- package/dist/permissions.d.ts +198 -0
- package/dist/permissions.js +272 -0
- package/dist/property.d.ts +188 -0
- package/dist/property.js +301 -0
- package/dist/query.d.ts +245 -0
- package/dist/query.js +615 -0
- package/dist/relationship.d.ts +99 -0
- package/dist/relationship.js +33 -0
- package/dist/render.d.ts +81 -0
- package/dist/render.js +512 -0
- package/dist/replication/baseline.d.ts +51 -0
- package/dist/replication/baseline.js +215 -0
- package/dist/replication/bigquery.d.ts +37 -0
- package/dist/replication/bigquery.js +211 -0
- package/dist/replication/coverage.d.ts +14 -0
- package/dist/replication/coverage.js +53 -0
- package/dist/replication/evolution.d.ts +25 -0
- package/dist/replication/evolution.js +184 -0
- package/dist/replication/identities.d.ts +6 -0
- package/dist/replication/identities.js +47 -0
- package/dist/replication/legacy-baseline.d.ts +27 -0
- package/dist/replication/legacy-baseline.js +109 -0
- package/dist/replication/legacy-store.d.ts +19 -0
- package/dist/replication/legacy-store.js +63 -0
- package/dist/replication/lineage.d.ts +36 -0
- package/dist/replication/lineage.js +72 -0
- package/dist/replication/migrate.d.ts +21 -0
- package/dist/replication/migrate.js +84 -0
- package/dist/replication/model.d.ts +52 -0
- package/dist/replication/model.js +99 -0
- package/dist/replication/scans.d.ts +34 -0
- package/dist/replication/scans.js +158 -0
- package/dist/replication/schema.d.ts +11 -0
- package/dist/replication/schema.js +226 -0
- package/dist/replication/shadow-schema.d.ts +4 -0
- package/dist/replication/shadow-schema.js +61 -0
- package/dist/replication/shadow.d.ts +127 -0
- package/dist/replication/shadow.js +614 -0
- package/dist/replication/source-replacement.d.ts +33 -0
- package/dist/replication/source-replacement.js +76 -0
- package/dist/replication/store.d.ts +36 -0
- package/dist/replication/store.js +382 -0
- package/dist/replication/transaction.d.ts +23 -0
- package/dist/replication/transaction.js +88 -0
- package/dist/role.d.ts +61 -0
- package/dist/role.js +76 -0
- package/dist/runtime/action-deadlocks.d.ts +21 -0
- package/dist/runtime/action-deadlocks.js +130 -0
- package/dist/runtime/action-transactions.d.ts +35 -0
- package/dist/runtime/action-transactions.js +54 -0
- package/dist/runtime/agent-counters.d.ts +26 -0
- package/dist/runtime/agent-counters.js +98 -0
- package/dist/runtime/agent-tasks.d.ts +63 -0
- package/dist/runtime/agent-tasks.js +120 -0
- package/dist/runtime/agents.d.ts +15 -0
- package/dist/runtime/agents.js +457 -0
- package/dist/runtime/batch-diagnostics.d.ts +22 -0
- package/dist/runtime/batch-diagnostics.js +89 -0
- package/dist/runtime/batch.d.ts +52 -0
- package/dist/runtime/batch.js +534 -0
- package/dist/runtime/channel-session-revocation.d.ts +3 -0
- package/dist/runtime/channel-session-revocation.js +5 -0
- package/dist/runtime/channel-sessions.d.ts +4 -0
- package/dist/runtime/channel-sessions.js +61 -0
- package/dist/runtime/confirmations.d.ts +29 -0
- package/dist/runtime/confirmations.js +57 -0
- package/dist/runtime/cursor.d.ts +23 -0
- package/dist/runtime/cursor.js +100 -0
- package/dist/runtime/deployment.d.ts +7 -0
- package/dist/runtime/deployment.js +4 -0
- package/dist/runtime/errors.d.ts +118 -0
- package/dist/runtime/errors.js +109 -0
- package/dist/runtime/federation-tables.d.ts +2 -0
- package/dist/runtime/federation-tables.js +20 -0
- package/dist/runtime/federation.d.ts +42 -0
- package/dist/runtime/federation.js +222 -0
- package/dist/runtime/files.d.ts +39 -0
- package/dist/runtime/files.js +44 -0
- package/dist/runtime/generated-actions.d.ts +37 -0
- package/dist/runtime/generated-actions.js +307 -0
- package/dist/runtime/history.d.ts +91 -0
- package/dist/runtime/history.js +77 -0
- package/dist/runtime/ids.d.ts +6 -0
- package/dist/runtime/ids.js +39 -0
- package/dist/runtime/member-tables.d.ts +8 -0
- package/dist/runtime/member-tables.js +33 -0
- package/dist/runtime/member-writes.d.ts +78 -0
- package/dist/runtime/member-writes.js +202 -0
- package/dist/runtime/metric-query.d.ts +19 -0
- package/dist/runtime/metric-query.js +411 -0
- package/dist/runtime/model.d.ts +67 -0
- package/dist/runtime/model.js +150 -0
- package/dist/runtime/new-user-hook.d.ts +6 -0
- package/dist/runtime/new-user-hook.js +37 -0
- package/dist/runtime/oauth.d.ts +9 -0
- package/dist/runtime/oauth.js +299 -0
- package/dist/runtime/pipeline.d.ts +155 -0
- package/dist/runtime/pipeline.js +597 -0
- package/dist/runtime/postgres-tls.d.ts +10 -0
- package/dist/runtime/postgres-tls.js +14 -0
- package/dist/runtime/principals.d.ts +302 -0
- package/dist/runtime/principals.js +1307 -0
- package/dist/runtime/reads.d.ts +55 -0
- package/dist/runtime/reads.js +313 -0
- package/dist/runtime/records.d.ts +42 -0
- package/dist/runtime/records.js +245 -0
- package/dist/runtime/resolve-agent-identity.d.ts +6 -0
- package/dist/runtime/resolve-agent-identity.js +181 -0
- package/dist/runtime/service-binding.d.ts +18 -0
- package/dist/runtime/service-binding.js +266 -0
- package/dist/runtime/sign-in-links.d.ts +68 -0
- package/dist/runtime/sign-in-links.js +147 -0
- package/dist/runtime/sql-runtime.d.ts +131 -0
- package/dist/runtime/sql-runtime.js +362 -0
- package/dist/runtime/statement.d.ts +18 -0
- package/dist/runtime/statement.js +31 -0
- package/dist/runtime/user-identities.d.ts +66 -0
- package/dist/runtime/user-identities.js +106 -0
- package/dist/runtime/user-identity-sql.d.ts +86 -0
- package/dist/runtime/user-identity-sql.js +297 -0
- package/dist/runtime/user-roles.d.ts +16 -0
- package/dist/runtime/user-roles.js +32 -0
- package/dist/runtime/validation.d.ts +16 -0
- package/dist/runtime/validation.js +26 -0
- package/dist/runtime/where.d.ts +57 -0
- package/dist/runtime/where.js +404 -0
- package/dist/runtime/workflow-admission.d.ts +49 -0
- package/dist/runtime/workflow-admission.js +92 -0
- package/dist/runtime/workflow-argument-codec.d.ts +10 -0
- package/dist/runtime/workflow-argument-codec.js +120 -0
- package/dist/runtime/workflow-arguments.d.ts +17 -0
- package/dist/runtime/workflow-arguments.js +99 -0
- package/dist/runtime/workflow-starts.d.ts +203 -0
- package/dist/runtime/workflow-starts.js +493 -0
- package/dist/runtime/workflow-users.d.ts +9 -0
- package/dist/runtime/workflow-users.js +17 -0
- package/dist/runtime/workload.d.ts +25 -0
- package/dist/runtime/workload.js +24 -0
- package/dist/runtime/writes.d.ts +108 -0
- package/dist/runtime/writes.js +491 -0
- package/dist/runtime-source.d.ts +22 -0
- package/dist/runtime-source.js +28 -0
- package/dist/runtime.d.ts +310 -0
- package/dist/runtime.js +31 -0
- package/dist/server.d.ts +23 -0
- package/dist/server.js +107 -0
- package/dist/service/agent/attachments.d.ts +33 -0
- package/dist/service/agent/attachments.js +228 -0
- package/dist/service/agent/authentication.d.ts +22 -0
- package/dist/service/agent/authentication.js +58 -0
- package/dist/service/agent/confirmations.d.ts +5 -0
- package/dist/service/agent/confirmations.js +73 -0
- package/dist/service/agent/conversation-routes.d.ts +14 -0
- package/dist/service/agent/conversation-routes.js +45 -0
- package/dist/service/agent/conversations.d.ts +40 -0
- package/dist/service/agent/conversations.js +69 -0
- package/dist/service/agent/files.d.ts +12 -0
- package/dist/service/agent/files.js +69 -0
- package/dist/service/agent/protocol.d.ts +90 -0
- package/dist/service/agent/protocol.js +114 -0
- package/dist/service/agent/server.d.ts +28 -0
- package/dist/service/agent/server.js +374 -0
- package/dist/service/agent/task-caller.d.ts +21 -0
- package/dist/service/agent/task-caller.js +35 -0
- package/dist/service/agent/task-start.d.ts +53 -0
- package/dist/service/agent/task-start.js +161 -0
- package/dist/service/agent/tasks.d.ts +40 -0
- package/dist/service/agent/tasks.js +155 -0
- package/dist/service/api.d.ts +50 -0
- package/dist/service/api.js +288 -0
- package/dist/service/authentication.d.ts +227 -0
- package/dist/service/authentication.js +767 -0
- package/dist/service/caller-context.d.ts +24 -0
- package/dist/service/caller-context.js +6 -0
- package/dist/service/catalog.d.ts +42 -0
- package/dist/service/catalog.js +66 -0
- package/dist/service/channel/provider.d.ts +10 -0
- package/dist/service/channel/provider.js +1 -0
- package/dist/service/channel/providers/telegram.d.ts +18 -0
- package/dist/service/channel/providers/telegram.js +108 -0
- package/dist/service/channel/sessions.d.ts +5 -0
- package/dist/service/channel/sessions.js +53 -0
- package/dist/service/channel/sign-in.d.ts +7 -0
- package/dist/service/channel/sign-in.js +78 -0
- package/dist/service/chat/archive.d.ts +64 -0
- package/dist/service/chat/archive.js +62 -0
- package/dist/service/chat/attribution.d.ts +26 -0
- package/dist/service/chat/attribution.js +28 -0
- package/dist/service/chat/delivery.d.ts +18 -0
- package/dist/service/chat/delivery.js +251 -0
- package/dist/service/chat/diagnostics.d.ts +2 -0
- package/dist/service/chat/diagnostics.js +35 -0
- package/dist/service/chat/envelope.d.ts +96 -0
- package/dist/service/chat/envelope.js +39 -0
- package/dist/service/chat/idempotency.d.ts +19 -0
- package/dist/service/chat/idempotency.js +37 -0
- package/dist/service/chat/providers/telegram.d.ts +36 -0
- package/dist/service/chat/providers/telegram.js +133 -0
- package/dist/service/chat/reads.d.ts +25 -0
- package/dist/service/chat/reads.js +75 -0
- package/dist/service/chat/resolve.d.ts +34 -0
- package/dist/service/chat/resolve.js +150 -0
- package/dist/service/chat/routes.d.ts +23 -0
- package/dist/service/chat/routes.js +75 -0
- package/dist/service/chat/schemas.d.ts +43 -0
- package/dist/service/chat/schemas.js +31 -0
- package/dist/service/config.d.ts +218 -0
- package/dist/service/config.js +265 -0
- package/dist/service/connection-stream.d.ts +10 -0
- package/dist/service/connection-stream.js +191 -0
- package/dist/service/connections.d.ts +60 -0
- package/dist/service/connections.js +271 -0
- package/dist/service/decisions.d.ts +35 -0
- package/dist/service/decisions.js +63 -0
- package/dist/service/descriptions.d.ts +8 -0
- package/dist/service/descriptions.js +20 -0
- package/dist/service/discovery-schemas.d.ts +92 -0
- package/dist/service/discovery-schemas.js +59 -0
- package/dist/service/discovery-search.d.ts +30 -0
- package/dist/service/discovery-search.js +95 -0
- package/dist/service/discovery.d.ts +37 -0
- package/dist/service/discovery.js +436 -0
- package/dist/service/docs.d.ts +9 -0
- package/dist/service/docs.js +197 -0
- package/dist/service/errors.d.ts +145 -0
- package/dist/service/errors.js +704 -0
- package/dist/service/federation-provider.d.ts +36 -0
- package/dist/service/federation-provider.js +110 -0
- package/dist/service/federation-server.d.ts +20 -0
- package/dist/service/federation-server.js +249 -0
- package/dist/service/federation-status.d.ts +40 -0
- package/dist/service/federation-status.js +151 -0
- package/dist/service/handlers.d.ts +18 -0
- package/dist/service/handlers.js +287 -0
- package/dist/service/mcp/confirmation.d.ts +68 -0
- package/dist/service/mcp/confirmation.js +178 -0
- package/dist/service/mcp/find-input.d.ts +12 -0
- package/dist/service/mcp/find-input.js +122 -0
- package/dist/service/mcp/input-schema.d.ts +6 -0
- package/dist/service/mcp/input-schema.js +126 -0
- package/dist/service/mcp/listing.d.ts +26 -0
- package/dist/service/mcp/listing.js +92 -0
- package/dist/service/mcp/metric-tools.d.ts +85 -0
- package/dist/service/mcp/metric-tools.js +258 -0
- package/dist/service/mcp/request-log.d.ts +5 -0
- package/dist/service/mcp/request-log.js +53 -0
- package/dist/service/mcp/runtime-policy.d.ts +27 -0
- package/dist/service/mcp/runtime-policy.js +62 -0
- package/dist/service/mcp/server.d.ts +52 -0
- package/dist/service/mcp/server.js +861 -0
- package/dist/service/mcp/tools.d.ts +99 -0
- package/dist/service/mcp/tools.js +938 -0
- package/dist/service/member-file-routes.d.ts +22 -0
- package/dist/service/member-file-routes.js +52 -0
- package/dist/service/member-files.d.ts +245 -0
- package/dist/service/member-files.js +258 -0
- package/dist/service/metric-query-platform.d.ts +77 -0
- package/dist/service/metric-query-platform.js +198 -0
- package/dist/service/metric-query-scopes.d.ts +43 -0
- package/dist/service/metric-query-scopes.js +147 -0
- package/dist/service/metric-query.d.ts +48 -0
- package/dist/service/metric-query.js +200 -0
- package/dist/service/name-suggestions.d.ts +3 -0
- package/dist/service/name-suggestions.js +38 -0
- package/dist/service/navigation-schemas.d.ts +80 -0
- package/dist/service/navigation-schemas.js +49 -0
- package/dist/service/navigation.d.ts +20 -0
- package/dist/service/navigation.js +165 -0
- package/dist/service/oauth/protocol.d.ts +70 -0
- package/dist/service/oauth/protocol.js +157 -0
- package/dist/service/oauth/refresh-replay.d.ts +2 -0
- package/dist/service/oauth/refresh-replay.js +20 -0
- package/dist/service/oauth/server.d.ts +28 -0
- package/dist/service/oauth/server.js +769 -0
- package/dist/service/operations.d.ts +170 -0
- package/dist/service/operations.js +392 -0
- package/dist/service/plan.d.ts +57 -0
- package/dist/service/plan.js +96 -0
- package/dist/service/rate-limit.d.ts +22 -0
- package/dist/service/rate-limit.js +52 -0
- package/dist/service/record-reads.d.ts +21 -0
- package/dist/service/record-reads.js +155 -0
- package/dist/service/replication.d.ts +5 -0
- package/dist/service/replication.js +39 -0
- package/dist/service/runtime-contract.d.ts +508 -0
- package/dist/service/runtime-contract.js +18 -0
- package/dist/service/runtime-identity.d.ts +71 -0
- package/dist/service/runtime-identity.js +122 -0
- package/dist/service/schemas.d.ts +961 -0
- package/dist/service/schemas.js +639 -0
- package/dist/service/service.d.ts +21 -0
- package/dist/service/service.js +526 -0
- package/dist/service/warehouse-platform.d.ts +17 -0
- package/dist/service/warehouse-platform.js +122 -0
- package/dist/service/warehouse-query.d.ts +24 -0
- package/dist/service/warehouse-query.js +280 -0
- package/dist/service/webhooks.d.ts +106 -0
- package/dist/service/webhooks.js +233 -0
- package/dist/service/workflow-admission-provider.d.ts +31 -0
- package/dist/service/workflow-admission-provider.js +205 -0
- package/dist/service/workflow-argument-serialization.d.ts +2 -0
- package/dist/service/workflow-argument-serialization.js +14 -0
- package/dist/service/workflow-callback.d.ts +22 -0
- package/dist/service/workflow-callback.js +75 -0
- package/dist/service/workflow-deployment.d.ts +8 -0
- package/dist/service/workflow-deployment.js +131 -0
- package/dist/service/workflow-diagnostics.d.ts +23 -0
- package/dist/service/workflow-diagnostics.js +263 -0
- package/dist/service/workflow-errors.d.ts +26 -0
- package/dist/service/workflow-errors.js +181 -0
- package/dist/service/workflow-logging.d.ts +2 -0
- package/dist/service/workflow-logging.js +50 -0
- package/dist/service/workflow-queue-fence.d.ts +6 -0
- package/dist/service/workflow-queue-fence.js +66 -0
- package/dist/service/workflows.d.ts +200 -0
- package/dist/service/workflows.js +1549 -0
- package/dist/sign-in.d.ts +58 -0
- package/dist/sign-in.js +57 -0
- package/dist/source.d.ts +30 -0
- package/dist/source.js +107 -0
- package/dist/start-recovery-contract.d.ts +49 -0
- package/dist/start-recovery-contract.js +26 -0
- package/dist/start-recovery.d.ts +27 -0
- package/dist/start-recovery.js +81 -0
- package/dist/storage/api.d.ts +4 -0
- package/dist/storage/api.js +40 -0
- package/dist/storage/attachments.d.ts +146 -0
- package/dist/storage/attachments.js +733 -0
- package/dist/storage/authorization.d.ts +38 -0
- package/dist/storage/authorization.js +83 -0
- package/dist/storage/file-access.d.ts +17 -0
- package/dist/storage/file-access.js +8 -0
- package/dist/storage/limits.d.ts +12 -0
- package/dist/storage/limits.js +17 -0
- package/dist/storage/maintenance-auth.d.ts +20 -0
- package/dist/storage/maintenance-auth.js +24 -0
- package/dist/storage/maintenance.d.ts +11 -0
- package/dist/storage/maintenance.js +67 -0
- package/dist/storage/neon.d.ts +4 -0
- package/dist/storage/neon.js +318 -0
- package/dist/storage/operator.d.ts +11 -0
- package/dist/storage/operator.js +30 -0
- package/dist/storage/provider.d.ts +93 -0
- package/dist/storage/provider.js +36 -0
- package/dist/storage/sessions.d.ts +184 -0
- package/dist/storage/sessions.js +688 -0
- package/dist/storage/tables.d.ts +54 -0
- package/dist/storage/tables.js +205 -0
- package/dist/storage/transfers.d.ts +16 -0
- package/dist/storage/transfers.js +153 -0
- package/dist/storage/writes.d.ts +7 -0
- package/dist/storage/writes.js +88 -0
- package/dist/telegram.d.ts +35 -0
- package/dist/telegram.js +173 -0
- package/dist/user-identity.d.ts +28 -0
- package/dist/user-identity.js +106 -0
- package/dist/user.d.ts +75 -0
- package/dist/user.js +111 -0
- package/dist/warehouse-backed.d.ts +6 -0
- package/dist/warehouse-backed.js +495 -0
- package/dist/webhook-token.d.ts +11 -0
- package/dist/webhook-token.js +18 -0
- package/dist/webhooks.d.ts +40 -0
- package/dist/webhooks.js +55 -0
- package/dist/wire.d.ts +10 -0
- package/dist/wire.js +35 -0
- package/dist/workflow-runtime.d.ts +116 -0
- package/dist/workflow-runtime.js +109 -0
- package/dist/workflow-topics.d.ts +28 -0
- package/dist/workflow-topics.js +28 -0
- package/dist/workflow.d.ts +284 -0
- package/dist/workflow.js +259 -0
- package/dist/workflows.d.ts +24 -0
- package/dist/workflows.js +18 -0
- package/package.json +127 -4
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { toSnakeCase } from "../names.js";
|
|
2
|
+
/** Levenshtein distance, stopping once a match within two edits is impossible. */
|
|
3
|
+
function distance(left, right) {
|
|
4
|
+
if (Math.abs(left.length - right.length) > 2) {
|
|
5
|
+
return 3;
|
|
6
|
+
}
|
|
7
|
+
let previous = Array.from({ length: right.length + 1 }, (_, index) => index);
|
|
8
|
+
for (let row = 1; row <= left.length; row++) {
|
|
9
|
+
const current = [row];
|
|
10
|
+
for (let column = 1; column <= right.length; column++) {
|
|
11
|
+
current[column] = Math.min(previous[column] + 1, current[column - 1] + 1, previous[column - 1] + (left[row - 1] === right[column - 1] ? 0 : 1));
|
|
12
|
+
}
|
|
13
|
+
if (Math.min(...current) > 2) {
|
|
14
|
+
return 3;
|
|
15
|
+
}
|
|
16
|
+
previous = current;
|
|
17
|
+
}
|
|
18
|
+
return previous[right.length];
|
|
19
|
+
}
|
|
20
|
+
/** Candidates must already be filtered for this authenticated caller's visibility. */
|
|
21
|
+
export function suggestNames(name, candidates) {
|
|
22
|
+
const canonical = toSnakeCase(name);
|
|
23
|
+
if (candidates.includes(canonical)) {
|
|
24
|
+
return [canonical];
|
|
25
|
+
}
|
|
26
|
+
return [...new Set(candidates)]
|
|
27
|
+
.map((candidate) => ({ name: candidate, distance: distance(canonical, candidate) }))
|
|
28
|
+
.filter((candidate) => candidate.distance <= 2)
|
|
29
|
+
.sort((left, right) => left.distance - right.distance ||
|
|
30
|
+
(left.name < right.name ? -1 : left.name > right.name ? 1 : 0))
|
|
31
|
+
.slice(0, 3)
|
|
32
|
+
.map((candidate) => candidate.name);
|
|
33
|
+
}
|
|
34
|
+
export function suggestionDetail(detail, suggestions) {
|
|
35
|
+
return suggestions.length === 0
|
|
36
|
+
? detail
|
|
37
|
+
: `${detail} did you mean ${suggestions.map((name) => JSON.stringify(name)).join(" or ")}?`;
|
|
38
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
export declare const NavigationInput: Schema.Struct<{
|
|
3
|
+
readonly entity: Schema.optionalKey<Schema.String>;
|
|
4
|
+
readonly query: Schema.optionalKey<Schema.String>;
|
|
5
|
+
readonly after: Schema.optionalKey<Schema.String>;
|
|
6
|
+
readonly limit: Schema.optionalKey<Schema.Int>;
|
|
7
|
+
readonly expected_revision: Schema.optionalKey<Schema.String>;
|
|
8
|
+
}>;
|
|
9
|
+
export type NavigationInput = typeof NavigationInput.Type;
|
|
10
|
+
export declare const NavigationOutput: Schema.Struct<{
|
|
11
|
+
readonly revision: Schema.String;
|
|
12
|
+
readonly pages: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
|
|
13
|
+
readonly url: Schema.String;
|
|
14
|
+
readonly ref: Schema.String;
|
|
15
|
+
readonly route: Schema.String;
|
|
16
|
+
readonly title: Schema.String;
|
|
17
|
+
readonly description: Schema.String;
|
|
18
|
+
readonly entities: Schema.$Array<Schema.String>;
|
|
19
|
+
readonly parameters: Schema.$Array<Schema.Struct<{
|
|
20
|
+
readonly name: Schema.String;
|
|
21
|
+
readonly kind: Schema.Literals<readonly ["segment", "catch_all"]>;
|
|
22
|
+
readonly required: Schema.Boolean;
|
|
23
|
+
readonly description: Schema.optionalKey<Schema.String>;
|
|
24
|
+
}>>;
|
|
25
|
+
readonly query: Schema.$Record<Schema.String, Schema.String>;
|
|
26
|
+
}>, Schema.Struct<{
|
|
27
|
+
readonly url_pattern: Schema.String;
|
|
28
|
+
readonly ref: Schema.String;
|
|
29
|
+
readonly route: Schema.String;
|
|
30
|
+
readonly title: Schema.String;
|
|
31
|
+
readonly description: Schema.String;
|
|
32
|
+
readonly entities: Schema.$Array<Schema.String>;
|
|
33
|
+
readonly parameters: Schema.$Array<Schema.Struct<{
|
|
34
|
+
readonly name: Schema.String;
|
|
35
|
+
readonly kind: Schema.Literals<readonly ["segment", "catch_all"]>;
|
|
36
|
+
readonly required: Schema.Boolean;
|
|
37
|
+
readonly description: Schema.optionalKey<Schema.String>;
|
|
38
|
+
}>>;
|
|
39
|
+
readonly query: Schema.$Record<Schema.String, Schema.String>;
|
|
40
|
+
}>]>>;
|
|
41
|
+
readonly next_cursor: Schema.NullOr<Schema.String>;
|
|
42
|
+
}>;
|
|
43
|
+
export declare const NavigationToolOutput: Schema.Union<readonly [Schema.Struct<{
|
|
44
|
+
readonly revision: Schema.String;
|
|
45
|
+
readonly pages: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
|
|
46
|
+
readonly url: Schema.String;
|
|
47
|
+
readonly ref: Schema.String;
|
|
48
|
+
readonly route: Schema.String;
|
|
49
|
+
readonly title: Schema.String;
|
|
50
|
+
readonly description: Schema.String;
|
|
51
|
+
readonly entities: Schema.$Array<Schema.String>;
|
|
52
|
+
readonly parameters: Schema.$Array<Schema.Struct<{
|
|
53
|
+
readonly name: Schema.String;
|
|
54
|
+
readonly kind: Schema.Literals<readonly ["segment", "catch_all"]>;
|
|
55
|
+
readonly required: Schema.Boolean;
|
|
56
|
+
readonly description: Schema.optionalKey<Schema.String>;
|
|
57
|
+
}>>;
|
|
58
|
+
readonly query: Schema.$Record<Schema.String, Schema.String>;
|
|
59
|
+
}>, Schema.Struct<{
|
|
60
|
+
readonly url_pattern: Schema.String;
|
|
61
|
+
readonly ref: Schema.String;
|
|
62
|
+
readonly route: Schema.String;
|
|
63
|
+
readonly title: Schema.String;
|
|
64
|
+
readonly description: Schema.String;
|
|
65
|
+
readonly entities: Schema.$Array<Schema.String>;
|
|
66
|
+
readonly parameters: Schema.$Array<Schema.Struct<{
|
|
67
|
+
readonly name: Schema.String;
|
|
68
|
+
readonly kind: Schema.Literals<readonly ["segment", "catch_all"]>;
|
|
69
|
+
readonly required: Schema.Boolean;
|
|
70
|
+
readonly description: Schema.optionalKey<Schema.String>;
|
|
71
|
+
}>>;
|
|
72
|
+
readonly query: Schema.$Record<Schema.String, Schema.String>;
|
|
73
|
+
}>]>>;
|
|
74
|
+
readonly next_cursor: Schema.NullOr<Schema.String>;
|
|
75
|
+
}>, Schema.Top, Schema.Top, Schema.Struct<{
|
|
76
|
+
readonly error: Schema.Literals<readonly ["invalid_cursor", "page_catalog_version_mismatch", "page_catalog_unavailable"]>;
|
|
77
|
+
readonly detail: Schema.String;
|
|
78
|
+
readonly request_id: Schema.String;
|
|
79
|
+
readonly revision: Schema.optionalKey<Schema.String>;
|
|
80
|
+
}>]>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { ErrorSchemas } from "./schemas.js";
|
|
3
|
+
export const NavigationInput = Schema.Struct({
|
|
4
|
+
entity: Schema.optionalKey(Schema.String.check(Schema.isPattern(/^[a-z][a-z0-9_]*$/))),
|
|
5
|
+
query: Schema.optionalKey(Schema.String.check(Schema.makeFilter((value) => value.trim().length > 0 && Array.from(value).length <= 512
|
|
6
|
+
? true
|
|
7
|
+
: "Use a nonblank query of at most 512 Unicode code points.", { toJsonSchema: () => ({ minLength: 1, maxLength: 512, pattern: "\\S" }) }))),
|
|
8
|
+
after: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(16 * 1024))),
|
|
9
|
+
limit: Schema.optionalKey(Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 50 }))),
|
|
10
|
+
expected_revision: Schema.optionalKey(Schema.String.check(Schema.isPattern(/^sha256:[a-f0-9]{64}$/))),
|
|
11
|
+
});
|
|
12
|
+
const Page = {
|
|
13
|
+
ref: Schema.String,
|
|
14
|
+
route: Schema.String,
|
|
15
|
+
title: Schema.String,
|
|
16
|
+
description: Schema.String,
|
|
17
|
+
entities: Schema.Array(Schema.String),
|
|
18
|
+
parameters: Schema.Array(Schema.Struct({
|
|
19
|
+
name: Schema.String,
|
|
20
|
+
kind: Schema.Literals(["segment", "catch_all"]),
|
|
21
|
+
required: Schema.Boolean,
|
|
22
|
+
description: Schema.optionalKey(Schema.String),
|
|
23
|
+
})),
|
|
24
|
+
query: Schema.Record(Schema.String, Schema.String),
|
|
25
|
+
};
|
|
26
|
+
export const NavigationOutput = Schema.Struct({
|
|
27
|
+
revision: Schema.String,
|
|
28
|
+
pages: Schema.Array(Schema.Union([
|
|
29
|
+
Schema.Struct({ ...Page, url: Schema.String }),
|
|
30
|
+
Schema.Struct({ ...Page, url_pattern: Schema.String }),
|
|
31
|
+
])),
|
|
32
|
+
next_cursor: Schema.NullOr(Schema.String),
|
|
33
|
+
});
|
|
34
|
+
const NavigationFailureOutput = Schema.Struct({
|
|
35
|
+
error: Schema.Literals([
|
|
36
|
+
"invalid_cursor",
|
|
37
|
+
"page_catalog_version_mismatch",
|
|
38
|
+
"page_catalog_unavailable",
|
|
39
|
+
]),
|
|
40
|
+
detail: Schema.String,
|
|
41
|
+
request_id: Schema.String,
|
|
42
|
+
revision: Schema.optionalKey(Schema.String),
|
|
43
|
+
});
|
|
44
|
+
export const NavigationToolOutput = Schema.Union([
|
|
45
|
+
NavigationOutput,
|
|
46
|
+
ErrorSchemas.invalidRequest,
|
|
47
|
+
ErrorSchemas.internal,
|
|
48
|
+
NavigationFailureOutput,
|
|
49
|
+
]);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { OntologyManifest } from "../manifest.js";
|
|
2
|
+
import { type PageCatalogV1 } from "../navigation-catalog.js";
|
|
3
|
+
import { type PermissionHolder } from "../permissions.js";
|
|
4
|
+
import type { CallerContext } from "./caller-context.js";
|
|
5
|
+
import type { NavigationInput } from "./navigation-schemas.js";
|
|
6
|
+
type JsonObject = Readonly<Record<string, unknown>>;
|
|
7
|
+
declare const NavigationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
8
|
+
readonly _tag: "NavigationError";
|
|
9
|
+
} & Readonly<A>;
|
|
10
|
+
export declare class NavigationError extends NavigationError_base<{
|
|
11
|
+
readonly error: "invalid_cursor" | "page_catalog_version_mismatch" | "page_catalog_unavailable";
|
|
12
|
+
readonly detail: string;
|
|
13
|
+
readonly revision?: string;
|
|
14
|
+
readonly cause?: unknown;
|
|
15
|
+
}> {
|
|
16
|
+
}
|
|
17
|
+
/** Snapshot immutable deployment metadata once; compute caller visibility on every invocation. */
|
|
18
|
+
export declare function createNavigation(value: PageCatalogV1, manifest: OntologyManifest, origins: readonly string[]): (input: NavigationInput, principal: PermissionHolder, caller: CallerContext, origin: string) => JsonObject;
|
|
19
|
+
export type Navigation = ReturnType<typeof createNavigation>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { Data } from "effect";
|
|
3
|
+
import { NAVIGATION_CATALOG_LIMITS, parsePageCatalog, } from "../navigation-catalog.js";
|
|
4
|
+
import { effectivePermissions } from "../permissions.js";
|
|
5
|
+
import { catalogFor } from "./catalog.js";
|
|
6
|
+
import { discoveryResultBytes } from "./discovery.js";
|
|
7
|
+
import { compareRefs, normalizeSearch } from "./discovery-search.js";
|
|
8
|
+
export class NavigationError extends Data.TaggedError("NavigationError") {
|
|
9
|
+
}
|
|
10
|
+
function unavailable(cause) {
|
|
11
|
+
throw new NavigationError({
|
|
12
|
+
error: "page_catalog_unavailable",
|
|
13
|
+
detail: "Page discovery is unavailable for this deployment.",
|
|
14
|
+
cause,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function invalidCursor() {
|
|
18
|
+
throw new NavigationError({
|
|
19
|
+
error: "invalid_cursor",
|
|
20
|
+
detail: "Restart page discovery; its cursor is invalid.",
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function checkRevision(revision, expected) {
|
|
24
|
+
if (expected !== undefined && expected !== revision) {
|
|
25
|
+
throw new NavigationError({
|
|
26
|
+
error: "page_catalog_version_mismatch",
|
|
27
|
+
detail: "The page catalog changed. Repeat page discovery with the current revision.",
|
|
28
|
+
revision,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function digest(value) {
|
|
33
|
+
return createHash("sha256").update(JSON.stringify(value)).digest("hex");
|
|
34
|
+
}
|
|
35
|
+
/** Keyword search inspects only published titles/descriptions and never executes page code. */
|
|
36
|
+
function score(title, description, query) {
|
|
37
|
+
const normalizedTitle = normalizeSearch(title);
|
|
38
|
+
const normalizedDescription = normalizeSearch(description);
|
|
39
|
+
const terms = query.match(/[\p{L}\p{N}]+/gu) ?? [query];
|
|
40
|
+
if (!terms.every((term) => normalizedTitle.includes(term) || normalizedDescription.includes(term))) {
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
return ((normalizedTitle === query ? 100 : normalizedTitle.includes(query) ? 50 : 0) +
|
|
44
|
+
(normalizedDescription.includes(query) ? 10 : 0) +
|
|
45
|
+
terms.filter((term) => normalizedTitle.includes(term)).length +
|
|
46
|
+
1);
|
|
47
|
+
}
|
|
48
|
+
/** The existing app-origin allowlist is the authority; forwarded headers only select an exact member. */
|
|
49
|
+
function trustedOrigin(candidate, origins) {
|
|
50
|
+
const parsed = URL.parse(candidate);
|
|
51
|
+
if (parsed === null ||
|
|
52
|
+
!["https:", "http:"].includes(parsed.protocol) ||
|
|
53
|
+
parsed.username !== "" ||
|
|
54
|
+
parsed.password !== "" ||
|
|
55
|
+
parsed.origin !== candidate ||
|
|
56
|
+
!origins.includes(candidate)) {
|
|
57
|
+
return unavailable(new Error("The request has no verified app origin for navigation."));
|
|
58
|
+
}
|
|
59
|
+
return parsed.origin;
|
|
60
|
+
}
|
|
61
|
+
/** Snapshot immutable deployment metadata once; compute caller visibility on every invocation. */
|
|
62
|
+
export function createNavigation(value, manifest, origins) {
|
|
63
|
+
let catalog;
|
|
64
|
+
let catalogFailure;
|
|
65
|
+
try {
|
|
66
|
+
catalog = parsePageCatalog(value);
|
|
67
|
+
const names = new Set(manifest.entities.map(({ name }) => name));
|
|
68
|
+
for (const page of catalog.pages) {
|
|
69
|
+
for (const name of page.entities) {
|
|
70
|
+
if (!names.has(name)) {
|
|
71
|
+
throw new Error(`Page ${page.ref} references unknown ontology entity ${name}.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
catalog = undefined;
|
|
78
|
+
catalogFailure = error;
|
|
79
|
+
}
|
|
80
|
+
const trustedOrigins = [...origins];
|
|
81
|
+
return (input, principal, caller, origin) => {
|
|
82
|
+
if (catalog === undefined) {
|
|
83
|
+
return unavailable(catalogFailure);
|
|
84
|
+
}
|
|
85
|
+
checkRevision(catalog.revision, input.expected_revision);
|
|
86
|
+
const appOrigin = trustedOrigin(origin, trustedOrigins);
|
|
87
|
+
const visibleNames = catalogFor(manifest, effectivePermissions(principal)).entities.map(({ name }) => name);
|
|
88
|
+
const visible = new Set(visibleNames);
|
|
89
|
+
const scope = digest([caller.kind, visibleNames.sort(compareRefs)]);
|
|
90
|
+
const query = input.query === undefined ? undefined : normalizeSearch(input.query);
|
|
91
|
+
const request = digest({
|
|
92
|
+
entity: input.entity ?? null,
|
|
93
|
+
query: query ?? null,
|
|
94
|
+
order: "keywords-v1",
|
|
95
|
+
origin: appOrigin,
|
|
96
|
+
});
|
|
97
|
+
const items = catalog.pages
|
|
98
|
+
.filter((page) => page.entities.every((name) => visible.has(name)))
|
|
99
|
+
.filter((page) => input.entity === undefined || page.entities.includes(input.entity))
|
|
100
|
+
.map((page) => ({
|
|
101
|
+
page,
|
|
102
|
+
score: query === undefined ? 1 : score(page.title, page.description, query),
|
|
103
|
+
}))
|
|
104
|
+
.filter((item) => item.score > 0)
|
|
105
|
+
.sort((a, b) => b.score - a.score || compareRefs(a.page.ref, b.page.ref))
|
|
106
|
+
.map(({ page }) => ({
|
|
107
|
+
...page,
|
|
108
|
+
[page.parameters.length === 0 ? "url" : "url_pattern"]: `${appOrigin}${page.route}`,
|
|
109
|
+
}));
|
|
110
|
+
let start = 0;
|
|
111
|
+
if (input.after !== undefined) {
|
|
112
|
+
let cursor;
|
|
113
|
+
try {
|
|
114
|
+
if (!/^[A-Za-z0-9_-]+$/.test(input.after)) {
|
|
115
|
+
return invalidCursor();
|
|
116
|
+
}
|
|
117
|
+
const decoded = JSON.parse(Buffer.from(input.after, "base64url").toString("utf8"));
|
|
118
|
+
if (typeof decoded !== "object" || decoded === null || Array.isArray(decoded)) {
|
|
119
|
+
return invalidCursor();
|
|
120
|
+
}
|
|
121
|
+
cursor = decoded;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return invalidCursor();
|
|
125
|
+
}
|
|
126
|
+
if (typeof cursor.revision !== "string") {
|
|
127
|
+
return invalidCursor();
|
|
128
|
+
}
|
|
129
|
+
checkRevision(catalog.revision, cursor.revision);
|
|
130
|
+
if (cursor.scope !== scope || cursor.request !== request || typeof cursor.last !== "string") {
|
|
131
|
+
return invalidCursor();
|
|
132
|
+
}
|
|
133
|
+
const position = items.findIndex(({ ref }) => ref === cursor.last);
|
|
134
|
+
if (position < 0) {
|
|
135
|
+
return invalidCursor();
|
|
136
|
+
}
|
|
137
|
+
start = position + 1;
|
|
138
|
+
}
|
|
139
|
+
const cursorAfter = (last) => Buffer.from(JSON.stringify({
|
|
140
|
+
revision: catalog.revision,
|
|
141
|
+
scope,
|
|
142
|
+
request,
|
|
143
|
+
last,
|
|
144
|
+
})).toString("base64url");
|
|
145
|
+
const selected = [];
|
|
146
|
+
let result = { revision: catalog.revision, pages: selected, next_cursor: null };
|
|
147
|
+
for (const item of items.slice(start, start + (input.limit ?? 20))) {
|
|
148
|
+
const candidate = [...selected, item];
|
|
149
|
+
const next = {
|
|
150
|
+
revision: catalog.revision,
|
|
151
|
+
pages: candidate,
|
|
152
|
+
next_cursor: start + candidate.length < items.length ? cursorAfter(item.ref) : null,
|
|
153
|
+
};
|
|
154
|
+
if (discoveryResultBytes(next) > NAVIGATION_CATALOG_LIMITS.responseBytes) {
|
|
155
|
+
if (selected.length === 0) {
|
|
156
|
+
return unavailable(new Error("A complete navigation result exceeds the MCP response budget."));
|
|
157
|
+
}
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
selected.push(item);
|
|
161
|
+
result = next;
|
|
162
|
+
}
|
|
163
|
+
return result;
|
|
164
|
+
};
|
|
165
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { HttpServerRequest } from "effect/unstable/http";
|
|
3
|
+
import type { Principal } from "../../runtime.js";
|
|
4
|
+
import type { OAuthStore } from "../runtime-contract.js";
|
|
5
|
+
import type { VerifiedCaller } from "../caller-context.js";
|
|
6
|
+
/** Access tokens: `sso_` and 43 characters of base64url, isolated by their grant's resource. */
|
|
7
|
+
export declare const ACCESS_TOKEN_PREFIX = "sso_";
|
|
8
|
+
/** First-party app sessions have a resource distinct from every MCP grant. */
|
|
9
|
+
export declare const APP_SESSION_RESOURCE_PATH = "/api/ontology/session";
|
|
10
|
+
export declare const REFRESH_TOKEN_PREFIX = "ssr_";
|
|
11
|
+
export declare const CODE_PREFIX = "ssc_";
|
|
12
|
+
export declare const CLIENT_ID_PREFIX = "ssa_";
|
|
13
|
+
export declare const CLIENT_SECRET_PREFIX = "sss_";
|
|
14
|
+
export declare const ACCESS_TOKEN_TTL_MS: number;
|
|
15
|
+
export declare const REFRESH_TOKEN_TTL_MS: number;
|
|
16
|
+
export declare const CODE_TTL_MS: number;
|
|
17
|
+
/** How long a member has to sign in and decide. */
|
|
18
|
+
export declare const REQUEST_TTL_MS: number;
|
|
19
|
+
/** Everything the member may do. */
|
|
20
|
+
export declare const FULL_SCOPE = "ontology";
|
|
21
|
+
/** Only the reads of what the member may do. */
|
|
22
|
+
export declare const READ_SCOPE = "ontology:read";
|
|
23
|
+
export declare const SCOPES: readonly ["ontology", "ontology:read"];
|
|
24
|
+
export type Scope = (typeof SCOPES)[number];
|
|
25
|
+
/** The well-known path of the MCP server's protected resource metadata (RFC 9728). */
|
|
26
|
+
export declare const PROTECTED_RESOURCE_PATH = "/.well-known/oauth-protected-resource";
|
|
27
|
+
/** The well-known path of the authorization server metadata (RFC 8414). */
|
|
28
|
+
export declare const AUTHORIZATION_SERVER_PATH = "/.well-known/oauth-authorization-server";
|
|
29
|
+
/** The app's page where a signed-in member approves or denies a request. */
|
|
30
|
+
export declare const CONSENT_PATH = "/oauth/consent";
|
|
31
|
+
/** 32 random bytes, base64url, after a prefix that says what the value is. */
|
|
32
|
+
export declare function newSecret(prefix?: string): string;
|
|
33
|
+
/** SHA-256 in hex: how codes, tokens and client secrets are stored. */
|
|
34
|
+
export declare function secretHash(value: string): string;
|
|
35
|
+
/** URL serialization preserves the resource boundary while normalizing host case and default ports. */
|
|
36
|
+
export declare function sameResource(left: string, right: string): boolean;
|
|
37
|
+
export declare function appSessionResource(origin: string): string;
|
|
38
|
+
type AccessRejection = "token_not_found" | "token_expired" | "grant_revoked" | "resource_mismatch" | "member_unavailable" | "client_unavailable" | "unsupported_route" | "oauth_unavailable";
|
|
39
|
+
export declare function rejectedAccessToken(reason: AccessRejection, grantId?: string): Effect.Effect<undefined, never, never>;
|
|
40
|
+
export declare function sameSecret(value: string, hash: string): boolean;
|
|
41
|
+
/** Whether a PKCE verifier answers an S256 challenge (RFC 7636). */
|
|
42
|
+
export declare function verifierMatches(verifier: string, challenge: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* The scope a request gets: everything the member may do unless it asks only to read. Scopes this
|
|
45
|
+
* server does not know are ignored, as clients often ask for the ones they always ask for.
|
|
46
|
+
*/
|
|
47
|
+
export declare function grantedScope(requested: string | undefined): Scope;
|
|
48
|
+
/** The member as a grant of this scope acts: with only their reads under `ontology:read`. */
|
|
49
|
+
export declare function scopedPrincipal(principal: Principal, scope: string): Principal;
|
|
50
|
+
export declare function isLoopback(host: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* The origin the client reached the app on, as Vercel forwards it: the issuer of the authorization
|
|
53
|
+
* server and the origin of the MCP server's URL. Each domain of the app is its own resource.
|
|
54
|
+
*/
|
|
55
|
+
export declare function publicOrigin(request: HttpServerRequest.HttpServerRequest): string;
|
|
56
|
+
/**
|
|
57
|
+
* The member an access token acts for, as its grant allows: only for the resource it was issued
|
|
58
|
+
* for, while the grant stands and the member may still sign in.
|
|
59
|
+
*/
|
|
60
|
+
export declare function callerOfAccessToken(store: OAuthStore, token: string, resource: string): Effect.Effect<{
|
|
61
|
+
readonly principal: Principal;
|
|
62
|
+
readonly caller: VerifiedCaller;
|
|
63
|
+
} | undefined>;
|
|
64
|
+
export declare const DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
65
|
+
export declare const DEVICE_TTL_MS: number;
|
|
66
|
+
export declare const DEVICE_INTERVAL = 5;
|
|
67
|
+
/** 32 symbols, five bits per symbol, without ambiguous I/O/0/1. */
|
|
68
|
+
export declare function humanCode(groups?: number): string;
|
|
69
|
+
export declare function normalizedUserCode(value: string): string;
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { createHash, randomBytes, randomInt, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import { CHANNEL_SESSION_PATH } from "../../channel-session.js";
|
|
4
|
+
import { parsePermission, permissionOf, READ_VERB, WILDCARD } from "../../permissions.js";
|
|
5
|
+
/** Access tokens: `sso_` and 43 characters of base64url, isolated by their grant's resource. */
|
|
6
|
+
export const ACCESS_TOKEN_PREFIX = "sso_";
|
|
7
|
+
/** First-party app sessions have a resource distinct from every MCP grant. */
|
|
8
|
+
export const APP_SESSION_RESOURCE_PATH = CHANNEL_SESSION_PATH;
|
|
9
|
+
export const REFRESH_TOKEN_PREFIX = "ssr_";
|
|
10
|
+
export const CODE_PREFIX = "ssc_";
|
|
11
|
+
export const CLIENT_ID_PREFIX = "ssa_";
|
|
12
|
+
export const CLIENT_SECRET_PREFIX = "sss_";
|
|
13
|
+
export const ACCESS_TOKEN_TTL_MS = 60 * 60 * 1000;
|
|
14
|
+
export const REFRESH_TOKEN_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
15
|
+
export const CODE_TTL_MS = 5 * 60 * 1000;
|
|
16
|
+
/** How long a member has to sign in and decide. */
|
|
17
|
+
export const REQUEST_TTL_MS = 15 * 60 * 1000;
|
|
18
|
+
/** Everything the member may do. */
|
|
19
|
+
export const FULL_SCOPE = "ontology";
|
|
20
|
+
/** Only the reads of what the member may do. */
|
|
21
|
+
export const READ_SCOPE = "ontology:read";
|
|
22
|
+
export const SCOPES = [FULL_SCOPE, READ_SCOPE];
|
|
23
|
+
/** The well-known path of the MCP server's protected resource metadata (RFC 9728). */
|
|
24
|
+
export const PROTECTED_RESOURCE_PATH = "/.well-known/oauth-protected-resource";
|
|
25
|
+
/** The well-known path of the authorization server metadata (RFC 8414). */
|
|
26
|
+
export const AUTHORIZATION_SERVER_PATH = "/.well-known/oauth-authorization-server";
|
|
27
|
+
/** The app's page where a signed-in member approves or denies a request. */
|
|
28
|
+
export const CONSENT_PATH = "/oauth/consent";
|
|
29
|
+
/** 32 random bytes, base64url, after a prefix that says what the value is. */
|
|
30
|
+
export function newSecret(prefix = "") {
|
|
31
|
+
return `${prefix}${randomBytes(32).toString("base64url")}`;
|
|
32
|
+
}
|
|
33
|
+
/** SHA-256 in hex: how codes, tokens and client secrets are stored. */
|
|
34
|
+
export function secretHash(value) {
|
|
35
|
+
return createHash("sha256").update(value, "utf8").digest("hex");
|
|
36
|
+
}
|
|
37
|
+
/** URL serialization preserves the resource boundary while normalizing host case and default ports. */
|
|
38
|
+
export function sameResource(left, right) {
|
|
39
|
+
return URL.canParse(left) && URL.canParse(right) && new URL(left).href === new URL(right).href;
|
|
40
|
+
}
|
|
41
|
+
export function appSessionResource(origin) {
|
|
42
|
+
return new URL(APP_SESSION_RESOURCE_PATH, origin).href;
|
|
43
|
+
}
|
|
44
|
+
export function rejectedAccessToken(reason, grantId) {
|
|
45
|
+
return Effect.logWarning("ontology.oauth.access_rejected").pipe(Effect.annotateLogs({ reason, ...(grantId === undefined ? {} : { grantId }) }), Effect.as(undefined));
|
|
46
|
+
}
|
|
47
|
+
export function sameSecret(value, hash) {
|
|
48
|
+
const left = Buffer.from(secretHash(value), "hex");
|
|
49
|
+
const right = Buffer.from(hash, "hex");
|
|
50
|
+
return left.length === right.length && timingSafeEqual(left, right);
|
|
51
|
+
}
|
|
52
|
+
/** Whether a PKCE verifier answers an S256 challenge (RFC 7636). */
|
|
53
|
+
export function verifierMatches(verifier, challenge) {
|
|
54
|
+
if (!/^[A-Za-z0-9._~-]{43,128}$/.test(verifier)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const computed = Buffer.from(createHash("sha256").update(verifier, "ascii").digest("base64url"));
|
|
58
|
+
const expected = Buffer.from(challenge);
|
|
59
|
+
return computed.length === expected.length && timingSafeEqual(computed, expected);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The scope a request gets: everything the member may do unless it asks only to read. Scopes this
|
|
63
|
+
* server does not know are ignored, as clients often ask for the ones they always ask for.
|
|
64
|
+
*/
|
|
65
|
+
export function grantedScope(requested) {
|
|
66
|
+
const asked = new Set((requested ?? "").split(" ").filter((scope) => scope !== ""));
|
|
67
|
+
return asked.has(READ_SCOPE) && !asked.has(FULL_SCOPE) ? READ_SCOPE : FULL_SCOPE;
|
|
68
|
+
}
|
|
69
|
+
/** `lead:*` and `lead:read` keep `lead:read`; `*:*` keeps `*:read`; other verbs go. */
|
|
70
|
+
function readPermissions(permissions) {
|
|
71
|
+
const reads = permissions.flatMap((permission) => {
|
|
72
|
+
const parsed = parsePermission(permission);
|
|
73
|
+
return parsed !== undefined && (parsed.verb === READ_VERB || parsed.verb === WILDCARD)
|
|
74
|
+
? [permissionOf(parsed.entity, READ_VERB)]
|
|
75
|
+
: [];
|
|
76
|
+
});
|
|
77
|
+
return [...new Set(reads)];
|
|
78
|
+
}
|
|
79
|
+
/** The member as a grant of this scope acts: with only their reads under `ontology:read`. */
|
|
80
|
+
export function scopedPrincipal(principal, scope) {
|
|
81
|
+
return scope === READ_SCOPE
|
|
82
|
+
? { ...principal, permissions: readPermissions(principal.permissions) }
|
|
83
|
+
: principal;
|
|
84
|
+
}
|
|
85
|
+
const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
86
|
+
export function isLoopback(host) {
|
|
87
|
+
return LOOPBACK_HOSTS.has(host.replace(/:\d+$/, ""));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The origin the client reached the app on, as Vercel forwards it: the issuer of the authorization
|
|
91
|
+
* server and the origin of the MCP server's URL. Each domain of the app is its own resource.
|
|
92
|
+
*/
|
|
93
|
+
export function publicOrigin(request) {
|
|
94
|
+
const forwardedHost = request.headers["x-forwarded-host"] ?? request.headers.host;
|
|
95
|
+
if (forwardedHost === undefined) {
|
|
96
|
+
// A web Request without a Host header still carries its absolute URL.
|
|
97
|
+
return URL.canParse(request.originalUrl)
|
|
98
|
+
? new URL(request.originalUrl).origin
|
|
99
|
+
: "http://localhost";
|
|
100
|
+
}
|
|
101
|
+
const host = forwardedHost.split(",")[0].trim();
|
|
102
|
+
const forwardedProto = request.headers["x-forwarded-proto"]?.split(",")[0]?.trim();
|
|
103
|
+
const protocol = forwardedProto === "http" || forwardedProto === "https"
|
|
104
|
+
? forwardedProto
|
|
105
|
+
: isLoopback(host)
|
|
106
|
+
? "http"
|
|
107
|
+
: "https";
|
|
108
|
+
return new URL(`${protocol}://${host}`).origin;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The member an access token acts for, as its grant allows: only for the resource it was issued
|
|
112
|
+
* for, while the grant stands and the member may still sign in.
|
|
113
|
+
*/
|
|
114
|
+
export function callerOfAccessToken(store, token, resource) {
|
|
115
|
+
return Effect.gen(function* () {
|
|
116
|
+
const grant = yield* store.findAccess(secretHash(token));
|
|
117
|
+
if (grant === undefined) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
if (!sameResource(grant.resource, resource)) {
|
|
121
|
+
return yield* rejectedAccessToken("resource_mismatch", grant.id);
|
|
122
|
+
}
|
|
123
|
+
const member = yield* store.memberPrincipal(grant.userId);
|
|
124
|
+
const client = yield* store.findClient(grant.clientId);
|
|
125
|
+
if (member === undefined || member.kind !== "member" || member.id !== grant.userId) {
|
|
126
|
+
return yield* rejectedAccessToken("member_unavailable", grant.id);
|
|
127
|
+
}
|
|
128
|
+
if (client === undefined || client.id !== grant.clientId) {
|
|
129
|
+
return yield* rejectedAccessToken("client_unavailable", grant.id);
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
principal: {
|
|
133
|
+
...scopedPrincipal(member, grant.scope),
|
|
134
|
+
...(grant.identityProvider ? { authenticatedVia: grant.identityProvider } : {}),
|
|
135
|
+
},
|
|
136
|
+
caller: new URL(grant.resource).pathname === APP_SESSION_RESOURCE_PATH
|
|
137
|
+
? { kind: "member", subjectId: member.id }
|
|
138
|
+
: {
|
|
139
|
+
kind: "oauth",
|
|
140
|
+
subjectId: member.id,
|
|
141
|
+
client: { id: client.id, name: client.name },
|
|
142
|
+
scope: grant.scope,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
export const DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
148
|
+
export const DEVICE_TTL_MS = 10 * 60 * 1000;
|
|
149
|
+
export const DEVICE_INTERVAL = 5;
|
|
150
|
+
/** 32 symbols, five bits per symbol, without ambiguous I/O/0/1. */
|
|
151
|
+
export function humanCode(groups = 2) {
|
|
152
|
+
const alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
153
|
+
return Array.from({ length: groups }, () => Array.from({ length: 4 }, () => alphabet[randomInt(alphabet.length)]).join("")).join("-");
|
|
154
|
+
}
|
|
155
|
+
export function normalizedUserCode(value) {
|
|
156
|
+
return value.toUpperCase().replace(/[\s-]/g, "");
|
|
157
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
|
|
2
|
+
/** The high-entropy presented token is the key; a database dump cannot recover successors. */
|
|
3
|
+
function key(token) {
|
|
4
|
+
return createHash("sha256").update("ontology.oauth.refresh-replay.v1\0").update(token).digest();
|
|
5
|
+
}
|
|
6
|
+
export function encryptReplay(token, response) {
|
|
7
|
+
const nonce = randomBytes(12);
|
|
8
|
+
const cipher = createCipheriv("aes-256-gcm", key(token), nonce);
|
|
9
|
+
const ciphertext = Buffer.concat([
|
|
10
|
+
cipher.update(JSON.stringify(response), "utf8"),
|
|
11
|
+
cipher.final(),
|
|
12
|
+
]);
|
|
13
|
+
return Buffer.concat([nonce, cipher.getAuthTag(), ciphertext]).toString("base64url");
|
|
14
|
+
}
|
|
15
|
+
export function decryptReplay(token, encrypted) {
|
|
16
|
+
const bytes = Buffer.from(encrypted, "base64url");
|
|
17
|
+
const decipher = createDecipheriv("aes-256-gcm", key(token), bytes.subarray(0, 12));
|
|
18
|
+
decipher.setAuthTag(bytes.subarray(12, 28));
|
|
19
|
+
return JSON.parse(Buffer.concat([decipher.update(bytes.subarray(28)), decipher.final()]).toString("utf8"));
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Layer } from "effect";
|
|
2
|
+
import { HttpRouter } from "effect/unstable/http";
|
|
3
|
+
import { type TokenVerifier } from "../authentication.js";
|
|
4
|
+
import { RequestId } from "../errors.js";
|
|
5
|
+
import { type RateLimit } from "../rate-limit.js";
|
|
6
|
+
import { OntologyBackend } from "../runtime-contract.js";
|
|
7
|
+
/** The authorization server's endpoints, under the ontology service's path. */
|
|
8
|
+
export declare const OAUTH_PATH = "/api/ontology/oauth";
|
|
9
|
+
/** Registrations one client address may make per minute; each one is a row in the database. */
|
|
10
|
+
export declare const REGISTRATION_LIMIT: RateLimit;
|
|
11
|
+
/** Where the MCP server is, on the origin the client reached. */
|
|
12
|
+
export declare function mcpResource(origin: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* The `WWW-Authenticate` challenge of the MCP server: it names the protected resource metadata,
|
|
15
|
+
* which is how a client learns where members authorize it (RFC 9728).
|
|
16
|
+
*/
|
|
17
|
+
export declare function mcpChallenge(origin: string, missing: boolean): string;
|
|
18
|
+
export interface OAuthServerOptions {
|
|
19
|
+
readonly verifyToken: TokenVerifier;
|
|
20
|
+
readonly refreshReuseGraceMs?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The MCP server's OAuth 2.1 authorization server, on the app's own origin: the protected resource
|
|
24
|
+
* and authorization server metadata, dynamic client registration, the authorization endpoint that
|
|
25
|
+
* hands the member to the app's consent page, the endpoints the consent page decides with, and the
|
|
26
|
+
* token and revocation endpoints. Without the OAuth tables, it serves nothing.
|
|
27
|
+
*/
|
|
28
|
+
export declare function oauthLayer(options: OAuthServerOptions): Layer.Layer<never, never, OntologyBackend | HttpRouter.HttpRouter | HttpRouter.Request<"Requires", RequestId>>;
|