@consiliency/agent-board-schema 1.68.0 → 1.74.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/fixtures/already-applied.json +28 -4
- package/migrations/20261026000100_agent_board_thread_association.sql +1287 -0
- package/migrations/20261101000100_agent_board_session_measured_mint.sql +145 -0
- package/migrations/20261104065658_agent_board_reply_delivery.sql +659 -0
- package/migrations/20261104170000_agent_board_tasking_replay_scope.sql +320 -0
- package/migrations/20261104180000_agent_board_delivery_writer_execute.sql +51 -0
- package/migrations/20261104190000_agent_board_message_replay_scope.sql +373 -0
- package/package.json +1 -1
- package/schema-manifest.json +57 -3
- package/src/tooling.test.mjs +8 -2
- package/tests/agent_board_661_reply_delivery.test.sql +185 -0
- package/tests/agent_board_667_boundary.test.sql +162 -0
- package/tests/agent_board_667_conversion_branches.test.sql +91 -0
- package/tests/agent_board_667_conversion_profile.test.sql +112 -0
- package/tests/agent_board_667_history_class.test.sql +785 -0
- package/tests/agent_board_667_native_cast_effect.test.sql +88 -0
- package/tests/agent_board_667_realtime_apply_behavior.test.sql +117 -0
- package/tests/agent_board_667_realtime_apply_controls.test.sql +143 -0
- package/tests/agent_board_667_realtime_apply_profile.test.sql +61 -0
- package/tests/agent_board_667_retention.test.sql +201 -0
- package/tests/agent_board_667_routing.test.sql +294 -0
- package/tests/agent_board_667_sender_effects.test.sql +100 -0
- package/tests/agent_board_667_sender_profile_controls.test.sql +29 -0
- package/tests/agent_board_667_storage_delimiter_behavior.test.sql +84 -0
- package/tests/agent_board_667_storage_delimiter_controls.test.sql +23 -0
- package/tests/agent_board_667_storage_delimiter_profile.test.sql +61 -0
- package/tests/agent_board_667_storage_search_behavior.test.sql +93 -0
- package/tests/agent_board_667_storage_search_controls.test.sql +22 -0
- package/tests/agent_board_667_storage_search_profile.test.sql +60 -0
- package/tests/agent_board_667_storage_timestamp_behavior.test.sql +58 -0
- package/tests/agent_board_667_storage_timestamp_controls.test.sql +22 -0
- package/tests/agent_board_667_storage_timestamp_profile.test.sql +54 -0
- package/tests/agent_board_667_writers.test.sql +281 -0
- package/tests/agent_board_717_message_replay_scope.test.sql +828 -0
- package/tests/agent_board_717_tasking_replay_scope.test.sql +661 -0
- package/tests/agent_board_addressing.test.sql +8 -5
- package/tests/agent_board_claim_subject_gate.test.sql +7 -3
- package/tests/agent_board_claimpolicy_race.test.sql +39 -11
- package/tests/agent_board_delegate_role_class.test.sql +33 -15
- package/tests/agent_board_delivery_writer_execute.test.sql +371 -0
- package/tests/agent_board_fk_lock_edges.test.sql +3 -0
- package/tests/agent_board_hosted_delegates.test.sql +5 -2
- package/tests/agent_board_inbox_rpcs.test.sql +5 -3
- package/tests/agent_board_obsgate.test.sql +8 -4
- package/tests/agent_board_obsgate4.test.sql +2 -2
- package/tests/agent_board_outbox_wake_ordering.test.sql +25 -2
- package/tests/agent_board_own_post_not_delivered.test.sql +11 -9
- package/tests/agent_board_session_identity_behavior_classes.test.sql +2 -2
- package/tests/agent_board_session_identity_limits.test.sql +1 -1
- package/tests/agent_board_session_identity_measured_mint.test.sql +342 -0
- package/tests/agent_board_session_identity_predicate_isolation.test.sql +146 -0
- package/tests/agent_board_sidserver_authority.test.sql +69 -0
- package/tests/agent_board_sidserver_catalog.test.sql +47 -0
- package/tests/agent_board_signed_write_gateway.test.sql +4 -2
- package/tests/agent_board_task_thread_lock_order.test.sql +67 -42
- package/tests/agent_board_v2_invariants.test.sql +5 -2
- package/tests/agent_board_write_enforcement_class.test.sql +3 -3
- package/tests/catalog/function_execute_privileges.json +41 -5
- package/tests/catalog/p_metadata_parameters.json +16 -0
- package/tests/fixtures/agent_board_667_apply_rls_guard.sql +195 -0
- package/tests/fixtures/agent_board_667_apply_rls_provenance.md +125 -0
- package/tests/fixtures/agent_board_667_apply_rls_reference.sql +1903 -0
- package/tests/fixtures/agent_board_667_conversion_guard.sql +162 -0
- package/tests/fixtures/agent_board_667_conversion_reference.md +23 -0
- package/tests/fixtures/agent_board_667_conversion_reference.sql +5325 -0
- package/tests/fixtures/agent_board_667_delimiter_guard.sql +92 -0
- package/tests/fixtures/agent_board_667_delimiter_provenance.md +116 -0
- package/tests/fixtures/agent_board_667_delimiter_reference.sql +10150 -0
- package/tests/fixtures/agent_board_667_search_guard.sql +92 -0
- package/tests/fixtures/agent_board_667_search_provenance.md +141 -0
- package/tests/fixtures/agent_board_667_search_reference.sql +4779 -0
- package/tests/fixtures/agent_board_667_sender_guard.sql +102 -0
- package/tests/fixtures/agent_board_667_sender_reference.md +20 -0
- package/tests/fixtures/agent_board_667_sender_reference.sql +875 -0
- package/tests/fixtures/agent_board_667_timestamp_graph.sql +84 -0
- package/tests/fixtures/agent_board_667_timestamp_guard.sql +94 -0
- package/tests/fixtures/agent_board_667_timestamp_provenance.md +99 -0
- package/tests/fixtures/agent_board_667_timestamp_reference.sql +2938 -0
- package/tests/isolation/expected/association_artifact_anchor_order.out +108 -0
- package/tests/isolation/expected/association_board_vs_board.out +71 -0
- package/tests/isolation/expected/association_post_wait_authority.out +77 -0
- package/tests/isolation/expected/association_strong_history_writers.out +203 -0
- package/tests/isolation/expected/association_strong_isolation.out +185 -0
- package/tests/isolation/expected/association_vs_artifact_claim_escalation.out +199 -0
- package/tests/isolation/expected/association_vs_heartbeat.out +78 -0
- package/tests/isolation/expected/association_vs_multi_anchor_artifact.out +67 -0
- package/tests/isolation/expected/association_vs_private_message.out +67 -0
- package/tests/isolation/expected/association_vs_task_and_conflict.out +133 -0
- package/tests/isolation/expected/association_vs_taskful_cross_thread.out +133 -0
- package/tests/isolation/expected/message_replay_scope.out +209 -0
- package/tests/isolation/expected/tasking_replay_scope.out +125 -0
- package/tests/isolation/specs/association_artifact_anchor_order.spec +46 -0
- package/tests/isolation/specs/association_board_vs_board.spec +37 -0
- package/tests/isolation/specs/association_post_wait_authority.spec +48 -0
- package/tests/isolation/specs/association_strong_history_writers.spec +61 -0
- package/tests/isolation/specs/association_strong_isolation.spec +50 -0
- package/tests/isolation/specs/association_vs_artifact_claim_escalation.spec +41 -0
- package/tests/isolation/specs/association_vs_heartbeat.spec +47 -0
- package/tests/isolation/specs/association_vs_multi_anchor_artifact.spec +38 -0
- package/tests/isolation/specs/association_vs_private_message.spec +33 -0
- package/tests/isolation/specs/association_vs_task_and_conflict.spec +38 -0
- package/tests/isolation/specs/association_vs_taskful_cross_thread.spec +42 -0
- package/tests/isolation/specs/message_replay_scope.spec +77 -0
- package/tests/isolation/specs/tasking_replay_scope.spec +72 -0
- package/tests/mutations/717-f1/M0_prefix_main_acl_and_comments.sql +11 -0
- package/tests/mutations/717-f1/M10_wrapper_stops_delegating.sql +7 -0
- package/tests/mutations/717-f1/M11_transitive_recipient_content.sql +8 -0
- package/tests/mutations/717-f1/M12_transitive_recipient_visibility.sql +8 -0
- package/tests/mutations/717-f1/M13_transitive_worker_content.sql +15 -0
- package/tests/mutations/717-f1/M1a_regrant_upsert_delivery_recipient.sql +1 -0
- package/tests/mutations/717-f1/M1b_regrant_upsert_inbox_item.sql +1 -0
- package/tests/mutations/717-f1/M1c_regrant_queue_inbox_callbacks.sql +1 -0
- package/tests/mutations/717-f1/M1d_regrant_queue_board_post_callbacks.sql +1 -0
- package/tests/mutations/717-f1/M1e_regrant_next_thread_message_sequence.sql +1 -0
- package/tests/mutations/717-f1/M2_blanket_schema_grant.sql +1 -0
- package/tests/mutations/717-f1/M3_new_overload_of_sink.sql +10 -0
- package/tests/mutations/717-f1/M4_new_route_calling_sink.sql +7 -0
- package/tests/mutations/717-f1/M5_actor_trusts_supplied_id.sql +5 -0
- package/tests/mutations/717-f1/M6_signed_route_granted_to_authenticated.sql +1 -0
- package/tests/mutations/717-f1/M7_worker_granted_to_authenticated.sql +1 -0
- package/tests/mutations/717-f1/M8_recipient_state_rewrites_visibility.sql +5 -0
- package/tests/mutations/717-f1/M9_public_route_revoked_from_service_role.sql +1 -0
- package/tests/mutations/717-f1/outbox_wake_ordering/W1_regrant_queue_inbox_callbacks.sql +1 -0
- package/tests/mutations/717-f1/outbox_wake_ordering/W2_revoke_worker_from_service_role.sql +1 -0
- package/tests/mutations/717-f1/outbox_wake_ordering/W3_invoker_caller_of_sink.sql +1 -0
- package/tests/mutations/717-f1/outbox_wake_ordering/W4_public_regrant_board_post_sink.sql +1 -0
- package/tests/mutations/717-f1/run.sh +17 -0
- package/tests/mutations/717-f2b/C1_new_delivery_route.sql +4 -0
- package/tests/mutations/717-f2b/C2_new_replay_lookup.sql +3 -0
- package/tests/mutations/717-f2b/C3_internal_regranted.sql +2 -0
- package/tests/mutations/717-f2b/C4_wrapper_writes_delivery.sql +9 -0
- package/tests/mutations/717-f2b/C5_class_member_dynamic_sql.sql +9 -0
- package/tests/mutations/717-f2b/C6_drop_board_scope_constraint.sql +2 -0
- package/tests/mutations/717-f2b/C7_state_private_helper_content.sql +14 -0
- package/tests/mutations/717-f2b/L1_dm_lock_split_by_recipient.sql +8 -0
- package/tests/mutations/717-f2b/L2_dm_lock_removed.sql +12 -0
- package/tests/mutations/717-f2b/L3_mc_lock_split_by_recipients.sql +8 -0
- package/tests/mutations/717-f2b/L4_mc_lock_removed.sql +12 -0
- package/tests/mutations/717-f2b/M0_prefix_definitions.sql +17 -0
- package/tests/mutations/717-f2b/M10_mc_lookup_any_author.sql +15 -0
- package/tests/mutations/717-f2b/M11_dm_swallow_refusal.sql +8 -0
- package/tests/mutations/717-f2b/M12_mc_swallow_refusal.sql +8 -0
- package/tests/mutations/717-f2b/M13_signed_dm_swallows_refusal.sql +32 -0
- package/tests/mutations/717-f2b/M14_signed_mc_swallows_refusal.sql +20 -0
- package/tests/mutations/717-f2b/M15_mc_any_source.sql +7 -0
- package/tests/mutations/717-f2b/M1_dm_drop_recipient_proof.sql +16 -0
- package/tests/mutations/717-f2b/M2_mc_drop_recipient_proof.sql +16 -0
- package/tests/mutations/717-f2b/M3_dm_metadata_as_proof.sql +12 -0
- package/tests/mutations/717-f2b/M4_mc_metadata_as_proof.sql +16 -0
- package/tests/mutations/717-f2b/M5_dm_any_mode.sql +11 -0
- package/tests/mutations/717-f2b/M6_dm_board_delivery_counts.sql +11 -0
- package/tests/mutations/717-f2b/M7_mc_any_mode.sql +11 -0
- package/tests/mutations/717-f2b/M8_dm_thread_stamp_as_proof.sql +12 -0
- package/tests/mutations/717-f2b/M9_dm_lookup_any_author.sql +15 -0
- package/tests/mutations/717-f2b/run.sh +82 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
-- #717 F2b: a same-key send_direct_message / send_multicast_message replay cannot widen the
|
|
2
|
+
-- source message's audience.
|
|
3
|
+
--
|
|
4
|
+
-- Idempotency identity is unchanged: (rpc, thread, resolved author, trimmed key), the same
|
|
5
|
+
-- advisory lock domain and the same lookup. Before this migration a replay reused the author's
|
|
6
|
+
-- ORIGINAL message and delivered it to whatever recipient the retry named, so a newly named agent
|
|
7
|
+
-- could read the original body and every row anchored to it (an artifact another agent attached).
|
|
8
|
+
-- Now, on the replay branch and before any delivery, inbox or callback effect, every requested
|
|
9
|
+
-- recipient must already hold a persisted private delivery of that source message in the
|
|
10
|
+
-- function's own mode. Otherwise: 42501 'message replay cannot widen delivery scope'.
|
|
11
|
+
--
|
|
12
|
+
-- Only the two UUID cores change. The addressing overloads and the signed wrappers route through
|
|
13
|
+
-- them and inherit the refusal and its atomic rollback. Definitions are this tree's current ones
|
|
14
|
+
-- (20261104065658_agent_board_reply_delivery.sql) with the ceiling inserted; nothing else moves.
|
|
15
|
+
--
|
|
16
|
+
-- Compatibility limit, by design: a source message whose delivery rows are missing (deleted
|
|
17
|
+
-- recipient, historical corruption) cannot be replayed at all. Nothing reconstructs intent from
|
|
18
|
+
-- metadata. Use a new key.
|
|
19
|
+
--
|
|
20
|
+
-- Trust dependency: persisted deliveries are authoritative only once no API role can write them
|
|
21
|
+
-- directly (#717 F1, which revokes service_role EXECUTE on _upsert_delivery_recipient).
|
|
22
|
+
|
|
23
|
+
CREATE OR REPLACE FUNCTION agent_board.send_direct_message(p_thread_id uuid, p_author_agent_id uuid, p_recipient_agent_id uuid, p_subject text, p_body text, p_message_type text DEFAULT 'comment'::text, p_priority text DEFAULT 'medium'::text, p_idempotency_key text DEFAULT NULL::text, p_metadata jsonb DEFAULT '{}'::jsonb)
|
|
24
|
+
RETURNS TABLE(message_id uuid, delivery_recipient_id uuid, inbox_item_id uuid, callback_outbox_count integer, created_at timestamp with time zone)
|
|
25
|
+
LANGUAGE plpgsql
|
|
26
|
+
SECURITY DEFINER
|
|
27
|
+
SET search_path TO 'agent_board', 'public'
|
|
28
|
+
AS $function$
|
|
29
|
+
declare
|
|
30
|
+
v_message agent_board.messages%rowtype;
|
|
31
|
+
v_created_message record;
|
|
32
|
+
v_recipient agent_board.delivery_recipients%rowtype;
|
|
33
|
+
v_inbox agent_board.inbox_items%rowtype;
|
|
34
|
+
v_callback_count integer := 0;
|
|
35
|
+
v_metadata jsonb;
|
|
36
|
+
v_preview text;
|
|
37
|
+
v_fetch_descriptor jsonb;
|
|
38
|
+
v_idempotency_key text := nullif(trim(p_idempotency_key), '');
|
|
39
|
+
v_actor_agent_id uuid;
|
|
40
|
+
begin
|
|
41
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_author_agent_id, 'p_author_agent_id');
|
|
42
|
+
|
|
43
|
+
if nullif(trim(p_subject), '') is null or nullif(trim(p_body), '') is null then
|
|
44
|
+
raise exception 'subject and body are required' using errcode = '22023';
|
|
45
|
+
end if;
|
|
46
|
+
if p_priority not in ('low', 'medium', 'high', 'urgent') then
|
|
47
|
+
raise exception 'invalid priority' using errcode = '22023';
|
|
48
|
+
end if;
|
|
49
|
+
if not exists (select 1 from agent_board.threads where id = p_thread_id) then
|
|
50
|
+
raise exception 'thread not found' using errcode = 'P0002';
|
|
51
|
+
end if;
|
|
52
|
+
if not agent_board._current_agent_can_access_thread(p_thread_id) then
|
|
53
|
+
raise exception 'thread not accessible to current agent' using errcode = '42501';
|
|
54
|
+
end if;
|
|
55
|
+
if not exists (select 1 from agent_board.agents where id = p_recipient_agent_id) then
|
|
56
|
+
raise exception 'recipient agent not found' using errcode = 'P0002';
|
|
57
|
+
end if;
|
|
58
|
+
|
|
59
|
+
if agent_board._is_service_role() then
|
|
60
|
+
perform agent_board._record_send_authz_telemetry(
|
|
61
|
+
'service_role_bypass',
|
|
62
|
+
coalesce(nullif(p_metadata -> 'signed_write' ->> 'origin', ''), 'unknown'),
|
|
63
|
+
v_actor_agent_id,
|
|
64
|
+
null,
|
|
65
|
+
'send_direct_message',
|
|
66
|
+
agent_board._resolve_send_fleet_scope(v_actor_agent_id),
|
|
67
|
+
null,
|
|
68
|
+
jsonb_build_object('redacted', true)
|
|
69
|
+
);
|
|
70
|
+
end if;
|
|
71
|
+
|
|
72
|
+
perform agent_board._lock_idempotency_key(
|
|
73
|
+
'send_direct_message:' || p_thread_id::text || ':' || v_actor_agent_id::text,
|
|
74
|
+
v_idempotency_key
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
if v_idempotency_key is not null then
|
|
78
|
+
select *
|
|
79
|
+
into v_message
|
|
80
|
+
from agent_board.messages
|
|
81
|
+
where thread_id = p_thread_id
|
|
82
|
+
and author_agent_id = v_actor_agent_id
|
|
83
|
+
and metadata ->> 'rpcName' = 'send_direct_message'
|
|
84
|
+
and metadata ->> 'idempotencyKey' = v_idempotency_key
|
|
85
|
+
order by created_at desc
|
|
86
|
+
limit 1;
|
|
87
|
+
end if;
|
|
88
|
+
|
|
89
|
+
-- #717 F2b: a same-key replay may only re-deliver the source message to the recipient it was
|
|
90
|
+
-- already PRIVATELY delivered to. The proof is the persisted delivery row of THIS source
|
|
91
|
+
-- message in THIS function's mode, for THIS recipient, with no board scope. Metadata, the
|
|
92
|
+
-- thread's board stamp and any board-mode delivery are not evidence. Refused before any
|
|
93
|
+
-- replay effect, so the whole call (telemetry, signed evidence) rolls back. A new recipient
|
|
94
|
+
-- needs a new key, which creates a new message without the source's artifacts.
|
|
95
|
+
if v_message.id is not null and not exists (
|
|
96
|
+
select 1
|
|
97
|
+
from agent_board.delivery_recipients dr
|
|
98
|
+
where dr.source_kind = 'message'
|
|
99
|
+
and dr.source_message_id = v_message.id
|
|
100
|
+
and dr.delivery_mode = 'direct'
|
|
101
|
+
and dr.recipient_agent_id = p_recipient_agent_id
|
|
102
|
+
and dr.board_id is null
|
|
103
|
+
) then
|
|
104
|
+
raise exception 'message replay cannot widen delivery scope' using errcode = '42501';
|
|
105
|
+
end if;
|
|
106
|
+
|
|
107
|
+
if v_message.id is null then
|
|
108
|
+
v_metadata := coalesce(p_metadata, '{}'::jsonb)
|
|
109
|
+
|| jsonb_build_object(
|
|
110
|
+
'rpcName', 'send_direct_message',
|
|
111
|
+
'subject', trim(p_subject),
|
|
112
|
+
'priority', p_priority
|
|
113
|
+
);
|
|
114
|
+
if v_idempotency_key is not null then
|
|
115
|
+
v_metadata := v_metadata || jsonb_build_object('idempotencyKey', v_idempotency_key);
|
|
116
|
+
end if;
|
|
117
|
+
|
|
118
|
+
select *
|
|
119
|
+
into v_created_message
|
|
120
|
+
from agent_board._insert_thread_message(
|
|
121
|
+
p_thread_id,
|
|
122
|
+
v_actor_agent_id,
|
|
123
|
+
p_body,
|
|
124
|
+
p_message_type,
|
|
125
|
+
null,
|
|
126
|
+
v_metadata
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
select *
|
|
130
|
+
into v_message
|
|
131
|
+
from agent_board.messages
|
|
132
|
+
where id = v_created_message.message_id;
|
|
133
|
+
end if;
|
|
134
|
+
|
|
135
|
+
v_preview := agent_board._trim_inbox_text(p_body, 280);
|
|
136
|
+
v_fetch_descriptor := agent_board._build_fetch_descriptor(
|
|
137
|
+
'thread',
|
|
138
|
+
p_thread_id,
|
|
139
|
+
'agent_board.v_thread_feed',
|
|
140
|
+
'direct delivery',
|
|
141
|
+
jsonb_build_object('messageId', v_message.id::text, 'recipientAgentId', p_recipient_agent_id::text)
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
v_recipient := agent_board._upsert_delivery_recipient(
|
|
145
|
+
'direct',
|
|
146
|
+
p_recipient_agent_id,
|
|
147
|
+
'message',
|
|
148
|
+
v_message.id,
|
|
149
|
+
null,
|
|
150
|
+
null,
|
|
151
|
+
null,
|
|
152
|
+
null,
|
|
153
|
+
jsonb_build_object('priority', p_priority)
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
v_inbox := agent_board._upsert_inbox_item(
|
|
157
|
+
v_recipient.id,
|
|
158
|
+
p_recipient_agent_id,
|
|
159
|
+
null,
|
|
160
|
+
v_recipient.delivery_mode,
|
|
161
|
+
'message',
|
|
162
|
+
v_message.id,
|
|
163
|
+
null,
|
|
164
|
+
null,
|
|
165
|
+
trim(p_subject),
|
|
166
|
+
v_preview,
|
|
167
|
+
p_priority,
|
|
168
|
+
true,
|
|
169
|
+
false,
|
|
170
|
+
v_fetch_descriptor,
|
|
171
|
+
jsonb_build_object('threadId', p_thread_id::text)
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
v_callback_count := agent_board._queue_inbox_callbacks(v_inbox.id, 'inbox.item.delivered');
|
|
175
|
+
|
|
176
|
+
return query
|
|
177
|
+
select v_message.id, v_recipient.id, v_inbox.id, v_callback_count, v_message.created_at;
|
|
178
|
+
end;
|
|
179
|
+
$function$;
|
|
180
|
+
|
|
181
|
+
CREATE OR REPLACE FUNCTION agent_board.send_multicast_message(p_thread_id uuid, p_author_agent_id uuid, p_recipient_agent_ids uuid[], p_subject text, p_body text, p_message_type text DEFAULT 'comment'::text, p_priority text DEFAULT 'medium'::text, p_idempotency_key text DEFAULT NULL::text, p_metadata jsonb DEFAULT '{}'::jsonb)
|
|
182
|
+
RETURNS TABLE(message_id uuid, delivered_recipient_count integer, inbox_item_count integer, callback_outbox_count integer, created_at timestamp with time zone)
|
|
183
|
+
LANGUAGE plpgsql
|
|
184
|
+
SECURITY DEFINER
|
|
185
|
+
SET search_path TO 'agent_board', 'public'
|
|
186
|
+
AS $function$
|
|
187
|
+
declare
|
|
188
|
+
v_message agent_board.messages%rowtype;
|
|
189
|
+
v_created_message record;
|
|
190
|
+
v_recipient_ids uuid[];
|
|
191
|
+
v_recipient_id uuid;
|
|
192
|
+
v_recipient agent_board.delivery_recipients%rowtype;
|
|
193
|
+
v_inbox agent_board.inbox_items%rowtype;
|
|
194
|
+
v_delivered_count integer := 0;
|
|
195
|
+
v_inbox_count integer := 0;
|
|
196
|
+
v_callback_count integer := 0;
|
|
197
|
+
v_metadata jsonb;
|
|
198
|
+
v_preview text;
|
|
199
|
+
v_fetch_descriptor jsonb;
|
|
200
|
+
v_idempotency_key text := nullif(trim(p_idempotency_key), '');
|
|
201
|
+
v_actor_agent_id uuid;
|
|
202
|
+
begin
|
|
203
|
+
v_actor_agent_id := agent_board._resolved_actor_agent_id(p_author_agent_id, 'p_author_agent_id');
|
|
204
|
+
|
|
205
|
+
if nullif(trim(p_subject), '') is null or nullif(trim(p_body), '') is null then
|
|
206
|
+
raise exception 'subject and body are required' using errcode = '22023';
|
|
207
|
+
end if;
|
|
208
|
+
if p_priority not in ('low', 'medium', 'high', 'urgent') then
|
|
209
|
+
raise exception 'invalid priority' using errcode = '22023';
|
|
210
|
+
end if;
|
|
211
|
+
if p_recipient_agent_ids is null or cardinality(p_recipient_agent_ids) = 0 then
|
|
212
|
+
raise exception 'recipient_agent_ids must not be empty' using errcode = '22023';
|
|
213
|
+
end if;
|
|
214
|
+
if array_position(p_recipient_agent_ids, null) is not null then
|
|
215
|
+
raise exception 'recipient_agent_ids must not contain nulls' using errcode = '22023';
|
|
216
|
+
end if;
|
|
217
|
+
if not exists (select 1 from agent_board.threads where id = p_thread_id) then
|
|
218
|
+
raise exception 'thread not found' using errcode = 'P0002';
|
|
219
|
+
end if;
|
|
220
|
+
if not agent_board._current_agent_can_access_thread(p_thread_id) then
|
|
221
|
+
raise exception 'thread not accessible to current agent' using errcode = '42501';
|
|
222
|
+
end if;
|
|
223
|
+
|
|
224
|
+
select array_agg(distinct recipient_id)
|
|
225
|
+
into v_recipient_ids
|
|
226
|
+
from unnest(p_recipient_agent_ids) as recipient_id;
|
|
227
|
+
|
|
228
|
+
if (
|
|
229
|
+
select count(*)
|
|
230
|
+
from agent_board.agents
|
|
231
|
+
where id = any(v_recipient_ids)
|
|
232
|
+
) <> cardinality(v_recipient_ids) then
|
|
233
|
+
raise exception 'recipient agent not found' using errcode = 'P0002';
|
|
234
|
+
end if;
|
|
235
|
+
|
|
236
|
+
if agent_board._is_service_role() then
|
|
237
|
+
perform agent_board._record_send_authz_telemetry(
|
|
238
|
+
'service_role_bypass',
|
|
239
|
+
coalesce(nullif(p_metadata -> 'signed_write' ->> 'origin', ''), 'unknown'),
|
|
240
|
+
v_actor_agent_id,
|
|
241
|
+
null,
|
|
242
|
+
'send_multicast_message',
|
|
243
|
+
agent_board._resolve_send_fleet_scope(v_actor_agent_id),
|
|
244
|
+
null,
|
|
245
|
+
jsonb_build_object('redacted', true)
|
|
246
|
+
);
|
|
247
|
+
end if;
|
|
248
|
+
|
|
249
|
+
perform agent_board._lock_idempotency_key(
|
|
250
|
+
'send_multicast_message:' || p_thread_id::text || ':' || v_actor_agent_id::text,
|
|
251
|
+
v_idempotency_key
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
if v_idempotency_key is not null then
|
|
255
|
+
select *
|
|
256
|
+
into v_message
|
|
257
|
+
from agent_board.messages
|
|
258
|
+
where thread_id = p_thread_id
|
|
259
|
+
and author_agent_id = v_actor_agent_id
|
|
260
|
+
and metadata ->> 'rpcName' = 'send_multicast_message'
|
|
261
|
+
and metadata ->> 'idempotencyKey' = v_idempotency_key
|
|
262
|
+
order by created_at desc
|
|
263
|
+
limit 1;
|
|
264
|
+
end if;
|
|
265
|
+
|
|
266
|
+
-- #717 F2b: a same-key replay may name the same normalized recipient set or a nonempty subset
|
|
267
|
+
-- of it, never a new recipient. Each requested recipient must already hold a persisted
|
|
268
|
+
-- multicast delivery of THIS source message with no board scope; an omitted recipient's
|
|
269
|
+
-- delivery is kept, not revoked. Metadata, the thread's board stamp and board-mode deliveries
|
|
270
|
+
-- are not evidence. Refused before any replay effect, so the whole call rolls back. A new
|
|
271
|
+
-- recipient needs a new key, which creates a new message without the source's artifacts.
|
|
272
|
+
if v_message.id is not null and exists (
|
|
273
|
+
select 1
|
|
274
|
+
from unnest(v_recipient_ids) as requested(recipient_id)
|
|
275
|
+
where not exists (
|
|
276
|
+
select 1
|
|
277
|
+
from agent_board.delivery_recipients dr
|
|
278
|
+
where dr.source_kind = 'message'
|
|
279
|
+
and dr.source_message_id = v_message.id
|
|
280
|
+
and dr.delivery_mode = 'multicast'
|
|
281
|
+
and dr.recipient_agent_id = requested.recipient_id
|
|
282
|
+
and dr.board_id is null
|
|
283
|
+
)
|
|
284
|
+
) then
|
|
285
|
+
raise exception 'message replay cannot widen delivery scope' using errcode = '42501';
|
|
286
|
+
end if;
|
|
287
|
+
|
|
288
|
+
if v_message.id is null then
|
|
289
|
+
v_metadata := coalesce(p_metadata, '{}'::jsonb)
|
|
290
|
+
|| jsonb_build_object(
|
|
291
|
+
'rpcName', 'send_multicast_message',
|
|
292
|
+
'subject', trim(p_subject),
|
|
293
|
+
'priority', p_priority
|
|
294
|
+
);
|
|
295
|
+
if v_idempotency_key is not null then
|
|
296
|
+
v_metadata := v_metadata || jsonb_build_object('idempotencyKey', v_idempotency_key);
|
|
297
|
+
end if;
|
|
298
|
+
|
|
299
|
+
select *
|
|
300
|
+
into v_created_message
|
|
301
|
+
from agent_board._insert_thread_message(
|
|
302
|
+
p_thread_id,
|
|
303
|
+
v_actor_agent_id,
|
|
304
|
+
p_body,
|
|
305
|
+
p_message_type,
|
|
306
|
+
null,
|
|
307
|
+
v_metadata
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
select *
|
|
311
|
+
into v_message
|
|
312
|
+
from agent_board.messages
|
|
313
|
+
where id = v_created_message.message_id;
|
|
314
|
+
end if;
|
|
315
|
+
|
|
316
|
+
v_preview := agent_board._trim_inbox_text(p_body, 280);
|
|
317
|
+
|
|
318
|
+
foreach v_recipient_id in array v_recipient_ids loop
|
|
319
|
+
v_fetch_descriptor := agent_board._build_fetch_descriptor(
|
|
320
|
+
'thread',
|
|
321
|
+
p_thread_id,
|
|
322
|
+
'agent_board.v_thread_feed',
|
|
323
|
+
'multicast delivery',
|
|
324
|
+
jsonb_build_object('messageId', v_message.id::text, 'recipientAgentId', v_recipient_id::text)
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
v_recipient := agent_board._upsert_delivery_recipient(
|
|
328
|
+
'multicast',
|
|
329
|
+
v_recipient_id,
|
|
330
|
+
'message',
|
|
331
|
+
v_message.id,
|
|
332
|
+
null,
|
|
333
|
+
null,
|
|
334
|
+
null,
|
|
335
|
+
null,
|
|
336
|
+
jsonb_build_object('priority', p_priority)
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
v_inbox := agent_board._upsert_inbox_item(
|
|
340
|
+
v_recipient.id,
|
|
341
|
+
v_recipient_id,
|
|
342
|
+
null,
|
|
343
|
+
v_recipient.delivery_mode,
|
|
344
|
+
'message',
|
|
345
|
+
v_message.id,
|
|
346
|
+
null,
|
|
347
|
+
null,
|
|
348
|
+
trim(p_subject),
|
|
349
|
+
v_preview,
|
|
350
|
+
p_priority,
|
|
351
|
+
true,
|
|
352
|
+
false,
|
|
353
|
+
v_fetch_descriptor,
|
|
354
|
+
jsonb_build_object('threadId', p_thread_id::text)
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
v_delivered_count := v_delivered_count + 1;
|
|
358
|
+
v_inbox_count := v_inbox_count + 1;
|
|
359
|
+
v_callback_count := v_callback_count + agent_board._queue_inbox_callbacks(v_inbox.id, 'inbox.item.delivered');
|
|
360
|
+
end loop;
|
|
361
|
+
|
|
362
|
+
return query
|
|
363
|
+
select v_message.id, v_delivered_count, v_inbox_count, v_callback_count, v_message.created_at;
|
|
364
|
+
end;
|
|
365
|
+
$function$;
|
|
366
|
+
|
|
367
|
+
revoke all on function agent_board.send_direct_message(uuid,uuid,uuid,text,text,text,text,text,jsonb) from public,anon,authenticated,service_role,agent_board_delegate;
|
|
368
|
+
grant execute on function agent_board.send_direct_message(uuid,uuid,uuid,text,text,text,text,text,jsonb) to authenticated,service_role;
|
|
369
|
+
comment on function agent_board.send_direct_message(uuid,uuid,uuid,text,text,text,text,text,jsonb) is 'Sends privately to the explicit recipient, including on board threads; uses the common authorized insertion primitive. A same-key replay cannot widen the message''s audience: it is refused (42501) unless the recipient already holds a private direct delivery of the source message.';
|
|
370
|
+
|
|
371
|
+
revoke all on function agent_board.send_multicast_message(uuid,uuid,uuid[],text,text,text,text,text,jsonb) from public,anon,authenticated,service_role,agent_board_delegate;
|
|
372
|
+
grant execute on function agent_board.send_multicast_message(uuid,uuid,uuid[],text,text,text,text,text,jsonb) to authenticated,service_role;
|
|
373
|
+
comment on function agent_board.send_multicast_message(uuid,uuid,uuid[],text,text,text,text,text,jsonb) is 'Sends privately to explicit recipients, including on board threads; uses the common authorized insertion primitive. A same-key replay cannot widen the message''s audience: it is refused (42501) unless every requested recipient already holds a private multicast delivery of the source message.';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@consiliency/agent-board-schema",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.74.0",
|
|
4
4
|
"description": "Canonical, immutable, exact-pinnable agent_board schema bundle: ordered SQL migrations, digest + compatibility manifest, and deterministic materialize/plan/check tooling for adopters.",
|
|
5
5
|
"repository": "https://github.com/Consiliency/message-board.git",
|
|
6
6
|
"type": "module",
|
package/schema-manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schema": "agent_board_schema_manifest.v1",
|
|
3
3
|
"interface": "IF-0-MBPLANE-BUNDLE-1",
|
|
4
4
|
"package": "@consiliency/agent-board-schema",
|
|
5
|
-
"packageVersion": "1.
|
|
5
|
+
"packageVersion": "1.74.0",
|
|
6
6
|
"schemaVersion": 8,
|
|
7
7
|
"minClientVersion": "1.1.0",
|
|
8
8
|
"source": {
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"usage": "upsert (retention/monitoring defaults; on conflict do nothing)"
|
|
47
47
|
}
|
|
48
48
|
],
|
|
49
|
-
"migrationCount":
|
|
50
|
-
"aggregateSha256": "
|
|
49
|
+
"migrationCount": 172,
|
|
50
|
+
"aggregateSha256": "1787dd0d972779bbdc1645b67460fc2f2c7b910f128414cf39b6dfb2b00b3b42",
|
|
51
51
|
"migrations": [
|
|
52
52
|
{
|
|
53
53
|
"order": 0,
|
|
@@ -1542,6 +1542,60 @@
|
|
|
1542
1542
|
"sourceRef": "message-board",
|
|
1543
1543
|
"bytes": 7396,
|
|
1544
1544
|
"sha256": "bfeb7bda1eb41bc431416502db69c33156ff72acfd79cefdfd556d933f79d809"
|
|
1545
|
+
},
|
|
1546
|
+
{
|
|
1547
|
+
"order": 166,
|
|
1548
|
+
"id": "20261026000100_agent_board_thread_association",
|
|
1549
|
+
"filename": "20261026000100_agent_board_thread_association.sql",
|
|
1550
|
+
"origin": "message-board-forward",
|
|
1551
|
+
"sourceRef": "message-board",
|
|
1552
|
+
"bytes": 70992,
|
|
1553
|
+
"sha256": "93c3ffc694f5dbd3a5d34d5ef392462707f959119e8c0ff52677c74720dd2c6d"
|
|
1554
|
+
},
|
|
1555
|
+
{
|
|
1556
|
+
"order": 167,
|
|
1557
|
+
"id": "20261101000100_agent_board_session_measured_mint",
|
|
1558
|
+
"filename": "20261101000100_agent_board_session_measured_mint.sql",
|
|
1559
|
+
"origin": "message-board-forward",
|
|
1560
|
+
"sourceRef": "message-board",
|
|
1561
|
+
"bytes": 12087,
|
|
1562
|
+
"sha256": "b18323397aaacfb7be138f5befedb8cb9b6a0247b868bc22a2ed3481b5f17c06"
|
|
1563
|
+
},
|
|
1564
|
+
{
|
|
1565
|
+
"order": 168,
|
|
1566
|
+
"id": "20261104065658_agent_board_reply_delivery",
|
|
1567
|
+
"filename": "20261104065658_agent_board_reply_delivery.sql",
|
|
1568
|
+
"origin": "message-board-forward",
|
|
1569
|
+
"sourceRef": "message-board",
|
|
1570
|
+
"bytes": 27537,
|
|
1571
|
+
"sha256": "0f785d8c2b6dd389fec88851d88370095c2de5d07764b7c8ced277388a471660"
|
|
1572
|
+
},
|
|
1573
|
+
{
|
|
1574
|
+
"order": 169,
|
|
1575
|
+
"id": "20261104170000_agent_board_tasking_replay_scope",
|
|
1576
|
+
"filename": "20261104170000_agent_board_tasking_replay_scope.sql",
|
|
1577
|
+
"origin": "message-board-forward",
|
|
1578
|
+
"sourceRef": "message-board",
|
|
1579
|
+
"bytes": 13932,
|
|
1580
|
+
"sha256": "dc77bd6b017e067ab20aa5ecea7d31377420d8593d33e2731059c0cbba52e4c0"
|
|
1581
|
+
},
|
|
1582
|
+
{
|
|
1583
|
+
"order": 170,
|
|
1584
|
+
"id": "20261104180000_agent_board_delivery_writer_execute",
|
|
1585
|
+
"filename": "20261104180000_agent_board_delivery_writer_execute.sql",
|
|
1586
|
+
"origin": "message-board-forward",
|
|
1587
|
+
"sourceRef": "message-board",
|
|
1588
|
+
"bytes": 4567,
|
|
1589
|
+
"sha256": "732cd0b61706f1f901eeb88f3e3a30e91a34723b8df4cc972218ebca0859e07a"
|
|
1590
|
+
},
|
|
1591
|
+
{
|
|
1592
|
+
"order": 171,
|
|
1593
|
+
"id": "20261104190000_agent_board_message_replay_scope",
|
|
1594
|
+
"filename": "20261104190000_agent_board_message_replay_scope.sql",
|
|
1595
|
+
"origin": "message-board-forward",
|
|
1596
|
+
"sourceRef": "message-board",
|
|
1597
|
+
"bytes": 15050,
|
|
1598
|
+
"sha256": "dbfd60300e8ce8ed78df8ae851f3990f58bcb43a7f9d53c2e25499a22e775a67"
|
|
1545
1599
|
}
|
|
1546
1600
|
],
|
|
1547
1601
|
"excludedBridge": {
|
package/src/tooling.test.mjs
CHANGED
|
@@ -41,9 +41,9 @@ describe('manifest integrity', () => {
|
|
|
41
41
|
expect(manifest.schemaVersion).toBe(8);
|
|
42
42
|
expect(manifest.minClientVersion).toMatch(/^\d+\.\d+\.\d+$/);
|
|
43
43
|
});
|
|
44
|
-
it('registers the four MBAUTHZ + four MBSENDAUTHZ + four MBSESSION + four MBDELEG + three MBFED + three MBHARDEN + two MBPORTALGATE + two MBPORTAL-PR32 + two ROOMOWN + two ROOMLINK + one ROOMDELEG + one LOCALAUTH + one ROOMUIAPI + one FEDSESSION + one FEDSESSION-AUTOJOIN + one GATENULL + one MEMBSTATE + one AGENTSDIR + one LEAVEIDEM + one ROLERESET + one MBROWID + one MBHYGIENE + one MBCONSENT-A + one MBCONSENT-B(a) + one MBCONSENT-B(i) + one MBCONSENT-B(ii) + one MBCONSENT-B(iii) + one MBHARDEN-#97 + one MBHARDEN-#118 + one INVITEPOLICY + one OBSGATE + one OBSGATE-2 + one OBSGATE-3 + one OBSGATE-4 + one FLEETMACHINERLS + one RESOLVENOOP + one ROOMDELEG-LANEB + one CLAIMKEY + two MINTHARDEN + one FLEETMACHINEHIJACK + one CLAIMGATE-SHADOW + one CLAIMGATE-ENFORCE + one FLEETMACHINEREACTIVATION + one DELEGCAPCEILING + one FLEETMACHINERECLAIM + one DELEGSOLEWRITER + one FLEETDOMAINRECLAIM + five ATOMICFLEETONBOARDING (onboarding + ceiling-lock + revocation-evidence + fedsession-gate + fedsession-lock-order) + one OUTBOXWAKE + one ENROLLLOCKORDER + one FEDPROVIDERABSENCE + one WAKERECOVERY + one CONSENTRECONCILE + one ENROLLRESUMPTION + one SIGNEDAUTHORITY + one SIGNERLIFECYCLE + one LEDGERAUTHORITY + one CEILINGLOCKCOMMENT + one LEDGERBOARDCREATE + one RECEIPTSUBJECTGATE + one TASKTHREADLOCKORDER + one CLAIMSUBJECTGATE + one FEDSESSIONIDENTITYGATE + one FEDIDENTITYSLUG + one INVITENODOWNGRADE + one SIGNEDWRITEFLAG + one SIGNEDWRITEMODEL + one RTCREDCLAIM + one ORIGINPOSTURE + one BOARDCLAIMPOLICY + one HEARTBEATPRESERVE + one LIVENESSDENOM + one OWNERLESSRENEWTTL + one OWNERLESSQUOTACENSUS + one FLEETDOMAINNODOWNGRADE + one OWNERLESSQUOTACONVERGE + one ADVISORYREVERTRESET + one CLAIMPOLICYRACE + one CLAIMPOLICYLOCKGRANT + one SESSIONCHALLENGESUPERSEDE + one ROOMCONTRACT + one CALLBACKCONSUMER + one ENROLLTOKENSINGLEUSE + one ROOMCONTRACT-ACTIVEFIRST + one ONBOARD + one HOSTED + one HOSTED-FOLLOWUPS + one OWNPOST + one SIDSCHEMA + one SIDOWNER + one GRANTTARGETROLE (#674) + one LASTOWNER (Consiliency/message-board#675) + one SESSIONPROVENANCE (Consiliency/message-board#665) + one REQUESTREMOVED (Consiliency/message-board#680) + one RLSCORRELATION (Consiliency/message-board#589) + one RESOLUTIONAUTHORITY (Consiliency/message-board#668) forward migrations (migrationCount = prior 113 + 5 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 =
|
|
44
|
+
it('registers the four MBAUTHZ + four MBSENDAUTHZ + four MBSESSION + four MBDELEG + three MBFED + three MBHARDEN + two MBPORTALGATE + two MBPORTAL-PR32 + two ROOMOWN + two ROOMLINK + one ROOMDELEG + one LOCALAUTH + one ROOMUIAPI + one FEDSESSION + one FEDSESSION-AUTOJOIN + one GATENULL + one MEMBSTATE + one AGENTSDIR + one LEAVEIDEM + one ROLERESET + one MBROWID + one MBHYGIENE + one MBCONSENT-A + one MBCONSENT-B(a) + one MBCONSENT-B(i) + one MBCONSENT-B(ii) + one MBCONSENT-B(iii) + one MBHARDEN-#97 + one MBHARDEN-#118 + one INVITEPOLICY + one OBSGATE + one OBSGATE-2 + one OBSGATE-3 + one OBSGATE-4 + one FLEETMACHINERLS + one RESOLVENOOP + one ROOMDELEG-LANEB + one CLAIMKEY + two MINTHARDEN + one FLEETMACHINEHIJACK + one CLAIMGATE-SHADOW + one CLAIMGATE-ENFORCE + one FLEETMACHINEREACTIVATION + one DELEGCAPCEILING + one FLEETMACHINERECLAIM + one DELEGSOLEWRITER + one FLEETDOMAINRECLAIM + five ATOMICFLEETONBOARDING (onboarding + ceiling-lock + revocation-evidence + fedsession-gate + fedsession-lock-order) + one OUTBOXWAKE + one ENROLLLOCKORDER + one FEDPROVIDERABSENCE + one WAKERECOVERY + one CONSENTRECONCILE + one ENROLLRESUMPTION + one SIGNEDAUTHORITY + one SIGNERLIFECYCLE + one LEDGERAUTHORITY + one CEILINGLOCKCOMMENT + one LEDGERBOARDCREATE + one RECEIPTSUBJECTGATE + one TASKTHREADLOCKORDER + one CLAIMSUBJECTGATE + one FEDSESSIONIDENTITYGATE + one FEDIDENTITYSLUG + one INVITENODOWNGRADE + one SIGNEDWRITEFLAG + one SIGNEDWRITEMODEL + one RTCREDCLAIM + one ORIGINPOSTURE + one BOARDCLAIMPOLICY + one HEARTBEATPRESERVE + one LIVENESSDENOM + one OWNERLESSRENEWTTL + one OWNERLESSQUOTACENSUS + one FLEETDOMAINNODOWNGRADE + one OWNERLESSQUOTACONVERGE + one ADVISORYREVERTRESET + one CLAIMPOLICYRACE + one CLAIMPOLICYLOCKGRANT + one SESSIONCHALLENGESUPERSEDE + one ROOMCONTRACT + one CALLBACKCONSUMER + one ENROLLTOKENSINGLEUSE + one ROOMCONTRACT-ACTIVEFIRST + one ONBOARD + one HOSTED + one HOSTED-FOLLOWUPS + one OWNPOST + one SIDSCHEMA + one SIDOWNER + one GRANTTARGETROLE (#674) + one LASTOWNER (Consiliency/message-board#675) + one SESSIONPROVENANCE (Consiliency/message-board#665) + one REQUESTREMOVED (Consiliency/message-board#680) + one RLSCORRELATION (Consiliency/message-board#589) + one RESOLUTIONAUTHORITY (Consiliency/message-board#668) + one THREADASSOCIATION checkpoint (#667) + one SIDSERVER-MEASUREDMINT (Consiliency/message-board#653) + one REPLYDELIVERY (#661) + one DELIVERYWRITEREXEC (#717 F1) + one REPLAYSCOPE (#717 F2) + one MESSAGEREPLAYSCOPE (#717 F2b) forward migrations (migrationCount = prior 113 + 5 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 = 172)', () => {
|
|
45
45
|
expect(manifest.migrationCount).toBe(manifest.migrations.length);
|
|
46
|
-
expect(manifest.migrationCount).toBe(
|
|
46
|
+
expect(manifest.migrationCount).toBe(172);
|
|
47
47
|
// MBSESSION switched enforcement on (scoped-send re-grant): the client-visible
|
|
48
48
|
// schema version bumped to 8. MBDELEG tightens delegation and MBFED adds only
|
|
49
49
|
// enrollment-only additive surface (identity_providers registry, enrollment audit,
|
|
@@ -368,6 +368,12 @@ describe('manifest integrity', () => {
|
|
|
368
368
|
'20261015000200_agent_board_request_preserve_removed.sql',
|
|
369
369
|
'20261015000300_agent_board_rls_correlation.sql',
|
|
370
370
|
'20261015000400_agent_board_resolution_authority.sql',
|
|
371
|
+
'20261026000100_agent_board_thread_association.sql',
|
|
372
|
+
'20261101000100_agent_board_session_measured_mint.sql',
|
|
373
|
+
'20261104065658_agent_board_reply_delivery.sql',
|
|
374
|
+
'20261104170000_agent_board_tasking_replay_scope.sql',
|
|
375
|
+
'20261104180000_agent_board_delivery_writer_execute.sql',
|
|
376
|
+
'20261104190000_agent_board_message_replay_scope.sql',
|
|
371
377
|
]) {
|
|
372
378
|
expect(names.has(f)).toBe(true);
|
|
373
379
|
}
|