Skip to content

Commit f67d08d

Browse files
committed
Fix EQL v3 concrete domains
1 parent 1fdb1f5 commit f67d08d

15 files changed

Lines changed: 105 additions & 174 deletions

.changeset/eql-v3-ffi-0-27-concrete-types.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
'@cipherstash/stack': patch
33
---
44

5-
Upgrade `@cipherstash/protect-ffi` to 0.27.0 and update the EQL v3 concrete type factories/domains to the new names (`Integer`, `Smallint`, `Boolean`, `Real`, `Double`, and `Bigint`).
5+
Upgrade `@cipherstash/protect-ffi` to 0.27.0 and update EQL v3 concrete Postgres domain names to match the SQL fixture (`int4*`, `int2*`, `bool`, `float4*`, and `float8*`).

.changeset/eql-v3-typed-client.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@ Every method derives its types from the concrete `table` / `column` builder
1111
arguments:
1212

1313
- `encrypt` / `encryptQuery` pin the plaintext to the column's domain type
14-
(`text → string`, `int8 → bigint`, `timestamp → Date`, …).
14+
(`text → string`, `timestamp → Date`, …).
1515
- `encryptQuery` constrains `queryType` to the column's capabilities and rejects
1616
storage-only columns at compile time.
1717
- `encryptModel` / `bulkEncryptModels` validate schema-column fields against their
1818
inferred plaintext type (passthrough fields are untouched) and return a precise
1919
encrypted model.
2020
- `decryptModel` / `bulkDecryptModels` return the precise plaintext model,
21-
reconstructing `Date` / `bigint` values from the encrypt-config `cast_as`.
21+
reconstructing `Date` values from the encrypt-config `cast_as`.
2222

2323
Because the typed methods bind to the concrete branded v3 classes, a hand-rolled
2424
structural table/column is rejected — closing the soundness gap where a non-branded
2525
table could be encrypted at runtime while typed as plaintext.
2626

2727
Runtime behaviour is unchanged: the encrypt/query paths return the same operations
28-
as the base client; only the model-decrypt paths add a per-column `Date` / `bigint`
28+
as the base client; only the model-decrypt paths add a per-column `Date`
2929
reconstruction step. The v2 client surface (`Encryption`) is untouched.

.changeset/eql-v3-typed-schema.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
'@cipherstash/stack': minor
33
---
44

5-
Add EQL v3 schema builders for all generated SQL domains under `@cipherstash/stack/eql/v3`, exposed as the `types` namespace (one member per EQL v3 domain, e.g. `types.TextEq` / `types.IntegerOrd` / `types.Timestamp`), including explicit query capability metadata (`getQueryCapabilities()` / `isQueryable()`) and v3 table support in model encryption helpers (`encryptModel` / `bulkEncryptModels`).
5+
Add EQL v3 schema builders for supported generated SQL domains under `@cipherstash/stack/eql/v3`, exposed as the `types` namespace (one member per supported EQL v3 domain, e.g. `types.TextEq` / `types.IntegerOrd` / `types.Timestamp`), including explicit query capability metadata (`getQueryCapabilities()` / `isQueryable()`) and v3 table support in model encryption helpers (`encryptModel` / `bulkEncryptModels`).
66

7-
Also widen the accepted plaintext input type for `encrypt` / `encryptQuery` to include `Date` and `bigint` (via the new `Plaintext` type), so v3 `date` / `timestamp` / `int8` domains can be encrypted and queried with their natural JavaScript values.
7+
Also widen the accepted plaintext input type for `encrypt` / `encryptQuery` to include `Date` (via the new `Plaintext` type), so v3 `date` / `timestamp` domains can be encrypted and queried with their natural JavaScript values.

.changeset/skip-v3-bigint.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@cipherstash/stack': patch
3+
---
4+
5+
Omit EQL v3 bigint factories from the public DSL and test matrix until native bigint round-tripping is supported.

packages/stack/__tests__/cjs-require.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ describe('CJS consumers can require the built bundles', () => {
9393
`if (typeof v3.encryptedTable !== 'function') { throw new Error('missing v3 CJS export: encryptedTable') }`,
9494
`if (typeof v3.buildEncryptConfig !== 'function') { throw new Error('missing v3 CJS export: buildEncryptConfig') }`,
9595
`if (typeof v3.types !== 'object' || v3.types === null) { throw new Error('missing v3 CJS export: types namespace') }`,
96-
`const requiredTypes = ['TextSearch', 'TextEq', 'IntegerOrd', 'Boolean', 'Timestamp', 'Bigint']`,
96+
`const requiredTypes = ['TextSearch', 'TextEq', 'IntegerOrd', 'Boolean', 'Timestamp']`,
9797
`const missing = requiredTypes.filter((k) => typeof v3.types[k] !== 'function')`,
9898
`if (missing.length > 0) { throw new Error('missing v3 types.* CJS members: ' + missing.join(', ')) }`,
9999
].join('\n')

packages/stack/__tests__/schema-v3-pg.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'dotenv/config'
22
import postgres from 'postgres'
3-
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest'
3+
import { afterAll, beforeAll, beforeEach, expect, it } from 'vitest'
44
import type { EncryptionClient } from '@/encryption'
55
import { encryptedTable, types } from '@/eql/v3'
66
import { Encryption } from '@/index'
@@ -107,9 +107,9 @@ beforeAll(async () => {
107107
await sql`
108108
CREATE TABLE IF NOT EXISTS protect_ci_v3_typed_domains (
109109
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
110-
age eql_v3.integer_ord NOT NULL,
110+
age eql_v3.int4_ord NOT NULL,
111111
nickname eql_v3.text_eq NOT NULL,
112-
active eql_v3.boolean NOT NULL,
112+
active eql_v3.bool NOT NULL,
113113
test_run_id TEXT NOT NULL
114114
)
115115
`
@@ -280,9 +280,9 @@ describeLivePg('eql_v3 text_search postgres integration', () => {
280280
const [inserted] = await sql<{ id: number }[]>`
281281
INSERT INTO protect_ci_v3_typed_domains (age, nickname, active, test_run_id)
282282
VALUES (
283-
${sql.json(age as postgres.JSONValue)}::eql_v3.integer_ord,
283+
${sql.json(age as postgres.JSONValue)}::eql_v3.int4_ord,
284284
${sql.json(nickname as postgres.JSONValue)}::eql_v3.text_eq,
285-
${sql.json(active as postgres.JSONValue)}::eql_v3.boolean,
285+
${sql.json(active as postgres.JSONValue)}::eql_v3.bool,
286286
${TEST_RUN_ID}
287287
)
288288
RETURNING id
@@ -333,9 +333,9 @@ describeLivePg('eql_v3 text_search postgres integration', () => {
333333
const [row] = await sql<{ id: number }[]>`
334334
INSERT INTO protect_ci_v3_typed_domains (age, nickname, active, test_run_id)
335335
VALUES (
336-
${sql.json(ageCt)}::eql_v3.integer_ord,
336+
${sql.json(ageCt)}::eql_v3.int4_ord,
337337
${sql.json(nick)}::eql_v3.text_eq,
338-
${sql.json(act)}::eql_v3.boolean,
338+
${sql.json(act)}::eql_v3.bool,
339339
${TEST_RUN_ID}
340340
)
341341
RETURNING id

packages/stack/__tests__/schema-v3.test-d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ describe('eql_v3 schema type inference', () => {
2121
expectTypeOf(col).toEqualTypeOf<EncryptedTextSearchColumn>()
2222
})
2323

24+
it('does not expose bigint factories until native bigint round-tripping lands', () => {
25+
// @ts-expect-error - bigint v3 domains are intentionally not public yet
26+
types.Bigint('large')
27+
})
28+
2429
it('encryptedTable exposes column builders as typed properties', () => {
2530
const users = encryptedTable('users', {
2631
email: types.TextSearch('email'),

packages/stack/__tests__/schema-v3.test.ts

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -157,33 +157,26 @@ describe('eql_v3 text_match column', () => {
157157
})
158158

159159
describe('eql_v3 concrete type names', () => {
160-
it('exposes the renamed concrete type factories and emits the new EQL v3 domain names', () => {
161-
expect(types.Integer('n').getEqlType()).toBe('eql_v3.integer')
162-
expect(types.IntegerEq('n').getEqlType()).toBe('eql_v3.integer_eq')
163-
expect(types.IntegerOrdOre('n').getEqlType()).toBe('eql_v3.integer_ord_ore')
164-
expect(types.IntegerOrd('n').getEqlType()).toBe('eql_v3.integer_ord')
165-
166-
expect(types.Smallint('n').getEqlType()).toBe('eql_v3.smallint')
167-
expect(types.SmallintEq('n').getEqlType()).toBe('eql_v3.smallint_eq')
168-
expect(types.SmallintOrdOre('n').getEqlType()).toBe(
169-
'eql_v3.smallint_ord_ore',
170-
)
171-
expect(types.SmallintOrd('n').getEqlType()).toBe('eql_v3.smallint_ord')
172-
173-
expect(types.Bigint('n').getEqlType()).toBe('eql_v3.bigint')
174-
expect(types.BigintEq('n').getEqlType()).toBe('eql_v3.bigint_eq')
175-
expect(types.BigintOrdOre('n').getEqlType()).toBe('eql_v3.bigint_ord_ore')
176-
expect(types.BigintOrd('n').getEqlType()).toBe('eql_v3.bigint_ord')
177-
178-
expect(types.Boolean('b').getEqlType()).toBe('eql_v3.boolean')
179-
expect(types.Real('n').getEqlType()).toBe('eql_v3.real')
180-
expect(types.RealEq('n').getEqlType()).toBe('eql_v3.real_eq')
181-
expect(types.RealOrdOre('n').getEqlType()).toBe('eql_v3.real_ord_ore')
182-
expect(types.RealOrd('n').getEqlType()).toBe('eql_v3.real_ord')
183-
expect(types.Double('n').getEqlType()).toBe('eql_v3.double')
184-
expect(types.DoubleEq('n').getEqlType()).toBe('eql_v3.double_eq')
185-
expect(types.DoubleOrdOre('n').getEqlType()).toBe('eql_v3.double_ord_ore')
186-
expect(types.DoubleOrd('n').getEqlType()).toBe('eql_v3.double_ord')
160+
it('preserves public factory names while exposing concrete Postgres domain names', () => {
161+
expect(types.Integer('n').getEqlType()).toBe('eql_v3.int4')
162+
expect(types.IntegerEq('n').getEqlType()).toBe('eql_v3.int4_eq')
163+
expect(types.IntegerOrdOre('n').getEqlType()).toBe('eql_v3.int4_ord_ore')
164+
expect(types.IntegerOrd('n').getEqlType()).toBe('eql_v3.int4_ord')
165+
166+
expect(types.Smallint('n').getEqlType()).toBe('eql_v3.int2')
167+
expect(types.SmallintEq('n').getEqlType()).toBe('eql_v3.int2_eq')
168+
expect(types.SmallintOrdOre('n').getEqlType()).toBe('eql_v3.int2_ord_ore')
169+
expect(types.SmallintOrd('n').getEqlType()).toBe('eql_v3.int2_ord')
170+
171+
expect(types.Boolean('b').getEqlType()).toBe('eql_v3.bool')
172+
expect(types.Real('n').getEqlType()).toBe('eql_v3.float4')
173+
expect(types.RealEq('n').getEqlType()).toBe('eql_v3.float4_eq')
174+
expect(types.RealOrdOre('n').getEqlType()).toBe('eql_v3.float4_ord_ore')
175+
expect(types.RealOrd('n').getEqlType()).toBe('eql_v3.float4_ord')
176+
expect(types.Double('n').getEqlType()).toBe('eql_v3.float8')
177+
expect(types.DoubleEq('n').getEqlType()).toBe('eql_v3.float8_eq')
178+
expect(types.DoubleOrdOre('n').getEqlType()).toBe('eql_v3.float8_ord_ore')
179+
expect(types.DoubleOrd('n').getEqlType()).toBe('eql_v3.float8_ord')
187180
})
188181
})
189182

packages/stack/__tests__/v3-matrix/catalog.ts

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ import type {
2323
QueryCapabilities,
2424
} from '@/eql/v3'
2525
import {
26-
EncryptedBigintColumn,
27-
EncryptedBigintEqColumn,
28-
EncryptedBigintOrdColumn,
29-
EncryptedBigintOrdOreColumn,
3026
EncryptedBooleanColumn,
3127
EncryptedDateColumn,
3228
EncryptedDateEqColumn,
@@ -103,7 +99,7 @@ export type DomainSpec = Readonly<{
10399
* tell `integer` from `double`, and a fractional value on an int-named domain is
104100
* untested territory (it would truncate against a real narrow PG column).
105101
*/
106-
samples: ReadonlyArray<string | number | bigint | boolean | Date>
102+
samples: ReadonlyArray<string | number | boolean | Date>
107103
/**
108104
* Values that MUST fail encryption. Number domains reject `NaN`/`±Infinity`
109105
* via a global guard; other domains omit this.
@@ -179,7 +175,6 @@ const TEXT_SEARCH_IDX: Indexes = {
179175
// smallint/integer, fractionals for real/double/numeric. See `DomainSpec.samples`.
180176
const SMALLINT_S = [0, -1, 32767, -32768] as const
181177
const INTEGER_S = [0, -42, 2147483647, -2147483648] as const
182-
const BIGINT_S = [0n, -1n, 9223372036854775807n, -9223372036854775808n] as const
183178
const REAL_S = [0, 77.5, -117.25, 0.5] as const
184179
const DOUBLE_S = [0, -117.123456, 1e15, -1e15] as const
185180
const NUMERIC_S = [0, 12345.678, -42, -0.5] as const
@@ -216,20 +211,15 @@ const NUM_ERR = [
216211
// biome-ignore format: one row per domain reads as a table; keep it dense.
217212
export const V3_MATRIX = {
218213
// integer
219-
'eql_v3.integer': { builder: types.Integer, ColumnClass: EncryptedIntegerColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: INTEGER_S, errorSamples: NUM_ERR },
220-
'eql_v3.integer_eq': { builder: types.IntegerEq, ColumnClass: EncryptedIntegerEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: INTEGER_S, errorSamples: NUM_ERR },
221-
'eql_v3.integer_ord_ore': { builder: types.IntegerOrdOre, ColumnClass: EncryptedIntegerOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: INTEGER_S, errorSamples: NUM_ERR },
222-
'eql_v3.integer_ord': { builder: types.IntegerOrd, ColumnClass: EncryptedIntegerOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: INTEGER_S, errorSamples: NUM_ERR },
214+
'eql_v3.int4': { builder: types.Integer, ColumnClass: EncryptedIntegerColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: INTEGER_S, errorSamples: NUM_ERR },
215+
'eql_v3.int4_eq': { builder: types.IntegerEq, ColumnClass: EncryptedIntegerEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: INTEGER_S, errorSamples: NUM_ERR },
216+
'eql_v3.int4_ord_ore': { builder: types.IntegerOrdOre, ColumnClass: EncryptedIntegerOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: INTEGER_S, errorSamples: NUM_ERR },
217+
'eql_v3.int4_ord': { builder: types.IntegerOrd, ColumnClass: EncryptedIntegerOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: INTEGER_S, errorSamples: NUM_ERR },
223218
// smallint
224-
'eql_v3.smallint': { builder: types.Smallint, ColumnClass: EncryptedSmallintColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: SMALLINT_S, errorSamples: NUM_ERR },
225-
'eql_v3.smallint_eq': { builder: types.SmallintEq, ColumnClass: EncryptedSmallintEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: SMALLINT_S, errorSamples: NUM_ERR },
226-
'eql_v3.smallint_ord_ore': { builder: types.SmallintOrdOre, ColumnClass: EncryptedSmallintOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: SMALLINT_S, errorSamples: NUM_ERR },
227-
'eql_v3.smallint_ord': { builder: types.SmallintOrd, ColumnClass: EncryptedSmallintOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: SMALLINT_S, errorSamples: NUM_ERR },
228-
// bigint
229-
'eql_v3.bigint': { builder: types.Bigint, ColumnClass: EncryptedBigintColumn, castAs: 'bigint', capabilities: STORAGE, indexes: NONE, samples: BIGINT_S },
230-
'eql_v3.bigint_eq': { builder: types.BigintEq, ColumnClass: EncryptedBigintEqColumn, castAs: 'bigint', capabilities: EQ, indexes: UNIQUE_IDX, samples: BIGINT_S },
231-
'eql_v3.bigint_ord_ore': { builder: types.BigintOrdOre, ColumnClass: EncryptedBigintOrdOreColumn, castAs: 'bigint', capabilities: ORD, indexes: ORE_IDX, samples: BIGINT_S },
232-
'eql_v3.bigint_ord': { builder: types.BigintOrd, ColumnClass: EncryptedBigintOrdColumn, castAs: 'bigint', capabilities: ORD, indexes: ORE_IDX, samples: BIGINT_S },
219+
'eql_v3.int2': { builder: types.Smallint, ColumnClass: EncryptedSmallintColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: SMALLINT_S, errorSamples: NUM_ERR },
220+
'eql_v3.int2_eq': { builder: types.SmallintEq, ColumnClass: EncryptedSmallintEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: SMALLINT_S, errorSamples: NUM_ERR },
221+
'eql_v3.int2_ord_ore': { builder: types.SmallintOrdOre, ColumnClass: EncryptedSmallintOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: SMALLINT_S, errorSamples: NUM_ERR },
222+
'eql_v3.int2_ord': { builder: types.SmallintOrd, ColumnClass: EncryptedSmallintOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: SMALLINT_S, errorSamples: NUM_ERR },
233223
// date
234224
'eql_v3.date': { builder: types.Date, ColumnClass: EncryptedDateColumn, castAs: 'date', capabilities: STORAGE, indexes: NONE, samples: DATE_S },
235225
'eql_v3.date_eq': { builder: types.DateEq, ColumnClass: EncryptedDateEqColumn, castAs: 'date', capabilities: EQ, indexes: UNIQUE_IDX, samples: DATE_S },
@@ -253,15 +243,15 @@ export const V3_MATRIX = {
253243
'eql_v3.text_ord': { builder: types.TextOrd, ColumnClass: EncryptedTextOrdColumn, castAs: 'string', capabilities: ORD, indexes: TEXT_ORD_IDX, samples: TEXT_ORE_S },
254244
'eql_v3.text_search': { builder: types.TextSearch, ColumnClass: EncryptedTextSearchColumn, castAs: 'string', capabilities: FULL, indexes: TEXT_SEARCH_IDX, samples: TEXT_ORE_S },
255245
// boolean
256-
'eql_v3.boolean': { builder: types.Boolean, ColumnClass: EncryptedBooleanColumn, castAs: 'boolean', capabilities: STORAGE, indexes: NONE, samples: BOOLEAN_S },
246+
'eql_v3.bool': { builder: types.Boolean, ColumnClass: EncryptedBooleanColumn, castAs: 'boolean', capabilities: STORAGE, indexes: NONE, samples: BOOLEAN_S },
257247
// real
258-
'eql_v3.real': { builder: types.Real, ColumnClass: EncryptedRealColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: REAL_S, errorSamples: NUM_ERR },
259-
'eql_v3.real_eq': { builder: types.RealEq, ColumnClass: EncryptedRealEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: REAL_S, errorSamples: NUM_ERR },
260-
'eql_v3.real_ord_ore': { builder: types.RealOrdOre, ColumnClass: EncryptedRealOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: REAL_S, errorSamples: NUM_ERR },
261-
'eql_v3.real_ord': { builder: types.RealOrd, ColumnClass: EncryptedRealOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: REAL_S, errorSamples: NUM_ERR },
248+
'eql_v3.float4': { builder: types.Real, ColumnClass: EncryptedRealColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: REAL_S, errorSamples: NUM_ERR },
249+
'eql_v3.float4_eq': { builder: types.RealEq, ColumnClass: EncryptedRealEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: REAL_S, errorSamples: NUM_ERR },
250+
'eql_v3.float4_ord_ore': { builder: types.RealOrdOre, ColumnClass: EncryptedRealOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: REAL_S, errorSamples: NUM_ERR },
251+
'eql_v3.float4_ord': { builder: types.RealOrd, ColumnClass: EncryptedRealOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: REAL_S, errorSamples: NUM_ERR },
262252
// double
263-
'eql_v3.double': { builder: types.Double, ColumnClass: EncryptedDoubleColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: DOUBLE_S, errorSamples: NUM_ERR },
264-
'eql_v3.double_eq': { builder: types.DoubleEq, ColumnClass: EncryptedDoubleEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: DOUBLE_S, errorSamples: NUM_ERR },
265-
'eql_v3.double_ord_ore': { builder: types.DoubleOrdOre, ColumnClass: EncryptedDoubleOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: DOUBLE_S, errorSamples: NUM_ERR },
266-
'eql_v3.double_ord': { builder: types.DoubleOrd, ColumnClass: EncryptedDoubleOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: DOUBLE_S, errorSamples: NUM_ERR },
253+
'eql_v3.float8': { builder: types.Double, ColumnClass: EncryptedDoubleColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: DOUBLE_S, errorSamples: NUM_ERR },
254+
'eql_v3.float8_eq': { builder: types.DoubleEq, ColumnClass: EncryptedDoubleEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: DOUBLE_S, errorSamples: NUM_ERR },
255+
'eql_v3.float8_ord_ore': { builder: types.DoubleOrdOre, ColumnClass: EncryptedDoubleOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: DOUBLE_S, errorSamples: NUM_ERR },
256+
'eql_v3.float8_ord': { builder: types.DoubleOrd, ColumnClass: EncryptedDoubleOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: DOUBLE_S, errorSamples: NUM_ERR },
267257
} as const satisfies Record<EqlV3TypeName, DomainSpec>

packages/stack/__tests__/v3-matrix/matrix-live-pg.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
*/
3535
import 'dotenv/config'
3636
import postgres from 'postgres'
37-
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
37+
import { afterAll, beforeAll, expect, it } from 'vitest'
3838
import { EncryptionV3, encryptedTable } from '@/encryption/v3'
3939
import { unwrapResult } from '../fixtures'
4040
import { installEqlV3IfNeeded } from '../helpers/eql-v3'
@@ -63,7 +63,7 @@ const sql = LIVE_EQL_V3_PG_ENABLED
6363
const TABLE_NAME = 'v3_matrix_live_pg'
6464
const TEST_RUN_ID = `matrix-live-pg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
6565

66-
/** `eql_v3.integer_ord` -> `integer_ord`: a valid, unique Postgres column name. */
66+
/** `eql_v3.int4_ord` -> `int4_ord`: a valid, unique Postgres column name. */
6767
const slug = (t: EqlV3TypeName): string => t.replace('eql_v3.', '')
6868

6969
const expectDecryptedStorageValue = (
@@ -108,7 +108,7 @@ const table = encryptedTable(TABLE_NAME, columns as never)
108108
const hasIndex = (
109109
indexes: DomainSpec['indexes'],
110110
key: 'unique' | 'ore' | 'match',
111-
): boolean => Boolean((indexes ?? {})[key])
111+
): boolean => Boolean(indexes?.[key])
112112

113113
const matchDomains = domains.filter(([, spec]) =>
114114
hasIndex(spec.indexes, 'match'),

0 commit comments

Comments
 (0)