Repository navigation
Description
Background
Stack Encrypt (packages/stack-encrypt) is the Rust engine that every CipherStash language SDK runs on. Milestone 4 is its first stable Rust release. The milestone tracks both API work and cross-language conformance work. Not every tracked item has to block the release.
The Stack Encrypt API plan, merged in pull request #1365, is the target design. Its stored-format rule applies to every change: the Go customer already stores data written by the Go SDK's rc.3 release. Code and APIs may change. Data rc.3 wrote must stay readable and searchable.
Problem
Without a written list of release gates, every open issue in the milestone looks like a blocker, and none of them is clearly one.
Proposal
- Record the stable Rust public API and its optional capabilities. Record the required profiles and backends. Record the supported versions of the engine, the SDKs, and the SQL.
- Classify Python (python: parity with Rust, fixtures, frozen rows, heap hygiene #1393), TypeScript (stack-encrypt conformance: add TypeScript runner and public SDK mapping tests #1479), and packaging (stack-encrypt refactor: finalize crate ownership, naming and coordinated migration #1489) as required or deferred, with a reason for each. Being in the milestone does not decide it.
- Use Docs: EQL v4 and Stack Encrypt compatibility policy #1314 for the compatibility policy for EQL and stored data. Publish the rules for profile changes, for refusing an unknown version or capability, and for changes to expected behaviour.
- Add reports and CI lanes for the claimed version matrix, using stack-encrypt conformance: expand fresh cross-language artifact exchange #1478. Label evidence as hermetic, database, live provider, or cross-version.
- Check that the API examples run, and check the ownership, context, and lifecycle guarantees (stack-encrypt conformance: define lifecycle, cleanup and key-I/O requirements #1480). List the limits that remain.
- Settle the release's dependency pins and publication checks. Choose the release version and date explicitly. Do not infer them from the milestone name.
- Freeze the rc.3 stored format in test vectors, so CI fails on any change to the stored bytes of rc.3 data. The plan item Freeze the rc.3 stored format in test vectors has no other issue.
- Decide which of these issues block the release. Each one is outside the milestone:
- stack-encrypt: a query's refusals are written separately for Rust callers and the Go binding, and have drifted once — give both one query preparation #1279, with its child issues stack-encrypt: replace
Supports::check,verifierandadmitwith oneprepare, called once per query #1318, stack-encrypt: one match query preparation for the typed chain and the binding, and no query flag in term derivation #1319, and stack-encrypt: a typed equality query on text that cannot be normalized is refused only after the keyset is resolved — refuse it first, as the Go binding does #1321: one query preparation; - A field can store both ORE and OPE order terms, but queries only ever use ORE: refuse a second order index #1233: refuse a second order index;
- Go SDK: methods on Cipher and Client take a *record.Plan and their docs and errors say "plan" — rename and hide them #1116 and Go: public plan-building API for types stashgen can't tag (reconcile with #1116) #1307: the Go plan names.
- stack-encrypt: a query's refusals are written separately for Rust callers and the Go binding, and have drifted once — give both one query preparation #1279, with its child issues stack-encrypt: replace
- Decide which of the issues added on 9 November 2026 block the stable release:
- stack-encrypt: every context part is packed into one 512-byte descriptor that ZeroKMS cannot parse — send scopes and bindings as key request items #1566: key request items;
- stack-encrypt: a stored value cannot be tied to its row without changing its key — add labels to EQL payloads #1567: labels;
- stack-encrypt: a developer cannot see the context a call will use — show it, name the parameter
context, and accept it by reference #1568: seeing the context; - stack-encrypt: a string literal, a
serde_json::Value, or a newtype needs a copy or hand-written traits — accept borrowed values, addJsonPlaintextand#[derive(Scalar)]#1569: borrowed values,JsonPlaintext, and#[derive(Scalar)]; - stack-encrypt: no opt-in type authenticates a collection's order and length — add
Positioned<Vec<T>>#1570:Positioned<Vec<T>>; - eql-bindings: every dynamic-interface consumer writes its own
TargetResolver— ship one #1571: a shared EQL resolver; - stack-encrypt: the caller must look up each record's keyset by hand — let a declaration choose the keyset from a field #1572: the keyset from the data.
Two fixtures are frozen already: stored_rows_v1.json (#1119, 18 October 2026) and the Go rows in eql_v4_test.go. Both predate the rc.3 tag of 2 November 2026, so neither is labelled rc.3.
Follows #1470 to #1474 and the rest of the milestone. Keep the shared corpus and the API migration in step. Then a Rust refactor cannot change released Go behaviour or stored data unless a test fails.
Plans: the Stack Encrypt API plan and the conformance roadmap.
Activity