Skip to content

Commit 36df60a

Browse files
committed
fix(stack-encrypt): address the review of the planned lowering
The review of #1597 found five in-diff mutants surviving. Three were equivalent: the "keys nothing" distinction in `compose` under a label context, where a passthrough ignores its context either way, and the context-field disjunct of the predicate, dead because a context field is always a passthrough. The distinction is removed rather than excluded. Two were checks nothing reached: `check_stored` and `check_names` are now reached by unit tests in `planned.rs`. `validate` is deleted. Its duplicate-field and label rules were refused by the parser first; the one live rule, shared identity between keyed fields, is in `Plan::build`'s loop beside the target rule. The builder's `join`, `field_label`, `FROM_PLAN` and `FROM_CALL` are shared with the lowering rather than copied. A target field is skipped by `operation_of` returning `None`, so no `unreachable!` sits in library code. Docs that still described lowering through the builder, or that said the checks run the lowering, are reworded: the checks share `check_names`, `check_stored` and `opening_base` with it. Tests added: a context field declared last, a batch with absent fields under a context field opened with an expected context, the stored and value checks refusing each kind of misfit, and the shared-identity table with exact reasons. Refs #1488.
1 parent cf748de commit 36df60a

8 files changed

Lines changed: 512 additions & 207 deletions

File tree

‎docs/plans/2026-10-24-stack-encrypt-api-plan.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,8 +1998,9 @@ table.
19981998
`dynamic::planned::compose` and `opening` build each field's combinator
19991999
from the parsed plan, and `encrypt_with`, `decrypt_with`, `contexts()`
20002000
and the checks read them. The dynamic path no longer uses the plan
2001-
builder. The builder, the chain, the old traits and `Label` are still
2002-
to be removed.
2001+
builder. Those functions do not yet build a `Planned`: they run the
2002+
lowering themselves. That inversion, the builder, the chain, the old
2003+
traits and `Label` are still to be removed.
20032004
- **Tracked in.** Issue #1488 is open. Its first pull request is the
20042005
lowering; the removals follow it.
20052006
- **Finished when** the old API is gone, and every consumer uses the new

‎packages/stack-encrypt/CHANGELOG.md‎

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5858
`K: 'static`, as `record::encrypt_with` does. The key source's bounds
5959
apply when the pending is awaited, not when the term is described.
6060

61-
### Changed
62-
63-
- **A data plan lowers to the combinators directly** (#1488, first part).
64-
`dynamic::planned::compose` and `opening` build each field's combinator
65-
from the parsed plan. The dynamic entry points run them: `encrypt_with`,
66-
`decrypt_with`, `check_source`, `check_record`, and `Plan::contexts`.
67-
The plan builder is no longer in the dynamic path. No stored byte
68-
changes: the record shape, the terms, and the contexts are the ones the
69-
builder's lowering produced, and the conformance vectors pin them.
70-
7161
### Breaking
7262

7363
- **Every operator is declared once, and `op::Supports` has one method**
@@ -507,6 +497,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
507497

508498
### Changed
509499

500+
- **A data plan lowers to the combinators directly** (#1488, first part).
501+
`dynamic::planned::compose` and `opening` build each field's combinator
502+
from the parsed plan, and the dynamic entry points run them:
503+
`encrypt_with`, `decrypt_with`, `check_source`, `check_record`, and
504+
`Plan::contexts`. The checks a binding asks without a cipher share
505+
`check_names`, `check_stored` and `opening_base` with the lowering. The
506+
plan builder is no longer in the dynamic path. No stored byte changes:
507+
the record shape, the terms, and the contexts are the ones the
508+
builder's lowering produced, and the conformance vectors pin them.
510509
- **The context parameter of the cipher-directed methods is named
511510
`context`, not `aad`** (#1568): `KeysetCipher::encrypt_tree`,
512511
`KeysetCipher::decrypt_tree`, `StackCipher::decrypt`,

‎packages/stack-encrypt/docs/adr/0007-bindings-enter-through-a-plan-never-a-second-executor.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,9 @@ The first pull request for #1488 did the lowering: `compose` and
382382
`opening` in `dynamic::planned` build the combinators from the parsed
383383
plan, and `encrypt_with`, `decrypt_with`, `check_source`, `check_record`
384384
and `contexts()` run them. The builder is no longer in the dynamic path.
385+
The inversion is still to come: those functions run `compose` and
386+
`opening` themselves rather than building a `Planned`, so `Planned` and
387+
the record functions are two callers of one lowering until then.
385388

386389
**The derive emits no plan.** `encryption_plan()` is not added. A typed
387390
query starts from a field marker. The marker has the field's context and

0 commit comments

Comments
 (0)