Skip to main content

Anti-Patterns from Legacy Systems

Purpose: This document catalogs critical mistakes from legacy systems that Framework M must not repeat.

Structure:

  • Tackled = Already designed into Framework M (kept for reference)
  • ⚠️ Remaining = Still needs explicit implementation

✅ TACKLED ISSUES

These issues have design decisions in place. Listed for reference only.

#IssueSolutionWhere
1name as Primary Keyid (UUID) as PK, name as unique indexPhase 01, 02
2Global State (frappe.session.user)Explicit user_context parameterPhase 02
3Metadata in DatabaseCode-first Pydantic modelsPhase 01, 02
4Synchronous/BlockingAsync native (Litestar + SQLAlchemy Async)Phase 01
5Monkey PatchingEntrypoint-based overridesPhase 01
6No Dependency Injectiondependency-injector libraryPhase 01
7Weak/No Type Hints100% type hints, mypy --strictPhase 01
8Database-Specific FeaturesPortable SQLAlchemy types onlyPhase 02
9Implicit TransactionsExplicit transaction context managersPhase 02
10No Event Sourcing / Audit TrailEvery state change emits eventPhase 02, 04
11Hard-coded HooksEvent bus with multiple subscribersPhase 04
12Permission Checks in Business LogicRepository-level enforcementPhase 03
13Session-Only AuthStateless JWT/header-based authPhase 03
14eval()/exec() in User InputJMESPath/SimpleEval onlyPhase 10
15Hard Delete OnlySoft delete with deleted_atPhase 02
16Opt-out API ExposureOpt-in api_resource = TruePhase 03
17Timezone-Naive DatetimesDateTime(timezone=True) in SchemaMapperPhase 02
18N+1 Query Problemload_children_for_parents() (select_in_loading) in GenericRepositoryPhase 02, 10
19Unbounded QueriesDEFAULT_LIMIT=20, MAX_LIMIT=1000 enforcedPhase 02
22Unrestricted File UploadsFile DocType with extension whitelist, MIME validationPhase 06
25No Circuit Breaker (Email)EmailQueue with async processing, not blockingPhase 06
26No API VersioningURL-based versioning /api/v1/ prefixPhase 03
29Health Check Endpoints Missing/studio/api/health endpoint implementedPhase 07
30Caching Layer MissingRedisCacheAdapter + GenericRepository integrationPhase 02, 04
32Over-Customization Upgrade TrapOverride mechanism + event-based extensionPhase 08
33Missing/Manual Database IndexesAutomatic indexing of modified and Foreign KeysPhase 10
23Missing Request ID TracingRequest context middleware injects request_id into structured logsPhase 10
31MariaDB-Specific IssuesDB-agnostic SQLAlchemy + connection pooling defaults (20/10/30/3600, pool_pre_ping)Phase 02, 10
34Post-Submission Editing (allow_on_submit)Strict immutability for SUBMITTED docs via controller validation (ImmutableDocumentError)Phase 02
27Unsafe DeserializationProhibit pickle/yaml.load via Bandit (B301/B506) and 100% JSON-first logic.Phase ALL
28Missing CSRF ProtectionPluggable CSRFProtocol with Origin-header validation for all mutation methods.Phase 11
20Missing Rate LimitingIdentity-aware middleware with fallback to IP, and granular @rate_limit decorators.Phase 03
21Secrets in LogsPluggable ScrubbingLogic with case-insensitive redaction and Pydantic introspection.Phase 10
35Raw print() StatementsGoverned output via CLIConsole (Human) and logging/structlog/LoggingProtocol.Phase 10
24No Idempotency Keys for MutationsPluggable IdempotencyProtocol via middleware with Redis/DB locking and response caching.Phase 03

Checklist for Every Feature

Before implementing any feature, verify:

  • Datetimes are timezone-aware (UTC)?
  • Queries are paginated with max limit?
  • No N+1 queries (use eager loading)?
  • Rate limiting applied (if user-facing)?
  • Secrets redacted from logs?
  • No raw print() statements (use CLIConsole or module-level logs)?
  • File uploads validated (extension + magic bytes)?
  • Request ID propagated through logs?
  • No pickle/unsafe YAML?
  • CSRF protection on mutations?
  • Circuit breaker on external calls?

Checklist for Frontend / UI Features

To maintain cross-platform compatibility and React Native support, all UI code must follow these principles:

  • No Web-Exclusive DOM Primitives: Never use raw HTML tags like <div>, <span>, <button>, <input>, <form>, or <select>.
  • Leverage @framework-m/ui Components: Always wrap layouts in Tamagui equivalents such as XStack, YStack, Paragraph, Button, Input, and Select.
  • Eliminate Form Layouts: Avoid traditional <form> logic; implement state-driven hooks instead.