← back to Lifestyle Asset Intel

db/migrations/0004_valuation_calls.sql

42 lines

-- 0004_valuation_calls.sql — immutable audit log for the valuation API.
--
-- BLUEPRINT.md and METHODOLOGY.md both require an immutable audit log
-- of every published valuation. Lenders and insurers will not sign a
-- contract without it: they need to be able to point at a specific
-- call, see what we returned, and reproduce the answer. This table is
-- the canonical record; the v0 middleware writes to it fire-and-forget
-- after the response, so it doesn't add user-visible latency.
--
-- The table is INSERT-only by app convention. There's no UPDATE or
-- DELETE permission grant — when we lock down DB roles in v1.0, the
-- app role gets only INSERT + SELECT here.

CREATE TABLE IF NOT EXISTS valuation_calls (
  id                    uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  called_at             timestamptz NOT NULL DEFAULT now(),
  caller_ip             inet,
  -- Hashed Bearer token (sha256) — never store the raw token.
  caller_token_hash     text,
  route                 text NOT NULL,         -- '/api/valuation/:slug'
  method                text NOT NULL,         -- 'GET'
  asset_slug            text,                  -- when applicable
  response_status       int  NOT NULL,
  methodology_version   text,
  latency_ms            int,
  user_agent            text,
  request_id            uuid                   -- for trace correlation across services
);

CREATE INDEX IF NOT EXISTS valuation_calls_called_idx
  ON valuation_calls(called_at DESC);

CREATE INDEX IF NOT EXISTS valuation_calls_slug_idx
  ON valuation_calls(asset_slug, called_at DESC) WHERE asset_slug IS NOT NULL;

CREATE INDEX IF NOT EXISTS valuation_calls_ip_idx
  ON valuation_calls(caller_ip, called_at DESC) WHERE caller_ip IS NOT NULL;

-- bookkeeping
INSERT INTO schema_migrations(filename) VALUES ('0004_valuation_calls.sql')
  ON CONFLICT (filename) DO NOTHING;