Commit 0ebf57e
committed
fix(stack): close v3 drizzle fail-open paths, fix false-negative tests
An audit of the EQL v3 Drizzle adapter found the index/query-type wiring
correct, but several tests unable to detect the bug they guard. Three stayed
green under the exact regression they existed to catch, and two source paths
failed open.
Source:
- `contains` now rejects a needle shorter than the tokenizer's `token_length`.
A short needle builds an EMPTY bloom filter and `stored_bf @> '{}'` holds for
every row. Measured live: needles "ad", "a" and "x" each returned 3/3 seeded
rows -- "x" occurs in none of them. The floor lives in `schema/match-defaults`
so v2 and v3 share it; they build byte-identical blooms.
- `v3FromDriver` throws the new `EqlV3CodecError` rather than surfacing a raw
SyntaxError on malformed JSON or passing a wrong-shape payload through:
`v3FromDriver('5')` returned `5` typed as `Encrypted`. The shape guard accepts
SteVec documents, whose ciphertext is at `sv[0].c` with no top-level `c`.
- Removed the unreachable `sql`false`` fallback in `inArray`/`notInArray`; the
empty-list guard throws first.
Tests (each verified RED against the bug it guards, then reverted):
- `and` was indistinguishable from `or`: both predicates were true for ROW_B
alone, so swapping the operator still passed. Now paired over disjoint rows
and asserted from both directions.
- bigint filters ran against a one-row table, where `gt` returning every row
passed. Seeded a negative row they must exclude.
- `between` was only ever called with identical bounds against a constant
encrypt stub, so a min/max transposition in `range` was invisible. Added an
echoing stub that pins operand order.
- `contains` had no needle that must NOT match, and none longer than
`token_length`. The unit test searched `TEXT_S[0]` -- the empty string --
i.e. it asserted the fail-open. Now drives four needles through a substring
oracle, including a negative one.
- Seeded a third matrix row. With two, every predicate could only return [A],
[B], [A,B] or [] -- ordering ties were untestable and `eq` over-matching
undetectable. Row `i` takes `samples[min(i, len-1)]`, the scheme
`v3-matrix/matrix-live-pg` already uses.
Lock context:
The suite supplied the same context on seed and query in every test, so a
regression dropping it from the index term would drop it identically on both
sides and stay green. Added the negatives obtainable with one JWT: an
identity-bound row must not match an `eq` issued with no lock context, and must
not decrypt without it. A cross-identity proof needs a second JWT with a
different `sub` and remains a follow-up.
`lock-context.test.ts` wrapped `decryptModel` in try/catch, but it reports
denial as a `Result` and never throws -- the test ran zero assertions and would
also have passed had decryption wrongly succeeded.
Smaller pins: sql-dialect asserts operands BIND rather than interpolate;
schema-extraction uses toStrictEqual; the barrel is pinned exhaustively; codec
fixtures are realistic envelopes; the column's customType mappers are exercised.
Not included, per plan: the SQL `bloom_filter` empty-array change (contradicts
a documented semantic; needs sign-off) and the Supabase needle guard (lives on
another branch).1 parent 222be16 commit 0ebf57e
14 files changed
Lines changed: 704 additions & 113 deletions
File tree
- .changeset
- packages/stack
- __tests__
- drizzle-v3
- src
- eql/v3/drizzle
- schema
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
3 | 26 | | |
4 | 27 | | |
5 | | - | |
6 | | - | |
| 28 | + | |
| 29 | + | |
7 | 30 | | |
8 | 31 | | |
9 | 32 | | |
10 | 33 | | |
11 | 34 | | |
12 | 35 | | |
13 | 36 | | |
14 | | - | |
15 | | - | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
16 | 53 | | |
17 | 54 | | |
18 | | - | |
19 | | - | |
20 | | - | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
21 | 60 | | |
22 | 61 | | |
23 | 62 | | |
| |||
26 | 65 | | |
27 | 66 | | |
28 | 67 | | |
29 | | - | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
30 | 107 | | |
31 | 108 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
133 | 133 | | |
134 | 134 | | |
135 | 135 | | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
136 | 177 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
4 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
5 | 25 | | |
6 | 26 | | |
7 | 27 | | |
8 | 28 | | |
| 29 | + | |
9 | 30 | | |
10 | 31 | | |
11 | 32 | | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
12 | 41 | | |
0 commit comments