@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,222 @@
|
|
|
1
|
+
create extension if not exists pgtap with schema extensions;
|
|
2
|
+
set search_path = extensions, public, agent_board;
|
|
3
|
+
|
|
4
|
+
begin;
|
|
5
|
+
|
|
6
|
+
select plan(8);
|
|
7
|
+
|
|
8
|
+
create temp table _callbackcap_fixture (
|
|
9
|
+
agent_id uuid,
|
|
10
|
+
thread_id uuid,
|
|
11
|
+
board_id uuid,
|
|
12
|
+
endpoint_id uuid
|
|
13
|
+
) on commit drop;
|
|
14
|
+
|
|
15
|
+
grant all on table _callbackcap_fixture to authenticated, service_role;
|
|
16
|
+
|
|
17
|
+
do $$
|
|
18
|
+
declare
|
|
19
|
+
v_agent uuid := gen_random_uuid();
|
|
20
|
+
v_thread uuid := gen_random_uuid();
|
|
21
|
+
v_board uuid;
|
|
22
|
+
v_endpoint record;
|
|
23
|
+
begin
|
|
24
|
+
insert into agent_board.agents(id, agent_type, handle, display_name)
|
|
25
|
+
values (v_agent, 'agent', 'callbackcap-agent-' || substr(v_agent::text, 1, 8), 'CALLBACKCAP Agent');
|
|
26
|
+
|
|
27
|
+
insert into agent_board.threads(id, thread_type, created_by_agent_id, subject)
|
|
28
|
+
values (v_thread, 'coordination', v_agent, 'CALLBACKCAP thread');
|
|
29
|
+
|
|
30
|
+
select board_id into v_board
|
|
31
|
+
from agent_board.create_board(
|
|
32
|
+
v_agent,
|
|
33
|
+
'callbackcap-board-' || substr(v_agent::text, 1, 8),
|
|
34
|
+
'CALLBACKCAP Board',
|
|
35
|
+
'callback capability regression',
|
|
36
|
+
'{}'::jsonb,
|
|
37
|
+
'open'
|
|
38
|
+
);
|
|
39
|
+
perform agent_board.join_board(v_board, v_agent, 'subscribed', v_agent, '{}'::jsonb);
|
|
40
|
+
|
|
41
|
+
select * into v_endpoint
|
|
42
|
+
from agent_board.register_callback_endpoint(
|
|
43
|
+
v_agent,
|
|
44
|
+
'https://callbackcap.example.test/hook',
|
|
45
|
+
'{"purpose":"callbackcap"}'::jsonb
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
insert into _callbackcap_fixture(agent_id, thread_id, board_id, endpoint_id)
|
|
49
|
+
values (v_agent, v_thread, v_board, v_endpoint.endpoint_id);
|
|
50
|
+
end
|
|
51
|
+
$$;
|
|
52
|
+
|
|
53
|
+
do $$
|
|
54
|
+
declare
|
|
55
|
+
v_fixture record;
|
|
56
|
+
begin
|
|
57
|
+
select * into v_fixture from _callbackcap_fixture;
|
|
58
|
+
begin
|
|
59
|
+
perform *
|
|
60
|
+
from agent_board.verify_callback_endpoint(v_fixture.endpoint_id, v_fixture.agent_id, '{}'::jsonb);
|
|
61
|
+
raise exception 'verify_callback_endpoint unexpectedly accepted missing controlProofRef';
|
|
62
|
+
exception
|
|
63
|
+
when sqlstate '22023' then null;
|
|
64
|
+
end;
|
|
65
|
+
end
|
|
66
|
+
$$;
|
|
67
|
+
select pass('verify_callback_endpoint requires bounded controlProofRef metadata');
|
|
68
|
+
|
|
69
|
+
do $$
|
|
70
|
+
declare
|
|
71
|
+
v_fixture record;
|
|
72
|
+
v_verified record;
|
|
73
|
+
v_metadata jsonb;
|
|
74
|
+
begin
|
|
75
|
+
select * into v_fixture from _callbackcap_fixture;
|
|
76
|
+
select * into v_verified
|
|
77
|
+
from agent_board.verify_callback_endpoint(
|
|
78
|
+
v_fixture.endpoint_id,
|
|
79
|
+
v_fixture.agent_id,
|
|
80
|
+
'{"controlProofRef":"callbackcap/operator-note/1"}'::jsonb
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if v_verified.endpoint_status <> 'verified' then
|
|
84
|
+
raise exception 'endpoint did not verify';
|
|
85
|
+
end if;
|
|
86
|
+
|
|
87
|
+
select metadata into v_metadata
|
|
88
|
+
from agent_board.callback_endpoints
|
|
89
|
+
where id = v_fixture.endpoint_id;
|
|
90
|
+
|
|
91
|
+
if v_metadata ->> 'verificationMethod' <> 'administrative_enablement'
|
|
92
|
+
or v_metadata ->> 'controlProofRef' <> 'callbackcap/operator-note/1'
|
|
93
|
+
or v_metadata ? 'signingSecret' then
|
|
94
|
+
raise exception 'verification metadata was not bounded and proof-referenced: %', v_metadata;
|
|
95
|
+
end if;
|
|
96
|
+
end
|
|
97
|
+
$$;
|
|
98
|
+
select pass('verify_callback_endpoint records administrative enablement plus control proof metadata');
|
|
99
|
+
|
|
100
|
+
do $$
|
|
101
|
+
declare
|
|
102
|
+
v_fixture record;
|
|
103
|
+
begin
|
|
104
|
+
select * into v_fixture from _callbackcap_fixture;
|
|
105
|
+
perform *
|
|
106
|
+
from agent_board.subscribe_callback_endpoint(
|
|
107
|
+
v_fixture.endpoint_id,
|
|
108
|
+
v_fixture.agent_id,
|
|
109
|
+
'board',
|
|
110
|
+
'board.post.delivered',
|
|
111
|
+
v_fixture.board_id,
|
|
112
|
+
'{}'::jsonb
|
|
113
|
+
);
|
|
114
|
+
perform *
|
|
115
|
+
from agent_board.subscribe_callback_endpoint(
|
|
116
|
+
v_fixture.endpoint_id,
|
|
117
|
+
v_fixture.agent_id,
|
|
118
|
+
'board',
|
|
119
|
+
'board.post.updated',
|
|
120
|
+
v_fixture.board_id,
|
|
121
|
+
'{}'::jsonb
|
|
122
|
+
);
|
|
123
|
+
end
|
|
124
|
+
$$;
|
|
125
|
+
select pass('board callback subscriptions accept delivered and updated categories with boardId');
|
|
126
|
+
|
|
127
|
+
do $$
|
|
128
|
+
declare
|
|
129
|
+
v_fixture record;
|
|
130
|
+
begin
|
|
131
|
+
select * into v_fixture from _callbackcap_fixture;
|
|
132
|
+
begin
|
|
133
|
+
perform *
|
|
134
|
+
from agent_board.subscribe_callback_endpoint(
|
|
135
|
+
v_fixture.endpoint_id,
|
|
136
|
+
v_fixture.agent_id,
|
|
137
|
+
'board',
|
|
138
|
+
'board.post.delivered',
|
|
139
|
+
null,
|
|
140
|
+
'{}'::jsonb
|
|
141
|
+
);
|
|
142
|
+
raise exception 'board callback subscription unexpectedly accepted missing boardId';
|
|
143
|
+
exception
|
|
144
|
+
when sqlstate '22023' then null;
|
|
145
|
+
end;
|
|
146
|
+
end
|
|
147
|
+
$$;
|
|
148
|
+
select pass('board callback subscriptions require boardId');
|
|
149
|
+
|
|
150
|
+
do $$
|
|
151
|
+
declare
|
|
152
|
+
v_fixture record;
|
|
153
|
+
begin
|
|
154
|
+
select * into v_fixture from _callbackcap_fixture;
|
|
155
|
+
begin
|
|
156
|
+
perform *
|
|
157
|
+
from agent_board.subscribe_callback_endpoint(
|
|
158
|
+
v_fixture.endpoint_id,
|
|
159
|
+
v_fixture.agent_id,
|
|
160
|
+
'own_inbox',
|
|
161
|
+
'board.post.delivered',
|
|
162
|
+
null,
|
|
163
|
+
'{}'::jsonb
|
|
164
|
+
);
|
|
165
|
+
raise exception 'own_inbox callback subscription unexpectedly accepted board category';
|
|
166
|
+
exception
|
|
167
|
+
when sqlstate '22023' then null;
|
|
168
|
+
end;
|
|
169
|
+
end
|
|
170
|
+
$$;
|
|
171
|
+
select pass('own_inbox callback subscriptions reject board categories');
|
|
172
|
+
|
|
173
|
+
do $$
|
|
174
|
+
declare
|
|
175
|
+
v_fixture record;
|
|
176
|
+
v_post record;
|
|
177
|
+
begin
|
|
178
|
+
select * into v_fixture from _callbackcap_fixture;
|
|
179
|
+
select * into v_post
|
|
180
|
+
from agent_board.post_board_message(
|
|
181
|
+
v_fixture.thread_id,
|
|
182
|
+
v_fixture.agent_id,
|
|
183
|
+
v_fixture.board_id,
|
|
184
|
+
'CALLBACKCAP board post',
|
|
185
|
+
'board callback outbox proof',
|
|
186
|
+
'comment',
|
|
187
|
+
'medium',
|
|
188
|
+
'callbackcap-board-post',
|
|
189
|
+
'{}'::jsonb
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
if coalesce(v_post.callback_outbox_count, 0) < 1 then
|
|
193
|
+
raise exception 'board post did not enqueue board callback outbox work';
|
|
194
|
+
end if;
|
|
195
|
+
end
|
|
196
|
+
$$;
|
|
197
|
+
select pass('board post delivery enqueues callback outbox work for board subscriptions');
|
|
198
|
+
|
|
199
|
+
select ok(
|
|
200
|
+
exists (
|
|
201
|
+
select 1
|
|
202
|
+
from agent_board.callback_outbox_events
|
|
203
|
+
where event_category = 'board.post.delivered'
|
|
204
|
+
and idempotency_key like 'board.post.delivered:%'
|
|
205
|
+
and board_id = (select board_id from _callbackcap_fixture)
|
|
206
|
+
),
|
|
207
|
+
'board callback outbox rows carry board category and idempotency key'
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
select ok(
|
|
211
|
+
not exists (
|
|
212
|
+
select 1
|
|
213
|
+
from agent_board.callback_endpoints
|
|
214
|
+
where id = (select endpoint_id from _callbackcap_fixture)
|
|
215
|
+
and metadata ? 'signingSecret'
|
|
216
|
+
),
|
|
217
|
+
'callback endpoint metadata does not expose signing secrets'
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
select finish();
|
|
221
|
+
|
|
222
|
+
rollback;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
create extension if not exists pgtap with schema extensions;
|
|
2
|
+
set search_path = extensions, public, agent_board;
|
|
3
|
+
|
|
4
|
+
begin;
|
|
5
|
+
|
|
6
|
+
select plan(8);
|
|
7
|
+
|
|
8
|
+
select has_function('agent_board', 'evaluate_signed_write_fleet_policy', array['text', 'jsonb', 'jsonb'], 'signed fleet policy evaluator exists');
|
|
9
|
+
select has_function('agent_board', 'signed_send_multicast_message', array['jsonb', 'jsonb'], 'signed multicast wrapper exists');
|
|
10
|
+
select has_function('agent_board', 'signed_create_tasking_delivery', array['jsonb', 'jsonb'], 'signed tasking wrapper exists');
|
|
11
|
+
|
|
12
|
+
select function_privs_are(
|
|
13
|
+
'agent_board',
|
|
14
|
+
'send_direct_message',
|
|
15
|
+
array['uuid','uuid','uuid','text','text','text','text','text','jsonb'],
|
|
16
|
+
'authenticated',
|
|
17
|
+
array[]::text[],
|
|
18
|
+
'authenticated cannot bypass direct signed gateway'
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
select function_privs_are(
|
|
22
|
+
'agent_board',
|
|
23
|
+
'send_multicast_message',
|
|
24
|
+
array['uuid','uuid','uuid[]','text','text','text','text','text','jsonb'],
|
|
25
|
+
'authenticated',
|
|
26
|
+
array[]::text[],
|
|
27
|
+
'authenticated cannot bypass multicast signed gateway'
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
select function_privs_are(
|
|
31
|
+
'agent_board',
|
|
32
|
+
'post_board_message',
|
|
33
|
+
array['uuid','uuid','uuid','text','text','text','text','text','jsonb'],
|
|
34
|
+
'authenticated',
|
|
35
|
+
array[]::text[],
|
|
36
|
+
'authenticated cannot bypass board signed gateway'
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
select function_privs_are(
|
|
40
|
+
'agent_board',
|
|
41
|
+
'create_tasking_delivery',
|
|
42
|
+
array['uuid','uuid','text','text','uuid[]','uuid','text','text','text','jsonb'],
|
|
43
|
+
'authenticated',
|
|
44
|
+
array[]::text[],
|
|
45
|
+
'authenticated cannot bypass tasking signed gateway'
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
select ok(
|
|
49
|
+
not exists (
|
|
50
|
+
select 1 from information_schema.routine_privileges
|
|
51
|
+
where routine_schema = 'agent_board'
|
|
52
|
+
and routine_name in ('evaluate_signed_write_fleet_policy', 'signed_send_multicast_message', 'signed_create_tasking_delivery')
|
|
53
|
+
and grantee in ('anon', 'authenticated')
|
|
54
|
+
),
|
|
55
|
+
'new enforcement functions remain service-role only'
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
select finish();
|
|
59
|
+
|
|
60
|
+
rollback;
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
create extension if not exists pgtap with schema extensions;
|
|
2
|
+
set search_path = extensions, public, agent_board;
|
|
3
|
+
|
|
4
|
+
begin;
|
|
5
|
+
|
|
6
|
+
select plan(10);
|
|
7
|
+
|
|
8
|
+
insert into agent_board.agents(id, agent_type, handle, display_name)
|
|
9
|
+
values
|
|
10
|
+
('00000000-0000-0000-0000-000000000101', 'agent', 'test_dblint_creator', 'DBLINT Creator'),
|
|
11
|
+
('00000000-0000-0000-0000-000000000102', 'agent', 'test_dblint_resolver', 'DBLINT Resolver'),
|
|
12
|
+
('00000000-0000-0000-0000-000000000103', 'agent', 'test_dblint_recipient_one', 'DBLINT Recipient One'),
|
|
13
|
+
('00000000-0000-0000-0000-000000000104', 'agent', 'test_dblint_recipient_two', 'DBLINT Recipient Two');
|
|
14
|
+
|
|
15
|
+
insert into agent_board.threads(id, thread_type, created_by_agent_id, subject)
|
|
16
|
+
values (
|
|
17
|
+
'00000000-0000-0000-0000-000000000201',
|
|
18
|
+
'coordination',
|
|
19
|
+
'00000000-0000-0000-0000-000000000101',
|
|
20
|
+
'DBLINT RPC coverage'
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
create temporary table dblint_primary_task on commit drop as
|
|
24
|
+
select *
|
|
25
|
+
from agent_board.create_task(
|
|
26
|
+
'00000000-0000-0000-0000-000000000201',
|
|
27
|
+
'00000000-0000-0000-0000-000000000101',
|
|
28
|
+
'Primary task',
|
|
29
|
+
'seed task for dblint coverage',
|
|
30
|
+
null,
|
|
31
|
+
null,
|
|
32
|
+
'medium',
|
|
33
|
+
'distributed',
|
|
34
|
+
'{}'::jsonb
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
create temporary table dblint_appended on commit drop as
|
|
38
|
+
select *
|
|
39
|
+
from agent_board.append_task_event(
|
|
40
|
+
(select task_id from dblint_primary_task),
|
|
41
|
+
'00000000-0000-0000-0000-000000000101',
|
|
42
|
+
'commented',
|
|
43
|
+
jsonb_build_object('note', 'second event')
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
select is(
|
|
47
|
+
(select event_sequence from dblint_appended),
|
|
48
|
+
2::bigint,
|
|
49
|
+
'_next_task_event_sequence advances through append_task_event'
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
create temporary table dblint_tasking on commit drop as
|
|
53
|
+
select *
|
|
54
|
+
from agent_board.create_tasking_delivery(
|
|
55
|
+
'00000000-0000-0000-0000-000000000201',
|
|
56
|
+
'00000000-0000-0000-0000-000000000101',
|
|
57
|
+
'Tasking delivery title',
|
|
58
|
+
'Tasking delivery details',
|
|
59
|
+
array[
|
|
60
|
+
'00000000-0000-0000-0000-000000000103'::uuid,
|
|
61
|
+
'00000000-0000-0000-0000-000000000103'::uuid,
|
|
62
|
+
'00000000-0000-0000-0000-000000000104'::uuid
|
|
63
|
+
],
|
|
64
|
+
null,
|
|
65
|
+
'high',
|
|
66
|
+
'distributed',
|
|
67
|
+
null,
|
|
68
|
+
'{}'::jsonb
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
select ok(
|
|
72
|
+
(
|
|
73
|
+
select td.created_event_id = te.id
|
|
74
|
+
from dblint_tasking td
|
|
75
|
+
join agent_board.task_events te
|
|
76
|
+
on te.task_id = td.task_id
|
|
77
|
+
and te.event_sequence = 1
|
|
78
|
+
),
|
|
79
|
+
'create_tasking_delivery reuses the first task event lookup'
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
select is(
|
|
83
|
+
(select delivered_recipient_count from dblint_tasking),
|
|
84
|
+
2,
|
|
85
|
+
'create_tasking_delivery suppresses duplicate explicit recipients'
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
create temporary table dblint_conflict on commit drop as
|
|
89
|
+
select *
|
|
90
|
+
from agent_board.raise_conflict(
|
|
91
|
+
'00000000-0000-0000-0000-000000000201',
|
|
92
|
+
'00000000-0000-0000-0000-000000000101',
|
|
93
|
+
'Need a conflict record',
|
|
94
|
+
'plan',
|
|
95
|
+
'high',
|
|
96
|
+
(select task_id from dblint_primary_task),
|
|
97
|
+
jsonb_build_object('seed', 'conflict')
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
create temporary table dblint_resolved_conflict on commit drop as
|
|
101
|
+
select *
|
|
102
|
+
from agent_board.resolve_conflict(
|
|
103
|
+
(select conflict_id from dblint_conflict),
|
|
104
|
+
'00000000-0000-0000-0000-000000000102',
|
|
105
|
+
jsonb_build_object('resolution', 'done')
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
select is(
|
|
109
|
+
(select status from dblint_resolved_conflict),
|
|
110
|
+
'resolved',
|
|
111
|
+
'resolve_conflict marks the conflict resolved'
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
select ok(
|
|
115
|
+
(
|
|
116
|
+
select c.details @> jsonb_build_object('seed', 'conflict', 'resolution', 'done')
|
|
117
|
+
from agent_board.conflicts c
|
|
118
|
+
where c.id = (select conflict_id from dblint_conflict)
|
|
119
|
+
),
|
|
120
|
+
'resolve_conflict merges detail payloads without ambiguity regressions'
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
create temporary table dblint_escalation on commit drop as
|
|
124
|
+
select *
|
|
125
|
+
from agent_board.raise_escalation(
|
|
126
|
+
'00000000-0000-0000-0000-000000000201',
|
|
127
|
+
'00000000-0000-0000-0000-000000000101',
|
|
128
|
+
'Need an escalation record',
|
|
129
|
+
'approval',
|
|
130
|
+
'high',
|
|
131
|
+
(select task_id from dblint_primary_task),
|
|
132
|
+
'00000000-0000-0000-0000-000000000102',
|
|
133
|
+
jsonb_build_object('seed', 'escalation')
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
create temporary table dblint_resolved_escalation on commit drop as
|
|
137
|
+
select *
|
|
138
|
+
from agent_board.resolve_escalation(
|
|
139
|
+
(select escalation_id from dblint_escalation),
|
|
140
|
+
'00000000-0000-0000-0000-000000000102',
|
|
141
|
+
jsonb_build_object('resolution', 'approved')
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
select is(
|
|
145
|
+
(select status from dblint_resolved_escalation),
|
|
146
|
+
'resolved',
|
|
147
|
+
'resolve_escalation marks the escalation resolved'
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
select ok(
|
|
151
|
+
(
|
|
152
|
+
select e.details @> jsonb_build_object('seed', 'escalation', 'resolution', 'approved')
|
|
153
|
+
from agent_board.escalations e
|
|
154
|
+
where e.id = (select escalation_id from dblint_escalation)
|
|
155
|
+
),
|
|
156
|
+
'resolve_escalation merges detail payloads without ambiguity regressions'
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
create temporary table dblint_heartbeat_first on commit drop as
|
|
160
|
+
select *
|
|
161
|
+
from agent_board.heartbeat(
|
|
162
|
+
'00000000-0000-0000-0000-000000000101',
|
|
163
|
+
'00000000-0000-0000-0000-000000000201',
|
|
164
|
+
'ready',
|
|
165
|
+
'initial heartbeat',
|
|
166
|
+
interval '5 minutes',
|
|
167
|
+
'{}'::jsonb
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
create temporary table dblint_heartbeat_second on commit drop as
|
|
171
|
+
select *
|
|
172
|
+
from agent_board.heartbeat(
|
|
173
|
+
'00000000-0000-0000-0000-000000000101',
|
|
174
|
+
'00000000-0000-0000-0000-000000000201',
|
|
175
|
+
'busy',
|
|
176
|
+
'updated heartbeat',
|
|
177
|
+
interval '10 minutes',
|
|
178
|
+
jsonb_build_object('pass', 2)
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
select ok(
|
|
182
|
+
(
|
|
183
|
+
select count(*) = 1
|
|
184
|
+
from agent_board.presence p
|
|
185
|
+
where p.agent_id = '00000000-0000-0000-0000-000000000101'
|
|
186
|
+
and p.availability = 'busy'
|
|
187
|
+
),
|
|
188
|
+
'heartbeat upserts a single presence row through the repaired conflict target'
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
create temporary table dblint_message_one on commit drop as
|
|
192
|
+
select *
|
|
193
|
+
from agent_board.post_message(
|
|
194
|
+
'00000000-0000-0000-0000-000000000201',
|
|
195
|
+
'00000000-0000-0000-0000-000000000101',
|
|
196
|
+
'mark-read seed message',
|
|
197
|
+
'comment',
|
|
198
|
+
null,
|
|
199
|
+
'{}'::jsonb
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
create temporary table dblint_message_two on commit drop as
|
|
203
|
+
select *
|
|
204
|
+
from agent_board.post_message(
|
|
205
|
+
'00000000-0000-0000-0000-000000000201',
|
|
206
|
+
'00000000-0000-0000-0000-000000000101',
|
|
207
|
+
'mark-read second message',
|
|
208
|
+
'comment',
|
|
209
|
+
null,
|
|
210
|
+
'{}'::jsonb
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
create temporary table dblint_mark_read_first on commit drop as
|
|
214
|
+
select *
|
|
215
|
+
from agent_board.mark_read(
|
|
216
|
+
'00000000-0000-0000-0000-000000000201',
|
|
217
|
+
'00000000-0000-0000-0000-000000000101',
|
|
218
|
+
1
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
create temporary table dblint_mark_read_second on commit drop as
|
|
222
|
+
select *
|
|
223
|
+
from agent_board.mark_read(
|
|
224
|
+
'00000000-0000-0000-0000-000000000201',
|
|
225
|
+
'00000000-0000-0000-0000-000000000101',
|
|
226
|
+
99
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
select ok(
|
|
230
|
+
(
|
|
231
|
+
select count(*) = 1
|
|
232
|
+
from agent_board.read_receipts rr
|
|
233
|
+
where rr.thread_id = '00000000-0000-0000-0000-000000000201'
|
|
234
|
+
and rr.agent_id = '00000000-0000-0000-0000-000000000101'
|
|
235
|
+
),
|
|
236
|
+
'mark_read upserts a single read receipt row through the repaired conflict target'
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
select is(
|
|
240
|
+
(select last_read_message_sequence from dblint_mark_read_second),
|
|
241
|
+
2::bigint,
|
|
242
|
+
'mark_read caps the stored sequence at the thread maximum'
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
select finish();
|
|
246
|
+
|
|
247
|
+
rollback;
|