Skip to content

feat(TC-498): authorize exact native share email delivery - #229

Merged
samgbafa merged 7 commits into
mainfrom
feat/tinycloud-native-sharing
Sep 15, 2026
Merged

samgbafa merged 7 commits into
mainfrom
feat/tinycloud-native-sharing

Conversation

@samgbafa

@samgbafa samgbafa commented Aug 22, 2026 •

Copy link
Copy Markdown
Contributor

Scope

Joins TinyCloud-native Policy/v3 sharing to an email-only delivery service without giving that service content or authority.

  • Policy/v3 remains admission/control only; ordinary /delegate and /invoke remain the data plane, with no /share routes
  • root status stays usable through the signed root expiry rather than a five-minute owner-daemon lease
  • generic SDK root revocation is checked together with signed Policy/v3 status for invocation, new admission, delivery, and status renewal
  • descriptor status.freshnessSeconds is enforced for the non-revocable email-proof profile on both account and accountless admission paths
  • production delivery audience is pinned to https://email.tinycloud.xyz; https://api.share.tinycloud.xyz is rejected outside the hermetic fixture
  • the reviewed bundle hand-off contract documents exact origin/node/enforcer binding and the Node release environment

Toolchain determinism

At head 3912553e69dd84d5012e8d62f4ba106d6d0df8a2, rust-toolchain.toml pins reviewed Rust 1.97.1 for local and cargo-dist release commands. The Docker builder uses rust:1.97.1-alpine and fails fast if rustc -V differs; all Rust CI, release-plz, and descriptor-export jobs use the same exact dtolnay/rust-toolchain@1.97.1 pin. This prevents Rust 1.98 from introducing 35 unrelated deny-warning result_large_err failures. No lint suppression or core error-type refactor is included.

Verification

At head 3912553e69dd84d5012e8d62f4ba106d6d0df8a2:

  • injected-clock root-liveness test proves an unrevoked root remains usable after 301 seconds and generic revocation denies it
  • mounted Policy/v3 integration proves an SDK /revoke denies an existing invocation plus fresh challenge admission and delivery; the existing presentation replay denial remains covered
  • descriptor freshness and email-origin contract tests pass
  • cargo fmt --all -- --check, RUSTFLAGS=-Dwarnings cargo check --workspace --all-targets, and RUSTFLAGS=-Dwarnings cargo clippy --workspace --all-targets pass on Rust 1.97.1
  • cargo test -p tinycloud-node -- --test-threads=1 previously passed: 349 library tests plus all integration/doc tests. The default parallel invocation has a pre-existing timing-sensitive quota test that intermittently observes zero background requests; its isolated test passes.
  • Docker daemon access is unavailable in this worker, so the image-stage build could not be executed locally; the committed Dockerfile includes the exact-image pin and compiler-version guard.

Downstream Share bundle generation must emit emailOrigin=https://email.tinycloud.xyz before rotating/removing its legacy bundle. No merge, release, or deployment is included.

@samgbafa

Copy link
Copy Markdown
Contributor Author

Superseding security evidence for 67c20a536cce39fd09b38fd568b40c7a8c35dcc0:

  • Policy/v3 derives tinycloud.email-proof/v1 freshness from its pinned authenticated profile/issuer contract (300 seconds), not the unsigned wrapper status.freshnessSeconds. The account/accountless integration mutates the outer status to 3600 seconds after issuance and is denied at +301 seconds while the issuer-signed compact SD-JWT remains unchanged.
  • Delivery now consumes the existing SDK/Share native sealedEnvelope + envelopeKey contract: AES-256-GCM v1 sealed envelope (AAD tinycloud-share-envelope-v1), CID over sealed bytes, compact URL https://share.tinycloud.xyz/s/<cid>#k=<key>. Node recomputes the CID, decrypts, canonical-binds the signed recipient envelope, and rejects plaintext ?tc2 links. The compact and inline-fragment tests prove URL path/query/loggable portions contain no recipient email while the delivery projection binds the exact recipient. envelopeKey unwraps share-envelope metadata only, not document content.
  • No SDK/Share wire-contract change is required; Node was brought back into alignment with current native SDK fields and URL shape. The durable downstream hand-off contract now records this.

Verified locally on the reviewed Rust 1.97.1 pin: cargo fmt --all -- --check; RUSTFLAGS=-Dwarnings cargo check -p tinycloud-node --tests; RUSTFLAGS=-Dwarnings cargo clippy -p tinycloud-node --all-targets -- -D warnings; focused delivery/freshness tests; and cargo test -p tinycloud-node --lib -- --test-threads=1 (349 passed, 0 failed). No merge, release, or deployment.

@samgbafa
samgbafa merged commit 4a441ad into main Sep 15, 2026
16 checks passed
@samgbafa
samgbafa deleted the feat/tinycloud-native-sharing branch September 15, 2026 01:16
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