Photo System
State of Stick — Photo System
Section titled “State of Stick — Photo System”The site has three separate photo pipelines, each with a different purpose, storage backend, and trust model. They are not interchangeable — don’t conflate them.
| # | Subsystem | Direction | Trust model |
|---|---|---|---|
| 1 | Catalog / product imagery | read (display) | public, hotlink-protected |
| 2 | Claim photos | write (buyer upload) | public after upload |
| 3 | Sponsor logos | write (sponsor upload) | private, reviewed |
1. Catalog / product imagery — read path
Section titled “1. Catalog / product imagery — read path”The display layer for emblems and products. Origin files live on disk; delivery runs through an edge image service that resizes and caches variants (thumb / medium / hero) so the browser fetches the smallest size that satisfies the layout width.
- Responsive
srcsetacross variants. - Hotlink protection at the edge.
- A drop-in image component, plus a protected-image variant that adds casual-theft deterrents (disables right-click / drag / long-press). The protected variant explicitly does not stop screenshots, devtools, or headless scrapers.
2. Claim photos — write path (public)
Section titled “2. Claim photos — write path (public)”When a buyer claims a physical piece, they can upload one photo of it.
- The claim must already exist and be in the
claimedstate (claim first, then photo). - One photo per claim.
- JPG / PNG / WebP only, size-capped.
- Magic-byte validation — the declared content-type is not trusted on its own.
- Rate limited per request fingerprint.
Uploaded photos are served publicly and linked back to the claim record.
3. Sponsor logos — write path (private, reviewed)
Section titled “3. Sponsor logos — write path (private, reviewed)”Sponsor / supporter logo intake. Stricter than claim photos.
- Token-gated — requires a valid intake token tied to a contribution.
- PNG and SVG only. PNG validated by magic bytes; SVG sanitized against script / embed / event-handler / external-reference vectors (anti-XSS / anti-XXE) before it is ever stored.
- Roles: primary / secondary logo; capped per contribution; no silent replace.
- Rate limited per fingerprint.
- Stored in a private bucket and held for manual review before use.
Shared security primitives
Section titled “Shared security primitives”- Magic-byte signature sniffing for uploaded images — never trust the declared content-type.
- Per-route rate limiting keyed on a request fingerprint.
- Constant-time token comparison for token-gated flows.