Skip to content

refactor(model): move OTP email rendering to campus.api (campus.model goes Flask-free at call time) - #983

Merged
ngjunsiang merged 1 commit into
weeklyfrom
refactor/emailotp-rendering
Oct 27, 2026
Merged

ngjunsiang merged 1 commit into
weeklyfrom
refactor/emailotp-rendering

Conversation

@nycomp

@nycomp nycomp commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Refators #970 (phase-3 prep — campus-model purity). Non-closing: #970 stays open as the phase tracker.

Change

campus.model.emailotp.template → campus.api.emailotp_templates (module + templates/ moved via git mv, 84%/100% renames). The emailotp route was the template's only consumer; it now imports the renderer from its own package, with module-level import flask (api is Flask territory — the #968 lazy-import arrangement is superseded, not preserved).

campus.model.emailotp keeps only the EmailOTP record; template is dropped from its namespace.

Why

campus.model must be Flask-free even at call time for the phase-3 campus-model distribution split: downstream apps install the data model without Flask-adjacent behavior. This completes what #968 started (lazy import) by relocating instead. Sister issue for the other model-purity move: #982 (webauth models remigration).

Tests

  • tests/unit/model/test_import_weight.py: keeps the flask/jinja2-free import guard; adds a gone-check for campus.model.emailotp.template (attribute-access pattern — the namespace-package trap from refactor(audit): move campus.common.http to campus.audit.http #976 applies); the render test moves out with its subject.
  • New tests/unit/api/test_emailotp_templates.py: subject/body/html_body render under an app context.
  • Boundary contract: rule 3's docstring drops the emailotp exception — no shared-layer module imports flask at all now, module level or lazy.

Docs sweep

Ran the full docs/openapi sweep for emailotp/template/model.emailotp references: every hit is feature-name prose ("Email OTP verification") or the openapi endpoint spec — zero module-path references exist in any doc, so no doc changes were needed for this move.

Verification

Unit, contract, integration, and ruff check . all green (contract's test_api_emailotp exercises the moved rendering through the route).

…lates

The emailotp route was the only consumer of
campus.model.emailotp.template, whose body()/html_body() call
flask.render_template_string. Move the rendering (module + templates)
into campus.api/emailotp_templates/ so campus.model is Flask-free even
at call time - completing what #968 started lazily, in prep for the
campus-model distribution split (#970 phase 3, see also #982 for the
webauth-models remigration).

campus.model.emailotp now holds only the EmailOTP record; the route
imports the new module from its own package. Boundary-contract docstring
drops the emailotp flask exception (rule 3 now has no exceptions), the
model import-weight test asserts the template module is gone, and
rendering coverage moves to tests/unit/api/test_emailotp_templates.py.
@ngjunsiang
ngjunsiang merged commit e1adc3a into weekly Oct 27, 2026
22 checks passed
@nycomp
nycomp deleted the refactor/emailotp-rendering branch October 27, 2026 23:51
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.

2 participants