@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.
- package/LICENSE +202 -0
- package/NOTICE +11 -0
- package/README.md +55 -0
- package/bin/agent-board-schema.js +97 -0
- package/fixtures/already-applied.json +181 -0
- package/fixtures/divergent-history.json +173 -0
- package/fixtures/production-history.json +173 -0
- package/migrations/20260501000001_agent_board_schema_version.sql +12 -0
- package/migrations/20260502000000_agent_board_schema.sql +180 -0
- package/migrations/20260503000000_agent_board_rpcs.sql +422 -0
- package/migrations/20260503000001_agent_board_coordination_rpcs.sql +229 -0
- package/migrations/20260504000000_agent_board_read_models.sql +206 -0
- package/migrations/20260505000000_agent_board_inbox_schema.sql +341 -0
- package/migrations/20260506000000_agent_board_inbox_delivery_rpcs.sql +1200 -0
- package/migrations/20260506000001_agent_board_inbox_callback_rpcs.sql +330 -0
- package/migrations/20260507000000_agent_board_inbox_reads.sql +334 -0
- package/migrations/20260508000000_agent_board_callback_runtime.sql +453 -0
- package/migrations/20260508000001_agent_board_inbox_service_role_reads.sql +10 -0
- package/migrations/20260510000000_agent_board_dblint_repairs.sql +413 -0
- package/migrations/20260511000000_agent_board_auth_schema.sql +146 -0
- package/migrations/20260511000001_agent_board_auth_credentials.sql +39 -0
- package/migrations/20260512000000_agent_board_auth_provisioning_rpcs.sql +622 -0
- package/migrations/20260512000001_agent_board_auth_v1_rpcs.sql +798 -0
- package/migrations/20260512000002_agent_board_auth_v2_rpcs.sql +1243 -0
- package/migrations/20260512000003_agent_board_auth_rls.sql +484 -0
- package/migrations/20260513000000_agent_board_backup_ops.sql +34 -0
- package/migrations/20260513000001_agent_board_retention.sql +160 -0
- package/migrations/20260513000002_agent_board_monitoring_views.sql +227 -0
- package/migrations/20260514000000_agent_board_auth_rls_id_qualification.sql +150 -0
- package/migrations/20260515000000_agent_board_boardopt.sql +493 -0
- package/migrations/20260516000000_agent_board_callbackcap.sql +113 -0
- package/migrations/20260517000000_agent_board_addressing.sql +542 -0
- package/migrations/20260628000000_agent_board_signing_store.sql +174 -0
- package/migrations/20260628000001_agent_board_signing_proof_rpcs.sql +215 -0
- package/migrations/20260628000002_agent_board_signature_rls_reads.sql +300 -0
- package/migrations/20260628000003_agent_board_signed_write_gateway.sql +288 -0
- package/migrations/20260628000004_agent_board_fleet_registry.sql +411 -0
- package/migrations/20260628000005_agent_board_fleet_policy.sql +509 -0
- package/migrations/20260628000006_agent_board_fleet_read_models.sql +170 -0
- package/migrations/20260629000100_agent_board_fleet_registry_repair.sql +411 -0
- package/migrations/20260629000101_agent_board_fleet_policy_refresh.sql +509 -0
- package/migrations/20260629000102_agent_board_fleet_read_models_refresh.sql +170 -0
- package/migrations/20260630000100_agent_board_harness_kind_open_vocab.sql +15 -0
- package/migrations/20260710000000_agent_board_authbound_boundary.sql +155 -0
- package/migrations/20260710000100_agent_board_schema_version_rpc.sql +14 -0
- package/migrations/20260710000400_agent_board_nonfleet_identity.sql +87 -0
- package/migrations/20260710000401_agent_board_workload_providers.sql +39 -0
- package/migrations/20260711000000_agent_board_provision_system_fail_closed.sql +242 -0
- package/migrations/20260711000100_canary_signed_fleet_enforcement.sql +234 -0
- package/migrations/20260712000000_agent_board_bundle_endpoint_compat.sql +97 -0
- package/migrations/20260713000000_agent_board_rls_reassert_board_scoping.sql +90 -0
- package/package.json +42 -0
- package/provenance.json +580 -0
- package/schema-manifest.json +458 -0
- package/src/check.js +23 -0
- package/src/index.js +50 -0
- package/src/materialize.js +73 -0
- package/src/plan.js +44 -0
- package/src/tooling.test.mjs +97 -0
- package/tests/agent_board_addressing.test.sql +166 -0
- package/tests/agent_board_auth_rls.test.sql +243 -0
- package/tests/agent_board_auth_rls_id_qualification.test.sql +225 -0
- package/tests/agent_board_auth_rpcs.test.sql +311 -0
- package/tests/agent_board_auth_schema.test.sql +411 -0
- package/tests/agent_board_authbound_boundary.test.sql +148 -0
- package/tests/agent_board_boardopt.test.sql +170 -0
- package/tests/agent_board_bundle_endpoint_compat.test.sql +49 -0
- package/tests/agent_board_callback_runtime.test.sql +425 -0
- package/tests/agent_board_callbackcap.test.sql +222 -0
- package/tests/agent_board_canary_signed_fleet_enforcement.test.sql +60 -0
- package/tests/agent_board_dblint_rpcs.test.sql +247 -0
- package/tests/agent_board_fleet_policy.test.sql +370 -0
- package/tests/agent_board_fleet_read_models.test.sql +158 -0
- package/tests/agent_board_fleet_registry.test.sql +149 -0
- package/tests/agent_board_inbox_reads.test.sql +471 -0
- package/tests/agent_board_inbox_rpcs.test.sql +452 -0
- package/tests/agent_board_inbox_schema.test.sql +355 -0
- package/tests/agent_board_nonfleet_identity.test.sql +26 -0
- package/tests/agent_board_rls_reassert_board_scoping.test.sql +39 -0
- package/tests/agent_board_schema_version.test.sql +24 -0
- package/tests/agent_board_schema_version_rpc.test.sql +40 -0
- package/tests/agent_board_signature_rls_reads.test.sql +133 -0
- package/tests/agent_board_signed_write_gateway.test.sql +219 -0
- package/tests/agent_board_signing_proof_rpcs.test.sql +143 -0
- package/tests/agent_board_signing_store.test.sql +183 -0
- package/tests/agent_board_smoke.test.sql +12 -0
- package/tests/agent_board_v1_invariants.test.sql +298 -0
- package/tests/agent_board_v2_invariants.test.sql +753 -0
- package/tests/agent_board_workload_providers.test.sql +15 -0
- package/tests/fixtures/adopter-base.sql +19 -0
- package/tests/fixtures/operator-hardening.sql +27 -0
- package/tests/fixtures/test-prereqs.sql +84 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
begin;
|
|
2
|
+
|
|
3
|
+
select plan(19);
|
|
4
|
+
|
|
5
|
+
select has_function(
|
|
6
|
+
'agent_board',
|
|
7
|
+
'send_direct_message',
|
|
8
|
+
array['uuid', 'uuid', 'uuid', 'text', 'text', 'text', 'text', 'text', 'jsonb'],
|
|
9
|
+
'send_direct_message rpc exists'
|
|
10
|
+
);
|
|
11
|
+
select has_function(
|
|
12
|
+
'agent_board',
|
|
13
|
+
'send_multicast_message',
|
|
14
|
+
array['uuid', 'uuid', 'uuid[]', 'text', 'text', 'text', 'text', 'text', 'jsonb'],
|
|
15
|
+
'send_multicast_message rpc exists'
|
|
16
|
+
);
|
|
17
|
+
select has_function(
|
|
18
|
+
'agent_board',
|
|
19
|
+
'post_board_message',
|
|
20
|
+
array['uuid', 'uuid', 'uuid', 'text', 'text', 'text', 'text', 'text', 'jsonb'],
|
|
21
|
+
'post_board_message rpc exists'
|
|
22
|
+
);
|
|
23
|
+
select has_function(
|
|
24
|
+
'agent_board',
|
|
25
|
+
'create_tasking_delivery',
|
|
26
|
+
array['uuid', 'uuid', 'text', 'text', 'uuid[]', 'uuid', 'text', 'text', 'text', 'jsonb'],
|
|
27
|
+
'create_tasking_delivery rpc exists'
|
|
28
|
+
);
|
|
29
|
+
select has_function(
|
|
30
|
+
'agent_board',
|
|
31
|
+
'create_board',
|
|
32
|
+
array['uuid', 'text', 'text', 'text', 'jsonb', 'text'],
|
|
33
|
+
'create_board rpc exists'
|
|
34
|
+
);
|
|
35
|
+
select has_function(
|
|
36
|
+
'agent_board',
|
|
37
|
+
'join_board',
|
|
38
|
+
array['uuid', 'uuid', 'text', 'uuid', 'jsonb'],
|
|
39
|
+
'join_board rpc exists'
|
|
40
|
+
);
|
|
41
|
+
select has_function(
|
|
42
|
+
'agent_board',
|
|
43
|
+
'leave_board',
|
|
44
|
+
array['uuid', 'uuid', 'jsonb'],
|
|
45
|
+
'leave_board rpc exists'
|
|
46
|
+
);
|
|
47
|
+
select has_function(
|
|
48
|
+
'agent_board',
|
|
49
|
+
'update_board_membership',
|
|
50
|
+
array['uuid', 'uuid', 'text', 'jsonb'],
|
|
51
|
+
'update_board_membership rpc exists'
|
|
52
|
+
);
|
|
53
|
+
select has_function(
|
|
54
|
+
'agent_board',
|
|
55
|
+
'update_inbox_item_state',
|
|
56
|
+
array['uuid', 'uuid', 'text', 'jsonb'],
|
|
57
|
+
'update_inbox_item_state rpc exists'
|
|
58
|
+
);
|
|
59
|
+
select has_function(
|
|
60
|
+
'agent_board',
|
|
61
|
+
'register_callback_endpoint',
|
|
62
|
+
array['uuid', 'text', 'jsonb'],
|
|
63
|
+
'register_callback_endpoint rpc exists'
|
|
64
|
+
);
|
|
65
|
+
select has_function(
|
|
66
|
+
'agent_board',
|
|
67
|
+
'verify_callback_endpoint',
|
|
68
|
+
array['uuid', 'uuid', 'jsonb'],
|
|
69
|
+
'verify_callback_endpoint rpc exists'
|
|
70
|
+
);
|
|
71
|
+
select has_function(
|
|
72
|
+
'agent_board',
|
|
73
|
+
'disable_callback_endpoint',
|
|
74
|
+
array['uuid', 'uuid', 'text', 'jsonb'],
|
|
75
|
+
'disable_callback_endpoint rpc exists'
|
|
76
|
+
);
|
|
77
|
+
select has_function(
|
|
78
|
+
'agent_board',
|
|
79
|
+
'rotate_callback_signing_key',
|
|
80
|
+
array['uuid', 'uuid', 'jsonb'],
|
|
81
|
+
'rotate_callback_signing_key rpc exists'
|
|
82
|
+
);
|
|
83
|
+
select has_function(
|
|
84
|
+
'agent_board',
|
|
85
|
+
'delete_callback_endpoint',
|
|
86
|
+
array['uuid', 'uuid'],
|
|
87
|
+
'delete_callback_endpoint rpc exists'
|
|
88
|
+
);
|
|
89
|
+
select has_function(
|
|
90
|
+
'agent_board',
|
|
91
|
+
'subscribe_callback_endpoint',
|
|
92
|
+
array['uuid', 'uuid', 'text', 'text', 'uuid', 'jsonb'],
|
|
93
|
+
'subscribe_callback_endpoint rpc exists'
|
|
94
|
+
);
|
|
95
|
+
select has_function(
|
|
96
|
+
'agent_board',
|
|
97
|
+
'unsubscribe_callback_endpoint',
|
|
98
|
+
array['uuid', 'uuid', 'text', 'text', 'uuid', 'jsonb'],
|
|
99
|
+
'unsubscribe_callback_endpoint rpc exists'
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
select ok(
|
|
103
|
+
(
|
|
104
|
+
select count(distinct routine_name) = 16
|
|
105
|
+
from information_schema.routine_privileges
|
|
106
|
+
where specific_schema = 'agent_board'
|
|
107
|
+
and routine_name in (
|
|
108
|
+
'send_direct_message',
|
|
109
|
+
'send_multicast_message',
|
|
110
|
+
'post_board_message',
|
|
111
|
+
'create_tasking_delivery',
|
|
112
|
+
'create_board',
|
|
113
|
+
'join_board',
|
|
114
|
+
'leave_board',
|
|
115
|
+
'update_board_membership',
|
|
116
|
+
'update_inbox_item_state',
|
|
117
|
+
'register_callback_endpoint',
|
|
118
|
+
'verify_callback_endpoint',
|
|
119
|
+
'disable_callback_endpoint',
|
|
120
|
+
'rotate_callback_signing_key',
|
|
121
|
+
'delete_callback_endpoint',
|
|
122
|
+
'subscribe_callback_endpoint',
|
|
123
|
+
'unsubscribe_callback_endpoint'
|
|
124
|
+
)
|
|
125
|
+
and grantee = 'service_role'
|
|
126
|
+
and privilege_type = 'EXECUTE'
|
|
127
|
+
),
|
|
128
|
+
'service_role can execute the public inbox rpc surface'
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
select ok(
|
|
132
|
+
(
|
|
133
|
+
select count(distinct routine_name) = 12
|
|
134
|
+
from information_schema.routine_privileges
|
|
135
|
+
where specific_schema = 'agent_board'
|
|
136
|
+
and routine_name in (
|
|
137
|
+
'send_direct_message',
|
|
138
|
+
'send_multicast_message',
|
|
139
|
+
'post_board_message',
|
|
140
|
+
'create_tasking_delivery',
|
|
141
|
+
'create_board',
|
|
142
|
+
'join_board',
|
|
143
|
+
'leave_board',
|
|
144
|
+
'update_board_membership',
|
|
145
|
+
'update_inbox_item_state',
|
|
146
|
+
'register_callback_endpoint',
|
|
147
|
+
'verify_callback_endpoint',
|
|
148
|
+
'disable_callback_endpoint',
|
|
149
|
+
'rotate_callback_signing_key',
|
|
150
|
+
'delete_callback_endpoint',
|
|
151
|
+
'subscribe_callback_endpoint',
|
|
152
|
+
'unsubscribe_callback_endpoint'
|
|
153
|
+
)
|
|
154
|
+
and grantee = 'authenticated'
|
|
155
|
+
and privilege_type = 'EXECUTE'
|
|
156
|
+
)
|
|
157
|
+
and not has_function_privilege('authenticated', 'agent_board.send_direct_message(uuid,uuid,uuid,text,text,text,text,text,jsonb)', 'EXECUTE')
|
|
158
|
+
and not has_function_privilege('authenticated', 'agent_board.send_multicast_message(uuid,uuid,uuid[],text,text,text,text,text,jsonb)', 'EXECUTE')
|
|
159
|
+
and not has_function_privilege('authenticated', 'agent_board.post_board_message(uuid,uuid,uuid,text,text,text,text,text,jsonb)', 'EXECUTE')
|
|
160
|
+
and not has_function_privilege('authenticated', 'agent_board.create_tasking_delivery(uuid,uuid,text,text,uuid[],uuid,text,text,text,jsonb)', 'EXECUTE'),
|
|
161
|
+
'authenticated keeps non-delivery inbox RPCs while signed delivery RPC overloads stay gateway-only'
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
select ok(
|
|
165
|
+
(
|
|
166
|
+
select count(*) = 0
|
|
167
|
+
from information_schema.routine_privileges
|
|
168
|
+
where specific_schema = 'agent_board'
|
|
169
|
+
and routine_name in (
|
|
170
|
+
'send_direct_message',
|
|
171
|
+
'send_multicast_message',
|
|
172
|
+
'post_board_message',
|
|
173
|
+
'create_tasking_delivery',
|
|
174
|
+
'create_board',
|
|
175
|
+
'join_board',
|
|
176
|
+
'leave_board',
|
|
177
|
+
'update_board_membership',
|
|
178
|
+
'update_inbox_item_state',
|
|
179
|
+
'register_callback_endpoint',
|
|
180
|
+
'verify_callback_endpoint',
|
|
181
|
+
'disable_callback_endpoint',
|
|
182
|
+
'rotate_callback_signing_key',
|
|
183
|
+
'delete_callback_endpoint',
|
|
184
|
+
'subscribe_callback_endpoint',
|
|
185
|
+
'unsubscribe_callback_endpoint'
|
|
186
|
+
)
|
|
187
|
+
and grantee in ('PUBLIC', 'anon')
|
|
188
|
+
and privilege_type = 'EXECUTE'
|
|
189
|
+
),
|
|
190
|
+
'public and anon have no execute grant on the inbox rpc surface'
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
do $$
|
|
194
|
+
declare
|
|
195
|
+
v_sender uuid := gen_random_uuid();
|
|
196
|
+
v_direct_recipient uuid := gen_random_uuid();
|
|
197
|
+
v_multicast_recipient uuid := gen_random_uuid();
|
|
198
|
+
v_board_member uuid := gen_random_uuid();
|
|
199
|
+
v_left_member uuid := gen_random_uuid();
|
|
200
|
+
v_outsider uuid := gen_random_uuid();
|
|
201
|
+
v_thread uuid := gen_random_uuid();
|
|
202
|
+
v_board uuid;
|
|
203
|
+
v_direct_endpoint uuid;
|
|
204
|
+
v_board_endpoint uuid;
|
|
205
|
+
v_outsider_endpoint uuid;
|
|
206
|
+
v_direct_inbox uuid;
|
|
207
|
+
v_direct_message uuid;
|
|
208
|
+
v_board_message uuid;
|
|
209
|
+
v_task uuid;
|
|
210
|
+
v_result record;
|
|
211
|
+
begin
|
|
212
|
+
insert into agent_board.agents(id, agent_type, handle, display_name)
|
|
213
|
+
values
|
|
214
|
+
(v_sender, 'agent', 'test_inboxrpc_sender', 'Inbox RPC Sender'),
|
|
215
|
+
(v_direct_recipient, 'agent', 'test_inboxrpc_direct', 'Inbox RPC Direct'),
|
|
216
|
+
(v_multicast_recipient, 'agent', 'test_inboxrpc_multi', 'Inbox RPC Multi'),
|
|
217
|
+
(v_board_member, 'agent', 'test_inboxrpc_board', 'Inbox RPC Board'),
|
|
218
|
+
(v_left_member, 'agent', 'test_inboxrpc_left', 'Inbox RPC Left'),
|
|
219
|
+
(v_outsider, 'agent', 'test_inboxrpc_outsider', 'Inbox RPC Outsider');
|
|
220
|
+
|
|
221
|
+
insert into agent_board.threads(id, thread_type, created_by_agent_id, subject)
|
|
222
|
+
values (v_thread, 'coordination', v_sender, 'Inbox RPC Test Thread');
|
|
223
|
+
|
|
224
|
+
select * into v_result
|
|
225
|
+
from agent_board.create_board(
|
|
226
|
+
v_sender,
|
|
227
|
+
'test-inboxrpc-board',
|
|
228
|
+
'Inbox RPC Board',
|
|
229
|
+
'board for inbox rpc tests',
|
|
230
|
+
'{}'::jsonb,
|
|
231
|
+
'private'
|
|
232
|
+
);
|
|
233
|
+
v_board := v_result.board_id;
|
|
234
|
+
perform ok(v_board is not null, 'create_board returns a board id');
|
|
235
|
+
|
|
236
|
+
select * into v_result
|
|
237
|
+
from agent_board.join_board(v_board, v_board_member, 'subscribed', v_sender, '{}'::jsonb);
|
|
238
|
+
perform is(v_result.membership_state, 'subscribed', 'join_board supports subscribed state');
|
|
239
|
+
|
|
240
|
+
select * into v_result
|
|
241
|
+
from agent_board.join_board(v_board, v_direct_recipient, 'joined', v_sender, '{}'::jsonb);
|
|
242
|
+
perform is(v_result.membership_state, 'joined', 'join_board supports joined state');
|
|
243
|
+
|
|
244
|
+
select * into v_result
|
|
245
|
+
from agent_board.join_board(v_board, v_left_member, 'joined', v_sender, '{}'::jsonb);
|
|
246
|
+
select * into v_result
|
|
247
|
+
from agent_board.leave_board(v_board, v_left_member, '{}'::jsonb);
|
|
248
|
+
perform is(v_result.membership_state, 'left', 'leave_board marks memberships as left');
|
|
249
|
+
|
|
250
|
+
select * into v_result
|
|
251
|
+
from agent_board.register_callback_endpoint(v_direct_recipient, 'https://example.test/direct', '{}'::jsonb);
|
|
252
|
+
v_direct_endpoint := v_result.endpoint_id;
|
|
253
|
+
perform is(v_result.endpoint_status, 'pending_verification', 'register_callback_endpoint starts pending verification');
|
|
254
|
+
|
|
255
|
+
select * into v_result
|
|
256
|
+
from agent_board.verify_callback_endpoint(v_direct_endpoint, v_direct_recipient, '{"controlProofRef":"inbox-rpcs/direct"}'::jsonb);
|
|
257
|
+
perform is(v_result.endpoint_status, 'verified', 'verify_callback_endpoint marks endpoint verified');
|
|
258
|
+
|
|
259
|
+
select * into v_result
|
|
260
|
+
from agent_board.subscribe_callback_endpoint(v_direct_endpoint, v_direct_recipient, 'own_inbox', 'inbox.item.delivered', null, '{}'::jsonb);
|
|
261
|
+
perform is(v_result.subscription_status, 'active', 'own-inbox callback subscription activates');
|
|
262
|
+
|
|
263
|
+
select * into v_result
|
|
264
|
+
from agent_board.subscribe_callback_endpoint(v_direct_endpoint, v_direct_recipient, 'own_inbox', 'inbox.item.updated', null, '{}'::jsonb);
|
|
265
|
+
perform is(v_result.subscription_status, 'active', 'own-inbox update subscription activates');
|
|
266
|
+
|
|
267
|
+
select * into v_result
|
|
268
|
+
from agent_board.register_callback_endpoint(v_board_member, 'https://example.test/board', '{}'::jsonb);
|
|
269
|
+
v_board_endpoint := v_result.endpoint_id;
|
|
270
|
+
select * into v_result
|
|
271
|
+
from agent_board.verify_callback_endpoint(v_board_endpoint, v_board_member, '{"controlProofRef":"inbox-rpcs/board"}'::jsonb);
|
|
272
|
+
select * into v_result
|
|
273
|
+
from agent_board.subscribe_callback_endpoint(v_board_endpoint, v_board_member, 'board', 'board.post.delivered', v_board, '{}'::jsonb);
|
|
274
|
+
perform is(v_result.subscription_status, 'active', 'board callback subscription activates for active member');
|
|
275
|
+
|
|
276
|
+
select * into v_result
|
|
277
|
+
from agent_board.register_callback_endpoint(v_outsider, 'https://example.test/outsider', '{}'::jsonb);
|
|
278
|
+
v_outsider_endpoint := v_result.endpoint_id;
|
|
279
|
+
|
|
280
|
+
begin
|
|
281
|
+
perform agent_board.subscribe_callback_endpoint(v_outsider_endpoint, v_outsider, 'board', 'board.post.delivered', v_board, '{}'::jsonb);
|
|
282
|
+
perform ok(false, 'board subscription without membership should fail');
|
|
283
|
+
exception
|
|
284
|
+
when sqlstate 'P0002' then
|
|
285
|
+
perform ok(true, 'board subscription requires active board membership');
|
|
286
|
+
end;
|
|
287
|
+
|
|
288
|
+
select * into v_result
|
|
289
|
+
from agent_board.send_direct_message(
|
|
290
|
+
v_thread,
|
|
291
|
+
v_sender,
|
|
292
|
+
v_direct_recipient,
|
|
293
|
+
'Direct subject',
|
|
294
|
+
'Direct body for idempotent delivery',
|
|
295
|
+
'comment',
|
|
296
|
+
'high',
|
|
297
|
+
'direct-key',
|
|
298
|
+
'{}'::jsonb
|
|
299
|
+
);
|
|
300
|
+
v_direct_message := v_result.message_id;
|
|
301
|
+
v_direct_inbox := v_result.inbox_item_id;
|
|
302
|
+
perform is(v_result.callback_outbox_count, 1, 'direct delivery enqueues one own-inbox callback');
|
|
303
|
+
perform is(
|
|
304
|
+
(select count(*)::integer from agent_board.delivery_recipients where source_message_id = v_direct_message),
|
|
305
|
+
1,
|
|
306
|
+
'direct delivery writes one recipient row'
|
|
307
|
+
);
|
|
308
|
+
perform is(
|
|
309
|
+
(select count(*)::integer from agent_board.inbox_items where source_message_id = v_direct_message),
|
|
310
|
+
1,
|
|
311
|
+
'direct delivery writes one inbox row'
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
select * into v_result
|
|
315
|
+
from agent_board.send_direct_message(
|
|
316
|
+
v_thread,
|
|
317
|
+
v_sender,
|
|
318
|
+
v_direct_recipient,
|
|
319
|
+
'Direct subject',
|
|
320
|
+
'Direct body for idempotent delivery',
|
|
321
|
+
'comment',
|
|
322
|
+
'high',
|
|
323
|
+
'direct-key',
|
|
324
|
+
'{}'::jsonb
|
|
325
|
+
);
|
|
326
|
+
perform is(v_result.message_id, v_direct_message, 'direct idempotency reuses canonical message');
|
|
327
|
+
perform is(
|
|
328
|
+
(select count(*)::integer from agent_board.callback_outbox_events where source_message_id = v_direct_message and event_category = 'inbox.item.delivered'),
|
|
329
|
+
1,
|
|
330
|
+
'direct idempotency does not duplicate delivered callback events'
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
select * into v_result
|
|
334
|
+
from agent_board.update_inbox_item_state(v_direct_inbox, v_direct_recipient, 'read', '{}'::jsonb);
|
|
335
|
+
perform is(v_result.action_state, 'read', 'update_inbox_item_state changes action state');
|
|
336
|
+
perform is(
|
|
337
|
+
(select count(*)::integer from agent_board.callback_outbox_events where inbox_item_id = v_direct_inbox and event_category = 'inbox.item.updated'),
|
|
338
|
+
1,
|
|
339
|
+
'updating inbox state enqueues one inbox.item.updated callback'
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
select * into v_result
|
|
343
|
+
from agent_board.send_multicast_message(
|
|
344
|
+
v_thread,
|
|
345
|
+
v_sender,
|
|
346
|
+
array[v_direct_recipient, v_multicast_recipient, v_direct_recipient]::uuid[],
|
|
347
|
+
'Multicast subject',
|
|
348
|
+
'Multicast body for duplicate suppression',
|
|
349
|
+
'comment',
|
|
350
|
+
'medium',
|
|
351
|
+
'multicast-key',
|
|
352
|
+
'{}'::jsonb
|
|
353
|
+
);
|
|
354
|
+
perform is(v_result.delivered_recipient_count, 2, 'multicast collapses duplicate recipients');
|
|
355
|
+
perform is(
|
|
356
|
+
(select count(*)::integer from agent_board.delivery_recipients where source_message_id = v_result.message_id),
|
|
357
|
+
2,
|
|
358
|
+
'multicast writes one recipient row per unique recipient'
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
select * into v_result
|
|
362
|
+
from agent_board.post_board_message(
|
|
363
|
+
v_thread,
|
|
364
|
+
v_sender,
|
|
365
|
+
v_board,
|
|
366
|
+
'Board subject',
|
|
367
|
+
'Board body for subscribed members',
|
|
368
|
+
'comment',
|
|
369
|
+
'urgent',
|
|
370
|
+
'board-key',
|
|
371
|
+
'{}'::jsonb
|
|
372
|
+
);
|
|
373
|
+
v_board_message := v_result.message_id;
|
|
374
|
+
perform is(v_result.delivered_recipient_count, 2, 'board delivery reaches joined and subscribed members only');
|
|
375
|
+
perform is(
|
|
376
|
+
(select count(*)::integer from agent_board.delivery_recipients where source_message_id = v_board_message and recipient_agent_id = v_left_member),
|
|
377
|
+
0,
|
|
378
|
+
'left board members do not receive board delivery'
|
|
379
|
+
);
|
|
380
|
+
perform ok(
|
|
381
|
+
exists(
|
|
382
|
+
select 1
|
|
383
|
+
from agent_board.callback_outbox_events
|
|
384
|
+
where source_message_id = v_board_message
|
|
385
|
+
and event_category = 'board.post.delivered'
|
|
386
|
+
and recipient_agent_id = v_board_member
|
|
387
|
+
),
|
|
388
|
+
'board.post.delivered callback events are queued for board subscribers'
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
select * into v_result
|
|
392
|
+
from agent_board.create_tasking_delivery(
|
|
393
|
+
v_thread,
|
|
394
|
+
v_sender,
|
|
395
|
+
'Tasking title',
|
|
396
|
+
'Tasking details for duplicate suppression',
|
|
397
|
+
array[v_direct_recipient]::uuid[],
|
|
398
|
+
v_board,
|
|
399
|
+
'high',
|
|
400
|
+
'distributed',
|
|
401
|
+
'task-key',
|
|
402
|
+
'{}'::jsonb
|
|
403
|
+
);
|
|
404
|
+
v_task := v_result.task_id;
|
|
405
|
+
perform is(v_result.delivered_recipient_count, 3, 'tasking counts explicit and board fan-out attempts');
|
|
406
|
+
perform is(
|
|
407
|
+
(select count(*)::integer from agent_board.delivery_recipients where source_task_id = v_task),
|
|
408
|
+
2,
|
|
409
|
+
'tasking suppresses duplicate recipient rows across explicit and board fan-out'
|
|
410
|
+
);
|
|
411
|
+
perform is(
|
|
412
|
+
(select count(*)::integer from agent_board.inbox_items where source_task_id = v_task),
|
|
413
|
+
2,
|
|
414
|
+
'tasking writes one inbox row per unique recipient'
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
select * into v_result
|
|
418
|
+
from agent_board.rotate_callback_signing_key(v_direct_endpoint, v_direct_recipient, '{}'::jsonb);
|
|
419
|
+
perform is(v_result.signing_key_version, 2, 'rotate_callback_signing_key bumps signing key version');
|
|
420
|
+
perform is(v_result.endpoint_status, 'pending_verification', 'signing key rotation returns endpoint to pending verification');
|
|
421
|
+
|
|
422
|
+
select * into v_result
|
|
423
|
+
from agent_board.disable_callback_endpoint(v_board_endpoint, v_board_member, 'test disable', '{}'::jsonb);
|
|
424
|
+
perform is(v_result.endpoint_status, 'disabled', 'disable_callback_endpoint marks endpoint disabled');
|
|
425
|
+
perform ok(
|
|
426
|
+
exists(
|
|
427
|
+
select 1
|
|
428
|
+
from agent_board.callback_subscriptions
|
|
429
|
+
where endpoint_id = v_board_endpoint
|
|
430
|
+
and subscription_status = 'disabled'
|
|
431
|
+
),
|
|
432
|
+
'disabling an endpoint disables attached subscriptions'
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
select * into v_result
|
|
436
|
+
from agent_board.unsubscribe_callback_endpoint(v_direct_endpoint, v_direct_recipient, 'own_inbox', 'inbox.item.updated', null, '{}'::jsonb);
|
|
437
|
+
perform is(v_result.subscription_status, 'disabled', 'unsubscribe_callback_endpoint disables an active subscription');
|
|
438
|
+
|
|
439
|
+
select * into v_result
|
|
440
|
+
from agent_board.delete_callback_endpoint(v_outsider_endpoint, v_outsider);
|
|
441
|
+
perform ok(v_result.deleted, 'delete_callback_endpoint removes owned endpoints');
|
|
442
|
+
|
|
443
|
+
perform is(
|
|
444
|
+
(select count(*)::integer from agent_board.callback_delivery_attempts),
|
|
445
|
+
0,
|
|
446
|
+
'callback management remains metadata-only before runtime delivery exists'
|
|
447
|
+
);
|
|
448
|
+
end;
|
|
449
|
+
$$;
|
|
450
|
+
|
|
451
|
+
select * from finish();
|
|
452
|
+
rollback;
|