release: v0.9.1 — auth scheme, doc-system router, lint adoption#53
Merged
Conversation
chore(release): v0.9.0 — mandatory --patterns + heuristic detectors + Chromium fix + lint cleanup
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
…ases Codecov flagged 5 uncovered lines in the v0.9.0 dialog resolution closure (browser.py:611, 615 partial, 629) — the defensive isinstance() guard, one arm of the match condition, and the no-match warning path. Integration tests cover them end-to-end but CI's default `-m "not integration"` profile doesn't see those, so the coverage gate didn't observe the gap. Refactor: extract the pure match-and-update logic from the `_on_dialog_resolved` closure inside `_run_browser_session` into a module-level pure function `_apply_dialog_resolution`. The closure stays thin — delegate, then log. Pure function is fixture-driven unit-testable without going through Playwright mocks (CLAUDE.md principle #12: test overrides are a code smell — restructure code, don't paper over with mocks). Add 12 fixture-driven test cases in tests/fixtures/test_browser.json covering every branch: - Match accept (single unresolved entry) - Match dismiss (single unresolved entry) - Skip already-resolved, pick unresolved LIFO - Match by message when multiple unresolved - Missing 'action' key defaults to 'unknown' - No match (different message) returns None - Empty dialogs list returns None - Type mismatch returns None - All-already-resolved returns None - Non-dict outcome (string) returns None - Non-dict outcome (None) returns None - Non-dict outcome (list) returns None Each case asserts the return value AND the in-place mutation (or non-mutation) of the dialogs list. `expect_updated_index` pins which entry got updated for multi-entry cases. Full suite: 2014 passed, 26 deselected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ction
Add a third header-classification bucket `headers.scheme_redact` alongside
`full_redact` and `cookie_redact`. RFC 7235 `Scheme credentials` headers are
recognized by scheme token (Basic, Bearer, Digest, NTLM, Negotiate, OAuth) —
the scheme is preserved, only the credential after the first whitespace is
tag-redacted (`Authorization: Bearer AUTH_xxxxxxxx`). Unknown schemes or
values with no whitespace fall through to full redaction so non-standard
leading tokens can't escape.
Restores the ability of intake pipelines (e.g. cable_modem_monitor's
analyze_har) to classify auth strategy from a single authenticated request,
without needing a 401 + WWW-Authenticate exchange that often doesn't appear
when the browser sends cached credentials from request 1.
Also adds `AUTH_[a-f0-9]{8}` to allowlist.json `redaction_patterns` so
pre-commit validation's `is_redacted` matches the scheme-preserved form
(`Bearer AUTH_xxx`) via `re.search`.
Specs reconciled: SANITIZATION_SPEC, PATTERN_SPEC, VALIDATION_SPEC, patterns
README. CHANGELOG entry added under Unreleased.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Enumerates every public sanitization entry point x every reachable detection site as a parametrized test matrix and asserts custom_patterns takes effect at each pair. 30 rows: 4 sanitize_post_data body cases, 1 sanitize_html inline-script case, 8 sanitize_entry cases, 8 sanitize_har cases, 8 sanitize_har_file cases (tmp_path-bound), plus 1 control test proving the SENSITIVE marker is NOT redacted without custom_patterns (guards against built-in patterns coincidentally catching the marker and making every row pass falsely). Background: 0.7.0 shipped a ContextVar-scoped custom_patterns override that entered the scope only at two leaf entry points. Three detection sites (sanitize_header_value, structured queryString params, URL query params) ran from wrapper entry points BEFORE the leaves were called, so custom_patterns silently no-op'd when callers used sanitize_entry / sanitize_har / sanitize_har_file. 0.7.1 closed the specific gap. This file is the executable form of the coverage claim "every public entry point honors custom_patterns at every reachable detection site." Adding a new detection site in source requires adding a matching row here; adding a new public entry point likewise. A missing row is a coverage claim without evidence — the exact failure mode that shipped in 0.7.0. No production code change; quality / regression-prevention only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bundles the v0.9.1 release content: the Authorization-scheme preservation feature (already cherry-picked), the custom_patterns coverage audit (already cherry-picked), the dialog integration tests (already on this branch from PR #52 follow-up), plus the doc-system audit and lint hardening work this commit adds. Doc-system router restructure - CLAUDE.md slimmed to disciplines + Where Things Live routing table - New docs/CODE_REVIEW.md houses code-quality and test-file standards - docs/ARCHITECTURE.md gains Code Organization section (SoC, DRY, no-CLI-dep, additive-only) - docs/RELEASE.md gains Version Numbering (pre-1.0 bump policy + CHANGELOG-section tiebreaker) and Branching and Merging sections - New ADR-11 in docs/ARCHITECTURE_DECISIONS.md records the rationale Cross-reference migration - 10 code/test/script comments that cited numbered CLAUDE.md principles now point at the authoritative doc and section instead - scripts/release.py rule-3 reference corrected (DRY was rule 2) - Historical CHANGELOG entries untouched Lint adoption - New .markdownlint.jsonc / .json / -cli2.jsonc — every customization verified by isolation-test, only MD013 customized (line-length enforced at 120 with table/code exemptions documented in config) - markdownlint-cli2 v0.22.1 added as pre-commit hook - mdformat hook now passes --wrap 120 and includes mdformat-frontmatter plugin (required so .github/ISSUE_TEMPLATE/*.md frontmatter stops being collapsed to horizontal-rule underscores) - Full doc tree reflowed to 120-char lines (~2700 mechanical diff lines) - Surfaced and fixed: 3 bare-URL violations, 2 trailing-colon headings, 1 missing-H1 in PR template, 1 detect-secrets pragma separated from its target line by the reflow Release-flow fixes - .github/workflows/release.yml awk regex extracted empty release notes for every prior release (single-range pattern where both endpoints matched the same line). Replaced with flag-toggle pattern; verified against the 0.9.1 CHANGELOG content - .github/ISSUE_TEMPLATE/bug_report.md and feature_request.md restored to proper YAML frontmatter format Verification - 2064 tests passing, coverage 94.34% - All pre-commit hooks green - markdownlint 0 errors across 24 doc files - Fresh-context subagent smoke test on three trick questions (version bump, PR consolidation, coverage threshold) — all answered correctly from docs alone Version bump - pyproject.toml + src/har_capture/__init__.py: 0.9.0 -> 0.9.1 - CHANGELOG.md dated 2026-05-13 with comparison link Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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 scope: v0.9.1
Bundles four streams of work into a single patch release. CHANGELOG entries have the full details — this PR description is a tour for reviewers.
1. Authorization scheme preservation —
feat(sanitization):Authorizationheader redaction now preserves the RFC 7235 scheme token (Basic,Bearer,Digest,NTLM,Negotiate,OAuth) and only redacts the credential after the first whitespace:Authorization: Bearer AUTH_xxxxx. Unknown schemes fall through to full redaction so non-standard leading tokens can't escape. Implemented as a third header-classification bucket (headers.scheme_redact). Restores the ability of downstream pipelines (e.g.cable_modem_monitor'sanalyze_har) to classify auth strategy from a single authenticated request.2. Dialog observability integration tests —
test(capture):Closes the test-coverage gap acknowledged when v0.9.0 shipped: the dialog observability code (PR #52, closes #46) had unit tests but was never verified against a real browser. Adds 8 integration tests that drive the production JS init script +
page.expose_functionbridge through a real Playwright headless Chromium session and assert the cross-context callback round-trip works. Tests import the production strings directly so any future drift in either side fails the suite.test_alert_records_acceptalert()has only an accept path; bridge recordsaction=accepttest_confirm_accept_records_acceptconfirm()recordsaction=accepttest_confirm_dismiss_records_dismissconfirm()recordsaction=dismisstest_prompt_accept_with_value_records_acceptprompt()with value recordsaction=accepttest_prompt_dismiss_records_dismissprompt()recordsaction=dismisstest_multiple_dialogs_in_sequence_all_recordedtest_duplicate_messages_each_recorded_separatelyconfirm()calls with identical message produce two distinct resolutions (regression guard)test_production_dialog_handlers_round_trip_end_to_endresolved_by="browser_ui"+action=acceptrecordMarked
@pytest.mark.integration+@skip_no_browserso the tests only run withpytest -m integrationagainst an installed chromium.3. Doc-system router restructure + lint adoption
CLAUDE.md becomes a thin router with a "Where Things Live" routing table; architecture / code-quality / testing / release principles move to their authoritative homes:
docs/CODE_REVIEW.mdhouses code-quality and test-file standards plus a concrete Quality Gates table.docs/ARCHITECTURE.mdgains a Code Organization section (SoC, DRY, no-CLI-dep, additive-only).docs/RELEASE.mdgains a Version Numbering policy (pre-1.0 bump rules + CHANGELOG-section tiebreaker) and a Branching and Merging section (one PR per release, consolidate before pushing, cherry-pick vs rebase).ADR-11indocs/ARCHITECTURE_DECISIONS.mdrecords the rationale.Markdownlint adopted alongside the existing mdformat hook:
.markdownlint.jsonc/.markdownlint.json/.markdownlint-cli2.jsonc— every customization verified by isolation-testing, onlyMD013customized (line-length 120 with table/code exemptions documented in the config).markdownlint-cli2 v0.22.1added to pre-commit.mdformathook now uses--wrap 120+ themdformat-frontmatterplugin so YAML frontmatter in issue templates stops being collapsed to horizontal rules.Release-flow hardening:
.github/workflows/release.ymlawk regex was extracting empty release notes for every prior release. Replaced with flag-toggle pattern; verified against the 0.9.1 CHANGELOG content..github/ISSUE_TEMPLATE/bug_report.mdandfeature_request.mdrestored to functioning YAML frontmatter.scripts/release.pyrule-3 reference corrected.4.
custom_patternscross-cutting coverage audit —test(sanitization):New 387-line parametrized matrix asserting
custom_patternstakes effect at every public sanitization entry point × every reachable detection site. Executable form of the coverage claim aroundcustom_patterns.Verification
-m "not integration"): 2064 passed, coverage 94.34% (gate 90%)markdownlint-cli2, mdformat with--wrap 120,mdformat-frontmatter,detect-secrets)scripts/release.py 0.9.1 --dry-runpre-flight validates (the on-mainpart of the gate runs post-merge)Version bump
pyproject.tomlandsrc/har_capture/__init__.pybumped 0.9.0 → 0.9.1.CHANGELOG.mddated 2026-05-13 with comparison link.🤖 Generated with Claude Code