Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/bench-eql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ on:
- "packages/eql/docker/**"
- "packages/eql/README.md"
- "packages/eql/SUPABASE.md"
- "conformance/stack-encrypt/**"
- "packages/stack-encrypt/**"
- "packages/stack-encrypt-derive/**"
- "packages/stack-kms/**"
Expand Down
16 changes: 12 additions & 4 deletions .github/workflows/crap-crates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ env:
CARGO_NET_GIT_FETCH_WITH_CLI: true
NEXTEST_PROFILE: ci

# cargo-crap 0.6.1's prebuilt GNU/Linux binary needs GLIBC 2.39 (Ubuntu 24.04).
# Keep the runner and its mise cache on that image. The gate itself is unchanged.
jobs:
crap-stack-auth:
name: CRAP (stack-auth)
runs-on: blacksmith-16vcpu-ubuntu-2204
runs-on: blacksmith-16vcpu-ubuntu-2404
timeout-minutes: 45
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
Expand All @@ -74,16 +76,19 @@ jobs:
working_directory: .
cache: true
# Must name runs-on's image; see scripts/__tests__/workflow-mise-cache-image.test.mjs
cache_key_prefix: mise-v1-ubuntu-2204
cache_key_prefix: mise-v1-ubuntu-2404

- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2

- name: Check the CRAP executable before collecting coverage
run: cargo crap --version

- name: Run the CRAP gate
run: mise run crap:stack-auth -- --format github

crap-stack-encrypt:
name: CRAP (stack-encrypt)
runs-on: blacksmith-16vcpu-ubuntu-2204
runs-on: blacksmith-16vcpu-ubuntu-2404
timeout-minutes: 45
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
Expand All @@ -97,9 +102,12 @@ jobs:
working_directory: .
cache: true
# Must name runs-on's image; see scripts/__tests__/workflow-mise-cache-image.test.mjs
cache_key_prefix: mise-v1-ubuntu-2204
cache_key_prefix: mise-v1-ubuntu-2404

- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2

- name: Check the CRAP executable before collecting coverage
run: cargo crap --version

- name: Run the CRAP gate
run: mise run crap:stack-encrypt -- --format github
2 changes: 2 additions & 0 deletions .github/workflows/test-eql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ on:
# cannot see them (a task body names a cargo package, not a path); the
# manifest walk in eql-suite-ci.test.mjs does, and fails when one of them
# is missing from this list.
- "conformance/stack-encrypt/**"
- "packages/stack-encrypt/**"
- "packages/stack-encrypt-derive/**"
- "packages/stack-kms/**"
Expand Down Expand Up @@ -208,6 +209,7 @@ jobs:
- "packages/eql/docker/**"
- "packages/eql/README.md"
- "packages/eql/SUPABASE.md"
- "conformance/stack-encrypt/**"
- "packages/stack-encrypt/**"
- "packages/stack-encrypt-derive/**"
- "packages/stack-kms/**"
Expand Down
46 changes: 45 additions & 1 deletion .github/workflows/tests-golang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ on:
- scripts/go-binding-test.sh
- scripts/stack-conformance.sh
- scripts/stack-conformance-selection.mjs
- scripts/stack-eql-conformance.mjs
- Cargo.toml
- Cargo.lock
- .cargo/**
Expand Down Expand Up @@ -99,6 +100,7 @@ on:
- scripts/go-binding-test.sh
- scripts/stack-conformance.sh
- scripts/stack-conformance-selection.mjs
- scripts/stack-eql-conformance.mjs
- Cargo.toml
- Cargo.lock
- .cargo/**
Expand Down Expand Up @@ -144,6 +146,18 @@ jobs:
with:
persist-credentials: false

# Native EQL conformance uses the EQL workspace's toolchain. Install it
# before root setup, so ordinary guest commands retain the root pin.
# Its local DATABASE_URL must not enable database tests in this job.
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
with:
version: 2026.4.0
install: true
working_directory: packages/eql
env: false
cache: true
cache_key_prefix: mise-v1-ubuntu-2204

- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
with:
version: 2026.4.0
Expand Down Expand Up @@ -258,6 +272,17 @@ jobs:
echo "RLIMIT_MEMLOCK: $(ulimit -l) KiB"
mise run go:test

- name: Required EQL and JSON conformance
env:
STACK_CONFORMANCE_REPORT_DIR: ${{ runner.temp }}/eql-conformance-fast
run: mise run test:conformance:eql

- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: eql-conformance-fast
path: ${{ runner.temp }}/eql-conformance-fast/*.json
if-no-files-found: error

- name: Fresh Go scalar artifacts open in Rust
env:
STACK_CONFORMANCE_INPUT: ${{ runner.temp }}/stack-conformance-go.json
Expand Down Expand Up @@ -392,6 +417,8 @@ jobs:
# v4 bundle under packages/eql's mise config, which pins its own Rust; the
# guests are the ones wasi-check built and checked.
eql-postgres:
env:
MISE_ENV: test
name: Go rows and queries in PostgreSQL with EQL v4
needs: wasi-check
runs-on: blacksmith-16vcpu-ubuntu-2204
Expand Down Expand Up @@ -434,6 +461,16 @@ jobs:
# Must name runs-on's image; see scripts/__tests__/workflow-mise-cache-image.test.mjs
cache_key_prefix: mise-v1-ubuntu-2204

# mise caches Rust symlinks, not ~/.rustup. A cache hit can leave a
# toolchain directory without cargo and still report "all tools installed".
# Reconcile both workspaces' configured toolchains before cargo is used.
- name: Restore Rust toolchains behind the cached mise links
run: |
mise install --force rust
mise -C packages/eql install --force rust
mise x -- cargo --version
mise -C packages/eql x -- cargo --version

# `mise run build` compiles eql-codegen to write the bundle.
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
Expand All @@ -459,11 +496,18 @@ jobs:

# Builds the bundle from the tree, installs it, and runs the tests; a
# skip fails the task, so a missing guest or database cannot pass.
- name: Go rows and queries through EQL v4
- name: Go rows, queries and required JSON conformance through EQL v4
env:
EQL_TEST_DATABASE_URL: "host=localhost port=${{ job.services.postgres.ports['5432'] }} user=postgres password=postgres dbname=postgres sslmode=disable"
STACK_CONFORMANCE_REPORT_DIR: ${{ runner.temp }}/eql-conformance-postgres
run: mise run go:test:postgres

- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: eql-conformance-postgres
path: ${{ runner.temp }}/eql-conformance-postgres/*.json
if-no-files-found: error

# Round trips through real ZeroKMS. The Go live tests skip without their
# STACK_ENCRYPT_TEST_* variables, so the secrets pre-flight runs first and
# turns a missing credential into a failure rather than a silent skip. The
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -752,8 +752,9 @@ exact pin would stop the suite sharing one `cts-common` with it.
`tests/ui` binary, doctests, rustdoc, the node bindings and
`stack-auth-wasm`), `tests-golang.yml` (WASI checks, the guests, the Go
module on Linux, macOS and Windows, its PostgreSQL tests against the EQL v4
bundle built from the tree — `mise run go:test:postgres` locally — and the
live tests), `crap-crates.yml`,
bundle built from the tree — `mise run go:test:postgres` locally, which also
runs the Rust and Go EQL/JSON conformance lane and so needs `psql` and the
`MISE_ENV=test` cargo tools — and the live tests), `crap-crates.yml`,
`mutants.yml`, `fuzz.yml`, `miri.yml` and `udeps.yml`.
`scripts/__tests__/crates-ci.test.mjs` fails when a mise task in the root
`mise.toml` or the five crate `tasks.toml` files loses its last CI caller.
Expand Down
8 changes: 6 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,12 @@ mise run wasm:auth-guest:build
mise run go:test
```

For EQL v4 PostgreSQL coverage, set `EQL_TEST_DATABASE_URL` and run
`mise run go:test:postgres`. Go examples that connect to ZeroKMS need
For EQL v4 PostgreSQL coverage, set `EQL_TEST_DATABASE_URL` to a disposable
database and run `mise run go:test:postgres`. The task builds the EQL v4 bundle
from this tree and installs it into that database, so it replaces the EQL there.
It needs `psql`, the Rust test tools (`mise install --env test`) and both
deterministic guests. It refuses to run while a fixture-update variable, such as
`STACK_ENCRYPT_UPDATE_FIXTURES`, is set. Go examples that connect to ZeroKMS need
CipherStash credentials. The [Go module guide](languages/golang/README.md)
links to the SDK, generator, credentials, examples and release notes. Commit
generated `*_stash.go` files when changing Go model tags; CI checks for drift.
Expand Down
22 changes: 18 additions & 4 deletions conformance/stack-encrypt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ from each profile's own version. `<role>` is one of:
producer regenerates this file, deliberately; runners compare against it.
- `inputs.<runner>`: extra inputs keyed by case ID that only `<runner>` needs,
such as Go host values that have no language-neutral form.
- `enrollment`: the profile's requirement IDs mapped onto existing compiled
tests that are its evidence, rather than cases of its own.

Every file has a `version` and `profile` header. An `expected` file also names
its `producer`, and an `inputs` file names its `runner`.
Expand All @@ -37,11 +39,14 @@ these rules.
| `record-contexts-v1.cases.json` | cases | `tests/context_conformance.rs` | `context_conformance_test.go` |
| `record-contexts-v1.expected.rust-native.json` | expected | `tests/context_conformance.rs` (writes it) | `context_conformance_test.go` |
| `record-context-boundaries-v1.cases.json` | cases | `tests/context_conformance.rs` | `context_conformance_test.go` |
| `eql-json-v1.cases.json` | cases | `tests/json_operators.rs`; EQL's `tests/encryption/tests/json_tree_data_plan.rs` | `json_conformance_test.go` |
| `eql-json-v1.enrollment.json` | enrollment | `scripts/stack-eql-conformance.mjs` runs the tests it names | `scripts/stack-eql-conformance.mjs` runs the tests it names |
| `fixture-enrollment.json` | index | `tests/common/mod.rs` | `fixture_conformance_test.go` |

Rust readers are under `packages/stack-encrypt/`; Go readers are under
`languages/golang/encrypt/`. `fixture-enrollment.json` is not a profile: it maps
requirement IDs onto existing fixtures and tests (see
`languages/golang/encrypt/`; EQL's are under `packages/eql/`.
`fixture-enrollment.json` is the one file not named after a profile: it maps
requirement IDs of several profiles onto existing fixtures and tests (see
[the fixture contract](fixture-contract.md)), and
`scripts/stack-conformance-selection.mjs` reads it to choose the Go tests that
`mise run test:conformance` runs.
Expand Down Expand Up @@ -70,6 +75,15 @@ is `languages/golang/encrypt/conformance_test.go`. Go calls the record interface
used by generated code. Testing public SDK declarations is a separate layer.
Python and TypeScript runners are pending; their absence is not a passing result.

## EQL and JSON operations

The [EQL/JSON contract](eql-json-contract.md) enrolls resolver capabilities,
document writes, queries, extraction/subtree reads, element-match and predicate
matching. It reuses the native, Go and independent PostgreSQL suites and shares
write/predicate case data. Run `mise run test:conformance:eql` and the separate
required `test:conformance:eql:postgres` task; see the contract for guest builds,
disposable database setup, intentional SQL differences and version reports.

## Context composition and expectations

The [context contract](context-contract.md) covers ordered extensions, canonical
Expand All @@ -93,8 +107,8 @@ checks. The task runs the existing tests directly, and a missing guest fails
when conformance is required. The ordinary CI suites already execute them.

This is representative fixture coverage, not an exhaustive type/operator
matrix. Wider fresh artifact exchange, shared query refusals and EQL/JSON
operations remain separate work.
matrix. Wider fresh artifact exchange and shared scalar query refusals remain
separate work. The EQL/JSON profiles are described below.

## `record-reads-v1` contract

Expand Down
16 changes: 16 additions & 0 deletions conformance/stack-encrypt/coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,19 @@ Go proves canonical AAD indirectly through its actual guest plan frame and nativ
ciphertext opening; provider-call instrumentation remains a separate gap.
Nested composite extensions remain a native API capability rather than an
unsupported feature silently advertised by the Go/dynamic record profile.

## EQL/JSON checkpoint

The [EQL/JSON contract](eql-json-contract.md) and its enrollment index cover
resolver/catalog capabilities, JSON writes and queries, request-bound reads,
element-match and predicate-match. Existing Rust, Go and PostgreSQL suites stay
in place. The common document and predicate-refusal tables now live in
`v1/eql-json-v1.cases.json`: Rust and Go execute them, retaining native key-call checks,
Go diagnostic mapping and all extra cases from the original suites.

The database lane preserves independent plaintext oracles and generated
properties. Required test inventory/no-skip checks and engine/guest/SQL identity
reports make enrollment observable. This consolidates data and requirements;
it does not replace adapter tests or claim whole-database authentication.
Fresh JSON artifact exchange, released-version matrices and Python/TypeScript
runners remain open.
Loading
Loading