0.1.38 gateway

This commit is contained in:
ponzischeme89
2026-08-14 09:40:03 +12:00
parent abc392d30b
commit 5e2ed3d12e
2847 changed files with 1072928 additions and 3783 deletions
+118
View File
@@ -539,3 +539,121 @@ CREATE TABLE IF NOT EXISTS media_requests (
CREATE INDEX IF NOT EXISTS media_requests_user_requested_idx
ON media_requests (emby_user_id, requested_at DESC);
-- Every sign-in attempt, successful or not.
--
-- The sessions table above holds one row per television and is overwritten by the next
-- sign-in, replaced when a device id moves and deleted when a set is removed — so it can
-- say what is true now and nothing at all about what happened. This is the history: how
-- often a set has connected, at what times, from which addresses, on which build, and
-- whether the attempt got in. Every column records what was true at the moment of the
-- attempt, including the ones that later change, which is why device_name and
-- client_version are copied here rather than joined from the session.
--
-- A failed attempt has no emby_user_id: Emby refused the credentials, so there is no
-- verified identity to attribute it to. The username is what was typed, and it is kept
-- precisely because a run of failures against one name is the thing worth noticing.
CREATE TABLE IF NOT EXISTS login_events (
id BIGSERIAL PRIMARY KEY,
occurred_at TIMESTAMPTZ NOT NULL DEFAULT now(),
emby_user_id TEXT NOT NULL DEFAULT '',
username TEXT NOT NULL DEFAULT '',
device_id TEXT NOT NULL DEFAULT '',
device_name TEXT NOT NULL DEFAULT '',
client_version TEXT NOT NULL DEFAULT '',
client_protocol TEXT NOT NULL DEFAULT '',
ip_address TEXT NOT NULL DEFAULT '',
success BOOLEAN NOT NULL,
method TEXT NOT NULL DEFAULT 'password',
failure_reason TEXT NOT NULL DEFAULT '',
new_device BOOLEAN NOT NULL DEFAULT false
);
CREATE INDEX IF NOT EXISTS login_events_time_idx ON login_events (occurred_at DESC);
CREATE INDEX IF NOT EXISTS login_events_device_time_idx
ON login_events (device_id, occurred_at DESC);
CREATE INDEX IF NOT EXISTS login_events_user_time_idx
ON login_events (emby_user_id, occurred_at DESC);
CREATE INDEX IF NOT EXISTS login_events_ip_idx ON login_events (ip_address);
-- Administrative events: the operational feed behind the console's notification bell.
--
-- Deliberately generic. A publisher supplies a type, a severity, who or what it concerns
-- and a sentence; nothing here knows about sign-ins, devices or scheduled tasks
-- specifically. That is what lets a service added later publish into the same feed, and
-- what lets one integration deliver every kind of event without a case per kind.
--
-- read_at is a single operator's read state rather than a per-account one: the console is
-- guarded by one shared admin token, so there is one reader by construction.
CREATE TABLE IF NOT EXISTS admin_events (
id BIGSERIAL PRIMARY KEY,
occurred_at TIMESTAMPTZ NOT NULL DEFAULT now(),
type TEXT NOT NULL,
severity TEXT NOT NULL DEFAULT 'info',
title TEXT NOT NULL DEFAULT '',
summary TEXT NOT NULL DEFAULT '',
actor TEXT NOT NULL DEFAULT '',
target TEXT NOT NULL DEFAULT '',
link TEXT NOT NULL DEFAULT '',
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
read_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS admin_events_time_idx ON admin_events (occurred_at DESC);
CREATE INDEX IF NOT EXISTS admin_events_unread_idx
ON admin_events (occurred_at DESC) WHERE read_at IS NULL;
CREATE INDEX IF NOT EXISTS admin_events_type_time_idx ON admin_events (type, occurred_at DESC);
-- One row per run of a scheduled task.
--
-- The scheduler keeps its next-run time in memory because it is derived from the schedule
-- and the clock, but what *happened* has to outlive the process: an operator asking why
-- the overnight housekeeping did not run is asking about a container that has since been
-- replaced. Duration is stored rather than derived so a run killed by a restart, which
-- has a start and no finish, is distinguishable from one that took no time.
CREATE TABLE IF NOT EXISTS scheduled_task_runs (
id BIGSERIAL PRIMARY KEY,
task_id TEXT NOT NULL,
trigger TEXT NOT NULL DEFAULT 'schedule', -- schedule | manual | startup
status TEXT NOT NULL, -- running | success | failed | skipped
started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
finished_at TIMESTAMPTZ,
duration_ms BIGINT NOT NULL DEFAULT 0,
detail TEXT NOT NULL DEFAULT '',
error TEXT NOT NULL DEFAULT ''
);
CREATE INDEX IF NOT EXISTS scheduled_task_runs_task_idx
ON scheduled_task_runs (task_id, started_at DESC);
CREATE INDEX IF NOT EXISTS scheduled_task_runs_time_idx
ON scheduled_task_runs (started_at DESC);
-- An operator's per-task overrides. A task that has never been touched has no row, and
-- absence is "run as the code declares" — reading it the other way would leave every task
-- disabled on the day this shipped.
CREATE TABLE IF NOT EXISTS scheduled_task_settings (
task_id TEXT PRIMARY KEY,
enabled BOOLEAN NOT NULL DEFAULT true,
interval_seconds INT NOT NULL DEFAULT 0, -- 0 keeps the task's declared interval
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- What an integration actually managed to deliver.
--
-- Kept because the two questions an operator has about a webhook are "is it working" and
-- "why did that one not arrive", and neither is answerable from configuration. The body
-- is not stored: it is reconstructible from the event, and a webhook payload is the one
-- place a URL containing a secret would otherwise come to rest in the database.
CREATE TABLE IF NOT EXISTS integration_deliveries (
id BIGSERIAL PRIMARY KEY,
integration_id TEXT NOT NULL,
event_type TEXT NOT NULL DEFAULT '',
attempted_at TIMESTAMPTZ NOT NULL DEFAULT now(),
success BOOLEAN NOT NULL,
status_code INT NOT NULL DEFAULT 0,
duration_ms BIGINT NOT NULL DEFAULT 0,
error TEXT NOT NULL DEFAULT ''
);
CREATE INDEX IF NOT EXISTS integration_deliveries_idx
ON integration_deliveries (integration_id, attempted_at DESC);