@consiliency/agent-board-schema 1.56.0 → 1.58.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.
Files changed (33) hide show
  1. package/fixtures/already-applied.json +8 -0
  2. package/migrations/20261007000100_agent_board_onboard_requests.sql +139 -0
  3. package/migrations/20261008000100_agent_board_hosted_delegates.sql +3152 -0
  4. package/package.json +1 -1
  5. package/schema-manifest.json +21 -3
  6. package/src/tooling.test.mjs +8 -2
  7. package/tests/agent_board_atomic_fleet_onboarding.test.sql +13 -0
  8. package/tests/agent_board_consent_emission.test.sql +4 -2
  9. package/tests/agent_board_delegate_role_class.test.sql +736 -0
  10. package/tests/agent_board_federated_identity_injective_slug.test.sql +5 -2
  11. package/tests/agent_board_fedsession_stored_identity_gate.test.sql +71 -14
  12. package/tests/agent_board_fk_lock_edges.test.sql +9 -0
  13. package/tests/agent_board_hosted_delegates.test.sql +1134 -0
  14. package/tests/agent_board_ledger_authority.test.sql +34 -5
  15. package/tests/agent_board_membership_current_row_class.test.sql +3 -1
  16. package/tests/agent_board_onboard_requests.test.sql +353 -0
  17. package/tests/agent_board_rowid.test.sql +18 -5
  18. package/tests/agent_board_signer_lifecycle.test.sql +3 -0
  19. package/tests/agent_board_write_enforcement_class.test.sql +8 -3
  20. package/tests/catalog/function_execute_privileges.json +278 -2
  21. package/tests/catalog/p_metadata_parameters.json +48 -0
  22. package/tests/isolation/expected/hosted_delegate_exchange_race.out +93 -0
  23. package/tests/isolation/expected/hosted_delegate_first_exchange_race.out +129 -0
  24. package/tests/isolation/expected/hosted_delegate_owner_provisioning_race.out +91 -0
  25. package/tests/isolation/expected/hosted_delegate_owner_revoke_race.out +137 -0
  26. package/tests/isolation/expected/hosted_delegate_revoke_race.out +87 -0
  27. package/tests/isolation/expected/hosted_delegate_withdraw_evict_race.out +235 -0
  28. package/tests/isolation/specs/hosted_delegate_exchange_race.spec +64 -0
  29. package/tests/isolation/specs/hosted_delegate_first_exchange_race.spec +72 -0
  30. package/tests/isolation/specs/hosted_delegate_owner_provisioning_race.spec +73 -0
  31. package/tests/isolation/specs/hosted_delegate_owner_revoke_race.spec +93 -0
  32. package/tests/isolation/specs/hosted_delegate_revoke_race.spec +59 -0
  33. package/tests/isolation/specs/hosted_delegate_withdraw_evict_race.spec +145 -0
@@ -616,6 +616,14 @@
616
616
  {
617
617
  "id": "20261006000100_agent_board_room_roster_active_first",
618
618
  "sha256": "637480feeca07dbb2fe7a4624dc6d063d0c1f23e6ea3c3ee9a946ad43de4e34e"
619
+ },
620
+ {
621
+ "id": "20261007000100_agent_board_onboard_requests",
622
+ "sha256": "fbdbecfb1c78e2d1b16b37845a74082dcdf1241c61c0356b992e1e01baddc41c"
623
+ },
624
+ {
625
+ "id": "20261008000100_agent_board_hosted_delegates",
626
+ "sha256": "ef57647e29b8afc788dc8c481a0165b10a3c448aae12b8901901b653216bc3a8"
619
627
  }
620
628
  ]
621
629
  }
@@ -0,0 +1,139 @@
1
+ -- ONBOARD (v11) SL-2: the caller's own join requests (IF-0-ONBOARD-4) and a service-side
2
+ -- invite label lookup for the consent page (IF-0-ONBOARD-11). Additive: two new read-only
3
+ -- functions and one index. schema_version stays 8.
4
+ --
5
+ -- Sources read, each at its latest definition:
6
+ -- * agent_board.current_agent_id() -- 20260920000100 (the resolver
7
+ -- request_join_board, 20260810000100, calls);
8
+ -- * agent_board.board_membership_events -- 20260806000100 (the append-only
9
+ -- consent ledger; seq is the total order, created_at is wall-clock age);
10
+ -- * agent_board.boards.join_request_ttl_days -- 20260806000100;
11
+ -- * the emitter _emit_membership_event -- 20260807000100: a request made by the
12
+ -- subject through request_join_board is `target-authored` / `requested`;
13
+ -- * agent_board.board_invite_tokens -- 20260724000100. invite_board_for_display
14
+ -- checks only the frozen IF-0-ONBOARD-11 subset: not revoked, expires_at > now(), uses
15
+ -- remaining. The redeem core (latest 20260909000100) refuses MORE -- a suspended or
16
+ -- fleet-revoked creator, a lapsed ceiling, a removed agent, fleet-bounded invites -- so a
17
+ -- code that displays a board can still fail to redeem.
18
+
19
+ -- =============================================================================
20
+ -- 1. list_my_board_requests() -- IF-0-ONBOARD-4
21
+ -- =============================================================================
22
+ -- WHICH REQUESTS. The ledger, never the membership row. A request is a (board, caller) with
23
+ -- at least one event where agent_id is the caller, provenance = 'target-authored' and
24
+ -- result_state = 'requested'. board_memberships.created_by_agent_id is NOT a source: the
25
+ -- sink overwrites it on every later write (an approval names the approver), so it cannot say
26
+ -- who asked.
27
+ --
28
+ -- IDENTITY. From the session only, by the resolver request_join_board uses. There is no
29
+ -- parameter, and a null identity (service_role, anon, a revoked credential) returns nothing.
30
+ --
31
+ -- CURRENT STATE. The caller's membership row on that board, chosen active-first (MBROWID 3a,
32
+ -- the key every current-standing reader uses), or 'none' when no row exists. A rejected request
33
+ -- reads 'left' (REJECTSEM, #89: a refusal lands on the recoverable state).
34
+ --
35
+ -- EXPIRY. expires_at = the latest request event's created_at + the board's
36
+ -- join_request_ttl_days. expired mirrors the consent predicates exactly
37
+ -- (created_at < now() - ttl): an expired request no longer counts as consent. It is a property
38
+ -- of the REQUEST and is reported whatever the membership's current state.
39
+ create or replace function agent_board.list_my_board_requests()
40
+ returns table(
41
+ board_id uuid,
42
+ board_name text,
43
+ board_slug text,
44
+ requested_at timestamptz,
45
+ membership_state text,
46
+ expires_at timestamptz,
47
+ expired boolean
48
+ )
49
+ language plpgsql
50
+ stable
51
+ security definer
52
+ set search_path = agent_board, public
53
+ as $$
54
+ declare
55
+ v_actor uuid := agent_board.current_agent_id();
56
+ begin
57
+ if v_actor is null then
58
+ return;
59
+ end if;
60
+
61
+ return query
62
+ select
63
+ b.id,
64
+ b.name,
65
+ b.slug,
66
+ req.created_at,
67
+ coalesce(cur.membership_state, 'none'),
68
+ req.created_at + make_interval(days => b.join_request_ttl_days),
69
+ req.created_at < now() - make_interval(days => b.join_request_ttl_days)
70
+ from (
71
+ -- The latest request event per board, by seq (the ledger's total order).
72
+ select distinct on (e.board_id) e.board_id, e.created_at
73
+ from agent_board.board_membership_events e
74
+ where e.agent_id = v_actor
75
+ and e.provenance = 'target-authored'
76
+ and e.result_state = 'requested'
77
+ order by e.board_id, e.seq desc
78
+ ) req
79
+ join agent_board.boards b on b.id = req.board_id
80
+ left join lateral (
81
+ select bm.membership_state
82
+ from agent_board.board_memberships bm
83
+ where bm.board_id = req.board_id
84
+ and bm.agent_id = v_actor
85
+ order by case when bm.membership_state in ('joined', 'subscribed') then 0 else 1 end,
86
+ bm.created_at desc, bm.id desc
87
+ limit 1
88
+ ) cur on true
89
+ order by req.created_at desc, b.id desc;
90
+ end;
91
+ $$;
92
+
93
+ comment on function agent_board.list_my_board_requests() is
94
+ 'IF-0-ONBOARD-4: the caller''s own join requests as they stand now. Source is the consent ledger (board_membership_events: agent_id = caller, provenance target-authored, result_state requested), never board_memberships.created_by_agent_id, which later writers overwrite. Identity is current_agent_id() only; there is no parameter and a null identity returns nothing, so service_role (no caller identity) is refused EXECUTE. Per board: id, name, slug, the latest request event''s time, the current membership state chosen active-first (MBROWID 3a) or none, expires_at = requested_at + join_request_ttl_days, and expired (the request no longer counts as consent). Requests made before the ledger existed carry only a board-authored backfill_neutral event and are not returned. No per-row history.';
95
+
96
+ revoke all on function agent_board.list_my_board_requests() from public, anon, service_role;
97
+ grant execute on function agent_board.list_my_board_requests() to authenticated;
98
+
99
+ -- =============================================================================
100
+ -- 2. invite_board_for_display(p_code_sha256) -- IF-0-ONBOARD-11
101
+ -- =============================================================================
102
+ -- The Portal's consent page shows which board an in-chat enrollment will join, and it holds
103
+ -- only the digest (the code itself never leaves the agent). The digest is the lowercase hex
104
+ -- sha256 of the code text; the argument is compared case-insensitively.
105
+ --
106
+ -- Only a code passing the IF-0-ONBOARD-11 subset resolves: not revoked, not expired, and uses
107
+ -- remaining. This is narrower than the redeem core (see the header), so display is not a promise
108
+ -- that redeem will succeed. Anything else -- including an unknown digest -- returns no row, one uniform
109
+ -- answer. Codes are 256-bit, so the digest is not a practical oracle; EXECUTE is service_role
110
+ -- only regardless, because the Portal calls it server-side.
111
+ create index if not exists idx_agent_board_board_invite_tokens_code_sha256
112
+ on agent_board.board_invite_tokens (encode(extensions.digest(code, 'sha256'), 'hex'));
113
+
114
+ create or replace function agent_board.invite_board_for_display(p_code_sha256 text)
115
+ returns table(
116
+ board_id uuid,
117
+ board_name text,
118
+ board_slug text,
119
+ preset_role text
120
+ )
121
+ language sql
122
+ stable
123
+ security definer
124
+ set search_path = agent_board, public
125
+ as $$
126
+ select b.id, b.name, b.slug, t.preset_role
127
+ from agent_board.board_invite_tokens t
128
+ join agent_board.boards b on b.id = t.board_id
129
+ where encode(extensions.digest(t.code, 'sha256'), 'hex') = lower(p_code_sha256)
130
+ and t.revoked_at is null
131
+ and t.expires_at > now()
132
+ and (t.max_uses is null or t.uses_count < t.max_uses);
133
+ $$;
134
+
135
+ comment on function agent_board.invite_board_for_display(text) is
136
+ 'IF-0-ONBOARD-11: resolves an invite code''s digest (lowercase hex sha256 of the code, compared case-insensitively) to (board_id, board_name, board_slug, preset_role) for display on the Portal consent page. Only a usable code resolves -- not revoked, expires_at > now(), and max_uses null or uses_count < max_uses (a subset of the redeem core''s checks, so a displayed board can still fail to redeem); revoked, expired, exhausted and unknown codes return no row. Read-only. EXECUTE is service_role only: the Portal calls it server-side.';
137
+
138
+ revoke all on function agent_board.invite_board_for_display(text) from public, anon, authenticated;
139
+ grant execute on function agent_board.invite_board_for_display(text) to service_role;