Skip to content

fix(decoders): guard pydantic import so the module loads without the extra#62

Merged
lesnik512 merged 7 commits into
mainfrom
fix/pydantic-import-isolation
Jun 14, 2026
Merged

fix(decoders): guard pydantic import so the module loads without the extra#62
lesnik512 merged 7 commits into
mainfrom
fix/pydantic-import-isolation

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Summary

Resolves the High finding (and the two folded Medium findings sharing its root cause) from the 2026-06-14 deep audit.

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 ever run. Only the msgspec sibling matched the documented Seam-C isolation pattern.

This PR mirrors the canonical decoders/msgspec.py pattern:

  • import import_checker first, then guard from pydantic import TypeAdapter behind if import_checker.is_pydantic_installed:
  • quote the one class annotation (_adapters) that references TypeAdapter as a forward-ref, so the class body doesn't evaluate the name at definition time when the extra is absent
  • runtime TypeAdapter uses (inside methods) are only reachable with pydantic installed, so they're unchanged

The module now imports cleanly without the extra and the friendly ImportError is the real fail-fast path. This also makes the Seam-C invariant in architecture/extras.md true 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

  • New fresh-subprocess regression test (test_pydantic_decoder_module_imports_when_pydantic_absent) simulates true pydantic absence via sys.modules['pydantic'] = None; it failed for the right reason (ModuleNotFoundError at module load) before the fix and passes after.
  • grep -rnE 'from pydantic|import pydantic' src/httpware/ | grep -v import_checker returns exactly one indented line.
  • just test — 570 passed, 100% coverage.
  • just lint — ruff + ty clean.

🤖 Generated with Claude Code

lesnik512 and others added 7 commits June 14, 2026 11:58
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 lesnik512 merged commit 9a4009c into main Jun 14, 2026
5 checks passed
@lesnik512 lesnik512 deleted the fix/pydantic-import-isolation branch June 14, 2026 12:21
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>
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