Skip to content

test(store): check that what ck writes stays readable under the frozen format (LAB-10651) - #25

Merged
27Bslash6 merged 5 commits into
mainfrom
lab-10651-writer-format-test
Oct 23, 2026
Merged

27Bslash6 merged 5 commits into
mainfrom
lab-10651-writer-format-test

Conversation

@27Bslash6

@27Bslash6 27Bslash6 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

an_older_entry_still_decrypts checks that ck can read entries an older release wrote. Nothing checked the other direction. A cachekit-rs or cachekit-core writer change that the same release can still read, such as a prepended header byte, would pass every ck test, while an older ck sharing the backend would miss on every new entry and re-run the command.

What changed

  • what_ck_writes_the_frozen_format_reads writes values through Store::set on the file backend, takes the exact bytes ck handed to the backend, and opens them with an independent reader. It writes a short text value, an empty value, and zeros at every power of 4 from 1 byte to 16 MiB and at store.max_output() (20 MiB on the file store). A writer branch gated on size therefore passes unseen only if its whole range falls between two neighbouring sizes. The master key has 32 distinct bytes, so a byte-order mistake in the key's path into HKDF changes the key.
  • The reader (store::tests::frozen) rebuilds the subset of the format ck writes from the protocol spec, on RustCrypto alone: the HKDF-SHA256 key with the cachekit_v1_ length-prefixed salt and the encryption domain, the four-part v0x03 AAD (tenant, cache key, msgpack, False), and nonce(12) ‖ ciphertext ‖ tag(16) with nothing around it. Neither cachekit-rs nor cachekit-core derives the key or decrypts.
  • the_frozen_reader_reads_the_protocol_vectors pins that reader to known answers:
    • from the protocol's test-vectors/encryption.json 1.5.0, the basic_bytes AAD and ciphertext;
    • also from that file, the master_key_every_hex_digit entry (32 distinct key bytes, tenant default), sealed outside the Rust SDKs;
    • the cachekit-rs 0.9.0 ciphertext already in this module (OLD_CIPHERTEXT).
  • aes-gcm 0.10, hkdf 0.12 and sha2 0.10 become dev-dependencies. All three were already locked through cachekit-core (0.10.3, 0.12.4, 0.10.9). The Cargo.lock diff only lists them under cachekit-cli: it adds no package and changes no version.
  • The doc comment on an_older_entry_still_decrypts now says what it checks: a ciphertext from the same EncryptionLayer call ck makes, on cachekit-rs 0.9.0 and cachekit-core 0.6.0, whose plaintext is a fixed string rather than an Envelope.

Proof it catches the gap

Each change below went into a local copy of cachekit-rs 0.11.1 or cachekit-core 0.7.0 through [patch.crates-io], which is not committed. In each case the same release still reads its own output:

Writer change Result
encrypt prepends a 0xC4 byte; decrypt strips it only what_ck_writes_the_frozen_format_reads fails
AAD "True" for plaintexts above 64 KiB only that test fails
AAD "True" above 2 MiB only that test fails
AAD "True" for 64 KiB to 1 MiB only only that test fails, at the 64 KiB value
cachekit-core reverses the master key before HKDF only that test fails

A reference reader that reverses its key fails the_frozen_reader_reads_the_protocol_vectors on the master_key_every_hex_digit entry. Unmodified, every test passes.

Checks run locally

cargo fmt --all -- --check, cargo clippy --locked --all-targets -- -D warnings, cargo test --locked (21 unit, 45 run, 17 saas, 1 readme), cargo +1.85 check --locked --all-targets and cargo test --locked --release --test bench -- --ignored pass.

cargo deny check fails on RUSTSEC-2026-0386 (tokio 1.53.1, also locked on main). This PR's lock changes no version. #26 fixes it, and it should land first.

No docs needed: this is test-only and changes no behaviour or documented surface.

Closes LAB-10651

…ader

an_older_entry_still_decrypts checks that ck reads old entries. Nothing
checked the other direction: a writer change that the same release can
still read (a prepended header byte, say) passed every test while an
older ck sharing the backend would miss on every entry.

The new test stores a value through Store::set and opens the exact bytes
handed to the backend with HKDF-SHA256 and AES-256-GCM from RustCrypto,
rebuilding the key, the v0x03 AAD and the nonce/ciphertext/tag split
from the protocol spec. The reader is pinned to the protocol's
basic_bytes vector and to the cachekit-rs 0.9.0 ciphertext, so it reads
the frozen format rather than echoing today's writer.

aes-gcm, hkdf and sha2 become dev-dependencies at the versions already
locked through cachekit-core: no package or version changes in
Cargo.lock.

Also corrects the old-entry test's doc comment: its ciphertext comes
from the EncryptionLayer call ck makes, and its plaintext is not an
Envelope.
@kodus-27b

kodus-27b Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the `@kody start-review` command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Providing Context (Files & MCPs)

Add these hints in your PR description (or a comment) to unlock deeper checks:

  • Ticket / Acceptance Criteria: `Refs: ABC-123` (Linear/Jira/Asana/ClickUp/Trello) or a direct ticket link.
  • Bugfix Validation: a Sentry/Datadog/Bugsnag event link (or paste the stack trace/error message).
  • Endpoint Risk: mention the route (e.g., `POST /api/payments`) or controller/action name.
  • Attach a repo file as context: use an explicit marker like `@file:docs/guide.mdx#L10-L50` (replace with your real path).
  • API Contract Docs: include `@file:openapi.yaml` or `@file:swagger.json` when changing routes/schemas.
  • Definition of Done / Standards: include `@file:DOD.md` or `@file:CONTRIBUTING.md` if your repo has them.
  • Design System Source of Truth: include `@file:ui/index.ts` (replace with your DS entrypoint path).
  • Feature Flags: include the flag key/name and `@file:flags.ts` / `@file:config.json` (and optionally the PostHog flag name).
  • Edge/CDN Rules: link the Cloudflare rule/zone or describe the intended redirect/header behavior.
  • Attach an MCP tool output: use `@mcp<provider|tool>` (replace with an installed MCP provider + tool, e.g., `@mcp<sentry|events.search>`).
Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug ✅
Performance ✅
Security ✅
Business Logic ✅

Access your configuration settings here.

kodus-27b[bot]
kodus-27b Bot previously approved these changes Oct 23, 2026
The writer check now also stores the saas capture cap's worth of zeros,
so a writer branch gated on size (compression past a threshold, say)
cannot pass unseen. Its doc comment claims only what it shows: the bytes
put hands to the backend open under the frozen encryption format. A
failure now names both lengths and the leading stored bytes.

The reader's docs say it covers the subset ck writes. The key-fingerprint
check is dropped, since the basic_bytes open already pins the derived
key. OLD_KEY becomes KNOWN_ANSWER_KEY, and the old ciphertext's master
key is a named constant.
@kodus-27b

kodus-27b Bot commented Oct 23, 2026

Copy link
Copy Markdown

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the `@kody start-review` command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Providing Context (Files & MCPs)

Add these hints in your PR description (or a comment) to unlock deeper checks:

  • Ticket / Acceptance Criteria: `Refs: ABC-123` (Linear/Jira/Asana/ClickUp/Trello) or a direct ticket link.
  • Bugfix Validation: a Sentry/Datadog/Bugsnag event link (or paste the stack trace/error message).
  • Endpoint Risk: mention the route (e.g., `POST /api/payments`) or controller/action name.
  • Attach a repo file as context: use an explicit marker like `@file:docs/guide.mdx#L10-L50` (replace with your real path).
  • API Contract Docs: include `@file:openapi.yaml` or `@file:swagger.json` when changing routes/schemas.
  • Definition of Done / Standards: include `@file:DOD.md` or `@file:CONTRIBUTING.md` if your repo has them.
  • Design System Source of Truth: include `@file:ui/index.ts` (replace with your DS entrypoint path).
  • Feature Flags: include the flag key/name and `@file:flags.ts` / `@file:config.json` (and optionally the PostHog flag name).
  • Edge/CDN Rules: link the Cloudflare rule/zone or describe the intended redirect/header behavior.
  • Attach an MCP tool output: use `@mcp<provider|tool>` (replace with an installed MCP provider + tool, e.g., `@mcp<sentry|events.search>`).
Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug ✅
Performance ✅
Security ✅
Business Logic ✅

Access your configuration settings here.

kodus-27b[bot]
kodus-27b Bot previously approved these changes Oct 23, 2026
The file store keeps up to OUTPUT_CAP, not the saas cap, so a 1 MiB
write let a writer branch gated between the two pass unseen. The large
case now writes store.max_output() zeros.
@kodus-27b

kodus-27b Bot commented Oct 23, 2026

Copy link
Copy Markdown

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the `@kody start-review` command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Providing Context (Files & MCPs)

Add these hints in your PR description (or a comment) to unlock deeper checks:

  • Ticket / Acceptance Criteria: `Refs: ABC-123` (Linear/Jira/Asana/ClickUp/Trello) or a direct ticket link.
  • Bugfix Validation: a Sentry/Datadog/Bugsnag event link (or paste the stack trace/error message).
  • Endpoint Risk: mention the route (e.g., `POST /api/payments`) or controller/action name.
  • Attach a repo file as context: use an explicit marker like `@file:docs/guide.mdx#L10-L50` (replace with your real path).
  • API Contract Docs: include `@file:openapi.yaml` or `@file:swagger.json` when changing routes/schemas.
  • Definition of Done / Standards: include `@file:DOD.md` or `@file:CONTRIBUTING.md` if your repo has them.
  • Design System Source of Truth: include `@file:ui/index.ts` (replace with your DS entrypoint path).
  • Feature Flags: include the flag key/name and `@file:flags.ts` / `@file:config.json` (and optionally the PostHog flag name).
  • Edge/CDN Rules: link the Cloudflare rule/zone or describe the intended redirect/header behavior.
  • Attach an MCP tool output: use `@mcp<provider|tool>` (replace with an installed MCP provider + tool, e.g., `@mcp<sentry|events.search>`).
Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug ✅
Performance ✅
Security ✅
Business Logic ✅

Access your configuration settings here.

kodus-27b[bot]
kodus-27b Bot previously approved these changes Oct 23, 2026
Every key the format checks used repeated one byte, so it read the same
reversed and could not show a byte-order mistake in the key's path into
HKDF, in the writer or in the reference reader. The writer check now uses
the protocol's master_key_every_hex_digit key (32 distinct bytes), and
the reader is pinned to that vector's sealed entry.

Two sizes could not catch a writer branch gated on a range between them.
The writer check now also stores zeros at every power of 4 from 1 byte to
16 MiB, and its doc says what that covers.
@27Bslash6

Copy link
Copy Markdown
Contributor Author

@kody start-review

@kodus-27b

kodus-27b Bot commented Oct 23, 2026

Copy link
Copy Markdown

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the `@kody start-review` command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Providing Context (Files & MCPs)

Add these hints in your PR description (or a comment) to unlock deeper checks:

  • Ticket / Acceptance Criteria: `Refs: ABC-123` (Linear/Jira/Asana/ClickUp/Trello) or a direct ticket link.
  • Bugfix Validation: a Sentry/Datadog/Bugsnag event link (or paste the stack trace/error message).
  • Endpoint Risk: mention the route (e.g., `POST /api/payments`) or controller/action name.
  • Attach a repo file as context: use an explicit marker like `@file:docs/guide.mdx#L10-L50` (replace with your real path).
  • API Contract Docs: include `@file:openapi.yaml` or `@file:swagger.json` when changing routes/schemas.
  • Definition of Done / Standards: include `@file:DOD.md` or `@file:CONTRIBUTING.md` if your repo has them.
  • Design System Source of Truth: include `@file:ui/index.ts` (replace with your DS entrypoint path).
  • Feature Flags: include the flag key/name and `@file:flags.ts` / `@file:config.json` (and optionally the PostHog flag name).
  • Edge/CDN Rules: link the Cloudflare rule/zone or describe the intended redirect/header behavior.
  • Attach an MCP tool output: use `@mcp<provider|tool>` (replace with an installed MCP provider + tool, e.g., `@mcp<sentry|events.search>`).
Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug ✅
Performance ✅
Security ✅
Business Logic ✅

Access your configuration settings here.

@27Bslash6
27Bslash6 merged commit 6877a85 into main Oct 23, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant