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
Path 3D rendering — CSS perspective math, billboard system, canvas grass
Path performance — Optimization strategies (implemented and remaining)
Critical Gotchas (Quick Reference)
STI NULL scope: User.verified must be where(type: nil) not where.not(type: "TrialUser") — PostgreSQL excludes NULL from !=
Rails 8.1 callback validation: Controllers without index must use blanket skip_after_action (no only:) — Rails validates action names in inherited chains
only: vs except: rule: Relaxing directives use only: (fail-closed); restricting directives use except: or blanket
Lookout signed URLs expire after 1 hour — always fetch fresh via /video or /thumbnail endpoints
Active Storage direct uploads require auth — patched in active_storage_auth.rb because DirectUploadsController bypasses ApplicationController
Inertia exposes all props to browser devtools — never pass secrets or tokens to the frontend
Soft-delete cascades are explicit — Project#discard manually cascades to collaborators, invites, and journal entries in a transaction
Recording deletion ≠ timelapse deletion — destroying a Recording unlinks but preserves the underlying timelapse/video for reuse
HCB is off-limits — do not edit HCB-related code without explicit written approval
Koi awarding flows downstream into HCB — approving a ship issues a ship_reviewKoiTransaction (7 koi/hour of user-facing time + DR/BR koi_adjustment), which is later spendable on ProjectGrantOrder → real HCB topup. Treat the awarding code as financial. See arch-ship-and-koi.md §10 for the awarding formula and §7 for the user-facing-vs-internal hours distinction (koi follows user-facing only).
Ship pending and awaiting_identity both block resubmission — ProjectPolicy#ship? excludes both, so an unverified user with a held submission cannot ship a different project either.
Reviewer claim is global across types — claiming any review releases the user's claims on all other review types (one active claim at a time).