Owner follow-up to the #280 fix (PR #284): the trusted-header env var is
gone. clientIP() now uses the peer address exclusively and ignores all
client-supplied IP headers; the env var row is removed from the README.
clientIP() keyed rate-limit buckets on the rightmost X-Forwarded-For
entry, assuming traefik appends the real client IP. The deployed ingress
does not rewrite XFF, so rotating the header gave a fresh bucket per
request (pentest H1: 8 creates with rotating XFF -> 6x201).
Now the bucket keys on the actual peer address (RemoteAddr) by default;
every client-supplied IP header is ignored. Deployments whose ingress
overwrites a client-IP header can opt in via PALETTE_TRUSTED_IP_HEADER
(e.g. CF-Connecting-IP behind Cloudflare) to restore per-client limits.
Adds tests: rotating XFF no longer resets the bucket; the trusted header
is honored only when explicitly configured.
- Add code-viewer polish line to the feature list (pinned gutter sized to
the widest number, line wrap, jump buttons, theme-aware scrollbars)
- Extend mobile preview links (editor, dark and light paste views)
- Clarify PALETTE_MAX_ITEM covers can items and file attachments
- Document PALETTE_DEFAULT_DARK in docker-compose.yml so the compose file
really covers every env var
- Collapse the 10 theme cards into 5 pairs: light swatches top row, dark bottom row
- Dark mode toggle in settings and topbar (sun/moon inline SVG)
- Toggling dark mode switches to the other variant of the selected pair
- Persist pair id in localStorage palette-theme, dark flag in palette-dark
- Head script resolves base+dark to variant; URL ?theme= accepts both ids and wins
- Settings gear highlights like nav tabs on /settings
- PALETTE_DEFAULT_DARK env var sets server default dark state (default on)
- Server-side resolution helpers + tests
- Cut Admin walkthrough and API curl block to one-liners pointing at docs
- Keep Configuration table, features, Get Started, doc links
- Retake all screenshots against current UI, one theme each:
/new midnight, /history pastel-lavender, paste view pastel-peach,
/mine pastel-cloud; remove superseded stale previews
- Fix filter fetch to request limit=100 (API max) instead of 500, which
the API silently clamped, so filtered results actually cover the fetch window.
- Document client-side filtering behavior and limits in README Performance Notes.