Updated 2026-10-05 (PDT). The Go SDK design is PR cipherstash/stack#1070: docs/plans/2026-10-04-plan-builder.md, "The Go SDK", and the principles in docs/sdk-design-principles.md (ADR-0008). Generated types give a typed Decrypt by construction: users.Decrypt returns []users.User. No Plan[T] is needed.
Background
The Go binding (languages/golang/stackencrypt/) runs stack-encrypt, our Rust field-level encryption library, inside a WebAssembly guest. #1046 reshapes it into one chained Encrypt that runs a plan (a saved declaration: per field, a context and search indexes). That chain is untyped: a plan is a plain value, encrypt returns an EncryptedRecord, and decrypt fills an out any.
Problem
Decrypt(..).Using(plan).Into(&user) checks the destination type only at run time. A plan built for User can be handed a *Order, and the mistake surfaces as a run-time error (or a partially filled struct) instead of a compile error.
Proposal
From the open questions in docs/plans/2026-10-04-plan-builder.md (PR cipherstash/stack#1052):
- A generic
Plan[T] that carries the Go type, for example from PlanOf[T]().
Encrypt(ctx, T) and Decrypt(..) (T, error) on it, so the plaintext type is checked by the compiler.
- Deferred until the untyped chain from #1046 lands. Go methods cannot take type parameters, so the exact shape (generic struct versus generic functions) is settled in the PR.
Relationship to other work
Background
The Go binding (
languages/golang/stackencrypt/) runs stack-encrypt, our Rust field-level encryption library, inside a WebAssembly guest. #1046 reshapes it into one chainedEncryptthat runs a plan (a saved declaration: per field, a context and search indexes). That chain is untyped: a plan is a plain value, encrypt returns anEncryptedRecord, and decrypt fills anout any.Problem
Decrypt(..).Using(plan).Into(&user)checks the destination type only at run time. A plan built forUsercan be handed a*Order, and the mistake surfaces as a run-time error (or a partially filled struct) instead of a compile error.Proposal
From the open questions in
docs/plans/2026-10-04-plan-builder.md(PR cipherstash/stack#1052):Plan[T]that carries the Go type, for example fromPlanOf[T]().Encrypt(ctx, T)andDecrypt(..) (T, error)on it, so the plaintext type is checked by the compiler.Relationship to other work
docs/plans/2026-10-04-plan-builder.mdon PR cipherstash/stack#1052.