fix(decoders): guard pydantic import so the module loads without the extra#62
Merged
Conversation
Full-codebase audit spec covering the dimensions the 2026-06-07 deep audit left uncovered (performance, security, supply-chain) plus correctness, concurrency, refactoring, and test quality. Report-only, run via a refreshed multi-agent Workflow orchestrator. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Executor checklist: build workflow-deep.mjs (refreshed paths/models, 3 new finders, architecture_docs, refuted-candidate retention), run the combined Workflow, validate the report and reproduce the headline finding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Forks workflow.mjs into workflow-deep.mjs: refreshed model IDs, paths repointed to architecture/ + planning/changes, three new finders (performance, security, refactoring), architecture_docs replaces the docs/planning_docs finders, and refuted candidates are kept for a Negative-results section in a single combined-run report. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…, 1 high, 4 medium, 14 low, 14 nits) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Report-only sweep covering perf/security/supply-chain (the 2026-06-07 gaps) plus correctness, concurrency, refactoring, test quality. 35 confirmed findings (1 High, 4 Medium, 14 Low, 14 nits); no source changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…extra decoders/pydantic.py imported `from pydantic import TypeAdapter` unconditionally at module top, so `import httpware.decoders.pydantic` raised a bare ModuleNotFoundError when the extra was absent — before the friendly ImportError guard in PydanticDecoder.__init__ could run. Mirror the msgspec pattern: import import_checker first, guard the hard import behind is_pydantic_installed, and quote the one class annotation that references TypeAdapter. Runtime TypeAdapter uses are only reachable with pydantic installed, so they're unchanged. This makes the Seam-C isolation invariant in architecture/extras.md true for pydantic (the grep self-check now returns one indented line, matching the doc); no doc edit needed. Resolves the 2026-06-14 deep-audit High finding and the two folded Medium findings sharing its root cause. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lesnik512
added a commit
that referenced
this pull request
Jun 14, 2026
Promote 2026-06-14.02-pydantic-import-isolation (#62) and 2026-06-14.03-security-hardening (#63) to changes/archive/ with status: shipped, pr, and outcome filled; move their Index lines from Active to Archived. The deep-audit umbrella bundle stays active (still spawning remediation). Co-Authored-By: Claude Opus 4.8 (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.
Summary
Resolves the High finding (and the two folded Medium findings sharing its root cause) from the 2026-06-14 deep audit.
decoders/pydantic.pyimportedfrom pydantic import TypeAdapterunconditionally at module top, soimport httpware.decoders.pydanticraised a bareModuleNotFoundErrorwhen the extra was absent — before the friendlyImportErrorguard inPydanticDecoder.__init__could ever run. Only the msgspec sibling matched the documented Seam-C isolation pattern.This PR mirrors the canonical
decoders/msgspec.pypattern:import_checkerfirst, then guardfrom pydantic import TypeAdapterbehindif import_checker.is_pydantic_installed:_adapters) that referencesTypeAdapteras a forward-ref, so the class body doesn't evaluate the name at definition time when the extra is absentTypeAdapteruses (inside methods) are only reachable with pydantic installed, so they're unchangedThe module now imports cleanly without the extra and the friendly
ImportErroris the real fail-fast path. This also makes the Seam-C invariant inarchitecture/extras.mdtrue for pydantic — the documented grep self-check now returns exactly one indented line — so no doc edit is needed (the code was wrong, not the doc).Change bundle:
planning/changes/active/2026-06-14.02-pydantic-import-isolation/change.md.Test Plan
test_pydantic_decoder_module_imports_when_pydantic_absent) simulates true pydantic absence viasys.modules['pydantic'] = None; it failed for the right reason (ModuleNotFoundErrorat module load) before the fix and passes after.grep -rnE 'from pydantic|import pydantic' src/httpware/ | grep -v import_checkerreturns exactly one indented line.just test— 570 passed, 100% coverage.just lint— ruff + ty clean.🤖 Generated with Claude Code