Self-hosted HTML artifact publisher. Single Go binary, SQLite metadata, HTML on disk. Features: password-protected artifacts, per-artifact expiration, admin dashboard with view metrics (privacy-preserving daily-salt visitor hash, sparklines, 30-day SVG chart, top referrers), rate-limited unlock endpoint. Packaged as a Docker image (two-stage, CGO_ENABLED=0, pure-Go SQLite). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
51 lines
1.5 KiB
SQL
51 lines
1.5 KiB
SQL
CREATE TABLE IF NOT EXISTS artifacts (
|
|
slug TEXT PRIMARY KEY,
|
|
title TEXT NOT NULL DEFAULT '',
|
|
size_bytes INTEGER NOT NULL,
|
|
password_hash TEXT,
|
|
created_at INTEGER NOT NULL,
|
|
expires_at INTEGER,
|
|
view_count INTEGER NOT NULL DEFAULT 0,
|
|
last_viewed_at INTEGER
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_artifacts_created_at ON artifacts(created_at DESC);
|
|
|
|
CREATE TABLE IF NOT EXISTS views (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
slug TEXT NOT NULL,
|
|
viewed_at INTEGER NOT NULL,
|
|
visitor TEXT NOT NULL,
|
|
referrer TEXT,
|
|
FOREIGN KEY (slug) REFERENCES artifacts(slug) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_views_slug_time ON views(slug, viewed_at);
|
|
CREATE INDEX IF NOT EXISTS idx_views_time ON views(viewed_at);
|
|
|
|
CREATE TABLE IF NOT EXISTS daily_stats (
|
|
slug TEXT NOT NULL,
|
|
day TEXT NOT NULL,
|
|
views INTEGER NOT NULL DEFAULT 0,
|
|
uniques INTEGER NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (slug, day),
|
|
FOREIGN KEY (slug) REFERENCES artifacts(slug) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_daily_stats_day ON daily_stats(day);
|
|
|
|
CREATE TABLE IF NOT EXISTS unlock_attempts (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
slug TEXT NOT NULL,
|
|
at INTEGER NOT NULL,
|
|
visitor TEXT NOT NULL,
|
|
success INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_unlock_attempts_slug_time ON unlock_attempts(slug, at);
|
|
|
|
CREATE TABLE IF NOT EXISTS meta (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL
|
|
);
|