@segmentstream/ontology 0.0.0-stage → 0.92.1
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,9 @@
|
|
|
1
|
+
import { SqlClient } from "effect/unstable/sql";
|
|
2
|
+
import type { Ontology } from "../ontology.js";
|
|
3
|
+
import type { OAuthStore } from "../service/runtime-contract.js";
|
|
4
|
+
/**
|
|
5
|
+
* The OAuth store on the runtime's OAuth tables, as `ontology_app`. Expiry is the database's
|
|
6
|
+
* wall clock; codes and refresh tokens are used with one `UPDATE … WHERE "used_at" IS NULL`, so two
|
|
7
|
+
* concurrent uses cannot both succeed.
|
|
8
|
+
*/
|
|
9
|
+
export declare function sqlOAuthStore(ontology: Ontology, sql: SqlClient.SqlClient): OAuthStore;
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/unstable/sql";
|
|
3
|
+
import { OAUTH_CLIENTS_TABLE, OAUTH_GRANTS_TABLE, OAUTH_REQUESTS_TABLE, OAUTH_TOKENS_TABLE, } from "../migrate/storage.js";
|
|
4
|
+
import { lockSessionMember, resolveMemberById } from "./principals.js";
|
|
5
|
+
import { CHANNEL_IDENTITIES_FROM, LIVE_CHANNEL_IDENTITY, USER_IDENTITY_TABLE, } from "./user-identity-sql.js";
|
|
6
|
+
import { rejectedAccessToken, sameResource } from "../service/oauth/protocol.js";
|
|
7
|
+
const CLIENTS = `"${OAUTH_CLIENTS_TABLE}"`;
|
|
8
|
+
const REQUESTS = `"${OAUTH_REQUESTS_TABLE}"`;
|
|
9
|
+
const GRANTS = `"${OAUTH_GRANTS_TABLE}"`;
|
|
10
|
+
const TOKENS = `"${OAUTH_TOKENS_TABLE}"`;
|
|
11
|
+
const CLIENT_COLUMNS = `"id", "name", "redirect_uris"::text AS "redirect_uris", "auth_method", "secret_hash", ` +
|
|
12
|
+
`"client_uri"`;
|
|
13
|
+
/** A timestamp as epoch milliseconds, which every driver returns as a plain number. */
|
|
14
|
+
function epochMs(column) {
|
|
15
|
+
return `(extract(epoch from ${column}) * 1000)::double precision`;
|
|
16
|
+
}
|
|
17
|
+
const REQUEST_COLUMNS = `"id", "client_id", "redirect_uri", "state", "code_challenge", "scope", "resource", ` +
|
|
18
|
+
`${epochMs(`"expires_at"`)} AS "expires_at"`;
|
|
19
|
+
/** The grant's columns, read through the alias `g`. */
|
|
20
|
+
const GRANT_COLUMNS = `"g"."id"::text AS "grant_id", "g"."client_id" AS "client_id", ` +
|
|
21
|
+
`"g"."user_id"::text AS "user_id", "g"."scope" AS "scope", "g"."resource" AS "resource"`;
|
|
22
|
+
function text(value) {
|
|
23
|
+
return String(value);
|
|
24
|
+
}
|
|
25
|
+
function nullableText(value) {
|
|
26
|
+
return value === null || value === undefined ? null : String(value);
|
|
27
|
+
}
|
|
28
|
+
function date(value) {
|
|
29
|
+
return new Date(Number(value));
|
|
30
|
+
}
|
|
31
|
+
function clientOf(row) {
|
|
32
|
+
return {
|
|
33
|
+
id: text(row.id),
|
|
34
|
+
name: text(row.name),
|
|
35
|
+
redirectUris: JSON.parse(text(row.redirect_uris)),
|
|
36
|
+
authMethod: text(row.auth_method),
|
|
37
|
+
secretHash: nullableText(row.secret_hash),
|
|
38
|
+
clientUri: nullableText(row.client_uri),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function requestOf(row) {
|
|
42
|
+
return {
|
|
43
|
+
id: text(row.id),
|
|
44
|
+
clientId: text(row.client_id),
|
|
45
|
+
redirectUri: text(row.redirect_uri),
|
|
46
|
+
state: nullableText(row.state),
|
|
47
|
+
codeChallenge: text(row.code_challenge),
|
|
48
|
+
scope: text(row.scope),
|
|
49
|
+
resource: text(row.resource),
|
|
50
|
+
expiresAt: date(row.expires_at),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function deviceOf(row) {
|
|
54
|
+
return {
|
|
55
|
+
hash: text(row.hash),
|
|
56
|
+
userCodeHash: text(row.user_code_hash),
|
|
57
|
+
clientId: text(row.client_id),
|
|
58
|
+
scope: text(row.scope),
|
|
59
|
+
resource: text(row.resource),
|
|
60
|
+
expiresAt: date(row.expires_at),
|
|
61
|
+
interval: Number(row.interval),
|
|
62
|
+
status: text(row.status),
|
|
63
|
+
userId: nullableText(row.user_id),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const DEVICE_COLUMNS = `*, ${epochMs('"expires_at"')} AS "expires_at"`;
|
|
67
|
+
function grantOf(row) {
|
|
68
|
+
return {
|
|
69
|
+
id: text(row.grant_id),
|
|
70
|
+
clientId: text(row.client_id),
|
|
71
|
+
userId: text(row.user_id),
|
|
72
|
+
scope: text(row.scope),
|
|
73
|
+
resource: text(row.resource),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function tokenOf(row) {
|
|
77
|
+
return {
|
|
78
|
+
hash: text(row.hash),
|
|
79
|
+
grantId: text(row.grant_id),
|
|
80
|
+
kind: text(row.kind),
|
|
81
|
+
expiresAt: date(row.expires_at),
|
|
82
|
+
...(row.redirect_uri === null ? {} : { redirectUri: text(row.redirect_uri) }),
|
|
83
|
+
...(row.code_challenge === null ? {} : { codeChallenge: text(row.code_challenge) }),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const INSERT_TOKEN = `INSERT INTO ${TOKENS} ("hash", "grant_id", "kind", "redirect_uri", "code_challenge", ` +
|
|
87
|
+
`"expires_at") VALUES ($1, $2::uuid, $3, $4, $5, $6::timestamptz)`;
|
|
88
|
+
function tokenValues(token) {
|
|
89
|
+
return [
|
|
90
|
+
token.hash,
|
|
91
|
+
token.grantId,
|
|
92
|
+
token.kind,
|
|
93
|
+
token.redirectUri ?? null,
|
|
94
|
+
token.codeChallenge ?? null,
|
|
95
|
+
token.expiresAt.toISOString(),
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The OAuth store on the runtime's OAuth tables, as `ontology_app`. Expiry is the database's
|
|
100
|
+
* wall clock; codes and refresh tokens are used with one `UPDATE … WHERE "used_at" IS NULL`, so two
|
|
101
|
+
* concurrent uses cannot both succeed.
|
|
102
|
+
*/
|
|
103
|
+
export function sqlOAuthStore(ontology, sql) {
|
|
104
|
+
const rows = (statement, values = []) => sql.unsafe(statement, values).pipe(Effect.orDie);
|
|
105
|
+
return {
|
|
106
|
+
withTokenLock: (hash, effect) => sql
|
|
107
|
+
.withTransaction(Effect.gen(function* () {
|
|
108
|
+
yield* rows(`SELECT "hash" FROM ${TOKENS} WHERE "hash" = $1 FOR UPDATE`, [hash]);
|
|
109
|
+
return yield* effect;
|
|
110
|
+
}))
|
|
111
|
+
.pipe(Effect.orDie),
|
|
112
|
+
refreshReplay: (hash, graceMs) => rows(`SELECT "t"."replay" FROM ${TOKENS} AS "t"
|
|
113
|
+
JOIN ${TOKENS} AS "s" ON "s"."hash" = "t"."successor_hash"
|
|
114
|
+
JOIN ${GRANTS} AS "g" ON "g"."id" = "t"."grant_id"
|
|
115
|
+
WHERE "t"."hash" = $1 AND $2 > 0 AND "t"."used_at" IS NOT NULL
|
|
116
|
+
AND "t"."kind" = 'refresh' AND "t"."expires_at" > clock_timestamp()
|
|
117
|
+
AND "s"."kind" = 'refresh' AND "s"."grant_id" = "t"."grant_id"
|
|
118
|
+
AND "s"."used_at" IS NULL AND "s"."expires_at" > clock_timestamp()
|
|
119
|
+
AND "g"."revoked_at" IS NULL FOR UPDATE OF "s"`, [hash, graceMs]).pipe(Effect.map(([row]) => (row?.replay == null ? undefined : text(row.replay)))),
|
|
120
|
+
saveRefreshReplay: (hash, encrypted, successorHash) => rows(`UPDATE ${TOKENS} SET "replay" = $2, "successor_hash" = $3 WHERE "hash" = $1`, [
|
|
121
|
+
hash,
|
|
122
|
+
encrypted,
|
|
123
|
+
successorHash,
|
|
124
|
+
]).pipe(Effect.asVoid),
|
|
125
|
+
saveDevice: (device) => sql
|
|
126
|
+
.withTransaction(Effect.gen(function* () {
|
|
127
|
+
yield* rows(`DELETE FROM "_oauth_devices" WHERE "expires_at" < now() - interval '1 day'`);
|
|
128
|
+
const inserted = yield* rows(`INSERT INTO "_oauth_devices"
|
|
129
|
+
("hash", "user_code_hash", "client_id", "scope", "resource", "expires_at", "interval")
|
|
130
|
+
VALUES ($1, $2, $3, $4, $5, $6::timestamptz, $7) ON CONFLICT DO NOTHING RETURNING "hash"`, [
|
|
131
|
+
device.hash,
|
|
132
|
+
device.userCodeHash,
|
|
133
|
+
device.clientId,
|
|
134
|
+
device.scope,
|
|
135
|
+
device.resource,
|
|
136
|
+
device.expiresAt.toISOString(),
|
|
137
|
+
device.interval,
|
|
138
|
+
]);
|
|
139
|
+
return inserted.length === 1;
|
|
140
|
+
}))
|
|
141
|
+
.pipe(Effect.orDie),
|
|
142
|
+
findDevice: (hash) => rows(`SELECT ${DEVICE_COLUMNS} FROM "_oauth_devices" WHERE "user_code_hash" = $1`, [
|
|
143
|
+
hash,
|
|
144
|
+
]).pipe(Effect.map(([row]) => (row === undefined ? undefined : deviceOf(row)))),
|
|
145
|
+
deviceAttempt: (memberId) => rows(`INSERT INTO "_oauth_device_attempts" ("member_id") VALUES ($1::uuid)
|
|
146
|
+
ON CONFLICT ("member_id") DO UPDATE SET
|
|
147
|
+
"attempts" = CASE WHEN "_oauth_device_attempts"."window_at" <= now() - interval '10 minutes'
|
|
148
|
+
THEN 1 ELSE "_oauth_device_attempts"."attempts" + 1 END,
|
|
149
|
+
"window_at" = CASE WHEN "_oauth_device_attempts"."window_at" <= now() - interval '10 minutes'
|
|
150
|
+
THEN now() ELSE "_oauth_device_attempts"."window_at" END RETURNING "attempts"`, [memberId]).pipe(Effect.map(([row]) => Number(row?.attempts) <= 10)),
|
|
151
|
+
decideDevice: (hash, userId, scope, decision) => rows(`UPDATE "_oauth_devices" SET "user_id" = $2::uuid, "status" = $3,
|
|
152
|
+
"scope" = CASE WHEN $4 = 'ontology:read' THEN $4 ELSE "scope" END
|
|
153
|
+
WHERE "user_code_hash" = $1 AND "status" = 'pending' AND "expires_at" > now()
|
|
154
|
+
RETURNING "hash"`, [hash, userId, decision === "approve" ? "approved" : "denied", scope ?? null]).pipe(Effect.map((updated) => updated.length === 1)),
|
|
155
|
+
pollDevice: (hash, clientId, resource) => sql
|
|
156
|
+
.withTransaction(Effect.gen(function* () {
|
|
157
|
+
const [row] = yield* rows(`SELECT ${DEVICE_COLUMNS}, "expires_at" <= now() AS "expired",
|
|
158
|
+
"next_poll_at" > clock_timestamp() AS "early"
|
|
159
|
+
FROM "_oauth_devices" WHERE "hash" = $1 AND "client_id" = $2 FOR UPDATE`, [hash, clientId]);
|
|
160
|
+
if (row === undefined ||
|
|
161
|
+
(resource !== undefined && !sameResource(resource, text(row.resource)))) {
|
|
162
|
+
return { status: "invalid_grant" };
|
|
163
|
+
}
|
|
164
|
+
if (row.expired === true) {
|
|
165
|
+
return { status: "expired_token" };
|
|
166
|
+
}
|
|
167
|
+
const device = deviceOf(row);
|
|
168
|
+
if (device.status === "consumed") {
|
|
169
|
+
return { status: "invalid_grant" };
|
|
170
|
+
}
|
|
171
|
+
if (row.early === true) {
|
|
172
|
+
yield* rows(`UPDATE "_oauth_devices" SET "interval" = "interval" + 5,
|
|
173
|
+
"next_poll_at" = clock_timestamp() + ("interval" + 5) * interval '1 second'
|
|
174
|
+
WHERE "hash" = $1`, [hash]);
|
|
175
|
+
return { status: "slow_down" };
|
|
176
|
+
}
|
|
177
|
+
yield* rows(`UPDATE "_oauth_devices" SET
|
|
178
|
+
"next_poll_at" = clock_timestamp() + "interval" * interval '1 second',
|
|
179
|
+
"status" = CASE WHEN "status" = 'approved' THEN 'consumed' ELSE "status" END
|
|
180
|
+
WHERE "hash" = $1`, [hash]);
|
|
181
|
+
if (device.status === "approved") {
|
|
182
|
+
return { status: "approved", device };
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
status: device.status === "denied" ? "access_denied" : "authorization_pending",
|
|
186
|
+
};
|
|
187
|
+
}))
|
|
188
|
+
.pipe(Effect.orDie),
|
|
189
|
+
saveClient: (client) => rows(`INSERT INTO ${CLIENTS} ("id", "name", "redirect_uris", "auth_method", "secret_hash", ` +
|
|
190
|
+
`"client_uri") VALUES ($1, $2, $3::jsonb, $4, $5, $6)`, [
|
|
191
|
+
client.id,
|
|
192
|
+
client.name,
|
|
193
|
+
JSON.stringify(client.redirectUris),
|
|
194
|
+
client.authMethod,
|
|
195
|
+
client.secretHash,
|
|
196
|
+
client.clientUri,
|
|
197
|
+
]).pipe(Effect.asVoid),
|
|
198
|
+
findClient: (id) => rows(`SELECT ${CLIENT_COLUMNS} FROM ${CLIENTS} WHERE "id" = $1`, [id]).pipe(Effect.map(([row]) => (row === undefined ? undefined : clientOf(row)))),
|
|
199
|
+
saveRequest: (request) => sql
|
|
200
|
+
.withTransaction(Effect.gen(function* () {
|
|
201
|
+
yield* rows(`DELETE FROM ${REQUESTS} WHERE "expires_at" <= now()`);
|
|
202
|
+
yield* rows(`INSERT INTO ${REQUESTS} ("id", "client_id", "redirect_uri", "state", ` +
|
|
203
|
+
`"code_challenge", "scope", "resource", "expires_at") ` +
|
|
204
|
+
`VALUES ($1, $2, $3, $4, $5, $6, $7, $8::timestamptz)`, [
|
|
205
|
+
request.id,
|
|
206
|
+
request.clientId,
|
|
207
|
+
request.redirectUri,
|
|
208
|
+
request.state,
|
|
209
|
+
request.codeChallenge,
|
|
210
|
+
request.scope,
|
|
211
|
+
request.resource,
|
|
212
|
+
request.expiresAt.toISOString(),
|
|
213
|
+
]);
|
|
214
|
+
}))
|
|
215
|
+
.pipe(Effect.orDie),
|
|
216
|
+
findRequest: (id) => rows(`SELECT ${REQUEST_COLUMNS} FROM ${REQUESTS} WHERE "id" = $1 AND "expires_at" > now()`, [
|
|
217
|
+
id,
|
|
218
|
+
]).pipe(Effect.map(([row]) => (row === undefined ? undefined : requestOf(row)))),
|
|
219
|
+
takeRequest: (id) => rows(`DELETE FROM ${REQUESTS} WHERE "id" = $1 AND "expires_at" > now() ` +
|
|
220
|
+
`RETURNING ${REQUEST_COLUMNS}`, [id]).pipe(Effect.map(([row]) => (row === undefined ? undefined : requestOf(row)))),
|
|
221
|
+
saveGrant: (grant, code) => sql
|
|
222
|
+
.withTransaction(Effect.gen(function* () {
|
|
223
|
+
yield* lockSessionMember(sql, grant.userId);
|
|
224
|
+
yield* rows(`INSERT INTO ${GRANTS} ("id", "client_id", "user_id", "scope", "resource") ` +
|
|
225
|
+
`VALUES ($1::uuid, $2, $3::uuid, $4, $5)`, [grant.id, grant.clientId, grant.userId, grant.scope, grant.resource]);
|
|
226
|
+
if (code !== undefined) {
|
|
227
|
+
yield* rows(INSERT_TOKEN, tokenValues(code));
|
|
228
|
+
}
|
|
229
|
+
}))
|
|
230
|
+
.pipe(Effect.orDie),
|
|
231
|
+
useToken: (hash, kind) => Effect.gen(function* () {
|
|
232
|
+
const [used] = yield* rows(`UPDATE ${TOKENS} AS "t" SET "used_at" = clock_timestamp() FROM ${GRANTS} AS "g" ` +
|
|
233
|
+
`WHERE "t"."hash" = $1 AND "t"."kind" = $2 AND "t"."used_at" IS NULL ` +
|
|
234
|
+
`AND "t"."expires_at" > clock_timestamp() AND "g"."id" = "t"."grant_id" ` +
|
|
235
|
+
`AND "g"."revoked_at" IS NULL ` +
|
|
236
|
+
`RETURNING "t"."hash" AS "hash", "t"."kind" AS "kind", ` +
|
|
237
|
+
`"t"."redirect_uri" AS "redirect_uri", "t"."code_challenge" AS "code_challenge", ` +
|
|
238
|
+
`${epochMs(`"t"."expires_at"`)} AS "expires_at", ${GRANT_COLUMNS}`, [hash, kind]);
|
|
239
|
+
if (used !== undefined) {
|
|
240
|
+
return { status: "valid", token: tokenOf(used), grant: grantOf(used) };
|
|
241
|
+
}
|
|
242
|
+
const [reused] = yield* rows(`SELECT ${GRANT_COLUMNS}, "s"."used_at" IS NOT NULL AS "successor_used" FROM ${TOKENS} AS "t" ` +
|
|
243
|
+
`JOIN ${GRANTS} AS "g" ON "g"."id" = "t"."grant_id" ` +
|
|
244
|
+
`LEFT JOIN ${TOKENS} AS "s" ON "s"."hash" = "t"."successor_hash" ` +
|
|
245
|
+
`AND "s"."grant_id" = "t"."grant_id" AND "s"."kind" = 'refresh' ` +
|
|
246
|
+
`WHERE "t"."hash" = $1 AND "t"."kind" = $2 AND "t"."used_at" IS NOT NULL ` +
|
|
247
|
+
`AND "t"."expires_at" > clock_timestamp() AND "g"."revoked_at" IS NULL`, [hash, kind]);
|
|
248
|
+
return reused === undefined
|
|
249
|
+
? { status: "invalid" }
|
|
250
|
+
: {
|
|
251
|
+
status: "reused",
|
|
252
|
+
grant: grantOf(reused),
|
|
253
|
+
...(kind === "refresh" ? { successorUsed: reused.successor_used === true } : {}),
|
|
254
|
+
};
|
|
255
|
+
}),
|
|
256
|
+
saveTokens: (tokens) => sql
|
|
257
|
+
.withTransaction(Effect.gen(function* () {
|
|
258
|
+
yield* rows(`DELETE FROM ${TOKENS} WHERE "expires_at" <= clock_timestamp()`);
|
|
259
|
+
for (const token of tokens) {
|
|
260
|
+
yield* rows(INSERT_TOKEN, tokenValues(token));
|
|
261
|
+
}
|
|
262
|
+
}))
|
|
263
|
+
.pipe(Effect.orDie),
|
|
264
|
+
findAccess: (hash) => rows(`SELECT ${GRANT_COLUMNS}, ${epochMs(`"t"."expires_at"`)} AS "access_expires_at", ` +
|
|
265
|
+
`"g"."identity_id" IS NOT NULL AS "channel", ` +
|
|
266
|
+
`(SELECT "i"."provider" FROM "${USER_IDENTITY_TABLE}" AS "i" ` +
|
|
267
|
+
`WHERE "i"."id" = "g"."identity_id") AS "identity_provider", ` +
|
|
268
|
+
`"t"."expires_at" <= clock_timestamp() AS "expired", ` +
|
|
269
|
+
`"g"."revoked_at" IS NOT NULL AS "revoked" FROM ${TOKENS} AS "t" ` +
|
|
270
|
+
`JOIN ${GRANTS} AS "g" ON "g"."id" = "t"."grant_id" ` +
|
|
271
|
+
`WHERE "t"."hash" = $1 AND "t"."kind" = 'access' ` +
|
|
272
|
+
// A channel session lives while the member's channel account does.
|
|
273
|
+
`AND ("g"."identity_id" IS NULL OR EXISTS (` +
|
|
274
|
+
`SELECT 1 FROM ${CHANNEL_IDENTITIES_FROM} WHERE "i"."id" = "g"."identity_id" ` +
|
|
275
|
+
`AND "i"."user_id" = "g"."user_id" AND ${LIVE_CHANNEL_IDENTITY}))`, [hash]).pipe(Effect.flatMap(([row]) => {
|
|
276
|
+
if (row === undefined) {
|
|
277
|
+
return rejectedAccessToken("token_not_found");
|
|
278
|
+
}
|
|
279
|
+
const grant = grantOf(row);
|
|
280
|
+
if (row.revoked === true) {
|
|
281
|
+
return rejectedAccessToken("grant_revoked", grant.id);
|
|
282
|
+
}
|
|
283
|
+
if (row.expired === true) {
|
|
284
|
+
return rejectedAccessToken("token_expired", grant.id);
|
|
285
|
+
}
|
|
286
|
+
return Effect.succeed(row.channel === true
|
|
287
|
+
? {
|
|
288
|
+
...grant,
|
|
289
|
+
expiresAt: new Date(Number(row.access_expires_at)),
|
|
290
|
+
identityProvider: String(row.identity_provider),
|
|
291
|
+
}
|
|
292
|
+
: grant);
|
|
293
|
+
})),
|
|
294
|
+
findGrantOfToken: (hash) => rows(`SELECT ${GRANT_COLUMNS} FROM ${TOKENS} AS "t" ` +
|
|
295
|
+
`JOIN ${GRANTS} AS "g" ON "g"."id" = "t"."grant_id" WHERE "t"."hash" = $1`, [hash]).pipe(Effect.map(([row]) => (row === undefined ? undefined : grantOf(row)))),
|
|
296
|
+
revokeGrant: (id) => rows(`UPDATE ${GRANTS} SET "revoked_at" = now() WHERE "id" = $1::uuid AND "revoked_at" IS NULL`, [id]).pipe(Effect.asVoid),
|
|
297
|
+
memberPrincipal: (userId) => resolveMemberById(ontology, userId).pipe(Effect.provideService(SqlClient.SqlClient, sql)),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { ActionRuntime } from "../runtime-source.js";
|
|
2
|
+
import { Duration, Effect, Schema } from "effect";
|
|
3
|
+
import { SqlClient } from "effect/unstable/sql";
|
|
4
|
+
import { type AnyAction } from "../action.js";
|
|
5
|
+
import { ConnectionError, ConnectionTransport } from "../connection.js";
|
|
6
|
+
import { type ActionError } from "../errors.js";
|
|
7
|
+
import type { Ontology } from "../ontology.js";
|
|
8
|
+
import { type Principal } from "../runtime.js";
|
|
9
|
+
import { TriggerInputInvalid, UnknownAction, WorkflowRecoveryUnavailable } from "./errors.js";
|
|
10
|
+
import { Edit } from "./history.js";
|
|
11
|
+
import type { WriteGuard } from "./writes.js";
|
|
12
|
+
/** An action that committed, as after-commit effects receive it. */
|
|
13
|
+
export interface CommittedAction {
|
|
14
|
+
readonly entity: string;
|
|
15
|
+
readonly action: string;
|
|
16
|
+
readonly actionId: string;
|
|
17
|
+
readonly principal: Principal;
|
|
18
|
+
/** The decoded input. */
|
|
19
|
+
readonly input: unknown;
|
|
20
|
+
readonly result: unknown;
|
|
21
|
+
readonly edits: ReadonlyArray<Edit>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Runs after the transaction commits, never inside it: starting a workflow that notifies the team
|
|
25
|
+
* or calls a webhook. A failure is logged; the action has committed and still succeeds.
|
|
26
|
+
*/
|
|
27
|
+
export type AfterCommit<R = never> = (committed: CommittedAction) => Effect.Effect<void, unknown, R>;
|
|
28
|
+
export interface ActionRequest<R = never> {
|
|
29
|
+
readonly runtime?: ActionRuntime;
|
|
30
|
+
readonly entity: string;
|
|
31
|
+
readonly action: string;
|
|
32
|
+
/** The input as the caller sent it; the action's input schema decodes it. */
|
|
33
|
+
readonly input: unknown;
|
|
34
|
+
readonly principal: Principal;
|
|
35
|
+
readonly options?: {
|
|
36
|
+
/**
|
|
37
|
+
* Decode the input and check the permission, without running `prepare` or the handler. A
|
|
38
|
+
* generated action of a principal whose permission is scoped also runs its write in a
|
|
39
|
+
* transaction that is always rolled back, so that the scope's checks answer as they would.
|
|
40
|
+
*/
|
|
41
|
+
readonly validateOnly?: boolean;
|
|
42
|
+
readonly idempotencyKey?: string;
|
|
43
|
+
readonly createIntent?: string;
|
|
44
|
+
/** Internal channel lifecycle execution; marker commits atomically with the handler. */
|
|
45
|
+
readonly newUserHook?: true;
|
|
46
|
+
/**
|
|
47
|
+
* Describe what a person confirms before the action runs, in the chat's language, with the
|
|
48
|
+
* action's `confirm`: decode the input, check the permission, and answer with the confirmation,
|
|
49
|
+
* or `null` for an action without one. Nothing is prepared or written.
|
|
50
|
+
*/
|
|
51
|
+
readonly confirm?: {
|
|
52
|
+
readonly locale: string;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
readonly branchId?: string;
|
|
56
|
+
readonly afterCommit?: ReadonlyArray<AfterCommit<R>>;
|
|
57
|
+
/** The request's id, which `prepare` and the handler receive for logs; the action id by default. */
|
|
58
|
+
readonly requestId?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Sends the calls of `prepare` to the declared connections, bound to this request. The
|
|
61
|
+
* {@link ConnectionTransport} in context, such as `Connections.test`, is used when it is not set.
|
|
62
|
+
*/
|
|
63
|
+
readonly connections?: ConnectionTransport["Service"];
|
|
64
|
+
}
|
|
65
|
+
/** How long an action's `confirm` may take: a person waits for the card it describes. */
|
|
66
|
+
export declare const CONFIRM_TIMEOUT: Duration.Duration;
|
|
67
|
+
/** How long `prepare` may take, connection calls included; each call has its own 30 s deadline. */
|
|
68
|
+
export declare const PREPARE_TIMEOUT: Duration.Duration;
|
|
69
|
+
export declare const ActionValidation: Schema.Struct<{
|
|
70
|
+
readonly ok: Schema.Boolean;
|
|
71
|
+
readonly issues: Schema.$Array<Schema.Struct<{
|
|
72
|
+
readonly path: Schema.$Array<Schema.Union<readonly [Schema.String, Schema.Number]>>;
|
|
73
|
+
readonly message: Schema.String;
|
|
74
|
+
}>>;
|
|
75
|
+
}>;
|
|
76
|
+
export type ActionValidation = typeof ActionValidation.Type;
|
|
77
|
+
/** The response of an action: its result, the input's validation, and the records it changed. */
|
|
78
|
+
export declare const ActionOutcome: Schema.Struct<{
|
|
79
|
+
readonly result: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
80
|
+
readonly validation: Schema.Struct<{
|
|
81
|
+
readonly ok: Schema.Boolean;
|
|
82
|
+
readonly issues: Schema.$Array<Schema.Struct<{
|
|
83
|
+
readonly path: Schema.$Array<Schema.Union<readonly [Schema.String, Schema.Number]>>;
|
|
84
|
+
readonly message: Schema.String;
|
|
85
|
+
}>>;
|
|
86
|
+
}>;
|
|
87
|
+
readonly edits: Schema.$Array<Schema.Struct<{
|
|
88
|
+
readonly entity: Schema.String;
|
|
89
|
+
readonly id: Schema.String;
|
|
90
|
+
readonly kind: Schema.Literals<readonly ["create", "update", "delete", "link", "unlink"]>;
|
|
91
|
+
readonly changes: Schema.$Record<Schema.String, Schema.Struct<{
|
|
92
|
+
readonly before: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
93
|
+
readonly after: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
94
|
+
}>>;
|
|
95
|
+
}>>;
|
|
96
|
+
}>;
|
|
97
|
+
export interface ActionOutcome<Result = unknown> {
|
|
98
|
+
/** `null` when the input was invalid, under `validateOnly`, and for actions without a result. */
|
|
99
|
+
readonly result: Result | null;
|
|
100
|
+
readonly validation: ActionValidation;
|
|
101
|
+
readonly edits: ReadonlyArray<Edit>;
|
|
102
|
+
}
|
|
103
|
+
/** An action and every permission a principal needs to run it. */
|
|
104
|
+
export interface FoundAction {
|
|
105
|
+
readonly action: AnyAction;
|
|
106
|
+
readonly permissions: ReadonlyArray<string>;
|
|
107
|
+
/**
|
|
108
|
+
* A generated `create`, `update`, `delete`, `upsert_by_<property>`, `link`, `unlink` or member
|
|
109
|
+
* action, whose input and result are in wire names.
|
|
110
|
+
*/
|
|
111
|
+
readonly generated: boolean;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The entity's authored action of that name with the permission it requires, or else its generated
|
|
115
|
+
* one with the permissions named after it.
|
|
116
|
+
*/
|
|
117
|
+
export declare function resolveAction(ontology: Ontology, entityName: string, actionName: string): FoundAction | undefined;
|
|
118
|
+
/**
|
|
119
|
+
* The scopes the principal's grants put on an action's writes of its own entity. An authored action
|
|
120
|
+
* checks every write of its entity against the scope of its permission. A generated action checks
|
|
121
|
+
* records it creates against `<entity>:create` and records it changes against the permission of its
|
|
122
|
+
* verb; `upsert_by_<property>` checks against `create` or `update`, whichever it does. `undefined`
|
|
123
|
+
* when every permission is held unscoped, so that unscoped principals write as before.
|
|
124
|
+
*/
|
|
125
|
+
export declare function writeGuard(entity: string, found: FoundAction, principal: Principal): WriteGuard | undefined;
|
|
126
|
+
/** The entity's authored action of that name, or else its generated one. */
|
|
127
|
+
export declare function findAction(ontology: Ontology, entityName: string, actionName: string): AnyAction | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* Runs an action the way every action runs, authored or generated:
|
|
130
|
+
*
|
|
131
|
+
* 1. decode the input with the action's schema; issues are returned, not raised;
|
|
132
|
+
* 2. check that the principal's permissions cover the action's (PermissionDenied);
|
|
133
|
+
* 3. with `validateOnly`, stop, unless the action is generated, the principal's permission for it is
|
|
134
|
+
* scoped and the input holds no upload: then run step 6 in a transaction that is
|
|
135
|
+
* always rolled back, and answer a NotFound or ScopeViolated of the writes as a validation issue;
|
|
136
|
+
* 4. reauthorize and replay a committed blob action, if its idempotency key matches;
|
|
137
|
+
* otherwise run `prepare`, when the action has one, without a transaction: reads and the declared
|
|
138
|
+
* connections only, under {@link PREPARE_TIMEOUT};
|
|
139
|
+
* 5. without a handler, answer with what `prepare` returned; when a trigger matches the action, make
|
|
140
|
+
* sure through the {@link WorkflowStarter} in context that a recovery run will sweep after the
|
|
141
|
+
* transaction's deadline, and refuse the action with WorkflowRecoveryUnavailable when it cannot;
|
|
142
|
+
* 6. open a transaction and run the handler with what `prepare` returned and the runtime, which
|
|
143
|
+
* records history rows for every write, under one action id, with `created_by`/`updated_by` set to
|
|
144
|
+
* the principal;
|
|
145
|
+
* 7. evaluate the action triggers that match the action, and insert the starts they decide, in the
|
|
146
|
+
* same transaction: a trigger function that throws rolls the action back, an input its workflow
|
|
147
|
+
* does not accept fails it with TriggerInputInvalid;
|
|
148
|
+
* 8. commit, or roll back on any failure, defect or interruption; an action explicitly declared
|
|
149
|
+
* retryOnDeadlock may repeat steps 6–8 after a confirmed deadlock rollback, with fresh state;
|
|
150
|
+
* 9. start the decided runs through the {@link WorkflowStarter} in context, then run the
|
|
151
|
+
* after-commit effects, outside the transaction.
|
|
152
|
+
*
|
|
153
|
+
* Database failures are defects.
|
|
154
|
+
*/
|
|
155
|
+
export declare function runAction<R = never>(ontology: Ontology, request: ActionRequest<R>): Effect.Effect<ActionOutcome, ActionError | ConnectionError | UnknownAction | TriggerInputInvalid | WorkflowRecoveryUnavailable, SqlClient.SqlClient | R>;
|