@retinue/agentkit 0.1.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 +22 -0
- package/README.md +310 -0
- package/dist/adapters/bullmq/consumer.d.ts +33 -0
- package/dist/adapters/bullmq/consumer.js +41 -0
- package/dist/adapters/bullmq/dispatcher.d.ts +74 -0
- package/dist/adapters/bullmq/dispatcher.js +160 -0
- package/dist/adapters/bullmq/export.d.ts +31 -0
- package/dist/adapters/bullmq/export.js +53 -0
- package/dist/adapters/bullmq/extraction.d.ts +42 -0
- package/dist/adapters/bullmq/extraction.js +63 -0
- package/dist/adapters/bullmq/index.d.ts +13 -0
- package/dist/adapters/bullmq/index.js +13 -0
- package/dist/adapters/bullmq/lock.d.ts +77 -0
- package/dist/adapters/bullmq/lock.js +126 -0
- package/dist/adapters/bullmq/queue.d.ts +50 -0
- package/dist/adapters/bullmq/queue.js +81 -0
- package/dist/adapters/memory/artifact-exports.d.ts +11 -0
- package/dist/adapters/memory/artifact-exports.js +102 -0
- package/dist/adapters/memory/artifacts.d.ts +15 -0
- package/dist/adapters/memory/artifacts.js +134 -0
- package/dist/adapters/memory/blobs.d.ts +7 -0
- package/dist/adapters/memory/blobs.js +27 -0
- package/dist/adapters/memory/evaluation.d.ts +18 -0
- package/dist/adapters/memory/evaluation.js +148 -0
- package/dist/adapters/memory/files.d.ts +27 -0
- package/dist/adapters/memory/files.js +0 -0
- package/dist/adapters/memory/flows.d.ts +16 -0
- package/dist/adapters/memory/flows.js +117 -0
- package/dist/adapters/memory/hitl.d.ts +9 -0
- package/dist/adapters/memory/hitl.js +130 -0
- package/dist/adapters/memory/idempotency.d.ts +13 -0
- package/dist/adapters/memory/idempotency.js +32 -0
- package/dist/adapters/memory/index.d.ts +39 -0
- package/dist/adapters/memory/index.js +107 -0
- package/dist/adapters/memory/knowledge.d.ts +43 -0
- package/dist/adapters/memory/knowledge.js +248 -0
- package/dist/adapters/memory/mcp.d.ts +9 -0
- package/dist/adapters/memory/mcp.js +37 -0
- package/dist/adapters/memory/message-store.d.ts +17 -0
- package/dist/adapters/memory/message-store.js +70 -0
- package/dist/adapters/memory/principal-memory.d.ts +7 -0
- package/dist/adapters/memory/principal-memory.js +83 -0
- package/dist/adapters/memory/runtime.d.ts +29 -0
- package/dist/adapters/memory/runtime.js +0 -0
- package/dist/adapters/memory/sessions.d.ts +29 -0
- package/dist/adapters/memory/sessions.js +0 -0
- package/dist/adapters/memory/skills.d.ts +10 -0
- package/dist/adapters/memory/skills.js +41 -0
- package/dist/adapters/memory/thread-summary.d.ts +7 -0
- package/dist/adapters/memory/thread-summary.js +29 -0
- package/dist/adapters/memory/usage-limits.d.ts +13 -0
- package/dist/adapters/memory/usage-limits.js +72 -0
- package/dist/adapters/memory/usage.d.ts +16 -0
- package/dist/adapters/memory/usage.js +279 -0
- package/dist/adapters/otel/index.d.ts +111 -0
- package/dist/adapters/otel/index.js +133 -0
- package/dist/adapters/postgres/artifact-exports.d.ts +12 -0
- package/dist/adapters/postgres/artifact-exports.js +117 -0
- package/dist/adapters/postgres/artifacts.d.ts +16 -0
- package/dist/adapters/postgres/artifacts.js +172 -0
- package/dist/adapters/postgres/checkpoint-store.d.ts +16 -0
- package/dist/adapters/postgres/checkpoint-store.js +34 -0
- package/dist/adapters/postgres/config.d.ts +15 -0
- package/dist/adapters/postgres/config.js +187 -0
- package/dist/adapters/postgres/conversation-store.d.ts +4 -0
- package/dist/adapters/postgres/conversation-store.js +82 -0
- package/dist/adapters/postgres/evaluation.d.ts +17 -0
- package/dist/adapters/postgres/evaluation.js +193 -0
- package/dist/adapters/postgres/file-content.d.ts +30 -0
- package/dist/adapters/postgres/file-content.js +111 -0
- package/dist/adapters/postgres/files.d.ts +19 -0
- package/dist/adapters/postgres/files.js +209 -0
- package/dist/adapters/postgres/flows.d.ts +20 -0
- package/dist/adapters/postgres/flows.js +206 -0
- package/dist/adapters/postgres/hitl.d.ts +5 -0
- package/dist/adapters/postgres/hitl.js +247 -0
- package/dist/adapters/postgres/index.d.ts +35 -0
- package/dist/adapters/postgres/index.js +35 -0
- package/dist/adapters/postgres/knowledge.d.ts +48 -0
- package/dist/adapters/postgres/knowledge.js +255 -0
- package/dist/adapters/postgres/memory.d.ts +14 -0
- package/dist/adapters/postgres/memory.js +194 -0
- package/dist/adapters/postgres/message-store.d.ts +11 -0
- package/dist/adapters/postgres/message-store.js +145 -0
- package/dist/adapters/postgres/migrations.d.ts +69 -0
- package/dist/adapters/postgres/migrations.js +1594 -0
- package/dist/adapters/postgres/pg-executor.d.ts +19 -0
- package/dist/adapters/postgres/pg-executor.js +32 -0
- package/dist/adapters/postgres/retention.d.ts +26 -0
- package/dist/adapters/postgres/retention.js +59 -0
- package/dist/adapters/postgres/rollups.d.ts +17 -0
- package/dist/adapters/postgres/rollups.js +267 -0
- package/dist/adapters/postgres/run-coordinator.d.ts +5 -0
- package/dist/adapters/postgres/run-coordinator.js +98 -0
- package/dist/adapters/postgres/run-event-log.d.ts +26 -0
- package/dist/adapters/postgres/run-event-log.js +30 -0
- package/dist/adapters/postgres/run-store.d.ts +4 -0
- package/dist/adapters/postgres/run-store.js +199 -0
- package/dist/adapters/postgres/schema.d.ts +39 -0
- package/dist/adapters/postgres/schema.js +70 -0
- package/dist/adapters/postgres/session-state.d.ts +7 -0
- package/dist/adapters/postgres/session-state.js +99 -0
- package/dist/adapters/postgres/sql.d.ts +8 -0
- package/dist/adapters/postgres/sql.js +2 -0
- package/dist/adapters/postgres/transaction.d.ts +37 -0
- package/dist/adapters/postgres/transaction.js +93 -0
- package/dist/adapters/postgres/unit-of-work.d.ts +18 -0
- package/dist/adapters/postgres/unit-of-work.js +8 -0
- package/dist/adapters/postgres/usage-limits.d.ts +15 -0
- package/dist/adapters/postgres/usage-limits.js +136 -0
- package/dist/adapters/postgres/usage.d.ts +15 -0
- package/dist/adapters/postgres/usage.js +226 -0
- package/dist/adapters/redis/index.d.ts +9 -0
- package/dist/adapters/redis/index.js +9 -0
- package/dist/adapters/redis/realtime.d.ts +74 -0
- package/dist/adapters/redis/realtime.js +112 -0
- package/dist/adapters/supabase/index.d.ts +88 -0
- package/dist/adapters/supabase/index.js +84 -0
- package/dist/adapters/supabase/realtime.d.ts +30 -0
- package/dist/adapters/supabase/realtime.js +53 -0
- package/dist/adapters/supabase/rls.d.ts +99 -0
- package/dist/adapters/supabase/rls.js +216 -0
- package/dist/adapters/supabase/storage.d.ts +50 -0
- package/dist/adapters/supabase/storage.js +207 -0
- package/dist/agents/agent.d.ts +66 -0
- package/dist/agents/agent.js +209 -0
- package/dist/agents/define.d.ts +21 -0
- package/dist/agents/define.js +63 -0
- package/dist/agents/engine.d.ts +98 -0
- package/dist/agents/engine.js +462 -0
- package/dist/agents/index.d.ts +50 -0
- package/dist/agents/index.js +17 -0
- package/dist/artifacts/index.d.ts +114 -0
- package/dist/artifacts/index.js +219 -0
- package/dist/authorization/index.d.ts +76 -0
- package/dist/authorization/index.js +76 -0
- package/dist/capabilities/index.d.ts +120 -0
- package/dist/capabilities/index.js +167 -0
- package/dist/capabilities/runtime.d.ts +89 -0
- package/dist/capabilities/runtime.js +84 -0
- package/dist/citations/index.d.ts +161 -0
- package/dist/citations/index.js +182 -0
- package/dist/context/assembler.d.ts +82 -0
- package/dist/context/assembler.js +129 -0
- package/dist/context/compaction.d.ts +45 -0
- package/dist/context/compaction.js +55 -0
- package/dist/context/index.d.ts +75 -0
- package/dist/context/index.js +17 -0
- package/dist/core/content-parts.d.ts +194 -0
- package/dist/core/content-parts.js +23 -0
- package/dist/core/context.d.ts +51 -0
- package/dist/core/context.js +9 -0
- package/dist/core/env.d.ts +25 -0
- package/dist/core/env.js +41 -0
- package/dist/core/errors.d.ts +30 -0
- package/dist/core/errors.js +65 -0
- package/dist/core/events.d.ts +139 -0
- package/dist/core/events.js +99 -0
- package/dist/core/ids.d.ts +52 -0
- package/dist/core/ids.js +13 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.js +9 -0
- package/dist/core/tokens.d.ts +22 -0
- package/dist/core/tokens.js +22 -0
- package/dist/core/validation.d.ts +34 -0
- package/dist/core/validation.js +176 -0
- package/dist/documents/extraction.d.ts +121 -0
- package/dist/documents/extraction.js +293 -0
- package/dist/documents/index.d.ts +199 -0
- package/dist/documents/index.js +65 -0
- package/dist/documents/parsers/pdf.d.ts +47 -0
- package/dist/documents/parsers/pdf.js +508 -0
- package/dist/documents/parsers/text.d.ts +59 -0
- package/dist/documents/parsers/text.js +325 -0
- package/dist/documents/read-tool.d.ts +52 -0
- package/dist/documents/read-tool.js +109 -0
- package/dist/documents/render.d.ts +29 -0
- package/dist/documents/render.js +59 -0
- package/dist/documents/vision.d.ts +159 -0
- package/dist/documents/vision.js +214 -0
- package/dist/entries/adapters-bullmq.d.ts +8 -0
- package/dist/entries/adapters-bullmq.js +8 -0
- package/dist/entries/adapters-otel.d.ts +13 -0
- package/dist/entries/adapters-otel.js +13 -0
- package/dist/entries/adapters-postgres.d.ts +10 -0
- package/dist/entries/adapters-postgres.js +10 -0
- package/dist/entries/adapters-redis.d.ts +3 -0
- package/dist/entries/adapters-redis.js +3 -0
- package/dist/entries/context.d.ts +20 -0
- package/dist/entries/context.js +20 -0
- package/dist/entries/flows.d.ts +15 -0
- package/dist/entries/flows.js +15 -0
- package/dist/entries/hitl.d.ts +10 -0
- package/dist/entries/hitl.js +10 -0
- package/dist/entries/knowledge.d.ts +18 -0
- package/dist/entries/knowledge.js +19 -0
- package/dist/entries/mcp.d.ts +10 -0
- package/dist/entries/mcp.js +10 -0
- package/dist/entries/observability.d.ts +14 -0
- package/dist/entries/observability.js +16 -0
- package/dist/entries/persistence.d.ts +11 -0
- package/dist/entries/persistence.js +11 -0
- package/dist/entries/providers.d.ts +14 -0
- package/dist/entries/providers.js +14 -0
- package/dist/entries/runtime.d.ts +13 -0
- package/dist/entries/runtime.js +13 -0
- package/dist/entries/server.d.ts +24 -0
- package/dist/entries/server.js +24 -0
- package/dist/entries/tools.d.ts +21 -0
- package/dist/entries/tools.js +21 -0
- package/dist/entries/usage.d.ts +10 -0
- package/dist/entries/usage.js +10 -0
- package/dist/evaluation/gate.d.ts +168 -0
- package/dist/evaluation/gate.js +180 -0
- package/dist/evaluation/graders.d.ts +125 -0
- package/dist/evaluation/graders.js +203 -0
- package/dist/evaluation/index.d.ts +120 -0
- package/dist/evaluation/index.js +183 -0
- package/dist/evaluation/judge.d.ts +75 -0
- package/dist/evaluation/judge.js +111 -0
- package/dist/export/index.d.ts +162 -0
- package/dist/export/index.js +363 -0
- package/dist/export/markdown.d.ts +19 -0
- package/dist/export/markdown.js +29 -0
- package/dist/export/pdf.d.ts +73 -0
- package/dist/export/pdf.js +407 -0
- package/dist/files/context.d.ts +97 -0
- package/dist/files/context.js +185 -0
- package/dist/files/index.d.ts +210 -0
- package/dist/files/index.js +338 -0
- package/dist/files/read-tool.d.ts +81 -0
- package/dist/files/read-tool.js +163 -0
- package/dist/files/turn-parts.d.ts +96 -0
- package/dist/files/turn-parts.js +171 -0
- package/dist/flows/index.d.ts +270 -0
- package/dist/flows/index.js +62 -0
- package/dist/flows/interpreter.d.ts +146 -0
- package/dist/flows/interpreter.js +426 -0
- package/dist/flows/runner.d.ts +145 -0
- package/dist/flows/runner.js +270 -0
- package/dist/graphql/index.d.ts +8 -0
- package/dist/graphql/index.js +8 -0
- package/dist/graphql/resolvers.d.ts +237 -0
- package/dist/graphql/resolvers.js +253 -0
- package/dist/graphql/schema.d.ts +11 -0
- package/dist/graphql/schema.js +258 -0
- package/dist/graphql/sse.d.ts +77 -0
- package/dist/graphql/sse.js +100 -0
- package/dist/hitl/approved-execution.d.ts +127 -0
- package/dist/hitl/approved-execution.js +177 -0
- package/dist/hitl/index.d.ts +79 -0
- package/dist/hitl/index.js +12 -0
- package/dist/hitl/service.d.ts +221 -0
- package/dist/hitl/service.js +268 -0
- package/dist/idempotency/index.d.ts +70 -0
- package/dist/idempotency/index.js +59 -0
- package/dist/index.d.ts +103 -0
- package/dist/index.js +60 -0
- package/dist/knowledge/chunking.d.ts +57 -0
- package/dist/knowledge/chunking.js +158 -0
- package/dist/knowledge/index.d.ts +119 -0
- package/dist/knowledge/index.js +166 -0
- package/dist/knowledge/retrieval.d.ts +146 -0
- package/dist/knowledge/retrieval.js +170 -0
- package/dist/loadtest/harness.d.ts +168 -0
- package/dist/loadtest/harness.js +507 -0
- package/dist/loadtest/index.d.ts +13 -0
- package/dist/loadtest/index.js +13 -0
- package/dist/loadtest/injection.d.ts +89 -0
- package/dist/loadtest/injection.js +147 -0
- package/dist/loadtest/metrics.d.ts +197 -0
- package/dist/loadtest/metrics.js +160 -0
- package/dist/loadtest/runbooks.d.ts +28 -0
- package/dist/loadtest/runbooks.js +159 -0
- package/dist/loadtest/scenario.d.ts +104 -0
- package/dist/loadtest/scenario.js +208 -0
- package/dist/mcp/egress.d.ts +53 -0
- package/dist/mcp/egress.js +115 -0
- package/dist/mcp/index.d.ts +93 -0
- package/dist/mcp/index.js +33 -0
- package/dist/mcp/provider.d.ts +62 -0
- package/dist/mcp/provider.js +0 -0
- package/dist/models/index.d.ts +98 -0
- package/dist/models/index.js +74 -0
- package/dist/models/pricing.d.ts +24 -0
- package/dist/models/pricing.js +37 -0
- package/dist/models/provider-factory.d.ts +31 -0
- package/dist/models/provider-factory.js +67 -0
- package/dist/models/streaming.d.ts +145 -0
- package/dist/models/streaming.js +272 -0
- package/dist/models/vision.d.ts +38 -0
- package/dist/models/vision.js +62 -0
- package/dist/persistence/index.d.ts +1654 -0
- package/dist/persistence/index.js +226 -0
- package/dist/principal-memory/index.d.ts +106 -0
- package/dist/principal-memory/index.js +89 -0
- package/dist/retention/index.d.ts +89 -0
- package/dist/retention/index.js +70 -0
- package/dist/runtime/checkpoint.d.ts +37 -0
- package/dist/runtime/checkpoint.js +22 -0
- package/dist/runtime/index.d.ts +118 -0
- package/dist/runtime/index.js +69 -0
- package/dist/runtime/retry.d.ts +95 -0
- package/dist/runtime/retry.js +126 -0
- package/dist/runtime/serialization.d.ts +85 -0
- package/dist/runtime/serialization.js +95 -0
- package/dist/runtime/streaming.d.ts +54 -0
- package/dist/runtime/streaming.js +115 -0
- package/dist/runtime/worker.d.ts +130 -0
- package/dist/runtime/worker.js +405 -0
- package/dist/security/checklist.d.ts +53 -0
- package/dist/security/checklist.js +204 -0
- package/dist/security/findings.d.ts +56 -0
- package/dist/security/findings.js +168 -0
- package/dist/security/index.d.ts +14 -0
- package/dist/security/index.js +14 -0
- package/dist/security/prompt-safety.d.ts +100 -0
- package/dist/security/prompt-safety.js +133 -0
- package/dist/server/boot.d.ts +32 -0
- package/dist/server/boot.js +36 -0
- package/dist/server/cli-worker.d.ts +37 -0
- package/dist/server/cli-worker.js +151 -0
- package/dist/server/cli.d.ts +27 -0
- package/dist/server/cli.js +74 -0
- package/dist/server/config.d.ts +42 -0
- package/dist/server/config.js +127 -0
- package/dist/server/health.d.ts +59 -0
- package/dist/server/health.js +90 -0
- package/dist/server/host.d.ts +39 -0
- package/dist/server/host.js +124 -0
- package/dist/server/index.d.ts +15 -0
- package/dist/server/index.js +15 -0
- package/dist/server/main.d.ts +16 -0
- package/dist/server/main.js +31 -0
- package/dist/server/sse-route.d.ts +21 -0
- package/dist/server/sse-route.js +282 -0
- package/dist/skills/index.d.ts +67 -0
- package/dist/skills/index.js +31 -0
- package/dist/skills/resolver.d.ts +54 -0
- package/dist/skills/resolver.js +121 -0
- package/dist/teams/index.d.ts +93 -0
- package/dist/teams/index.js +207 -0
- package/dist/telemetry/index.d.ts +157 -0
- package/dist/telemetry/index.js +71 -0
- package/dist/telemetry/instrument.d.ts +108 -0
- package/dist/telemetry/instrument.js +232 -0
- package/dist/telemetry/log-events.d.ts +17 -0
- package/dist/telemetry/log-events.js +58 -0
- package/dist/telemetry/metrics.d.ts +123 -0
- package/dist/telemetry/metrics.js +135 -0
- package/dist/telemetry/noop.d.ts +39 -0
- package/dist/telemetry/noop.js +143 -0
- package/dist/telemetry/redaction.d.ts +64 -0
- package/dist/telemetry/redaction.js +153 -0
- package/dist/telemetry/spans.d.ts +56 -0
- package/dist/telemetry/spans.js +78 -0
- package/dist/telemetry/trace-context.d.ts +55 -0
- package/dist/telemetry/trace-context.js +60 -0
- package/dist/toolkit/compute.d.ts +53 -0
- package/dist/toolkit/compute.js +152 -0
- package/dist/toolkit/data.d.ts +98 -0
- package/dist/toolkit/data.js +235 -0
- package/dist/toolkit/http.d.ts +113 -0
- package/dist/toolkit/http.js +205 -0
- package/dist/toolkit/index.d.ts +21 -0
- package/dist/toolkit/index.js +17 -0
- package/dist/toolkit/web.d.ts +107 -0
- package/dist/toolkit/web.js +147 -0
- package/dist/tools/define.d.ts +25 -0
- package/dist/tools/define.js +45 -0
- package/dist/tools/delegating.d.ts +132 -0
- package/dist/tools/delegating.js +211 -0
- package/dist/tools/index.d.ts +129 -0
- package/dist/tools/index.js +33 -0
- package/dist/tools/library/compute.d.ts +11 -0
- package/dist/tools/library/compute.js +46 -0
- package/dist/tools/library/data.d.ts +16 -0
- package/dist/tools/library/data.js +92 -0
- package/dist/tools/library/http.d.ts +28 -0
- package/dist/tools/library/http.js +71 -0
- package/dist/tools/library/index.d.ts +97 -0
- package/dist/tools/library/index.js +134 -0
- package/dist/tools/library/knowledge.d.ts +39 -0
- package/dist/tools/library/knowledge.js +58 -0
- package/dist/tools/library/web.d.ts +19 -0
- package/dist/tools/library/web.js +65 -0
- package/dist/tools/meta-tools.d.ts +19 -0
- package/dist/tools/meta-tools.js +36 -0
- package/dist/tools/registry.d.ts +146 -0
- package/dist/tools/registry.js +291 -0
- package/dist/usage/index.d.ts +105 -0
- package/dist/usage/index.js +20 -0
- package/dist/usage/quota.d.ts +258 -0
- package/dist/usage/quota.js +510 -0
- package/dist/usage/recorder.d.ts +29 -0
- package/dist/usage/recorder.js +96 -0
- package/dist/usage/rollups.d.ts +121 -0
- package/dist/usage/rollups.js +157 -0
- package/dist/worker/export.d.ts +57 -0
- package/dist/worker/export.js +81 -0
- package/dist/worker/extraction.d.ts +57 -0
- package/dist/worker/extraction.js +84 -0
- package/dist/worker/main.d.ts +103 -0
- package/dist/worker/main.js +159 -0
- package/package.json +187 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supabase adapter — Postgres stores + RLS + Realtime (#104).
|
|
3
|
+
*
|
|
4
|
+
* Supabase *is* Postgres, so every store here is an **alias** of the PostgreSQL implementation rather
|
|
5
|
+
* than a second one. That is deliberate and it is the whole reason the Supabase column can be trusted:
|
|
6
|
+
* one implementation cannot drift from itself. The conformance suite still runs the column, because
|
|
7
|
+
* an alias can be repointed and because RLS changes the executor's effective privileges — "same code"
|
|
8
|
+
* is a claim worth re-checking rather than assuming.
|
|
9
|
+
*
|
|
10
|
+
* What is genuinely Supabase-specific lives in `rls.ts` (policies, tenant binding) and `realtime.ts`
|
|
11
|
+
* (the live event channel). Both carry no `@supabase/supabase-js` dependency: the host app adapts its
|
|
12
|
+
* client to the small interfaces here, so this package stays deployable without one.
|
|
13
|
+
*/
|
|
14
|
+
import type { AdapterCapability } from "../../persistence/index.js";
|
|
15
|
+
export { createPostgresConversationStore as createSupabaseConversationStore } from "../postgres/conversation-store.js";
|
|
16
|
+
export { createPostgresSessionStateStore as createSupabaseSessionStateStore, createPostgresThreadSummaryStore as createSupabaseThreadSummaryStore, } from "../postgres/session-state.js";
|
|
17
|
+
export { createPostgresConversationBindingStore as createSupabaseConversationBindingStore, createPostgresMessageStore as createSupabaseMessageStore, createPostgresAgentStore as createSupabaseAgentStore, } from "../postgres/message-store.js";
|
|
18
|
+
export { createPostgresConversationRunCoordinator as createSupabaseConversationRunCoordinator } from "../postgres/run-coordinator.js";
|
|
19
|
+
export { createPostgresUnitOfWork as createSupabaseUnitOfWork } from "../postgres/unit-of-work.js";
|
|
20
|
+
export { createPostgresRunStore as createSupabaseRunStore } from "../postgres/run-store.js";
|
|
21
|
+
export { createPostgresRunEventLog as createSupabaseRunEventLog } from "../postgres/run-event-log.js";
|
|
22
|
+
export { createPostgresCheckpointStore as createSupabaseCheckpointStore } from "../postgres/checkpoint-store.js";
|
|
23
|
+
export { createPostgresInteractionStore as createSupabaseInteractionStore, createPostgresApprovalGrantStore as createSupabaseApprovalGrantStore, } from "../postgres/hitl.js";
|
|
24
|
+
export { createPostgresUsageStore as createSupabaseUsageStore, createPostgresIdempotencyStore as createSupabaseIdempotencyStore, } from "../postgres/usage.js";
|
|
25
|
+
export { createPostgresUsageLimitStore as createSupabaseUsageLimitStore } from "../postgres/usage-limits.js";
|
|
26
|
+
export { createPostgresSkillStore as createSupabaseSkillStore, createPostgresMcpConnectionStore as createSupabaseMcpConnectionStore, } from "../postgres/config.js";
|
|
27
|
+
export { createPostgresPrincipalMemoryStore as createSupabasePrincipalMemoryStore, createPostgresBlobStore as createSupabaseBlobStore, } from "../postgres/memory.js";
|
|
28
|
+
/**
|
|
29
|
+
* File *metadata* aliases to Postgres. File *bytes* do not, and this is the one port where Supabase is not
|
|
30
|
+
* simply Postgres under another name.
|
|
31
|
+
*
|
|
32
|
+
* `0013_files` keeps metadata only, so `FileMetadataStore` is an alias like every other port. The bytes live
|
|
33
|
+
* in Supabase Storage, which has its own adapter in `./storage.js` — a genuine second implementation, not an
|
|
34
|
+
* alias, because there is no Postgres factory to alias to. `notApplicable` in the matrix therefore belongs to
|
|
35
|
+
* **postgres alone**: file bytes in a relational column is the antipattern #102 rejected, whereas Supabase
|
|
36
|
+
* has a real home for them.
|
|
37
|
+
*/
|
|
38
|
+
export { createPostgresFileMetadataStore as createSupabaseFileMetadataStore } from "../postgres/files.js";
|
|
39
|
+
export * from "./storage.js";
|
|
40
|
+
/**
|
|
41
|
+
* Artifacts alias to Postgres like every other relational port (#133).
|
|
42
|
+
*
|
|
43
|
+
* Their *content* does not live here at all — it is a `BlobRef`, and where those bytes sit is `BlobStore`'s
|
|
44
|
+
* business, which is itself an alias. So unlike `FileContentStore` there is nothing Supabase-specific to add:
|
|
45
|
+
* the artifact row is a relational row.
|
|
46
|
+
*/
|
|
47
|
+
export { createPostgresArtifactStore as createSupabaseArtifactStore } from "../postgres/artifacts.js";
|
|
48
|
+
export { createPostgresArtifactExportStore as createSupabaseArtifactExportStore } from "../postgres/artifact-exports.js";
|
|
49
|
+
/**
|
|
50
|
+
* Knowledge and vector search alias to Postgres too (#135).
|
|
51
|
+
*
|
|
52
|
+
* Supabase ships pgvector, so this is the same adapter and not a second implementation — unlike
|
|
53
|
+
* `FileContentStore`, where Supabase Storage genuinely is a different service. The vector migrations are
|
|
54
|
+
* separate from the main list (`migrateVector`) because `CREATE EXTENSION vector` fails where the extension is
|
|
55
|
+
* absent, and a Supabase project has it while a bare Postgres may not.
|
|
56
|
+
*/
|
|
57
|
+
export { createPostgresUsageRollupStore as createSupabaseUsageRollupStore } from "../postgres/rollups.js";
|
|
58
|
+
export { createPostgresEvaluationStore as createSupabaseEvaluationStore } from "../postgres/evaluation.js";
|
|
59
|
+
export { createPostgresKnowledgeStore as createSupabaseKnowledgeStore, createPostgresVectorIndex as createSupabaseVectorIndex, createPostgresKeywordIndex as createSupabaseKeywordIndex, } from "../postgres/knowledge.js";
|
|
60
|
+
export * from "./rls.js";
|
|
61
|
+
export * from "./realtime.js";
|
|
62
|
+
/**
|
|
63
|
+
* What a Supabase deployment can honestly advertise.
|
|
64
|
+
*
|
|
65
|
+
* **`distributed-locking` is included, and the SPEC expected it not to be.** #104 asks to declare it
|
|
66
|
+
* unsupported "if pooled connections make advisory locks unavailable" — but the premise no longer
|
|
67
|
+
* holds. #98 deliberately avoided advisory locks: a lock whose lifetime is a transaction cannot hold
|
|
68
|
+
* a run slot across a `waiting-for-approval` state that waits hours for a human, and the port
|
|
69
|
+
* promises a FIFO queue a lock cannot express. The coordinator is a slot table with
|
|
70
|
+
* `SELECT … FOR UPDATE` inside a short transaction, which is exactly what transaction pooling
|
|
71
|
+
* supports. Declaring it unsupported would skip real coverage for a reason that stopped being true.
|
|
72
|
+
*
|
|
73
|
+
* **`full-text-search` is removed.** Nothing implements it in either adapter, so it was a claim with
|
|
74
|
+
* nothing behind it — one of the two unproven capabilities flagged on #98. `POSTGRES_CAPABILITIES`
|
|
75
|
+
* still lists it; that is tracked separately rather than changed here, since Postgres is not this
|
|
76
|
+
* SPEC's subject.
|
|
77
|
+
*/
|
|
78
|
+
export declare const SUPABASE_CAPABILITIES: readonly AdapterCapability[];
|
|
79
|
+
/**
|
|
80
|
+
* Flows — #187, #186.
|
|
81
|
+
*
|
|
82
|
+
* Aliased, like every other relational port: the tables are ordinary Postgres and there is nothing
|
|
83
|
+
* Supabase-specific about a flow definition or an execution. An alias rather than a wrapper keeps AC-5's
|
|
84
|
+
* "identical results" true by identity rather than by proof.
|
|
85
|
+
*/
|
|
86
|
+
export { createPostgresFlowDefinitionStore as createSupabaseFlowDefinitionStore } from "../postgres/flows.js";
|
|
87
|
+
export { createPostgresFlowExecutionStore as createSupabaseFlowExecutionStore } from "../postgres/flows.js";
|
|
88
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Conversation and session
|
|
2
|
+
export { createPostgresConversationStore as createSupabaseConversationStore } from "../postgres/conversation-store.js";
|
|
3
|
+
export { createPostgresSessionStateStore as createSupabaseSessionStateStore, createPostgresThreadSummaryStore as createSupabaseThreadSummaryStore, } from "../postgres/session-state.js";
|
|
4
|
+
export { createPostgresConversationBindingStore as createSupabaseConversationBindingStore, createPostgresMessageStore as createSupabaseMessageStore, createPostgresAgentStore as createSupabaseAgentStore, } from "../postgres/message-store.js";
|
|
5
|
+
export { createPostgresConversationRunCoordinator as createSupabaseConversationRunCoordinator } from "../postgres/run-coordinator.js";
|
|
6
|
+
export { createPostgresUnitOfWork as createSupabaseUnitOfWork } from "../postgres/unit-of-work.js";
|
|
7
|
+
// Run lifecycle
|
|
8
|
+
export { createPostgresRunStore as createSupabaseRunStore } from "../postgres/run-store.js";
|
|
9
|
+
export { createPostgresRunEventLog as createSupabaseRunEventLog } from "../postgres/run-event-log.js";
|
|
10
|
+
export { createPostgresCheckpointStore as createSupabaseCheckpointStore } from "../postgres/checkpoint-store.js";
|
|
11
|
+
// HITL, accounting and configuration
|
|
12
|
+
export { createPostgresInteractionStore as createSupabaseInteractionStore, createPostgresApprovalGrantStore as createSupabaseApprovalGrantStore, } from "../postgres/hitl.js";
|
|
13
|
+
export { createPostgresUsageStore as createSupabaseUsageStore, createPostgresIdempotencyStore as createSupabaseIdempotencyStore, } from "../postgres/usage.js";
|
|
14
|
+
// The limit store is the Postgres one: it is ordinary SQL over an ordinary table, and Supabase's differences
|
|
15
|
+
// (RLS, the connection mode) are handled by the executor rather than by the statement (#175).
|
|
16
|
+
export { createPostgresUsageLimitStore as createSupabaseUsageLimitStore } from "../postgres/usage-limits.js";
|
|
17
|
+
export { createPostgresSkillStore as createSupabaseSkillStore, createPostgresMcpConnectionStore as createSupabaseMcpConnectionStore, } from "../postgres/config.js";
|
|
18
|
+
export { createPostgresPrincipalMemoryStore as createSupabasePrincipalMemoryStore, createPostgresBlobStore as createSupabaseBlobStore, } from "../postgres/memory.js";
|
|
19
|
+
/**
|
|
20
|
+
* File *metadata* aliases to Postgres. File *bytes* do not, and this is the one port where Supabase is not
|
|
21
|
+
* simply Postgres under another name.
|
|
22
|
+
*
|
|
23
|
+
* `0013_files` keeps metadata only, so `FileMetadataStore` is an alias like every other port. The bytes live
|
|
24
|
+
* in Supabase Storage, which has its own adapter in `./storage.js` — a genuine second implementation, not an
|
|
25
|
+
* alias, because there is no Postgres factory to alias to. `notApplicable` in the matrix therefore belongs to
|
|
26
|
+
* **postgres alone**: file bytes in a relational column is the antipattern #102 rejected, whereas Supabase
|
|
27
|
+
* has a real home for them.
|
|
28
|
+
*/
|
|
29
|
+
export { createPostgresFileMetadataStore as createSupabaseFileMetadataStore } from "../postgres/files.js";
|
|
30
|
+
export * from "./storage.js";
|
|
31
|
+
/**
|
|
32
|
+
* Artifacts alias to Postgres like every other relational port (#133).
|
|
33
|
+
*
|
|
34
|
+
* Their *content* does not live here at all — it is a `BlobRef`, and where those bytes sit is `BlobStore`'s
|
|
35
|
+
* business, which is itself an alias. So unlike `FileContentStore` there is nothing Supabase-specific to add:
|
|
36
|
+
* the artifact row is a relational row.
|
|
37
|
+
*/
|
|
38
|
+
export { createPostgresArtifactStore as createSupabaseArtifactStore } from "../postgres/artifacts.js";
|
|
39
|
+
export { createPostgresArtifactExportStore as createSupabaseArtifactExportStore } from "../postgres/artifact-exports.js";
|
|
40
|
+
/**
|
|
41
|
+
* Knowledge and vector search alias to Postgres too (#135).
|
|
42
|
+
*
|
|
43
|
+
* Supabase ships pgvector, so this is the same adapter and not a second implementation — unlike
|
|
44
|
+
* `FileContentStore`, where Supabase Storage genuinely is a different service. The vector migrations are
|
|
45
|
+
* separate from the main list (`migrateVector`) because `CREATE EXTENSION vector` fails where the extension is
|
|
46
|
+
* absent, and a Supabase project has it while a bare Postgres may not.
|
|
47
|
+
*/
|
|
48
|
+
export { createPostgresUsageRollupStore as createSupabaseUsageRollupStore } from "../postgres/rollups.js";
|
|
49
|
+
export { createPostgresEvaluationStore as createSupabaseEvaluationStore } from "../postgres/evaluation.js";
|
|
50
|
+
export { createPostgresKnowledgeStore as createSupabaseKnowledgeStore, createPostgresVectorIndex as createSupabaseVectorIndex, createPostgresKeywordIndex as createSupabaseKeywordIndex, } from "../postgres/knowledge.js";
|
|
51
|
+
export * from "./rls.js";
|
|
52
|
+
export * from "./realtime.js";
|
|
53
|
+
/**
|
|
54
|
+
* What a Supabase deployment can honestly advertise.
|
|
55
|
+
*
|
|
56
|
+
* **`distributed-locking` is included, and the SPEC expected it not to be.** #104 asks to declare it
|
|
57
|
+
* unsupported "if pooled connections make advisory locks unavailable" — but the premise no longer
|
|
58
|
+
* holds. #98 deliberately avoided advisory locks: a lock whose lifetime is a transaction cannot hold
|
|
59
|
+
* a run slot across a `waiting-for-approval` state that waits hours for a human, and the port
|
|
60
|
+
* promises a FIFO queue a lock cannot express. The coordinator is a slot table with
|
|
61
|
+
* `SELECT … FOR UPDATE` inside a short transaction, which is exactly what transaction pooling
|
|
62
|
+
* supports. Declaring it unsupported would skip real coverage for a reason that stopped being true.
|
|
63
|
+
*
|
|
64
|
+
* **`full-text-search` is removed.** Nothing implements it in either adapter, so it was a claim with
|
|
65
|
+
* nothing behind it — one of the two unproven capabilities flagged on #98. `POSTGRES_CAPABILITIES`
|
|
66
|
+
* still lists it; that is tracked separately rather than changed here, since Postgres is not this
|
|
67
|
+
* SPEC's subject.
|
|
68
|
+
*/
|
|
69
|
+
export const SUPABASE_CAPABILITIES = [
|
|
70
|
+
"transactions",
|
|
71
|
+
"row-level-security",
|
|
72
|
+
"distributed-locking",
|
|
73
|
+
"realtime",
|
|
74
|
+
];
|
|
75
|
+
/**
|
|
76
|
+
* Flows — #187, #186.
|
|
77
|
+
*
|
|
78
|
+
* Aliased, like every other relational port: the tables are ordinary Postgres and there is nothing
|
|
79
|
+
* Supabase-specific about a flow definition or an execution. An alias rather than a wrapper keeps AC-5's
|
|
80
|
+
* "identical results" true by identity rather than by proof.
|
|
81
|
+
*/
|
|
82
|
+
export { createPostgresFlowDefinitionStore as createSupabaseFlowDefinitionStore } from "../postgres/flows.js";
|
|
83
|
+
export { createPostgresFlowExecutionStore as createSupabaseFlowExecutionStore } from "../postgres/flows.js";
|
|
84
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { RealtimePublisher } from "../../core/events.js";
|
|
2
|
+
import type { LiveEventSource } from "../../runtime/streaming.js";
|
|
3
|
+
/** The app adapts a Supabase channel's `send` to this (`channel.send({ type, event, payload })`). */
|
|
4
|
+
export interface RealtimeBroadcaster {
|
|
5
|
+
send(channel: string, event: string, payload: unknown): Promise<void> | void;
|
|
6
|
+
}
|
|
7
|
+
export declare const createSupabaseRealtimePublisher: (broadcaster: RealtimeBroadcaster) => RealtimePublisher;
|
|
8
|
+
/**
|
|
9
|
+
* The receive side the host adapts a subscribed channel to.
|
|
10
|
+
*
|
|
11
|
+
* The contract that matters is inherited from `LiveEventSource`: **buffering must begin at call
|
|
12
|
+
* time**, before the caller's first `next()`. `openRunEventStream` subscribes and *then* reads the
|
|
13
|
+
* durable log, and that ordering is the only thing stopping an event published during catch-up from
|
|
14
|
+
* being lost. An adapter that connects lazily on first `next()` silently breaks it.
|
|
15
|
+
*/
|
|
16
|
+
export interface RealtimeSubscriber {
|
|
17
|
+
subscribe(channel: string): AsyncIterable<unknown>;
|
|
18
|
+
}
|
|
19
|
+
export type LiveEventSourceOptions = {
|
|
20
|
+
/**
|
|
21
|
+
* Whether this subscriber may read the channel. Rejected subscriptions yield nothing and end.
|
|
22
|
+
* Absent means every channel is allowed, which is only appropriate when the caller has already
|
|
23
|
+
* authorized — the GraphQL resolver path, for instance.
|
|
24
|
+
*/
|
|
25
|
+
readonly authorize?: (channel: string) => Promise<boolean> | boolean;
|
|
26
|
+
/** Called for each payload that fails validation. Defaults to silence. */
|
|
27
|
+
readonly onInvalid?: (channel: string, payload: unknown) => void;
|
|
28
|
+
};
|
|
29
|
+
export declare const createSupabaseLiveEventSource: (subscriber: RealtimeSubscriber, options?: LiveEventSourceOptions) => LiveEventSource;
|
|
30
|
+
//# sourceMappingURL=realtime.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supabase Realtime — the publisher and, as of #104, the `LiveEventSource` half.
|
|
3
|
+
*
|
|
4
|
+
* Both sides are defined against tiny interfaces the host app adapts its Supabase client to, so this
|
|
5
|
+
* package carries no `@supabase/supabase-js` dependency and stays deployable without one.
|
|
6
|
+
*
|
|
7
|
+
* Two things the in-memory bus never had to worry about, and this does:
|
|
8
|
+
*
|
|
9
|
+
* **A Realtime payload is network input.** `openRunEventStream` feeds whatever the live source yields
|
|
10
|
+
* straight into `reduceRunEvents`, so an unvalidated payload would put attacker-shaped or merely
|
|
11
|
+
* corrupt data into a run's projected state. Every payload is parsed with `parseRunEvent` and dropped
|
|
12
|
+
* if it fails, rather than trusted because it arrived on the right channel.
|
|
13
|
+
*
|
|
14
|
+
* **Entitlement is checked at subscribe time, not on delivery.** Filtering events after subscribing
|
|
15
|
+
* would still reveal that a conversation exists and roughly how active it is. Refusing the
|
|
16
|
+
* subscription is the only version that leaks nothing.
|
|
17
|
+
*/
|
|
18
|
+
import { parseRunEvent } from "../../core/validation.js";
|
|
19
|
+
export const createSupabaseRealtimePublisher = (broadcaster) => ({
|
|
20
|
+
async publish(channel, event) {
|
|
21
|
+
await broadcaster.send(channel, event.type, event);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
export const createSupabaseLiveEventSource = (subscriber, options = {}) => ({
|
|
25
|
+
subscribe(channel) {
|
|
26
|
+
// Subscribe eagerly, before the authorization check resolves, so the buffering contract above
|
|
27
|
+
// holds. An unauthorized channel yields nothing regardless — see below.
|
|
28
|
+
const upstream = subscriber.subscribe(channel);
|
|
29
|
+
return {
|
|
30
|
+
async *[Symbol.asyncIterator]() {
|
|
31
|
+
const allowed = options.authorize === undefined ? true : await options.authorize(channel);
|
|
32
|
+
// Ending the stream rather than throwing: a subscriber that is not entitled should observe
|
|
33
|
+
// an ordinary empty stream, not an error that distinguishes "forbidden" from "no such run".
|
|
34
|
+
if (!allowed)
|
|
35
|
+
return;
|
|
36
|
+
for await (const payload of upstream) {
|
|
37
|
+
let event;
|
|
38
|
+
try {
|
|
39
|
+
event = parseRunEvent(payload);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Dropped, not thrown: one malformed broadcast must not tear down a live stream that is
|
|
43
|
+
// otherwise healthy, and the durable log remains the source of truth for the run.
|
|
44
|
+
options.onInvalid?.(channel, payload);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
yield event;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=realtime.js.map
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { SqlExecutor } from "../postgres/sql.js";
|
|
2
|
+
import type { TransactionRunner } from "../postgres/transaction.js";
|
|
3
|
+
/**
|
|
4
|
+
* A table whose rows belong to a tenant, plus any predicate beyond the tenant match.
|
|
5
|
+
*
|
|
6
|
+
* `extraPredicate` exists for one case today. Tenant-only scoping on `principal_memory` would leak
|
|
7
|
+
* one user's memories to every other user of the same customer, which is the opposite of what
|
|
8
|
+
* per-principal memory is for.
|
|
9
|
+
*/
|
|
10
|
+
export type RlsTable = {
|
|
11
|
+
readonly table: string;
|
|
12
|
+
readonly extraPredicate?: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Tenant-scoped tables that live behind the optional pgvector migration (#135).
|
|
16
|
+
*
|
|
17
|
+
* Separate from `TENANT_SCOPED_TABLES` because `knowledge_chunks` does not exist until `migrateVector` runs, and
|
|
18
|
+
* `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` on an absent table fails. A deployment that runs the vector
|
|
19
|
+
* migration runs `applyVectorRls` with it; one that does not has no table to protect. Listed rather than
|
|
20
|
+
* omitted so the requirement is recorded — a tenant-scoped table without RLS is the one omission that matters.
|
|
21
|
+
*/
|
|
22
|
+
export declare const VECTOR_TENANT_SCOPED_TABLES: readonly {
|
|
23
|
+
readonly table: string;
|
|
24
|
+
}[];
|
|
25
|
+
export declare const TENANT_SCOPED_TABLES: readonly RlsTable[];
|
|
26
|
+
/**
|
|
27
|
+
* Tables that deliberately have no tenant policy, each with the reason.
|
|
28
|
+
*
|
|
29
|
+
* Classified rather than skipped. A silent omission is indistinguishable from a forgotten table,
|
|
30
|
+
* which is exactly what the coverage gate exists to catch — so an exemption has to be a decision
|
|
31
|
+
* someone wrote down.
|
|
32
|
+
*/
|
|
33
|
+
export declare const RLS_EXEMPT_TABLES: readonly {
|
|
34
|
+
readonly table: string;
|
|
35
|
+
readonly reason: string;
|
|
36
|
+
}[];
|
|
37
|
+
export declare const RLS_STATEMENTS: readonly string[];
|
|
38
|
+
export declare const applyRls: (sql: SqlExecutor) => Promise<void>;
|
|
39
|
+
/** The same policies for the vector table, applied by whoever ran `migrateVector` (#135). */
|
|
40
|
+
export declare const VECTOR_RLS_STATEMENTS: readonly string[];
|
|
41
|
+
export declare const applyVectorRls: (sql: SqlExecutor) => Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Every table `MIGRATIONS` creates, in migration order.
|
|
44
|
+
*
|
|
45
|
+
* Derived rather than transcribed: the SPEC's hand-written list named `interactions` and `blob_refs`,
|
|
46
|
+
* neither of which exists, and missed `schema_migrations`. A list that can disagree with the schema
|
|
47
|
+
* will eventually disagree with the schema.
|
|
48
|
+
*/
|
|
49
|
+
/**
|
|
50
|
+
* Every table any migration creates — **both** lists (#145).
|
|
51
|
+
*
|
|
52
|
+
* `VECTOR_MIGRATIONS` was missing, and that was a hole in the coverage gate rather than an oversight in a list:
|
|
53
|
+
* a table added there was never scanned, so it could ship with no RLS policy and no exemption and nothing would
|
|
54
|
+
* say so. `knowledge_chunks` happened to be covered because someone remembered; the *next* vector table would
|
|
55
|
+
* not have been.
|
|
56
|
+
*
|
|
57
|
+
* Found by auditing the gate rather than the list, which is the difference between checking the answer and
|
|
58
|
+
* checking the thing that produces it.
|
|
59
|
+
*/
|
|
60
|
+
export declare const tablesInMigrations: () => readonly string[];
|
|
61
|
+
/**
|
|
62
|
+
* Bind the **session** to a tenant. Safe only on a direct connection.
|
|
63
|
+
*
|
|
64
|
+
* `is_local = false` makes the setting outlive the current transaction, which is right for a
|
|
65
|
+
* connection this process owns exclusively — and **dangerous behind a transaction-mode pooler**, which
|
|
66
|
+
* is how Supabase's pooler port works. There, a backend is handed to a different client after each
|
|
67
|
+
* transaction while the session GUC stays set, so tenant A's binding is still in place when tenant B's
|
|
68
|
+
* query lands on that backend, and B's queries are evaluated against A's tenant id.
|
|
69
|
+
*
|
|
70
|
+
* That is a cross-tenant read produced by the mechanism introduced to prevent cross-tenant reads, and
|
|
71
|
+
* it is worse than having no policy at all, because the policy makes it look handled.
|
|
72
|
+
*
|
|
73
|
+
* Prefer `withTenantContext` unless you are certain the connection is not pooled. See the open
|
|
74
|
+
* question on #104 about removing this entirely.
|
|
75
|
+
*/
|
|
76
|
+
export declare const setTenantContext: (sql: SqlExecutor, tenantId: string) => Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Run `fn` with the tenant (and optionally the principal) bound **for the duration of one
|
|
79
|
+
* transaction**, which is the only binding that is safe behind a pooler.
|
|
80
|
+
*
|
|
81
|
+
* `is_local = true` scopes the setting to the transaction, so it is discarded at commit or rollback
|
|
82
|
+
* and cannot be observed by whoever gets the backend next. The transaction comes from #98's
|
|
83
|
+
* `TransactionRunner`, and the executor handed to `fn` is the transaction's — so stores built over a
|
|
84
|
+
* `scoped()` executor participate without knowing any of this exists.
|
|
85
|
+
*/
|
|
86
|
+
export declare const withTenantContext: <T>(runner: TransactionRunner, scope: {
|
|
87
|
+
readonly tenantId: string;
|
|
88
|
+
readonly principalId?: string;
|
|
89
|
+
}, fn: (sql: SqlExecutor) => Promise<T>) => Promise<T>;
|
|
90
|
+
/**
|
|
91
|
+
* Bind the **session** to a principal. Same pooling caveat as `setTenantContext` — prefer passing
|
|
92
|
+
* `principalId` to `withTenantContext`.
|
|
93
|
+
*
|
|
94
|
+
* Separate from `setTenantContext` because most work has a tenant and no principal — a background
|
|
95
|
+
* reaper, a migration, a rollup. Those must not be able to read principal-scoped rows, and with this
|
|
96
|
+
* unset they cannot: the predicate compares against NULL and matches nothing.
|
|
97
|
+
*/
|
|
98
|
+
export declare const setPrincipalContext: (sql: SqlExecutor, principalId: string) => Promise<void>;
|
|
99
|
+
//# sourceMappingURL=rls.d.ts.map
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Row-Level Security — `docs/02` + `docs/11`.
|
|
3
|
+
*
|
|
4
|
+
* Enforces tenant isolation *at the database*, independent of any app-level `WHERE`. The policy
|
|
5
|
+
* predicate `tenant_id = current_setting('app.tenant_id')` is exactly the filter the authorization
|
|
6
|
+
* `scope()` produces (see `tenantRlsFilter`), so the two agree by construction — and if the
|
|
7
|
+
* application filter is ever forgotten, the database still refuses.
|
|
8
|
+
*
|
|
9
|
+
* Until #103 this covered exactly one table, because `conversations` was the only table when it was
|
|
10
|
+
* written. There are now 19, and a table without a policy means a Supabase deployment relies on
|
|
11
|
+
* application filtering alone — the single point of failure REQ-014 exists to remove.
|
|
12
|
+
*
|
|
13
|
+
* **Policies are generated from the registry below rather than written out**, so adding a table's
|
|
14
|
+
* policy is a one-line entry and the statements cannot drift from the list. The coverage gate in
|
|
15
|
+
* `supabase-rls.test.ts` derives the table list from `MIGRATIONS`, so a new table cannot ship
|
|
16
|
+
* uncovered and a stale entry for a dropped table fails too.
|
|
17
|
+
*/
|
|
18
|
+
import { MIGRATIONS, VECTOR_MIGRATIONS } from "../postgres/migrations.js";
|
|
19
|
+
/**
|
|
20
|
+
* The principal predicate is written so an **absent** setting matches nothing.
|
|
21
|
+
*
|
|
22
|
+
* `current_setting('app.principal_id', true)` returns NULL when unset, and `principal_id = NULL` is
|
|
23
|
+
* NULL — which the policy treats as false. That is the behaviour we want: a connection with no
|
|
24
|
+
* principal bound sees no memories at all, rather than seeing every row whose `principal_id` happens
|
|
25
|
+
* to equal the empty string. Getting this backwards is how a background job ends up able to read
|
|
26
|
+
* everyone's memory.
|
|
27
|
+
*/
|
|
28
|
+
const PRINCIPAL_PREDICATE = `principal_id = current_setting('app.principal_id', true)`;
|
|
29
|
+
/**
|
|
30
|
+
* Tenant-scoped tables that live behind the optional pgvector migration (#135).
|
|
31
|
+
*
|
|
32
|
+
* Separate from `TENANT_SCOPED_TABLES` because `knowledge_chunks` does not exist until `migrateVector` runs, and
|
|
33
|
+
* `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` on an absent table fails. A deployment that runs the vector
|
|
34
|
+
* migration runs `applyVectorRls` with it; one that does not has no table to protect. Listed rather than
|
|
35
|
+
* omitted so the requirement is recorded — a tenant-scoped table without RLS is the one omission that matters.
|
|
36
|
+
*/
|
|
37
|
+
export const VECTOR_TENANT_SCOPED_TABLES = [
|
|
38
|
+
{ table: "knowledge_chunks" },
|
|
39
|
+
];
|
|
40
|
+
export const TENANT_SCOPED_TABLES = [
|
|
41
|
+
{ table: "conversations" },
|
|
42
|
+
{ table: "runs" },
|
|
43
|
+
{ table: "run_events" },
|
|
44
|
+
{ table: "checkpoints" },
|
|
45
|
+
{ table: "messages" },
|
|
46
|
+
{ table: "agents" },
|
|
47
|
+
{ table: "conversation_bindings" },
|
|
48
|
+
{ table: "session_state" },
|
|
49
|
+
{ table: "thread_summaries" },
|
|
50
|
+
{ table: "conversation_run_slots" },
|
|
51
|
+
// Two tables, not one: #99 split questions from approvals because PendingQuestion and
|
|
52
|
+
// PendingApproval share only three fields. The SPEC's list named a single `interactions`.
|
|
53
|
+
{ table: "interaction_questions" },
|
|
54
|
+
{ table: "interaction_approvals" },
|
|
55
|
+
{ table: "approval_grants" },
|
|
56
|
+
{ table: "usage_records" },
|
|
57
|
+
{ table: "usage_rollups" },
|
|
58
|
+
/**
|
|
59
|
+
* Tenant-scoped only, deliberately — #175.
|
|
60
|
+
*
|
|
61
|
+
* Not `PRINCIPAL_PREDICATE`, even though the table has a `principal_id`. A spend limit is a fact *about* a
|
|
62
|
+
* person that belongs to the tenant's administrator, not to the person it constrains: someone who could only
|
|
63
|
+
* see their own row could not be shown the tenant default they inherit, and — the part that matters — a
|
|
64
|
+
* limit nobody but its subject can read is a limit its subject can quietly delete.
|
|
65
|
+
*
|
|
66
|
+
* The principal column here is a dimension, not an owner. That distinction is why this needs saying: the
|
|
67
|
+
* neighbouring `principal_memory` has the same column and the opposite answer.
|
|
68
|
+
*/
|
|
69
|
+
{ table: "usage_limits" },
|
|
70
|
+
{ table: "evaluation_runs" },
|
|
71
|
+
{ table: "evaluation_case_results" },
|
|
72
|
+
{ table: "idempotency_keys" },
|
|
73
|
+
{ table: "skills" },
|
|
74
|
+
{ table: "mcp_connections" },
|
|
75
|
+
{ table: "principal_memory", extraPredicate: PRINCIPAL_PREDICATE },
|
|
76
|
+
// `blobs`, not the SPEC's `blob_refs`: BlobStore stores the value, and the metadata-and-pointer
|
|
77
|
+
// design belongs to FileMetadataStore (#129) / ArtifactStore (#133).
|
|
78
|
+
{ table: "blobs" },
|
|
79
|
+
/**
|
|
80
|
+
* #129, revised by #185.
|
|
81
|
+
*
|
|
82
|
+
* This used to say "the bytes are not in Postgres at all, so this policy covers the metadata only". That was
|
|
83
|
+
* true when the only content stores were in-memory and Supabase Storage. `createPostgresFileContentStore`
|
|
84
|
+
* changed it: bytes can now live in `file_objects`, in the same database, and a metadata policy that implied
|
|
85
|
+
* the bytes were somebody else's problem would have been the most reassuring kind of wrong.
|
|
86
|
+
*
|
|
87
|
+
* Both are covered now. A Storage bucket still needs its own access rules, and RLS here says nothing about
|
|
88
|
+
* those — that part of the original comment stands.
|
|
89
|
+
*/
|
|
90
|
+
{ table: "files" },
|
|
91
|
+
{ table: "file_objects" },
|
|
92
|
+
{ table: "artifacts" },
|
|
93
|
+
{ table: "artifact_versions" },
|
|
94
|
+
{ table: "artifact_exports" },
|
|
95
|
+
/**
|
|
96
|
+
* #187, #186. A flow definition is a tenant's automation and an execution is a tenant's data — including its
|
|
97
|
+
* `state`, which routinely holds whatever the automation was working on.
|
|
98
|
+
*/
|
|
99
|
+
{ table: "flow_definitions" },
|
|
100
|
+
{ table: "flow_executions" },
|
|
101
|
+
];
|
|
102
|
+
/**
|
|
103
|
+
* Tables that deliberately have no tenant policy, each with the reason.
|
|
104
|
+
*
|
|
105
|
+
* Classified rather than skipped. A silent omission is indistinguishable from a forgotten table,
|
|
106
|
+
* which is exactly what the coverage gate exists to catch — so an exemption has to be a decision
|
|
107
|
+
* someone wrote down.
|
|
108
|
+
*/
|
|
109
|
+
export const RLS_EXEMPT_TABLES = [
|
|
110
|
+
{
|
|
111
|
+
table: "schema_migrations",
|
|
112
|
+
reason: "Records which migrations have been applied. Deployment state, not customer data, and it holds " +
|
|
113
|
+
"no tenant_id to scope on. A migration runner must read it before any tenant context exists.",
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
const policyFor = ({ table, extraPredicate }) => {
|
|
117
|
+
const tenant = `tenant_id = current_setting('app.tenant_id', true)`;
|
|
118
|
+
const predicate = extraPredicate === undefined ? tenant : `${tenant} AND ${extraPredicate}`;
|
|
119
|
+
return [
|
|
120
|
+
`ALTER TABLE ${table} ENABLE ROW LEVEL SECURITY`,
|
|
121
|
+
// FORCE matters more than it looks. Without it the table owner bypasses every policy — and the
|
|
122
|
+
// owner is the role that runs migrations, and in many deployments the role the app connects as.
|
|
123
|
+
// An isolation test would then pass while proving nothing.
|
|
124
|
+
`ALTER TABLE ${table} FORCE ROW LEVEL SECURITY`,
|
|
125
|
+
`DROP POLICY IF EXISTS tenant_isolation ON ${table}`,
|
|
126
|
+
`CREATE POLICY tenant_isolation ON ${table}
|
|
127
|
+
USING (${predicate})
|
|
128
|
+
WITH CHECK (${predicate})`,
|
|
129
|
+
];
|
|
130
|
+
};
|
|
131
|
+
export const RLS_STATEMENTS = TENANT_SCOPED_TABLES.flatMap(policyFor);
|
|
132
|
+
export const applyRls = async (sql) => {
|
|
133
|
+
for (const stmt of RLS_STATEMENTS)
|
|
134
|
+
await sql.query(stmt);
|
|
135
|
+
};
|
|
136
|
+
/** The same policies for the vector table, applied by whoever ran `migrateVector` (#135). */
|
|
137
|
+
export const VECTOR_RLS_STATEMENTS = VECTOR_TENANT_SCOPED_TABLES.flatMap(policyFor);
|
|
138
|
+
export const applyVectorRls = async (sql) => {
|
|
139
|
+
for (const stmt of VECTOR_RLS_STATEMENTS)
|
|
140
|
+
await sql.query(stmt);
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Every table `MIGRATIONS` creates, in migration order.
|
|
144
|
+
*
|
|
145
|
+
* Derived rather than transcribed: the SPEC's hand-written list named `interactions` and `blob_refs`,
|
|
146
|
+
* neither of which exists, and missed `schema_migrations`. A list that can disagree with the schema
|
|
147
|
+
* will eventually disagree with the schema.
|
|
148
|
+
*/
|
|
149
|
+
/**
|
|
150
|
+
* Every table any migration creates — **both** lists (#145).
|
|
151
|
+
*
|
|
152
|
+
* `VECTOR_MIGRATIONS` was missing, and that was a hole in the coverage gate rather than an oversight in a list:
|
|
153
|
+
* a table added there was never scanned, so it could ship with no RLS policy and no exemption and nothing would
|
|
154
|
+
* say so. `knowledge_chunks` happened to be covered because someone remembered; the *next* vector table would
|
|
155
|
+
* not have been.
|
|
156
|
+
*
|
|
157
|
+
* Found by auditing the gate rather than the list, which is the difference between checking the answer and
|
|
158
|
+
* checking the thing that produces it.
|
|
159
|
+
*/
|
|
160
|
+
export const tablesInMigrations = () => {
|
|
161
|
+
const names = [];
|
|
162
|
+
for (const migration of [...MIGRATIONS, ...VECTOR_MIGRATIONS]) {
|
|
163
|
+
for (const statement of migration.up) {
|
|
164
|
+
const match = /CREATE TABLE (?:IF NOT EXISTS )?([a-z_][a-z0-9_]*)/i.exec(statement);
|
|
165
|
+
if (match?.[1] && !names.includes(match[1]))
|
|
166
|
+
names.push(match[1]);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return names;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Bind the **session** to a tenant. Safe only on a direct connection.
|
|
173
|
+
*
|
|
174
|
+
* `is_local = false` makes the setting outlive the current transaction, which is right for a
|
|
175
|
+
* connection this process owns exclusively — and **dangerous behind a transaction-mode pooler**, which
|
|
176
|
+
* is how Supabase's pooler port works. There, a backend is handed to a different client after each
|
|
177
|
+
* transaction while the session GUC stays set, so tenant A's binding is still in place when tenant B's
|
|
178
|
+
* query lands on that backend, and B's queries are evaluated against A's tenant id.
|
|
179
|
+
*
|
|
180
|
+
* That is a cross-tenant read produced by the mechanism introduced to prevent cross-tenant reads, and
|
|
181
|
+
* it is worse than having no policy at all, because the policy makes it look handled.
|
|
182
|
+
*
|
|
183
|
+
* Prefer `withTenantContext` unless you are certain the connection is not pooled. See the open
|
|
184
|
+
* question on #104 about removing this entirely.
|
|
185
|
+
*/
|
|
186
|
+
export const setTenantContext = async (sql, tenantId) => {
|
|
187
|
+
await sql.query(`SELECT set_config('app.tenant_id', $1, false)`, [tenantId]);
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* Run `fn` with the tenant (and optionally the principal) bound **for the duration of one
|
|
191
|
+
* transaction**, which is the only binding that is safe behind a pooler.
|
|
192
|
+
*
|
|
193
|
+
* `is_local = true` scopes the setting to the transaction, so it is discarded at commit or rollback
|
|
194
|
+
* and cannot be observed by whoever gets the backend next. The transaction comes from #98's
|
|
195
|
+
* `TransactionRunner`, and the executor handed to `fn` is the transaction's — so stores built over a
|
|
196
|
+
* `scoped()` executor participate without knowing any of this exists.
|
|
197
|
+
*/
|
|
198
|
+
export const withTenantContext = async (runner, scope, fn) => runner.transaction(async (sql) => {
|
|
199
|
+
await sql.query(`SELECT set_config('app.tenant_id', $1, true)`, [scope.tenantId]);
|
|
200
|
+
if (scope.principalId !== undefined) {
|
|
201
|
+
await sql.query(`SELECT set_config('app.principal_id', $1, true)`, [scope.principalId]);
|
|
202
|
+
}
|
|
203
|
+
return fn(sql);
|
|
204
|
+
});
|
|
205
|
+
/**
|
|
206
|
+
* Bind the **session** to a principal. Same pooling caveat as `setTenantContext` — prefer passing
|
|
207
|
+
* `principalId` to `withTenantContext`.
|
|
208
|
+
*
|
|
209
|
+
* Separate from `setTenantContext` because most work has a tenant and no principal — a background
|
|
210
|
+
* reaper, a migration, a rollup. Those must not be able to read principal-scoped rows, and with this
|
|
211
|
+
* unset they cannot: the predicate compares against NULL and matches nothing.
|
|
212
|
+
*/
|
|
213
|
+
export const setPrincipalContext = async (sql, principalId) => {
|
|
214
|
+
await sql.query(`SELECT set_config('app.principal_id', $1, false)`, [principalId]);
|
|
215
|
+
};
|
|
216
|
+
//# sourceMappingURL=rls.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `FileContentStore` over Supabase Storage — the production object-storage adapter (#129).
|
|
3
|
+
*
|
|
4
|
+
* This is the first store where Supabase is not simply Postgres. Every other port aliases straight to the
|
|
5
|
+
* Postgres implementation, and `supabase-conformance.test.ts` asserts that by identity. File bytes are the
|
|
6
|
+
* exception, and not incidentally: #102 declined to make `blobs` a pointer table, and `0013_files` keeps
|
|
7
|
+
* only metadata, precisely so that bytes live somewhere built for them.
|
|
8
|
+
*
|
|
9
|
+
* **Over `fetch`, not an SDK.** Supabase Storage is a plain REST API with a bearer token, so an SDK would
|
|
10
|
+
* add a dependency, a client lifecycle and an auth model for four HTTP calls. `fetch` is injected rather
|
|
11
|
+
* than reached for, so the conformance harness runs the real URL construction and status handling against
|
|
12
|
+
* an in-process double instead of a live bucket.
|
|
13
|
+
*
|
|
14
|
+
* **Two properties that are not obvious from the port:**
|
|
15
|
+
*
|
|
16
|
+
* - **The tenant is the path prefix, and a content key may not contain a separator.** `sanitizeMediaRefs` in
|
|
17
|
+
* ShareFlow is the cautionary tale this is written against — its workspace-prefix check was *"the ONLY
|
|
18
|
+
* thing standing between a forged path and a signed URL to another tenant's private object."* Here the
|
|
19
|
+
* key is validated to a character class, so `../` cannot be spelled at all.
|
|
20
|
+
* - **Listing is offset-paged, because the API is.** Unlike the metadata stores, which use keyset cursors
|
|
21
|
+
* deliberately, this one cannot: a concurrent upload can shift a page. That is tolerable only because the
|
|
22
|
+
* sole caller is reconciliation, which reports rather than deletes and runs again.
|
|
23
|
+
*/
|
|
24
|
+
import type { FileContentStore } from "../../persistence/index.js";
|
|
25
|
+
/** The slice of `fetch` this adapter uses. Injected so the harness can run the real request building. */
|
|
26
|
+
export type FetchLike = (url: string, init?: {
|
|
27
|
+
method?: string;
|
|
28
|
+
headers?: Record<string, string>;
|
|
29
|
+
body?: Uint8Array | string;
|
|
30
|
+
}) => Promise<{
|
|
31
|
+
readonly status: number;
|
|
32
|
+
readonly ok: boolean;
|
|
33
|
+
text(): Promise<string>;
|
|
34
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
35
|
+
}>;
|
|
36
|
+
export type SupabaseStorageConfig = {
|
|
37
|
+
/** Project URL, e.g. `https://abc.supabase.co`. No trailing slash required. */
|
|
38
|
+
readonly url: string;
|
|
39
|
+
/**
|
|
40
|
+
* The service-role key.
|
|
41
|
+
*
|
|
42
|
+
* A `secret://` reference in a manifest, resolved by the host before it reaches here — the same rule
|
|
43
|
+
* #96 set for MCP credentials. Never logged: every error below reports status and path, never headers.
|
|
44
|
+
*/
|
|
45
|
+
readonly serviceKey: string;
|
|
46
|
+
readonly bucket: string;
|
|
47
|
+
readonly fetch: FetchLike;
|
|
48
|
+
};
|
|
49
|
+
export declare const createSupabaseStorageFileContentStore: (config: SupabaseStorageConfig) => FileContentStore;
|
|
50
|
+
//# sourceMappingURL=storage.d.ts.map
|