@consiliency/agent-board-schema 1.24.0 → 1.27.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 +12 -0
- package/migrations/20260906000100_agent_board_enroll_resumption.sql +749 -0
- package/migrations/20260907000100_agent_board_signed_authority_provenance.sql +243 -0
- package/migrations/20260908000100_agent_board_signer_lifecycle_revalidation.sql +451 -0
- package/package.json +1 -1
- package/schema-manifest.json +30 -3
- package/src/tooling.test.mjs +3 -3
- package/tests/agent_board_atomic_fleet_onboarding.test.sql +129 -112
- package/tests/agent_board_claimkey.test.sql +25 -3
- package/tests/agent_board_consent_emission.test.sql +17 -13
- package/tests/agent_board_consent_gating.test.sql +55 -11
- package/tests/agent_board_delegation_policies.test.sql +3 -1
- package/tests/agent_board_enroll_resumption.test.sql +412 -0
- package/tests/agent_board_federated_lock_order_class.test.sql +1 -3
- package/tests/agent_board_fedsession_provider_absence_gate.test.sql +9 -6
- package/tests/agent_board_fleet_machine_reactivation.test.sql +56 -5
- package/tests/agent_board_mint_harden.test.sql +39 -4
- package/tests/agent_board_outbox_wake_ordering.test.sql +27 -12
- package/tests/agent_board_rejectsem.test.sql +1 -1
- package/tests/agent_board_rolereset.test.sql +23 -2
- package/tests/agent_board_rowid.test.sql +24 -13
- package/tests/agent_board_scoped_send_regrant.test.sql +8 -4
- package/tests/agent_board_signed_authority_provenance.test.sql +477 -0
- package/tests/agent_board_signer_lifecycle.test.sql +709 -0
- package/tests/agent_board_source_strip_helper.test.sql +285 -0
- package/tests/agent_board_wake_recovery.test.sql +58 -40
- package/tests/catalog/p_metadata_parameters.json +693 -0
- package/tests/fixtures/test-prereqs.sql +313 -0
- package/tests/isolation/expected/atomic_fleet_lifecycle_races.out +3 -3
- package/tests/isolation/expected/signed_grant_onboarding_deadlock.out +220 -0
- package/tests/isolation/expected/signer_lifecycle_revoke.out +307 -0
- package/tests/isolation/specs/signed_grant_onboarding_deadlock.spec +159 -0
- package/tests/isolation/specs/signer_lifecycle_revoke.spec +176 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
-- ===========================================================================
|
|
2
|
+
-- agent_board_test.strip_sql — the shared source-text strip every positional
|
|
3
|
+
-- and negative pgTAP assertion in this suite now reads through
|
|
4
|
+
-- (message-board#196, message-board#199).
|
|
5
|
+
--
|
|
6
|
+
-- WHY THIS FILE EXISTS. The strip is now a single point of failure for ~47
|
|
7
|
+
-- assertion sites across 14 files. Before it was shared, each file carried its
|
|
8
|
+
-- own regex; the two most hardened copies were kept deliberately byte-identical
|
|
9
|
+
-- so they could not drift, and they were both WRONG in the same way -- a nested
|
|
10
|
+
-- block comment walked straight through them and left
|
|
11
|
+
-- agent_board_atomic_fleet_onboarding at 52/52 and
|
|
12
|
+
-- agent_board_federated_lock_order_class at 15/15 with a lock genuinely moved.
|
|
13
|
+
-- A shared scanner without its own vectors would just be one wrong copy instead
|
|
14
|
+
-- of two, so every escape hatch the helper's header CLAIMS to close is asserted
|
|
15
|
+
-- here, and the claim is treated as falsifiable.
|
|
16
|
+
--
|
|
17
|
+
-- WHAT A REGEX CANNOT DO, and why this is a character scanner. Postgres block
|
|
18
|
+
-- comments NEST. Nested delimiters are not a regular language, and Postgres'
|
|
19
|
+
-- regex engine has no recursion, so no regular expression -- however clever --
|
|
20
|
+
-- can match `/* a /* b */ c */`. Every regex-based strip in the tree stopped at
|
|
21
|
+
-- the FIRST `*/` and handed back the text after it as if it were code.
|
|
22
|
+
--
|
|
23
|
+
-- The last three assertions are CORPUS-WIDE and catalog-derived: they run the
|
|
24
|
+
-- scanner over every live agent_board function rather than over vectors, so a
|
|
25
|
+
-- desync on real source (which is exactly how #199 was found) fails here.
|
|
26
|
+
-- ===========================================================================
|
|
27
|
+
create extension if not exists pgtap with schema extensions;
|
|
28
|
+
set search_path = extensions, public, agent_board;
|
|
29
|
+
|
|
30
|
+
begin;
|
|
31
|
+
|
|
32
|
+
select plan(31);
|
|
33
|
+
|
|
34
|
+
-- ---------------------------------------------------------------------------
|
|
35
|
+
-- The four demonstrated masking constructs.
|
|
36
|
+
-- ---------------------------------------------------------------------------
|
|
37
|
+
select is(
|
|
38
|
+
agent_board_test.strip_sql(E'a -- MARKER\nb'),
|
|
39
|
+
E'a \nb',
|
|
40
|
+
'MASK 1 (line comment): a `--` comment naming the marker is removed');
|
|
41
|
+
|
|
42
|
+
select is(
|
|
43
|
+
agent_board_test.strip_sql('a /* MARKER **/ b'),
|
|
44
|
+
'a b',
|
|
45
|
+
'MASK 2 (block comment ending in `*`): `/* … **/` is removed -- the regex form `(/\*([^*]|\*[^/])*\*/)` could not match this at all');
|
|
46
|
+
|
|
47
|
+
select is(
|
|
48
|
+
agent_board_test.strip_sql(E'a /* note /* x */\nselect * into v_board from agent_board.boards b where b.id = v_inv.board_id for update;\n*/ b'),
|
|
49
|
+
'a b',
|
|
50
|
+
'MASK 3 (NESTED block comment, message-board#199): the code after the INNER `*/` is removed too -- this is the construct that left two hardened files fully green with the lock relocated');
|
|
51
|
+
|
|
52
|
+
select is(
|
|
53
|
+
agent_board_test.strip_sql($x$v_note := 'MARKER'; b$x$),
|
|
54
|
+
'v_note := ; b',
|
|
55
|
+
'MASK 4 (string literal): `raise debug ''…''`-style prose naming the marker is removed');
|
|
56
|
+
|
|
57
|
+
-- ...and the mode that keeps literals keeps EXACTLY the literals, not the comments.
|
|
58
|
+
select is(
|
|
59
|
+
agent_board_test.strip_sql(E'v_note := \'MARKER\'; -- and a comment\nb', true),
|
|
60
|
+
E'v_note := \'MARKER\'; \nb',
|
|
61
|
+
'p_keep_literals keeps the literal (for a marker that IS a literal) and still removes the comment');
|
|
62
|
+
|
|
63
|
+
-- ---------------------------------------------------------------------------
|
|
64
|
+
-- Desync vectors: constructs that make a two-pass or regex scanner lose its
|
|
65
|
+
-- place, so that a LIVE statement afterwards is silently dropped or kept.
|
|
66
|
+
-- ---------------------------------------------------------------------------
|
|
67
|
+
select is(
|
|
68
|
+
agent_board_test.strip_sql($x$x 'it''s -- not a comment' y$x$),
|
|
69
|
+
'x y',
|
|
70
|
+
'DESYNC: a doubled quote does not end the literal, and a `--` inside a literal is not a comment');
|
|
71
|
+
|
|
72
|
+
select is(
|
|
73
|
+
agent_board_test.strip_sql($x$p $r$ don't /* nope $r$ q$x$),
|
|
74
|
+
'p q',
|
|
75
|
+
'DESYNC: a dollar-quoted block with an ODD apostrophe count is consumed whole -- `mark_retention_metadata` survives a naive scanner today only because its 64 apostrophes happen to be even');
|
|
76
|
+
|
|
77
|
+
select is(
|
|
78
|
+
agent_board_test.strip_sql(E'select "weird\'col" -- c\n, z'),
|
|
79
|
+
E'select "weird\'col" \n, z',
|
|
80
|
+
'DESYNC: an apostrophe inside a "quoted identifier" does not open a literal -- the identifier is CODE and survives');
|
|
81
|
+
|
|
82
|
+
-- PostgreSQL permits `$` INSIDE an unquoted identifier and consumes it greedily,
|
|
83
|
+
-- so `foo$tag$danger$tag$` is ONE identifier -- live code, not a dollar-quoted
|
|
84
|
+
-- string. A scanner that does not look at the preceding character reads `$tag$`
|
|
85
|
+
-- as an opener and silently DELETES the rest. Confirmed against the server rather
|
|
86
|
+
-- than argued: `do $do$ declare foo$tag$danger$tag$ int := 7;
|
|
87
|
+
-- begin raise notice '%', foo$tag$danger$tag$; end $do$;` runs and prints 7.
|
|
88
|
+
select is(
|
|
89
|
+
agent_board_test.strip_sql('select foo$tag$danger$tag$ from t'),
|
|
90
|
+
'select foo$tag$danger$tag$ from t',
|
|
91
|
+
'DESYNC: `$` inside an unquoted identifier does not open a dollar quote -- `foo$tag$danger$tag$` is one identifier and survives whole');
|
|
92
|
+
|
|
93
|
+
-- The identifier grammar is NOT ASCII. PostgreSQL accepts any letter the server
|
|
94
|
+
-- encoding recognises, in unquoted identifiers AND in dollar-quote tags, so an
|
|
95
|
+
-- `[A-Za-z0-9_]` class (or an \x80-\xff BYTE range, which is simply wrong for
|
|
96
|
+
-- multi-byte UTF-8) fails in both directions at once. Both confirmed to be legal
|
|
97
|
+
-- SQL against the server, not assumed:
|
|
98
|
+
-- do $do$ begin raise notice '%', $Ω$ hello $Ω$; end $do$;
|
|
99
|
+
-- do $do$ declare Ω$tag$danger$tag$ int := 7; begin raise notice '%', Ω$tag$danger$tag$; end $do$;
|
|
100
|
+
select is(
|
|
101
|
+
agent_board_test.strip_sql('a $Ω$ perform agent_board._lock_board_authority_ceiling(x) $Ω$ b'),
|
|
102
|
+
'a b',
|
|
103
|
+
'DESYNC: a NON-ASCII dollar-quote tag still opens a dollar quote -- a marker planted inside `$Ω$ … $Ω$` is stripped, not handed back as code');
|
|
104
|
+
|
|
105
|
+
select is(
|
|
106
|
+
agent_board_test.strip_sql('select Ω$tag$danger$tag$ from t'),
|
|
107
|
+
'select Ω$tag$danger$tag$ from t',
|
|
108
|
+
'DESYNC: an identifier STARTING with a non-ASCII letter is still an identifier -- `Ω$tag$danger$tag$` survives whole');
|
|
109
|
+
|
|
110
|
+
-- ...and the identifier class must be LOCALE-INDEPENDENT, not merely non-ASCII
|
|
111
|
+
-- aware. `[[:alpha:]]` is locale-sensitive: under `C` collation it does NOT match
|
|
112
|
+
-- `Ω` (measured: `('Ω' collate "C") ~ '[[:alpha:]]'` is FALSE, while the default
|
|
113
|
+
-- collation says TRUE). A scanner built on it passes here and fails on a runner
|
|
114
|
+
-- with a different collation -- and diverges from the JS mirror in scripts/, so the
|
|
115
|
+
-- two enforcement paths would disagree about the same file. These two vectors pin
|
|
116
|
+
-- the behaviour under an explicitly C-collated input.
|
|
117
|
+
select is(
|
|
118
|
+
agent_board_test.strip_sql(('a $Ω$ perform agent_board._lock_board_authority_ceiling(x) $Ω$ b' collate "C")),
|
|
119
|
+
'a b',
|
|
120
|
+
'LOCALE: a non-ASCII dollar-quote tag is stripped under C collation too -- the identifier class is collation-free');
|
|
121
|
+
|
|
122
|
+
select is(
|
|
123
|
+
agent_board_test.strip_sql(('select Ω$tag$danger$tag$ from t' collate "C")),
|
|
124
|
+
'select Ω$tag$danger$tag$ from t',
|
|
125
|
+
'LOCALE: a non-ASCII identifier survives under C collation too');
|
|
126
|
+
|
|
127
|
+
select is(
|
|
128
|
+
agent_board_test.strip_sql('select foo$$danger$$ from t'),
|
|
129
|
+
'select foo$$danger$$ from t',
|
|
130
|
+
'DESYNC: the same holds for the untagged form -- `foo$$danger$$` is an identifier, not code plus a $$-quoted string');
|
|
131
|
+
|
|
132
|
+
select is(
|
|
133
|
+
agent_board_test.strip_sql(E'select $1 + $2 -- c\nfrom t'),
|
|
134
|
+
E'select $1 + $2 \nfrom t',
|
|
135
|
+
'DESYNC: `$1` is a parameter, not a dollar quote -- a tag cannot start with a digit, and treating it as one would swallow live SQL');
|
|
136
|
+
|
|
137
|
+
select is(
|
|
138
|
+
agent_board_test.strip_sql($x$a E'x\'y -- z' b$x$),
|
|
139
|
+
'a b',
|
|
140
|
+
'DESYNC: in an E-string a backslash escapes the closing quote, so the literal ends where the E-string rules say it does');
|
|
141
|
+
|
|
142
|
+
select is(
|
|
143
|
+
agent_board_test.strip_sql($x$a '/*' b '*/' c$x$, true),
|
|
144
|
+
$x$a '/*' b '*/' c$x$,
|
|
145
|
+
'DESYNC: comment OPENERS inside literals are not comment openers, even in keep-literals mode');
|
|
146
|
+
|
|
147
|
+
select is(
|
|
148
|
+
agent_board_test.strip_sql('a/*x*/b'),
|
|
149
|
+
'a b',
|
|
150
|
+
'TOKENS: a stripped construct collapses to a SPACE, so `a/*x*/b` never becomes the identifier `ab`');
|
|
151
|
+
|
|
152
|
+
select is(
|
|
153
|
+
agent_board_test.strip_sql(null),
|
|
154
|
+
null,
|
|
155
|
+
'NULL in, NULL out');
|
|
156
|
+
|
|
157
|
+
-- ---------------------------------------------------------------------------
|
|
158
|
+
-- FAIL CLOSED. An unterminated construct raises rather than returning a
|
|
159
|
+
-- truncated body -- a short string silently satisfies every `!~` in the suite.
|
|
160
|
+
-- ---------------------------------------------------------------------------
|
|
161
|
+
select throws_ok(
|
|
162
|
+
$$ select agent_board_test.strip_sql('a /* oops') $$,
|
|
163
|
+
null, null,
|
|
164
|
+
'FAIL-CLOSED: an unterminated block comment raises instead of returning a truncated body');
|
|
165
|
+
|
|
166
|
+
select throws_ok(
|
|
167
|
+
$$ select agent_board_test.strip_sql('a ''oops') $$,
|
|
168
|
+
null, null,
|
|
169
|
+
'FAIL-CLOSED: an unterminated string literal raises');
|
|
170
|
+
|
|
171
|
+
select throws_ok(
|
|
172
|
+
$$ select agent_board_test.strip_sql('a $q$ oops') $$,
|
|
173
|
+
null, null,
|
|
174
|
+
'FAIL-CLOSED: an unterminated dollar-quoted string raises');
|
|
175
|
+
|
|
176
|
+
select throws_ok(
|
|
177
|
+
$$ select agent_board_test.strip_sql('a "oops') $$,
|
|
178
|
+
null, null,
|
|
179
|
+
'FAIL-CLOSED: an unterminated quoted identifier raises');
|
|
180
|
+
|
|
181
|
+
-- ---------------------------------------------------------------------------
|
|
182
|
+
-- stripped_def: the header must survive, the body must NOT be deleted.
|
|
183
|
+
-- ---------------------------------------------------------------------------
|
|
184
|
+
-- pg_get_functiondef wraps the body in a dollar quote (`AS $function$ … $function$`).
|
|
185
|
+
-- Handing that whole string to a dollar-quote-aware strip deletes the ENTIRE body
|
|
186
|
+
-- and every negative assertion over the result passes. stripped_def() splices
|
|
187
|
+
-- instead, and these two assertions are what stop that regression.
|
|
188
|
+
select ok(
|
|
189
|
+
agent_board_test.stripped_def('agent_board.update_board_membership(uuid,uuid,text,jsonb)'::regprocedure)
|
|
190
|
+
~ 'SECURITY DEFINER',
|
|
191
|
+
'stripped_def keeps the generated HEADER -- SECURITY DEFINER is still matchable');
|
|
192
|
+
|
|
193
|
+
-- The token below is deliberately one that appears ONLY in the body. The first
|
|
194
|
+
-- version of this assertion used `board_memberships` against
|
|
195
|
+
-- _upsert_board_membership_state, whose header says `RETURNS
|
|
196
|
+
-- agent_board.board_memberships` -- so it passed even with the entire body
|
|
197
|
+
-- deleted, which is precisely the failure it was written to catch.
|
|
198
|
+
select ok(
|
|
199
|
+
agent_board_test.stripped_def('agent_board.update_board_membership(uuid,uuid,text,jsonb)'::regprocedure)
|
|
200
|
+
~ '_membership_consent_present',
|
|
201
|
+
'stripped_def does NOT delete the body -- a BODY-ONLY code token is still matchable');
|
|
202
|
+
|
|
203
|
+
select ok(
|
|
204
|
+
length(agent_board_test.stripped_def('agent_board.mark_retention_metadata(text,timestamp with time zone,uuid,text)'::regprocedure))
|
|
205
|
+
> length(pg_get_functiondef('agent_board.mark_retention_metadata(text,timestamp with time zone,uuid,text)'::regprocedure)) / 4,
|
|
206
|
+
'stripped_def on a body containing a dollar-quoted block keeps the surrounding code rather than collapsing the definition');
|
|
207
|
+
|
|
208
|
+
-- ---------------------------------------------------------------------------
|
|
209
|
+
-- CORPUS (catalog-derived). The vectors above are written by hand and can only
|
|
210
|
+
-- prove what their author thought of. These run the scanner over every live
|
|
211
|
+
-- agent_board function: a desync leaves a comment delimiter behind, and the
|
|
212
|
+
-- offender NAMES ITSELF.
|
|
213
|
+
-- ---------------------------------------------------------------------------
|
|
214
|
+
select is(
|
|
215
|
+
(select coalesce(string_agg(proname, ', ' order by proname), '')
|
|
216
|
+
from (
|
|
217
|
+
select p.proname, agent_board_test.stripped_body(p.oid) as b
|
|
218
|
+
from pg_proc p
|
|
219
|
+
join pg_namespace n on n.oid = p.pronamespace
|
|
220
|
+
where n.nspname = 'agent_board'
|
|
221
|
+
and p.prolang <> (select oid from pg_language where lanname = 'internal')
|
|
222
|
+
) s
|
|
223
|
+
where b ~ '--' or b ~ '/\*' or b ~ '\*/'),
|
|
224
|
+
'',
|
|
225
|
+
'CORPUS: no agent_board function body leaves a comment delimiter behind after the default strip');
|
|
226
|
+
|
|
227
|
+
select is(
|
|
228
|
+
(select coalesce(string_agg(proname, ', ' order by proname), '')
|
|
229
|
+
from (
|
|
230
|
+
select p.proname, agent_board_test.stripped_body(p.oid, true) as b
|
|
231
|
+
from pg_proc p
|
|
232
|
+
join pg_namespace n on n.oid = p.pronamespace
|
|
233
|
+
where n.nspname = 'agent_board'
|
|
234
|
+
and p.prolang <> (select oid from pg_language where lanname = 'internal')
|
|
235
|
+
) s
|
|
236
|
+
where b ~ '--' or b ~ '/\*' or b ~ '\*/'),
|
|
237
|
+
'',
|
|
238
|
+
'CORPUS: the keep-literals mode still removes every comment form -- removing comments is its only job there');
|
|
239
|
+
|
|
240
|
+
-- NON-VACUITY, both directions. The two corpus checks above would pass on a
|
|
241
|
+
-- corpus with no comments in it, and they would also pass if the scanner returned
|
|
242
|
+
-- the empty string for everything. Neither is true, and both are asserted rather
|
|
243
|
+
-- than assumed.
|
|
244
|
+
--
|
|
245
|
+
-- Stated plainly because it bounds what the corpus checks prove: the live
|
|
246
|
+
-- agent_board corpus contains 62 bodies with `--` comments and ZERO with a block
|
|
247
|
+
-- comment, so the block-comment half of those checks is a TRIPWIRE for the day
|
|
248
|
+
-- one appears, not evidence today. The block-comment and nested-block-comment
|
|
249
|
+
-- behaviour is pinned by the vectors above instead, where it can be mutated.
|
|
250
|
+
select cmp_ok(
|
|
251
|
+
(select count(*)::int
|
|
252
|
+
from pg_proc p
|
|
253
|
+
join pg_namespace n on n.oid = p.pronamespace
|
|
254
|
+
where n.nspname = 'agent_board'
|
|
255
|
+
and p.prolang <> (select oid from pg_language where lanname = 'internal')
|
|
256
|
+
and p.prosrc ~ '--'),
|
|
257
|
+
'>', 20,
|
|
258
|
+
'CORPUS NON-VACUITY: the corpus really does contain `--` comments for the strip to remove');
|
|
259
|
+
select ok(
|
|
260
|
+
(select min(length(agent_board_test.stripped_body(p.oid)))
|
|
261
|
+
from pg_proc p
|
|
262
|
+
join pg_namespace n on n.oid = p.pronamespace
|
|
263
|
+
where n.nspname = 'agent_board'
|
|
264
|
+
and p.prolang <> (select oid from pg_language where lanname = 'internal')
|
|
265
|
+
and length(p.prosrc) > 200) > 50,
|
|
266
|
+
'CORPUS NON-VACUITY: every non-trivial body still has substance after stripping -- the corpus checks are not passing on empty strings');
|
|
267
|
+
|
|
268
|
+
-- stripped_def must not be "simplified" into strip_sql(pg_get_functiondef(...)).
|
|
269
|
+
-- That form deletes the whole body (it is dollar-quoted) and every negative
|
|
270
|
+
-- assertion in the suite would pass on the remains. Asserted as a SIZE relation
|
|
271
|
+
-- against the raw definition so the collapse cannot hide.
|
|
272
|
+
select cmp_ok(
|
|
273
|
+
(select length(agent_board_test.stripped_def(p.oid))::int
|
|
274
|
+
from pg_proc p
|
|
275
|
+
join pg_namespace n on n.oid = p.pronamespace
|
|
276
|
+
where n.nspname = 'agent_board' and p.proname = 'update_board_membership'),
|
|
277
|
+
'>',
|
|
278
|
+
(select (length(pg_get_functiondef(p.oid)) / 2)::int
|
|
279
|
+
from pg_proc p
|
|
280
|
+
join pg_namespace n on n.oid = p.pronamespace
|
|
281
|
+
where n.nspname = 'agent_board' and p.proname = 'update_board_membership'),
|
|
282
|
+
'stripped_def keeps most of a real definition -- a dollar-quote-aware strip applied to the WHOLE functiondef would leave almost nothing');
|
|
283
|
+
|
|
284
|
+
select * from finish();
|
|
285
|
+
rollback;
|
|
@@ -94,14 +94,11 @@ select plan(35);
|
|
|
94
94
|
-- Shared helpers. Both are temp objects and vanish with the rollback.
|
|
95
95
|
-- ---------------------------------------------------------------------------
|
|
96
96
|
|
|
97
|
-
--
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
$re$'(?:[^']|'')*'|--[^\n]*|/\*(?:[^*]|\*+[^*/])*\*+/$re$,
|
|
103
|
-
' ', 'g')
|
|
104
|
-
$fn$;
|
|
97
|
+
-- The one-pass strip is agent_board_test.strip_sql(), shared by the whole suite
|
|
98
|
+
-- from tests/fixtures/test-prereqs.sql. The local copy this replaces was a regex,
|
|
99
|
+
-- and no regex can match a NESTED block comment (message-board#199); it also had
|
|
100
|
+
-- no dollar-quote alternative, so it desynced on any body whose apostrophes did
|
|
101
|
+
-- not happen to pair up. Both are handled by construction now.
|
|
105
102
|
|
|
106
103
|
-- A "cursor gate" is a range test against a PRE-COMMIT-ASSIGNED column.
|
|
107
104
|
--
|
|
@@ -166,13 +163,6 @@ $fn$;
|
|
|
166
163
|
-- exactly that boundary: it goes red the day a function moves to a SQL-standard
|
|
167
164
|
-- body, because at that point the parse tree this file could not use becomes
|
|
168
165
|
-- available and the function half can be made exhaustive too.
|
|
169
|
-
create or replace function pg_temp._wr_strip(p_text text) returns text
|
|
170
|
-
language sql immutable as $fn$
|
|
171
|
-
select regexp_replace(
|
|
172
|
-
coalesce($1, ''),
|
|
173
|
-
$re$'(?:[^']|'')*'|--[^\n]*|/\*(?:[^*]|\*+[^*/])*\*+/$re$,
|
|
174
|
-
' ', 'g')
|
|
175
|
-
$fn$;
|
|
176
166
|
|
|
177
167
|
-- The closure, and the two derived patterns, materialised once.
|
|
178
168
|
create temp table _wr_class(kind text, pattern text) on commit drop;
|
|
@@ -218,7 +208,9 @@ language sql stable as $fn$
|
|
|
218
208
|
(select string_agg(distinct regexp_replace(m[1], '[[:space:]]+', ' ', 'g'), ' | ')
|
|
219
209
|
from _wr_class c,
|
|
220
210
|
regexp_matches(
|
|
221
|
-
|
|
211
|
+
-- literals KEPT: this file's class members put real predicates in
|
|
212
|
+
-- dynamic SQL (see the _wr_members header). Comments are removed.
|
|
213
|
+
agent_board_test.strip_sql($1, true),
|
|
222
214
|
'(\m(' || c.pattern || ')\M[^<>=]{0,40}(?:<=|>=|<|>)'
|
|
223
215
|
|| '|(?:<=|>=|<|>)[^<>=]{0,40}\m(' || c.pattern || ')\M'
|
|
224
216
|
|| '|\m(' || c.pattern || ')\M[^<>=]{0,20}\mbetween\M'
|
|
@@ -228,7 +220,28 @@ language sql stable as $fn$
|
|
|
228
220
|
'')
|
|
229
221
|
$fn$;
|
|
230
222
|
|
|
231
|
-
|
|
223
|
+
-- `src` is the RAW definition and `body` is the STRIPPED one. Two columns rather
|
|
224
|
+
-- than one because both are legitimately needed: WR-8 reads a jsonb KEY, which is
|
|
225
|
+
-- a string literal and only exists in `src`.
|
|
226
|
+
--
|
|
227
|
+
-- `body` for a FUNCTION is agent_board_test.stripped_body(), never
|
|
228
|
+
-- strip_sql(pg_get_functiondef(...)). pg_get_functiondef wraps the body in a
|
|
229
|
+
-- dollar quote (`AS $function$ … $function$`), so a dollar-quote-aware strip
|
|
230
|
+
-- applied to the whole definition deletes THE ENTIRE BODY and every `!~` over the
|
|
231
|
+
-- result passes. stripped_def() splices the stripped body back into the generated
|
|
232
|
+
-- header instead.
|
|
233
|
+
--
|
|
234
|
+
-- LITERALS ARE KEPT (the `true` argument), and this file is the reason that mode
|
|
235
|
+
-- exists. `mark_retention_metadata` builds its entire retention sweep as DYNAMIC
|
|
236
|
+
-- SQL inside `format($retention$ … $retention$, …)`, so the `created_at <` and
|
|
237
|
+
-- `available_at <=` comparisons WR-7/WR-8 exist to find are CODE THAT LIVES
|
|
238
|
+
-- INSIDE A STRING LITERAL. Measured with literals stripped: WR-7 and WR-8 both
|
|
239
|
+
-- read the empty string -- vacuous, not passing. Comments (all forms, including
|
|
240
|
+
-- the nested one of message-board#199) are still removed in this mode, which is
|
|
241
|
+
-- what closes the message-board#196 masks. It is also the fail-CLOSED direction
|
|
242
|
+
-- for these particular assertions: an extra gate that only exists in a message
|
|
243
|
+
-- makes an exact-set claim RED, never green.
|
|
244
|
+
create temp table _wr_members(name text, kind text, src text, body text) on commit drop;
|
|
232
245
|
|
|
233
246
|
with recursive closure as (
|
|
234
247
|
select 'agent_board.inbox_items'::regclass as oid
|
|
@@ -243,16 +256,16 @@ with recursive closure as (
|
|
|
243
256
|
and d.refclassid = 'pg_class'::regclass
|
|
244
257
|
and r.ev_class <> d.refobjid
|
|
245
258
|
)
|
|
246
|
-
insert into _wr_members(name, kind, src)
|
|
247
|
-
select c.relname, 'view', pg_get_viewdef(c.oid)
|
|
259
|
+
insert into _wr_members(name, kind, src, body)
|
|
260
|
+
select c.relname, 'view', pg_get_viewdef(c.oid), agent_board_test.stripped_viewdef(c.oid, true)
|
|
248
261
|
from closure cl
|
|
249
262
|
join pg_class c on c.oid = cl.oid
|
|
250
263
|
join pg_namespace n on n.oid = c.relnamespace
|
|
251
264
|
where c.relkind in ('v', 'm')
|
|
252
265
|
and n.nspname = 'agent_board';
|
|
253
266
|
|
|
254
|
-
insert into _wr_members(name, kind, src)
|
|
255
|
-
select p.proname, 'function', pg_get_functiondef(p.oid)
|
|
267
|
+
insert into _wr_members(name, kind, src, body)
|
|
268
|
+
select p.proname, 'function', pg_get_functiondef(p.oid), agent_board_test.stripped_body(p.oid, true)
|
|
256
269
|
from pg_proc p
|
|
257
270
|
join pg_namespace n on n.oid = p.pronamespace
|
|
258
271
|
where n.nspname = 'agent_board'
|
|
@@ -339,7 +352,8 @@ select is(
|
|
|
339
352
|
'WR-4 the wake recovery view definition references no pre-commit ordering column in a comparison -- a cursor filter in view clothing is NAMED here');
|
|
340
353
|
|
|
341
354
|
select ok(
|
|
342
|
-
(select
|
|
355
|
+
(select agent_board_test.stripped_viewdef(to_regclass('agent_board.v_agent_wake_recovery'), true)
|
|
356
|
+
!~* '\morder[[:space:]]+by\M'),
|
|
343
357
|
'WR-4 the wake recovery view carries no ORDER BY -- the unhandled set is a SET, not a cursor stream');
|
|
344
358
|
|
|
345
359
|
-- ---------------------------------------------------------------------------
|
|
@@ -583,7 +597,7 @@ select is(
|
|
|
583
597
|
select is(
|
|
584
598
|
(select coalesce(string_agg(distinct name, ', ' order by name), '')
|
|
585
599
|
from _wr_members
|
|
586
|
-
where pg_temp._wr_cursor_gates(
|
|
600
|
+
where pg_temp._wr_cursor_gates(body) <> ''),
|
|
587
601
|
'claim_callback_outbox_events, mark_retention_metadata',
|
|
588
602
|
'WR-7 no member of the derived class gates on a derived pre-commit column, except the two asserted positively below -- an offender NAMES ITSELF here');
|
|
589
603
|
|
|
@@ -599,17 +613,20 @@ select is(
|
|
|
599
613
|
'WR-8 mark_retention_metadata returns a COUNT and is not set-returning -- it hands no batch to a consumer, so its comparison cannot be a recovery cursor');
|
|
600
614
|
|
|
601
615
|
select is(
|
|
602
|
-
(select pg_temp._wr_cursor_gates(
|
|
616
|
+
(select pg_temp._wr_cursor_gates(body) from _wr_members where name = 'mark_retention_metadata'),
|
|
603
617
|
'created_at <',
|
|
604
618
|
'WR-8 mark_retention_metadata''s ONLY pre-commit comparison is `created_at <` (an age cutoff) -- it never compares seq, and never gates on a lower bound');
|
|
605
619
|
|
|
606
|
-
--
|
|
607
|
-
--
|
|
608
|
-
--
|
|
609
|
-
--
|
|
620
|
+
-- `ops_retention_reason` is a jsonb KEY -- a string literal -- so it is read from
|
|
621
|
+
-- the RAW definition, which is true regardless of strip mode. The companion half
|
|
622
|
+
-- is read from `body`, i.e. through the shared strip: the UPDATE it looks for is
|
|
623
|
+
-- inside the `$retention$` dynamic-SQL block, which survives because this file
|
|
624
|
+
-- keeps literals (see the _wr_members header) but would NOT survive the default
|
|
625
|
+
-- literal-stripping mode. Restated so the next reader does not "simplify" the two
|
|
626
|
+
-- halves into one column.
|
|
610
627
|
select ok(
|
|
611
628
|
(select src ~ 'ops_retention_reason'
|
|
612
|
-
and
|
|
629
|
+
and body ~ 'update agent_board'
|
|
613
630
|
from _wr_members where name = 'mark_retention_metadata'),
|
|
614
631
|
'WR-8 mark_retention_metadata stamps retention metadata through an UPDATE sweep -- the age cutoff drives retention, not a fetch');
|
|
615
632
|
|
|
@@ -628,12 +645,12 @@ select ok(
|
|
|
628
645
|
-- SCHEDULING predicate against now(), not a caller-supplied cursor, and the batch
|
|
629
646
|
-- it hands back is bounded by STATUS (WR-9 below). Both halves are stated.
|
|
630
647
|
select is(
|
|
631
|
-
(select pg_temp._wr_cursor_gates(
|
|
648
|
+
(select pg_temp._wr_cursor_gates(body) from _wr_members where name = 'claim_callback_outbox_events'),
|
|
632
649
|
'available_at <=',
|
|
633
650
|
'WR-8 claim_callback_outbox_events'' ONLY pre-commit gate is `available_at <=` -- a scheduling predicate, never a lower bound against a caller cursor');
|
|
634
651
|
|
|
635
652
|
select ok(
|
|
636
|
-
(select
|
|
653
|
+
(select body !~* '\mavailable_at\M[^<>=]{0,40}(?:>=|>)'
|
|
637
654
|
from _wr_members where name = 'claim_callback_outbox_events'),
|
|
638
655
|
'WR-8 that gate is an UPPER bound (<=) and never a lower bound -- a `available_at >` would be a cursor, and is what this distinguishes');
|
|
639
656
|
|
|
@@ -661,7 +678,7 @@ select is(
|
|
|
661
678
|
-- WR-9 POSITIVE: the recovery-shaped members partition on STATUS.
|
|
662
679
|
-- ---------------------------------------------------------------------------
|
|
663
680
|
select ok(
|
|
664
|
-
(select
|
|
681
|
+
(select body ~ 'outbox_status[[:space:]]*(=|in|<>)'
|
|
665
682
|
from _wr_members where name = 'claim_callback_outbox_events'),
|
|
666
683
|
'WR-9 claim_callback_outbox_events partitions the queue on outbox_status -- the lossless property #187 relies on, restated positively here');
|
|
667
684
|
|
|
@@ -683,12 +700,12 @@ select is(
|
|
|
683
700
|
from pg_proc p
|
|
684
701
|
where p.pronamespace = 'agent_board'::regnamespace
|
|
685
702
|
and p.prolang <> (select oid from pg_language where lanname = 'internal')
|
|
686
|
-
and
|
|
703
|
+
and agent_board_test.stripped_body(p.oid, true) ~* 'action_state[[:space:]]*=[[:space:]]*[^=]'
|
|
687
704
|
-- The schema qualification is OPTIONAL on purpose (board review F3): a writer
|
|
688
705
|
-- using `set search_path` plus a bare `update inbox_items` was invisible to
|
|
689
706
|
-- the qualified form, and WR-10 stayed green naming only one writer. Same
|
|
690
707
|
-- class as the WR-7 name filter -- two name-based enumerators in one file.
|
|
691
|
-
and
|
|
708
|
+
and agent_board_test.stripped_body(p.oid, true) ~* 'update[[:space:]]+(agent_board\.)?inbox_items\M'),
|
|
692
709
|
'update_inbox_item_state',
|
|
693
710
|
'WR-10 exactly ONE function writes inbox_items.action_state -- the only way out of the unhandled set');
|
|
694
711
|
|
|
@@ -696,8 +713,8 @@ select is(
|
|
|
696
713
|
-- the intuition the comment encoded and it is false: mark_read writes read
|
|
697
714
|
-- receipts, so a READ item is still unhandled and still woken for.
|
|
698
715
|
select ok(
|
|
699
|
-
(select
|
|
700
|
-
and
|
|
716
|
+
(select agent_board_test.stripped_body(p.oid, true) !~* 'action_state'
|
|
717
|
+
and agent_board_test.stripped_body(p.oid, true) ~* 'read_receipts'
|
|
701
718
|
from pg_proc p
|
|
702
719
|
where p.pronamespace = 'agent_board'::regnamespace and p.proname = 'mark_read'),
|
|
703
720
|
'WR-10 mark_read writes read_receipts and NEVER action_state -- marking an item read does not remove it from the recovery set');
|
|
@@ -741,11 +758,12 @@ select is(
|
|
|
741
758
|
-- assert a falsehood. Pinning this properly needs named arguments at the call
|
|
742
759
|
-- sites; until then this is a known, unpinned second exit.
|
|
743
760
|
select ok(
|
|
744
|
-
|
|
745
|
-
|
|
761
|
+
-- CODE markers -> case-insensitive (`ON CONFLICT … DO UPDATE` is the same clause)
|
|
762
|
+
(select agent_board_test.stripped_body(p.oid, true)
|
|
763
|
+
~* 'on conflict[^;]*do update'
|
|
746
764
|
and (select m[1] !~ 'action_state'
|
|
747
|
-
from regexp_matches(
|
|
748
|
-
'on conflict[^;]*do update([^;]*)', '
|
|
765
|
+
from regexp_matches(agent_board_test.stripped_body(p.oid, true),
|
|
766
|
+
'on conflict[^;]*do update([^;]*)', 'gi') m
|
|
749
767
|
limit 1)
|
|
750
768
|
from pg_proc p
|
|
751
769
|
where p.pronamespace = 'agent_board'::regnamespace and p.proname = '_upsert_inbox_item'),
|