You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 7741dde
Browse filesBrowse the repository at this point in the historyBrowse files
feat(eql-bindings, golang): produce the ordered date, timestamp and numeric types
With the engine ordering dates, timestamps and decimals, the nine EQL v4
types it refused become producible: DateOrd, DateOrdOpe, DateOrdOre and
their timestamp and numeric twins. eql-codegen lists them in
ENCRYPTION_DOMAINS and loses the pending-order reason; the generated
bindings, the target table and Go's encrypt/eql table follow.
eql-bindings' `v4::plaintext` now re-exports Stack Encrypt's `value`
types, and its chrono and rust_decimal features turn on Stack Encrypt's.
Its one remaining direct use of vitaminc-aead, the null tag in the by-name
dispatch, goes through `stack_encrypt::dynamic::frame`, so the dependency
is dropped.
Tests: the OPE types join v4_order's ordering checks, the block ORE types
join v4_ore_block with a PostgreSQL comparison over dates, timestamps
(ties within a microsecond, flooring before the epoch) and decimals
(1.5 ties 1.50), and the between smoke test now ranges over every ordered
family. Tests that used DateOrdOre as the unproducible example use Json.
Go: stashgen's static engine and notices admit order indexes on decimals,
dates and timestamps; the ValueKinds model takes the order indexes the
value-kinds fixture now declares, and its test checks Lt against the
stored terms, folded queries included.
Closes#1236
Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
Copy file name to clipboardExpand all lines: .changeset/eql-v4-date-timestamp-numeric.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,4 +2,4 @@
2
2
'@cipherstash/eql': minor
3
3
---
4
4
5
-
**Stack Encrypt produces the EQL v4 date, timestamp and numeric types `Date`, `DateEq`, `Timestamp`, `TimestampEq`, `Numeric` and `NumericEq`** (`eql-bindings`, `stack-encrypt` feature). Their Rust plaintexts are the crate's own `v4::plaintext::Date`, `Timestamp` and `Decimal`, which hold the integers the engine stores (days since 1970-01-01; Unix seconds and nanoseconds; a mantissa and a scale), are range checked when built and are wiped when dropped. The `chrono` and `rust_decimal` features convert to and from those crates' types. `=` on `NumericEq` normalises the scale (`1.5 = 1.50`) and on `TimestampEq` compares to the microsecond, truncating (never rounding) the nanoseconds below it; each value decrypts as it was stored. The ordered types of these families stay unproducible until the engine derives their order terms. The Go SDK's `encrypt/eql` table marks the six producible, from `encrypt.Date`, `time.Time` and `encrypt.Decimal`.
5
+
**Stack Encrypt produces the EQL v4 date, timestamp and numeric types `Date`, `DateEq`, `Timestamp`, `TimestampEq`, `Numeric` and `NumericEq`** (`eql-bindings`, `stack-encrypt` feature). Their Rust plaintexts are `v4::plaintext::Date`, `Timestamp` and `Decimal`, which hold the integers the engine stores (days since 1970-01-01; Unix seconds and nanoseconds; a mantissa and a scale), are range checked when built and are wiped when dropped. The `chrono` and `rust_decimal` features convert to and from those crates' types. `=` on `NumericEq` normalises the scale (`1.5 = 1.50`) and on `TimestampEq` compares to the microsecond, truncating (never rounding) the nanoseconds below it; each value decrypts as it was stored. The Go SDK's `encrypt/eql` table marks the six producible, from `encrypt.Date`, `time.Time` and `encrypt.Decimal`.
**Stack Encrypt produces the EQL v4 ordered date, timestamp and numeric types** (`eql-bindings`, `stack-encrypt` feature): `DateOrd`, `DateOrdOpe`, `DateOrdOre`, `TimestampOrd`, `TimestampOrdOpe`, `TimestampOrdOre`, `NumericOrd`, `NumericOrdOpe` and `NumericOrdOre`. A date orders by its day, a timestamp by the microsecond (truncated, as `TimestampEq`'s `=` is) and a decimal by value, so `1.5` and `1.50` order as equal. `v4::plaintext::Date`, `Timestamp`, `Decimal` and `RangeError` are now Stack Encrypt's own types, re-exported at the same path. The Go SDK's `encrypt/eql` table marks the nine producible.
Copy file name to clipboardExpand all lines: languages/golang/cmd/stashgen/README.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -148,7 +148,7 @@ For `-type User`, the file `user_stash.go` holds:
148
148
-`Fields`, with one entry for each sealed field.
149
149
An opaque struct, or a struct with no sealed field outside an opaque one, gets no `Fields`: nothing in it is sealed on its own, so nothing can be queried.
150
150
An entry encrypts one value, and has one query method for each operator the engine answers on the field: `Eq`, `Lt`, `Lte`, `Gt`, `Gte`, `Between` or `Matches`.
151
-
stashgen asks the embedded engine which operators each field answers, and which index answers each one, so it holds no copy of those rules: an equality index answers `Eq`, a match index on a string `Matches`, and an ORE or OPE index on an integer, a floator a string the four orderings and `Between`, through ORE when the field declares both. A float orders as PostgreSQL's `float8` does (`-0.0` ties `0.0`, NaN sorts last), and a string by its folded form: case and accents folded, under Unicode 16.
151
+
stashgen asks the embedded engine which operators each field answers, and which index answers each one, so it holds no copy of those rules: an equality index answers `Eq`, a match index on a string `Matches`, and an ORE or OPE index on an integer of 16 bits or more, a float, a string, an `encrypt.Decimal`, an `encrypt.Date`or a `time.Time` the four orderings and `Between`, through ORE when the field declares both. A float orders as PostgreSQL's `float8` does (`-0.0` ties `0.0`, NaN sorts last), and a string by its folded form: case and accents folded, under Unicode 16.
152
152
`encrypt_into=TextEq` answers `Eq`, which returns the type's query value, `eql.TextEqQuery`.
153
153
`encrypt_into=TextMatch` answers `Matches`, which returns an `encrypt.EQLMatchQuery`: the `eql.TextMatchQuery` operand, with `Verify` and `TargetLimit`.
154
154
The query of `Matches` carries `Verify` and `TargetLimit`, because its answer can hold rows that do not match; an exact operator's query carries neither.
@@ -276,7 +276,7 @@ An `opaque` struct crosses as one JSON document and is one column, decoded back
276
276
A float in an opaque struct must be finite: `encoding/json` refuses NaN and the infinities, so `Encrypt` fails for the batch with `encrypt.ErrEncoding`. A sealed float field outside an opaque struct carries them.
277
277
A sealed field outside an opaque struct is one scalar, a type defined over one, or a pointer to either (see "Optional fields"); a struct, slice or map field seals only inside an opaque struct.
278
278
The scalars are `string`, `[]byte`, `bool`, every integer type (each sealed at its own width, `int` and `uint` as 64-bit), `encrypt.Int128` and `encrypt.Uint128`, `float32`, `float64`, `encrypt.Decimal`, `encrypt.Date` and `time.Time` (a timestamp). The wire type `stashgen` writes for each is the field's own: `int8` is `gensupport.Int8`, `time.Time` is `gensupport.Timestamp`, and so on.
279
-
An order index (`ore`, `ope`) on a decimal, date or timestamp is refused: those order terms are not supported yet (#1236).
279
+
A decimal orders by value, so `1.5` ties `1.50`; a `time.Time` orders by the microsecond, so instants within one microsecond tie.
280
280
The zero `encrypt.Date` is not a date: a date field must be set, and `Encrypt` refuses a zero one with `encrypt.ErrEncoding`, naming the field. An optional date is a `*encrypt.Date` field (see "Optional fields").
281
281
A nil `[]byte` in a sealed field, or a nil slice of a type defined over `[]byte`, comes back from `Decrypt` as an empty, non-nil slice; inside an opaque struct, nil comes back as nil.
282
282
A protobuf message with a `oneof` cannot be generated from a policy: protoc-gen-go puts its members in wrapper types, not in the message struct, and `Generate` refuses it.
0 commit comments