Skip to content

feat(TC-887): sealed KV block plumbing and plaintext sizes by space tag - #518

Draft
samgbafa wants to merge 1 commit into
skgbafa/tc-887-r3-node-wiringfrom
skgbafa/tc-887-r4-kv-sealed
Draft

samgbafa wants to merge 1 commit into
skgbafa/tc-887-r3-node-wiringfrom
skgbafa/tc-887-r4-kv-sealed

Conversation

@samgbafa

@samgbafa samgbafa commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

TC-887, part 4 of the refreshed at-rest stack (base: #515). Replaces #329 (skgbafa/tc-887-s3-kv-sealed), ported onto current main.

What

  • tinycloud-node-server/src/storage/sealed.rs: the decisions and envelope plumbing the S3 and FileSystem block stores share: write target (legacy in off, sealed iff encrypting, else 503), read plan (sealed then legacy; strict sealed only; locked keys: legacy only and a miss is 503), the name contains checks (the one a write would use), the names orphan removal deletes, whole-object and range decryption, file/in-memory sealing, and reason-coded AtRestStoreErrors. It uses the core AtRestView/AtRestSource from feat(TC-887): node wiring for at-rest keys, with a root from the environment #515; a thin AtRestHandle only gives stores a Debug + Clone handle.
  • Sealed names keep the HMAC inputs of sealed_object_name/space_tag (KAT vectors unchanged) and get the same @N generation suffix as legacy names (TC-735), appended outside the HMAC. BlobIdentity::KvBlock stays {space, content_hash}. Documented in docs/at-rest/INTERFACES.md §5.
  • storage/size.rs: sealed bytes are counted per space tag and joined to a space once keys can name the tag. Main's TC-1578 semantics are kept: init_size never lowers or resets an entry (and returns the joined size), decrements saturate.
  • Boot scans: FS reads {blocks}/v1/ (and no longer trips over it as a non-DID directory); S3 adds one ListObjectsV2 under v1/, since main's KV listing is restricted to tinycloud:.
  • /invoke (after the database-failure branch), signed_kv_get and the public KV GET/HEAD routes map at-rest causes to 503/500.

Nothing seals yet: no store holds an at-rest handle in this PR, so behaviour in every mode is unchanged.

Verification (run locally)

  • cargo fmt --all

  • RUSTFLAGS=-Dwarnings cargo clippy --locked -p tinycloud-node -p tinycloud-core --all-targets: clean

  • cargo test --locked -p tinycloud-node --lib storage::: 54 passed (includes storage::sealed::tests, storage::size::tests, storage::file_system::test::boot_scan_counts_sealed_objects_by_tag)

  • tests/sql_object_store.rs::mock_s3_kv_scan_ignores_sql_objects now also allows the boot scan's LIST v1/ (it still requires LIST tinycloud: and refuses any other listing). Verified: cargo test --locked -p tinycloud-node --test sql_object_store mock_s3_kv_scan.

… at-rest error mapping

Adds storage::sealed (sealed names with the legacy @n generation suffix,
read/write/remove plans, envelope streaming, reason-coded errors), joins
sealed bytes counted per space tag at boot into a space's quota, and maps
at-rest storage errors to 503/500 on /invoke and the KV GET routes.
Nothing is sealed yet.
@samgbafa
samgbafa force-pushed the skgbafa/tc-887-r4-kv-sealed branch from 0fa782d to 2c35d3f Compare November 8, 2026 00:53

This branch has not been deployed

No deployments
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