# Anti-Patterns > A catalog of violations. Each entry names the principle it breaches. Use this to recognize and reject patterns on sight. ## How to Use When you see a pattern listed here, it is a defect. Cite the principle it violates and require a fix. These are not "to be reviewed later"; they are rejected on sight. ## Core Anti-Patterns (C1–C8) | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Code that "mostly works" | C1 Correctness | Mostly correct is incorrect | | `function doStuff()` | C2 Clarity | Name reveals nothing | | A 500-line function | C3 Simplicity | Complexity is a liability | | Config in a distant repo, read silently | C4 Locality | Coupling you cannot see | | A migration with no `down` | C5 Reversibility | Irreversible bet | | A component reading global state implicitly | C6 Composability | Hidden dependency | | A service with no logs | C7 Observability | Cannot debug what you cannot see | | Loading all records into memory | C8 Economy | Unbounded = OOM | ## Domain Anti-Patterns ### UI/UX | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Image without `alt` | P2 Accessibility | Disqualifying | | "Delete" with no confirmation | P5 Forgiveness | Irreversible surprise | | `color: #3b82f6` in a component | P8 Consistency (via tokens) | Bypasses design system | | "Submit" on a delete button | P3 Clarity | Wrong verb | | Layout shift on image load | P7 Hierarchy / CLS | Visual instability | ### API | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | `/getUsers` (verb in URL) | P2 Clarity | Resources are nouns | | 200 with an error body | P9 Error Transparency | Status code lies | | 500 with a stack trace | P8 Security, P9 | Information leak | | No `Idempotency-Key` on a POST | P6 Idempotency | Retry is unsafe | | 10MB response by default | P7 Performance | Unbounded payload | ### Security | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | `eval()` of any string | P4, P5 | Code injection | | Hardcoded API key in source | P9 Secret Hygiene | Committed secret | | `catch (e) {}` (swallow) | P7, P8 | Silent failure, fail-open | | `md5` for password hashing | P6 Crypto | Broken primitive | | Open CORS `*` in production | P1, P10 | Zero trust violated | | `chmod 777` | P2 Least Privilege | Maximum privilege | | Logging the request body | P9 Secret Hygiene | Token leak | ### Data | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | `VARCHAR` for a UUID | P7 Type Fidelity | Wrong type | | No FOREIGN KEY | P3, P9 | Unenforced relationship | | `FLOAT` for money | P7, P1 | Floating point error | | `is_deleted` without filtering | P8 Lifecycle | Soft-delete leak | | `SELECT *` | P10 Performance | Unbounded columns | ### Testing | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Test that cannot fail | P10 No Test Theater | Not a test | | `Date.now()` in a fixture | P3 Determinism | Flaky | | Shared fixture mutated across tests | P2 Independence | Order-dependent | | 500 e2e tests, 50 unit | P4 Fast Feedback | Inverted pyramid | | `name: "test"` fixture | P7 Realism | Hides bugs | ### Performance | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | N+1 query in a loop | P3 Complexity | O(N) queries | | No timeout on HTTP call | P4, P8 (concurrency) | Hang forever | | Cache with no invalidation | P5 Caching | Stale forever | | Unbounded in-memory sort | P4 Resource Bounds | OOM | | Optimization without measurement | P1 Measure First | Guesswork | ### Observability | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | `console.log("here")` | P1 Structured | Not queryable | | `user_id` as a metric label | P4 Cardinality | Unbounded bill | | Average latency only | P8 SLO | Hides the tail | | No `trace_id` propagation | P2 Correlation | Cannot trace | | Logs without `request_id` | P3 Context | No correlation | ### Errors | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | `catch (e) { return null }` | P2 Fail Loudly | Silent failure | | `throw new Error("error")` | P3 Fail Specifically | Generic | | `return null` for "not found" | P1 Errors are Data | Conflates absence with error | | Retry without backoff | P5, P8 | Retry storm | | `throw` in a recovery path | P6 | Fail fast in wrong place | ### Documentation | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Doc with no examples | P3 Examples | Incomplete | | Stale doc (wrong, not updated) | P4 Currency | Worse than no doc | | Unlisted doc (not in MANIFEST) | (framework rule) | Not part of framework | | No audience statement | P2 Audience | Who is this for? | ### Concurrency | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Shared mutable state, no lock | P1 Immutability | Race condition | | Unbounded queue | P9 Bounded Queues | OOM | | `channel.send()` with no timeout | P8 Timeout | Hang | | Mutex held across I/O | P3 Lock Scope | Lock too long | | Spawned work with no cancellation | P7 Cancellation | Orphaned work | ### DevOps | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Manual deploy script | P2 Automation | Not repeatable | | No rollback path | P4 Rollback | Irreversible deploy | | Big-bang deploy | P5 Progressive | All-or-nothing | | Rebuild per environment | P7 Immutability | Different artifacts | | Snowflake server | P1, P6 | Not reproducible | ### Infrastructure as Code | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Unpinned provider (`source` without `version`) | P5 Version Everything | Unversioned drift | | `terraform apply` without a read `plan` | P4 Plan Before Apply | Unreviewed mutation | | Local state in a shared environment | P8 Remote State with Locking | No lock = corruption | | Hardcoded secret in HCL | P10 Secrets Never in Code | Committed secret | | Copy-pasted block instead of a module | P6 Modules Compose | Bug duplicated | | Manual change to a managed resource | P9 Drift is Recoverable | Unreconciled drift | | Admin credentials in CI | P7 Least Privilege Providers | Overbroad grant | | Committed `terraform.tfstate` | P3 State is Truth, P10 | Secret-bearing artifact in repo | ### Kubernetes | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Bare pod (no controller) | P2 Pods are Mortal | No recovery/scale | | No resource requests in prod | P4 Requests and Limits | BestEffort, first evicted | | Liveness probe checks a dependency | P5 Probes Drive Health | Cascade restart | | `cluster-admin` bound to a workload | P7 RBAC by Intent | Overbroad grant | | `:latest` image tag in prod | P5 Version Everything | Unversioned drift | | `emptyDir` for data that must persist | P8 Storage is Explicit | Data lost on pod death | | Secrets baked into the image | P9 Config and Secrets Separate | No rotation without rebuild | | `default` namespace in prod | P6 Namespaces Bound Blast Radius | No blast boundary | | Shared PVC across StatefulSet replicas | P8 Storage is Explicit | Concurrent write corruption | | `Delete` reclaim policy on prod storage | P8, P5 Reversibility | PVC delete = data delete | ## Cross-Cutting Anti-Patterns | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | "I'll add tests later" | C1 (no proof of correctness) | Later never comes | | "It's just a prototype" | C5 (irreversible by default) | Prototypes go to prod | | Copy-paste code | C6 (no composition) | Bug duplicated | | God object | C3, C6 | One thing, many things | | Leaky abstraction | C6, C2 | Hidden coupling | ## v0.2 Chaos Anti-Patterns (from IDEATE-13, IDEATE-14) | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Orphaned P-rule (a domain principle with no matrix row) | matrix completeness, C6 | Breaks the conflict-resolution arbiter; the rule has no core trace | | Deployable example artifact (standalone `.tf`/`.yaml` under `examples/`) | PROJECT.md "no runtime code", D-025 | Violates the docs-only contract; examples must be `.md` with fenced code | | Unlisted v0.2 doc (new doc not added to MANIFEST) | manifest rule | Not part of the framework by definition |