@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,330 @@
|
|
|
1
|
+
create or replace function agent_board._owned_callback_endpoint(
|
|
2
|
+
p_endpoint_id uuid,
|
|
3
|
+
p_owner_agent_id uuid
|
|
4
|
+
)
|
|
5
|
+
returns agent_board.callback_endpoints
|
|
6
|
+
language plpgsql
|
|
7
|
+
security definer
|
|
8
|
+
set search_path = agent_board, public
|
|
9
|
+
as $$
|
|
10
|
+
declare
|
|
11
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
12
|
+
begin
|
|
13
|
+
select *
|
|
14
|
+
into v_endpoint
|
|
15
|
+
from agent_board.callback_endpoints ce
|
|
16
|
+
where ce.id = p_endpoint_id
|
|
17
|
+
and ce.owner_agent_id = p_owner_agent_id
|
|
18
|
+
for update;
|
|
19
|
+
|
|
20
|
+
if v_endpoint.id is null then
|
|
21
|
+
raise exception 'callback endpoint not found' using errcode = 'P0002';
|
|
22
|
+
end if;
|
|
23
|
+
|
|
24
|
+
return v_endpoint;
|
|
25
|
+
end;
|
|
26
|
+
$$;
|
|
27
|
+
|
|
28
|
+
create or replace function agent_board.register_callback_endpoint(
|
|
29
|
+
p_owner_agent_id uuid,
|
|
30
|
+
p_endpoint_url text,
|
|
31
|
+
p_metadata jsonb default '{}'::jsonb
|
|
32
|
+
)
|
|
33
|
+
returns table(endpoint_id uuid, owner_agent_id uuid, endpoint_status text, signing_key_version integer, verification_requested_at timestamptz, updated_at timestamptz)
|
|
34
|
+
language plpgsql
|
|
35
|
+
security definer
|
|
36
|
+
set search_path = agent_board, public
|
|
37
|
+
as $$
|
|
38
|
+
begin
|
|
39
|
+
if not exists (select 1 from agent_board.agents where id = p_owner_agent_id) then
|
|
40
|
+
raise exception 'owner agent not found' using errcode = 'P0002';
|
|
41
|
+
end if;
|
|
42
|
+
if nullif(trim(p_endpoint_url), '') is null or trim(p_endpoint_url) !~ '^https://.+$' then
|
|
43
|
+
raise exception 'callback endpoint URL must be https' using errcode = '22023';
|
|
44
|
+
end if;
|
|
45
|
+
|
|
46
|
+
return query
|
|
47
|
+
insert into agent_board.callback_endpoints as ce(
|
|
48
|
+
owner_agent_id,
|
|
49
|
+
endpoint_url,
|
|
50
|
+
endpoint_status,
|
|
51
|
+
verification_requested_at,
|
|
52
|
+
verified_at,
|
|
53
|
+
disabled_at,
|
|
54
|
+
disabled_reason,
|
|
55
|
+
metadata
|
|
56
|
+
)
|
|
57
|
+
values (
|
|
58
|
+
p_owner_agent_id,
|
|
59
|
+
trim(p_endpoint_url),
|
|
60
|
+
'pending_verification',
|
|
61
|
+
now(),
|
|
62
|
+
null,
|
|
63
|
+
null,
|
|
64
|
+
null,
|
|
65
|
+
coalesce(p_metadata, '{}'::jsonb)
|
|
66
|
+
)
|
|
67
|
+
on conflict on constraint callback_endpoints_url_unique do update
|
|
68
|
+
set endpoint_status = 'pending_verification',
|
|
69
|
+
verification_requested_at = now(),
|
|
70
|
+
verified_at = null,
|
|
71
|
+
disabled_at = null,
|
|
72
|
+
disabled_reason = null,
|
|
73
|
+
metadata = coalesce(ce.metadata, '{}'::jsonb) || coalesce(excluded.metadata, '{}'::jsonb),
|
|
74
|
+
updated_at = now()
|
|
75
|
+
returning ce.id, ce.owner_agent_id, ce.endpoint_status, ce.signing_key_version, ce.verification_requested_at, ce.updated_at;
|
|
76
|
+
end;
|
|
77
|
+
$$;
|
|
78
|
+
|
|
79
|
+
create or replace function agent_board.verify_callback_endpoint(
|
|
80
|
+
p_endpoint_id uuid,
|
|
81
|
+
p_owner_agent_id uuid,
|
|
82
|
+
p_metadata jsonb default '{}'::jsonb
|
|
83
|
+
)
|
|
84
|
+
returns table(endpoint_id uuid, owner_agent_id uuid, endpoint_status text, verified_at timestamptz, updated_at timestamptz)
|
|
85
|
+
language plpgsql
|
|
86
|
+
security definer
|
|
87
|
+
set search_path = agent_board, public
|
|
88
|
+
as $$
|
|
89
|
+
declare
|
|
90
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
91
|
+
begin
|
|
92
|
+
v_endpoint := agent_board._owned_callback_endpoint(p_endpoint_id, p_owner_agent_id);
|
|
93
|
+
|
|
94
|
+
update agent_board.callback_endpoints ce
|
|
95
|
+
set endpoint_status = 'verified',
|
|
96
|
+
verified_at = now(),
|
|
97
|
+
disabled_at = null,
|
|
98
|
+
disabled_reason = null,
|
|
99
|
+
metadata = coalesce(ce.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
100
|
+
updated_at = now()
|
|
101
|
+
where ce.id = v_endpoint.id
|
|
102
|
+
returning * into v_endpoint;
|
|
103
|
+
|
|
104
|
+
return query
|
|
105
|
+
select v_endpoint.id, v_endpoint.owner_agent_id, v_endpoint.endpoint_status, v_endpoint.verified_at, v_endpoint.updated_at;
|
|
106
|
+
end;
|
|
107
|
+
$$;
|
|
108
|
+
|
|
109
|
+
create or replace function agent_board.disable_callback_endpoint(
|
|
110
|
+
p_endpoint_id uuid,
|
|
111
|
+
p_owner_agent_id uuid,
|
|
112
|
+
p_disabled_reason text default null,
|
|
113
|
+
p_metadata jsonb default '{}'::jsonb
|
|
114
|
+
)
|
|
115
|
+
returns table(endpoint_id uuid, owner_agent_id uuid, endpoint_status text, disabled_at timestamptz, updated_at timestamptz)
|
|
116
|
+
language plpgsql
|
|
117
|
+
security definer
|
|
118
|
+
set search_path = agent_board, public
|
|
119
|
+
as $$
|
|
120
|
+
declare
|
|
121
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
122
|
+
begin
|
|
123
|
+
v_endpoint := agent_board._owned_callback_endpoint(p_endpoint_id, p_owner_agent_id);
|
|
124
|
+
|
|
125
|
+
update agent_board.callback_endpoints ce
|
|
126
|
+
set endpoint_status = 'disabled',
|
|
127
|
+
disabled_at = now(),
|
|
128
|
+
disabled_reason = nullif(trim(p_disabled_reason), ''),
|
|
129
|
+
metadata = coalesce(ce.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
130
|
+
updated_at = now()
|
|
131
|
+
where ce.id = v_endpoint.id
|
|
132
|
+
returning * into v_endpoint;
|
|
133
|
+
|
|
134
|
+
update agent_board.callback_subscriptions cs
|
|
135
|
+
set subscription_status = 'disabled',
|
|
136
|
+
disabled_at = now(),
|
|
137
|
+
updated_at = now()
|
|
138
|
+
where cs.endpoint_id = v_endpoint.id
|
|
139
|
+
and cs.subscription_status = 'active';
|
|
140
|
+
|
|
141
|
+
return query
|
|
142
|
+
select v_endpoint.id, v_endpoint.owner_agent_id, v_endpoint.endpoint_status, v_endpoint.disabled_at, v_endpoint.updated_at;
|
|
143
|
+
end;
|
|
144
|
+
$$;
|
|
145
|
+
|
|
146
|
+
create or replace function agent_board.rotate_callback_signing_key(
|
|
147
|
+
p_endpoint_id uuid,
|
|
148
|
+
p_owner_agent_id uuid,
|
|
149
|
+
p_metadata jsonb default '{}'::jsonb
|
|
150
|
+
)
|
|
151
|
+
returns table(endpoint_id uuid, owner_agent_id uuid, signing_key_version integer, endpoint_status text, verification_requested_at timestamptz, updated_at timestamptz)
|
|
152
|
+
language plpgsql
|
|
153
|
+
security definer
|
|
154
|
+
set search_path = agent_board, public
|
|
155
|
+
as $$
|
|
156
|
+
declare
|
|
157
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
158
|
+
begin
|
|
159
|
+
v_endpoint := agent_board._owned_callback_endpoint(p_endpoint_id, p_owner_agent_id);
|
|
160
|
+
|
|
161
|
+
update agent_board.callback_endpoints ce
|
|
162
|
+
set signing_key_version = ce.signing_key_version + 1,
|
|
163
|
+
endpoint_status = 'pending_verification',
|
|
164
|
+
verification_requested_at = now(),
|
|
165
|
+
verified_at = null,
|
|
166
|
+
disabled_at = null,
|
|
167
|
+
disabled_reason = null,
|
|
168
|
+
metadata = coalesce(ce.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
169
|
+
updated_at = now()
|
|
170
|
+
where ce.id = v_endpoint.id
|
|
171
|
+
returning * into v_endpoint;
|
|
172
|
+
|
|
173
|
+
return query
|
|
174
|
+
select v_endpoint.id, v_endpoint.owner_agent_id, v_endpoint.signing_key_version, v_endpoint.endpoint_status, v_endpoint.verification_requested_at, v_endpoint.updated_at;
|
|
175
|
+
end;
|
|
176
|
+
$$;
|
|
177
|
+
|
|
178
|
+
create or replace function agent_board.delete_callback_endpoint(
|
|
179
|
+
p_endpoint_id uuid,
|
|
180
|
+
p_owner_agent_id uuid
|
|
181
|
+
)
|
|
182
|
+
returns table(endpoint_id uuid, owner_agent_id uuid, deleted boolean)
|
|
183
|
+
language plpgsql
|
|
184
|
+
security definer
|
|
185
|
+
set search_path = agent_board, public
|
|
186
|
+
as $$
|
|
187
|
+
declare
|
|
188
|
+
v_endpoint_id uuid;
|
|
189
|
+
begin
|
|
190
|
+
delete from agent_board.callback_endpoints ce
|
|
191
|
+
where ce.id = p_endpoint_id
|
|
192
|
+
and ce.owner_agent_id = p_owner_agent_id
|
|
193
|
+
returning id into v_endpoint_id;
|
|
194
|
+
|
|
195
|
+
if v_endpoint_id is null then
|
|
196
|
+
raise exception 'callback endpoint not found' using errcode = 'P0002';
|
|
197
|
+
end if;
|
|
198
|
+
|
|
199
|
+
return query
|
|
200
|
+
select v_endpoint_id, p_owner_agent_id, true;
|
|
201
|
+
end;
|
|
202
|
+
$$;
|
|
203
|
+
|
|
204
|
+
create or replace function agent_board.subscribe_callback_endpoint(
|
|
205
|
+
p_endpoint_id uuid,
|
|
206
|
+
p_agent_id uuid,
|
|
207
|
+
p_subscription_scope text,
|
|
208
|
+
p_event_category text,
|
|
209
|
+
p_board_id uuid default null,
|
|
210
|
+
p_metadata jsonb default '{}'::jsonb
|
|
211
|
+
)
|
|
212
|
+
returns table(subscription_id uuid, endpoint_id uuid, agent_id uuid, subscription_scope text, event_category text, board_id uuid, subscription_status text, updated_at timestamptz)
|
|
213
|
+
language plpgsql
|
|
214
|
+
security definer
|
|
215
|
+
set search_path = agent_board, public
|
|
216
|
+
as $$
|
|
217
|
+
declare
|
|
218
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
219
|
+
v_subscription agent_board.callback_subscriptions%rowtype;
|
|
220
|
+
v_board_membership_id uuid;
|
|
221
|
+
begin
|
|
222
|
+
v_endpoint := agent_board._owned_callback_endpoint(p_endpoint_id, p_agent_id);
|
|
223
|
+
|
|
224
|
+
if p_subscription_scope = 'own_inbox' then
|
|
225
|
+
if p_event_category not in ('inbox.item.delivered', 'inbox.item.updated') or p_board_id is not null then
|
|
226
|
+
raise exception 'invalid own_inbox subscription shape' using errcode = '22023';
|
|
227
|
+
end if;
|
|
228
|
+
elsif p_subscription_scope = 'board' then
|
|
229
|
+
if p_event_category not in ('board.post.delivered', 'board.post.updated') or p_board_id is null then
|
|
230
|
+
raise exception 'invalid board subscription shape' using errcode = '22023';
|
|
231
|
+
end if;
|
|
232
|
+
v_board_membership_id := agent_board._active_board_membership_id(p_board_id, p_agent_id);
|
|
233
|
+
if v_board_membership_id is null then
|
|
234
|
+
raise exception 'board membership not found' using errcode = 'P0002';
|
|
235
|
+
end if;
|
|
236
|
+
else
|
|
237
|
+
raise exception 'invalid subscription scope' using errcode = '22023';
|
|
238
|
+
end if;
|
|
239
|
+
|
|
240
|
+
select *
|
|
241
|
+
into v_subscription
|
|
242
|
+
from agent_board.callback_subscriptions cs
|
|
243
|
+
where cs.endpoint_id = p_endpoint_id
|
|
244
|
+
and cs.agent_id = p_agent_id
|
|
245
|
+
and cs.subscription_scope = p_subscription_scope
|
|
246
|
+
and cs.event_category = p_event_category
|
|
247
|
+
and coalesce(cs.board_id, '00000000-0000-0000-0000-000000000000'::uuid) = coalesce(p_board_id, '00000000-0000-0000-0000-000000000000'::uuid)
|
|
248
|
+
order by cs.created_at desc
|
|
249
|
+
limit 1
|
|
250
|
+
for update;
|
|
251
|
+
|
|
252
|
+
if v_subscription.id is null then
|
|
253
|
+
insert into agent_board.callback_subscriptions(
|
|
254
|
+
endpoint_id,
|
|
255
|
+
agent_id,
|
|
256
|
+
subscription_scope,
|
|
257
|
+
event_category,
|
|
258
|
+
board_id,
|
|
259
|
+
board_membership_id,
|
|
260
|
+
metadata
|
|
261
|
+
)
|
|
262
|
+
values (
|
|
263
|
+
v_endpoint.id,
|
|
264
|
+
p_agent_id,
|
|
265
|
+
p_subscription_scope,
|
|
266
|
+
p_event_category,
|
|
267
|
+
p_board_id,
|
|
268
|
+
v_board_membership_id,
|
|
269
|
+
coalesce(p_metadata, '{}'::jsonb)
|
|
270
|
+
)
|
|
271
|
+
returning * into v_subscription;
|
|
272
|
+
else
|
|
273
|
+
update agent_board.callback_subscriptions
|
|
274
|
+
set subscription_status = 'active',
|
|
275
|
+
disabled_at = null,
|
|
276
|
+
board_membership_id = v_board_membership_id,
|
|
277
|
+
metadata = coalesce(callback_subscriptions.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
278
|
+
updated_at = now()
|
|
279
|
+
where id = v_subscription.id
|
|
280
|
+
returning * into v_subscription;
|
|
281
|
+
end if;
|
|
282
|
+
|
|
283
|
+
return query
|
|
284
|
+
select v_subscription.id, v_subscription.endpoint_id, v_subscription.agent_id, v_subscription.subscription_scope, v_subscription.event_category, v_subscription.board_id, v_subscription.subscription_status, v_subscription.updated_at;
|
|
285
|
+
end;
|
|
286
|
+
$$;
|
|
287
|
+
|
|
288
|
+
create or replace function agent_board.unsubscribe_callback_endpoint(
|
|
289
|
+
p_endpoint_id uuid,
|
|
290
|
+
p_agent_id uuid,
|
|
291
|
+
p_subscription_scope text,
|
|
292
|
+
p_event_category text,
|
|
293
|
+
p_board_id uuid default null,
|
|
294
|
+
p_metadata jsonb default '{}'::jsonb
|
|
295
|
+
)
|
|
296
|
+
returns table(subscription_id uuid, endpoint_id uuid, agent_id uuid, subscription_scope text, event_category text, board_id uuid, subscription_status text, disabled_at timestamptz, updated_at timestamptz)
|
|
297
|
+
language plpgsql
|
|
298
|
+
security definer
|
|
299
|
+
set search_path = agent_board, public
|
|
300
|
+
as $$
|
|
301
|
+
declare
|
|
302
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
303
|
+
v_subscription agent_board.callback_subscriptions%rowtype;
|
|
304
|
+
begin
|
|
305
|
+
v_endpoint := agent_board._owned_callback_endpoint(p_endpoint_id, p_agent_id);
|
|
306
|
+
|
|
307
|
+
update agent_board.callback_subscriptions cs
|
|
308
|
+
set subscription_status = 'disabled',
|
|
309
|
+
disabled_at = now(),
|
|
310
|
+
metadata = coalesce(cs.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
311
|
+
updated_at = now()
|
|
312
|
+
where cs.endpoint_id = v_endpoint.id
|
|
313
|
+
and cs.agent_id = p_agent_id
|
|
314
|
+
and cs.subscription_scope = p_subscription_scope
|
|
315
|
+
and cs.event_category = p_event_category
|
|
316
|
+
and coalesce(cs.board_id, '00000000-0000-0000-0000-000000000000'::uuid) = coalesce(p_board_id, '00000000-0000-0000-0000-000000000000'::uuid)
|
|
317
|
+
and cs.subscription_status = 'active'
|
|
318
|
+
returning * into v_subscription;
|
|
319
|
+
|
|
320
|
+
if v_subscription.id is null then
|
|
321
|
+
raise exception 'callback subscription not found' using errcode = 'P0002';
|
|
322
|
+
end if;
|
|
323
|
+
|
|
324
|
+
return query
|
|
325
|
+
select v_subscription.id, v_subscription.endpoint_id, v_subscription.agent_id, v_subscription.subscription_scope, v_subscription.event_category, v_subscription.board_id, v_subscription.subscription_status, v_subscription.disabled_at, v_subscription.updated_at;
|
|
326
|
+
end;
|
|
327
|
+
$$;
|
|
328
|
+
|
|
329
|
+
revoke all on all functions in schema agent_board from public, anon, authenticated;
|
|
330
|
+
grant execute on all functions in schema agent_board to service_role;
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
create or replace view agent_board.v_agent_inbox
|
|
2
|
+
with (security_invoker = true)
|
|
3
|
+
as
|
|
4
|
+
select
|
|
5
|
+
ii.id as inbox_item_id,
|
|
6
|
+
ii.delivery_recipient_id,
|
|
7
|
+
ii.recipient_agent_id,
|
|
8
|
+
recipient.handle as recipient_handle,
|
|
9
|
+
recipient.display_name as recipient_display_name,
|
|
10
|
+
ii.board_id,
|
|
11
|
+
b.slug as board_slug,
|
|
12
|
+
b.name as board_name,
|
|
13
|
+
ii.delivery_mode,
|
|
14
|
+
ii.source_kind,
|
|
15
|
+
ii.source_message_id,
|
|
16
|
+
ii.source_task_id,
|
|
17
|
+
ii.source_delegation_id,
|
|
18
|
+
ii.subject,
|
|
19
|
+
ii.preview,
|
|
20
|
+
ii.priority,
|
|
21
|
+
ii.action_state,
|
|
22
|
+
ii.visible_in_board_feed,
|
|
23
|
+
ii.fetch_descriptor,
|
|
24
|
+
ii.created_at,
|
|
25
|
+
ii.updated_at
|
|
26
|
+
from agent_board.inbox_items ii
|
|
27
|
+
join agent_board.agents recipient on recipient.id = ii.recipient_agent_id
|
|
28
|
+
left join agent_board.boards b on b.id = ii.board_id
|
|
29
|
+
where ii.visible_in_inbox = true;
|
|
30
|
+
|
|
31
|
+
create or replace view agent_board.v_agent_inbox_counts
|
|
32
|
+
with (security_invoker = true)
|
|
33
|
+
as
|
|
34
|
+
select
|
|
35
|
+
ii.recipient_agent_id,
|
|
36
|
+
count(*) filter (where ii.action_state in ('new', 'restored'))::bigint as unread_count,
|
|
37
|
+
count(*) filter (where ii.action_state in ('new', 'restored', 'deferred'))::bigint as pending_action_count,
|
|
38
|
+
count(*)::bigint as total_visible_count,
|
|
39
|
+
max(ii.updated_at) as latest_inbox_updated_at
|
|
40
|
+
from agent_board.inbox_items ii
|
|
41
|
+
where ii.visible_in_inbox = true
|
|
42
|
+
group by ii.recipient_agent_id;
|
|
43
|
+
|
|
44
|
+
create or replace view agent_board.v_board_directory
|
|
45
|
+
with (security_invoker = true)
|
|
46
|
+
as
|
|
47
|
+
select
|
|
48
|
+
b.id as board_id,
|
|
49
|
+
b.slug as board_slug,
|
|
50
|
+
b.name as board_name,
|
|
51
|
+
b.description as board_description,
|
|
52
|
+
b.status as board_status,
|
|
53
|
+
b.created_by_agent_id,
|
|
54
|
+
creator.handle as created_by_handle,
|
|
55
|
+
coalesce(members.active_member_count, 0)::bigint as active_member_count,
|
|
56
|
+
coalesce(board_activity.latest_board_activity_at, b.updated_at) as latest_board_activity_at,
|
|
57
|
+
b.created_at,
|
|
58
|
+
b.updated_at
|
|
59
|
+
from agent_board.boards b
|
|
60
|
+
join agent_board.agents creator on creator.id = b.created_by_agent_id
|
|
61
|
+
left join lateral (
|
|
62
|
+
select count(*) as active_member_count
|
|
63
|
+
from agent_board.board_memberships bm
|
|
64
|
+
where bm.board_id = b.id
|
|
65
|
+
and bm.membership_state in ('joined', 'subscribed')
|
|
66
|
+
) members on true
|
|
67
|
+
left join lateral (
|
|
68
|
+
select max(ii.created_at) as latest_board_activity_at
|
|
69
|
+
from agent_board.inbox_items ii
|
|
70
|
+
where ii.board_id = b.id
|
|
71
|
+
and ii.visible_in_board_feed = true
|
|
72
|
+
) board_activity on true;
|
|
73
|
+
|
|
74
|
+
create or replace view agent_board.v_board_memberships
|
|
75
|
+
with (security_invoker = true)
|
|
76
|
+
as
|
|
77
|
+
select
|
|
78
|
+
bm.id as board_membership_id,
|
|
79
|
+
bm.board_id,
|
|
80
|
+
b.slug as board_slug,
|
|
81
|
+
b.name as board_name,
|
|
82
|
+
bm.agent_id,
|
|
83
|
+
a.handle as agent_handle,
|
|
84
|
+
a.display_name as agent_display_name,
|
|
85
|
+
bm.membership_state,
|
|
86
|
+
bm.created_by_agent_id,
|
|
87
|
+
creator.handle as created_by_handle,
|
|
88
|
+
bm.left_at,
|
|
89
|
+
bm.created_at,
|
|
90
|
+
bm.updated_at
|
|
91
|
+
from agent_board.board_memberships bm
|
|
92
|
+
join agent_board.boards b on b.id = bm.board_id
|
|
93
|
+
join agent_board.agents a on a.id = bm.agent_id
|
|
94
|
+
left join agent_board.agents creator on creator.id = bm.created_by_agent_id;
|
|
95
|
+
|
|
96
|
+
create or replace view agent_board.v_board_feed
|
|
97
|
+
with (security_invoker = true)
|
|
98
|
+
as
|
|
99
|
+
with board_posts as (
|
|
100
|
+
select distinct on (dr.board_id, dr.source_message_id)
|
|
101
|
+
dr.board_id,
|
|
102
|
+
dr.source_message_id as message_id,
|
|
103
|
+
min(ii.created_at) over (partition by dr.board_id, dr.source_message_id) as first_delivered_at,
|
|
104
|
+
ii.subject,
|
|
105
|
+
ii.preview,
|
|
106
|
+
ii.priority,
|
|
107
|
+
ii.fetch_descriptor
|
|
108
|
+
from agent_board.delivery_recipients dr
|
|
109
|
+
join agent_board.inbox_items ii on ii.delivery_recipient_id = dr.id
|
|
110
|
+
where dr.board_id is not null
|
|
111
|
+
and dr.source_kind = 'message'
|
|
112
|
+
and dr.source_message_id is not null
|
|
113
|
+
and ii.visible_in_board_feed = true
|
|
114
|
+
order by dr.board_id, dr.source_message_id, ii.created_at asc, ii.id asc
|
|
115
|
+
)
|
|
116
|
+
select
|
|
117
|
+
bp.board_id,
|
|
118
|
+
b.slug as board_slug,
|
|
119
|
+
b.name as board_name,
|
|
120
|
+
bp.message_id,
|
|
121
|
+
m.thread_id,
|
|
122
|
+
m.message_sequence,
|
|
123
|
+
m.created_at as message_created_at,
|
|
124
|
+
m.author_agent_id,
|
|
125
|
+
author.handle as author_handle,
|
|
126
|
+
author.display_name as author_display_name,
|
|
127
|
+
bp.subject,
|
|
128
|
+
bp.preview,
|
|
129
|
+
bp.priority,
|
|
130
|
+
bp.fetch_descriptor,
|
|
131
|
+
bp.first_delivered_at
|
|
132
|
+
from board_posts bp
|
|
133
|
+
join agent_board.boards b on b.id = bp.board_id
|
|
134
|
+
join agent_board.messages m on m.id = bp.message_id
|
|
135
|
+
join agent_board.agents author on author.id = m.author_agent_id;
|
|
136
|
+
|
|
137
|
+
create or replace view agent_board.v_callback_endpoint_status
|
|
138
|
+
with (security_invoker = true)
|
|
139
|
+
as
|
|
140
|
+
select
|
|
141
|
+
ce.id as endpoint_id,
|
|
142
|
+
ce.owner_agent_id,
|
|
143
|
+
owner.handle as owner_agent_handle,
|
|
144
|
+
owner.display_name as owner_agent_display_name,
|
|
145
|
+
ce.endpoint_status,
|
|
146
|
+
ce.signing_key_version,
|
|
147
|
+
ce.verification_requested_at,
|
|
148
|
+
ce.verified_at,
|
|
149
|
+
ce.disabled_at,
|
|
150
|
+
ce.disabled_reason,
|
|
151
|
+
ce.last_delivery_at,
|
|
152
|
+
ce.last_failure_at,
|
|
153
|
+
coalesce(active_subscriptions.active_subscription_count, 0)::bigint as active_subscription_count,
|
|
154
|
+
ce.created_at,
|
|
155
|
+
ce.updated_at
|
|
156
|
+
from agent_board.callback_endpoints ce
|
|
157
|
+
join agent_board.agents owner on owner.id = ce.owner_agent_id
|
|
158
|
+
left join lateral (
|
|
159
|
+
select count(*) as active_subscription_count
|
|
160
|
+
from agent_board.callback_subscriptions cs
|
|
161
|
+
where cs.endpoint_id = ce.id
|
|
162
|
+
and cs.subscription_status = 'active'
|
|
163
|
+
) active_subscriptions on true;
|
|
164
|
+
|
|
165
|
+
create or replace view agent_board.v_callback_subscriptions
|
|
166
|
+
with (security_invoker = true)
|
|
167
|
+
as
|
|
168
|
+
select
|
|
169
|
+
cs.id as subscription_id,
|
|
170
|
+
cs.endpoint_id,
|
|
171
|
+
ce.owner_agent_id,
|
|
172
|
+
owner.handle as owner_agent_handle,
|
|
173
|
+
cs.agent_id,
|
|
174
|
+
agent.handle as agent_handle,
|
|
175
|
+
cs.subscription_scope,
|
|
176
|
+
cs.event_category,
|
|
177
|
+
cs.board_id,
|
|
178
|
+
b.slug as board_slug,
|
|
179
|
+
b.name as board_name,
|
|
180
|
+
cs.board_membership_id,
|
|
181
|
+
cs.subscription_status,
|
|
182
|
+
cs.disabled_at,
|
|
183
|
+
cs.created_at,
|
|
184
|
+
cs.updated_at
|
|
185
|
+
from agent_board.callback_subscriptions cs
|
|
186
|
+
join agent_board.callback_endpoints ce on ce.id = cs.endpoint_id
|
|
187
|
+
join agent_board.agents owner on owner.id = ce.owner_agent_id
|
|
188
|
+
join agent_board.agents agent on agent.id = cs.agent_id
|
|
189
|
+
left join agent_board.boards b on b.id = cs.board_id;
|
|
190
|
+
|
|
191
|
+
create or replace view agent_board.v_callback_delivery_health
|
|
192
|
+
with (security_invoker = true)
|
|
193
|
+
as
|
|
194
|
+
select
|
|
195
|
+
cs.id as subscription_id,
|
|
196
|
+
cs.endpoint_id,
|
|
197
|
+
ce.owner_agent_id,
|
|
198
|
+
owner.handle as owner_agent_handle,
|
|
199
|
+
cs.agent_id,
|
|
200
|
+
agent.handle as agent_handle,
|
|
201
|
+
cs.subscription_scope,
|
|
202
|
+
cs.event_category,
|
|
203
|
+
cs.board_id,
|
|
204
|
+
b.slug as board_slug,
|
|
205
|
+
cs.subscription_status,
|
|
206
|
+
latest_outbox.id as latest_outbox_event_id,
|
|
207
|
+
latest_outbox.outbox_status as latest_outbox_status,
|
|
208
|
+
latest_outbox.delivery_mode as latest_delivery_mode,
|
|
209
|
+
latest_outbox.source_kind as latest_source_kind,
|
|
210
|
+
latest_attempt.attempt_number as latest_attempt_number,
|
|
211
|
+
latest_attempt.attempt_outcome as latest_attempt_outcome,
|
|
212
|
+
latest_attempt.http_status as latest_http_status,
|
|
213
|
+
latest_attempt.error_summary as latest_error_summary,
|
|
214
|
+
latest_attempt.started_at as latest_attempt_started_at,
|
|
215
|
+
latest_attempt.finished_at as latest_attempt_finished_at,
|
|
216
|
+
latest_attempt.next_retry_at as latest_next_retry_at,
|
|
217
|
+
ce.last_delivery_at,
|
|
218
|
+
ce.last_failure_at,
|
|
219
|
+
cs.created_at,
|
|
220
|
+
cs.updated_at
|
|
221
|
+
from agent_board.callback_subscriptions cs
|
|
222
|
+
join agent_board.callback_endpoints ce on ce.id = cs.endpoint_id
|
|
223
|
+
join agent_board.agents owner on owner.id = ce.owner_agent_id
|
|
224
|
+
join agent_board.agents agent on agent.id = cs.agent_id
|
|
225
|
+
left join agent_board.boards b on b.id = cs.board_id
|
|
226
|
+
left join lateral (
|
|
227
|
+
select coe.id, coe.outbox_status, coe.delivery_mode, coe.source_kind, coe.created_at
|
|
228
|
+
from agent_board.callback_outbox_events coe
|
|
229
|
+
where coe.subscription_id = cs.id
|
|
230
|
+
order by coe.created_at desc, coe.id desc
|
|
231
|
+
limit 1
|
|
232
|
+
) latest_outbox on true
|
|
233
|
+
left join lateral (
|
|
234
|
+
select cda.attempt_number, cda.attempt_outcome, cda.http_status, cda.error_summary, cda.started_at, cda.finished_at, cda.next_retry_at
|
|
235
|
+
from agent_board.callback_delivery_attempts cda
|
|
236
|
+
where cda.outbox_event_id = latest_outbox.id
|
|
237
|
+
order by cda.attempt_number desc
|
|
238
|
+
limit 1
|
|
239
|
+
) latest_attempt on true;
|
|
240
|
+
|
|
241
|
+
create or replace view agent_board.v_agent_dashboard
|
|
242
|
+
with (security_invoker = true)
|
|
243
|
+
as
|
|
244
|
+
select
|
|
245
|
+
a.id as agent_id,
|
|
246
|
+
a.handle,
|
|
247
|
+
a.display_name,
|
|
248
|
+
a.status as participant_status,
|
|
249
|
+
p.availability,
|
|
250
|
+
p.thread_id as presence_thread_id,
|
|
251
|
+
p.last_heartbeat_at,
|
|
252
|
+
p.expires_at as presence_expires_at,
|
|
253
|
+
coalesce(open_tasks.open_task_count, 0)::bigint as open_task_count,
|
|
254
|
+
coalesce(active_claims.active_claim_count, 0)::bigint as active_claim_count,
|
|
255
|
+
coalesce(open_escalations.assigned_open_escalation_count, 0)::bigint as assigned_open_escalation_count,
|
|
256
|
+
latest.task_id as latest_task_id,
|
|
257
|
+
latest.event_sequence as latest_task_event_sequence,
|
|
258
|
+
latest.event_type as latest_task_event_type,
|
|
259
|
+
latest.payload->>'kind' as latest_task_event_kind,
|
|
260
|
+
latest.updated_at as latest_task_updated_at,
|
|
261
|
+
coalesce(inbox_counts.inbox_unread_count, 0)::bigint as inbox_unread_count,
|
|
262
|
+
coalesce(inbox_counts.inbox_pending_action_count, 0)::bigint as inbox_pending_action_count
|
|
263
|
+
from agent_board.agents a
|
|
264
|
+
left join agent_board.presence p on p.agent_id = a.id
|
|
265
|
+
left join lateral (
|
|
266
|
+
select count(*) as open_task_count
|
|
267
|
+
from agent_board.tasks t
|
|
268
|
+
where t.assigned_agent_id = a.id
|
|
269
|
+
and t.status in ('pending', 'in_progress', 'blocked')
|
|
270
|
+
) open_tasks on true
|
|
271
|
+
left join lateral (
|
|
272
|
+
select count(*) as active_claim_count
|
|
273
|
+
from agent_board.claims c
|
|
274
|
+
where c.agent_id = a.id
|
|
275
|
+
and c.status = 'active'
|
|
276
|
+
and c.released_at is null
|
|
277
|
+
and c.lease_expires_at > now()
|
|
278
|
+
) active_claims on true
|
|
279
|
+
left join lateral (
|
|
280
|
+
select count(*) as assigned_open_escalation_count
|
|
281
|
+
from agent_board.escalations e
|
|
282
|
+
where e.assigned_agent_id = a.id
|
|
283
|
+
and e.status in ('open', 'acknowledged')
|
|
284
|
+
) open_escalations on true
|
|
285
|
+
left join lateral (
|
|
286
|
+
select
|
|
287
|
+
count(*) filter (where ii.action_state in ('new', 'restored')) as inbox_unread_count,
|
|
288
|
+
count(*) filter (where ii.action_state in ('new', 'restored', 'deferred')) as inbox_pending_action_count
|
|
289
|
+
from agent_board.inbox_items ii
|
|
290
|
+
where ii.recipient_agent_id = a.id
|
|
291
|
+
and ii.visible_in_inbox = true
|
|
292
|
+
) inbox_counts on true
|
|
293
|
+
left join lateral (
|
|
294
|
+
select t.id as task_id, te.event_sequence, te.event_type, te.payload, t.updated_at
|
|
295
|
+
from agent_board.tasks t
|
|
296
|
+
left join agent_board.task_events te on te.task_id = t.id
|
|
297
|
+
where t.assigned_agent_id = a.id or t.created_by_agent_id = a.id
|
|
298
|
+
order by t.updated_at desc, te.event_sequence desc nulls last
|
|
299
|
+
limit 1
|
|
300
|
+
) latest on true;
|
|
301
|
+
|
|
302
|
+
grant select on agent_board.v_agent_inbox,
|
|
303
|
+
agent_board.v_agent_inbox_counts,
|
|
304
|
+
agent_board.v_board_directory,
|
|
305
|
+
agent_board.v_board_memberships,
|
|
306
|
+
agent_board.v_board_feed,
|
|
307
|
+
agent_board.v_callback_endpoint_status,
|
|
308
|
+
agent_board.v_callback_subscriptions,
|
|
309
|
+
agent_board.v_callback_delivery_health,
|
|
310
|
+
agent_board.v_agent_dashboard
|
|
311
|
+
to authenticated;
|
|
312
|
+
|
|
313
|
+
do $$
|
|
314
|
+
declare
|
|
315
|
+
v_table text;
|
|
316
|
+
begin
|
|
317
|
+
foreach v_table in array array[
|
|
318
|
+
'boards',
|
|
319
|
+
'board_memberships',
|
|
320
|
+
'inbox_items',
|
|
321
|
+
'callback_endpoints',
|
|
322
|
+
'callback_subscriptions',
|
|
323
|
+
'callback_delivery_attempts'
|
|
324
|
+
]
|
|
325
|
+
loop
|
|
326
|
+
begin
|
|
327
|
+
execute format('alter publication supabase_realtime add table agent_board.%I', v_table);
|
|
328
|
+
exception
|
|
329
|
+
when duplicate_object then null;
|
|
330
|
+
when undefined_object then null;
|
|
331
|
+
end;
|
|
332
|
+
end loop;
|
|
333
|
+
end;
|
|
334
|
+
$$;
|