@consiliency/agent-board-schema 1.64.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/README.md +19 -0
- package/fixtures/already-applied.json +44 -4
- package/migrations/20261015000100_agent_board_session_provenance.sql +367 -0
- package/migrations/20261015000200_agent_board_request_preserve_removed.sql +87 -0
- package/migrations/20261015000300_agent_board_rls_correlation.sql +132 -0
- package/migrations/20261015000400_agent_board_resolution_authority.sql +146 -0
- 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 +93 -3
- package/src/deployment-drift-main.test.mjs +156 -0
- package/src/deployment-drift-script.test.mjs +14 -1
- package/src/policy-comment.test.mjs +17 -0
- package/src/tooling.test.mjs +12 -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_consent_gating.test.sql +4 -4
- 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_gatenull_membstate.test.sql +7 -4
- 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_policy_correlation.test.sql +189 -0
- package/tests/agent_board_request_removed.test.sql +96 -0
- package/tests/agent_board_resolution_authority.test.sql +190 -0
- 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_session_provenance.test.sql +106 -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 +43 -7
- 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/consent_approval_lock.out +1 -1
- 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/consent_approval_lock.spec +13 -7
- 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,145 @@
|
|
|
1
|
+
-- SIDSERVER blocker fix (Consiliency/message-board#653 panel BLOCKs 1 and 2; owner decision
|
|
2
|
+
-- 2026-11-01 "Fix + new replay round", shape "Measured overload" -- a separate strict function
|
|
3
|
+
-- the relay calls exclusively; named distinctly by exec decision so that every frozen
|
|
4
|
+
-- one-row-per-name contract (SIDCLIENT) keeps holding).
|
|
5
|
+
--
|
|
6
|
+
-- The seven-argument mint_fleet_agent_session is the SIDSCHEMA "trusted caller" form: it gates
|
|
7
|
+
-- on the STORED current/approved digests and lets a lapsed Claude identity bind any unseen
|
|
8
|
+
-- session id. Frozen SIDSCHEMA tests pin both behaviours, so that form is left byte-identical.
|
|
9
|
+
-- The relay must instead call this measured function, which receives the PoP-verified binding's
|
|
10
|
+
-- measured fingerprint, continuity and predecessor and:
|
|
11
|
+
--
|
|
12
|
+
-- 1. records the measured reading after the challenge is validated and consumed, and on a
|
|
13
|
+
-- changed risky digest durably freezes the identity and RETURNS a refusal row (raising
|
|
14
|
+
-- would roll the freeze back; the refused session row is revoked in the same transaction);
|
|
15
|
+
-- 2. binds a NEW alias on a lapsed reclaim only for continuity preserved_uuids whose
|
|
16
|
+
-- predecessor is this identity; any other unfamiliar alias refuses identity_continuity_refused;
|
|
17
|
+
-- 3. stores the CLAIMANT'S presented holder secret when it claims or reclaims (generating one
|
|
18
|
+
-- only when none is presented), so a claim whose response is lost is recovered in place: the
|
|
19
|
+
-- retry re-presents that secret and refreshes the claimant's own live lease (#653 re-panel
|
|
20
|
+
-- BLOCK B). On a live lease the identical bound session id refuses duplicate_live_session
|
|
21
|
+
-- whatever secret it presents, then a wrong secret refuses identity_lease_not_held, so every
|
|
22
|
+
-- OTHER claimant is still refused while the lease is live.
|
|
23
|
+
--
|
|
24
|
+
-- The residual -- a service_role caller can still choose the seven-argument trusted form -- is
|
|
25
|
+
-- pre-existing and recorded on Consiliency/message-board#722.
|
|
26
|
+
create function agent_board.mint_fleet_agent_session_measured(
|
|
27
|
+
p_challenge_id uuid, p_nonce text, p_signing_key_id uuid, p_agent_id uuid,
|
|
28
|
+
p_max_ttl_seconds integer, p_holder_secret text, p_session_id text,
|
|
29
|
+
p_fingerprint jsonb, p_continuity text, p_predecessor_agent_id uuid
|
|
30
|
+
) returns table(session_id text, expires_at timestamptz, identity_lease_epoch bigint, holder_secret text, refusal text)
|
|
31
|
+
language plpgsql security definer set search_path = agent_board, public as $$
|
|
32
|
+
declare v_identity agent_board.session_identities%rowtype; v_session record; v_new_secret text; v_alias uuid;
|
|
33
|
+
v_ancestor_expires timestamptz; v_grant_expires timestamptz; v_state text;
|
|
34
|
+
v_risky text := nullif(p_fingerprint ->> 'risky_digest', '');
|
|
35
|
+
v_recorded jsonb;
|
|
36
|
+
begin
|
|
37
|
+
if not agent_board._is_service_role() then raise exception 'session mint is service_role-only' using errcode = '42501'; end if;
|
|
38
|
+
if p_fingerprint is null or jsonb_typeof(p_fingerprint) <> 'object'
|
|
39
|
+
or coalesce(p_fingerprint ->> 'resolution', '') not in ('resolved', 'unresolved')
|
|
40
|
+
or jsonb_typeof(coalesce(p_fingerprint -> 'recorded', '{}'::jsonb)) <> 'object' then
|
|
41
|
+
raise exception 'invalid identity fingerprint reading' using errcode = '22023';
|
|
42
|
+
end if;
|
|
43
|
+
v_recorded := coalesce(p_fingerprint -> 'recorded', '{}'::jsonb) || jsonb_build_object('resolution', p_fingerprint ->> 'resolution');
|
|
44
|
+
if p_holder_secret is not null and p_holder_secret !~ '^[0-9a-f]{64}$' then
|
|
45
|
+
raise exception 'invalid holder secret' using errcode = '22023';
|
|
46
|
+
end if;
|
|
47
|
+
if p_session_id is null or length(p_session_id) = 0
|
|
48
|
+
or p_continuity is null or p_continuity not in ('same_alias', 'preserved_uuids', 'new', 'fork', 'ambiguous_fork') then
|
|
49
|
+
raise exception 'invalid measured session binding' using errcode = '22023';
|
|
50
|
+
end if;
|
|
51
|
+
-- The predecessor is the measured continuity evidence: preserved UUIDs name this identity,
|
|
52
|
+
-- every other class names none at a token mint.
|
|
53
|
+
if p_continuity = 'preserved_uuids' and p_predecessor_agent_id is distinct from p_agent_id
|
|
54
|
+
or p_continuity <> 'preserved_uuids' and p_predecessor_agent_id is not null then
|
|
55
|
+
raise exception 'identity_continuity_refused' using errcode = '42501';
|
|
56
|
+
end if;
|
|
57
|
+
-- Same challenge-before-principal and identity/alias-before-key order as the trusted form.
|
|
58
|
+
perform 1 from agent_board.agent_signing_key_challenges where id = p_challenge_id for update;
|
|
59
|
+
perform 1 from agent_board.agents where id = (
|
|
60
|
+
select root_agent_id from agent_board.session_identities where agent_id = p_agent_id
|
|
61
|
+
) for no key update;
|
|
62
|
+
select * into v_identity from agent_board.session_identities where agent_id = p_agent_id for update;
|
|
63
|
+
perform 1 from agent_board.session_id_aliases where identity_agent_id = p_agent_id order by id for update;
|
|
64
|
+
if v_identity.tombstoned_at is not null then raise exception 'identity_tombstoned' using errcode = '42501'; end if;
|
|
65
|
+
if v_identity.agent_id is null or v_identity.identity_kind <> 'session' then
|
|
66
|
+
raise exception 'measured mint requires a session identity' using errcode = '22023';
|
|
67
|
+
end if;
|
|
68
|
+
if not exists (select 1 from agent_board.agent_signing_keys k where k.id = p_signing_key_id
|
|
69
|
+
and k.agent_id = p_agent_id and k.proof_state = 'proven') then
|
|
70
|
+
raise exception 'key_unproven: session key requires proof' using errcode = '42501';
|
|
71
|
+
end if;
|
|
72
|
+
-- Validates and consumes the challenge (and the key/principal/grant gates) BEFORE the reading
|
|
73
|
+
-- is stored, so only a reading bound to a proven, single-use challenge can be recorded.
|
|
74
|
+
select * into v_session from agent_board._mint_fleet_agent_session_legacy(p_challenge_id, p_nonce, p_signing_key_id, p_agent_id, p_max_ttl_seconds);
|
|
75
|
+
v_state := case
|
|
76
|
+
when p_fingerprint ->> 'resolution' is distinct from 'resolved' or v_risky is null
|
|
77
|
+
or v_identity.approved_risky_digest is null then 'frozen'
|
|
78
|
+
when v_risky is distinct from v_identity.approved_risky_digest or v_identity.resolution_state = 'frozen' then 'frozen'
|
|
79
|
+
else 'active' end;
|
|
80
|
+
update agent_board.session_identities
|
|
81
|
+
set current_risky_digest = v_risky, recorded_fingerprint = v_recorded, resolution_state = v_state, updated_at = now()
|
|
82
|
+
where agent_id = p_agent_id;
|
|
83
|
+
if v_state = 'frozen' or exists (
|
|
84
|
+
with recursive ancestry(id, parent_agent_id) as (
|
|
85
|
+
select id, parent_agent_id from agent_board.agents where id = p_agent_id
|
|
86
|
+
union all
|
|
87
|
+
select a.id, a.parent_agent_id from agent_board.agents a join ancestry c on a.id = c.parent_agent_id
|
|
88
|
+
)
|
|
89
|
+
select 1 from ancestry a join agent_board.session_identities si on si.agent_id = a.id
|
|
90
|
+
where si.resolution_state = 'frozen'
|
|
91
|
+
) then
|
|
92
|
+
-- Return, never raise: the recorded reading and freeze must commit with this refusal.
|
|
93
|
+
update agent_board.nonfleet_sessions s set revoked_at = now() where s.session_id = v_session.session_id;
|
|
94
|
+
return query select null::text, null::timestamptz, null::bigint, null::text, 'identity_fingerprint_unapproved'::text; return;
|
|
95
|
+
end if;
|
|
96
|
+
v_ancestor_expires := agent_board._session_identity_ancestor_ceiling(v_identity.parent_agent_id);
|
|
97
|
+
if not agent_board._session_identity_lease_live(p_agent_id) then
|
|
98
|
+
perform agent_board._session_identity_check_limits(v_identity.root_agent_id, v_identity.parent_agent_id, p_agent_id);
|
|
99
|
+
end if;
|
|
100
|
+
select g.grant_expires_at into v_grant_expires from agent_board.delegation_grants g where g.child_agent_id = p_agent_id;
|
|
101
|
+
v_session.expires_at := least(v_session.expires_at, v_ancestor_expires, v_grant_expires);
|
|
102
|
+
update agent_board.nonfleet_sessions s set expires_at = v_session.expires_at where s.session_id = v_session.session_id;
|
|
103
|
+
if v_identity.holder_secret_hash is not null and v_identity.last_heartbeat > now() - interval '180 seconds' then
|
|
104
|
+
if p_holder_secret is not null and extensions.digest(p_holder_secret, 'sha256') = v_identity.holder_secret_hash then
|
|
105
|
+
return query select v_session.session_id, v_session.expires_at, v_identity.credential_epoch, null::text, null::text; return;
|
|
106
|
+
end if;
|
|
107
|
+
if exists (select 1 from agent_board.session_id_aliases a where a.id = v_identity.lease_alias_id and a.session_id = p_session_id) then
|
|
108
|
+
raise exception 'duplicate_live_session' using errcode = '42501';
|
|
109
|
+
end if;
|
|
110
|
+
if p_holder_secret is not null then raise exception 'identity_lease_not_held' using errcode = '42501'; end if;
|
|
111
|
+
raise exception 'identity_lease_live' using errcode = '42501';
|
|
112
|
+
end if;
|
|
113
|
+
select a.id into v_alias from agent_board.session_id_aliases a
|
|
114
|
+
where a.identity_agent_id = p_agent_id and a.session_id = p_session_id;
|
|
115
|
+
if v_identity.holder_secret_hash is null then
|
|
116
|
+
if v_alias is null or v_alias is distinct from v_identity.lease_alias_id then raise exception 'identity_continuity_refused' using errcode = '42501'; end if;
|
|
117
|
+
elsif v_alias is null then
|
|
118
|
+
-- A lapsed reclaim may bind an unseen session id only as measured preserved-UUID continuity
|
|
119
|
+
-- (Claude resume; the predecessor = this identity rule is enforced once, above). Same-alias,
|
|
120
|
+
-- new and fork claims never mint a new alias.
|
|
121
|
+
if v_identity.harness <> 'claude' or p_continuity <> 'preserved_uuids' then
|
|
122
|
+
raise exception 'identity_continuity_refused' using errcode = '42501';
|
|
123
|
+
end if;
|
|
124
|
+
if exists (select 1 from agent_board.session_id_aliases a where a.root_agent_id = v_identity.root_agent_id
|
|
125
|
+
and a.harness = v_identity.harness and a.session_id = p_session_id) then
|
|
126
|
+
raise exception 'identity_continuity_refused' using errcode = '42501';
|
|
127
|
+
end if;
|
|
128
|
+
insert into agent_board.session_id_aliases(identity_agent_id, root_agent_id, harness, session_id)
|
|
129
|
+
values (p_agent_id, v_identity.root_agent_id, v_identity.harness, p_session_id) returning id into v_alias;
|
|
130
|
+
end if;
|
|
131
|
+
-- The claimant's own presented secret becomes the lease secret (the relay admits only 64 lower
|
|
132
|
+
-- hex); a claimant presenting none gets a generated one, as in the trusted form.
|
|
133
|
+
v_new_secret := coalesce(p_holder_secret, encode(extensions.gen_random_bytes(32), 'hex'));
|
|
134
|
+
update agent_board.session_identities
|
|
135
|
+
set holder_secret_hash = extensions.digest(v_new_secret, 'sha256'), lease_alias_id = v_alias,
|
|
136
|
+
credential_epoch = case when holder_secret_hash is null then credential_epoch else credential_epoch + 1 end,
|
|
137
|
+
last_heartbeat = now(), updated_at = now()
|
|
138
|
+
where agent_id = p_agent_id
|
|
139
|
+
returning credential_epoch into identity_lease_epoch;
|
|
140
|
+
return query select v_session.session_id, v_session.expires_at, identity_lease_epoch, v_new_secret, null::text;
|
|
141
|
+
end;
|
|
142
|
+
$$;
|
|
143
|
+
revoke all on function agent_board.mint_fleet_agent_session_measured(uuid, text, uuid, uuid, integer, text, text, jsonb, text, uuid) from public, anon, authenticated, service_role;
|
|
144
|
+
grant execute on function agent_board.mint_fleet_agent_session_measured(uuid, text, uuid, uuid, integer, text, text, jsonb, text, uuid) to service_role;
|
|
145
|
+
comment on function agent_board.mint_fleet_agent_session_measured(uuid, text, uuid, uuid, integer, text, text, jsonb, text, uuid) is 'Service-role MEASURED session-identity PoP mint, the only session-identity mint the /session relay calls. It enforces every gate of the seven-argument mint_fleet_agent_session trusted form (pgTAP SIDSERVER-MM-PARITY-*) plus measured-reading and continuity gates. Fingerprint, continuity and predecessor come from the PoP-verified session binding. After the challenge is validated and consumed it records the measured reading; a changed or unresolved risky digest (or any frozen ancestor) durably freezes and RETURNS refusal identity_fingerprint_unapproved instead of raising, so the freeze commits and the refused session row is revoked. A lapsed reclaim binds an unseen alias only for preserved_uuids continuity naming this identity; otherwise identity_continuity_refused. A claim or reclaim stores the claimant-presented holder secret (generated only when none is presented), so a claim whose response was lost refreshes on retry; on a live lease the bound session id refuses duplicate_live_session before a wrong secret refuses identity_lease_not_held. Epoch rotation matches the seven-argument trusted form, which remains for SIDSCHEMA callers (residual: Consiliency/message-board#722).';
|