Skip to content

stack-encrypt refactor: migrate record derives and plans to owned declarations #1483

Closed

Description

@coderdan

Background

Stack Encrypt (packages/stack-encrypt) is the Rust engine that every CipherStash language SDK runs on. A Rust program encrypts a record by deriving traits on an encrypted struct. Each field's type says how that field is stored. A field's indexes come from its target type, such as SearchableEmail or IntegerOrd.

The scalar API already uses the owned traits EncryptTarget and DecryptSource (#1404), and collections do too (#1501). Records, derives, plans, and dynamic targets still use the older EncryptFrom and DecryptInto.

The Stack Encrypt API plan, merged in pull request #1365, describes the record derives.

Problem

Until records move to the owned traits, the old traits cannot be removed (#1488). Two record APIs also make the right one hard to find.

Proposal

  1. Derive EncryptTarget and DecryptSource on the encrypted struct. That struct is the declaration. The plaintext struct carries no attributes, so it can come from another crate.
  2. Support passthrough fields, nested records, and stored context. The existing from attribute renames a source field. Extend it to passthrough fields.
  3. Apply two safety rules. A plaintext field with no counterpart in the encrypted struct is a compile error, so no field is dropped silently. A field is stored in the clear only where passthrough is written on it.
  4. Enforce required, optional, and omitted caller context through types, with compile errors that name the field.
  5. Keep plaintext cleanup, passthrough ownership transfer, and collection batching.
  6. Update these against the same engine: plan lowering, the dynamic consumers, the guest, and the EQL adapters.

Pull request #1504 does this work and closes this issue.

Decision needed

Pull request #1504 uses #[stash(context = "..")] and adds ContextExtension. The naming review on 8 November 2026 replaced context = with scope = and removed ContextExtension. Choose one:

Acceptance

  • A mixed record, with passthrough and encrypted fields, round-trips as a test.
  • A searchable record round-trips as a test.
  • A tests/ui case shows that a plaintext field with no counterpart fails to compile.
  • Typed, dynamic, and generated code produce the same results for the record and batch examples.
  • Behaviour that already works is kept. Old APIs are removed only in stack-encrypt refactor: remove transitional traits and redundant execution APIs #1488, after every consumer has a replacement.

Relationship to other work

Plans: the Stack Encrypt API plan and the conformance roadmap.

Activity

  1. self-assigned this
    on Nov 1, 2026
  2. added a commit that references this issue on Nov 2, 2026
    55ff30f
  3. added 5 commits that reference this issue on Nov 3, 2026
    ff79e97
    bd64b2e
    0c0602d
    4450db4
    330d881
  4. coderdan commented on Nov 9, 2026

    @coderdan
    ContributorAuthor

    Follow-up work for the EQL types, which #1504 leaves out:

  5. coderdan commented on Nov 9, 2026

    @coderdan
    ContributorAuthor

    Done by #1504, which merged into next on 2026-11-09. GitHub closes an issue only from the default branch, so this one is closed by hand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions