refactor(backend): provider-scoped rollout Wave 1 (balance, line directory, diagnostics)#28
Merged
Merged
Conversation
Plan completing the provider-scoped layering conversion the CDR vertical started (the standard is already reconciled; only CDR's code was migrated). Phased easy→hard across the six remaining pairs; snapshot stays exempt. - requirements.md: interim-state inventory + success criteria - plan.md: conversion recipe, wave sequencing, write/command pattern, risks - spec.md: Wave 1 (balance, voipms_account→rename, diagnostics) — read-only verticals; designs the write/command pattern (first implemented in Wave 2). Passed Architect+QA persona review and the pre-implementation standards gate. Personas: Architect, QA. GLaDOS plan-feature + spec-feature trace in README.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ctory, diagnostics) Complete the provider-scoped layering for the three read-only pairs, per specs/2026-06-29_feature_providerScopedRollout/spec.md. Behavior-preserving. - protocols.py: add ProviderLookupError(kind) + classify_provider_error(); CallLookupError now subclasses it. Add BalanceRepository, LineDirectoryRepository, DiagnosticsRepository ABCs. - balance: VoipMsBalanceRepository owns the client and translates errors; BalanceService depends on the ABC; router maps ProviderLookupError. - line directory: rename the provider-named AccountService (services/ voipms_account.py) to LineDirectoryService + VoipMsLineDirectoryRepository, resolving the AccountService name collision with the DB account service. Rewire the parental-controls router. - diagnostics: repository owns did→sub resolution, the 4-call gather with graceful degradation, and tc re-evaluation, returning a new LineDiagnostics domain model; translation is pure module functions. DB parental-controls summary translation stays service-side (DB models + line timezone). Router drops the unreachable provider except clauses (service degrades, never raises). - standard: add "Repository writes / commands" subsection; trim migration note. Services are provider-free (leak gate clean). Full suite 689 passed; ruff check + format clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address PR #28 review nit #1: TestFetchLineDiagnostics only asserted degradation for the registration sub-call. Add the cases that moved out of the old service tests when orchestration relocated to the repository: sub-account-fail → None, did-routing-fail → None, servers-info-fail → empty POP map (IDs unresolved), and all-four-fail → fully degraded. None raise. Also record the two non-blocking review follow-ups (dedupe CDR error classification onto classify_provider_error; diagnostics-route defense-in-depth) in the rollout trace for a later wave. 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.
What
Wave 1 of completing the provider-scoped repository conversion that the CDR vertical (PR #27) started. Converts the three read-only service/repository pairs to the provider-scoped layering: repositories own their client and translate provider shapes → HowdyBox domain models behind a HowdyBox-owned ABC; services depend only on the ABC and contain no provider knowledge.
Behavior-preserving — no
/api/*contract, response-schema, or DB changes.Plan/spec:
specs/2026-06-29_feature_providerScopedRollout/(plan.md,spec.md; passed Architect+QA persona review and the pre-implementation standards gate).Pairs converted
VoipMsBalanceRepositoryowns the client + translates provider failures toProviderLookupError;BalanceServicedepends on the ABC; router maps the domain error.AccountService(services/voipms_account.py) →LineDirectoryService+VoipMsLineDirectoryRepository. Resolves theAccountServicename collision with the DB account service. Rewires the parental-controls router.VoipMsDiagnosticsRepositoryowns did→sub resolution, the 4-call gather with graceful degradation, and the time-condition re-evaluation, returning a newLineDiagnosticsdomain model. DB-sourced parental-controls summary + timezone logic stays service-side.Also
protocols.py: sharedProviderLookupError(kind)+classify_provider_error();CallLookupErrornow subclasses it (CDR untouched). NewBalanceRepository,LineDirectoryRepository,DiagnosticsRepositoryABCs.backend-layered-architecture.mdgains a Repository writes / commands subsection (designed here, first implemented in Wave 2); migration note trimmed.Judgment calls
build_pop_map) rather than private methods — keeps the granular translation unit tests as plain function calls.Verification
VoipMs|timezone=|client.in the three services) is clean.ruff check+ruff format --checkclean.Next
Wave 2 = remediation (first real write command, exercising the new command pattern), then Wave 3 = parental_controls + wizard. Snapshot stays exempt.
🤖 Generated with Claude Code