Skip to content

fixture: add x.509 trust/time/path negatives#314

Merged
EffortlessSteven merged 1 commit into
mainfrom
work/279-x509-negatives
Mar 27, 2026
Merged

fixture: add x.509 trust/time/path negatives#314
EffortlessSteven merged 1 commit into
mainfrom
work/279-x509-negatives

Conversation

@EffortlessSteven

Copy link
Copy Markdown
Member

Summary

  • lift ChainSpec to use NotBeforeOffset for leaf/intermediate not_before and add minimal intermediate CA/key-usage overrides
  • add the missing chain negatives for not-yet-valid leaf/intermediate plus intermediate path failures (IntermediateNotCa, IntermediateWrongKeyUsage)
  • expose the new X509Chain helpers and extend tests, snapshots, README/docs, and the X.509 example to cover the expanded chain-negative surface

Closes #279.

Verification

  • cargo test -p uselesskey-core-x509-spec
  • cargo test -p uselesskey-core-x509-chain-negative
  • cargo test -p uselesskey-x509 --test x509_unit
  • cargo test -p uselesskey-x509 --test x509_comprehensive
  • cargo check -p uselesskey --example x509_certificates --features x509
  • cargo xtask gate --check

@coderabbitai

coderabbitai Bot commented Mar 27, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e3f44e61-0d0d-467f-a078-7f1d747c1575

📥 Commits

Reviewing files that changed from the base of the PR and between ca885d0 and 42fcc4d.

⛔ Files ignored due to path filters (16)
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots/snapshots_chain_negative__chain_neg_all_variant_names.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots/snapshots_chain_negative__chain_neg_expired_intermediate.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots/snapshots_chain_negative__chain_neg_expired_leaf.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots/snapshots_chain_negative__chain_neg_hostname_mismatch.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots/snapshots_chain_negative__chain_neg_intermediate_not_ca.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots/snapshots_chain_negative__chain_neg_intermediate_wrong_key_usage.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots/snapshots_chain_negative__chain_neg_not_yet_valid_intermediate.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots/snapshots_chain_negative__chain_neg_not_yet_valid_leaf.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots/snapshots_chain_negative__chain_neg_revoked_leaf.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots/snapshots_chain_negative__chain_neg_unknown_ca.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-negative/tests/snapshots/snapshots_negative__chain_negative_applied_specs.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-negative/tests/snapshots/snapshots_negative__chain_negative_variant_names.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-spec/tests/snapshots/snapshots_x509_spec__chain_spec_custom.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-spec/tests/snapshots/snapshots_x509_spec__chain_spec_default.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509-spec/tests/snapshots/snapshots_x509_spec__chain_spec_stable_bytes.snap is excluded by !**/*.snap
  • crates/uselesskey-core-x509/tests/snapshots/snapshots_core_x509__chain_negative_all_variants.snap is excluded by !**/*.snap
📒 Files selected for processing (27)
  • crates/uselesskey-core-x509-chain-negative/src/lib.rs
  • crates/uselesskey-core-x509-chain-negative/tests/chain_negative_tests.rs
  • crates/uselesskey-core-x509-chain-negative/tests/comprehensive_tests.rs
  • crates/uselesskey-core-x509-chain-negative/tests/integration.rs
  • crates/uselesskey-core-x509-chain-negative/tests/mutant_killers.rs
  • crates/uselesskey-core-x509-chain-negative/tests/property_tests.rs
  • crates/uselesskey-core-x509-chain-negative/tests/snapshots_chain_negative.rs
  • crates/uselesskey-core-x509-negative/tests/negative_tests.rs
  • crates/uselesskey-core-x509-negative/tests/snapshots_negative.rs
  • crates/uselesskey-core-x509-negative/tests/x509_negative_integration.rs
  • crates/uselesskey-core-x509-spec/src/chain_spec.rs
  • crates/uselesskey-core-x509-spec/tests/comprehensive.rs
  • crates/uselesskey-core-x509-spec/tests/integration.rs
  • crates/uselesskey-core-x509-spec/tests/mutant_killers.rs
  • crates/uselesskey-core-x509-spec/tests/snapshots_x509_spec.rs
  • crates/uselesskey-core-x509-spec/tests/spec_edge_cases.rs
  • crates/uselesskey-core-x509-spec/tests/spec_integration_tests.rs
  • crates/uselesskey-core-x509/tests/negative_policy_tests.rs
  • crates/uselesskey-core-x509/tests/snapshots_core_x509.rs
  • crates/uselesskey-x509/src/chain.rs
  • crates/uselesskey-x509/src/chain_negative.rs
  • crates/uselesskey-x509/tests/x509_comprehensive.rs
  • crates/uselesskey-x509/tests/x509_unit.rs
  • crates/uselesskey/README.md
  • crates/uselesskey/examples/x509_certificates.rs
  • docs/adr/0006-negative-fixtures-first-class.md
  • docs/explanation/architecture.md

Summary by CodeRabbit

Release Notes

  • New Features

    • Added certificate chain fixtures for additional validation failure scenarios: not-yet-valid leaf and intermediate certificates, intermediate certificates without CA status, and intermediate certificates with incorrect key usage.
    • Enhanced certificate configuration to support fine-grained control over validity windows and intermediate certificate properties.
  • Documentation

    • Updated X.509 chain fixture documentation to reflect expanded negative test scenarios.

Walkthrough

This pull request expands X.509 chain negative fixtures by adding four new test scenarios (not-yet-valid leaf/intermediate, intermediate lacking CA status, intermediate with incorrect key usage) and refactors timing configuration from numeric day-offsets to an enum-based NotBeforeOffset representation supporting both past and future dates.

Changes

Cohort / File(s) Summary
Core Data Structure Refactoring
crates/uselesskey-core-x509-spec/src/chain_spec.rs
Replaced leaf_not_before_offset_days / intermediate_not_before_offset_days (Option<i64>) with leaf_not_before / intermediate_not_before (Option<NotBeforeOffset>). Added intermediate_is_ca: Option<bool> and intermediate_key_usage: Option<KeyUsage> fields with corresponding builder methods. Bumped stable_bytes() version from v2 to v3.
Negative Fixture Enum Extension
crates/uselesskey-core-x509-chain-negative/src/lib.rs
Added four new ChainNegative variants: NotYetValidLeaf, NotYetValidIntermediate, IntermediateNotCa, IntermediateWrongKeyUsage. Updated variant_name() mapping and apply_to_spec() to handle future-dated certificates and intermediate CA/key-usage overrides.
Certificate Generation Implementation
crates/uselesskey-x509/src/chain.rs, crates/uselesskey-x509/src/chain_negative.rs
Added apply_not_before helper for computing timestamps from NotBeforeOffset. Added key_usage_purposes to derive key usages from KeyUsage spec. Updated intermediate/leaf generation to use configurable is_ca and key usages. Added four new public methods: not_yet_valid_leaf(), not_yet_valid_intermediate(), intermediate_not_ca(), intermediate_wrong_key_usage().
Spec Tests
crates/uselesskey-core-x509-spec/tests/comprehensive.rs, crates/uselesskey-core-x509-spec/tests/integration.rs, crates/uselesskey-core-x509-spec/tests/mutant_killers.rs, crates/uselesskey-core-x509-spec/tests/snapshots_x509_spec.rs, crates/uselesskey-core-x509-spec/tests/spec_edge_cases.rs, crates/uselesskey-core-x509-spec/tests/spec_integration_tests.rs
Updated stable-bytes version expectation from 2 to 3. Replaced assertions using *_not_before_offset_days with *_not_before field comparisons using NotBeforeOffset enum variants.
Chain Negative Tests
crates/uselesskey-core-x509-chain-negative/tests/chain_negative_tests.rs, crates/uselesskey-core-x509-chain-negative/tests/comprehensive_tests.rs, crates/uselesskey-core-x509-chain-negative/tests/integration.rs, crates/uselesskey-core-x509-chain-negative/tests/mutant_killers.rs, crates/uselesskey-core-x509-chain-negative/tests/property_tests.rs, crates/uselesskey-core-x509-chain-negative/tests/snapshots_chain_negative.rs
Extended test coverage for new ChainNegative variants. Updated assertions from *_not_before_offset_days to *_not_before. Added field isolation tests ensuring timing and CA/key-usage changes apply only to intended certificate components.
Core X.509 Tests
crates/uselesskey-core-x509-negative/tests/negative_tests.rs, crates/uselesskey-core-x509-negative/tests/snapshots_negative.rs, crates/uselesskey-core-x509-negative/tests/x509_negative_integration.rs
Added helper expect_days_ago(NotBeforeOffset) for test assertions. Updated snapshots to use string representations of NotBeforeOffset. Extended variant coverage to include all four new ChainNegative variants.
X.509 Implementation Tests
crates/uselesskey-x509/tests/negative_policy_tests.rs, crates/uselesskey-x509/tests/snapshots_core_x509.rs, crates/uselesskey-x509/tests/x509_comprehensive.rs, crates/uselesskey-x509/tests/x509_unit.rs
Added comprehensive tests validating not-yet-valid certificates have future not_before timestamps, intermediate CA-status assertions, and key-usage validation. Introduced key-material preservation tests ensuring private keys remain unchanged across negative variants.
Documentation & Examples
crates/uselesskey/README.md, crates/uselesskey/examples/x509_certificates.rs, docs/adr/0006-negative-fixtures-first-class.md, docs/explanation/architecture.md
Updated documentation and examples to enumerate new negative fixture scenarios: not-yet-valid leaf/intermediate and intermediate CA/key-usage violations. Expanded architecture and ADR descriptions to reflect broader negative fixture coverage.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant ChainNegative
    participant ChainSpec
    participant X509Chain
    participant Certificate

    Caller->>X509Chain: not_yet_valid_leaf()
    X509Chain->>ChainNegative: apply(spec)
    ChainNegative->>ChainSpec: set leaf_not_before = DaysFromNow(730)
    ChainSpec-->>ChainNegative: modified spec
    X509Chain->>Certificate: generate with future not_before
    Certificate-->>X509Chain: certificate (not yet valid)
    X509Chain-->>Caller: X509Chain with not-yet-valid leaf

    Caller->>X509Chain: intermediate_wrong_key_usage()
    X509Chain->>ChainNegative: apply(spec)
    ChainNegative->>ChainSpec: set intermediate_is_ca = Some(true)
    ChainNegative->>ChainSpec: set intermediate_key_usage = KeyUsage{digital_signature: true, key_cert_sign: false, ...}
    ChainSpec-->>ChainNegative: modified spec
    X509Chain->>Certificate: generate intermediate with restricted usages
    Certificate-->>X509Chain: intermediate (wrong key usage)
    X509Chain-->>Caller: X509Chain with mismatched CA/usage
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Four new negatives hopped into our test warren,
With certificates not-yet-valid and CAs bearing spurious charmin'!
From DaysAgo to DaysFromNow, our fixtures now dance,
Intermediate CA and key-usage get their variance—
A v2-to-v3 leap makes our bytes more vibrant! 🏃‍♂️✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch work/279-x509-negatives

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@EffortlessSteven EffortlessSteven merged commit 42fcc4d into main Mar 27, 2026
2 of 4 checks passed

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request expands the X.509 negative fixture capabilities by adding support for not-yet-valid certificates and intermediate CA/key-usage violations. It introduces the NotBeforeOffset enum to distinguish between past and future offsets and updates the ChainSpec to include intermediate certificate overrides. Consequently, the deterministic stable_bytes representation has been bumped to version 3 to incorporate these rich offsets and new fields. Extensive test coverage and documentation have been updated to reflect these changes. I have no feedback to provide.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42fcc4da5f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

spec.leaf_not_before = Some(NotBeforeOffset::DaysAgo(730));
}
ChainNegative::NotYetValidLeaf => {
spec.leaf_not_before = Some(NotBeforeOffset::DaysFromNow(730));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Derive not-yet-valid offsets from current date

ChainNegative::NotYetValidLeaf sets DaysFromNow(730) relative to the deterministic base time, but deterministic_base_time_from_parts is anchored to a fixed 2025 window (BASE_TIME_EPOCH_UNIX + BASE_TIME_WINDOW_DAYS), so these certs land around 2027 and stop being future-dated as wall-clock time advances (partially during 2027, fully by 2028-01-01); at that point the advertised “not yet valid” chain negative can become valid in production tests. The same time-bomb applies to NotYetValidIntermediate a few lines below.

Useful? React with 👍 / 👎.

@EffortlessSteven EffortlessSteven deleted the work/279-x509-negatives branch April 3, 2026 03:45
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.

fixture: add x.509 trust/time/path negatives

1 participant