@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,1243 @@
|
|
|
1
|
+
create or replace function agent_board.create_board(
|
|
2
|
+
p_created_by_agent_id uuid,
|
|
3
|
+
p_slug text,
|
|
4
|
+
p_name text,
|
|
5
|
+
p_description text default null,
|
|
6
|
+
p_metadata jsonb default '{}'::jsonb
|
|
7
|
+
)
|
|
8
|
+
returns table(board_id uuid, slug text, name text, status text, created_at timestamptz, updated_at timestamptz)
|
|
9
|
+
language plpgsql
|
|
10
|
+
security definer
|
|
11
|
+
set search_path = agent_board, public
|
|
12
|
+
as $$
|
|
13
|
+
declare
|
|
14
|
+
v_actor_agent_id uuid;
|
|
15
|
+
begin
|
|
16
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_created_by_agent_id, 'p_created_by_agent_id');
|
|
17
|
+
|
|
18
|
+
if nullif(trim(p_slug), '') is null or nullif(trim(p_name), '') is null then
|
|
19
|
+
raise exception 'board slug and name are required' using errcode = '22023';
|
|
20
|
+
end if;
|
|
21
|
+
|
|
22
|
+
return query
|
|
23
|
+
insert into agent_board.boards as b(slug, name, description, created_by_agent_id, metadata)
|
|
24
|
+
values (trim(p_slug), trim(p_name), nullif(trim(p_description), ''), v_actor_agent_id, coalesce(p_metadata, '{}'::jsonb))
|
|
25
|
+
on conflict on constraint boards_slug_key do update
|
|
26
|
+
set name = excluded.name,
|
|
27
|
+
description = excluded.description,
|
|
28
|
+
status = 'active',
|
|
29
|
+
metadata = coalesce(b.metadata, '{}'::jsonb) || coalesce(excluded.metadata, '{}'::jsonb),
|
|
30
|
+
updated_at = now()
|
|
31
|
+
returning b.id, b.slug, b.name, b.status, b.created_at, b.updated_at;
|
|
32
|
+
end;
|
|
33
|
+
$$;
|
|
34
|
+
|
|
35
|
+
create or replace function agent_board.join_board(
|
|
36
|
+
p_board_id uuid,
|
|
37
|
+
p_agent_id uuid,
|
|
38
|
+
p_membership_state text default 'joined',
|
|
39
|
+
p_created_by_agent_id uuid default null,
|
|
40
|
+
p_metadata jsonb default '{}'::jsonb
|
|
41
|
+
)
|
|
42
|
+
returns table(membership_id uuid, board_id uuid, agent_id uuid, membership_state text, created_at timestamptz, updated_at timestamptz)
|
|
43
|
+
language plpgsql
|
|
44
|
+
security definer
|
|
45
|
+
set search_path = agent_board, public
|
|
46
|
+
as $$
|
|
47
|
+
declare
|
|
48
|
+
v_membership agent_board.board_memberships%rowtype;
|
|
49
|
+
v_actor_agent_id uuid;
|
|
50
|
+
v_created_by_agent_id uuid;
|
|
51
|
+
begin
|
|
52
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_agent_id, 'p_agent_id');
|
|
53
|
+
if p_created_by_agent_id is null then
|
|
54
|
+
v_created_by_agent_id := case when agent_board._is_service_role() then null else v_actor_agent_id end;
|
|
55
|
+
else
|
|
56
|
+
v_created_by_agent_id := agent_board._resolved_actor_agent_id(p_created_by_agent_id, 'p_created_by_agent_id');
|
|
57
|
+
end if;
|
|
58
|
+
|
|
59
|
+
if p_membership_state not in ('joined', 'subscribed') then
|
|
60
|
+
raise exception 'join_board only accepts joined or subscribed' using errcode = '22023';
|
|
61
|
+
end if;
|
|
62
|
+
if not exists (select 1 from agent_board.boards where id = p_board_id) then
|
|
63
|
+
raise exception 'board not found' using errcode = 'P0002';
|
|
64
|
+
end if;
|
|
65
|
+
|
|
66
|
+
select *
|
|
67
|
+
into v_membership
|
|
68
|
+
from agent_board.board_memberships bm
|
|
69
|
+
where bm.board_id = p_board_id
|
|
70
|
+
and bm.agent_id = v_actor_agent_id
|
|
71
|
+
order by bm.created_at desc
|
|
72
|
+
limit 1
|
|
73
|
+
for update;
|
|
74
|
+
|
|
75
|
+
if v_membership.id is null then
|
|
76
|
+
insert into agent_board.board_memberships(board_id, agent_id, membership_state, created_by_agent_id, metadata)
|
|
77
|
+
values (p_board_id, v_actor_agent_id, p_membership_state, coalesce(v_created_by_agent_id, v_actor_agent_id), coalesce(p_metadata, '{}'::jsonb))
|
|
78
|
+
returning * into v_membership;
|
|
79
|
+
else
|
|
80
|
+
update agent_board.board_memberships bm
|
|
81
|
+
set membership_state = p_membership_state,
|
|
82
|
+
left_at = null,
|
|
83
|
+
metadata = coalesce(bm.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
84
|
+
updated_at = now()
|
|
85
|
+
where bm.id = v_membership.id
|
|
86
|
+
returning * into v_membership;
|
|
87
|
+
end if;
|
|
88
|
+
|
|
89
|
+
return query
|
|
90
|
+
select v_membership.id, v_membership.board_id, v_membership.agent_id, v_membership.membership_state, v_membership.created_at, v_membership.updated_at;
|
|
91
|
+
end;
|
|
92
|
+
$$;
|
|
93
|
+
|
|
94
|
+
create or replace function agent_board.update_board_membership(
|
|
95
|
+
p_board_id uuid,
|
|
96
|
+
p_agent_id uuid,
|
|
97
|
+
p_membership_state text,
|
|
98
|
+
p_metadata jsonb default '{}'::jsonb
|
|
99
|
+
)
|
|
100
|
+
returns table(membership_id uuid, board_id uuid, agent_id uuid, membership_state text, left_at timestamptz, updated_at timestamptz)
|
|
101
|
+
language plpgsql
|
|
102
|
+
security definer
|
|
103
|
+
set search_path = agent_board, public
|
|
104
|
+
as $$
|
|
105
|
+
declare
|
|
106
|
+
v_membership agent_board.board_memberships%rowtype;
|
|
107
|
+
v_actor_agent_id uuid;
|
|
108
|
+
begin
|
|
109
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_agent_id, 'p_agent_id');
|
|
110
|
+
|
|
111
|
+
if p_membership_state not in ('joined', 'subscribed', 'left', 'removed') then
|
|
112
|
+
raise exception 'invalid board membership state' using errcode = '22023';
|
|
113
|
+
end if;
|
|
114
|
+
|
|
115
|
+
select *
|
|
116
|
+
into v_membership
|
|
117
|
+
from agent_board.board_memberships bm
|
|
118
|
+
where bm.board_id = p_board_id
|
|
119
|
+
and bm.agent_id = v_actor_agent_id
|
|
120
|
+
order by bm.created_at desc
|
|
121
|
+
limit 1
|
|
122
|
+
for update;
|
|
123
|
+
|
|
124
|
+
if v_membership.id is null then
|
|
125
|
+
raise exception 'board membership not found' using errcode = 'P0002';
|
|
126
|
+
end if;
|
|
127
|
+
|
|
128
|
+
update agent_board.board_memberships bm
|
|
129
|
+
set membership_state = p_membership_state,
|
|
130
|
+
left_at = case when p_membership_state in ('left', 'removed') then now() else null end,
|
|
131
|
+
metadata = coalesce(bm.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
132
|
+
updated_at = now()
|
|
133
|
+
where bm.id = v_membership.id
|
|
134
|
+
returning * into v_membership;
|
|
135
|
+
|
|
136
|
+
return query
|
|
137
|
+
select v_membership.id, v_membership.board_id, v_membership.agent_id, v_membership.membership_state, v_membership.left_at, v_membership.updated_at;
|
|
138
|
+
end;
|
|
139
|
+
$$;
|
|
140
|
+
|
|
141
|
+
create or replace function agent_board.leave_board(
|
|
142
|
+
p_board_id uuid,
|
|
143
|
+
p_agent_id uuid,
|
|
144
|
+
p_metadata jsonb default '{}'::jsonb
|
|
145
|
+
)
|
|
146
|
+
returns table(membership_id uuid, board_id uuid, agent_id uuid, membership_state text, left_at timestamptz, updated_at timestamptz)
|
|
147
|
+
language plpgsql
|
|
148
|
+
security definer
|
|
149
|
+
set search_path = agent_board, public
|
|
150
|
+
as $$
|
|
151
|
+
declare
|
|
152
|
+
v_actor_agent_id uuid;
|
|
153
|
+
begin
|
|
154
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_agent_id, 'p_agent_id');
|
|
155
|
+
|
|
156
|
+
return query
|
|
157
|
+
select *
|
|
158
|
+
from agent_board.update_board_membership(p_board_id, v_actor_agent_id, 'left', p_metadata);
|
|
159
|
+
end;
|
|
160
|
+
$$;
|
|
161
|
+
|
|
162
|
+
create or replace function agent_board.send_direct_message(
|
|
163
|
+
p_thread_id uuid,
|
|
164
|
+
p_author_agent_id uuid,
|
|
165
|
+
p_recipient_agent_id uuid,
|
|
166
|
+
p_subject text,
|
|
167
|
+
p_body text,
|
|
168
|
+
p_message_type text default 'comment',
|
|
169
|
+
p_priority text default 'medium',
|
|
170
|
+
p_idempotency_key text default null,
|
|
171
|
+
p_metadata jsonb default '{}'::jsonb
|
|
172
|
+
)
|
|
173
|
+
returns table(message_id uuid, delivery_recipient_id uuid, inbox_item_id uuid, callback_outbox_count integer, created_at timestamptz)
|
|
174
|
+
language plpgsql
|
|
175
|
+
security definer
|
|
176
|
+
set search_path = agent_board, public
|
|
177
|
+
as $$
|
|
178
|
+
declare
|
|
179
|
+
v_message agent_board.messages%rowtype;
|
|
180
|
+
v_created_message record;
|
|
181
|
+
v_recipient agent_board.delivery_recipients%rowtype;
|
|
182
|
+
v_inbox agent_board.inbox_items%rowtype;
|
|
183
|
+
v_callback_count integer := 0;
|
|
184
|
+
v_metadata jsonb;
|
|
185
|
+
v_preview text;
|
|
186
|
+
v_fetch_descriptor jsonb;
|
|
187
|
+
v_idempotency_key text := nullif(trim(p_idempotency_key), '');
|
|
188
|
+
v_actor_agent_id uuid;
|
|
189
|
+
begin
|
|
190
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_author_agent_id, 'p_author_agent_id');
|
|
191
|
+
|
|
192
|
+
if nullif(trim(p_subject), '') is null or nullif(trim(p_body), '') is null then
|
|
193
|
+
raise exception 'subject and body are required' using errcode = '22023';
|
|
194
|
+
end if;
|
|
195
|
+
if p_priority not in ('low', 'medium', 'high', 'urgent') then
|
|
196
|
+
raise exception 'invalid priority' using errcode = '22023';
|
|
197
|
+
end if;
|
|
198
|
+
if not exists (select 1 from agent_board.threads where id = p_thread_id) then
|
|
199
|
+
raise exception 'thread not found' using errcode = 'P0002';
|
|
200
|
+
end if;
|
|
201
|
+
if not agent_board._current_agent_can_access_thread(p_thread_id) then
|
|
202
|
+
raise exception 'thread not accessible to current agent' using errcode = '42501';
|
|
203
|
+
end if;
|
|
204
|
+
if not exists (select 1 from agent_board.agents where id = p_recipient_agent_id) then
|
|
205
|
+
raise exception 'recipient agent not found' using errcode = 'P0002';
|
|
206
|
+
end if;
|
|
207
|
+
|
|
208
|
+
perform agent_board._lock_idempotency_key(
|
|
209
|
+
'send_direct_message:' || p_thread_id::text || ':' || v_actor_agent_id::text,
|
|
210
|
+
v_idempotency_key
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
if v_idempotency_key is not null then
|
|
214
|
+
select *
|
|
215
|
+
into v_message
|
|
216
|
+
from agent_board.messages
|
|
217
|
+
where thread_id = p_thread_id
|
|
218
|
+
and author_agent_id = v_actor_agent_id
|
|
219
|
+
and metadata ->> 'rpcName' = 'send_direct_message'
|
|
220
|
+
and metadata ->> 'idempotencyKey' = v_idempotency_key
|
|
221
|
+
order by created_at desc
|
|
222
|
+
limit 1;
|
|
223
|
+
end if;
|
|
224
|
+
|
|
225
|
+
if v_message.id is null then
|
|
226
|
+
v_metadata := coalesce(p_metadata, '{}'::jsonb)
|
|
227
|
+
|| jsonb_build_object(
|
|
228
|
+
'rpcName', 'send_direct_message',
|
|
229
|
+
'subject', trim(p_subject),
|
|
230
|
+
'priority', p_priority
|
|
231
|
+
);
|
|
232
|
+
if v_idempotency_key is not null then
|
|
233
|
+
v_metadata := v_metadata || jsonb_build_object('idempotencyKey', v_idempotency_key);
|
|
234
|
+
end if;
|
|
235
|
+
|
|
236
|
+
select *
|
|
237
|
+
into v_created_message
|
|
238
|
+
from agent_board.post_message(
|
|
239
|
+
p_thread_id,
|
|
240
|
+
v_actor_agent_id,
|
|
241
|
+
p_body,
|
|
242
|
+
p_message_type,
|
|
243
|
+
null,
|
|
244
|
+
v_metadata
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
select *
|
|
248
|
+
into v_message
|
|
249
|
+
from agent_board.messages
|
|
250
|
+
where id = v_created_message.message_id;
|
|
251
|
+
end if;
|
|
252
|
+
|
|
253
|
+
v_preview := agent_board._trim_inbox_text(p_body, 280);
|
|
254
|
+
v_fetch_descriptor := agent_board._build_fetch_descriptor(
|
|
255
|
+
'thread',
|
|
256
|
+
p_thread_id,
|
|
257
|
+
'agent_board.v_thread_feed',
|
|
258
|
+
'direct delivery',
|
|
259
|
+
jsonb_build_object('messageId', v_message.id::text, 'recipientAgentId', p_recipient_agent_id::text)
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
v_recipient := agent_board._upsert_delivery_recipient(
|
|
263
|
+
'direct',
|
|
264
|
+
p_recipient_agent_id,
|
|
265
|
+
'message',
|
|
266
|
+
v_message.id,
|
|
267
|
+
null,
|
|
268
|
+
null,
|
|
269
|
+
null,
|
|
270
|
+
null,
|
|
271
|
+
jsonb_build_object('priority', p_priority)
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
v_inbox := agent_board._upsert_inbox_item(
|
|
275
|
+
v_recipient.id,
|
|
276
|
+
p_recipient_agent_id,
|
|
277
|
+
null,
|
|
278
|
+
v_recipient.delivery_mode,
|
|
279
|
+
'message',
|
|
280
|
+
v_message.id,
|
|
281
|
+
null,
|
|
282
|
+
null,
|
|
283
|
+
trim(p_subject),
|
|
284
|
+
v_preview,
|
|
285
|
+
p_priority,
|
|
286
|
+
true,
|
|
287
|
+
false,
|
|
288
|
+
v_fetch_descriptor,
|
|
289
|
+
jsonb_build_object('threadId', p_thread_id::text)
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
v_callback_count := agent_board._queue_inbox_callbacks(v_inbox.id, 'inbox.item.delivered');
|
|
293
|
+
|
|
294
|
+
return query
|
|
295
|
+
select v_message.id, v_recipient.id, v_inbox.id, v_callback_count, v_message.created_at;
|
|
296
|
+
end;
|
|
297
|
+
$$;
|
|
298
|
+
|
|
299
|
+
create or replace function agent_board.send_multicast_message(
|
|
300
|
+
p_thread_id uuid,
|
|
301
|
+
p_author_agent_id uuid,
|
|
302
|
+
p_recipient_agent_ids uuid[],
|
|
303
|
+
p_subject text,
|
|
304
|
+
p_body text,
|
|
305
|
+
p_message_type text default 'comment',
|
|
306
|
+
p_priority text default 'medium',
|
|
307
|
+
p_idempotency_key text default null,
|
|
308
|
+
p_metadata jsonb default '{}'::jsonb
|
|
309
|
+
)
|
|
310
|
+
returns table(message_id uuid, delivered_recipient_count integer, inbox_item_count integer, callback_outbox_count integer, created_at timestamptz)
|
|
311
|
+
language plpgsql
|
|
312
|
+
security definer
|
|
313
|
+
set search_path = agent_board, public
|
|
314
|
+
as $$
|
|
315
|
+
declare
|
|
316
|
+
v_message agent_board.messages%rowtype;
|
|
317
|
+
v_created_message record;
|
|
318
|
+
v_recipient_ids uuid[];
|
|
319
|
+
v_recipient_id uuid;
|
|
320
|
+
v_recipient agent_board.delivery_recipients%rowtype;
|
|
321
|
+
v_inbox agent_board.inbox_items%rowtype;
|
|
322
|
+
v_delivered_count integer := 0;
|
|
323
|
+
v_inbox_count integer := 0;
|
|
324
|
+
v_callback_count integer := 0;
|
|
325
|
+
v_metadata jsonb;
|
|
326
|
+
v_preview text;
|
|
327
|
+
v_fetch_descriptor jsonb;
|
|
328
|
+
v_idempotency_key text := nullif(trim(p_idempotency_key), '');
|
|
329
|
+
v_actor_agent_id uuid;
|
|
330
|
+
begin
|
|
331
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_author_agent_id, 'p_author_agent_id');
|
|
332
|
+
|
|
333
|
+
if nullif(trim(p_subject), '') is null or nullif(trim(p_body), '') is null then
|
|
334
|
+
raise exception 'subject and body are required' using errcode = '22023';
|
|
335
|
+
end if;
|
|
336
|
+
if p_priority not in ('low', 'medium', 'high', 'urgent') then
|
|
337
|
+
raise exception 'invalid priority' using errcode = '22023';
|
|
338
|
+
end if;
|
|
339
|
+
if p_recipient_agent_ids is null or cardinality(p_recipient_agent_ids) = 0 then
|
|
340
|
+
raise exception 'recipient_agent_ids must not be empty' using errcode = '22023';
|
|
341
|
+
end if;
|
|
342
|
+
if array_position(p_recipient_agent_ids, null) is not null then
|
|
343
|
+
raise exception 'recipient_agent_ids must not contain nulls' using errcode = '22023';
|
|
344
|
+
end if;
|
|
345
|
+
if not exists (select 1 from agent_board.threads where id = p_thread_id) then
|
|
346
|
+
raise exception 'thread not found' using errcode = 'P0002';
|
|
347
|
+
end if;
|
|
348
|
+
if not agent_board._current_agent_can_access_thread(p_thread_id) then
|
|
349
|
+
raise exception 'thread not accessible to current agent' using errcode = '42501';
|
|
350
|
+
end if;
|
|
351
|
+
|
|
352
|
+
select array_agg(distinct recipient_id)
|
|
353
|
+
into v_recipient_ids
|
|
354
|
+
from unnest(p_recipient_agent_ids) as recipient_id;
|
|
355
|
+
|
|
356
|
+
if (
|
|
357
|
+
select count(*)
|
|
358
|
+
from agent_board.agents
|
|
359
|
+
where id = any(v_recipient_ids)
|
|
360
|
+
) <> cardinality(v_recipient_ids) then
|
|
361
|
+
raise exception 'recipient agent not found' using errcode = 'P0002';
|
|
362
|
+
end if;
|
|
363
|
+
|
|
364
|
+
perform agent_board._lock_idempotency_key(
|
|
365
|
+
'send_multicast_message:' || p_thread_id::text || ':' || v_actor_agent_id::text,
|
|
366
|
+
v_idempotency_key
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
if v_idempotency_key is not null then
|
|
370
|
+
select *
|
|
371
|
+
into v_message
|
|
372
|
+
from agent_board.messages
|
|
373
|
+
where thread_id = p_thread_id
|
|
374
|
+
and author_agent_id = v_actor_agent_id
|
|
375
|
+
and metadata ->> 'rpcName' = 'send_multicast_message'
|
|
376
|
+
and metadata ->> 'idempotencyKey' = v_idempotency_key
|
|
377
|
+
order by created_at desc
|
|
378
|
+
limit 1;
|
|
379
|
+
end if;
|
|
380
|
+
|
|
381
|
+
if v_message.id is null then
|
|
382
|
+
v_metadata := coalesce(p_metadata, '{}'::jsonb)
|
|
383
|
+
|| jsonb_build_object(
|
|
384
|
+
'rpcName', 'send_multicast_message',
|
|
385
|
+
'subject', trim(p_subject),
|
|
386
|
+
'priority', p_priority
|
|
387
|
+
);
|
|
388
|
+
if v_idempotency_key is not null then
|
|
389
|
+
v_metadata := v_metadata || jsonb_build_object('idempotencyKey', v_idempotency_key);
|
|
390
|
+
end if;
|
|
391
|
+
|
|
392
|
+
select *
|
|
393
|
+
into v_created_message
|
|
394
|
+
from agent_board.post_message(
|
|
395
|
+
p_thread_id,
|
|
396
|
+
v_actor_agent_id,
|
|
397
|
+
p_body,
|
|
398
|
+
p_message_type,
|
|
399
|
+
null,
|
|
400
|
+
v_metadata
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
select *
|
|
404
|
+
into v_message
|
|
405
|
+
from agent_board.messages
|
|
406
|
+
where id = v_created_message.message_id;
|
|
407
|
+
end if;
|
|
408
|
+
|
|
409
|
+
v_preview := agent_board._trim_inbox_text(p_body, 280);
|
|
410
|
+
|
|
411
|
+
foreach v_recipient_id in array v_recipient_ids loop
|
|
412
|
+
v_fetch_descriptor := agent_board._build_fetch_descriptor(
|
|
413
|
+
'thread',
|
|
414
|
+
p_thread_id,
|
|
415
|
+
'agent_board.v_thread_feed',
|
|
416
|
+
'multicast delivery',
|
|
417
|
+
jsonb_build_object('messageId', v_message.id::text, 'recipientAgentId', v_recipient_id::text)
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
v_recipient := agent_board._upsert_delivery_recipient(
|
|
421
|
+
'multicast',
|
|
422
|
+
v_recipient_id,
|
|
423
|
+
'message',
|
|
424
|
+
v_message.id,
|
|
425
|
+
null,
|
|
426
|
+
null,
|
|
427
|
+
null,
|
|
428
|
+
null,
|
|
429
|
+
jsonb_build_object('priority', p_priority)
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
v_inbox := agent_board._upsert_inbox_item(
|
|
433
|
+
v_recipient.id,
|
|
434
|
+
v_recipient_id,
|
|
435
|
+
null,
|
|
436
|
+
v_recipient.delivery_mode,
|
|
437
|
+
'message',
|
|
438
|
+
v_message.id,
|
|
439
|
+
null,
|
|
440
|
+
null,
|
|
441
|
+
trim(p_subject),
|
|
442
|
+
v_preview,
|
|
443
|
+
p_priority,
|
|
444
|
+
true,
|
|
445
|
+
false,
|
|
446
|
+
v_fetch_descriptor,
|
|
447
|
+
jsonb_build_object('threadId', p_thread_id::text)
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
v_delivered_count := v_delivered_count + 1;
|
|
451
|
+
v_inbox_count := v_inbox_count + 1;
|
|
452
|
+
v_callback_count := v_callback_count + agent_board._queue_inbox_callbacks(v_inbox.id, 'inbox.item.delivered');
|
|
453
|
+
end loop;
|
|
454
|
+
|
|
455
|
+
return query
|
|
456
|
+
select v_message.id, v_delivered_count, v_inbox_count, v_callback_count, v_message.created_at;
|
|
457
|
+
end;
|
|
458
|
+
$$;
|
|
459
|
+
|
|
460
|
+
create or replace function agent_board.post_board_message(
|
|
461
|
+
p_thread_id uuid,
|
|
462
|
+
p_author_agent_id uuid,
|
|
463
|
+
p_board_id uuid,
|
|
464
|
+
p_subject text,
|
|
465
|
+
p_body text,
|
|
466
|
+
p_message_type text default 'comment',
|
|
467
|
+
p_priority text default 'medium',
|
|
468
|
+
p_idempotency_key text default null,
|
|
469
|
+
p_metadata jsonb default '{}'::jsonb
|
|
470
|
+
)
|
|
471
|
+
returns table(message_id uuid, board_id uuid, delivered_recipient_count integer, callback_outbox_count integer, created_at timestamptz)
|
|
472
|
+
language plpgsql
|
|
473
|
+
security definer
|
|
474
|
+
set search_path = agent_board, public
|
|
475
|
+
as $$
|
|
476
|
+
declare
|
|
477
|
+
v_message agent_board.messages%rowtype;
|
|
478
|
+
v_created_message record;
|
|
479
|
+
v_membership record;
|
|
480
|
+
v_recipient agent_board.delivery_recipients%rowtype;
|
|
481
|
+
v_inbox agent_board.inbox_items%rowtype;
|
|
482
|
+
v_delivered_count integer := 0;
|
|
483
|
+
v_callback_count integer := 0;
|
|
484
|
+
v_metadata jsonb;
|
|
485
|
+
v_preview text;
|
|
486
|
+
v_fetch_descriptor jsonb;
|
|
487
|
+
v_idempotency_key text := nullif(trim(p_idempotency_key), '');
|
|
488
|
+
v_actor_agent_id uuid;
|
|
489
|
+
begin
|
|
490
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_author_agent_id, 'p_author_agent_id');
|
|
491
|
+
|
|
492
|
+
if nullif(trim(p_subject), '') is null or nullif(trim(p_body), '') is null then
|
|
493
|
+
raise exception 'subject and body are required' using errcode = '22023';
|
|
494
|
+
end if;
|
|
495
|
+
if p_priority not in ('low', 'medium', 'high', 'urgent') then
|
|
496
|
+
raise exception 'invalid priority' using errcode = '22023';
|
|
497
|
+
end if;
|
|
498
|
+
if not exists (select 1 from agent_board.threads where id = p_thread_id) then
|
|
499
|
+
raise exception 'thread not found' using errcode = 'P0002';
|
|
500
|
+
end if;
|
|
501
|
+
if not exists (select 1 from agent_board.boards where id = p_board_id) then
|
|
502
|
+
raise exception 'board not found' using errcode = 'P0002';
|
|
503
|
+
end if;
|
|
504
|
+
if not agent_board._current_agent_can_access_thread(p_thread_id) then
|
|
505
|
+
raise exception 'thread not accessible to current agent' using errcode = '42501';
|
|
506
|
+
end if;
|
|
507
|
+
if not agent_board._current_agent_has_board_access(p_board_id) then
|
|
508
|
+
raise exception 'board not accessible to current agent' using errcode = '42501';
|
|
509
|
+
end if;
|
|
510
|
+
|
|
511
|
+
perform agent_board._lock_idempotency_key(
|
|
512
|
+
'post_board_message:' || p_thread_id::text || ':' || v_actor_agent_id::text || ':' || p_board_id::text,
|
|
513
|
+
v_idempotency_key
|
|
514
|
+
);
|
|
515
|
+
|
|
516
|
+
if v_idempotency_key is not null then
|
|
517
|
+
select *
|
|
518
|
+
into v_message
|
|
519
|
+
from agent_board.messages
|
|
520
|
+
where thread_id = p_thread_id
|
|
521
|
+
and author_agent_id = v_actor_agent_id
|
|
522
|
+
and metadata ->> 'rpcName' = 'post_board_message'
|
|
523
|
+
and metadata ->> 'idempotencyKey' = v_idempotency_key
|
|
524
|
+
order by created_at desc
|
|
525
|
+
limit 1;
|
|
526
|
+
end if;
|
|
527
|
+
|
|
528
|
+
if v_message.id is null then
|
|
529
|
+
v_metadata := coalesce(p_metadata, '{}'::jsonb)
|
|
530
|
+
|| jsonb_build_object(
|
|
531
|
+
'rpcName', 'post_board_message',
|
|
532
|
+
'subject', trim(p_subject),
|
|
533
|
+
'priority', p_priority,
|
|
534
|
+
'boardId', p_board_id::text
|
|
535
|
+
);
|
|
536
|
+
if v_idempotency_key is not null then
|
|
537
|
+
v_metadata := v_metadata || jsonb_build_object('idempotencyKey', v_idempotency_key);
|
|
538
|
+
end if;
|
|
539
|
+
|
|
540
|
+
select *
|
|
541
|
+
into v_created_message
|
|
542
|
+
from agent_board.post_message(
|
|
543
|
+
p_thread_id,
|
|
544
|
+
v_actor_agent_id,
|
|
545
|
+
p_body,
|
|
546
|
+
p_message_type,
|
|
547
|
+
null,
|
|
548
|
+
v_metadata
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
select *
|
|
552
|
+
into v_message
|
|
553
|
+
from agent_board.messages
|
|
554
|
+
where id = v_created_message.message_id;
|
|
555
|
+
end if;
|
|
556
|
+
|
|
557
|
+
v_preview := agent_board._trim_inbox_text(p_body, 280);
|
|
558
|
+
v_fetch_descriptor := agent_board._build_fetch_descriptor(
|
|
559
|
+
'board',
|
|
560
|
+
p_board_id,
|
|
561
|
+
'agent_board.v_board_feed',
|
|
562
|
+
'board delivery',
|
|
563
|
+
jsonb_build_object('messageId', v_message.id::text)
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
for v_membership in
|
|
567
|
+
select bm.id, bm.agent_id
|
|
568
|
+
from agent_board.board_memberships bm
|
|
569
|
+
where bm.board_id = p_board_id
|
|
570
|
+
and bm.membership_state in ('joined', 'subscribed')
|
|
571
|
+
order by bm.created_at
|
|
572
|
+
loop
|
|
573
|
+
v_recipient := agent_board._upsert_delivery_recipient(
|
|
574
|
+
'board',
|
|
575
|
+
v_membership.agent_id,
|
|
576
|
+
'message',
|
|
577
|
+
v_message.id,
|
|
578
|
+
null,
|
|
579
|
+
null,
|
|
580
|
+
p_board_id,
|
|
581
|
+
v_membership.id,
|
|
582
|
+
jsonb_build_object('priority', p_priority)
|
|
583
|
+
);
|
|
584
|
+
|
|
585
|
+
v_inbox := agent_board._upsert_inbox_item(
|
|
586
|
+
v_recipient.id,
|
|
587
|
+
v_membership.agent_id,
|
|
588
|
+
p_board_id,
|
|
589
|
+
v_recipient.delivery_mode,
|
|
590
|
+
'message',
|
|
591
|
+
v_message.id,
|
|
592
|
+
null,
|
|
593
|
+
null,
|
|
594
|
+
trim(p_subject),
|
|
595
|
+
v_preview,
|
|
596
|
+
p_priority,
|
|
597
|
+
true,
|
|
598
|
+
true,
|
|
599
|
+
v_fetch_descriptor,
|
|
600
|
+
jsonb_build_object('threadId', p_thread_id::text, 'boardId', p_board_id::text)
|
|
601
|
+
);
|
|
602
|
+
|
|
603
|
+
v_delivered_count := v_delivered_count + 1;
|
|
604
|
+
v_callback_count := v_callback_count + agent_board._queue_inbox_callbacks(v_inbox.id, 'inbox.item.delivered');
|
|
605
|
+
end loop;
|
|
606
|
+
|
|
607
|
+
v_callback_count := v_callback_count + agent_board._queue_board_post_callbacks(
|
|
608
|
+
p_board_id,
|
|
609
|
+
v_message.id,
|
|
610
|
+
trim(p_subject),
|
|
611
|
+
v_preview,
|
|
612
|
+
p_priority,
|
|
613
|
+
v_fetch_descriptor
|
|
614
|
+
);
|
|
615
|
+
|
|
616
|
+
return query
|
|
617
|
+
select v_message.id, p_board_id, v_delivered_count, v_callback_count, v_message.created_at;
|
|
618
|
+
end;
|
|
619
|
+
$$;
|
|
620
|
+
|
|
621
|
+
create or replace function agent_board.create_tasking_delivery(
|
|
622
|
+
p_thread_id uuid,
|
|
623
|
+
p_created_by_agent_id uuid,
|
|
624
|
+
p_title text,
|
|
625
|
+
p_details text default null,
|
|
626
|
+
p_recipient_agent_ids uuid[] default null,
|
|
627
|
+
p_board_id uuid default null,
|
|
628
|
+
p_priority text default 'medium',
|
|
629
|
+
p_orchestration_mode text default 'distributed',
|
|
630
|
+
p_idempotency_key text default null,
|
|
631
|
+
p_metadata jsonb default '{}'::jsonb
|
|
632
|
+
)
|
|
633
|
+
returns table(task_id uuid, created_event_id uuid, delivered_recipient_count integer, inbox_item_count integer, callback_outbox_count integer, created_at timestamptz, updated_at timestamptz)
|
|
634
|
+
language plpgsql
|
|
635
|
+
security definer
|
|
636
|
+
set search_path = agent_board, public
|
|
637
|
+
as $$
|
|
638
|
+
declare
|
|
639
|
+
v_task agent_board.tasks%rowtype;
|
|
640
|
+
v_created_event_id uuid;
|
|
641
|
+
v_created_task record;
|
|
642
|
+
v_recipient_ids uuid[];
|
|
643
|
+
v_recipient_id uuid;
|
|
644
|
+
v_membership record;
|
|
645
|
+
v_recipient agent_board.delivery_recipients%rowtype;
|
|
646
|
+
v_inbox agent_board.inbox_items%rowtype;
|
|
647
|
+
v_delivered_count integer := 0;
|
|
648
|
+
v_inbox_count integer := 0;
|
|
649
|
+
v_callback_count integer := 0;
|
|
650
|
+
v_metadata jsonb;
|
|
651
|
+
v_preview text;
|
|
652
|
+
v_fetch_descriptor jsonb;
|
|
653
|
+
v_idempotency_key text := nullif(trim(p_idempotency_key), '');
|
|
654
|
+
v_actor_agent_id uuid;
|
|
655
|
+
begin
|
|
656
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_created_by_agent_id, 'p_created_by_agent_id');
|
|
657
|
+
|
|
658
|
+
if nullif(trim(p_title), '') is null then
|
|
659
|
+
raise exception 'task title is required' using errcode = '22023';
|
|
660
|
+
end if;
|
|
661
|
+
if p_priority not in ('low', 'medium', 'high', 'urgent') then
|
|
662
|
+
raise exception 'invalid priority' using errcode = '22023';
|
|
663
|
+
end if;
|
|
664
|
+
if p_orchestration_mode not in ('distributed', 'hierarchical', 'hybrid') then
|
|
665
|
+
raise exception 'invalid orchestration mode' using errcode = '22023';
|
|
666
|
+
end if;
|
|
667
|
+
if not exists (select 1 from agent_board.threads where id = p_thread_id) then
|
|
668
|
+
raise exception 'thread not found' using errcode = 'P0002';
|
|
669
|
+
end if;
|
|
670
|
+
if not agent_board._current_agent_can_access_thread(p_thread_id) then
|
|
671
|
+
raise exception 'thread not accessible to current agent' using errcode = '42501';
|
|
672
|
+
end if;
|
|
673
|
+
if (p_recipient_agent_ids is null or cardinality(p_recipient_agent_ids) = 0) and p_board_id is null then
|
|
674
|
+
raise exception 'tasking delivery requires explicit recipients or a board target' using errcode = '22023';
|
|
675
|
+
end if;
|
|
676
|
+
if p_recipient_agent_ids is not null and array_position(p_recipient_agent_ids, null) is not null then
|
|
677
|
+
raise exception 'recipient_agent_ids must not contain nulls' using errcode = '22023';
|
|
678
|
+
end if;
|
|
679
|
+
if p_board_id is not null then
|
|
680
|
+
if not exists (select 1 from agent_board.boards where id = p_board_id) then
|
|
681
|
+
raise exception 'board not found' using errcode = 'P0002';
|
|
682
|
+
end if;
|
|
683
|
+
if not agent_board._current_agent_has_board_access(p_board_id) then
|
|
684
|
+
raise exception 'board not accessible to current agent' using errcode = '42501';
|
|
685
|
+
end if;
|
|
686
|
+
end if;
|
|
687
|
+
|
|
688
|
+
select array_agg(distinct recipient_id)
|
|
689
|
+
into v_recipient_ids
|
|
690
|
+
from unnest(coalesce(p_recipient_agent_ids, '{}'::uuid[])) as recipient_id;
|
|
691
|
+
|
|
692
|
+
if v_recipient_ids is not null and (
|
|
693
|
+
select count(*)
|
|
694
|
+
from agent_board.agents
|
|
695
|
+
where id = any(v_recipient_ids)
|
|
696
|
+
) <> cardinality(v_recipient_ids) then
|
|
697
|
+
raise exception 'recipient agent not found' using errcode = 'P0002';
|
|
698
|
+
end if;
|
|
699
|
+
|
|
700
|
+
perform agent_board._lock_idempotency_key(
|
|
701
|
+
'create_tasking_delivery:' || p_thread_id::text || ':' || v_actor_agent_id::text,
|
|
702
|
+
v_idempotency_key
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
if v_idempotency_key is not null then
|
|
706
|
+
select *
|
|
707
|
+
into v_task
|
|
708
|
+
from agent_board.tasks
|
|
709
|
+
where thread_id = p_thread_id
|
|
710
|
+
and created_by_agent_id = v_actor_agent_id
|
|
711
|
+
and metadata ->> 'rpcName' = 'create_tasking_delivery'
|
|
712
|
+
and metadata ->> 'idempotencyKey' = v_idempotency_key
|
|
713
|
+
order by created_at desc
|
|
714
|
+
limit 1;
|
|
715
|
+
end if;
|
|
716
|
+
|
|
717
|
+
if v_task.id is null then
|
|
718
|
+
v_metadata := coalesce(p_metadata, '{}'::jsonb)
|
|
719
|
+
|| jsonb_build_object(
|
|
720
|
+
'rpcName', 'create_tasking_delivery',
|
|
721
|
+
'priority', p_priority
|
|
722
|
+
);
|
|
723
|
+
if p_board_id is not null then
|
|
724
|
+
v_metadata := v_metadata || jsonb_build_object('boardId', p_board_id::text);
|
|
725
|
+
end if;
|
|
726
|
+
if v_idempotency_key is not null then
|
|
727
|
+
v_metadata := v_metadata || jsonb_build_object('idempotencyKey', v_idempotency_key);
|
|
728
|
+
end if;
|
|
729
|
+
|
|
730
|
+
select *
|
|
731
|
+
into v_created_task
|
|
732
|
+
from agent_board.create_task(
|
|
733
|
+
p_thread_id,
|
|
734
|
+
v_actor_agent_id,
|
|
735
|
+
trim(p_title),
|
|
736
|
+
p_details,
|
|
737
|
+
null,
|
|
738
|
+
null,
|
|
739
|
+
p_priority,
|
|
740
|
+
p_orchestration_mode,
|
|
741
|
+
v_metadata
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
v_created_event_id := v_created_task.created_event_id;
|
|
745
|
+
|
|
746
|
+
select *
|
|
747
|
+
into v_task
|
|
748
|
+
from agent_board.tasks
|
|
749
|
+
where id = v_created_task.task_id;
|
|
750
|
+
else
|
|
751
|
+
select te.id
|
|
752
|
+
into v_created_event_id
|
|
753
|
+
from agent_board.task_events te
|
|
754
|
+
where te.task_id = v_task.id
|
|
755
|
+
and te.event_sequence = 1;
|
|
756
|
+
end if;
|
|
757
|
+
|
|
758
|
+
v_preview := agent_board._trim_inbox_text(coalesce(p_details, p_title), 280);
|
|
759
|
+
v_fetch_descriptor := agent_board._build_fetch_descriptor(
|
|
760
|
+
'task',
|
|
761
|
+
v_task.id,
|
|
762
|
+
'agent_board.v_task_tree',
|
|
763
|
+
'tasking delivery',
|
|
764
|
+
jsonb_build_object('threadId', p_thread_id::text)
|
|
765
|
+
);
|
|
766
|
+
|
|
767
|
+
if v_recipient_ids is not null then
|
|
768
|
+
foreach v_recipient_id in array v_recipient_ids loop
|
|
769
|
+
v_recipient := agent_board._upsert_delivery_recipient(
|
|
770
|
+
'tasking',
|
|
771
|
+
v_recipient_id,
|
|
772
|
+
'task',
|
|
773
|
+
null,
|
|
774
|
+
v_task.id,
|
|
775
|
+
null,
|
|
776
|
+
null,
|
|
777
|
+
null,
|
|
778
|
+
jsonb_build_object('priority', p_priority)
|
|
779
|
+
);
|
|
780
|
+
|
|
781
|
+
v_inbox := agent_board._upsert_inbox_item(
|
|
782
|
+
v_recipient.id,
|
|
783
|
+
v_recipient_id,
|
|
784
|
+
null,
|
|
785
|
+
v_recipient.delivery_mode,
|
|
786
|
+
'task',
|
|
787
|
+
null,
|
|
788
|
+
v_task.id,
|
|
789
|
+
null,
|
|
790
|
+
trim(p_title),
|
|
791
|
+
v_preview,
|
|
792
|
+
p_priority,
|
|
793
|
+
true,
|
|
794
|
+
false,
|
|
795
|
+
v_fetch_descriptor,
|
|
796
|
+
jsonb_build_object('threadId', p_thread_id::text)
|
|
797
|
+
);
|
|
798
|
+
|
|
799
|
+
v_delivered_count := v_delivered_count + 1;
|
|
800
|
+
v_inbox_count := v_inbox_count + 1;
|
|
801
|
+
v_callback_count := v_callback_count + agent_board._queue_inbox_callbacks(v_inbox.id, 'inbox.item.delivered');
|
|
802
|
+
end loop;
|
|
803
|
+
end if;
|
|
804
|
+
|
|
805
|
+
if p_board_id is not null then
|
|
806
|
+
for v_membership in
|
|
807
|
+
select bm.id, bm.agent_id
|
|
808
|
+
from agent_board.board_memberships bm
|
|
809
|
+
where bm.board_id = p_board_id
|
|
810
|
+
and bm.membership_state in ('joined', 'subscribed')
|
|
811
|
+
order by bm.created_at
|
|
812
|
+
loop
|
|
813
|
+
v_recipient := agent_board._upsert_delivery_recipient(
|
|
814
|
+
'tasking',
|
|
815
|
+
v_membership.agent_id,
|
|
816
|
+
'task',
|
|
817
|
+
null,
|
|
818
|
+
v_task.id,
|
|
819
|
+
null,
|
|
820
|
+
p_board_id,
|
|
821
|
+
v_membership.id,
|
|
822
|
+
jsonb_build_object('priority', p_priority)
|
|
823
|
+
);
|
|
824
|
+
|
|
825
|
+
v_inbox := agent_board._upsert_inbox_item(
|
|
826
|
+
v_recipient.id,
|
|
827
|
+
v_membership.agent_id,
|
|
828
|
+
v_recipient.board_id,
|
|
829
|
+
v_recipient.delivery_mode,
|
|
830
|
+
'task',
|
|
831
|
+
null,
|
|
832
|
+
v_task.id,
|
|
833
|
+
null,
|
|
834
|
+
trim(p_title),
|
|
835
|
+
v_preview,
|
|
836
|
+
p_priority,
|
|
837
|
+
true,
|
|
838
|
+
v_recipient.board_id is not null,
|
|
839
|
+
v_fetch_descriptor,
|
|
840
|
+
jsonb_build_object('threadId', p_thread_id::text, 'boardId', p_board_id::text)
|
|
841
|
+
);
|
|
842
|
+
|
|
843
|
+
v_delivered_count := v_delivered_count + 1;
|
|
844
|
+
v_inbox_count := v_inbox_count + 1;
|
|
845
|
+
v_callback_count := v_callback_count + agent_board._queue_inbox_callbacks(v_inbox.id, 'inbox.item.delivered');
|
|
846
|
+
end loop;
|
|
847
|
+
end if;
|
|
848
|
+
|
|
849
|
+
return query
|
|
850
|
+
select v_task.id, v_created_event_id, v_delivered_count, v_inbox_count, v_callback_count, v_task.created_at, v_task.updated_at;
|
|
851
|
+
end;
|
|
852
|
+
$$;
|
|
853
|
+
|
|
854
|
+
create or replace function agent_board.update_inbox_item_state(
|
|
855
|
+
p_inbox_item_id uuid,
|
|
856
|
+
p_recipient_agent_id uuid,
|
|
857
|
+
p_action_state text,
|
|
858
|
+
p_metadata jsonb default '{}'::jsonb
|
|
859
|
+
)
|
|
860
|
+
returns table(inbox_item_id uuid, recipient_agent_id uuid, action_state text, callback_outbox_count integer, updated_at timestamptz)
|
|
861
|
+
language plpgsql
|
|
862
|
+
security definer
|
|
863
|
+
set search_path = agent_board, public
|
|
864
|
+
as $$
|
|
865
|
+
declare
|
|
866
|
+
v_inbox agent_board.inbox_items%rowtype;
|
|
867
|
+
v_callback_count integer := 0;
|
|
868
|
+
v_actor_agent_id uuid;
|
|
869
|
+
begin
|
|
870
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_recipient_agent_id, 'p_recipient_agent_id');
|
|
871
|
+
|
|
872
|
+
if p_action_state not in ('new', 'read', 'acknowledged', 'deferred', 'dismissed', 'restored') then
|
|
873
|
+
raise exception 'invalid inbox action state' using errcode = '22023';
|
|
874
|
+
end if;
|
|
875
|
+
|
|
876
|
+
update agent_board.inbox_items ii
|
|
877
|
+
set action_state = p_action_state,
|
|
878
|
+
metadata = coalesce(ii.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
879
|
+
updated_at = now()
|
|
880
|
+
where ii.id = p_inbox_item_id
|
|
881
|
+
and ii.recipient_agent_id = v_actor_agent_id
|
|
882
|
+
returning * into v_inbox;
|
|
883
|
+
|
|
884
|
+
if v_inbox.id is null then
|
|
885
|
+
raise exception 'inbox item not found' using errcode = 'P0002';
|
|
886
|
+
end if;
|
|
887
|
+
|
|
888
|
+
v_callback_count := agent_board._queue_inbox_callbacks(v_inbox.id, 'inbox.item.updated');
|
|
889
|
+
|
|
890
|
+
return query
|
|
891
|
+
select v_inbox.id, v_inbox.recipient_agent_id, v_inbox.action_state, v_callback_count, v_inbox.updated_at;
|
|
892
|
+
end;
|
|
893
|
+
$$;
|
|
894
|
+
|
|
895
|
+
create or replace function agent_board.register_callback_endpoint(
|
|
896
|
+
p_owner_agent_id uuid,
|
|
897
|
+
p_endpoint_url text,
|
|
898
|
+
p_metadata jsonb default '{}'::jsonb
|
|
899
|
+
)
|
|
900
|
+
returns table(endpoint_id uuid, owner_agent_id uuid, endpoint_status text, signing_key_version integer, verification_requested_at timestamptz, updated_at timestamptz)
|
|
901
|
+
language plpgsql
|
|
902
|
+
security definer
|
|
903
|
+
set search_path = agent_board, public
|
|
904
|
+
as $$
|
|
905
|
+
declare
|
|
906
|
+
v_actor_agent_id uuid;
|
|
907
|
+
begin
|
|
908
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_owner_agent_id, 'p_owner_agent_id');
|
|
909
|
+
|
|
910
|
+
if nullif(trim(p_endpoint_url), '') is null or trim(p_endpoint_url) !~ '^https://.+$' then
|
|
911
|
+
raise exception 'callback endpoint URL must be https' using errcode = '22023';
|
|
912
|
+
end if;
|
|
913
|
+
|
|
914
|
+
return query
|
|
915
|
+
insert into agent_board.callback_endpoints as ce(
|
|
916
|
+
owner_agent_id,
|
|
917
|
+
endpoint_url,
|
|
918
|
+
endpoint_status,
|
|
919
|
+
verification_requested_at,
|
|
920
|
+
verified_at,
|
|
921
|
+
disabled_at,
|
|
922
|
+
disabled_reason,
|
|
923
|
+
metadata
|
|
924
|
+
)
|
|
925
|
+
values (
|
|
926
|
+
v_actor_agent_id,
|
|
927
|
+
trim(p_endpoint_url),
|
|
928
|
+
'pending_verification',
|
|
929
|
+
now(),
|
|
930
|
+
null,
|
|
931
|
+
null,
|
|
932
|
+
null,
|
|
933
|
+
coalesce(p_metadata, '{}'::jsonb)
|
|
934
|
+
)
|
|
935
|
+
on conflict on constraint callback_endpoints_url_unique do update
|
|
936
|
+
set endpoint_status = 'pending_verification',
|
|
937
|
+
verification_requested_at = now(),
|
|
938
|
+
verified_at = null,
|
|
939
|
+
disabled_at = null,
|
|
940
|
+
disabled_reason = null,
|
|
941
|
+
metadata = coalesce(ce.metadata, '{}'::jsonb) || coalesce(excluded.metadata, '{}'::jsonb),
|
|
942
|
+
updated_at = now()
|
|
943
|
+
returning ce.id, ce.owner_agent_id, ce.endpoint_status, ce.signing_key_version, ce.verification_requested_at, ce.updated_at;
|
|
944
|
+
end;
|
|
945
|
+
$$;
|
|
946
|
+
|
|
947
|
+
create or replace function agent_board.verify_callback_endpoint(
|
|
948
|
+
p_endpoint_id uuid,
|
|
949
|
+
p_owner_agent_id uuid,
|
|
950
|
+
p_metadata jsonb default '{}'::jsonb
|
|
951
|
+
)
|
|
952
|
+
returns table(endpoint_id uuid, owner_agent_id uuid, endpoint_status text, verified_at timestamptz, updated_at timestamptz)
|
|
953
|
+
language plpgsql
|
|
954
|
+
security definer
|
|
955
|
+
set search_path = agent_board, public
|
|
956
|
+
as $$
|
|
957
|
+
declare
|
|
958
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
959
|
+
v_actor_agent_id uuid;
|
|
960
|
+
begin
|
|
961
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_owner_agent_id, 'p_owner_agent_id');
|
|
962
|
+
v_endpoint := agent_board._owned_callback_endpoint(p_endpoint_id, v_actor_agent_id);
|
|
963
|
+
|
|
964
|
+
update agent_board.callback_endpoints ce
|
|
965
|
+
set endpoint_status = 'verified',
|
|
966
|
+
verified_at = now(),
|
|
967
|
+
disabled_at = null,
|
|
968
|
+
disabled_reason = null,
|
|
969
|
+
metadata = coalesce(ce.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
970
|
+
updated_at = now()
|
|
971
|
+
where ce.id = v_endpoint.id
|
|
972
|
+
returning * into v_endpoint;
|
|
973
|
+
|
|
974
|
+
return query
|
|
975
|
+
select v_endpoint.id, v_endpoint.owner_agent_id, v_endpoint.endpoint_status, v_endpoint.verified_at, v_endpoint.updated_at;
|
|
976
|
+
end;
|
|
977
|
+
$$;
|
|
978
|
+
|
|
979
|
+
create or replace function agent_board.disable_callback_endpoint(
|
|
980
|
+
p_endpoint_id uuid,
|
|
981
|
+
p_owner_agent_id uuid,
|
|
982
|
+
p_disabled_reason text default null,
|
|
983
|
+
p_metadata jsonb default '{}'::jsonb
|
|
984
|
+
)
|
|
985
|
+
returns table(endpoint_id uuid, owner_agent_id uuid, endpoint_status text, disabled_at timestamptz, updated_at timestamptz)
|
|
986
|
+
language plpgsql
|
|
987
|
+
security definer
|
|
988
|
+
set search_path = agent_board, public
|
|
989
|
+
as $$
|
|
990
|
+
declare
|
|
991
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
992
|
+
v_actor_agent_id uuid;
|
|
993
|
+
begin
|
|
994
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_owner_agent_id, 'p_owner_agent_id');
|
|
995
|
+
v_endpoint := agent_board._owned_callback_endpoint(p_endpoint_id, v_actor_agent_id);
|
|
996
|
+
|
|
997
|
+
update agent_board.callback_endpoints ce
|
|
998
|
+
set endpoint_status = 'disabled',
|
|
999
|
+
disabled_at = now(),
|
|
1000
|
+
disabled_reason = nullif(trim(p_disabled_reason), ''),
|
|
1001
|
+
metadata = coalesce(ce.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
1002
|
+
updated_at = now()
|
|
1003
|
+
where ce.id = v_endpoint.id
|
|
1004
|
+
returning * into v_endpoint;
|
|
1005
|
+
|
|
1006
|
+
update agent_board.callback_subscriptions cs
|
|
1007
|
+
set subscription_status = 'disabled',
|
|
1008
|
+
disabled_at = now(),
|
|
1009
|
+
updated_at = now()
|
|
1010
|
+
where cs.endpoint_id = v_endpoint.id
|
|
1011
|
+
and cs.subscription_status = 'active';
|
|
1012
|
+
|
|
1013
|
+
return query
|
|
1014
|
+
select v_endpoint.id, v_endpoint.owner_agent_id, v_endpoint.endpoint_status, v_endpoint.disabled_at, v_endpoint.updated_at;
|
|
1015
|
+
end;
|
|
1016
|
+
$$;
|
|
1017
|
+
|
|
1018
|
+
create or replace function agent_board.rotate_callback_signing_key(
|
|
1019
|
+
p_endpoint_id uuid,
|
|
1020
|
+
p_owner_agent_id uuid,
|
|
1021
|
+
p_metadata jsonb default '{}'::jsonb
|
|
1022
|
+
)
|
|
1023
|
+
returns table(endpoint_id uuid, owner_agent_id uuid, signing_key_version integer, endpoint_status text, verification_requested_at timestamptz, updated_at timestamptz)
|
|
1024
|
+
language plpgsql
|
|
1025
|
+
security definer
|
|
1026
|
+
set search_path = agent_board, public
|
|
1027
|
+
as $$
|
|
1028
|
+
declare
|
|
1029
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
1030
|
+
v_actor_agent_id uuid;
|
|
1031
|
+
begin
|
|
1032
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_owner_agent_id, 'p_owner_agent_id');
|
|
1033
|
+
v_endpoint := agent_board._owned_callback_endpoint(p_endpoint_id, v_actor_agent_id);
|
|
1034
|
+
|
|
1035
|
+
update agent_board.callback_endpoints ce
|
|
1036
|
+
set signing_key_version = ce.signing_key_version + 1,
|
|
1037
|
+
endpoint_status = 'pending_verification',
|
|
1038
|
+
verification_requested_at = now(),
|
|
1039
|
+
verified_at = null,
|
|
1040
|
+
disabled_at = null,
|
|
1041
|
+
disabled_reason = null,
|
|
1042
|
+
metadata = coalesce(ce.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
1043
|
+
updated_at = now()
|
|
1044
|
+
where ce.id = v_endpoint.id
|
|
1045
|
+
returning * into v_endpoint;
|
|
1046
|
+
|
|
1047
|
+
return query
|
|
1048
|
+
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;
|
|
1049
|
+
end;
|
|
1050
|
+
$$;
|
|
1051
|
+
|
|
1052
|
+
create or replace function agent_board.delete_callback_endpoint(
|
|
1053
|
+
p_endpoint_id uuid,
|
|
1054
|
+
p_owner_agent_id uuid
|
|
1055
|
+
)
|
|
1056
|
+
returns table(endpoint_id uuid, owner_agent_id uuid, deleted boolean)
|
|
1057
|
+
language plpgsql
|
|
1058
|
+
security definer
|
|
1059
|
+
set search_path = agent_board, public
|
|
1060
|
+
as $$
|
|
1061
|
+
declare
|
|
1062
|
+
v_endpoint_id uuid;
|
|
1063
|
+
v_actor_agent_id uuid;
|
|
1064
|
+
begin
|
|
1065
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_owner_agent_id, 'p_owner_agent_id');
|
|
1066
|
+
|
|
1067
|
+
delete from agent_board.callback_endpoints ce
|
|
1068
|
+
where ce.id = p_endpoint_id
|
|
1069
|
+
and ce.owner_agent_id = v_actor_agent_id
|
|
1070
|
+
returning id into v_endpoint_id;
|
|
1071
|
+
|
|
1072
|
+
if v_endpoint_id is null then
|
|
1073
|
+
raise exception 'callback endpoint not found' using errcode = 'P0002';
|
|
1074
|
+
end if;
|
|
1075
|
+
|
|
1076
|
+
return query
|
|
1077
|
+
select v_endpoint_id, v_actor_agent_id, true;
|
|
1078
|
+
end;
|
|
1079
|
+
$$;
|
|
1080
|
+
|
|
1081
|
+
create or replace function agent_board.subscribe_callback_endpoint(
|
|
1082
|
+
p_endpoint_id uuid,
|
|
1083
|
+
p_agent_id uuid,
|
|
1084
|
+
p_subscription_scope text,
|
|
1085
|
+
p_event_category text,
|
|
1086
|
+
p_board_id uuid default null,
|
|
1087
|
+
p_metadata jsonb default '{}'::jsonb
|
|
1088
|
+
)
|
|
1089
|
+
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)
|
|
1090
|
+
language plpgsql
|
|
1091
|
+
security definer
|
|
1092
|
+
set search_path = agent_board, public
|
|
1093
|
+
as $$
|
|
1094
|
+
declare
|
|
1095
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
1096
|
+
v_subscription agent_board.callback_subscriptions%rowtype;
|
|
1097
|
+
v_board_membership_id uuid;
|
|
1098
|
+
v_actor_agent_id uuid;
|
|
1099
|
+
begin
|
|
1100
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_agent_id, 'p_agent_id');
|
|
1101
|
+
v_endpoint := agent_board._owned_callback_endpoint(p_endpoint_id, v_actor_agent_id);
|
|
1102
|
+
|
|
1103
|
+
if p_subscription_scope = 'own_inbox' then
|
|
1104
|
+
if p_event_category not in ('inbox.item.delivered', 'inbox.item.updated') or p_board_id is not null then
|
|
1105
|
+
raise exception 'invalid own_inbox subscription shape' using errcode = '22023';
|
|
1106
|
+
end if;
|
|
1107
|
+
elsif p_subscription_scope = 'board' then
|
|
1108
|
+
if p_event_category not in ('board.post.delivered', 'board.post.updated') or p_board_id is null then
|
|
1109
|
+
raise exception 'invalid board subscription shape' using errcode = '22023';
|
|
1110
|
+
end if;
|
|
1111
|
+
v_board_membership_id := agent_board._active_board_membership_id(p_board_id, v_actor_agent_id);
|
|
1112
|
+
if v_board_membership_id is null then
|
|
1113
|
+
raise exception 'board membership not found' using errcode = 'P0002';
|
|
1114
|
+
end if;
|
|
1115
|
+
else
|
|
1116
|
+
raise exception 'invalid subscription scope' using errcode = '22023';
|
|
1117
|
+
end if;
|
|
1118
|
+
|
|
1119
|
+
select *
|
|
1120
|
+
into v_subscription
|
|
1121
|
+
from agent_board.callback_subscriptions cs
|
|
1122
|
+
where cs.endpoint_id = p_endpoint_id
|
|
1123
|
+
and cs.agent_id = v_actor_agent_id
|
|
1124
|
+
and cs.subscription_scope = p_subscription_scope
|
|
1125
|
+
and cs.event_category = p_event_category
|
|
1126
|
+
and coalesce(cs.board_id, '00000000-0000-0000-0000-000000000000'::uuid) = coalesce(p_board_id, '00000000-0000-0000-0000-000000000000'::uuid)
|
|
1127
|
+
order by cs.created_at desc
|
|
1128
|
+
limit 1
|
|
1129
|
+
for update;
|
|
1130
|
+
|
|
1131
|
+
if v_subscription.id is null then
|
|
1132
|
+
insert into agent_board.callback_subscriptions(
|
|
1133
|
+
endpoint_id,
|
|
1134
|
+
agent_id,
|
|
1135
|
+
subscription_scope,
|
|
1136
|
+
event_category,
|
|
1137
|
+
board_id,
|
|
1138
|
+
board_membership_id,
|
|
1139
|
+
metadata
|
|
1140
|
+
)
|
|
1141
|
+
values (
|
|
1142
|
+
v_endpoint.id,
|
|
1143
|
+
v_actor_agent_id,
|
|
1144
|
+
p_subscription_scope,
|
|
1145
|
+
p_event_category,
|
|
1146
|
+
p_board_id,
|
|
1147
|
+
v_board_membership_id,
|
|
1148
|
+
coalesce(p_metadata, '{}'::jsonb)
|
|
1149
|
+
)
|
|
1150
|
+
returning * into v_subscription;
|
|
1151
|
+
else
|
|
1152
|
+
update agent_board.callback_subscriptions
|
|
1153
|
+
set subscription_status = 'active',
|
|
1154
|
+
disabled_at = null,
|
|
1155
|
+
board_membership_id = v_board_membership_id,
|
|
1156
|
+
metadata = coalesce(callback_subscriptions.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
1157
|
+
updated_at = now()
|
|
1158
|
+
where id = v_subscription.id
|
|
1159
|
+
returning * into v_subscription;
|
|
1160
|
+
end if;
|
|
1161
|
+
|
|
1162
|
+
return query
|
|
1163
|
+
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;
|
|
1164
|
+
end;
|
|
1165
|
+
$$;
|
|
1166
|
+
|
|
1167
|
+
create or replace function agent_board.unsubscribe_callback_endpoint(
|
|
1168
|
+
p_endpoint_id uuid,
|
|
1169
|
+
p_agent_id uuid,
|
|
1170
|
+
p_subscription_scope text,
|
|
1171
|
+
p_event_category text,
|
|
1172
|
+
p_board_id uuid default null,
|
|
1173
|
+
p_metadata jsonb default '{}'::jsonb
|
|
1174
|
+
)
|
|
1175
|
+
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)
|
|
1176
|
+
language plpgsql
|
|
1177
|
+
security definer
|
|
1178
|
+
set search_path = agent_board, public
|
|
1179
|
+
as $$
|
|
1180
|
+
declare
|
|
1181
|
+
v_endpoint agent_board.callback_endpoints%rowtype;
|
|
1182
|
+
v_subscription agent_board.callback_subscriptions%rowtype;
|
|
1183
|
+
v_actor_agent_id uuid;
|
|
1184
|
+
begin
|
|
1185
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_agent_id, 'p_agent_id');
|
|
1186
|
+
v_endpoint := agent_board._owned_callback_endpoint(p_endpoint_id, v_actor_agent_id);
|
|
1187
|
+
|
|
1188
|
+
update agent_board.callback_subscriptions cs
|
|
1189
|
+
set subscription_status = 'disabled',
|
|
1190
|
+
disabled_at = now(),
|
|
1191
|
+
metadata = coalesce(cs.metadata, '{}'::jsonb) || coalesce(p_metadata, '{}'::jsonb),
|
|
1192
|
+
updated_at = now()
|
|
1193
|
+
where cs.endpoint_id = v_endpoint.id
|
|
1194
|
+
and cs.agent_id = v_actor_agent_id
|
|
1195
|
+
and cs.subscription_scope = p_subscription_scope
|
|
1196
|
+
and cs.event_category = p_event_category
|
|
1197
|
+
and coalesce(cs.board_id, '00000000-0000-0000-0000-000000000000'::uuid) = coalesce(p_board_id, '00000000-0000-0000-0000-000000000000'::uuid)
|
|
1198
|
+
and cs.subscription_status = 'active'
|
|
1199
|
+
returning * into v_subscription;
|
|
1200
|
+
|
|
1201
|
+
if v_subscription.id is null then
|
|
1202
|
+
raise exception 'callback subscription not found' using errcode = 'P0002';
|
|
1203
|
+
end if;
|
|
1204
|
+
|
|
1205
|
+
return query
|
|
1206
|
+
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;
|
|
1207
|
+
end;
|
|
1208
|
+
$$;
|
|
1209
|
+
|
|
1210
|
+
revoke all on function agent_board.create_board(uuid, text, text, text, jsonb) from public, anon;
|
|
1211
|
+
revoke all on function agent_board.join_board(uuid, uuid, text, uuid, jsonb) from public, anon;
|
|
1212
|
+
revoke all on function agent_board.update_board_membership(uuid, uuid, text, jsonb) from public, anon;
|
|
1213
|
+
revoke all on function agent_board.leave_board(uuid, uuid, jsonb) from public, anon;
|
|
1214
|
+
revoke all on function agent_board.send_direct_message(uuid, uuid, uuid, text, text, text, text, text, jsonb) from public, anon;
|
|
1215
|
+
revoke all on function agent_board.send_multicast_message(uuid, uuid, uuid[], text, text, text, text, text, jsonb) from public, anon;
|
|
1216
|
+
revoke all on function agent_board.post_board_message(uuid, uuid, uuid, text, text, text, text, text, jsonb) from public, anon;
|
|
1217
|
+
revoke all on function agent_board.create_tasking_delivery(uuid, uuid, text, text, uuid[], uuid, text, text, text, jsonb) from public, anon;
|
|
1218
|
+
revoke all on function agent_board.update_inbox_item_state(uuid, uuid, text, jsonb) from public, anon;
|
|
1219
|
+
revoke all on function agent_board.register_callback_endpoint(uuid, text, jsonb) from public, anon;
|
|
1220
|
+
revoke all on function agent_board.verify_callback_endpoint(uuid, uuid, jsonb) from public, anon;
|
|
1221
|
+
revoke all on function agent_board.disable_callback_endpoint(uuid, uuid, text, jsonb) from public, anon;
|
|
1222
|
+
revoke all on function agent_board.rotate_callback_signing_key(uuid, uuid, jsonb) from public, anon;
|
|
1223
|
+
revoke all on function agent_board.delete_callback_endpoint(uuid, uuid) from public, anon;
|
|
1224
|
+
revoke all on function agent_board.subscribe_callback_endpoint(uuid, uuid, text, text, uuid, jsonb) from public, anon;
|
|
1225
|
+
revoke all on function agent_board.unsubscribe_callback_endpoint(uuid, uuid, text, text, uuid, jsonb) from public, anon;
|
|
1226
|
+
|
|
1227
|
+
grant execute on all functions in schema agent_board to service_role;
|
|
1228
|
+
grant execute on function agent_board.create_board(uuid, text, text, text, jsonb) to authenticated;
|
|
1229
|
+
grant execute on function agent_board.join_board(uuid, uuid, text, uuid, jsonb) to authenticated;
|
|
1230
|
+
grant execute on function agent_board.update_board_membership(uuid, uuid, text, jsonb) to authenticated;
|
|
1231
|
+
grant execute on function agent_board.leave_board(uuid, uuid, jsonb) to authenticated;
|
|
1232
|
+
grant execute on function agent_board.send_direct_message(uuid, uuid, uuid, text, text, text, text, text, jsonb) to authenticated;
|
|
1233
|
+
grant execute on function agent_board.send_multicast_message(uuid, uuid, uuid[], text, text, text, text, text, jsonb) to authenticated;
|
|
1234
|
+
grant execute on function agent_board.post_board_message(uuid, uuid, uuid, text, text, text, text, text, jsonb) to authenticated;
|
|
1235
|
+
grant execute on function agent_board.create_tasking_delivery(uuid, uuid, text, text, uuid[], uuid, text, text, text, jsonb) to authenticated;
|
|
1236
|
+
grant execute on function agent_board.update_inbox_item_state(uuid, uuid, text, jsonb) to authenticated;
|
|
1237
|
+
grant execute on function agent_board.register_callback_endpoint(uuid, text, jsonb) to authenticated;
|
|
1238
|
+
grant execute on function agent_board.verify_callback_endpoint(uuid, uuid, jsonb) to authenticated;
|
|
1239
|
+
grant execute on function agent_board.disable_callback_endpoint(uuid, uuid, text, jsonb) to authenticated;
|
|
1240
|
+
grant execute on function agent_board.rotate_callback_signing_key(uuid, uuid, jsonb) to authenticated;
|
|
1241
|
+
grant execute on function agent_board.delete_callback_endpoint(uuid, uuid) to authenticated;
|
|
1242
|
+
grant execute on function agent_board.subscribe_callback_endpoint(uuid, uuid, text, text, uuid, jsonb) to authenticated;
|
|
1243
|
+
grant execute on function agent_board.unsubscribe_callback_endpoint(uuid, uuid, text, text, uuid, jsonb) to authenticated;
|