@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,471 @@
1
+ begin;
2
+
3
+ select plan(14);
4
+
5
+ select has_view('agent_board', 'v_agent_inbox', 'v_agent_inbox view exists');
6
+ select has_view('agent_board', 'v_agent_inbox_counts', 'v_agent_inbox_counts view exists');
7
+ select has_view('agent_board', 'v_board_directory', 'v_board_directory view exists');
8
+ select has_view('agent_board', 'v_board_memberships', 'v_board_memberships view exists');
9
+ select has_view('agent_board', 'v_board_feed', 'v_board_feed view exists');
10
+ select has_view('agent_board', 'v_callback_endpoint_status', 'v_callback_endpoint_status view exists');
11
+ select has_view('agent_board', 'v_callback_subscriptions', 'v_callback_subscriptions view exists');
12
+ select has_view('agent_board', 'v_callback_delivery_health', 'v_callback_delivery_health view exists');
13
+ select has_column('agent_board', 'v_agent_dashboard', 'inbox_unread_count', 'v_agent_dashboard exposes inbox_unread_count');
14
+ select has_column('agent_board', 'v_agent_dashboard', 'inbox_pending_action_count', 'v_agent_dashboard exposes inbox_pending_action_count');
15
+
16
+ select ok(
17
+ (
18
+ select count(*) = 9
19
+ from pg_class c
20
+ where c.relnamespace = 'agent_board'::regnamespace
21
+ and c.relname in (
22
+ 'v_agent_inbox',
23
+ 'v_agent_inbox_counts',
24
+ 'v_board_directory',
25
+ 'v_board_memberships',
26
+ 'v_board_feed',
27
+ 'v_callback_endpoint_status',
28
+ 'v_callback_subscriptions',
29
+ 'v_callback_delivery_health',
30
+ 'v_agent_dashboard'
31
+ )
32
+ and c.reloptions @> array['security_invoker=true']
33
+ ),
34
+ 'all inbox read views use security_invoker=true'
35
+ );
36
+
37
+ select ok(
38
+ (
39
+ select count(distinct table_name) = 9
40
+ from information_schema.role_table_grants
41
+ where table_schema = 'agent_board'
42
+ and table_name in (
43
+ 'v_agent_inbox',
44
+ 'v_agent_inbox_counts',
45
+ 'v_board_directory',
46
+ 'v_board_memberships',
47
+ 'v_board_feed',
48
+ 'v_callback_endpoint_status',
49
+ 'v_callback_subscriptions',
50
+ 'v_callback_delivery_health',
51
+ 'v_agent_dashboard'
52
+ )
53
+ and grantee = 'authenticated'
54
+ and privilege_type = 'SELECT'
55
+ ),
56
+ 'authenticated can read the inbox read-model view surface'
57
+ );
58
+
59
+ select ok(
60
+ (
61
+ select count(*) = 6
62
+ from pg_publication_tables
63
+ where pubname = 'supabase_realtime'
64
+ and schemaname = 'agent_board'
65
+ and tablename in (
66
+ 'boards',
67
+ 'board_memberships',
68
+ 'inbox_items',
69
+ 'callback_endpoints',
70
+ 'callback_subscriptions',
71
+ 'callback_delivery_attempts'
72
+ )
73
+ ),
74
+ 'supabase_realtime includes the exact INBOXREAD publication additions'
75
+ );
76
+
77
+ select ok(
78
+ not exists (
79
+ select 1
80
+ from pg_publication_tables
81
+ where pubname = 'supabase_realtime'
82
+ and schemaname = 'agent_board'
83
+ and tablename = 'callback_outbox_events'
84
+ ),
85
+ 'callback_outbox_events stays unpublished in INBOXREAD'
86
+ );
87
+
88
+ do $$
89
+ declare
90
+ v_sender uuid := gen_random_uuid();
91
+ v_recipient uuid := gen_random_uuid();
92
+ v_board_member uuid := gen_random_uuid();
93
+ v_left_member uuid := gen_random_uuid();
94
+ v_thread uuid := gen_random_uuid();
95
+ v_direct_message uuid := gen_random_uuid();
96
+ v_message uuid := gen_random_uuid();
97
+ v_task uuid := gen_random_uuid();
98
+ v_board uuid;
99
+ v_joined_membership uuid;
100
+ v_subscribed_membership uuid;
101
+ v_left_membership uuid;
102
+ v_direct_recipient uuid;
103
+ v_task_recipient uuid;
104
+ v_board_recipient_one uuid;
105
+ v_board_recipient_two uuid;
106
+ v_endpoint uuid;
107
+ v_subscription uuid;
108
+ v_outbox uuid;
109
+ begin
110
+ insert into agent_board.agents(id, agent_type, handle, display_name)
111
+ values
112
+ (v_sender, 'agent', 'test_inboxread_sender', 'Inbox Read Sender'),
113
+ (v_recipient, 'agent', 'test_inboxread_recipient', 'Inbox Read Recipient'),
114
+ (v_board_member, 'agent', 'test_inboxread_board_member', 'Inbox Read Board Member'),
115
+ (v_left_member, 'agent', 'test_inboxread_left_member', 'Inbox Read Left Member');
116
+
117
+ insert into agent_board.threads(id, thread_type, created_by_agent_id, subject)
118
+ values (v_thread, 'coordination', v_sender, 'Inbox read test thread');
119
+
120
+ insert into agent_board.tasks(
121
+ id,
122
+ thread_id,
123
+ created_by_agent_id,
124
+ assigned_agent_id,
125
+ title,
126
+ details,
127
+ status,
128
+ priority
129
+ )
130
+ values (
131
+ v_task,
132
+ v_thread,
133
+ v_sender,
134
+ v_recipient,
135
+ 'Inbox read test task',
136
+ 'Validate task-backed inbox reads',
137
+ 'pending',
138
+ 'high'
139
+ );
140
+
141
+ insert into agent_board.messages(id, thread_id, author_agent_id, message_sequence, message_type, body)
142
+ values
143
+ (v_direct_message, v_thread, v_sender, 1, 'comment', 'direct post body'),
144
+ (v_message, v_thread, v_sender, 2, 'comment', 'board post body');
145
+
146
+ insert into agent_board.boards(slug, name, description, created_by_agent_id)
147
+ values ('test-inboxread-board', 'Inbox Read Board', 'board used for inbox read tests', v_sender)
148
+ returning id into v_board;
149
+
150
+ insert into agent_board.board_memberships(board_id, agent_id, membership_state, created_by_agent_id)
151
+ values (v_board, v_recipient, 'joined', v_sender)
152
+ returning id into v_joined_membership;
153
+
154
+ insert into agent_board.board_memberships(board_id, agent_id, membership_state, created_by_agent_id)
155
+ values (v_board, v_board_member, 'subscribed', v_sender)
156
+ returning id into v_subscribed_membership;
157
+
158
+ insert into agent_board.board_memberships(board_id, agent_id, membership_state, created_by_agent_id, left_at)
159
+ values (v_board, v_left_member, 'left', v_sender, now())
160
+ returning id into v_left_membership;
161
+
162
+ insert into agent_board.delivery_recipients(delivery_mode, recipient_agent_id, source_kind, source_message_id)
163
+ values ('direct', v_recipient, 'message', v_direct_message)
164
+ returning id into v_direct_recipient;
165
+
166
+ insert into agent_board.inbox_items(
167
+ delivery_recipient_id,
168
+ recipient_agent_id,
169
+ delivery_mode,
170
+ source_kind,
171
+ source_message_id,
172
+ subject,
173
+ preview,
174
+ priority,
175
+ action_state,
176
+ visible_in_inbox,
177
+ visible_in_board_feed,
178
+ fetch_descriptor
179
+ )
180
+ values (
181
+ v_direct_recipient,
182
+ v_recipient,
183
+ 'direct',
184
+ 'message',
185
+ v_direct_message,
186
+ 'Direct inbox subject',
187
+ 'Direct preview',
188
+ 'high',
189
+ 'new',
190
+ true,
191
+ false,
192
+ jsonb_build_object('surface', 'thread', 'targetId', v_thread::text, 'view', 'agent_board.v_thread_feed', 'filters', jsonb_build_object(), 'reason', 'direct delivery')
193
+ );
194
+
195
+ insert into agent_board.delivery_recipients(delivery_mode, recipient_agent_id, source_kind, source_task_id)
196
+ values ('tasking', v_recipient, 'task', v_task)
197
+ returning id into v_task_recipient;
198
+
199
+ insert into agent_board.inbox_items(
200
+ delivery_recipient_id,
201
+ recipient_agent_id,
202
+ delivery_mode,
203
+ source_kind,
204
+ source_task_id,
205
+ subject,
206
+ preview,
207
+ priority,
208
+ action_state,
209
+ visible_in_inbox,
210
+ visible_in_board_feed,
211
+ fetch_descriptor
212
+ )
213
+ values (
214
+ v_task_recipient,
215
+ v_recipient,
216
+ 'tasking',
217
+ 'task',
218
+ v_task,
219
+ 'Task inbox subject',
220
+ 'Task preview',
221
+ 'urgent',
222
+ 'deferred',
223
+ true,
224
+ false,
225
+ jsonb_build_object('surface', 'task', 'targetId', v_task::text, 'view', 'agent_board.v_task_tree', 'filters', jsonb_build_object(), 'reason', 'tasking delivery')
226
+ );
227
+
228
+ insert into agent_board.delivery_recipients(
229
+ delivery_mode,
230
+ recipient_agent_id,
231
+ source_kind,
232
+ source_message_id,
233
+ board_id,
234
+ board_membership_id
235
+ )
236
+ values ('board', v_recipient, 'message', v_message, v_board, v_joined_membership)
237
+ returning id into v_board_recipient_one;
238
+
239
+ insert into agent_board.delivery_recipients(
240
+ delivery_mode,
241
+ recipient_agent_id,
242
+ source_kind,
243
+ source_message_id,
244
+ board_id,
245
+ board_membership_id
246
+ )
247
+ values ('board', v_board_member, 'message', v_message, v_board, v_subscribed_membership)
248
+ returning id into v_board_recipient_two;
249
+
250
+ insert into agent_board.inbox_items(
251
+ delivery_recipient_id,
252
+ recipient_agent_id,
253
+ board_id,
254
+ delivery_mode,
255
+ source_kind,
256
+ source_message_id,
257
+ subject,
258
+ preview,
259
+ priority,
260
+ action_state,
261
+ visible_in_inbox,
262
+ visible_in_board_feed,
263
+ fetch_descriptor
264
+ )
265
+ values
266
+ (
267
+ v_board_recipient_one,
268
+ v_recipient,
269
+ v_board,
270
+ 'board',
271
+ 'message',
272
+ v_message,
273
+ 'Board inbox subject',
274
+ 'Board preview',
275
+ 'medium',
276
+ 'read',
277
+ false,
278
+ true,
279
+ jsonb_build_object('surface', 'board', 'targetId', v_board::text, 'view', 'agent_board.v_board_feed', 'filters', jsonb_build_object(), 'reason', 'board delivery')
280
+ ),
281
+ (
282
+ v_board_recipient_two,
283
+ v_board_member,
284
+ v_board,
285
+ 'board',
286
+ 'message',
287
+ v_message,
288
+ 'Board inbox subject',
289
+ 'Board preview',
290
+ 'medium',
291
+ 'new',
292
+ true,
293
+ true,
294
+ jsonb_build_object('surface', 'board', 'targetId', v_board::text, 'view', 'agent_board.v_board_feed', 'filters', jsonb_build_object(), 'reason', 'board delivery')
295
+ );
296
+
297
+ insert into agent_board.callback_endpoints(
298
+ id,
299
+ owner_agent_id,
300
+ endpoint_url,
301
+ endpoint_status,
302
+ verification_requested_at,
303
+ verified_at,
304
+ last_failure_at
305
+ )
306
+ values (
307
+ gen_random_uuid(),
308
+ v_recipient,
309
+ 'https://example.test/inbox-read-callback',
310
+ 'verified',
311
+ now(),
312
+ now(),
313
+ now()
314
+ )
315
+ returning id into v_endpoint;
316
+
317
+ insert into agent_board.callback_subscriptions(
318
+ endpoint_id,
319
+ agent_id,
320
+ subscription_scope,
321
+ event_category,
322
+ board_id,
323
+ board_membership_id,
324
+ subscription_status
325
+ )
326
+ values (
327
+ v_endpoint,
328
+ v_recipient,
329
+ 'board',
330
+ 'board.post.delivered',
331
+ v_board,
332
+ v_joined_membership,
333
+ 'active'
334
+ )
335
+ returning id into v_subscription;
336
+
337
+ insert into agent_board.callback_outbox_events(
338
+ endpoint_id,
339
+ subscription_id,
340
+ recipient_agent_id,
341
+ board_id,
342
+ event_category,
343
+ delivery_mode,
344
+ source_kind,
345
+ source_message_id,
346
+ idempotency_key,
347
+ subject,
348
+ preview,
349
+ priority,
350
+ fetch_descriptor,
351
+ outbox_status
352
+ )
353
+ values (
354
+ v_endpoint,
355
+ v_subscription,
356
+ v_recipient,
357
+ v_board,
358
+ 'board.post.delivered',
359
+ 'board',
360
+ 'message',
361
+ v_message,
362
+ 'test-inboxread-health',
363
+ 'Board inbox subject',
364
+ 'Board preview',
365
+ 'medium',
366
+ jsonb_build_object('surface', 'board', 'targetId', v_board::text, 'view', 'agent_board.v_board_feed', 'filters', jsonb_build_object(), 'reason', 'board delivery'),
367
+ 'retryable'
368
+ )
369
+ returning id into v_outbox;
370
+
371
+ insert into agent_board.callback_delivery_attempts(
372
+ outbox_event_id,
373
+ endpoint_id,
374
+ attempt_number,
375
+ attempt_outcome,
376
+ http_status,
377
+ error_summary,
378
+ started_at,
379
+ finished_at,
380
+ next_retry_at
381
+ )
382
+ values (
383
+ v_outbox,
384
+ v_endpoint,
385
+ 1,
386
+ 'retryable_failure',
387
+ 503,
388
+ 'temporary callback failure',
389
+ now() - interval '2 minutes',
390
+ now() - interval '1 minute',
391
+ now() + interval '5 minutes'
392
+ );
393
+
394
+ perform is(
395
+ (select count(*)::bigint from agent_board.v_agent_inbox where recipient_agent_id = v_recipient),
396
+ 2::bigint,
397
+ 'v_agent_inbox returns visible inbox rows only'
398
+ );
399
+
400
+ perform is(
401
+ (select unread_count from agent_board.v_agent_inbox_counts where recipient_agent_id = v_recipient),
402
+ 1::bigint,
403
+ 'v_agent_inbox_counts computes unread_count from new and restored rows'
404
+ );
405
+
406
+ perform is(
407
+ (select pending_action_count from agent_board.v_agent_inbox_counts where recipient_agent_id = v_recipient),
408
+ 2::bigint,
409
+ 'v_agent_inbox_counts computes pending_action_count from actionable rows'
410
+ );
411
+
412
+ perform is(
413
+ (select active_member_count from agent_board.v_board_directory where board_id = v_board),
414
+ 2::bigint,
415
+ 'v_board_directory counts joined and subscribed members only'
416
+ );
417
+
418
+ perform is(
419
+ (select count(*)::bigint from agent_board.v_board_feed where board_id = v_board and message_id = v_message),
420
+ 1::bigint,
421
+ 'v_board_feed deduplicates a canonical board post across recipient fan-out'
422
+ );
423
+
424
+ perform is(
425
+ (select active_subscription_count from agent_board.v_callback_endpoint_status where endpoint_id = v_endpoint),
426
+ 1::bigint,
427
+ 'v_callback_endpoint_status counts active subscriptions'
428
+ );
429
+
430
+ perform ok(
431
+ exists (
432
+ select 1
433
+ from agent_board.v_callback_subscriptions
434
+ where subscription_id = v_subscription
435
+ and board_slug = 'test-inboxread-board'
436
+ ),
437
+ 'v_callback_subscriptions exposes board-scoped subscription metadata'
438
+ );
439
+
440
+ perform is(
441
+ (select latest_attempt_outcome from agent_board.v_callback_delivery_health where subscription_id = v_subscription),
442
+ 'retryable_failure',
443
+ 'v_callback_delivery_health anchors on the latest delivery attempt'
444
+ );
445
+
446
+ perform ok(
447
+ (
448
+ select latest_next_retry_at is not null
449
+ from agent_board.v_callback_delivery_health
450
+ where subscription_id = v_subscription
451
+ ),
452
+ 'v_callback_delivery_health exposes retry scheduling metadata'
453
+ );
454
+
455
+ perform is(
456
+ (select inbox_unread_count from agent_board.v_agent_dashboard where agent_id = v_recipient),
457
+ 1::bigint,
458
+ 'v_agent_dashboard exposes compact unread inbox counts'
459
+ );
460
+
461
+ perform is(
462
+ (select inbox_pending_action_count from agent_board.v_agent_dashboard where agent_id = v_recipient),
463
+ 2::bigint,
464
+ 'v_agent_dashboard exposes compact pending-action inbox counts'
465
+ );
466
+ end;
467
+ $$;
468
+
469
+ select * from finish();
470
+
471
+ rollback;