diff --git a/tradein-mvp/backend/data/sql/184_user_events.sql b/tradein-mvp/backend/data/sql/184_user_events.sql
new file mode 100644
index 00000000..af2e0c09
--- /dev/null
+++ b/tradein-mvp/backend/data/sql/184_user_events.sql
@@ -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;
diff --git a/tradein-mvp/frontend/src/components/trade-in/Topbar.tsx b/tradein-mvp/frontend/src/components/trade-in/Topbar.tsx
index 3c716ef7..d1e9628d 100644
--- a/tradein-mvp/frontend/src/components/trade-in/Topbar.tsx
+++ b/tradein-mvp/frontend/src/components/trade-in/Topbar.tsx
@@ -9,6 +9,58 @@ import { safeUrl } from "@/lib/safeUrl";
import { useBrand } from "@/lib/useBrand";
import { useMe } from "@/lib/useMe";
+/** Telegram-канал обратной связи для пилота. Build-time env — пусто до тех
+ пор, пока devops не настроит реальную ссылку (см. FeedbackButton ниже). */
+const FEEDBACK_TG_URL = process.env.NEXT_PUBLIC_FEEDBACK_TG_URL ?? "";
+
+/** Inline Send icon (lucide-react `Send` SVG path, stroke 1.5) — та же
+ конвенция, что и LogOutIcon в UserMenu.tsx: tradein-mvp не тянет
+ lucide-react в deps, поэтому иконка — inline SVG. */
+function TelegramIcon() {
+ return (
+
+ );
+}
+
+/**
+ * Кнопка обратной связи в Telegram — рендерится для ВСЕХ авторизованных
+ * пользователей (не зависит от RBAC allowed_paths, в отличие от NAV_ITEMS).
+ *
+ * Env-gated: пока `NEXT_PUBLIC_FEEDBACK_TG_URL` не задан на билде, кнопка не
+ * рендерится вообще — безопасно шипить до появления реальной Telegram-ссылки.
+ * safeUrl() дополнительно блокирует не-http(s) схемы (#766-class XSS).
+ */
+function FeedbackButton() {
+ const href = safeUrl(FEEDBACK_TG_URL);
+ if (!href) return null;
+
+ return (
+
+
+ Обратная связь
+
+ );
+}
+
/** «Мера» mark — буква М над размерной линией («мера» = измерение).
Глиф в currentColor; тёмный фон даёт CSS-бейдж .brand-mark. */
function MeraMark() {
@@ -156,6 +208,10 @@ export function Topbar({ active }: TopbarProps) {
{/* UserMenu — личный кабинет справа от nav. В dev (401) или до /me
UserMenu сам рендерит null. */}
+ {/* FeedbackButton — вне items.map/RBAC: видна всем авторизованным
+ пользователям независимо от allowed_paths. Сама себя прячет,
+ пока NEXT_PUBLIC_FEEDBACK_TG_URL не задан. */}
+