1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! Regression coverage for a confirmed SQL operator-precedence
//! authorization bypass in [`push_action_policy_query`], found while
//! diagnosing `crates/cratestack-pg/tests/policy_db_auth_engine.rs`
//! (2026-08 audit; see that test's `#[ignore]` reason for the live,
//! Postgres-backed reproduction). This file pins the defect at the
//! SQL-string level so it's caught by a plain `cargo test -p
//! cratestack-sqlx` run — no database required — rather than only by
//! the much slower/heavier PG-backed integration test.
//!
//! `push_action_policy_query` renders a model's allow policies as
//! `A OR B OR ...` (one [`ReadPolicy`] per separate `@@allow("<action>",
//! ...)` schema attribute). When the action has a matching `@@deny`
//! clause, the whole allow disjunction is correctly wrapped:
//! `NOT (deny...) AND (allow...)`. When it does NOT (the common case —
//! most actions have no `@@deny`), the function falls through to
//! emitting the *bare*, unparenthesized `A OR B OR ...` directly. Every
//! call site then does `<row filter> AND ` immediately before calling
//! this function (see `authorize_record_action` / `push_scoped_conditions`
//! in `query/support/conditions.rs`, and every `query/write/*_exec.rs`
//! / `query/batch/*.rs` mutation path). Because SQL's `AND` binds
//! tighter than `OR`, `id = $1 AND A OR B` parses as
//! `(id = $1 AND A) OR B` — the row filter only scopes the *first*
//! allow clause; every other clause becomes an unscoped, table-wide OR
//! that can make the whole predicate true for a row that has nothing
//! to do with `id = $1`.
//!
//! FIXED (2026-08 audit): `push_action_policy_query` now wraps its
//! entire emitted predicate in parentheses on both branches, so the
//! function's contract is "emits one self-contained boolean group" and
//! no call site has to know about the precedence hazard. This test
//! guards that contract and must stay green.
use ;
use cratepush_action_policy_query;
use crate::;
/// Two separate `@@allow` clauses (no `@@deny`) — the same shape as
/// `EnginePost` in `crates/cratestack-pg/tests/fixtures/auth_engine.cstack`,
/// which is what the live repro in `policy_db_auth_engine.rs` uses.