You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Grouped framework findings from the Oct 2026 survey:
Process-global mutable state with no reset: mail sender (core/mail.py:80-92), lease backend (core/leases.py:152), Sentry (hosting/sentry.py:166). Two create_app calls in one process (tests, embedding) share them, so the last install wins. Hang them off app.state.sm with module-level accessors, or at least a test-plugin reset.
14 except Exception sites that return/continue silently or at debug level, some on security/readiness paths: hosting/setup_gate.py:76-80, db/listeners.py:80-85, core/menu.py:127, core/_i18n_translator.py:32, core/invalidation.py:125. Write a fail-open/closed policy (WARNING + exc_info minimum; name each deliberate fail-open) and sweep.
33 getattr(app.state, "<name>", None) reads (public_routes, auth, migration, tenant_resolver, principal_serializer…): a typo or missing install silently defaults. Typed accessors in core, like get_user_directory.
Undated back-compat (CLAUDE.md forbids): ModuleBase.register_event_handlers(self, bus, app=None) "optional for back-compat" (core/module.py:78-80) and module_meta.py:53 "no compatibility check is performed (legacy modules)". Register with deprecate(remove_in=...) + test_deprecation_expiry.py, or drop.
Lazy imports to dodge cycles between setup_gate, _lifespan and _error_handlers: move run_deferred_startup and the error render helper into leaf modules.
From the Oct 2026 tech-debt survey of main@1c4270ac.
Batch-5 scope: items 1, 2, 4, 5 and 6 are being done now. Item 3 (typed app.state accessors for the ~33 getattr(app.state, ...) reads) is deferred to a follow-up because it is a broad, mostly mechanical change best done on its own.
Activity
antosubash commentedon Oct 23, 2026
Batch-5 scope: items 1, 2, 4, 5 and 6 are being done now. Item 3 (typed
app.stateaccessors for the ~33getattr(app.state, ...)reads) is deferred to a follow-up because it is a broad, mostly mechanical change best done on its own.