Background
vitaminc-aead-value is the value model behind vitaminc's encryption traits:
FfiValue is a value whose type is known only at runtime, as it arrives from
JavaScript, Go or Python. Each scalar seals as a one-byte type tag plus its
payload, inside the encrypted envelope. That tag table is frozen, because
stored ciphertexts depend on it. The transport module is a separate encoding
for handing a value tree across WebAssembly memory; it is never stored.
Problem
- The name misleads.
FfiValue reads as "a type for FFI", but it is the
value model for any vitaminc cipher. Reviewers have proposed moving the
crate into Stack Encrypt on that basis.
- It can't be cloned. Stack Encrypt's plan engine clones a field's
plaintext per operation, so it wraps FfiValue in its own dynamic::Value
only to add Clone (packages/stack-encrypt/src/dynamic/value.rs).
- Adding a kind is a breaking change.
FfiValue and ValueKind are
exhaustive enums.
- Transport's framing tags block the tag table.
ARRAY, OBJECT and
PASSTHROUGH are 0x10, 0x11 and 0x12 (transport.rs:27-35), and
transport reuses the scalar tag numbers for its leaves. So the next scalar
tags can't use 0x10 to 0x12 without colliding.
Proposal
- Rename
FfiValue to Value, keeping
#[deprecated] pub type FfiValue = Value; for one release.
- Implement
Clone as a deep copy that rebuilds every leaf into a fresh
Protected, as Stack Encrypt's duplicate() does today. Document that a
clone is under the same custody as its original.
- Mark
Value and ValueKind #[non_exhaustive].
- Move
ARRAY, OBJECT and PASSTHROUGH to 0xF0, 0xF1 and 0xF2, in
Rust and in Go's vcffi together. Transport carries no compatibility
commitment, and every user of it ships with its peer.
Breaking; part of 0.6.0. Decided in ADR-0002 (cipherstash/stack#1139).
Relationship to other work
Background
vitaminc-aead-valueis the value model behind vitaminc's encryption traits:FfiValueis a value whose type is known only at runtime, as it arrives fromJavaScript, Go or Python. Each scalar seals as a one-byte type tag plus its
payload, inside the encrypted envelope. That tag table is frozen, because
stored ciphertexts depend on it. The
transportmodule is a separate encodingfor handing a value tree across WebAssembly memory; it is never stored.
Problem
FfiValuereads as "a type for FFI", but it is thevalue model for any vitaminc cipher. Reviewers have proposed moving the
crate into Stack Encrypt on that basis.
plaintext per operation, so it wraps
FfiValuein its owndynamic::Valueonly to add
Clone(packages/stack-encrypt/src/dynamic/value.rs).FfiValueandValueKindareexhaustive enums.
ARRAY,OBJECTandPASSTHROUGHare0x10,0x11and0x12(transport.rs:27-35), andtransport reuses the scalar tag numbers for its leaves. So the next scalar
tags can't use
0x10to0x12without colliding.Proposal
FfiValuetoValue, keeping#[deprecated] pub type FfiValue = Value;for one release.Cloneas a deep copy that rebuilds every leaf into a freshProtected, as Stack Encrypt'sduplicate()does today. Document that aclone is under the same custody as its original.
ValueandValueKind#[non_exhaustive].ARRAY,OBJECTandPASSTHROUGHto0xF0,0xF1and0xF2, inRust and in Go's
vcffitogether. Transport carries no compatibilitycommitment, and every user of it ships with its peer.
Breaking; part of 0.6.0. Decided in ADR-0002 (cipherstash/stack#1139).
Relationship to other work
FfiValue) and aead / aead-value: after a decrypt, one unwiped copy of each decrypted string stays in freed heap memory #370 (plaintext left in the guest heap) touchthe same type; a new copy from step 2 must stay inside
Protected.