@creatornader/agent-bridge 0.2.0 → 0.3.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.
Files changed (115) hide show
  1. package/CHANGELOG.md +86 -4
  2. package/README.md +567 -55
  3. package/ROADMAP.md +114 -0
  4. package/SECURITY.md +90 -0
  5. package/SKILL.md +68 -2
  6. package/bin/agent-bridge +2 -2
  7. package/clients/claude-desktop.json +3 -1
  8. package/dist/archive.d.ts +163 -0
  9. package/dist/archive.js +50 -0
  10. package/dist/archive.js.map +1 -0
  11. package/dist/bridge-domain-CBX3IVqC.d.ts +153 -0
  12. package/dist/{bridge-service-CfqMcMAn.d.ts → bridge-service-hX1ZQp4W.d.ts} +15 -5
  13. package/dist/bridge-store-DPVSCwfs.d.ts +102 -0
  14. package/dist/bridge.d.ts +76 -17
  15. package/dist/bridge.js +52 -24
  16. package/dist/chunk-2DFNOLMO.js +618 -0
  17. package/dist/chunk-2DFNOLMO.js.map +1 -0
  18. package/dist/{chunk-KVR4JBRF.js → chunk-2EVLG3YA.js} +2 -2
  19. package/dist/{chunk-KVR4JBRF.js.map → chunk-2EVLG3YA.js.map} +1 -1
  20. package/dist/chunk-45BZGB77.js +709 -0
  21. package/dist/chunk-45BZGB77.js.map +1 -0
  22. package/dist/chunk-4VB44KJU.js +230 -0
  23. package/dist/chunk-4VB44KJU.js.map +1 -0
  24. package/dist/chunk-5GMB3A77.js +1013 -0
  25. package/dist/chunk-5GMB3A77.js.map +1 -0
  26. package/dist/chunk-A6W4QALF.js +1258 -0
  27. package/dist/chunk-A6W4QALF.js.map +1 -0
  28. package/dist/chunk-BZLMF5O5.js +328 -0
  29. package/dist/chunk-BZLMF5O5.js.map +1 -0
  30. package/dist/{chunk-AXL2I7FH.js → chunk-CEXBMOI5.js} +240 -79
  31. package/dist/chunk-CEXBMOI5.js.map +1 -0
  32. package/dist/chunk-GADH244D.js +527 -0
  33. package/dist/chunk-GADH244D.js.map +1 -0
  34. package/dist/chunk-MBPZXTJA.js +2428 -0
  35. package/dist/chunk-MBPZXTJA.js.map +1 -0
  36. package/dist/chunk-NCO7RLBM.js +146 -0
  37. package/dist/chunk-NCO7RLBM.js.map +1 -0
  38. package/dist/chunk-Q6PPMXJC.js +1050 -0
  39. package/dist/chunk-Q6PPMXJC.js.map +1 -0
  40. package/dist/{chunk-4KAOBC5X.js → chunk-SPSMZOCJ.js} +190 -165
  41. package/dist/chunk-SPSMZOCJ.js.map +1 -0
  42. package/dist/chunk-UAHMP6GC.js +54 -0
  43. package/dist/chunk-UAHMP6GC.js.map +1 -0
  44. package/dist/{chunk-YD6YJATN.js → chunk-VOQIDTCJ.js} +4 -2
  45. package/dist/chunk-VOQIDTCJ.js.map +1 -0
  46. package/dist/chunk-WAI2IYIQ.js +554 -0
  47. package/dist/chunk-WAI2IYIQ.js.map +1 -0
  48. package/dist/cli.d.ts +2 -1
  49. package/dist/cli.js +3555 -214
  50. package/dist/cli.js.map +1 -1
  51. package/dist/client-config.d.ts +1 -1
  52. package/dist/client-config.js +1 -1
  53. package/dist/client-runtime.d.ts +10 -6
  54. package/dist/client-runtime.js +9 -6
  55. package/dist/contracts/generate.d.ts +2 -0
  56. package/dist/contracts/generate.js +247 -0
  57. package/dist/contracts/generate.js.map +1 -0
  58. package/dist/dr.d.ts +324 -0
  59. package/dist/dr.js +124 -0
  60. package/dist/dr.js.map +1 -0
  61. package/dist/gateway-CggQ8vTC.d.ts +78 -0
  62. package/dist/gateway-main.js +190 -8
  63. package/dist/gateway-main.js.map +1 -1
  64. package/dist/gateway.d.ts +4 -3
  65. package/dist/gateway.js +4 -3
  66. package/dist/index.js +11 -8
  67. package/dist/index.js.map +1 -1
  68. package/dist/postgres-bridge-store-Bfd3hRId.d.ts +49 -0
  69. package/dist/server.d.ts +3 -2
  70. package/dist/server.js +13 -8
  71. package/dist/sqlite.d.ts +94 -12
  72. package/dist/sqlite.js +7 -4
  73. package/docs/architecture-v2.md +394 -0
  74. package/docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md +85 -0
  75. package/docs/decisions/0002-canonical-operation-contract-registry.md +46 -0
  76. package/docs/decisions/0003-host-adapters-and-consumer-instance-keys.md +88 -0
  77. package/docs/ecosystem.md +86 -0
  78. package/docs/postmortems/2026-07-08-wrapper-source-drift.md +82 -0
  79. package/docs/troubleshooting.md +89 -0
  80. package/llms.txt +107 -6
  81. package/openapi/agent-bridge-v2.openapi.json +9610 -0
  82. package/package.json +24 -4
  83. package/schemas/agent-bridge-v2.capabilities.json +1829 -0
  84. package/schemas/agent-bridge-v2.mcp.json +2074 -0
  85. package/schemas/agent-bridge-v2.schema.json +4560 -0
  86. package/sql/migrations/008_message_projects.sql +36 -0
  87. package/sql/migrations/009_mailbox_query_indexes.sql +28 -0
  88. package/sql/migrations/010_publisher_delivery_policy.sql +210 -0
  89. package/sql/migrations/011_credential_security.sql +875 -0
  90. package/sql/migrations/012_request_authority.sql +177 -0
  91. package/sql/migrations/013_row_isolation.sql +495 -0
  92. package/sql/migrations/014_owner_control_plane.sql +1641 -0
  93. package/sql/migrations/015_portable_archives.sql +1813 -0
  94. package/sql/migrations/016_native_dr_fence.sql +1005 -0
  95. package/bin/CLAUDE.md +0 -11
  96. package/dist/bridge-domain-BcnBeHOn.d.ts +0 -97
  97. package/dist/bridge-store-BuGjxTn4.d.ts +0 -61
  98. package/dist/chunk-4KAOBC5X.js.map +0 -1
  99. package/dist/chunk-6MAZ6YLZ.js +0 -146
  100. package/dist/chunk-6MAZ6YLZ.js.map +0 -1
  101. package/dist/chunk-AXL2I7FH.js.map +0 -1
  102. package/dist/chunk-BV6W4AJK.js +0 -211
  103. package/dist/chunk-BV6W4AJK.js.map +0 -1
  104. package/dist/chunk-CKSKUBDQ.js +0 -153
  105. package/dist/chunk-CKSKUBDQ.js.map +0 -1
  106. package/dist/chunk-JOUBDRYX.js +0 -272
  107. package/dist/chunk-JOUBDRYX.js.map +0 -1
  108. package/dist/chunk-JTC5YURG.js +0 -49
  109. package/dist/chunk-JTC5YURG.js.map +0 -1
  110. package/dist/chunk-O26W5QHS.js +0 -409
  111. package/dist/chunk-O26W5QHS.js.map +0 -1
  112. package/dist/chunk-WEULPMUY.js +0 -988
  113. package/dist/chunk-WEULPMUY.js.map +0 -1
  114. package/dist/chunk-YD6YJATN.js.map +0 -1
  115. package/dist/gateway-BULozv3K.d.ts +0 -54
@@ -0,0 +1,709 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/migrations.ts
4
+ import { createHash } from "crypto";
5
+ import { readdir, readFile } from "fs/promises";
6
+ import { join } from "path";
7
+ var MIGRATION_NAME = /^(\d+)_([a-z0-9_]+)\.sql$/;
8
+ var NATIVE_DR_ADVISORY_LOCK_KEY = 1646705664;
9
+ var REQUIRED_COLUMNS = /* @__PURE__ */ new Map([
10
+ ["workspaces.id", "text"],
11
+ ["agents.id", "uuid"],
12
+ ["agents.workspace_id", "text"],
13
+ ["agents.principal", "text"],
14
+ ["credentials.id", "uuid"],
15
+ ["credentials.workspace_id", "text"],
16
+ ["credentials.agent_id", "uuid"],
17
+ ["credentials.token_hash", "bpchar"],
18
+ ["credentials.scopes", "_text"],
19
+ ["credentials.scope_set_name", "text"],
20
+ ["credentials.replaces_credential_id", "uuid"],
21
+ ["credentials.revoked_by", "text"],
22
+ ["credentials.revocation_reason", "text"],
23
+ ["credentials.expiry_grace_until", "timestamptz"],
24
+ ["credential_scope_sets.name", "text"],
25
+ ["credential_scope_sets.scopes", "_text"],
26
+ ["credential_scope_sets.created_at", "timestamptz"],
27
+ ["security_events.sequence", "int8"],
28
+ ["security_events.event_id", "uuid"],
29
+ ["security_events.event_type", "text"],
30
+ ["security_events.outcome", "text"],
31
+ ["security_events.reason_code", "text"],
32
+ ["security_events.workspace_id", "text"],
33
+ ["security_events.principal", "text"],
34
+ ["security_events.actor_principal", "text"],
35
+ ["security_events.credential_id", "uuid"],
36
+ ["security_events.related_credential_id", "uuid"],
37
+ ["security_events.operation_id", "text"],
38
+ ["security_events.request_id", "uuid"],
39
+ ["security_events.policy_id", "text"],
40
+ ["security_events.retry_after_seconds", "int4"],
41
+ ["security_events.created_at", "timestamptz"],
42
+ ["rate_limit_policies.policy_id", "text"],
43
+ ["rate_limit_policies.operation_id", "text"],
44
+ ["rate_limit_policies.capacity", "int4"],
45
+ ["rate_limit_policies.refill_per_second", "numeric"],
46
+ ["rate_limit_policies.enabled", "bool"],
47
+ ["rate_limit_buckets.credential_id", "uuid"],
48
+ ["rate_limit_buckets.policy_id", "text"],
49
+ ["rate_limit_buckets.tokens", "numeric"],
50
+ ["rate_limit_buckets.updated_at", "timestamptz"],
51
+ ["request_authorities.backend_pid", "int4"],
52
+ ["request_authorities.transaction_id", "xid8"],
53
+ ["request_authorities.request_id", "uuid"],
54
+ ["request_authorities.credential_id", "uuid"],
55
+ ["request_authorities.workspace_id", "text"],
56
+ ["request_authorities.principal", "text"],
57
+ ["request_authorities.scopes", "_text"],
58
+ ["request_authorities.opened_session_user", "name"],
59
+ ["row_isolation_attestations.name", "text"],
60
+ ["row_isolation_attestations.catalog_definition", "text"],
61
+ ["row_isolation_attestations.attested_at", "timestamptz"],
62
+ ["control_requests.request_id", "uuid"],
63
+ ["control_requests.operation", "text"],
64
+ ["control_requests.fingerprint", "bpchar"],
65
+ ["control_requests.actor", "name"],
66
+ ["control_requests.result", "jsonb"],
67
+ ["control_requests.created_at", "timestamptz"],
68
+ ["control_events.sequence", "int8"],
69
+ ["control_events.event_id", "uuid"],
70
+ ["control_events.request_id", "uuid"],
71
+ ["control_events.operation", "text"],
72
+ ["control_events.outcome", "text"],
73
+ ["control_events.actor", "name"],
74
+ ["control_events.workspace_id", "text"],
75
+ ["control_events.principal", "text"],
76
+ ["control_events.credential_id", "uuid"],
77
+ ["control_events.related_credential_id", "uuid"],
78
+ ["control_events.reason_code", "text"],
79
+ ["control_events.created_at", "timestamptz"],
80
+ ["owner_control_attestations.name", "text"],
81
+ ["owner_control_attestations.catalog_definition", "text"],
82
+ ["owner_control_attestations.attested_at", "timestamptz"],
83
+ ["control_membership_events.sequence", "int8"],
84
+ ["control_membership_events.request_id", "uuid"],
85
+ ["control_membership_events.action", "text"],
86
+ ["control_membership_events.member_role", "name"],
87
+ ["control_membership_events.control_role", "text"],
88
+ ["control_membership_events.actor", "name"],
89
+ ["control_membership_events.created_at", "timestamptz"],
90
+ ["archive_membership_events.sequence", "int8"],
91
+ ["archive_membership_events.request_id", "uuid"],
92
+ ["archive_membership_events.action", "text"],
93
+ ["archive_membership_events.member_role", "name"],
94
+ ["archive_membership_events.actor", "name"],
95
+ ["archive_membership_events.created_at", "timestamptz"],
96
+ ["archive_operations.sequence", "int8"],
97
+ ["archive_operations.request_id", "uuid"],
98
+ ["archive_operations.phase", "text"],
99
+ ["archive_operations.operation", "text"],
100
+ ["archive_operations.workspace", "text"],
101
+ ["archive_operations.client_verified_digest", "bpchar"],
102
+ ["archive_operations.message_count", "int8"],
103
+ ["archive_operations.receipt_count", "int8"],
104
+ ["archive_operations.message_inserted_count", "int8"],
105
+ ["archive_operations.receipt_inserted_count", "int8"],
106
+ ["archive_operations.server_content_binding", "bpchar"],
107
+ ["archive_operations.outcome", "text"],
108
+ ["archive_operations.failure_code", "text"],
109
+ ["archive_operations.published_at", "timestamptz"],
110
+ ["archive_operations.apply", "bool"],
111
+ ["archive_operations.actor", "name"],
112
+ ["archive_operations.created_at", "timestamptz"],
113
+ ["archive_operation_batches.sequence", "int8"],
114
+ ["archive_operation_batches.request_id", "uuid"],
115
+ ["archive_operation_batches.record_kind", "text"],
116
+ ["archive_operation_batches.batch_ordinal", "int8"],
117
+ ["archive_operation_batches.record_count", "int8"],
118
+ ["archive_operation_batches.batch_fingerprint", "bpchar"],
119
+ ["archive_operation_batches.chain_binding", "bpchar"],
120
+ ["archive_operation_batches.actor", "name"],
121
+ ["archive_operation_batches.created_at", "timestamptz"],
122
+ ["archive_import_records.sequence", "int8"],
123
+ ["archive_import_records.request_id", "uuid"],
124
+ ["archive_import_records.record_kind", "text"],
125
+ ["archive_import_records.record_key", "text"],
126
+ ["archive_import_records.batch_ordinal", "int8"],
127
+ ["archive_import_records.semantic_fingerprint", "bpchar"],
128
+ ["archive_import_records.inserted", "bool"],
129
+ ["archive_import_records.actor", "name"],
130
+ ["archive_import_records.created_at", "timestamptz"],
131
+ ["archive_transaction_authorizations.backend_pid", "int4"],
132
+ ["archive_transaction_authorizations.transaction_id", "text"],
133
+ ["archive_transaction_authorizations.request_id", "uuid"],
134
+ ["archive_transaction_authorizations.operation", "text"],
135
+ ["archive_transaction_authorizations.workspace", "text"],
136
+ ["archive_transaction_authorizations.client_verified_digest", "bpchar"],
137
+ ["archive_transaction_authorizations.actor", "name"],
138
+ ["archive_transaction_authorizations.messages_consumed", "bool"],
139
+ ["archive_transaction_authorizations.receipts_consumed", "bool"],
140
+ ["archive_transaction_authorizations.created_at", "timestamptz"],
141
+ ["portable_archive_attestations.name", "text"],
142
+ ["portable_archive_attestations.catalog_definition", "text"],
143
+ ["portable_archive_attestations.attested_at", "timestamptz"],
144
+ ["messages.sequence", "int8"],
145
+ ["messages.id", "uuid"],
146
+ ["messages.workspace", "text"],
147
+ ["messages.project", "text"],
148
+ ["messages.source", "text"],
149
+ ["messages.targets", "jsonb"],
150
+ ["messages.delivery_mode", "text"],
151
+ ["messages.delivery_max_attempts", "int4"],
152
+ ["messages.delivery_retry_base_delay_ms", "int4"],
153
+ ["messages.delivery_retry_max_delay_ms", "int4"],
154
+ ["messages.delivery_retry_jitter_ratio", "float8"],
155
+ ["messages.delivery_not_before", "timestamptz"],
156
+ ["receipts.workspace", "text"],
157
+ ["receipts.message_id", "uuid"],
158
+ ["receipts.principal", "text"],
159
+ ["deliveries.id", "uuid"],
160
+ ["deliveries.message_id", "uuid"],
161
+ ["deliveries.workspace", "text"],
162
+ ["deliveries.publisher", "text"],
163
+ ["deliveries.recipient", "text"],
164
+ ["deliveries.state", "text"],
165
+ ["deliveries.lease_token", "uuid"],
166
+ ["deliveries.created_at", "timestamptz"],
167
+ ["deliveries.priority_rank", "int2"],
168
+ ["deliveries.cycle_attempt", "int4"],
169
+ ["deliveries.requeue_count", "int4"],
170
+ ["deliveries.last_actor", "text"],
171
+ ["deliveries.last_action", "text"],
172
+ ["delivery_events.delivery_id", "uuid"],
173
+ ["delivery_events.publisher", "text"],
174
+ ["delivery_events.to_state", "text"],
175
+ ["delivery_events.cycle_attempt", "int4"],
176
+ ["delivery_events.requeue_count", "int4"],
177
+ ["delivery_events.actor", "text"],
178
+ ["delivery_events.action", "text"],
179
+ ["agent_instances.workspace", "text"],
180
+ ["agent_instances.instance", "text"],
181
+ ["agent_instances.capabilities", "jsonb"]
182
+ ]);
183
+ var REQUIRED_MIGRATIONS = [
184
+ { version: 1, name: "schema_state" },
185
+ { version: 2, name: "workspaces_agents_credentials" },
186
+ { version: 3, name: "messages_receipts_deliveries" },
187
+ { version: 4, name: "message_query_indexes" },
188
+ { version: 5, name: "delivery_events_presence" },
189
+ { version: 6, name: "legacy_shared_context_import" },
190
+ { version: 7, name: "runtime_role" },
191
+ { version: 8, name: "message_projects" },
192
+ { version: 9, name: "mailbox_query_indexes" },
193
+ { version: 10, name: "publisher_delivery_policy" },
194
+ { version: 11, name: "credential_security" },
195
+ { version: 12, name: "request_authority" },
196
+ { version: 13, name: "row_isolation" },
197
+ { version: 14, name: "owner_control_plane" },
198
+ { version: 15, name: "portable_archives" },
199
+ { version: 16, name: "native_dr_fence" }
200
+ ];
201
+ function withNativeDrSharedLock(source) {
202
+ if (!/^begin;\s/i.test(source)) {
203
+ throw new Error("migration must begin with an explicit transaction");
204
+ }
205
+ return source.replace(
206
+ /^begin;\s/i,
207
+ `begin;
208
+
209
+ select pg_advisory_xact_lock_shared(${NATIVE_DR_ADVISORY_LOCK_KEY});
210
+
211
+ `
212
+ );
213
+ }
214
+ function checksum(source) {
215
+ return createHash("sha256").update(source, "utf8").digest("hex");
216
+ }
217
+ async function recordedMigrations(db) {
218
+ const exists = await db.query(
219
+ "SELECT to_regclass('agent_bridge.schema_migrations')::text AS table_name"
220
+ );
221
+ if (!exists.rows[0]?.table_name) return [];
222
+ const result = await db.query(
223
+ "SELECT version, name, checksum FROM agent_bridge.schema_migrations ORDER BY version"
224
+ );
225
+ return result.rows.map((row) => ({
226
+ version: Number(row.version),
227
+ name: row.name,
228
+ checksum: row.checksum
229
+ }));
230
+ }
231
+ async function loadMigrationPlan(directory) {
232
+ const files = (await readdir(directory)).filter((file) => MIGRATION_NAME.test(file)).sort((left, right) => left.localeCompare(right));
233
+ const expected = await Promise.all(files.map(async (file) => {
234
+ const match = file.match(MIGRATION_NAME);
235
+ const source = await readFile(join(directory, file), "utf8");
236
+ return { version: Number(match[1]), name: match[2], source, checksum: checksum(source) };
237
+ }));
238
+ if (expected.length !== REQUIRED_MIGRATIONS.length || !expected.every(
239
+ (migration, index) => migration.version === REQUIRED_MIGRATIONS[index]?.version && migration.name === REQUIRED_MIGRATIONS[index]?.name
240
+ )) {
241
+ throw new Error("migration directory does not match the required migration sequence");
242
+ }
243
+ return expected;
244
+ }
245
+ async function migrationsReady(db, expected) {
246
+ const applied = await recordedMigrations(db);
247
+ return expected.every(
248
+ (required, index) => applied[index]?.version === required.version && applied[index]?.name === required.name && applied[index]?.checksum === required.checksum
249
+ ) && applied.length === expected.length;
250
+ }
251
+ async function rowIsolationReady(db, allowPrivilegedCaller) {
252
+ const result = await db.query(`WITH names AS (
253
+ SELECT
254
+ ('agent_bridge_runtime_' || substr(md5(current_database()),1,16))::name AS runtime_role,
255
+ ('agent_bridge_data_owner_' || substr(md5(current_database()),1,16))::name AS data_owner,
256
+ ('agent_bridge_context_reader_' || substr(md5(current_database()),1,16))::name AS context_reader,
257
+ ('agent_bridge_event_writer_' || substr(md5(current_database()),1,16))::name AS event_writer
258
+ ), required_roles(role_name) AS (
259
+ SELECT runtime_role FROM names UNION ALL SELECT data_owner FROM names
260
+ UNION ALL SELECT context_reader FROM names UNION ALL SELECT event_writer FROM names
261
+ ), domain_tables(table_name) AS (
262
+ VALUES ('messages'),('receipts'),('deliveries'),('delivery_events'),('agent_instances')
263
+ ), caller_role AS (
264
+ SELECT * FROM pg_roles WHERE rolname=current_user
265
+ ), expected_policies(table_name,policy_name,command_name,role_name,needs_workspace,needs_principal) AS (
266
+ SELECT 'messages','messages_owner_all','*',data_owner::text,false,false FROM names UNION ALL
267
+ SELECT 'messages','messages_runtime_select','r',runtime_role::text,true,true FROM names UNION ALL
268
+ SELECT 'messages','messages_runtime_insert','a',runtime_role::text,true,true FROM names UNION ALL
269
+ SELECT 'receipts','receipts_owner_all','*',data_owner::text,false,false FROM names UNION ALL
270
+ SELECT 'receipts','receipts_runtime_select','r',runtime_role::text,true,true FROM names UNION ALL
271
+ SELECT 'receipts','receipts_runtime_insert','a',runtime_role::text,true,true FROM names UNION ALL
272
+ SELECT 'deliveries','deliveries_owner_all','*',data_owner::text,false,false FROM names UNION ALL
273
+ SELECT 'deliveries','deliveries_runtime_select','r',runtime_role::text,true,true FROM names UNION ALL
274
+ SELECT 'deliveries','deliveries_runtime_insert','a',runtime_role::text,true,true FROM names UNION ALL
275
+ SELECT 'deliveries','deliveries_runtime_update','w',runtime_role::text,true,true FROM names UNION ALL
276
+ SELECT 'delivery_events','delivery_events_owner_all','*',data_owner::text,false,false FROM names UNION ALL
277
+ SELECT 'delivery_events','delivery_events_runtime_select','r',runtime_role::text,true,true FROM names UNION ALL
278
+ SELECT 'delivery_events','delivery_events_writer_insert','a',event_writer::text,false,false FROM names UNION ALL
279
+ SELECT 'agent_instances','agent_instances_owner_all','*',data_owner::text,false,false FROM names UNION ALL
280
+ SELECT 'agent_instances','agent_instances_runtime_select','r',runtime_role::text,true,false FROM names UNION ALL
281
+ SELECT 'agent_instances','agent_instances_runtime_insert','a',runtime_role::text,true,true FROM names UNION ALL
282
+ SELECT 'agent_instances','agent_instances_runtime_update','w',runtime_role::text,true,true FROM names UNION ALL
283
+ SELECT 'agent_instances','agent_instances_runtime_delete','d',runtime_role::text,true,true FROM names
284
+ ), actual_policies AS (
285
+ SELECT relation.relname AS table_name,policy.polname AS policy_name,
286
+ policy.polcmd AS command_name,policy.polpermissive,
287
+ ARRAY(SELECT role.rolname::text FROM unnest(policy.polroles) member(oid)
288
+ JOIN pg_roles role ON role.oid=member.oid ORDER BY role.rolname) AS role_names,
289
+ coalesce(pg_get_expr(policy.polqual,policy.polrelid),'') || ' ' ||
290
+ coalesce(pg_get_expr(policy.polwithcheck,policy.polrelid),'') AS expressions
291
+ FROM pg_policy policy
292
+ JOIN pg_class relation ON relation.oid=policy.polrelid
293
+ JOIN pg_namespace namespace ON namespace.oid=relation.relnamespace
294
+ WHERE namespace.nspname='agent_bridge'
295
+ AND relation.relname IN (SELECT table_name FROM domain_tables)
296
+ )
297
+ SELECT
298
+ (SELECT count(*)=4 AND bool_and(
299
+ role.rolname=(required.role_name::text)
300
+ AND NOT role.rolcanlogin AND NOT role.rolsuper AND NOT role.rolcreatedb
301
+ AND NOT role.rolcreaterole AND NOT role.rolreplication AND NOT role.rolbypassrls
302
+ )
303
+ FROM required_roles required JOIN pg_roles role ON role.rolname=required.role_name::text) AS "rolesReady",
304
+ ((SELECT rolsuper OR rolbypassrls FROM caller_role) OR (
305
+ (SELECT rolcanlogin AND rolinherit AND NOT rolsuper AND NOT rolcreatedb
306
+ AND NOT rolcreaterole AND NOT rolreplication AND NOT rolbypassrls
307
+ FROM caller_role)
308
+ AND pg_has_role(current_user,(SELECT runtime_role FROM names),'MEMBER')
309
+ AND NOT EXISTS (
310
+ SELECT 1 FROM pg_roles unexpected
311
+ WHERE unexpected.oid<>(SELECT oid FROM caller_role)
312
+ AND unexpected.rolname<>(SELECT runtime_role::text FROM names)
313
+ AND pg_has_role(current_user,unexpected.oid,'MEMBER')
314
+ )
315
+ )) AS "callerReady",
316
+ EXISTS (
317
+ SELECT 1 FROM pg_roles elevated
318
+ WHERE (elevated.rolsuper OR elevated.rolbypassrls)
319
+ AND pg_has_role(current_user,elevated.oid,'MEMBER')
320
+ ) AS "callerBypasses",
321
+ (SELECT count(*)=5 AND bool_and(
322
+ relation.relrowsecurity AND relation.relforcerowsecurity
323
+ AND owner.rolname=(SELECT data_owner::text FROM names)
324
+ )
325
+ FROM domain_tables required
326
+ JOIN pg_namespace namespace ON namespace.nspname='agent_bridge'
327
+ JOIN pg_class relation ON relation.relnamespace=namespace.oid AND relation.relname=required.table_name
328
+ JOIN pg_roles owner ON owner.oid=relation.relowner)
329
+ AND EXISTS (
330
+ SELECT 1 FROM pg_class attestation
331
+ JOIN pg_namespace namespace ON namespace.oid=attestation.relnamespace
332
+ WHERE namespace.nspname='agent_bridge'
333
+ AND attestation.relname='row_isolation_attestations'
334
+ AND attestation.relowner=namespace.nspowner
335
+ ) AS "ownershipReady",
336
+ ((SELECT count(*) FROM actual_policies)=18 AND NOT EXISTS (
337
+ SELECT 1 FROM expected_policies expected
338
+ LEFT JOIN actual_policies actual
339
+ ON actual.table_name=expected.table_name AND actual.policy_name=expected.policy_name
340
+ WHERE actual.policy_name IS NULL OR actual.command_name<>expected.command_name
341
+ OR NOT actual.polpermissive OR actual.role_names<>ARRAY[expected.role_name]
342
+ OR (expected.needs_workspace AND position('current_request_workspace' in actual.expressions)=0)
343
+ OR (expected.needs_principal AND position('current_request_principal' in actual.expressions)=0)
344
+ OR (NOT expected.needs_workspace AND NOT expected.needs_principal
345
+ AND position('true' in actual.expressions)=0)
346
+ )) AS "policiesReady",
347
+ (SELECT count(*)=4 AND bool_and(
348
+ procedure.proconfig @> ARRAY['search_path=""']::text[]
349
+ AND CASE procedure.proname
350
+ WHEN 'record_delivery_event' THEN owner.rolname=(SELECT event_writer::text FROM names)
351
+ AND procedure.prosecdef AND procedure.provolatile='v'
352
+ WHEN 'row_isolation_catalog_definition' THEN
353
+ owner.oid=(SELECT relation.relowner FROM pg_class relation
354
+ JOIN pg_namespace namespace ON namespace.oid=relation.relnamespace
355
+ WHERE namespace.nspname='agent_bridge'
356
+ AND relation.relname='row_isolation_attestations')
357
+ AND NOT procedure.prosecdef AND procedure.provolatile='s'
358
+ ELSE owner.rolname=(SELECT context_reader::text FROM names)
359
+ AND procedure.prosecdef AND procedure.provolatile='s'
360
+ END
361
+ )
362
+ FROM pg_proc procedure
363
+ JOIN pg_namespace namespace ON namespace.oid=procedure.pronamespace
364
+ JOIN pg_roles owner ON owner.oid=procedure.proowner
365
+ WHERE namespace.nspname='agent_bridge'
366
+ AND procedure.proname IN (
367
+ 'current_request_workspace','current_request_principal',
368
+ 'record_delivery_event','row_isolation_catalog_definition'
369
+ ))
370
+ AND NOT EXISTS (
371
+ SELECT 1 FROM pg_proc private_function
372
+ JOIN pg_namespace private_namespace ON private_namespace.oid=private_function.pronamespace
373
+ WHERE private_namespace.nspname='agent_bridge'
374
+ AND has_function_privilege('public',private_function.oid,'EXECUTE')
375
+ )
376
+ AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.current_request_workspace()','EXECUTE')
377
+ AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.current_request_principal()','EXECUTE')
378
+ AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.row_isolation_catalog_definition()','EXECUTE')
379
+ AND NOT has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.record_delivery_event()','EXECUTE')
380
+ AND NOT has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.reject_delivery_identity_mutation()','EXECUTE')
381
+ AND NOT has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.enforce_delivery_actor_role()','EXECUTE')
382
+ AND NOT has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.reject_delivery_event_mutation()','EXECUTE')
383
+ AS "functionsReady",
384
+ ((SELECT count(*)=5 AND bool_and(constraint_record.convalidated)
385
+ FROM (VALUES
386
+ ('agent_bridge.messages'::regclass,'messages_workspace_id_source_unique'),
387
+ ('agent_bridge.deliveries'::regclass,'deliveries_publisher_message_fk'),
388
+ ('agent_bridge.deliveries'::regclass,'deliveries_event_identity_unique'),
389
+ ('agent_bridge.delivery_events'::regclass,'delivery_events_delivery_publisher_fk'),
390
+ ('agent_bridge.row_isolation_attestations'::regclass,'row_isolation_attestation_name')
391
+ ) required(relation_id,constraint_name)
392
+ JOIN pg_constraint constraint_record
393
+ ON constraint_record.conrelid=required.relation_id
394
+ AND constraint_record.conname=required.constraint_name)
395
+ AND (SELECT count(*)=2 AND bool_and(attribute.attnotnull)
396
+ FROM pg_attribute attribute
397
+ WHERE (attribute.attrelid,attribute.attname) IN (
398
+ ('agent_bridge.deliveries'::regclass,'publisher'),
399
+ ('agent_bridge.delivery_events'::regclass,'publisher')
400
+ ) AND attribute.attnum>0 AND NOT attribute.attisdropped)
401
+ ) AS "constraintsReady",
402
+ (SELECT count(*)=4 AND bool_and(trigger.tgenabled='O')
403
+ FROM (VALUES
404
+ ('agent_bridge.deliveries'::regclass,'deliveries_record_event'),
405
+ ('agent_bridge.deliveries'::regclass,'deliveries_identity_immutable'),
406
+ ('agent_bridge.deliveries'::regclass,'deliveries_actor_role'),
407
+ ('agent_bridge.delivery_events'::regclass,'delivery_events_append_only')
408
+ ) required(relation_id,trigger_name)
409
+ JOIN pg_trigger trigger ON trigger.tgrelid=required.relation_id
410
+ AND trigger.tgname=required.trigger_name AND NOT trigger.tgisinternal) AS "triggersReady",
411
+ (has_schema_privilege((SELECT runtime_role FROM names),'agent_bridge','USAGE')
412
+ AND NOT has_schema_privilege((SELECT runtime_role FROM names),'agent_bridge','CREATE')
413
+ AND has_schema_privilege((SELECT data_owner FROM names),'agent_bridge','USAGE')
414
+ AND NOT has_schema_privilege((SELECT data_owner FROM names),'agent_bridge','CREATE')
415
+ AND has_schema_privilege((SELECT context_reader FROM names),'agent_bridge','USAGE')
416
+ AND NOT has_schema_privilege((SELECT context_reader FROM names),'agent_bridge','CREATE')
417
+ AND has_schema_privilege((SELECT event_writer FROM names),'agent_bridge','USAGE')
418
+ AND NOT has_schema_privilege((SELECT event_writer FROM names),'agent_bridge','CREATE')
419
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.messages','SELECT')
420
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.messages','INSERT')
421
+ AND NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.messages','UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER')
422
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.receipts','SELECT')
423
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.receipts','INSERT')
424
+ AND NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.receipts','UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER')
425
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.deliveries','SELECT')
426
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.deliveries','INSERT')
427
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.deliveries','UPDATE')
428
+ AND NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.deliveries','DELETE,TRUNCATE,REFERENCES,TRIGGER')
429
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.delivery_events','SELECT')
430
+ AND NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.delivery_events','INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER')
431
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.agent_instances','SELECT')
432
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.agent_instances','INSERT')
433
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.agent_instances','UPDATE')
434
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.agent_instances','DELETE')
435
+ AND NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.agent_instances','TRUNCATE,REFERENCES,TRIGGER')
436
+ AND has_sequence_privilege((SELECT runtime_role FROM names),'agent_bridge.messages_sequence_seq','USAGE')
437
+ AND NOT has_sequence_privilege((SELECT runtime_role FROM names),'agent_bridge.messages_sequence_seq','SELECT,UPDATE')
438
+ AND NOT has_sequence_privilege((SELECT runtime_role FROM names),'agent_bridge.delivery_events_sequence_seq','USAGE,SELECT,UPDATE')
439
+ AND has_table_privilege((SELECT context_reader FROM names),'agent_bridge.request_authorities','SELECT')
440
+ AND NOT has_table_privilege((SELECT context_reader FROM names),'agent_bridge.request_authorities','INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER')
441
+ AND has_table_privilege((SELECT event_writer FROM names),'agent_bridge.delivery_events','INSERT')
442
+ AND NOT has_table_privilege((SELECT event_writer FROM names),'agent_bridge.delivery_events','SELECT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER')
443
+ AND NOT EXISTS (
444
+ SELECT 1 FROM pg_class relation
445
+ JOIN pg_namespace namespace ON namespace.oid=relation.relnamespace
446
+ WHERE namespace.nspname='agent_bridge' AND relation.relkind IN ('r','p','v','m','f')
447
+ AND (
448
+ (relation.relname<>'request_authorities' AND has_table_privilege(
449
+ (SELECT context_reader FROM names),relation.oid,
450
+ 'SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER'
451
+ ))
452
+ OR (relation.relname<>'delivery_events' AND has_table_privilege(
453
+ (SELECT event_writer FROM names),relation.oid,
454
+ 'SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER'
455
+ ))
456
+ )
457
+ )
458
+ AND has_sequence_privilege((SELECT event_writer FROM names),'agent_bridge.delivery_events_sequence_seq','USAGE')
459
+ AND NOT has_sequence_privilege((SELECT event_writer FROM names),'agent_bridge.delivery_events_sequence_seq','SELECT,UPDATE')
460
+ AND NOT EXISTS (
461
+ SELECT 1 FROM pg_class sequence
462
+ JOIN pg_namespace namespace ON namespace.oid=sequence.relnamespace
463
+ WHERE namespace.nspname='agent_bridge' AND sequence.relkind='S'
464
+ AND (
465
+ has_sequence_privilege((SELECT context_reader FROM names),sequence.oid,'USAGE,SELECT,UPDATE')
466
+ OR (sequence.relname<>'delivery_events_sequence_seq' AND has_sequence_privilege(
467
+ (SELECT event_writer FROM names),sequence.oid,'USAGE,SELECT,UPDATE'
468
+ ))
469
+ )
470
+ )
471
+ AND NOT has_sequence_privilege('public','agent_bridge.messages_sequence_seq','USAGE,SELECT,UPDATE')
472
+ AND NOT has_sequence_privilege('public','agent_bridge.delivery_events_sequence_seq','USAGE,SELECT,UPDATE')
473
+ AND has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.row_isolation_attestations','SELECT')
474
+ AND NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.row_isolation_attestations','INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER')
475
+ AND NOT EXISTS (
476
+ SELECT 1
477
+ FROM unnest(ARRAY[
478
+ 'agent_bridge.credentials','agent_bridge.agents',
479
+ 'agent_bridge.workspaces','agent_bridge.request_authorities'
480
+ ]) protected_table(value)
481
+ CROSS JOIN unnest(ARRAY[
482
+ 'SELECT','INSERT','UPDATE','DELETE','TRUNCATE','REFERENCES','TRIGGER'
483
+ ]) requested_privilege(value)
484
+ WHERE has_table_privilege(
485
+ (SELECT runtime_role FROM names),protected_table.value,requested_privilege.value
486
+ )
487
+ )
488
+ AND NOT EXISTS (
489
+ SELECT 1
490
+ FROM unnest(ARRAY[
491
+ 'agent_bridge.credentials','agent_bridge.agents',
492
+ 'agent_bridge.workspaces','agent_bridge.request_authorities'
493
+ ]) protected_table(value)
494
+ CROSS JOIN unnest(ARRAY['SELECT','INSERT','UPDATE','REFERENCES']) requested_privilege(value)
495
+ WHERE has_any_column_privilege(
496
+ (SELECT runtime_role FROM names),protected_table.value,requested_privilege.value
497
+ )
498
+ )
499
+ AND NOT has_table_privilege('public','agent_bridge.row_isolation_attestations','SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER')
500
+ AND NOT pg_has_role((SELECT runtime_role FROM names),(SELECT data_owner FROM names),'MEMBER')
501
+ AND NOT pg_has_role((SELECT runtime_role FROM names),(SELECT context_reader FROM names),'MEMBER')
502
+ AND NOT pg_has_role((SELECT runtime_role FROM names),(SELECT event_writer FROM names),'MEMBER')
503
+ AND NOT EXISTS (
504
+ SELECT 1 FROM pg_proc private_function
505
+ JOIN pg_namespace namespace ON namespace.oid=private_function.pronamespace
506
+ WHERE namespace.nspname='agent_bridge'
507
+ AND (
508
+ (NOT (private_function.proname IN ('current_request_workspace','current_request_principal')
509
+ AND private_function.pronargs=0)
510
+ AND has_function_privilege((SELECT context_reader FROM names),private_function.oid,'EXECUTE'))
511
+ OR (NOT (private_function.proname='record_delivery_event' AND private_function.pronargs=0)
512
+ AND has_function_privilege((SELECT event_writer FROM names),private_function.oid,'EXECUTE'))
513
+ )
514
+ )
515
+ ) AS "grantsReady",
516
+ (SELECT count(*)=1 AND bool_and(
517
+ attestation.catalog_definition=agent_bridge.row_isolation_catalog_definition()
518
+ )
519
+ FROM agent_bridge.row_isolation_attestations attestation
520
+ WHERE attestation.name='domain-v1') AS "catalogReady"
521
+ `);
522
+ const row = result.rows[0];
523
+ const callerReady = row?.callerReady && (allowPrivilegedCaller || !row.callerBypasses);
524
+ return Boolean(
525
+ row?.rolesReady && callerReady && row.ownershipReady && row.policiesReady && row.functionsReady && row.constraintsReady && row.triggersReady && row.grantsReady && row.catalogReady
526
+ );
527
+ }
528
+ async function runtimeSchemaReady(db, options = {}) {
529
+ const columns = await db.query(
530
+ `SELECT relation.relname AS table_name, attribute.attname AS column_name,
531
+ type.typname AS udt_name
532
+ FROM pg_catalog.pg_attribute attribute
533
+ JOIN pg_catalog.pg_class relation ON relation.oid=attribute.attrelid
534
+ JOIN pg_catalog.pg_namespace namespace ON namespace.oid=relation.relnamespace
535
+ JOIN pg_catalog.pg_type type ON type.oid=attribute.atttypid
536
+ WHERE namespace.nspname='agent_bridge'
537
+ AND attribute.attnum>0 AND NOT attribute.attisdropped`
538
+ );
539
+ const actual = new Map(
540
+ columns.rows.map((row2) => [`${row2.table_name}.${row2.column_name}`, row2.udt_name])
541
+ );
542
+ if ([...REQUIRED_COLUMNS].some(([name, type]) => actual.get(name) !== type)) return false;
543
+ const objects = await db.query(
544
+ `WITH names AS (
545
+ SELECT ('agent_bridge_runtime_' || substr(md5(current_database()),1,16))::name AS runtime_role
546
+ ) SELECT
547
+ EXISTS (
548
+ SELECT 1 FROM pg_trigger
549
+ WHERE tgrelid='agent_bridge.messages'::regclass
550
+ AND tgname='messages_immutable' AND NOT tgisinternal
551
+ ) AS immutable,
552
+ EXISTS (
553
+ SELECT 1 FROM pg_trigger
554
+ WHERE tgrelid='agent_bridge.deliveries'::regclass
555
+ AND tgname='deliveries_record_event' AND NOT tgisinternal
556
+ ) AS "deliveryAudit",
557
+ to_regclass('agent_bridge.messages_idempotency') IS NOT NULL AS idempotency,
558
+ to_regclass('agent_bridge.deliveries_claim') IS NOT NULL AS claim,
559
+ to_regclass('agent_bridge.deliveries_publisher_lookup') IS NOT NULL AS publisher,
560
+ to_regclass('agent_bridge.deliveries_terminal_lookup') IS NOT NULL AS terminal,
561
+ to_regclass('agent_bridge.messages_source') IS NOT NULL AS source,
562
+ to_regclass('agent_bridge.messages_thread') IS NOT NULL AS thread,
563
+ to_regclass('agent_bridge.messages_created') IS NOT NULL AS created,
564
+ to_regclass('agent_bridge.messages_project') IS NOT NULL AS project,
565
+ to_regclass('agent_bridge.messages_targets_gin') IS NOT NULL AS targets,
566
+ to_regclass('agent_bridge.agent_instances_active') IS NOT NULL AS presence,
567
+ to_regclass('agent_bridge.credential_scope_sets') IS NOT NULL AS "scopeSets",
568
+ to_regclass('agent_bridge.security_events') IS NOT NULL AS "securityEvents",
569
+ to_regclass('agent_bridge.rate_limit_policies') IS NOT NULL AS "ratePolicies",
570
+ to_regclass('agent_bridge.rate_limit_buckets') IS NOT NULL AS "rateBuckets",
571
+ to_regclass('agent_bridge.credentials_replacement_lineage') IS NOT NULL AS replacement,
572
+ to_regclass('agent_bridge.rate_limit_buckets_cleanup') IS NOT NULL AS "rateCleanup",
573
+ EXISTS (
574
+ SELECT 1 FROM pg_trigger
575
+ WHERE tgrelid=to_regclass('agent_bridge.credentials')
576
+ AND tgname='credentials_validate_security' AND NOT tgisinternal
577
+ ) AS "credentialSecurity",
578
+ EXISTS (
579
+ SELECT 1 FROM pg_trigger
580
+ WHERE tgrelid=to_regclass('agent_bridge.security_events')
581
+ AND tgname='security_events_append_only' AND NOT tgisinternal
582
+ ) AS "eventAppendOnly",
583
+ to_regprocedure('agent_bridge.record_scope_denial(uuid,text,uuid)') IS NOT NULL AS "scopeAudit",
584
+ to_regprocedure('agent_bridge.consume_rate_limit(uuid,text,uuid)') IS NOT NULL AS "rateConsume",
585
+ to_regprocedure('agent_bridge.security_schema_ready()') IS NOT NULL AS "securityReady",
586
+ to_regclass('agent_bridge.request_authorities') IS NOT NULL AS "requestAuthorities",
587
+ to_regprocedure('agent_bridge.open_request_authority(uuid,text,uuid)') IS NOT NULL
588
+ AND to_regprocedure('agent_bridge.resolve_credential_hash(text)') IS NOT NULL AS "authorityOpen",
589
+ to_regprocedure('agent_bridge.close_request_authority()') IS NOT NULL AS "authorityClose",
590
+ NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.credentials','SELECT') AS "credentialDigestHidden",
591
+ NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.request_authorities','SELECT') AS "authorityRowsHidden",
592
+ (NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.agents','SELECT')
593
+ AND NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.workspaces','SELECT')) AS "principalTablesHidden",
594
+ (
595
+ NOT EXISTS (
596
+ SELECT 1
597
+ FROM unnest(ARRAY[
598
+ 'agent_bridge.credentials','agent_bridge.agents',
599
+ 'agent_bridge.workspaces','agent_bridge.request_authorities'
600
+ ]) protected_table(value)
601
+ CROSS JOIN unnest(ARRAY[
602
+ 'SELECT','INSERT','UPDATE','DELETE','TRUNCATE','REFERENCES','TRIGGER'
603
+ ]) requested_privilege(value)
604
+ WHERE has_table_privilege(
605
+ (SELECT runtime_role FROM names),protected_table.value,requested_privilege.value
606
+ )
607
+ )
608
+ AND NOT EXISTS (
609
+ SELECT 1
610
+ FROM unnest(ARRAY[
611
+ 'agent_bridge.credentials','agent_bridge.agents',
612
+ 'agent_bridge.workspaces','agent_bridge.request_authorities'
613
+ ]) protected_table(value)
614
+ CROSS JOIN unnest(ARRAY['SELECT','INSERT','UPDATE','REFERENCES']) requested_privilege(value)
615
+ WHERE has_any_column_privilege(
616
+ (SELECT runtime_role FROM names),protected_table.value,requested_privilege.value
617
+ )
618
+ )
619
+ ) AS "authorityTablesLocked",
620
+ (
621
+ has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.resolve_credential_hash(text)','EXECUTE')
622
+ AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.open_request_authority(uuid,text,uuid)','EXECUTE')
623
+ AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.close_request_authority()','EXECUTE')
624
+ AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.record_scope_denial(uuid,text,uuid)','EXECUTE')
625
+ AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.consume_rate_limit(uuid,text,uuid)','EXECUTE')
626
+ AND NOT has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.active_request_authority()','EXECUTE')
627
+ AND NOT has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.assert_active_request_credential(uuid)','EXECUTE')
628
+ AND NOT has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.record_scope_denial_unbound_011(uuid,text,uuid)','EXECUTE')
629
+ AND NOT has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.consume_rate_limit_unbound_011(uuid,text,uuid)','EXECUTE')
630
+ AND NOT has_function_privilege('public','agent_bridge.resolve_credential_hash(text)','EXECUTE')
631
+ AND NOT has_function_privilege('public','agent_bridge.open_request_authority(uuid,text,uuid)','EXECUTE')
632
+ AND NOT has_function_privilege('public','agent_bridge.close_request_authority()','EXECUTE')
633
+ AND NOT has_function_privilege('public','agent_bridge.record_scope_denial(uuid,text,uuid)','EXECUTE')
634
+ AND NOT has_function_privilege('public','agent_bridge.consume_rate_limit(uuid,text,uuid)','EXECUTE')
635
+ AND NOT has_function_privilege('public','agent_bridge.record_scope_denial_unbound_011(uuid,text,uuid)','EXECUTE')
636
+ AND NOT has_function_privilege('public','agent_bridge.consume_rate_limit_unbound_011(uuid,text,uuid)','EXECUTE')
637
+ AND NOT EXISTS (
638
+ SELECT 1 FROM pg_proc procedure
639
+ JOIN pg_namespace namespace ON namespace.oid=procedure.pronamespace
640
+ WHERE namespace.nspname='agent_bridge'
641
+ AND procedure.proname IN (
642
+ 'resolve_credential_hash','open_request_authority','active_request_authority',
643
+ 'assert_active_request_credential','close_request_authority','record_scope_denial',
644
+ 'consume_rate_limit','record_scope_denial_unbound_011','consume_rate_limit_unbound_011'
645
+ )
646
+ AND (
647
+ NOT procedure.prosecdef
648
+ OR procedure.proowner <> (SELECT nspowner FROM pg_namespace WHERE nspname='agent_bridge')
649
+ OR NOT coalesce(procedure.proconfig @> ARRAY['search_path=""'],false)
650
+ )
651
+ )
652
+ ) AS "authorityCatalog"`
653
+ );
654
+ const row = objects.rows[0];
655
+ if (!Boolean(
656
+ row?.immutable && row.deliveryAudit && row.idempotency && row.claim && row.publisher && row.terminal && row.source && row.thread && row.created && row.presence && row.project && row.targets && row.scopeSets && row.securityEvents && row.ratePolicies && row.rateBuckets && row.replacement && row.rateCleanup && row.credentialSecurity && row.eventAppendOnly && row.scopeAudit && row.rateConsume && row.securityReady && row.requestAuthorities && row.authorityOpen && row.authorityClose && row.credentialDigestHidden && row.authorityRowsHidden && row.principalTablesHidden && row.authorityTablesLocked && row.authorityCatalog
657
+ )) return false;
658
+ try {
659
+ const security = await db.query(
660
+ "SELECT agent_bridge.security_schema_ready() AS ready"
661
+ );
662
+ const ownerControl = await db.query(
663
+ "SELECT agent_bridge.owner_control_plane_ready() AS ready"
664
+ );
665
+ const portableArchive = await db.query(
666
+ "SELECT agent_bridge.portable_archive_ready() AS ready"
667
+ );
668
+ return security.rows[0]?.ready === true && ownerControl.rows[0]?.ready === true && portableArchive.rows[0]?.ready === true && await rowIsolationReady(
669
+ db,
670
+ options.allowPrivilegedCaller === true
671
+ );
672
+ } catch {
673
+ return false;
674
+ }
675
+ }
676
+ async function runMigrations(db, directory) {
677
+ const expected = await loadMigrationPlan(directory);
678
+ for (const migration of expected) {
679
+ const applied = await recordedMigrations(db);
680
+ const recorded = applied.find((entry) => entry.version === migration.version);
681
+ if (recorded) {
682
+ if (recorded.name !== migration.name || recorded.checksum !== migration.checksum) {
683
+ throw new Error(`migration ${migration.version}_${migration.name} conflicts with schema state`);
684
+ }
685
+ continue;
686
+ }
687
+ await db.query(withNativeDrSharedLock(
688
+ migration.source.split("__AGENT_BRIDGE_MIGRATION_CHECKSUM__").join(migration.checksum)
689
+ ));
690
+ const verified = (await recordedMigrations(db)).find(
691
+ (entry) => entry.version === migration.version
692
+ );
693
+ if (verified?.name !== migration.name || verified.checksum !== migration.checksum) {
694
+ throw new Error(`migration ${migration.version}_${migration.name} was not recorded correctly`);
695
+ }
696
+ }
697
+ return recordedMigrations(db);
698
+ }
699
+
700
+ export {
701
+ NATIVE_DR_ADVISORY_LOCK_KEY,
702
+ REQUIRED_MIGRATIONS,
703
+ loadMigrationPlan,
704
+ migrationsReady,
705
+ rowIsolationReady,
706
+ runtimeSchemaReady,
707
+ runMigrations
708
+ };
709
+ //# sourceMappingURL=chunk-45BZGB77.js.map