@consiliency/agent-board-schema 1.2.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.
Files changed (92) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +11 -0
  3. package/README.md +55 -0
  4. package/bin/agent-board-schema.js +97 -0
  5. package/fixtures/already-applied.json +181 -0
  6. package/fixtures/divergent-history.json +173 -0
  7. package/fixtures/production-history.json +173 -0
  8. package/migrations/20260501000001_agent_board_schema_version.sql +12 -0
  9. package/migrations/20260502000000_agent_board_schema.sql +180 -0
  10. package/migrations/20260503000000_agent_board_rpcs.sql +422 -0
  11. package/migrations/20260503000001_agent_board_coordination_rpcs.sql +229 -0
  12. package/migrations/20260504000000_agent_board_read_models.sql +206 -0
  13. package/migrations/20260505000000_agent_board_inbox_schema.sql +341 -0
  14. package/migrations/20260506000000_agent_board_inbox_delivery_rpcs.sql +1200 -0
  15. package/migrations/20260506000001_agent_board_inbox_callback_rpcs.sql +330 -0
  16. package/migrations/20260507000000_agent_board_inbox_reads.sql +334 -0
  17. package/migrations/20260508000000_agent_board_callback_runtime.sql +453 -0
  18. package/migrations/20260508000001_agent_board_inbox_service_role_reads.sql +10 -0
  19. package/migrations/20260510000000_agent_board_dblint_repairs.sql +413 -0
  20. package/migrations/20260511000000_agent_board_auth_schema.sql +146 -0
  21. package/migrations/20260511000001_agent_board_auth_credentials.sql +39 -0
  22. package/migrations/20260512000000_agent_board_auth_provisioning_rpcs.sql +622 -0
  23. package/migrations/20260512000001_agent_board_auth_v1_rpcs.sql +798 -0
  24. package/migrations/20260512000002_agent_board_auth_v2_rpcs.sql +1243 -0
  25. package/migrations/20260512000003_agent_board_auth_rls.sql +484 -0
  26. package/migrations/20260513000000_agent_board_backup_ops.sql +34 -0
  27. package/migrations/20260513000001_agent_board_retention.sql +160 -0
  28. package/migrations/20260513000002_agent_board_monitoring_views.sql +227 -0
  29. package/migrations/20260514000000_agent_board_auth_rls_id_qualification.sql +150 -0
  30. package/migrations/20260515000000_agent_board_boardopt.sql +493 -0
  31. package/migrations/20260516000000_agent_board_callbackcap.sql +113 -0
  32. package/migrations/20260517000000_agent_board_addressing.sql +542 -0
  33. package/migrations/20260628000000_agent_board_signing_store.sql +174 -0
  34. package/migrations/20260628000001_agent_board_signing_proof_rpcs.sql +215 -0
  35. package/migrations/20260628000002_agent_board_signature_rls_reads.sql +300 -0
  36. package/migrations/20260628000003_agent_board_signed_write_gateway.sql +288 -0
  37. package/migrations/20260628000004_agent_board_fleet_registry.sql +411 -0
  38. package/migrations/20260628000005_agent_board_fleet_policy.sql +509 -0
  39. package/migrations/20260628000006_agent_board_fleet_read_models.sql +170 -0
  40. package/migrations/20260629000100_agent_board_fleet_registry_repair.sql +411 -0
  41. package/migrations/20260629000101_agent_board_fleet_policy_refresh.sql +509 -0
  42. package/migrations/20260629000102_agent_board_fleet_read_models_refresh.sql +170 -0
  43. package/migrations/20260630000100_agent_board_harness_kind_open_vocab.sql +15 -0
  44. package/migrations/20260710000000_agent_board_authbound_boundary.sql +155 -0
  45. package/migrations/20260710000100_agent_board_schema_version_rpc.sql +14 -0
  46. package/migrations/20260710000400_agent_board_nonfleet_identity.sql +87 -0
  47. package/migrations/20260710000401_agent_board_workload_providers.sql +39 -0
  48. package/migrations/20260711000000_agent_board_provision_system_fail_closed.sql +242 -0
  49. package/migrations/20260711000100_canary_signed_fleet_enforcement.sql +234 -0
  50. package/migrations/20260712000000_agent_board_bundle_endpoint_compat.sql +97 -0
  51. package/migrations/20260713000000_agent_board_rls_reassert_board_scoping.sql +90 -0
  52. package/package.json +42 -0
  53. package/provenance.json +580 -0
  54. package/schema-manifest.json +458 -0
  55. package/src/check.js +23 -0
  56. package/src/index.js +50 -0
  57. package/src/materialize.js +73 -0
  58. package/src/plan.js +44 -0
  59. package/src/tooling.test.mjs +97 -0
  60. package/tests/agent_board_addressing.test.sql +166 -0
  61. package/tests/agent_board_auth_rls.test.sql +243 -0
  62. package/tests/agent_board_auth_rls_id_qualification.test.sql +225 -0
  63. package/tests/agent_board_auth_rpcs.test.sql +311 -0
  64. package/tests/agent_board_auth_schema.test.sql +411 -0
  65. package/tests/agent_board_authbound_boundary.test.sql +148 -0
  66. package/tests/agent_board_boardopt.test.sql +170 -0
  67. package/tests/agent_board_bundle_endpoint_compat.test.sql +49 -0
  68. package/tests/agent_board_callback_runtime.test.sql +425 -0
  69. package/tests/agent_board_callbackcap.test.sql +222 -0
  70. package/tests/agent_board_canary_signed_fleet_enforcement.test.sql +60 -0
  71. package/tests/agent_board_dblint_rpcs.test.sql +247 -0
  72. package/tests/agent_board_fleet_policy.test.sql +370 -0
  73. package/tests/agent_board_fleet_read_models.test.sql +158 -0
  74. package/tests/agent_board_fleet_registry.test.sql +149 -0
  75. package/tests/agent_board_inbox_reads.test.sql +471 -0
  76. package/tests/agent_board_inbox_rpcs.test.sql +452 -0
  77. package/tests/agent_board_inbox_schema.test.sql +355 -0
  78. package/tests/agent_board_nonfleet_identity.test.sql +26 -0
  79. package/tests/agent_board_rls_reassert_board_scoping.test.sql +39 -0
  80. package/tests/agent_board_schema_version.test.sql +24 -0
  81. package/tests/agent_board_schema_version_rpc.test.sql +40 -0
  82. package/tests/agent_board_signature_rls_reads.test.sql +133 -0
  83. package/tests/agent_board_signed_write_gateway.test.sql +219 -0
  84. package/tests/agent_board_signing_proof_rpcs.test.sql +143 -0
  85. package/tests/agent_board_signing_store.test.sql +183 -0
  86. package/tests/agent_board_smoke.test.sql +12 -0
  87. package/tests/agent_board_v1_invariants.test.sql +298 -0
  88. package/tests/agent_board_v2_invariants.test.sql +753 -0
  89. package/tests/agent_board_workload_providers.test.sql +15 -0
  90. package/tests/fixtures/adopter-base.sql +19 -0
  91. package/tests/fixtures/operator-hardening.sql +27 -0
  92. package/tests/fixtures/test-prereqs.sql +84 -0
@@ -0,0 +1,453 @@
1
+ create or replace function agent_board._next_callback_attempt_number(
2
+ p_outbox_event_id uuid
3
+ )
4
+ returns integer
5
+ language sql
6
+ security definer
7
+ set search_path = agent_board, public
8
+ stable
9
+ as $$
10
+ select coalesce(max(cda.attempt_number), 0) + 1
11
+ from agent_board.callback_delivery_attempts cda
12
+ where cda.outbox_event_id = p_outbox_event_id;
13
+ $$;
14
+
15
+ create or replace function agent_board.claim_callback_outbox_events(
16
+ p_batch_size integer default 25
17
+ )
18
+ returns table(
19
+ outbox_event_id uuid,
20
+ endpoint_id uuid,
21
+ subscription_id uuid,
22
+ recipient_agent_id uuid,
23
+ inbox_item_id uuid,
24
+ board_id uuid,
25
+ endpoint_url text,
26
+ signing_key_version integer,
27
+ event_category text,
28
+ delivery_mode text,
29
+ source_kind text,
30
+ source_message_id uuid,
31
+ source_task_id uuid,
32
+ source_delegation_id uuid,
33
+ idempotency_key text,
34
+ subject text,
35
+ preview text,
36
+ priority text,
37
+ fetch_descriptor jsonb,
38
+ outbox_created_at timestamptz,
39
+ queued_at timestamptz,
40
+ claimed_at timestamptz,
41
+ attempt_number integer,
42
+ endpoint_status text,
43
+ subscription_status text,
44
+ metadata jsonb
45
+ )
46
+ language plpgsql
47
+ security definer
48
+ set search_path = agent_board, public
49
+ as $$
50
+ begin
51
+ if p_batch_size is null or p_batch_size < 1 or p_batch_size > 100 then
52
+ raise exception 'callback batch size must be between 1 and 100' using errcode = '22023';
53
+ end if;
54
+
55
+ return query
56
+ with candidates as (
57
+ select coe.id
58
+ from agent_board.callback_outbox_events coe
59
+ join agent_board.callback_endpoints ce on ce.id = coe.endpoint_id
60
+ join agent_board.callback_subscriptions cs on cs.id = coe.subscription_id
61
+ where coe.outbox_status in ('pending', 'retryable')
62
+ and coe.available_at <= now()
63
+ and ce.endpoint_status = 'verified'
64
+ and cs.subscription_status = 'active'
65
+ order by coe.available_at asc, coe.created_at asc, coe.id asc
66
+ for update of coe skip locked
67
+ limit p_batch_size
68
+ ),
69
+ updated as (
70
+ update agent_board.callback_outbox_events coe
71
+ set outbox_status = 'delivering',
72
+ locked_at = now(),
73
+ updated_at = now()
74
+ from candidates
75
+ where coe.id = candidates.id
76
+ returning coe.*
77
+ )
78
+ select
79
+ u.id,
80
+ u.endpoint_id,
81
+ u.subscription_id,
82
+ u.recipient_agent_id,
83
+ u.inbox_item_id,
84
+ u.board_id,
85
+ ce.endpoint_url,
86
+ ce.signing_key_version,
87
+ u.event_category,
88
+ u.delivery_mode,
89
+ u.source_kind,
90
+ u.source_message_id,
91
+ u.source_task_id,
92
+ u.source_delegation_id,
93
+ u.idempotency_key,
94
+ u.subject,
95
+ u.preview,
96
+ u.priority,
97
+ u.fetch_descriptor,
98
+ u.created_at,
99
+ u.available_at,
100
+ u.locked_at,
101
+ agent_board._next_callback_attempt_number(u.id),
102
+ ce.endpoint_status,
103
+ cs.subscription_status,
104
+ coalesce(u.metadata, '{}'::jsonb)
105
+ from updated u
106
+ join agent_board.callback_endpoints ce on ce.id = u.endpoint_id
107
+ join agent_board.callback_subscriptions cs on cs.id = u.subscription_id;
108
+ end;
109
+ $$;
110
+
111
+ create or replace function agent_board.record_callback_delivery_success(
112
+ p_outbox_event_id uuid,
113
+ p_endpoint_id uuid,
114
+ p_http_status integer default 200,
115
+ p_metadata jsonb default '{}'::jsonb
116
+ )
117
+ returns table(
118
+ outbox_event_id uuid,
119
+ endpoint_id uuid,
120
+ outbox_status text,
121
+ attempt_outcome text,
122
+ attempt_number integer,
123
+ delivered_at timestamptz
124
+ )
125
+ language plpgsql
126
+ security definer
127
+ set search_path = agent_board, public
128
+ as $$
129
+ declare
130
+ v_outbox agent_board.callback_outbox_events%rowtype;
131
+ v_attempt_number integer;
132
+ v_finished_at timestamptz := now();
133
+ begin
134
+ select *
135
+ into v_outbox
136
+ from agent_board.callback_outbox_events coe
137
+ where coe.id = p_outbox_event_id
138
+ and coe.endpoint_id = p_endpoint_id
139
+ for update;
140
+
141
+ if v_outbox.id is null then
142
+ raise exception 'callback outbox event not found' using errcode = 'P0002';
143
+ end if;
144
+
145
+ v_attempt_number := agent_board._next_callback_attempt_number(v_outbox.id);
146
+
147
+ insert into agent_board.callback_delivery_attempts(
148
+ outbox_event_id,
149
+ endpoint_id,
150
+ attempt_number,
151
+ attempt_outcome,
152
+ http_status,
153
+ started_at,
154
+ finished_at,
155
+ metadata
156
+ )
157
+ values (
158
+ v_outbox.id,
159
+ p_endpoint_id,
160
+ v_attempt_number,
161
+ 'delivered',
162
+ p_http_status,
163
+ coalesce(v_outbox.locked_at, v_finished_at),
164
+ v_finished_at,
165
+ coalesce(p_metadata, '{}'::jsonb)
166
+ );
167
+
168
+ update agent_board.callback_outbox_events coe
169
+ set outbox_status = 'delivered',
170
+ delivered_at = v_finished_at,
171
+ last_error_at = null,
172
+ locked_at = null,
173
+ updated_at = v_finished_at,
174
+ metadata = coalesce(coe.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb)
175
+ where coe.id = v_outbox.id;
176
+
177
+ update agent_board.callback_endpoints ce
178
+ set last_delivery_at = v_finished_at,
179
+ updated_at = v_finished_at
180
+ where ce.id = p_endpoint_id;
181
+
182
+ return query
183
+ select v_outbox.id, p_endpoint_id, 'delivered'::text, 'delivered'::text, v_attempt_number, v_finished_at;
184
+ end;
185
+ $$;
186
+
187
+ create or replace function agent_board.record_callback_delivery_retry(
188
+ p_outbox_event_id uuid,
189
+ p_endpoint_id uuid,
190
+ p_http_status integer default null,
191
+ p_error_summary text default null,
192
+ p_next_retry_at timestamptz default null,
193
+ p_metadata jsonb default '{}'::jsonb
194
+ )
195
+ returns table(
196
+ outbox_event_id uuid,
197
+ endpoint_id uuid,
198
+ outbox_status text,
199
+ attempt_outcome text,
200
+ attempt_number integer,
201
+ next_retry_at timestamptz
202
+ )
203
+ language plpgsql
204
+ security definer
205
+ set search_path = agent_board, public
206
+ as $$
207
+ declare
208
+ v_outbox agent_board.callback_outbox_events%rowtype;
209
+ v_attempt_number integer;
210
+ v_finished_at timestamptz := now();
211
+ begin
212
+ select *
213
+ into v_outbox
214
+ from agent_board.callback_outbox_events coe
215
+ where coe.id = p_outbox_event_id
216
+ and coe.endpoint_id = p_endpoint_id
217
+ for update;
218
+
219
+ if v_outbox.id is null then
220
+ raise exception 'callback outbox event not found' using errcode = 'P0002';
221
+ end if;
222
+ if p_next_retry_at is null or p_next_retry_at <= v_finished_at then
223
+ raise exception 'next retry timestamp must be in the future' using errcode = '22023';
224
+ end if;
225
+
226
+ v_attempt_number := agent_board._next_callback_attempt_number(v_outbox.id);
227
+
228
+ insert into agent_board.callback_delivery_attempts(
229
+ outbox_event_id,
230
+ endpoint_id,
231
+ attempt_number,
232
+ attempt_outcome,
233
+ http_status,
234
+ error_summary,
235
+ started_at,
236
+ finished_at,
237
+ next_retry_at,
238
+ metadata
239
+ )
240
+ values (
241
+ v_outbox.id,
242
+ p_endpoint_id,
243
+ v_attempt_number,
244
+ 'retryable_failure',
245
+ p_http_status,
246
+ nullif(trim(p_error_summary), ''),
247
+ coalesce(v_outbox.locked_at, v_finished_at),
248
+ v_finished_at,
249
+ p_next_retry_at,
250
+ coalesce(p_metadata, '{}'::jsonb)
251
+ );
252
+
253
+ update agent_board.callback_outbox_events coe
254
+ set outbox_status = 'retryable',
255
+ available_at = p_next_retry_at,
256
+ last_error_at = v_finished_at,
257
+ locked_at = null,
258
+ updated_at = v_finished_at,
259
+ metadata = coalesce(coe.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb)
260
+ where coe.id = v_outbox.id;
261
+
262
+ update agent_board.callback_endpoints ce
263
+ set last_failure_at = v_finished_at,
264
+ updated_at = v_finished_at
265
+ where ce.id = p_endpoint_id;
266
+
267
+ return query
268
+ select v_outbox.id, p_endpoint_id, 'retryable'::text, 'retryable_failure'::text, v_attempt_number, p_next_retry_at;
269
+ end;
270
+ $$;
271
+
272
+ create or replace function agent_board.record_callback_delivery_terminal_failure(
273
+ p_outbox_event_id uuid,
274
+ p_endpoint_id uuid,
275
+ p_http_status integer default null,
276
+ p_error_summary text default null,
277
+ p_metadata jsonb default '{}'::jsonb
278
+ )
279
+ returns table(
280
+ outbox_event_id uuid,
281
+ endpoint_id uuid,
282
+ outbox_status text,
283
+ attempt_outcome text,
284
+ attempt_number integer,
285
+ failed_at timestamptz
286
+ )
287
+ language plpgsql
288
+ security definer
289
+ set search_path = agent_board, public
290
+ as $$
291
+ declare
292
+ v_outbox agent_board.callback_outbox_events%rowtype;
293
+ v_attempt_number integer;
294
+ v_finished_at timestamptz := now();
295
+ begin
296
+ select *
297
+ into v_outbox
298
+ from agent_board.callback_outbox_events coe
299
+ where coe.id = p_outbox_event_id
300
+ and coe.endpoint_id = p_endpoint_id
301
+ for update;
302
+
303
+ if v_outbox.id is null then
304
+ raise exception 'callback outbox event not found' using errcode = 'P0002';
305
+ end if;
306
+
307
+ v_attempt_number := agent_board._next_callback_attempt_number(v_outbox.id);
308
+
309
+ insert into agent_board.callback_delivery_attempts(
310
+ outbox_event_id,
311
+ endpoint_id,
312
+ attempt_number,
313
+ attempt_outcome,
314
+ http_status,
315
+ error_summary,
316
+ started_at,
317
+ finished_at,
318
+ metadata
319
+ )
320
+ values (
321
+ v_outbox.id,
322
+ p_endpoint_id,
323
+ v_attempt_number,
324
+ 'terminal_failure',
325
+ p_http_status,
326
+ nullif(trim(p_error_summary), ''),
327
+ coalesce(v_outbox.locked_at, v_finished_at),
328
+ v_finished_at,
329
+ coalesce(p_metadata, '{}'::jsonb)
330
+ );
331
+
332
+ update agent_board.callback_outbox_events coe
333
+ set outbox_status = 'failed',
334
+ last_error_at = v_finished_at,
335
+ locked_at = null,
336
+ updated_at = v_finished_at,
337
+ metadata = coalesce(coe.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb)
338
+ where coe.id = v_outbox.id;
339
+
340
+ update agent_board.callback_endpoints ce
341
+ set last_failure_at = v_finished_at,
342
+ updated_at = v_finished_at
343
+ where ce.id = p_endpoint_id;
344
+
345
+ return query
346
+ select v_outbox.id, p_endpoint_id, 'failed'::text, 'terminal_failure'::text, v_attempt_number, v_finished_at;
347
+ end;
348
+ $$;
349
+
350
+ create or replace function agent_board.disable_callback_delivery_endpoint(
351
+ p_endpoint_id uuid,
352
+ p_outbox_event_id uuid default null,
353
+ p_disabled_reason text default null,
354
+ p_error_summary text default null,
355
+ p_metadata jsonb default '{}'::jsonb
356
+ )
357
+ returns table(
358
+ endpoint_id uuid,
359
+ endpoint_status text,
360
+ outbox_event_id uuid,
361
+ outbox_status text,
362
+ attempt_outcome text,
363
+ disabled_at timestamptz
364
+ )
365
+ language plpgsql
366
+ security definer
367
+ set search_path = agent_board, public
368
+ as $$
369
+ declare
370
+ v_endpoint agent_board.callback_endpoints%rowtype;
371
+ v_outbox agent_board.callback_outbox_events%rowtype;
372
+ v_attempt_number integer;
373
+ v_disabled_at timestamptz := now();
374
+ begin
375
+ select *
376
+ into v_endpoint
377
+ from agent_board.callback_endpoints ce
378
+ where ce.id = p_endpoint_id
379
+ for update;
380
+
381
+ if v_endpoint.id is null then
382
+ raise exception 'callback endpoint not found' using errcode = 'P0002';
383
+ end if;
384
+
385
+ update agent_board.callback_endpoints ce
386
+ set endpoint_status = 'disabled',
387
+ disabled_at = coalesce(ce.disabled_at, v_disabled_at),
388
+ disabled_reason = coalesce(nullif(trim(p_disabled_reason), ''), ce.disabled_reason, 'callback runtime disabled endpoint'),
389
+ last_failure_at = v_disabled_at,
390
+ updated_at = v_disabled_at,
391
+ metadata = coalesce(ce.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb)
392
+ where ce.id = p_endpoint_id
393
+ returning * into v_endpoint;
394
+
395
+ update agent_board.callback_subscriptions cs
396
+ set subscription_status = 'disabled',
397
+ disabled_at = coalesce(cs.disabled_at, v_disabled_at),
398
+ updated_at = v_disabled_at
399
+ where cs.endpoint_id = p_endpoint_id
400
+ and cs.subscription_status <> 'disabled';
401
+
402
+ update agent_board.callback_outbox_events coe
403
+ set outbox_status = 'disabled',
404
+ last_error_at = v_disabled_at,
405
+ locked_at = null,
406
+ updated_at = v_disabled_at,
407
+ metadata = coalesce(coe.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb)
408
+ where coe.endpoint_id = p_endpoint_id
409
+ and coe.outbox_status in ('pending', 'delivering', 'retryable');
410
+
411
+ if p_outbox_event_id is not null then
412
+ select *
413
+ into v_outbox
414
+ from agent_board.callback_outbox_events coe
415
+ where coe.id = p_outbox_event_id
416
+ and coe.endpoint_id = p_endpoint_id
417
+ for update;
418
+
419
+ if v_outbox.id is null then
420
+ raise exception 'callback outbox event not found' using errcode = 'P0002';
421
+ end if;
422
+
423
+ v_attempt_number := agent_board._next_callback_attempt_number(v_outbox.id);
424
+
425
+ insert into agent_board.callback_delivery_attempts(
426
+ outbox_event_id,
427
+ endpoint_id,
428
+ attempt_number,
429
+ attempt_outcome,
430
+ error_summary,
431
+ started_at,
432
+ finished_at,
433
+ metadata
434
+ )
435
+ values (
436
+ v_outbox.id,
437
+ p_endpoint_id,
438
+ v_attempt_number,
439
+ 'endpoint_disabled',
440
+ coalesce(nullif(trim(p_error_summary), ''), nullif(trim(p_disabled_reason), ''), 'callback endpoint disabled'),
441
+ coalesce(v_outbox.locked_at, v_disabled_at),
442
+ v_disabled_at,
443
+ coalesce(p_metadata, '{}'::jsonb)
444
+ );
445
+ end if;
446
+
447
+ return query
448
+ select p_endpoint_id, 'disabled'::text, p_outbox_event_id, 'disabled'::text, 'endpoint_disabled'::text, v_disabled_at;
449
+ end;
450
+ $$;
451
+
452
+ revoke all on all functions in schema agent_board from public, anon, authenticated;
453
+ grant execute on all functions in schema agent_board to service_role;
@@ -0,0 +1,10 @@
1
+ grant select on agent_board.v_agent_inbox,
2
+ agent_board.v_agent_inbox_counts,
3
+ agent_board.v_board_directory,
4
+ agent_board.v_board_memberships,
5
+ agent_board.v_board_feed,
6
+ agent_board.v_callback_endpoint_status,
7
+ agent_board.v_callback_subscriptions,
8
+ agent_board.v_callback_delivery_health,
9
+ agent_board.v_agent_dashboard
10
+ to service_role;