| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- -- 012_telegram_bot_fields.up.sql
- --
- -- M13b W3: extend public.telegram_bots so the admin UI can
- -- configure a per-bot welcome message and default source. Also
- -- adds a bcrypt hash of the bot_token so the UI can render a
- -- "configured / not configured" indicator without ever exposing
- -- the plaintext.
- --
- -- Why both columns?
- -- - bot_token — TEXT, plaintext. telegramd reads
- -- this directly to authenticate with
- -- api.telegram.org. Keep it for now
- -- so telegramd continues to work.
- -- - bot_token_hash — TEXT, bcrypt. Added in W3 so the UI
- -- can determine "configured" status
- -- without exposing the plaintext. The
- -- M11 security milestone will replace
- -- bot_token entirely with an
- -- AES-256-GCM-encrypted column and
- -- add a sidecar to decrypt for
- -- telegramd.
- --
- -- Why nullable bot_token_hash?
- -- Rows seeded by 004/seed_m3.sql have a plaintext bot_token
- -- but no hash yet. The next W3 rotation (or operator save via
- -- UI) will populate the hash. NULL = "unrotated since W3";
- -- the UI surfaces this as "Configured (legacy token)" with
- -- a one-click "Rotate to set hash" hint.
- --
- -- Other columns:
- -- welcome_message — sent in response to /start (M13c wires
- -- telegramd to use this; W3 just stores)
- -- default_source_id — optional pointer to public.sources.id.
- -- W3 sets it on the bot row; W4
- -- (Smoke) verifies the FK shape. We do
- -- NOT add a hard FK in this migration
- -- because sources can be deleted out
- -- from under the bot (admin flow); a
- -- soft reference + ON DELETE SET NULL
- -- would be correct, but we keep the
- -- bot row even if the source goes away
- -- (operator may want to point it at a
- -- new source). v1.1 adds the FK +
- -- a reconciliation job.
- -- description — free-text label. Same shape as
- -- sources.description.
- -- last_rotated_at — set every time the token is written
- -- (create OR rotate). UI shows it.
- -- updated_at — bumped on any PATCH. Audit-friendly.
- --
- -- The down migration drops the new columns. The original
- -- bot_token plaintext column is preserved.
- ALTER TABLE telegram_bots
- ADD COLUMN IF NOT EXISTS bot_token_hash TEXT,
- ADD COLUMN IF NOT EXISTS welcome_message TEXT,
- ADD COLUMN IF NOT EXISTS default_source_id TEXT,
- ADD COLUMN IF NOT EXISTS description TEXT,
- ADD COLUMN IF NOT EXISTS last_rotated_at TIMESTAMPTZ,
- ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT now();
- -- updated_at trigger so any UPDATE bumps it without the app
- -- having to remember. Mirrors the auth.tenants.updated_at
- -- pattern from migration 010.
- CREATE OR REPLACE FUNCTION telegram_bots_touch_updated_at() RETURNS TRIGGER AS $$
- BEGIN
- NEW.updated_at = now();
- RETURN NEW;
- END;
- $$ LANGUAGE plpgsql;
- DROP TRIGGER IF EXISTS trg_telegram_bots_touch_updated_at ON telegram_bots;
- CREATE TRIGGER trg_telegram_bots_touch_updated_at
- BEFORE UPDATE ON telegram_bots
- FOR EACH ROW
- EXECUTE FUNCTION telegram_bots_touch_updated_at();
- -- Index on default_source_id so M13c routing lookups
- -- ("give me the bots that use this source") are fast even when
- -- the table is large. Partial index — most rows will have NULL
- -- default_source_id in v1.
- CREATE INDEX IF NOT EXISTS idx_telegram_bots_default_source
- ON telegram_bots(default_source_id)
- WHERE default_source_id IS NOT NULL;
|