Skip to content

fix(TC-500): pin email-domain freshness and prove exact domain equality - #238

Draft
samgbafa wants to merge 4 commits into
mainfrom
skgbafa/tc-500-email-domain
Draft

samgbafa wants to merge 4 commits into
mainfrom
skgbafa/tc-500-email-domain

Conversation

@samgbafa

@samgbafa samgbafa commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary (TC-500): prove email-domain policy semantics (tests only)

This PR adds no production code. It proves that the embedded Policy/v3 engine already enforces email-domain recipient shares exactly: a {emailDomain} credential requirement is satisfied only by equality with the issuer-signed disclosure and the envelope claim.

The test mints real issuer-signed SD-JWT email-domain credentials and asserts rejection for:

  • Different domain spellings: subdomain, tinycloud.xyz.evil, eviltinycloud.xyz, uppercase, trailing dot, Cyrillic homoglyph, an IDNA spelling, zero-width suffix.
  • Tampered claims or disclosures: envelope claims that differ from the signed disclosure (both directions), an unsigned extra disclosure, a duplicated disclosure, a tampered payload.
  • Wrong credential or holder: another holder; a relabelled envelope; a genuinely issuer-signed exact-email credential.
  • Substituted requirement: a requirement that doesn't match the owner-signed policy commitment.

It also shows that the exact domain is accepted.

Evidence: cargo test -p tinycloud-node --lib email_domain_requirement passes; cargo fmt --all -- --check is clean; RUSTFLAGS=-Dwarnings cargo clippy -p tinycloud-node --all-targets is clean. Replay, write escalation, sibling-read and tamper enforcement for domain shares are exercised end to end by the Share native joined gate against Node 1.17.1.

Release: tests only; no deploy impact. Independent of the OpenCredentials, SDK and Share domain PRs.

Follow-up: freshness pin (head 4c039fa)

This PR is no longer tests-only. pinned_profile_status_freshness_seconds now also pins 300 s for tinycloud.email-domain-proof/v1:

  • Same VCT opencredentials.email/v1 and the same trusted issuer.
  • The exact-email pin and the generic Policy/v3, /delegate and /invoke paths are unchanged.

Tests:

  • A domain credential is accepted at 299 s and rejected at 301 s (credential-time-invalid) under a requirement without maxAgeSeconds.
  • The exact-email pin is unchanged.
  • An unreviewed look-alike profile is not pinned.

Evidence:

  • cargo test -p tinycloud-node --lib policy_v3: 27 passed. Clippy (-Dwarnings, all targets) and fmt --check are clean.
  • The Share native joined gate passed against this exact Node commit (TC500_NODE_COMMIT=4c039fa) with OpenCredentials 846c018: exact email, bearer, and domain legs; sibling 403, write 403, tamper 401, revoked 403, replay 401.

Release: a Node release is needed for this defense-in-depth pin. Domain shares already carry maxAgeSeconds: 300, so this can ship before or after the domain PRs.

Rollback: reverting restores the prior exact-only pin; domain policies from Share still enforce 300 s through maxAgeSeconds.

samgbafa and others added 4 commits September 25, 2026 05:08
…equality

Adds an issuer-signed email-domain credential fixture and a Policy/v3 test:
a {emailDomain} requirement accepts only the exact issuer-signed domain and
rejects subdomains, suffixes, look-alikes, case, trailing-dot, zero-width and
IDNA spellings; envelope/disclosure mismatches; unsigned or duplicated
disclosures; payload tampering; another holder; the exact-email profile;
and a requirement substituted against the policy commitment. No production
code changes: the embedded policy engine already enforces this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a domain policy

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…credential

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Node pinned the reviewed mailbox-proof status freshness only for
tinycloud.email-proof/v1, so a domain policy whose requirement omitted
maxAgeSeconds would accept a domain credential for its whole issuer
lifetime. Apply the same 300-second pin to tinycloud.email-domain-proof/v1
(same vct and issuer). The exact-email pin, generic Policy/v3, /delegate and
/invoke are unchanged. Tests: a domain credential is accepted at 299 s and
rejected at 301 s under a requirement without maxAgeSeconds; the exact pin
is unchanged; an unreviewed look-alike profile is not pinned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@samgbafa samgbafa changed the title test(TC-500): email-domain requirements are exact signed-claim equality fix(TC-500): pin email-domain freshness and prove exact domain equality Sep 25, 2026
@samgbafa

Copy link
Copy Markdown
Contributor Author

Release blocked by where production's release branch lives — not merged. Production tee.node.tinycloud.xyz runs 1.17.2, built from the Codex/roman/tinychat-native-release-* line (see draft #231). That line is not on main, which is still 1.16.1.

  • Merging this PR to main and releasing through release-plz would not reach production.
  • Deploying a main build would roll production back to 1.16.x.

Path forward: cherry-pick 4c039fa (a one-function pin plus tests) onto the 1.17.x release line, cut 1.17.3, and promote it through that line's exact-digest process with its owner.

Nothing depends on this for now. It is defense-in-depth. Domain shares published by Share already carry maxAgeSeconds: 300, which Node enforces today; production verified this with the domain profile live.

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