142 lines
6.4 KiB
Markdown
142 lines
6.4 KiB
Markdown
<!--
|
||
Sync Impact Report
|
||
|
||
- Version change: template -> 1.0.0
|
||
- Modified principles: added Product Principles (Trust-first, Fast public page, Simple UX,
|
||
Moderation-ready, Mobile usable)
|
||
- Added sections: Architecture Rules, Data Model Principles, Security Rules,
|
||
Frontend Rules, Rendering Contract, Quality Gates
|
||
- Removed sections: none
|
||
- Templates requiring updates:
|
||
- .specify/templates/plan-template.md: ⚠ pending
|
||
- .specify/templates/spec-template.md: ⚠ pending
|
||
- .specify/templates/tasks-template.md: ⚠ pending
|
||
- Follow-up TODOs:
|
||
- TODO(CONSTITUTION_PROPAGATION): update templates to include explicit "Constitution
|
||
Check" gates keyed to this constitution. See templates listed above.
|
||
-->
|
||
|
||
# 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)
|
||
|
||
1. Inertia-first: prefer server-rendered Inertia pages and avoid a separate REST
|
||
API unless a real justification exists.
|
||
2. Server state machine (source of truth): `draft` → `pending` → `paid` →
|
||
`rendering` → `rendered`. Failure/cancel states: `failed`, `cancelled`,
|
||
`refunded`.
|
||
3. Image compositing and heavy processing MUST run in queued Jobs; web
|
||
requests MUST never perform CPU-bound image composition.
|
||
4. 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`.
|
||
5. No double booking: cell reservations MUST be enforced at the DB level using
|
||
unique constraints and transactional locking; UI checks are supplementary.
|
||
6. Price computation MUST occur server-side based on `cell_count × price_per_cell`.
|
||
|
||
## Data Model Principles
|
||
|
||
- `orders`: store `x, y, w, h` in 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`: store `path`, `version` (integer), `updated_at`; increment
|
||
`version` after 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
|
||
|
||
1. Use Form Requests for all inputs and validate strictly.
|
||
2. 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.
|
||
3. `link_url` MUST be validated and normalized (prefer `https`); disallow
|
||
dangerous schemes (javascript: etc.).
|
||
4. Webhooks: verify signatures and persist provider event IDs to prevent replay.
|
||
5. Rate limit sensitive endpoints (upload, checkout creation) to mitigate abuse.
|
||
|
||
## Frontend Rules
|
||
|
||
1. Do NOT render thousands of DOM nodes for the grid. Use canvas / Konva for
|
||
drawing and hit-testing.
|
||
2. Support hover highlight, drag selection rectangle, unavailable/reserved
|
||
cell rendering, and client preview of uploaded image inside selection.
|
||
3. Master image URL MUST include `?v=<master_version>` token returned by server.
|
||
|
||
## Rendering Contract (Job: ProcessOrderRender)
|
||
|
||
1. Job loads current master image and user image from Storage.
|
||
2. Resize/crop user image to selection pixel size derived from cell size.
|
||
3. Composite user image onto master at pixel (x,y). Use lossless steps when
|
||
possible and preserve master metadata where required.
|
||
4. Write new master image (or write new version) and increment `master_images.version`.
|
||
5. Mark order `rendered` and persist `master_version` change 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 →
|
||
`rendered` and `master_version` incremented.
|
||
- 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
|