6.4 KiB
Pixel Donation Grid Constitution
Core Principles
Trust First (MUST)
Payments, allocations, and state transitions MUST be auditable and correct. All monetary actions and allocation changes MUST be recorded atomically and immutably in the database with provider references and timestamps. The system MUST compute and verify prices server-side; client-provided prices are not trusted.
Fast Public Page (MUST)
The public view MUST load a single cached master image plus minimal metadata
only. Public pages MUST NOT construct the master composition on request or make
users wait for rendering. Cache-busting MUST use a master_version token.
Simple UX (SHOULD)
The primary donation flow SHOULD be: select → preview → pay → render. The UI
flow MUST minimize steps and show clear state for draft, pending, paid,
rendering, and rendered states.
Moderation-ready (SHOULD)
Uploads SHOULD be held for review when moderation is enabled; the system MUST support both immediate-render and moderation-hold modes. Moderation decisions MUST be auditable and reversible (refund/deny paths documented).
Mobile Usable (SHOULD)
Interaction controls (pan/zoom/selection) SHOULD work on mobile. The UI MUST provide precise selection aids (snap-to-grid and pixel preview) and degrade gracefully on small screens.
Architecture Rules (NON-NEGOTIABLE)
- Inertia-first: prefer server-rendered Inertia pages and avoid a separate REST API unless a real justification exists.
- Server state machine (source of truth):
draft→pending→paid→rendering→rendered. Failure/cancel states:failed,cancelled,refunded. - Image compositing and heavy processing MUST run in queued Jobs; web requests MUST never perform CPU-bound image composition.
- Idempotency: webhooks and Jobs MUST be safe to retry (store provider event
IDs and order render idempotency keys). Jobs must exit safely if order is
already
rendered. - No double booking: cell reservations MUST be enforced at the DB level using unique constraints and transactional locking; UI checks are supplementary.
- Price computation MUST occur server-side based on
cell_count × price_per_cell.
Data Model Principles
orders: storex, y, w, hin cell units,status,user_id/email,amount,currency,provider,provider_session_id,provider_payment_id,image_path,link_url, timestamps and an audit trail.cell_reservations(cell_x,cell_y,order_id,expires_at): TTL based reservations (e.g., 10 minutes) plus a cleanup command; DB constraints must prevent multiple reservations for the same cell at the same time.master_images: storepath,version(integer),updated_at; incrementversionafter each successful render for cache-busting.
Coordinates MUST be stored in cell units; UI converts to pixels using configured cell size. Reservations MUST expire and be removable by a maintenance command.
Security Rules
- Use Form Requests for all inputs and validate strictly.
- Upload safety: allow only
jpg,png,webp; enforce max file size and max dimensions; strip metadata where feasible; store files via Laravel Storage and never accept client paths. link_urlMUST be validated and normalized (preferhttps); disallow dangerous schemes (javascript: etc.).- Webhooks: verify signatures and persist provider event IDs to prevent replay.
- Rate limit sensitive endpoints (upload, checkout creation) to mitigate abuse.
Frontend Rules
- Do NOT render thousands of DOM nodes for the grid. Use canvas / Konva for drawing and hit-testing.
- Support hover highlight, drag selection rectangle, unavailable/reserved cell rendering, and client preview of uploaded image inside selection.
- Master image URL MUST include
?v=<master_version>token returned by server.
Rendering Contract (Job: ProcessOrderRender)
- Job loads current master image and user image from Storage.
- Resize/crop user image to selection pixel size derived from cell size.
- Composite user image onto master at pixel (x,y). Use lossless steps when possible and preserve master metadata where required.
- Write new master image (or write new version) and increment
master_images.version. - Mark order
renderedand persistmaster_versionchange in a single transactional update.
Idempotency: If the order is already rendered, the Job exits with success and
no-op. On failure, mark order failed, log details, and surface a manual retry
path.
Quality Gates
- Tests required before merge for core flows: pricing, locking (concurrency), webhook idempotency.
- Feature test required: order pending → webhook paid → queued Job render →
renderedandmaster_versionincremented. - All changes touching payment/locking/render logic MUST include automated tests (Pest) that reproduce race conditions where applicable.
Workflow & Review
- Follow Laravel conventions: thin controllers, Form Requests for validation, business logic in Services/Jobs, image composition in Jobs.
- Document key decisions under
/docs/decisions/*.md. - Use small, reviewable commits and add tests when modifying core flows.
Governance
Amendments: Proposals to change this constitution MUST be documented in a PR explaining the rationale and migration plan. Amendments require approval from project maintainers and a test plan. Versioning follows semantic rules:
- MAJOR: incompatible governance or principle removals/rewrites.
- MINOR: new principle or materially expanded guidance.
- PATCH: clarifications, typos, or non-semantic refinements.
Compliance: All PRs touching core flows (payments, locking, rendering) MUST include a short checklist referencing this constitution and the related tests.
Version: 1.0.0 | Ratified: 2026-01-03 | Last Amended: 2026-01-03