Release 0.2.0#21
Merged
Merged
Conversation
…n instructions (#17)
* feat: ✨ Add SensitiveDateValidator * README * Docs, linting, and additional tests * MODULARIZATION_REPORT * Typos
* security: bump time crate to 0.3.47 (RUSTSEC-2026-0009) Updates Cargo.lock to pull in time >=0.3.47, addressing the DoS via stack exhaustion advisory flagged by cargo audit. The vulnerable version was pulled in transitively through x509-parser 0.16.0. Requires rustc >=1.88.0, which matches what the CI rust job already installs via dtolnay/rust-toolchain@stable. * feat: dynamic validator args dispatch (#18) Replaces the hardcoded subject_alt_names special case in core.validate() with a generic dispatch that discovers each validator's user arguments from its validate() signature. New validators automatically participate in argument passing without any core changes. Contract for validator authors: - The first three positional params of validate() are framework- supplied (cert/cipher data, host, port). Their names don't matter. - Any additional user-configurable arguments must be keyword-only, annotated, and have a default value. - Enforcement runs in BaseCertValidator/BaseCipherValidator __init_subclass__ at import time; malformed signatures raise TypeError before the class can be used. Performance: signature inspection happens once, at class definition, via __init_subclass__. The per-call dispatch hot path is a frozen-set difference and a dict unpack — sub-microsecond, zero inspect calls. User-facing API: - Canonical form: validate(validator_args={"name": {"arg": value}}) - The bare-list shorthand (subject_alt_names=[...]) still works for one-arg validators but now emits a DeprecationWarning. - New CertMonitor.describe_validators() returns every validator's name, doc, and argument schema (annotation, default) for introspection — reads the cached _user_params populated at class definition time. Validator migrations (signature changes only, no behavior changes): - subject_alt_names: alternate_names is now keyword-only. - sensitive_date: *args: SensitiveDate -> *, dates: Optional[List[ SensitiveDate]] = None. Weekend/leap-day flagging, return shape, and the internal isinstance check are unchanged. Existing tests that asserted positional dispatch were updated to the kwargs form. New tests cover enforcement (well-formed, missing annotation, missing default, *args, **kwargs, cipher parity), dispatch (canonical dict form, deprecation shim with pytest.warns, unknown arg, invalid arg type, validator raising TypeError), and describe_validators (shape, per-validator args, plain-class annotation rendering). Coverage: 98.67% (gate 95%); validators/base.py and all new core dispatch code are at 100%.
Follow-up to #18 addressing the issues that held this validator back from the last release. Purely additive changes to public output; core behavior (weekend / leap-day / user-date matching) is unchanged. Changes ------- - Error handling: replaces ``raise TypeError`` for malformed input with a structured error dict, matching every other validator's contract. The #18 dispatch layer also catches TypeError as a safety net, but the check now lives where it belongs — at the top of ``validate()``. - Input normalization: ``dates`` now accepts any of ``SensitiveDate``, ``date``, ``datetime``, an ISO 8601 string, or a ``(name, date)`` tuple. Bare dates and ISO strings auto-generate names from the ISO form, so users reading blackout dates from a YAML file or a simple list don't have to import the ``SensitiveDate`` named tuple just to use the validator. All forms can be mixed freely in a single call. - Structured match field: adds ``sensitive_date_matches`` to the return dict — a list of ``{"name", "date"}`` entries for every user-supplied date that matched. Callers that previously had to regex-parse the ``warnings`` list can now read a machine-friendly field. ``warnings`` is preserved for human-readable summaries. - Weekend / leap-day warning strings: when ``weekend_expiry`` or ``leapday_expiry`` fire, a corresponding human-readable line is now appended to ``warnings``. Previously these conditions set booleans but produced empty warnings, which was confusing when scanning logs. - Shared ``parse_not_after`` helper: extracts the ``notAfter`` format string into ``certmonitor/validators/_utils.py`` and migrates both ``expiration`` and ``sensitive_date`` to use it. Future format changes only need to touch one place. Docs ---- - Adds a sensitive_date example to ``docs/usage/validator_args.md`` showing all four input forms. - Adds the previously-missing ``SensitiveDate`` nav entry to ``mkdocs.yml`` so the validator's auto-generated reference page is reachable. - Regenerates ``MODULARIZATION_REPORT.md``. Tests ----- New coverage: one test per input form (SensitiveDate, date, datetime, ISO string, ``(name, date)`` tuple, ``(name, datetime)`` tuple, mixed); weekend warning string content for both Saturday and Sunday; leap-day warning string; structured ``sensitive_date_matches`` field; structured error dicts for invalid type, malformed ISO string, and bad tuple shape; ``dates=[]`` and ``dates=None`` behavior. All 360 tests pass; coverage 98.73% (sensitive_date.py, _utils.py, and expiration.py all at 100%). Depends on #18 (branches off feature/dynamic-validator-args).
- Bump certmonitor to 0.2.0 in pyproject.toml - Bump certinfo (Rust crate) to 0.2.0 in Cargo.toml and regenerate Cargo.lock - Backfill missing CHANGELOG entry for 0.1.4 from the published release notes - Add [0.2.0] CHANGELOG section with Breaking changes, Added, Changed, Deprecated, and Fixed categories This is a minor version bump because the release contains genuine breaking changes: the validator author contract now requires user args to be keyword-only, annotated, and defaulted (enforced at import time), and the subject_alt_names and sensitive_date validator signatures changed. The bare-list validator_args shorthand still works via a deprecation shim. Also bumps the minimum rustc from 1.86 to 1.88 transitively via the time 0.3.47 upgrade that addresses RUSTSEC-2026-0009. Affects contributors and source builds only; published wheels are unaffected.
Automated reformat performed by uv during ``make develop`` — bumps the lockfile schema revision and renames ``upload_time`` to ``upload-time`` across every entry. No package versions change. Separated from the 0.2.0 release-prep commit so that commit stays reviewable.
- Fix duplicated sections that accumulated from earlier edits during the version bump from 0.1.5 to 0.2.0 - Rewrite the 0.2.0 entry to match the marketing style used for the v0.1.4 release notes (header, overview, emoji section markers, Python compatibility + license footer, Full Changelog compare link) - Reframe validator author contract changes as notable Changed items rather than breaking changes — no user-facing API breaks, existing validator_args call style still works via the deprecation shim - Correct the overview: the sensitive_date validator itself is what has been sitting on develop since #15; input form improvements came along with this release
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release 0.2.0
Minor version bump. This release sweeps every unreleased commit on
developsincev0.1.4ontomainand tags0.2.0.Why a minor (not patch) bump
This release contains genuine breaking changes under semver, even for a pre-1.0 library:
validate()must now be keyword-only, type-annotated, and have a default value. Enforcement runs in__init_subclass__at import time. Third-party validators that don't conform will raiseTypeErrorat import.subject_alt_names/sensitive_datesignatures: both validators' user arguments became keyword-only. Direct positional callers break.validator_argscanonical form is now a nested dict. The pre-0.2.0 bare-list shorthand still works with aDeprecationWarning(migration, not a hard break).time 0.3.47security bump). Affects contributors and source builds only — published wheels are unaffected.See CHANGELOG.md for the full per-category list and migration notes.
What's in this release
Highlights (full list in the CHANGELOG):
CertMonitor.describe_validators(): introspection helper returning every validator's arg schema.sensitive_datecleanup: accepts baredate, ISO strings,(name, date)tuples, anddatetimein addition toSensitiveDate; adds structuredsensitive_date_matchesfield; weekend/leap-day conditions now emit warning strings; errors returned as dicts instead ofraise.timecrate bumped to 0.3.47).[0.1.4]section was reconstructed from the published release notes.Commits included
chore: uv.lock format migration (revision 2 -> 3)chore: prepare 0.2.0 release(version bumps + CHANGELOG)fix: sensitive_date validator cleanup and ergonomics (#20)feat: dynamic validator args dispatch (#18) (#19)housekeeping: remove obsolete test scripts for public key verificationfeat: :sparkles: Add SensitiveDateValidator (#15)Add Contributor Code of Conduct and remove Rust toolchain installation instructions (#17)Test plan
make testgreen at 0.2.0 (ruff format/lint, cargo fmt/clippy, 360 pytest at 98.73%, mypy, cargo audit, bandit, wheel build)cargo checkregeneratedCargo.lockwithcertinfo v0.2.0## [0.2.0]CHANGELOG section on tag pushv0.2.0will be pushed manually after this PR merges tomainAfter merge
Per the existing release workflow:
main(release notes and version bump land there).v0.2.0tag onmain— that triggers release.yml and creates the GitHub Release from the CHANGELOG section. PyPI publishing is handled byci.yml.developneeds a fast-forward (or merge) frommainto pick up the version bump + CHANGELOG so the next round of development starts from the right base.