0036_contact_messages.sql29 lines · main
1-- 0036_contact_messages — public /contact form intake.
2-- The /contact marketing page writes one row per submission from an
3-- unauthenticated visitor. The sender's email is collected + stored
4-- here so an operator can reply privately — it is never rendered back
5-- to the website. Triaged out-of-band; `handled_at` is stamped once an
6-- operator has actioned the message. Lands on the control DB (Postgres).
7
8CREATE TABLE IF NOT EXISTS "contact_messages" (
9 "id" text PRIMARY KEY NOT NULL,
10 "name" text NOT NULL,
11 -- Collected so the operator can reply privately. NEVER echoed back to
12 -- the website in any state.
13 "email" text NOT NULL,
14 -- Routing hint chosen by the sender. Values: general | support | sales
15 -- | security | privacy | other.
16 "topic" text NOT NULL,
17 "message" text NOT NULL,
18 -- Abuse signals — hashed IP + raw user-agent, both nullable when the
19 -- request arrives without them.
20 "ip_hash" text,
21 "user_agent" text,
22 "created_at" timestamp with time zone DEFAULT now() NOT NULL,
23 -- Stamped once an operator has actioned the message.
24 "handled_at" timestamp with time zone
25);
26
27-- Triage queue: operator reviews newest-first.
28CREATE INDEX IF NOT EXISTS "contact_messages_created_idx"
29 ON "contact_messages" USING btree ("created_at" DESC);