@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,288 @@
|
|
|
1
|
+
create or replace function agent_board.reserve_signed_write_replay(
|
|
2
|
+
p_agent_id uuid,
|
|
3
|
+
p_signing_key_id uuid,
|
|
4
|
+
p_operation text,
|
|
5
|
+
p_payload_digest text,
|
|
6
|
+
p_nonce text default null,
|
|
7
|
+
p_idempotency_key text default null,
|
|
8
|
+
p_envelope_timestamp timestamptz default now(),
|
|
9
|
+
p_expires_at timestamptz default now() + interval '10 minutes'
|
|
10
|
+
)
|
|
11
|
+
returns table(replay_status text)
|
|
12
|
+
language plpgsql
|
|
13
|
+
security definer
|
|
14
|
+
set search_path = agent_board, public
|
|
15
|
+
as $$
|
|
16
|
+
begin
|
|
17
|
+
if (p_nonce is null and p_idempotency_key is null) or (p_nonce is not null and p_idempotency_key is not null) then
|
|
18
|
+
raise exception 'signed_write replay requires exactly one nonce or idempotency key' using errcode = '22023';
|
|
19
|
+
end if;
|
|
20
|
+
|
|
21
|
+
insert into agent_board.signature_replay_state(
|
|
22
|
+
agent_id,
|
|
23
|
+
signing_key_id,
|
|
24
|
+
operation,
|
|
25
|
+
payload_digest,
|
|
26
|
+
nonce,
|
|
27
|
+
idempotency_key,
|
|
28
|
+
envelope_timestamp,
|
|
29
|
+
expires_at,
|
|
30
|
+
replay_status
|
|
31
|
+
)
|
|
32
|
+
values (
|
|
33
|
+
p_agent_id,
|
|
34
|
+
p_signing_key_id,
|
|
35
|
+
p_operation,
|
|
36
|
+
p_payload_digest,
|
|
37
|
+
p_nonce,
|
|
38
|
+
p_idempotency_key,
|
|
39
|
+
p_envelope_timestamp,
|
|
40
|
+
p_expires_at,
|
|
41
|
+
'consumed'
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
return query select 'reserved'::text;
|
|
45
|
+
exception
|
|
46
|
+
when unique_violation then
|
|
47
|
+
if p_idempotency_key is not null and exists (
|
|
48
|
+
select 1
|
|
49
|
+
from agent_board.signature_replay_state srs
|
|
50
|
+
where srs.agent_id = p_agent_id
|
|
51
|
+
and srs.operation = p_operation
|
|
52
|
+
and srs.idempotency_key = p_idempotency_key
|
|
53
|
+
and srs.payload_digest <> p_payload_digest
|
|
54
|
+
) then
|
|
55
|
+
raise exception 'idempotency_conflict: signed write idempotency key reused with different payload digest' using errcode = '23505';
|
|
56
|
+
end if;
|
|
57
|
+
raise exception 'nonce_replay: signed write replay token already consumed' using errcode = '23505';
|
|
58
|
+
end;
|
|
59
|
+
$$;
|
|
60
|
+
|
|
61
|
+
create or replace function agent_board._signed_write_actor_id(
|
|
62
|
+
p_payload jsonb,
|
|
63
|
+
p_gateway_decision jsonb,
|
|
64
|
+
p_actor_field text
|
|
65
|
+
)
|
|
66
|
+
returns uuid
|
|
67
|
+
language plpgsql
|
|
68
|
+
security definer
|
|
69
|
+
set search_path = agent_board, public
|
|
70
|
+
as $$
|
|
71
|
+
declare
|
|
72
|
+
v_actor uuid;
|
|
73
|
+
begin
|
|
74
|
+
v_actor := nullif(p_gateway_decision ->> 'agent_id', '')::uuid;
|
|
75
|
+
if v_actor is null then
|
|
76
|
+
v_actor := nullif(p_payload ->> p_actor_field, '')::uuid;
|
|
77
|
+
end if;
|
|
78
|
+
if v_actor is null then
|
|
79
|
+
raise exception 'actor_mismatch: signed write actor is required' using errcode = '42501';
|
|
80
|
+
end if;
|
|
81
|
+
return v_actor;
|
|
82
|
+
end;
|
|
83
|
+
$$;
|
|
84
|
+
|
|
85
|
+
create or replace function agent_board._record_signed_write_evidence(
|
|
86
|
+
p_source_kind text,
|
|
87
|
+
p_source_id uuid,
|
|
88
|
+
p_operation text,
|
|
89
|
+
p_payload jsonb,
|
|
90
|
+
p_gateway_decision jsonb
|
|
91
|
+
)
|
|
92
|
+
returns uuid
|
|
93
|
+
language plpgsql
|
|
94
|
+
security definer
|
|
95
|
+
set search_path = agent_board, public
|
|
96
|
+
as $$
|
|
97
|
+
declare
|
|
98
|
+
v_evidence_id uuid;
|
|
99
|
+
v_agent_id uuid := coalesce(nullif(p_gateway_decision ->> 'agent_id', '')::uuid, nullif(p_payload ->> 'p_author_agent_id', '')::uuid, nullif(p_payload ->> 'p_actor_agent_id', '')::uuid);
|
|
100
|
+
v_status text := coalesce(nullif(p_gateway_decision ->> 'verification_status', ''), 'unsigned');
|
|
101
|
+
begin
|
|
102
|
+
if v_status not in ('unsigned', 'observed', 'warn', 'verified', 'failed') then
|
|
103
|
+
v_status := 'failed';
|
|
104
|
+
end if;
|
|
105
|
+
|
|
106
|
+
insert into agent_board.signature_evidence(
|
|
107
|
+
agent_id,
|
|
108
|
+
signing_key_id,
|
|
109
|
+
key_id,
|
|
110
|
+
key_version,
|
|
111
|
+
algorithm,
|
|
112
|
+
source_kind,
|
|
113
|
+
source_message_id,
|
|
114
|
+
source_task_event_id,
|
|
115
|
+
operation,
|
|
116
|
+
payload_digest,
|
|
117
|
+
canonicalization_version,
|
|
118
|
+
signature_digest,
|
|
119
|
+
verification_status,
|
|
120
|
+
failure_class,
|
|
121
|
+
signed_at,
|
|
122
|
+
verified_at,
|
|
123
|
+
nonce,
|
|
124
|
+
idempotency_key,
|
|
125
|
+
external_evidence_ref,
|
|
126
|
+
metadata
|
|
127
|
+
)
|
|
128
|
+
values (
|
|
129
|
+
v_agent_id,
|
|
130
|
+
nullif(p_gateway_decision ->> 'signing_key_id', '')::uuid,
|
|
131
|
+
nullif(p_gateway_decision ->> 'key_id', ''),
|
|
132
|
+
nullif(p_gateway_decision ->> 'key_version', '')::integer,
|
|
133
|
+
coalesce(nullif(p_gateway_decision ->> 'algorithm', ''), 'Ed25519'),
|
|
134
|
+
p_source_kind,
|
|
135
|
+
case when p_source_kind = 'message' then p_source_id else null end,
|
|
136
|
+
case when p_source_kind = 'task_event' then p_source_id else null end,
|
|
137
|
+
p_operation,
|
|
138
|
+
coalesce(nullif(p_gateway_decision ->> 'payload_digest', ''), 'sha256:unsigned'),
|
|
139
|
+
coalesce(nullif(p_gateway_decision ->> 'canonicalization_version', ''), 'agent-provenance-jcs.v1'),
|
|
140
|
+
nullif(p_gateway_decision ->> 'signature_digest', ''),
|
|
141
|
+
v_status,
|
|
142
|
+
nullif(p_gateway_decision ->> 'failure_class', ''),
|
|
143
|
+
nullif(p_gateway_decision ->> 'signed_at', '')::timestamptz,
|
|
144
|
+
nullif(p_gateway_decision ->> 'verified_at', '')::timestamptz,
|
|
145
|
+
nullif(p_gateway_decision ->> 'nonce', ''),
|
|
146
|
+
nullif(p_gateway_decision ->> 'idempotency_key', ''),
|
|
147
|
+
nullif(p_gateway_decision ->> 'external_evidence_ref', ''),
|
|
148
|
+
jsonb_build_object(
|
|
149
|
+
'gateway', 'signed-write',
|
|
150
|
+
'enforcementMode', coalesce(p_gateway_decision ->> 'enforcement_mode', 'observe'),
|
|
151
|
+
'redacted', true,
|
|
152
|
+
'metadata-safe', true
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
returning id into v_evidence_id;
|
|
156
|
+
|
|
157
|
+
update agent_board.signature_replay_state
|
|
158
|
+
set signature_evidence_id = v_evidence_id
|
|
159
|
+
where agent_id = v_agent_id
|
|
160
|
+
and operation = p_operation
|
|
161
|
+
and (
|
|
162
|
+
(nonce is not null and nonce = nullif(p_gateway_decision ->> 'nonce', ''))
|
|
163
|
+
or (idempotency_key is not null and idempotency_key = nullif(p_gateway_decision ->> 'idempotency_key', ''))
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
return v_evidence_id;
|
|
167
|
+
end;
|
|
168
|
+
$$;
|
|
169
|
+
|
|
170
|
+
create or replace function agent_board.signed_send_direct_message(
|
|
171
|
+
p_payload jsonb,
|
|
172
|
+
p_gateway_decision jsonb
|
|
173
|
+
)
|
|
174
|
+
returns table(message_id uuid, delivery_recipient_id uuid, inbox_item_id uuid, callback_outbox_count integer, signature_evidence_id uuid, verification_status text, created_at timestamptz)
|
|
175
|
+
language plpgsql
|
|
176
|
+
security definer
|
|
177
|
+
set search_path = agent_board, public
|
|
178
|
+
as $$
|
|
179
|
+
declare
|
|
180
|
+
v_row record;
|
|
181
|
+
v_evidence_id uuid;
|
|
182
|
+
v_actor uuid;
|
|
183
|
+
begin
|
|
184
|
+
v_actor := agent_board._signed_write_actor_id(p_payload, p_gateway_decision, 'p_author_agent_id');
|
|
185
|
+
select *
|
|
186
|
+
into v_row
|
|
187
|
+
from agent_board.send_direct_message(
|
|
188
|
+
(p_payload ->> 'p_thread_id')::uuid,
|
|
189
|
+
v_actor,
|
|
190
|
+
(p_payload ->> 'p_recipient_agent_id')::uuid,
|
|
191
|
+
p_payload ->> 'p_subject',
|
|
192
|
+
p_payload ->> 'p_body',
|
|
193
|
+
coalesce(p_payload ->> 'p_message_type', 'comment'),
|
|
194
|
+
coalesce(p_payload ->> 'p_priority', 'medium'),
|
|
195
|
+
nullif(p_payload ->> 'p_idempotency_key', ''),
|
|
196
|
+
coalesce(p_payload -> 'p_metadata', '{}'::jsonb) || jsonb_build_object('signed_write', jsonb_build_object('verification_status', coalesce(p_gateway_decision ->> 'verification_status', 'unsigned'), 'redacted', true))
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
v_evidence_id := agent_board._record_signed_write_evidence('message', v_row.message_id, 'send_direct_message', p_payload, p_gateway_decision);
|
|
200
|
+
|
|
201
|
+
return query
|
|
202
|
+
select v_row.message_id, v_row.delivery_recipient_id, v_row.inbox_item_id, v_row.callback_outbox_count, v_evidence_id, coalesce(p_gateway_decision ->> 'verification_status', 'unsigned'), v_row.created_at;
|
|
203
|
+
end;
|
|
204
|
+
$$;
|
|
205
|
+
|
|
206
|
+
create or replace function agent_board.signed_append_task_event(
|
|
207
|
+
p_payload jsonb,
|
|
208
|
+
p_gateway_decision jsonb
|
|
209
|
+
)
|
|
210
|
+
returns table(task_id uuid, thread_id uuid, event_id uuid, event_sequence bigint, signature_evidence_id uuid, verification_status text, updated_at timestamptz)
|
|
211
|
+
language plpgsql
|
|
212
|
+
security definer
|
|
213
|
+
set search_path = agent_board, public
|
|
214
|
+
as $$
|
|
215
|
+
declare
|
|
216
|
+
v_row record;
|
|
217
|
+
v_evidence_id uuid;
|
|
218
|
+
v_actor uuid;
|
|
219
|
+
begin
|
|
220
|
+
v_actor := agent_board._signed_write_actor_id(p_payload, p_gateway_decision, 'p_actor_agent_id');
|
|
221
|
+
select *
|
|
222
|
+
into v_row
|
|
223
|
+
from agent_board.append_task_event(
|
|
224
|
+
(p_payload ->> 'p_task_id')::uuid,
|
|
225
|
+
v_actor,
|
|
226
|
+
p_payload ->> 'p_event_type',
|
|
227
|
+
coalesce(p_payload -> 'p_payload', '{}'::jsonb) || jsonb_build_object('signed_write', jsonb_build_object('verification_status', coalesce(p_gateway_decision ->> 'verification_status', 'unsigned'), 'redacted', true)),
|
|
228
|
+
nullif(p_payload ->> 'p_status', ''),
|
|
229
|
+
nullif(p_payload ->> 'p_assigned_agent_id', '')::uuid,
|
|
230
|
+
nullif(p_payload ->> 'p_completed_at', '')::timestamptz
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
v_evidence_id := agent_board._record_signed_write_evidence('task_event', v_row.event_id, 'append_task_event', p_payload, p_gateway_decision);
|
|
234
|
+
|
|
235
|
+
return query
|
|
236
|
+
select v_row.task_id, v_row.thread_id, v_row.event_id, v_row.event_sequence, v_evidence_id, coalesce(p_gateway_decision ->> 'verification_status', 'unsigned'), v_row.updated_at;
|
|
237
|
+
end;
|
|
238
|
+
$$;
|
|
239
|
+
|
|
240
|
+
create or replace function agent_board.signed_post_board_message(
|
|
241
|
+
p_payload jsonb,
|
|
242
|
+
p_gateway_decision jsonb
|
|
243
|
+
)
|
|
244
|
+
returns table(message_id uuid, board_id uuid, delivered_recipient_count integer, callback_outbox_count integer, signature_evidence_id uuid, verification_status text, created_at timestamptz)
|
|
245
|
+
language plpgsql
|
|
246
|
+
security definer
|
|
247
|
+
set search_path = agent_board, public
|
|
248
|
+
as $$
|
|
249
|
+
declare
|
|
250
|
+
v_row record;
|
|
251
|
+
v_evidence_id uuid;
|
|
252
|
+
v_actor uuid;
|
|
253
|
+
begin
|
|
254
|
+
v_actor := agent_board._signed_write_actor_id(p_payload, p_gateway_decision, 'p_author_agent_id');
|
|
255
|
+
select *
|
|
256
|
+
into v_row
|
|
257
|
+
from agent_board.post_board_message(
|
|
258
|
+
(p_payload ->> 'p_thread_id')::uuid,
|
|
259
|
+
v_actor,
|
|
260
|
+
(p_payload ->> 'p_board_id')::uuid,
|
|
261
|
+
p_payload ->> 'p_subject',
|
|
262
|
+
p_payload ->> 'p_body',
|
|
263
|
+
coalesce(p_payload ->> 'p_message_type', 'comment'),
|
|
264
|
+
coalesce(p_payload ->> 'p_priority', 'medium'),
|
|
265
|
+
nullif(p_payload ->> 'p_idempotency_key', ''),
|
|
266
|
+
coalesce(p_payload -> 'p_metadata', '{}'::jsonb) || jsonb_build_object('signed_write', jsonb_build_object('verification_status', coalesce(p_gateway_decision ->> 'verification_status', 'unsigned'), 'redacted', true))
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
v_evidence_id := agent_board._record_signed_write_evidence('message', v_row.message_id, 'post_board_message', p_payload, p_gateway_decision);
|
|
270
|
+
|
|
271
|
+
return query
|
|
272
|
+
select v_row.message_id, v_row.board_id, v_row.delivered_recipient_count, v_row.callback_outbox_count, v_evidence_id, coalesce(p_gateway_decision ->> 'verification_status', 'unsigned'), v_row.created_at;
|
|
273
|
+
end;
|
|
274
|
+
$$;
|
|
275
|
+
|
|
276
|
+
revoke all on function agent_board.reserve_signed_write_replay(uuid, uuid, text, text, text, text, timestamptz, timestamptz) from public, anon;
|
|
277
|
+
revoke all on function agent_board.signed_send_direct_message(jsonb, jsonb) from public, anon;
|
|
278
|
+
revoke all on function agent_board.signed_append_task_event(jsonb, jsonb) from public, anon;
|
|
279
|
+
revoke all on function agent_board.signed_post_board_message(jsonb, jsonb) from public, anon;
|
|
280
|
+
|
|
281
|
+
grant execute on function agent_board.reserve_signed_write_replay(uuid, uuid, text, text, text, text, timestamptz, timestamptz) to service_role;
|
|
282
|
+
grant execute on function agent_board.signed_send_direct_message(jsonb, jsonb) to service_role;
|
|
283
|
+
grant execute on function agent_board.signed_append_task_event(jsonb, jsonb) to service_role;
|
|
284
|
+
grant execute on function agent_board.signed_post_board_message(jsonb, jsonb) to service_role;
|
|
285
|
+
|
|
286
|
+
insert into agent_board.schema_version (version)
|
|
287
|
+
values (5)
|
|
288
|
+
on conflict ((true)) do update set version = excluded.version;
|