Repository navigation
Guard the provider seam the way pan_mail_pro guards its contract - #12
Merged
Merged
Conversation
The MailProvider protocol is structural: a backend missing a method fails at the first call, at runtime, in a user's session — never at import, and never in CI. pan_mail_pro solved the same problem for its mail.provider.client with a registry plus a contract test; this ports that shape. - providers/factory.py now builds from MAIL_PROVIDER_REGISTRY (one lazily-loaded entry per backend, the shape of PROVIDER_CLIENTS) instead of an if-branch per provider. - tests/test_provider_contract.py pins the seam: the registry and config.SUPPORTED_MAIL_PROVIDERS name the same backends, every registered backend implements the whole protocol, an unknown provider fails naming the supported set — and the tool layer contains no reference to a concrete client, which until now was only a convention in CLAUDE.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01St97qp2vqVGNN8piXgopG2
Merged
12 of 13 tasks
rutgerhofste
marked this pull request as ready for review
August 18, 2026 14:18
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.
Part of a two-repo alignment with
pantalytics/pan_mail_pro(see its sibling PR). Both codebases have the same architecture — provider-agnostic tools/callers over a mail-provider contract with swappable backends — and each had proven practices the other lacked. This PR ports pan_mail_pro's seam-guarding to Squirrel; the sibling PR ports Squirrel's SMTP/IMAP hardening the other way.What changed
providers/factory.pybuilds from a registry.MAIL_PROVIDER_REGISTRYmaps each provider name to a lazy loader — the same shape as pan_mail_pro'sPROVIDER_CLIENTS. Adding Gmail/Outlook later is one entry plus a subpackage, instead of anotherifbranch. Behaviour is unchanged; the unknown-provider error still names the supported set.tests/test_provider_contract.pypins the seam (the counterpart of pan_mail_pro's file of the same name):config.SUPPORTED_MAIL_PROVIDERSname the same backends — two lists, one meaning, held equal mechanically;MailProviderprotocol. The protocol is structural (typing.Protocol), so a missing method otherwise fails at the first call, at runtime, in a user's session — this moves that failure tomake test;soverin,imap_tools,imaplib,smtplib,caldav). Until now that was a convention in CLAUDE.md; pan_mail_pro greps the same boundary in CI, because a convention nobody can check is a convention that is already broken somewhere.Testing
make lint(ruff + ty) and the full unit suite pass: 226 passed, 19 integration tests deselected.🤖 Generated with Claude Code
https://claude.ai/code/session_01St97qp2vqVGNN8piXgopG2
Generated by Claude Code