feat(tradein/db): user_events table — unified login/IP audit + behavior event log (#2515)
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 48s
Deploy Trade-In / build-backend (push) Successful in 29s
Deploy Trade-In / deploy (push) Successful in 52s
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 48s
Deploy Trade-In / build-backend (push) Successful in 29s
Deploy Trade-In / deploy (push) Successful in 52s
Append-only user_events table (event_type, username, ip_address inet, user_agent, path, method, estimate_id, payload jsonb, created_at) + 4 indexes. Foundation for login/IP audit + behavior analytics. Resurrects dropped audit_log design.
This commit is contained in:
parent
749c96cd0c
commit
5647c2b40e
1 changed files with 60 additions and 0 deletions
60
tradein-mvp/backend/data/sql/184_user_events.sql
Normal file
60
tradein-mvp/backend/data/sql/184_user_events.sql
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
-- 184_user_events.sql
|
||||
-- Foundation schema for Features 2 & 3: unified user-event tracking.
|
||||
--
|
||||
-- WHY:
|
||||
-- trade-in had no durable event log for login/IP audit or behavior
|
||||
-- analytics. A near-identical design already existed once — `audit_log`
|
||||
-- (event_type, ip_address inet, user_agent, estimate_id uuid, payload
|
||||
-- jsonb, created_at) was defined in 002_core_tables.sql and DROPPED in
|
||||
-- 095_dead_schema.sql as unused dead schema at the time. Product now
|
||||
-- needs exactly that shape again, so this migration resurrects the
|
||||
-- design under a new name, `user_events`, as the ONE unified
|
||||
-- append-only table serving:
|
||||
-- - login-audit (who logged in, from what IP/UA, when)
|
||||
-- - search-audit (estimate requests, listing lookups)
|
||||
-- - behavior-analytics (pdf_download, listing_click, page_view,
|
||||
-- drawer_open, and future event_type values)
|
||||
--
|
||||
-- WHAT:
|
||||
-- `user_events` — append-only, admin-read-only. No 152-ФЗ consent
|
||||
-- gating and no mandatory retention policy for MVP (product-owner
|
||||
-- decision): we log IP/UA/path/method/payload unconditionally for every
|
||||
-- tracked event. `estimate_id` is a plain uuid column with NO FK
|
||||
-- constraint on purpose — this keeps the log decoupled/append-only so
|
||||
-- estimate deletion (or any future estimate lifecycle change) never
|
||||
-- blocks or cascades into event rows.
|
||||
--
|
||||
-- IDEMPOTENCY / SAFETY:
|
||||
-- CREATE TABLE IF NOT EXISTS + CREATE INDEX IF NOT EXISTS throughout —
|
||||
-- safe re-run. Purely additive: no existing table/view/column is
|
||||
-- touched.
|
||||
--
|
||||
-- Dependencies: none (new standalone table). Auto-applied on deploy via
|
||||
-- _schema_migrations tracking (tradein-mvp/backend/data/sql convention).
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_events (
|
||||
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
event_type text NOT NULL,
|
||||
username text NOT NULL,
|
||||
ip_address inet,
|
||||
user_agent text,
|
||||
path text,
|
||||
method text,
|
||||
estimate_id uuid,
|
||||
payload jsonb NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
COMMENT ON TABLE user_events IS 'Unified append-only event log (login/IP audit + behavior analytics), admin-read-only. Resurrects the design of audit_log (002_core_tables.sql, dropped in 095_dead_schema.sql).';
|
||||
COMMENT ON COLUMN user_events.event_type IS 'e.g. login / estimate_request / pdf_download / listing_click / page_view / drawer_open.';
|
||||
COMMENT ON COLUMN user_events.username IS 'X-Authenticated-User value at the time of the event.';
|
||||
COMMENT ON COLUMN user_events.estimate_id IS 'No FK constraint by design — keeps the log decoupled/append-only from trade_in_estimates lifecycle.';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS user_events_username_created_at_idx ON user_events (username, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS user_events_event_type_created_at_idx ON user_events (event_type, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS user_events_ip_address_idx ON user_events (ip_address);
|
||||
CREATE INDEX IF NOT EXISTS user_events_created_at_idx ON user_events (created_at DESC);
|
||||
|
||||
COMMIT;
|
||||
Loading…
Add table
Reference in a new issue