station · ivanmisic.net log in
§02 generic-rules ↵ back to rules
Mine Rules

generic-rules

A stack-agnostic .claude/rules baseline: security, code quality, architecture discipline, and a token-first CSS rule, ready to drop into any project.

The rules I want Claude to follow on every project, regardless of language. Four files that carry the discipline without any project's specifics baked in.

What's inside

  • security-discipline.md (always on): input validation, injection, output escaping, least-privilege access, secrets, timing-safe comparison, TOCTOU. Language-neutral; the language pack names the exact calls.
  • code-quality.md (always on): single responsibility, DRY without over-abstraction, minimum code, replace-don't-append, complexity thresholds, measure-before-optimize.
  • architecture.md (always on): layered separation (transport, logic, persistence), clear boundaries, fail-fast, the add-a-feature checklist.
  • css-discipline.md (loads on *.css): token-first, search-before-adding, no hardcoded colors, no inline styles, focus and reduced-motion.

How to use

Download the pack and drop the .md files into your project's .claude/rules/. Files with no paths: front matter load on every turn; css-discipline.md scopes itself to stylesheets. Layer a language pack (PHP, Python) on top for the stack-specific enforcement.

Want these tuned to your actual codebase instead of generic? Run /a-rules-optimizer from the dev-workflow-forge plugin: it reads your repo and rewrites the rules around your real conventions.

What's in the bundle 4 files
architecture.md 1.6 KB
# Architecture Discipline

Always-on. A pattern, not a framework. Adapt the names to your stack; keep the separation.

## Layered Separation
- Keep transport concerns, business logic, and persistence in separate layers. A request handler that also runs business rules and writes to the database is three responsibilities in one place.
- A common shape: Handler (transport) to Service (business logic) to Model or Repository (persistence). Handlers translate requests and responses; services own the rules and the mutations; models own data access.
- Mutations go through the logic layer. Reads may skip it. Don't put validation, business rules, or cache invalidation in the transport layer.

## Boundaries and Interfaces
- Each unit has one clear responsibility, a well-defined interface, and can be understood without reading its internals.
- If you can't change a unit's internals without breaking its callers, the boundary is wrong.
- Trace the data flow before writing code: know where input enters and where output goes.

## Failure Handling
- Fail explicitly with context. No silent exception swallowing.
- Validate early, fail fast: check preconditions at the entry of a function, not deep inside it.
- The user-facing message stays friendly; the log carries the full detail. Never leak internals to the user.

## Adding a Feature (checklist shape)
- Persistence change first (a migration if the schema moves), then the model, then the service, then the handler, then the view. Wire feature flags and navigation last.
- Keep files that change together close together. Split by responsibility, not by technical layer.
code-quality.md 1.8 KB
# Code Quality

Always-on baseline for keeping a codebase legible and small.

## Single Responsibility
- One function, one job. If a function needs a paragraph to explain, split it.
- Side effects at the edges, pure logic in the middle. Isolate I/O from decisions so the decisions are testable.
- Composition over inheritance.

## DRY, But Not Too Dry
- Don't repeat yourself. Two copies is fine; three means extract.
- Don't over-abstract. No flexibility or configurability nobody asked for. No abstraction for a single call site.

## Minimum Code
- Write the least code that solves the problem. No features beyond what was asked.
- No error handling for impossible states. Handle what can actually happen.
- Senior-engineer test: could 200 lines be 50? If yes, rewrite before shipping.

## Replace, Don't Append
- No `v2`, `_new`, `_final`, or `_improved` copies. Update the original and delete what you replace.
- Remove imports and variables your change orphaned. Flag pre-existing dead code; don't silently delete it.

## Complexity Signals (refactor triggers)
- Files over ~500 lines and functions over ~30 lines are review hot spots. New code in an already-large file should shrink it, not grow it.
- Nesting deeper than 4 levels, or more than 4 parameters, is a signal to extract a value object or split the function.

## Comments
- Comment the why, not the what. The code already says what it does.
- Follow the established patterns in the file you're editing. Match its style even if you'd do it differently.

## Performance (measure first)
- Profile before optimizing. Don't guess at bottlenecks.
- Watch for N+1: never issue a query inside a loop. Batch-load before the loop.
- Index the columns you filter, join, and order by.
- Cache expensive work with real invalidation. A stale cache is worse than no cache.
- Lazy-load. Don't fetch data you won't use.
css-discipline.md 1.8 KB
---
paths:
  - "**/*.css"
  - "**/*.scss"
---

# CSS Discipline

Loads when you touch a stylesheet. This is method, not a design system: it assumes your project has design tokens and components, and keeps you using them instead of hardcoding around them. Read "tokens" as whatever your project calls its variables.

## Before Adding Any CSS
1. Search your token or variable file. Does a variable already exist for this color, space, or size?
2. Search your component styles. Does a similar component already exist? Most styling should already live there.
3. Search your utilities. Is there a utility class for this?

If yes to any: use the existing code. Don't recreate it. Duplicate components are the most common source of CSS drift.

## Token Values Only
- Use your design tokens and variables, never hardcoded colors, spacing, or sizes. A raw hex or px value in a component is the tell that a token was skipped.
- One intentional scale. Don't invent one-off values that sit between two existing steps.

## Composition First
- Compose existing primitives and utilities before writing a new class.
- Only add a new class after searching all existing files and finding nothing. Put it in the right component file and give it hover and focus states.

## Anti-Patterns
- No duplicate components. Search first, always.
- No hardcoded colors or spacing. Use variables.
- No inline `style="..."` for color, spacing, or sizing. Use classes. (Runtime custom-property bridges for per-request computed values are the one exception.)
- No `-v2` or `-new` classes. Update the existing class, or discuss first.
- No inline event handlers in markup. Bind in a script.

## States and Motion
- Every interactive element gets a visible `:focus-visible` state.
- Respect `prefers-reduced-motion`: gate or zero out transitions for users who ask for less motion.
security-discipline.md 3.2 KB
# Security Discipline

Always-on baseline, language-neutral. The stack-specific enforcement (which escape helper, which hashing call) lives in the language pack that layers on top. This file is the discipline every project owes regardless of stack.

## Input Validation
- Validate and sanitize all input at system boundaries: request handlers, API endpoints, CLI args, queue consumers, webhook receivers.
- Whitelist, don't blacklist. Reject unknown values rather than trying to strip bad ones.
- Enforce length limits, type checks, and range bounds on every field.
- Only allow `http://` and `https://` for user-supplied URLs. Reject other schemes (`javascript:`, `file:`, `data:`).
- Cap array and batch sizes on ingest endpoints (for example, max 200 items) so one request can't exhaust memory.
- Bound date and time inputs to a sane range instead of trusting the parser.

## Injection
- Parameterized queries only. Never concatenate user input into SQL, shell commands, or any interpreter string.
- Context-appropriate escaping on output: HTML, SQL, shell, JSON, and URL each need their own escaping, applied at the boundary where the value leaves your control.

## Output Escaping (XSS)
- Escape every dynamic value before it lands in HTML. Treat all external data (DB rows, API responses, feed titles) as untrusted.
- Validate a URL's scheme before emitting it in an `href` or `src` attribute.
- When building HTML from data that arrived over the wire, prefer text nodes and safe builders over raw string interpolation.

## Access Control
- Least privilege by default: file permissions, DB users, API scopes, tokens.
- Return 404, not 403, for a resource a user isn't allowed to see. Don't confirm its existence.
- Enforce authorization on the server for every state-changing request. Never rely on a hidden UI control as the gate.
- CSRF protection on all state-changing requests.

## Secrets
- No secrets in source. Use environment variables or config files outside the web root.
- Never log secrets, tokens, passwords, or full external responses. Truncate and redact before logging.

## Credentials and Comparison
- Store passwords only as a slow salted hash (bcrypt, argon2, scrypt). Never md5, sha1, or plaintext.
- Compare secrets, tokens, signatures, and CSRF or OAuth values in constant time. A plain `==` on a secret is a timing oracle.

## Time-of-Check to Time-of-Use
- Don't check-then-act on shared state ("file exists? then open"). Operate directly and handle the error; the gap between check and act is a race.
- Writes to shared files or state need a lock or an atomic operation. A partial write under concurrency is a corruption bug.

## Dangerous Constructs
- Avoid dynamic code execution and unsafe deserialization on any value that could be attacker-influenced. Eval, template-from-input, and object deserializers are remote-code-execution surfaces.

## Outbound HTTP
- Verify TLS on outbound calls. Don't disable certificate checks to make something work.
- Set a timeout on every external call. A hung dependency shouldn't hang your process.
- Validate the destination of any request whose URL came from user input: allowlist schemes and hosts. `python-rules/python-security.md` has a worked SSRF section if you run that pack.

Everything mine on this shelf comes from my own working setup, shared for learning. Test it and adapt it to your project before relying on it; you run it at your own risk.