Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
640 commits
Select commit Hold shift + click to select a range
baa7458
Merge branch 'docs/json-index-stack-encrypt-spike' into feat/json-ind…
coderdan Oct 24, 2026
56264f2
Merge branch 'feat/json-index-stack-encrypt' into perf/json-tree-walk…
coderdan Oct 24, 2026
9cc4c8a
Merge branch 'perf/json-tree-walk-and-projection' into feat/json-tree…
coderdan Oct 24, 2026
4d672e1
Merge branch 'feat/json-tree-ordinal-chain' into feat/json-tree-gates
coderdan Oct 24, 2026
0f80f8c
Merge branch 'feat/json-tree-gates' into test/json-tree-containment-p…
coderdan Oct 24, 2026
7d63656
Merge pull request #1250 from cipherstash/docs/json-index-stack-encry…
coderdan Oct 24, 2026
1260823
Merge branch 'next' into feat/json-index-stack-encrypt
coderdan Oct 24, 2026
ba8a940
Merge branch 'feat/json-index-stack-encrypt' into perf/json-tree-walk…
coderdan Oct 24, 2026
fc462af
Merge branch 'perf/json-tree-walk-and-projection' into feat/json-tree…
coderdan Oct 24, 2026
6127434
Merge branch 'feat/json-tree-ordinal-chain' into feat/json-tree-gates
coderdan Oct 24, 2026
f2af67c
Merge branch 'feat/json-tree-gates' into test/json-tree-containment-p…
coderdan Oct 24, 2026
6a4f1c2
fix(eql-bindings): make Base64Text and Base85Text guarantee their enc…
coderdan Oct 24, 2026
666f407
Merge branch 'feat/json-tree-ordinal-chain' into feat/json-tree-gates
coderdan Oct 24, 2026
338e77b
Merge branch 'feat/json-tree-gates' into test/json-tree-containment-p…
coderdan Oct 24, 2026
8aa177a
test(scripts): count eql-bindings' encoding module among the stack-en…
coderdan Oct 24, 2026
fcf8f0c
Merge branch 'feat/json-tree-ordinal-chain' into feat/json-tree-gates
coderdan Oct 24, 2026
f35ee53
Merge branch 'feat/json-tree-gates' into test/json-tree-containment-p…
coderdan Oct 24, 2026
536d9e5
Merge pull request #1288 from cipherstash/feat/json-index-stack-encrypt
coderdan Oct 24, 2026
1c5e048
Merge pull request #1325 from cipherstash/perf/json-tree-walk-and-pro…
coderdan Oct 24, 2026
5652ec5
Merge pull request #1329 from cipherstash/feat/json-tree-ordinal-chain
coderdan Oct 24, 2026
b104982
Merge pull request #1336 from cipherstash/feat/json-tree-gates
coderdan Oct 24, 2026
9d05f8b
fix(stack-encrypt): check that a json_tree read returns the entry ask…
coderdan Oct 24, 2026
c3d7fee
docs(plans): name the pull request that took the extracted-entry check
coderdan Oct 24, 2026
1586b9a
docs(plans): design json_tree tokens derivable from the path alone
coderdan Oct 24, 2026
edabee6
docs(eql): state what json_tree reveals once tokens are derivable
coderdan Oct 24, 2026
15c952e
feat(stack-encrypt): derive json_tree tokens from the path alone
coderdan Oct 24, 2026
cf82a43
feat(eql): read json_tree subtrees by a list of tokens, without gates
coderdan Oct 24, 2026
6c8cd45
docs(plans): fold the owner's decisions into the derivable-token design
coderdan Oct 24, 2026
effe92b
test(stack-encrypt): check the json_tree leakage page against the scheme
coderdan Oct 24, 2026
683802b
test(stack-encrypt): refuse one json_tree token answered by two rows
coderdan Oct 24, 2026
f94a6eb
perf(eql): inline the json_tree chain primitives and build the read's…
coderdan Oct 25, 2026
f3400a2
fix(stack-encrypt): cap a json_tree read at 8,192 tokens, not 65,536
coderdan Oct 25, 2026
0ec0c73
ci: keep Biome off the json_tree vectors fixture
coderdan Oct 25, 2026
617a156
style(stack-encrypt): rustfmt the token-cap test
coderdan Oct 25, 2026
9ec5c59
fix(stack-encrypt): refuse a json_tree walk cut short as the wrong entry
coderdan Oct 25, 2026
aa591f2
fix(stack-encrypt): refuse a json_tree walk that leaves out an array'…
coderdan Oct 25, 2026
efc6bba
docs(eql): say what a json_tree walk with no gates still does not check
coderdan Oct 25, 2026
790d827
Merge branch 'fix/json-tree-extracted-entry-check' into docs/json-tre…
coderdan Oct 25, 2026
f42496c
Merge branch 'docs/json-tree-derivable-tokens' into feat/json-tree-de…
coderdan Oct 25, 2026
a0261c8
Merge branch 'fix/json-tree-extracted-entry-check' into test/json-tre…
coderdan Oct 25, 2026
241c776
docs(eql): state the ordering term's length, folding and cross-path e…
coderdan Oct 25, 2026
f2331ab
docs(plans): count a wildcard's tokens per array and keep the path ou…
coderdan Oct 25, 2026
febc4b2
fix(stack-encrypt): refuse a repeated or two-document read row as the…
coderdan Oct 25, 2026
516404a
fix(stack-encrypt): keep the last entry carrying a tag in the SQL rea…
coderdan Oct 25, 2026
a76c5fd
docs(stack-encrypt): count probes per expanded array, and drop the ga…
coderdan Oct 25, 2026
c06c5d3
docs(eql): say which json_tree read the entries-times-tokens LIMIT bo…
coderdan Oct 25, 2026
fbdaa23
docs(eql): say a withheld probe hides truncation, and that a read is …
coderdan Oct 25, 2026
d1025be
docs(plans): point section 3 of the derivable-token design at the dec…
coderdan Oct 25, 2026
e0191df
Merge branch 'docs/json-tree-derivable-tokens' into feat/json-tree-de…
coderdan Oct 25, 2026
e4dd59a
Merge pull request #1345 from cipherstash/test/json-tree-containment-…
coderdan Oct 25, 2026
4ce771c
style(stack-encrypt): rustfmt the read model lookup
coderdan Oct 25, 2026
ff287a3
fix(stack-encrypt): open JSON index floats to the exact value sealed
coderdan Oct 25, 2026
fe55bf1
Merge branch 'next' into fix/json-tree-extracted-entry-check
coderdan Oct 25, 2026
9a7ca37
Merge branch 'fix/json-tree-extracted-entry-check' into test/json-tre…
coderdan Oct 25, 2026
2f3a384
Merge branch 'fix/json-tree-extracted-entry-check' into docs/json-tre…
coderdan Oct 25, 2026
9c0ab3b
Merge branch 'docs/json-tree-derivable-tokens' into feat/json-tree-de…
coderdan Oct 25, 2026
997c64b
fix(stack-encrypt): take any wildcard bound on a path that uses none
coderdan Oct 25, 2026
8489400
Merge branch 'feat/json-tree-derivable-tokens' into test/json-tree-le…
coderdan Oct 25, 2026
b992e78
docs(eql): v3 also reveals which leaves share an array element
coderdan Oct 25, 2026
839c0f6
test(stack-encrypt): port the json_tree leakage profile to the #1363 …
coderdan Oct 25, 2026
fa26cb5
test(stack-encrypt): derive child tokens only from tokens that find a…
coderdan Oct 25, 2026
09a9dfc
docs(plans): compare the json_tree leakage profile before and after #…
coderdan Oct 25, 2026
561f273
Merge branch 'feat/json-tree-derivable-tokens' into test/json-tree-le…
coderdan Oct 25, 2026
ae27e40
Merge pull request #1358 from cipherstash/fix/json-tree-extracted-ent…
coderdan Oct 25, 2026
b2a20ab
docs(eql): a probe is distinguishable, and v3 also groups leaves by e…
coderdan Oct 25, 2026
64821b0
docs(plans): lead the leakage before-and-after note with the net
coderdan Oct 25, 2026
0edead7
docs(plans): keep the consecutive-position check, and put the probe e…
coderdan Oct 25, 2026
ba9a87f
Merge branch 'docs/json-tree-derivable-tokens' into feat/json-tree-de…
coderdan Oct 25, 2026
a386b9c
docs(plans): say which kind of absence each (none) in the clause tabl…
coderdan Oct 25, 2026
d6f02a4
docs(plans): an absent old-profile clause reads 'not measured', not '…
coderdan Oct 25, 2026
bdea70a
Merge branch 'feat/json-tree-derivable-tokens' into test/json-tree-le…
coderdan Oct 25, 2026
ee025bd
test(stack-encrypt): pin the one substitution only the position rule …
coderdan Oct 25, 2026
12207f6
Merge pull request #1361 from cipherstash/docs/json-tree-derivable-to…
coderdan Oct 25, 2026
7509600
test(stack-encrypt): hold the ordering terms' shared prefixes in the …
coderdan Oct 25, 2026
076a921
test(stack-encrypt): compare the leakage harness's values across kinds
coderdan Oct 25, 2026
e52fe64
test(stack-encrypt): check the wire field names of every query term a…
coderdan Oct 25, 2026
6b38463
test(stack-encrypt): let token_derivability try the element rule past…
coderdan Oct 25, 2026
7ca5b0d
test(stack-encrypt): give the leakage profile's four unchecked clause…
coderdan Oct 25, 2026
faff233
test(stack-encrypt): widen the leakage corpus to the clauses it never…
coderdan Oct 25, 2026
981360f
test(stack-encrypt): say #1363 corrected the probe comment, and give …
coderdan Oct 25, 2026
5455ae0
docs(plans): correct the leakage note's net, and record the review
coderdan Oct 25, 2026
294f03e
Merge branch 'feat/json-tree-derivable-tokens' into test/json-tree-le…
coderdan Oct 25, 2026
905791d
test(stack-encrypt): state what a path ordered over numbers and strin…
coderdan Oct 25, 2026
7c2f470
test(stack-encrypt): hold the page's "equality is as a 64-bit float" …
coderdan Oct 25, 2026
e50c18b
docs(eql): say the ordering terms' shared prefix is CLLW's known profile
coderdan Oct 25, 2026
fd22900
docs(plans): record the owner's decisions in the leakage note
coderdan Oct 25, 2026
8c843ee
fix(stack-encrypt): refuse a container at the deepest level the index…
coderdan Oct 25, 2026
7f7f5ce
Merge branch 'feat/json-tree-derivable-tokens' into test/json-tree-le…
coderdan Oct 25, 2026
25e9d69
Merge pull request #1363 from cipherstash/feat/json-tree-derivable-to…
coderdan Oct 25, 2026
bf42fc5
Merge pull request #1362 from cipherstash/test/json-tree-leakage-profile
coderdan Oct 25, 2026
ebdb5de
Merge pull request #1366 from cipherstash/fix/json-float-roundtrip
coderdan Oct 25, 2026
5ac7a5e
chore(deps): take vitaminc from cipherstash/vitaminc#526 by git refer…
coderdan Oct 25, 2026
207fa46
test(stack-encrypt): build the float round-trip test against the rena…
coderdan Oct 25, 2026
8d36a51
test(stack-encrypt): run the registry-path UI case only while vitamin…
coderdan Oct 25, 2026
4a35f6f
feat(go): seal an opaque struct as a vitaminc storage blob
coderdan Oct 25, 2026
657b98a
feat(stack-encrypt,eql): store a JSON document through a data plan as…
coderdan Oct 25, 2026
953bf0d
feat(go): name EncryptedJson in a plan and generate its EQL types
coderdan Oct 25, 2026
1f13b77
feat(stack-encrypt): answer a document field's JSON operators and ope…
coderdan Oct 25, 2026
eb47bad
feat(go): generate encrypted JSON document fields
coderdan Oct 25, 2026
e2077b5
fix(stack-encrypt,go): build the check_record fuzz harness and skip j…
coderdan Oct 25, 2026
deb4578
test(stack-encrypt): pin the JSON text scan, wipe_value and TargetOpt…
coderdan Oct 25, 2026
2bdc882
chore(deps): keep the Rust workspaces on vitaminc 0.8.0; only Go take…
coderdan Oct 25, 2026
256c56d
Merge branch 'chore/vitaminc-storage-profile-git' into feat/go-opaque…
coderdan Oct 25, 2026
2cd83ea
fix(go): close the opaque storage blob's review findings
coderdan Oct 25, 2026
8d608bd
Merge branch 'feat/go-opaque-storage-profile' into feat/json-tree-dat…
coderdan Oct 25, 2026
e1b21ce
test(stack-encrypt): cover the JSON operators and reads inside the crate
coderdan Oct 25, 2026
0f02825
Merge branch 'feat/json-tree-data-plan' into feat/json-tree-queries-r…
coderdan Oct 25, 2026
ffd4212
fix(stack-encrypt,eql,go): close the json-tree data-plan review findings
coderdan Oct 25, 2026
b2b5e1d
test(stack-encrypt): pin eq_at against the orderings and a token agai…
coderdan Oct 25, 2026
8485fe9
Merge branch 'feat/json-tree-data-plan' into feat/json-tree-queries-r…
coderdan Oct 25, 2026
e3c09ff
Merge branch 'feat/json-tree-queries-reads' into feat/go-json-tree-fi…
coderdan Oct 25, 2026
d36fb16
fix(stack-encrypt): move the JSON text parser by re-slicing, and pin …
coderdan Oct 25, 2026
abdc767
fix(stack-encrypt,go): close the JSON operators review findings
coderdan Oct 25, 2026
accb055
Merge branch 'feat/json-tree-data-plan' into feat/json-tree-queries-r…
coderdan Oct 25, 2026
ddf9ea1
fix(stack-encrypt): ask the buffer whether it is full in push_wiping
coderdan Oct 25, 2026
978f0cd
Merge branch 'feat/json-tree-data-plan' into feat/json-tree-queries-r…
coderdan Oct 25, 2026
b75b999
Merge branch 'feat/json-tree-queries-reads' into feat/go-json-tree-fi…
coderdan Oct 25, 2026
ba65680
test(stack-encrypt,eql): build heap-spy inputs that leave no marked g…
coderdan Oct 25, 2026
4f96d11
Merge branch 'feat/json-tree-data-plan' into feat/json-tree-queries-r…
coderdan Oct 25, 2026
8a2488e
test(stack-encrypt): frame the operator heap test's inputs with the t…
coderdan Oct 25, 2026
534d32f
Merge branch 'feat/json-tree-queries-reads' into feat/go-json-tree-fi…
coderdan Oct 25, 2026
3ae7166
fix(go): close the encrypted JSON fields review findings
coderdan Oct 25, 2026
acb9e13
feat(eql): name the v4 JSON tree domains as v3 names its JSON document
coderdan Oct 25, 2026
5306f14
feat(eql,stack-encrypt): name the v4 JSON document type JsonSearch, a…
coderdan Oct 25, 2026
2b78559
docs(eql,stack-encrypt): record the v3 names the v4 JSON document takes
coderdan Oct 25, 2026
102a07a
Merge feat/json-tree-data-plan into feat/json-tree-queries-reads
coderdan Oct 25, 2026
3ddb62a
feat(stack-encrypt,eql): answer JsonSearch's JSON operators under the…
coderdan Oct 25, 2026
42af346
Merge feat/json-tree-queries-reads into feat/go-json-tree-fields
coderdan Oct 25, 2026
d34aa24
docs(eql): realign the JSON tree domain list after the rename
coderdan Oct 25, 2026
43faafc
docs(stack-encrypt): say which target carries the json index
coderdan Oct 26, 2026
e91856e
Merge feat/json-tree-data-plan into feat/json-tree-queries-reads
coderdan Oct 26, 2026
c502848
test(go): sort rows by an ordered JSON path in PostgreSQL
coderdan Oct 26, 2026
e7310da
feat(go): tag a JSON document field encrypt_into=JsonSearch
coderdan Oct 26, 2026
0b001bf
test(stack-encrypt): compile the float round-trip test after the toke…
coderdan Oct 25, 2026
c2f29e4
Merge feat/json-tree-queries-reads into feat/go-json-tree-fields
coderdan Oct 26, 2026
8faa096
feat(stack-encrypt): cascade a JSON node's children's AEAD tags into …
coderdan Oct 26, 2026
b418feb
Merge origin/feat/go-json-tree-fields into feat/go-json-tree-fields
coderdan Oct 26, 2026
d257963
feat(stack-encrypt): store a JSON document's entries in a random order
coderdan Oct 26, 2026
aaf5da0
feat(stack-encrypt): load the keyset when opening a JSON document wit…
coderdan Oct 26, 2026
ca19d71
feat(go): store encrypted JSON documents of Go types
coderdan Oct 26, 2026
d2d236c
docs(go): document encrypted JSON documents of Go types
coderdan Oct 26, 2026
7bac217
Merge feat/go-json-tree-fields into feat/go-json-typed-documents
coderdan Oct 26, 2026
586e27c
fix(go): close the typed JSON document review findings
coderdan Oct 26, 2026
9cc5827
test(stack-encrypt): find JSON rows by path, and assert where each re…
coderdan Oct 26, 2026
4440890
docs(json-tree): record the cascade and the random stored order
coderdan Oct 26, 2026
7690219
fix(stack-encrypt): tighten the keyset load and compare projections a…
coderdan Oct 26, 2026
5bafdfc
docs(eql): stop promising document order from the json_tree walks
coderdan Oct 26, 2026
65cc466
test(go): pin what a typed nil pointer encodes to on the two raw paths
coderdan Oct 26, 2026
810852c
feat(stack-encrypt): send every JSON needle in a random order of its own
coderdan Oct 26, 2026
541be40
fix(go): accept a pointer to a text type in an opaque struct
coderdan Oct 26, 2026
21261e4
chore(deps): pin vitaminc's Go bindings to d7de535c4, the final #526 …
coderdan Oct 26, 2026
4c5ab21
ci(go-release): refuse a final version while go.mod pins vitaminc at …
coderdan Oct 26, 2026
3ed9d3b
fix(stack-encrypt): wipe the JSON index's key names, values and data …
coderdan Oct 26, 2026
540748c
fix(go): refuse an opaque value neither reader takes, and say how to …
coderdan Oct 26, 2026
0b77928
Merge chore/vitaminc-storage-profile-git into feat/go-opaque-storage-…
coderdan Oct 26, 2026
15f5aea
Merge feat/go-opaque-storage-profile into feat/json-tree-data-plan
coderdan Oct 26, 2026
7246df1
Merge feat/json-tree-data-plan into feat/json-tree-queries-reads
coderdan Oct 26, 2026
9abbe97
Merge feat/json-tree-queries-reads into feat/go-json-tree-fields
coderdan Oct 26, 2026
ee67f7f
Merge feat/go-json-tree-fields into feat/go-json-typed-documents
coderdan Oct 26, 2026
c18f294
refactor(stack-encrypt): draw the JSON index's permutations with rand…
coderdan Oct 26, 2026
b1e3db7
refactor(stack-encrypt): hold the JSON index's owned documents in Pro…
coderdan Oct 26, 2026
93ccdb9
refactor(stack-encrypt): name the JSON index's selector set and compa…
coderdan Oct 26, 2026
731c4ef
chore: record stack-encrypt's rand dependency in the detached lockfiles
coderdan Oct 26, 2026
2f0aa29
refactor(stack-encrypt): name what the JSON index's AAD, rows and wal…
coderdan Oct 26, 2026
d959826
refactor(stack-encrypt): load a root-open document's keyset through t…
coderdan Oct 26, 2026
f6ffc38
feat(stack-encrypt): load keysets beside the key retrieval, failing o…
coderdan Oct 26, 2026
98edbe7
ci(mutants): diff against the pull request's real base, read from the…
coderdan Oct 26, 2026
f2b6730
feat(stack-encrypt): report an extracted JSON entry that does not ope…
coderdan Oct 26, 2026
c7b35aa
feat(stack-encrypt): give an object's members random ordinals
coderdan Oct 26, 2026
b5a63af
fix(eql): return a node's children in ordinal order
coderdan Oct 26, 2026
a849cac
ci(mutants): check out the pull request's head so the diff matches th…
coderdan Oct 26, 2026
b540fa0
docs(stack-encrypt): draw the cascade and say what the JSON index cod…
coderdan Oct 26, 2026
7a6d070
Merge pull request #1381 from cipherstash/ci/mutants-diff-against-pr-…
coderdan Oct 26, 2026
0437e6b
Merge next into chore/vitaminc-storage-profile-git
coderdan Oct 26, 2026
e2e85c9
Merge chore/vitaminc-storage-profile-git into feat/go-opaque-storage-…
coderdan Oct 26, 2026
3513753
Merge feat/go-opaque-storage-profile into feat/json-tree-data-plan
coderdan Oct 26, 2026
ac4a934
Merge feat/json-tree-data-plan into feat/json-tree-queries-reads
coderdan Oct 26, 2026
22882f7
Merge feat/json-tree-queries-reads into feat/go-json-tree-fields
coderdan Oct 26, 2026
9021a89
Merge feat/go-json-tree-fields into feat/go-json-typed-documents
coderdan Oct 26, 2026
b79fec3
style(golang): format the encrypt guest's status test
coderdan Oct 26, 2026
f783f8e
Merge next into feat/json-tree-cascade-and-random-order
coderdan Oct 26, 2026
02ae76b
Merge pull request #1379 from cipherstash/feat/json-tree-cascade-and-…
coderdan Oct 26, 2026
b8a7be6
Merge next into chore/vitaminc-storage-profile-git
coderdan Oct 26, 2026
0bccc05
Merge chore/vitaminc-storage-profile-git into feat/go-opaque-storage-…
coderdan Oct 26, 2026
67bbb82
Merge feat/go-opaque-storage-profile into feat/json-tree-data-plan
coderdan Oct 26, 2026
b944419
test(eql): compare the data plan's stored document with the typed one…
coderdan Oct 26, 2026
c0cedd5
docs(stack-encrypt): name JsonSelectorSet in the fuzz:json-wire task
coderdan Oct 26, 2026
ed858fb
fix(go): decide OpenOne's wildcard from the engine's token count
coderdan Oct 26, 2026
247bd32
fix(go): refuse empty JSONTokens rather than bind them as {}
coderdan Oct 26, 2026
2424891
fix(go): print and log the JSON read types redacted
coderdan Oct 26, 2026
9d1df34
fix(go): refuse a document that embeds a pointer to an unexported struct
coderdan Oct 26, 2026
e33cf3e
docs(go): name the JSON read constructors' declaration parameter
coderdan Oct 26, 2026
3ad7e5e
fix(go): check a struct embedded through two branches each time
coderdan Oct 26, 2026
8736697
fix(go): refuse ordered paths the engine answers no ordering on
coderdan Oct 26, 2026
2a81108
fix(go): look up a pointer field's codec on the pointer
coderdan Oct 26, 2026
ef1bbd4
test(go): assert the reason stashgen gives for a sealed null document
coderdan Oct 26, 2026
288b3ca
fix(go): refuse a json:",string" field in a document
coderdan Oct 26, 2026
66a81a1
docs(go): say JsonSearch refuses a type defined over json.RawMessage
coderdan Oct 26, 2026
726e3a3
docs(go): say what the JSON read types print and refuse to bind
coderdan Oct 26, 2026
a32b09c
docs(go): say what a document of a Go type does not keep
coderdan Oct 26, 2026
9330134
fix(go): refuse a pointer-to-string or null containment needle
coderdan Oct 26, 2026
ed851e2
test(go): give TestRunGeneratesTypedJSONDocuments its own doc comment
coderdan Oct 26, 2026
c031644
docs(stack-encrypt): say which heap blocks parse_text leaves clean
coderdan Oct 26, 2026
f2573fe
perf(stack-encrypt): move a document's text into its frame
coderdan Oct 26, 2026
05d19b3
docs(stack-encrypt): say why a document is parsed twice and how targe…
coderdan Oct 26, 2026
20f099e
test(eql,go): pin a document's column and its SQL null through the da…
coderdan Oct 26, 2026
02acc73
fix(go): refuse a JSON field with no target in Plan.Validate
coderdan Oct 26, 2026
c22b688
docs(eql,go): name the version-confined surfaces and the test that st…
coderdan Oct 26, 2026
53d7a31
Merge feat/json-tree-data-plan into feat/json-tree-queries-reads
coderdan Oct 26, 2026
5062990
feat(stack-encrypt): index short words whole in a match index
coderdan Oct 26, 2026
0d38691
fix(stack-encrypt,go): follow the random entry order and the cascade …
coderdan Oct 26, 2026
36898b2
fix(stack-encrypt): refuse a JSON operator path deeper than a document
coderdan Oct 26, 2026
8afa98f
test(stack-encrypt): pin the operators' refusals, rows that are not a…
coderdan Oct 26, 2026
a9a4da7
test(go): read a bounded subtree request through Cipher.JSONOpen
coderdan Oct 26, 2026
9b01531
docs(eql-bindings): drop a duplicated changelog line
coderdan Oct 26, 2026
d1e9eeb
feat(eql-bindings): index two-letter words in the v4 match types
coderdan Oct 26, 2026
83bee57
fix(stack-encrypt): export MAX_DEPTH to the data plan alone
coderdan Oct 26, 2026
c9bb7ad
test(golang): a two-letter name is a TextMatch value and query
coderdan Oct 26, 2026
acb728e
Merge feat/json-tree-queries-reads into feat/go-json-tree-fields
coderdan Oct 26, 2026
166d3f1
docs(stack-encrypt): drop a public link to the private Tokens type
coderdan Oct 26, 2026
955b9a1
fix(go): write orderings at a wildcard path over every match
coderdan Oct 26, 2026
bf769f8
Merge feat/go-json-tree-fields into feat/go-json-typed-documents
coderdan Oct 26, 2026
8591f27
test(go): expect the typed documents' refusal of a type defined over …
coderdan Oct 26, 2026
5227d0f
test(go): compare a typed needle's query with its JSON text's as sets
coderdan Oct 26, 2026
e304684
test(stack-encrypt): pin that zeroizing match tokens clears both kinds
coderdan Oct 26, 2026
5eaabb5
fix(stack-encrypt): wipe short words on the error path, one word split
coderdan Oct 26, 2026
be25106
test(stack-encrypt): accept a JSON path exactly as deep as a document
coderdan Oct 26, 2026
e6ae4a8
Merge feat/json-tree-queries-reads into feat/go-json-tree-fields
coderdan Oct 26, 2026
fb87c42
Merge feat/go-json-tree-fields into feat/go-json-typed-documents
coderdan Oct 26, 2026
02241da
chore(golang): pin vitaminc's Go bindings to the storage profile on main
coderdan Oct 26, 2026
480dc76
Merge chore/vitaminc-storage-profile-git into feat/go-opaque-storage-…
coderdan Oct 26, 2026
db6dca0
Merge feat/go-opaque-storage-profile into feat/json-tree-data-plan
coderdan Oct 26, 2026
32dc305
Merge feat/json-tree-data-plan into feat/json-tree-queries-reads
coderdan Oct 26, 2026
01a2fc6
Merge feat/json-tree-queries-reads into feat/go-json-tree-fields
coderdan Oct 26, 2026
c8c6a39
Merge feat/go-json-tree-fields into feat/go-json-typed-documents
coderdan Oct 26, 2026
8d01178
Merge pull request #1369 from cipherstash/chore/vitaminc-storage-prof…
coderdan Oct 26, 2026
bdbe456
Merge pull request #1370 from cipherstash/feat/go-opaque-storage-profile
coderdan Oct 26, 2026
067ac28
Merge pull request #1372 from cipherstash/feat/json-tree-data-plan
coderdan Oct 26, 2026
2851026
Merge pull request #1374 from cipherstash/feat/go-json-tree-fields
coderdan Oct 26, 2026
2e95042
docs(go): add typed JSON walkthrough and correct EQL reference
coderdan Oct 26, 2026
a5e2f79
Merge next into feat/match-short-words
coderdan Oct 26, 2026
f9b93ac
Merge pull request #1373 from cipherstash/feat/json-tree-queries-reads
coderdan Oct 26, 2026
06ba56e
Merge pull request #1378 from cipherstash/feat/go-json-typed-documents
coderdan Oct 26, 2026
be96a9e
fix(go): close example query rows on error
coderdan Oct 26, 2026
93fd33e
Merge next into feat/match-short-words
coderdan Oct 26, 2026
657d7d8
docs(go): build embedded guests before source tests
coderdan Oct 26, 2026
b0c1513
Merge pull request #1397 from cipherstash/feat/match-short-words
coderdan Oct 26, 2026
311df36
Merge remote-tracking branch 'origin/next' into docs/go-typed-json-do…
coderdan Oct 26, 2026
238ac9a
docs(go): align match release notes with two-letter queries
coderdan Oct 26, 2026
ffeed7a
Merge pull request #1402 from cipherstash/docs/go-typed-json-document…
coderdan Oct 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
39 changes: 39 additions & 0 deletions .cargo/mutants.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ exclude_re = [
'stack-encrypt/src/cipher\.rs:\d+:\d+: replace client_key_provider -> EnvKeyProvider with Default::default\(\)$',
'stack-encrypt/src/target/pending\.rs:443:9: replace <impl IntoFuture for Pending<.*>>::into_future -> Self::IntoFuture with Default::default\(\)$',
# stack-encrypt — equivalent.
# An operator and an index are unit structs, whose `Default` is the value
# `clone` and `case_sensitive` already return.
'stack-encrypt/src/op(/mod)?\.rs:\d+:\d+: replace <impl Clone for Matches<C>>::clone -> Self with Default::default\(\)$',
'stack-encrypt/src/op(/mod)?\.rs:\d+:\d+: replace Matches::case_sensitive -> Matches<CaseSensitive> with Default::default\(\)$',
'stack-encrypt/src/target/index\.rs:\d+:\d+: replace <impl Clone for Match<O>>::clone -> Self with Default::default\(\)$',
'stack-encrypt/src/cipher\.rs:\d+:\d+: replace StackCipher<FromEnv>::builder -> StackCipherBuilder with Default::default\(\)$',
'stack-encrypt/src/sem/mod\.rs:\d+:\d+: replace <impl MatchConfig for DefaultMatch>::options -> MatchOptions with Default::default\(\)$',
# Both unit-context conversions explicitly return Self::default().
Expand All @@ -80,6 +85,40 @@ exclude_re = [
# the empty list (`dynamic::target::NoTargets`), which a test asserts on
# and `resolve` turns into `TargetError::NoTargets`; `vec![]` is the body.
'stack-encrypt/src/dynamic/target\.rs:\d+:\d+: replace <impl TargetResolver for NoTargets>::targets -> Vec<TargetDescriptor> with vec!\[\]$',
# A passthrough, and a typed null as any null, has no kind:
# `KindOf::passthrough` and `KindOf::typed_null` return `Ok(None)`, which
# is `Ok(Default::default())`. `a_frame_names_its_kind` asserts the first.
'stack-encrypt/src/dynamic/value_frame\.rs:\d+:\d+: replace <impl Sink for KindOf>::(passthrough|typed_null) -> Result<Self::Ok, DecodeError> with Ok\(Default::default\(\)\)$',
# `model`'s `admits` guard on a date, decimal or undefined value is checked
# again by vitaminc on every path that reaches it: the frame writer behind
# `Modeled` and `ModelOnly` refuses an inadmissible logical value
# (`FrameWriteError::Invalid`, mapped to the same `Expected`), and
# `ValueFrame::check` only walks frames `Frame::parse` has validated. So
# `true` there refuses the same values with the same error. The guard stays
# so the model says what it holds without leaning on the writer behind it.
'stack-encrypt/src/dynamic/value_frame\.rs:\d+:\d+: replace match guard logical\.admits\(&value\) with true in model$',
# A serde visitor's `expecting` writes only the "expected ..." half of a
# serde error's message, and no caller of these three reads that message:
# a context, statistics and a plan's root are each refused with one fixed
# `Reason` (`ContextKind`, `NotStats`, `NotAnObject`), and the plan's
# field-level reasons are read from the error's path, so writing nothing
# refuses the same input with the same error.
'stack-encrypt/src/dynamic/(context|query|record)\.rs:\d+:\d+: replace <impl (Visitor<\x27de> for ContextVisitor|serde::Deserialize<\x27de> for Confidence>::deserialize::<impl serde::de::Visitor<\x27_> for V|Deserialize<\x27de> for PlanWire>::deserialize::<impl Visitor<\x27de> for V)>::expecting -> fmt::Result with Ok\(Default::default\(\)\)$',
# The same for the visitor that reads a refused plan's keys back
# (`entry_key`): its error is discarded (`.ok()`), so its message is never
# read at all.
'stack-encrypt/src/dynamic/record\.rs:\d+:\d+: replace entry_key::<impl Deserialize<\x27de> for Keys>::deserialize::<impl Visitor<\x27de> for V>::expecting -> fmt::Result with Ok\(Default::default\(\)\)$',
# The JSON index. `unhex` joins a high nibble shifted into the top four
# bits with a low nibble below 16: the bits never overlap, so `^` is `|`.
'stack-encrypt/src/json/mod\.rs:\d+:\d+: replace \| with \^ in unhex$',
# `JsonPath::root` is `Self::default()`.
'stack-encrypt/src/json/path\.rs:\d+:\d+: replace JsonPath::root -> Self with Default::default\(\)$',
# A document always has a root, so its terms are never empty: `false` is
# the value `is_empty` returns. The `true` replacement is still caught.
'stack-encrypt/src/json/derive\.rs:\d+:\d+: replace JsonTerms::is_empty -> bool with false$',
# A JSON operator's input: the `JsonText` visitor's `expecting` writes a
# message `read_frame` discards for its fixed `Reason::JsonInput`.
'stack-encrypt/src/dynamic/json_query\.rs:\d+:\d+: replace <impl Deserialize<\x27de> for JsonText>::deserialize::<impl Visitor<\x27_> for V>::expecting -> std::fmt::Result with Ok\(Default::default\(\)\)$',
]

# Headroom over the measured baseline before a slow-but-correct mutant is
Expand Down
6 changes: 6 additions & 0 deletions .changeset/chacha20-0-10-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@cipherstash/protect-ffi': patch
'@cipherstash/auth': patch
---

Build the native binaries against `chacha20` 0.10.2. Versions 0.10.0 and 0.10.1 were yanked: on an x86 CPU without AVX2, their SSE2 fallback for the random number generator used an SSE4.1 instruction it had not checked the CPU for. A CPU without SSE4.1 (one from before 2008, or a virtual machine using QEMU's default `qemu64` CPU model) would crash with an illegal-instruction error. Every other CPU produced correct random numbers, so randomness was never weakened. No API change.
5 changes: 5 additions & 0 deletions .changeset/eql-bindings-optional-storage-only.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/eql": patch
---

`eql-bindings` (the Rust crate released with this package): an EQL v4 type whose terms a null has, a storage-only type (`Date`, `Integer`, `Text`, ...) or one whose only term is equality's (`DateEq`, `IntegerEq`, `TextEq`, ...), now also implements `EncryptFrom` and `DecryptInto` for an `Option` of its plaintext, and its query twin `EncryptFrom` for one. For a type of fixed width a `None` seals as a typed null as long as a value (vitaminc 0.8), so an optional column does not show which rows are absent. For text it seals as a null that is not padded, since text's ciphertext is as long as the text, so its length may show that the value is absent. Either way it opens as `None`; its `hm` is the one term every null shares, and the query of a `None` finds the stored nulls with `=`. A value seals exactly as before. The by-name dispatch (`encryption::targets`) reads, opens and queries these types through the `Option`; a type with an order or match term still refuses a null. eql-bindings' own `Date`, `Timestamp` and `Decimal` plaintexts declare their fixed width to vitaminc, so their `None` is padded too. The SQL bundle and the TypeScript types do not change.
5 changes: 5 additions & 0 deletions .changeset/eql-encrypted-json-operations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/eql": minor
---

**`JsonSearch` answers its JSON operators by name.** `eql-bindings`' target table row now tells Stack Encrypt the domain an ordering at a path binds as (`Target::leaf_query_sql_domain`, `eql_v4.query_json_leaf`), so a data plan's `lt_at`, `lte_at`, `gt_at`, `gte_at` and `between_at` bind their operand as that domain, beside `contains`, `contained_by` and `eq_at`, which bind the needle as `eql_v4.query_json`. No SQL changes.
5 changes: 5 additions & 0 deletions .changeset/eql-encrypted-json-target.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/eql": minor
---

**The `json_tree` family is in the EQL catalog as EQL v4's searchable JSON document, and a data plan can produce `public.eql_v4_json_search` by name: the target `JsonSearch`.** A language SDK names it in a plan field with the `json` type, gives it the JSON index's options (`{"name": "JsonSearch", "options": {"sealed_root": true, "ordered": ["$.age"]}}`, or the bare name for the defaults), and hands each document over as UTF-8 JSON text; the `eql-bindings` crate's by-name dispatch (`encryption::targets::encrypt_with`, `decrypt`) seals it through the same JSON index layout typed Rust uses and opens it back to its text. The text is parsed by Stack Encrypt's rules, before any key is requested: an object that names a member twice, an integer literal outside the 64-bit range, and text that is not JSON are refused (`TargetError::Json`, with a code and never a byte of the text). The catalog lists the family once (`eql_domains::DOCUMENT_FAMILIES`), so the target table, `v4::all()` / `v4::all_query()` and the Go types (`eql.JSONSearch`, `JSONSearchQuery`, `JSONSearchLeafQuery`, `JSONEntry`) are generated from it. The types take the names EQL v3 gives its searchable JSON document: `Json` (`public.eql_v4_json`) stays the storage-only type, `JsonSearch` is the searchable document, queried with `JsonSearchQuery` (`eql_v4.query_json`) and `JsonSearchLeafQuery` (`eql_v4.query_json_leaf`), and `JsonEntry` (`public.eql_v4_json_entry`) is one node as `->` and the reads return it. The JSON tree SQL domains are renamed to match: `public.eql_v4_json_tree` is now `public.eql_v4_json_search`, `public.eql_v4_json_tree_entry` is `public.eql_v4_json_entry`, `eql_v4.query_json_tree` is `eql_v4.query_json` and `eql_v4.query_json_tree_leaf` is `eql_v4.query_json_leaf`; the `eql_v4.json_tree_*` functions keep their names. The v4 bundle no longer carries the SteVec domains: in v4, `json_tree` implements `json_search`. The SteVec SQL (`src/v3/json/`) and the generated `json_entry_<T>` cross operators are confined to EQL v3 with `-- ONLY EQL VERSION: 3`, and the v4 target table drops its unproducible `SteVecDocument` row. The v3 bundle gains only those directive comment lines.
5 changes: 5 additions & 0 deletions .changeset/eql-json-tree-cascade-and-random-order.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/eql": patch
---

EQL v4 `json_tree` (unreleased): a stored document's entries are now in a random order, root first, an object's members get a random permutation as their ordinals (the `o` the server probes a node's children at, which was a keyed rank), and its containment projection `q` is shuffled the same way, so the stored order no longer shows each row's tree, the size of every subtree or the byte order of sibling key names (#1357). A containment or equality needle is sent in a random order of its own too, so a query no longer shows sibling key order either. Every entry's ciphertext now also commits to its children's AEAD tags, so the client checks a subtree read's rows by the chain rather than by their positions, and a row swapped, dropped, added, reordered or moved beneath the node read is refused by the cipher. Nothing stored changes shape; `json_tree_children` returns a node's children in ordinal order (an array's elements by position), where it returned them by stored slot, and no other SQL function changes (three doc comments stop promising document order); documents sealed by the earlier build of this unreleased family no longer open. `->`, `->>` and an ordering on `eql_v4.ord_term(col -> sel)` at a wildcard path now return an unspecified element of the row (the same one every time), not element 0; read every element with `json_tree_path_query`. `->` on an object or array with members no longer opens on the client (the entry's ciphertext commits to its children, which `->` does not return): Stack Encrypt reports `JsonNotALeaf`, which is also what an altered entry looks like through `->`; read a container with a subtree read. `docs/reference/json-tree-leakage.md` says what the stored row still shows and what a read now proves.
9 changes: 9 additions & 0 deletions .changeset/eql-json-tree-derivable-tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@cipherstash/eql": minor
---

EQL v4 `json_tree` (unreleased): a subtree read sends the token of exactly the node it reads, and returns that node. Every token is now derivable from its node's path alone: an object member's is `H("t" ‖ t(parent) ‖ s)`, with no ordinal, and an array element's keeps its index. Every stored entry gains a self tag `x`, the first eight bytes of `H("x" ‖ iv ‖ t)`, by which the server finds the node a token names; the entry validator requires it, so a document written by the earlier build of this unreleased family is refused. A read of `$.profile.address.city` used to send `$.profile`'s token, a capability over that whole field in every row, and walk to the leaf through gates; it now sends the leaf's token and nothing that covers any node above it.

**SQL signature changes.** `eql_v4.json_tree_subtree(doc, tokens text[], budget integer DEFAULT 64)` replaces `json_tree_subtree(doc, token, budget)` and `json_tree_subtree_at(doc, token, gates, budget)`, which is removed: for each token in order it returns the entry whose `x` matches at `d = 0`, then its descendants with `d` their depth below it, so `{}`, `[]`, a scalar and a missing node are four answers, as `jsonb` gives them (#1356). The budget counts rows across all the tokens. `json_tree_children(doc, token)` and `json_tree_child_count(doc, token)` lose their `gates` argument and take the token of any node; `json_tree_child_count` of a token that names no node is NULL, as `jsonb_array_length` of a missing path is (it was 0), and so is the sealed root's, whose top-level fields chain from nothing. `eql_v4_internal.json_tree_child_token` is replaced by `json_tree_member_token`, `json_tree_element_token`, `json_tree_self_tag`, `json_tree_hit_token` and `json_tree_index`, which maps every entry's `x`, and every chained entry's `p`, to its position in `sv`; `json_tree_by_parent` is removed. The chain primitives carry the `eql-inline-critical` marker, so the post-install step leaves their `search_path` unpinned and the planner inlines them: pinned, every probe of a walk was a full SQL-function call, which was most of a read's cost.

A wildcard (`$.items[*].price`) is expanded by the client into one token per position below a bound, 64 by default, plus a probe at the bound; a row where the probe finds an element fails the read with the bound rather than return part of the list, walked or fallen back to the sealed root. A read of `$` is legal under the sealed root and returns the root entry, which opens to the whole document. Stored documents grow by about a tenth in characters (+9.8% on a nested document, +9.4% on a flat one). `JsonHeader::FORMAT_VERSION` and the document's `v` are unchanged. In `eql-bindings`, `JsonTreeEntry` gains `x` and `JsonTreeSubtree` opens to `Option<Value>`; in Stack Encrypt, `JsonSubtreeKey` carries the token list (`tokens()`, `probes()`, `bound()`), `KeysetCipher::json_subtree_key_with_bound` sets the bound, `Error::JsonWildcardTruncated` and `TermError::JsonWildcardTooWide` are new, and `TermError::JsonSealedRoot` is removed. What the database learns is in `docs/reference/json-tree-leakage.md`; the design and the decisions behind it are in `docs/plans/2026-10-17-json-tree-index.md`, "Design change (2026-10-24)".
7 changes: 7 additions & 0 deletions .changeset/eql-json-tree-domain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cipherstash/eql": minor
---

**EQL v4 gains the `json_tree` domain family: `public.eql_v4_json_search`, an encrypted JSON document stored as one entry per node, with `@>` and `<@` that agree with PostgreSQL's own `jsonb @>` across array elements.** The family is new beside `public.eql_v4_json` and is not a port of the v3 SteVec surface: it is what Stack Encrypt's JSON index writes. A document's entries each carry a path selector `s` and a value selector `vs` (containment is a set comparison over the pair), the node's own ciphertext `c` (its label, kind and scalar value; a document's ciphertext is linear in its size, where a SteVec document repeats every subtree at every level), and a token chain (`p`, `w`, `o`) that lets core PostgreSQL walk the subtree under a node from one client-derived token: `eql_v4.json_tree_subtree(doc, token)`, `json_tree_subtree_at(doc, token, selector)`, `json_tree_children` and `json_tree_child_count`. By default the root is sealed, so no query can hand the server a token for the whole column. Containment projects a stored document into an element-nested shape from its group tags (`n`, `g`), `eql_v4.json_tree_query(doc)`, and compares it with the needle (`eql_v4.query_json`) by native `jsonb @>`, so each needle array element must fit inside one stored element, which closes the cross-element false positives of selector-set containment (#1231) for this family; a GIN index on `(eql_v4.json_tree_query(col)::jsonb) jsonb_path_ops` serves it. `->` by selector returns an entry that opens on its own (`public.eql_v4_json_entry`, with the header and ordinal grafted), and `eql_v4.query_json_leaf` orders an extracted number or string leaf with `<`, `<=`, `>`, `>=`. Every other native jsonb operator on the column is blocked, as on the other EQL domains. EQL v4 only (`-- ONLY EQL VERSION: 4`); the v3 bundle's SQL is unchanged. The `eql-bindings` crate carries the hand-written `v4::json_tree` types with Stack Encrypt's `EncryptFrom` / `DecryptInto` for the document and the entry.

Why. Stack Encrypt had no JSON index: the operators (`Contains`, `ContainedBy`, `AtPath`) were declared and answered by nothing, and the v4 JSON wire format was unconstrained by anything shipped. This is Phase 1 and 2 of the `json_tree` index's phased plan (#1249), implemented against `docs/plans/2026-10-17-json-tree-index.md`, whose "Implementation notes" section records where the code deviates from the design.
5 changes: 5 additions & 0 deletions .changeset/eql-json-tree-extracted-entry-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/eql": patch
---

EQL v4 `json_tree` (unreleased): the client now checks that what `->` and the subtree walks return is what it asked for. Every entry of a stored document is sealed under its own path selector and position, so any entry of the row opened, and a database could answer `doc -> s($.salary)` with the row's `$.bonus`, or with the sealed root (the whole document), or splice other entries into a walk. In the `eql-bindings` crate an entry `->` returned now opens through the selector that asked for it, `JsonTreeExtracted::from_selector(&selector, entry)`, which refuses an entry carrying any other selector; `JsonTreeEntry` no longer opens on its own. A walk's rows, opened through `JsonTreeSubtree::from_key(&key, rows)` as before, are each checked against the key's path: the node a gated walk reaches must carry the path's selector and position, every other row the selector of its parent's path and its own label, and the rows must follow each other in the document with no gap. A refusal is `stack_encrypt::Error::JsonWrongEntry`. Not checked, by design: which row of the column an entry comes from (ADR 0010). The SQL is unchanged.
Loading
Loading