Privacy and security
What Share Your Thoughts With Me stores
- Feedback answers — the literal values submitters typed or selected.
Persisted in Postgres
feedback_answer.answer(JSONB) until the operator deletes them. - Visibility flag and public text — whether the submitter chose to make their feedback public, and the text they want public.
- Submitter label — optional name/handle the submitter typed (empty by default).
- User agent + referrer — the raw strings from the browser request, stored on the feedback entry and on telemetry events.
- IP hash —
HMAC-SHA256(ip, SYTWM_IP_SALT). The raw IP is never persisted. The hash is used for rate-limit grouping and abuse correlation. - Session id — a random cookie value set on the visitor's browser to thread their post steps and telemetry events together. It does not persist across cleared cookies.
What Share Your Thoughts With Me does not store
- No raw IP addresses.
- No cross-site tracking identifiers.
- No third-party analytics integration.
- No real-name verification.
Public vs private
Private feedback is visible only to the admin operator (logged in at
/admin). Public feedback's public_text is visible to anyone on
/comments and through the GET /api/v1/feedback endpoint with a
read-scoped key. Private feedback's text and answers are never returned by
the public endpoints — the test suite asserts this invariant.
Admin and API protection
- The admin UI is gated by a shared secret (
SYTWM_ADMIN_TOKEN). - Admin sessions use a signed cookie that expires after 7 days.
- API keys are stored as a peppered HMAC of the raw secret; the raw value is shown once and never persisted.
Server-side fetches
When the admin uses the Fetch link preview action in the post editor (see Feedback posts), Share Your Thoughts With Me makes a single HTTP request from the server to the URL the admin supplied. The request:
- Times out after 5 seconds.
- Refuses to target internal addresses (loopback, RFC1918, link-local, IPv6 site-local).
- Caps the response body at 256 KiB.
- Follows up to 5 redirects.
- Identifies itself as
User-Agent: sytwm/0.1 (+https://shareyourthoughtswith.me).
The fetched HTML is parsed for Open Graph meta tags (og:title,
og:description, og:image, with twitter:* and <title> as
fallbacks). The parsed values are stored in the post definition and
exposed to visitors on /feedback/<slug> and via the API.
An og_fetch_attempted telemetry event is recorded for every fetch
(success or failure). The event payload contains a SHA-256 prefix of
(URL + IP salt), not the URL itself.
Abuse defenses
- Per-IP rate limits on feedback submission, admin login, and API.
- Honeypot field on the public post form (a non-empty value is rejected).
- Server-side validation on every submission. The API rejects requests whose JSON does not match the documented schema.