# Pre-Landing Review Checklist ## Instructions Review the `git diff origin/main` output for the issues listed below. Be specific — cite `file:line` and suggest fixes. Skip anything that's fine. Only flag real problems. **Two-pass review:** - **Pass 1 (CRITICAL):** Run SQL & Data Safety and LLM Output Trust Boundary first. These can block `/ship`. - **Pass 2 (INFORMATIONAL):** Run all remaining categories. These are included in the PR body but do not block. **Output format:** ``` Pre-Landing Review: N issues (X critical, Y informational) **CRITICAL** (blocking /ship): - [file:line] Problem description Fix: suggested fix **Issues** (non-blocking): - [file:line] Problem description Fix: suggested fix ``` If no issues found: `Pre-Landing Review: No issues found.` Be terse. For each issue: one line describing the problem, one line with the fix. No preamble, no summaries, no "looks good overall." --- ## Review Categories ### Pass 1 — CRITICAL #### SQL & Data Safety - String interpolation in SQL (even if values are `.to_i`/`.to_f` — use `sanitize_sql_array` or Arel) - TOCTOU races: check-then-set patterns that should be atomic `WHERE` + `update_all` - `update_column`/`update_columns` bypassing validations on fields that have or should have constraints - N+1 queries: `.includes()` missing for associations used in loops/views (especially avatar, attachments) #### Race Conditions & Concurrency - Read-check-write without uniqueness constraint or `rescue RecordNotUnique; retry` (e.g., `where(hash:).first` then `save!` without handling concurrent insert) - `find_or_create_by` on columns without unique DB index — concurrent calls can create duplicates - Status transitions that don't use atomic `WHERE old_status = ? UPDATE SET new_status` — concurrent updates can skip or double-apply transitions - `html_safe` on user-controlled data (XSS) — check any `.html_safe`, `raw()`, or string interpolation into `html_safe` output #### LLM Output Trust Boundary - LLM-generated values (emails, URLs, names) written to DB or passed to mailers without format validation. Add lightweight guards (`EMAIL_REGEXP`, `URI.parse`, `.strip`) before persisting. - Structured tool output (arrays, hashes) accepted without type/shape checks before database writes. #### Enum & Value Completeness When the diff introduces a new enum value, status string, tier name, or type constant: - **Trace it through every consumer.** Read (don't just grep — READ) each file that switches on, filters by, or displays that value. If any consumer doesn't handle the new value, flag it. Common miss: adding a value to the frontend dropdown but the backend model/compute method doesn't persist it. - **Check allowlists/filter arrays.** Search for arrays or `%w[]` lists containing sibling values (e.g., if adding "revise" to tiers, find every `%w[quick lfg mega]` and verify "revise" is included where needed). - **Check `case`/`if-elsif` chains.** If existing code branches on the enum, does the new value fall through to a wrong default? To do this: use Grep to find all references to the sibling values (e.g., grep for "lfg" or "mega" to find all tier consumers). Read each match. This step requires reading code OUTSIDE the diff. ### Pass 2 — INFORMATIONAL #### Conditional Side Effects - Code paths that branch on a condition but forget to apply a side effect on one branch. Example: item promoted to verified but URL only attached when a secondary condition is true — the other branch promotes without the URL, creating an inconsistent record. - Log messages that claim an action happened but the action was conditionally skipped. The log should reflect what actually occurred. #### Magic Numbers & String Coupling - Bare numeric literals used in multiple files — should be named constants documented together - Error message strings used as query filters elsewhere (grep for the string — is anything matching on it?) #### Dead Code & Consistency - Variables assigned but never read - Version mismatch between PR title and VERSION/CHANGELOG files - CHANGELOG entries that describe changes inaccurately (e.g., "changed from X to Y" when X never existed) - Comments/docstrings that describe old behavior after the code changed #### LLM Prompt Issues - 0-indexed lists in prompts (LLMs reliably return 1-indexed) - Prompt text listing available tools/capabilities that don't match what's actually wired up in the `tool_classes`/`tools` array - Word/token limits stated in multiple places that could drift #### Test Gaps - Negative-path tests that assert type/status but not the side effects (URL attached? field populated? callback fired?) - Assertions on string content without checking format (e.g., asserting title present but not URL format) - `.expects(:something).never` missing when a code path should explicitly NOT call an external service - Security enforcement features (blocking, rate limiting, auth) without integration tests verifying the enforcement path works end-to-end #### Crypto & Entropy - Truncation of data instead of hashing (last N chars instead of SHA-256) — less entropy, easier collisions - `rand()` / `Random.rand` for security-sensitive values — use `SecureRandom` instead - Non-constant-time comparisons (`==`) on secrets or tokens — vulnerable to timing attacks #### Time Window Safety - Date-key lookups that assume "today" covers 24h — report at 8am PT only sees midnight→8am under today's key - Mismatched time windows between related features — one uses hourly buckets, another uses daily keys for the same data #### Type Coercion at Boundaries - Values crossing Ruby→JSON→JS boundaries where type could change (numeric vs string) — hash/digest inputs must normalize types - Hash/digest inputs that don't call `.to_s` or equivalent before serialization — `{ cores: 8 }` vs `{ cores: "8" }` produce different hashes #### View/Frontend - Inline `