chore: remove redundant migrations directory and migrate binary

All content from 003_add_device_codes.sql and 004_add_trigram_indexes.sql
was already absorbed into db/schema.sql (the single source of truth).

The migrations had additional problems:
- Broken numbering (started at 003, missing 001/002)
- 004 used CREATE INDEX CONCURRENTLY which fails inside sqlx transactions
- No production flow ever invoked the migrate binary

Removed: db/migrations/, src/bin/migrate.rs, migrations Cargo feature,
[[bin]] migrate target, and doc/database-migrations.md.
This commit is contained in:
Dionisio
2026-03-02 23:52:37 +01:00
parent b9bf7ba288
commit 2c3dde2d75
5 changed files with 0 additions and 374 deletions
-99
View File
@@ -1,99 +0,0 @@
-- ============================================================
-- Migration 003: OAuth 2.0 Device Authorization Grant (RFC 8628)
-- ============================================================
-- Adds the device_codes table to support the Device Authorization
-- Grant flow for WebDAV/CalDAV/CardDAV client authentication.
--
-- Flow:
-- 1. Client POSTs to /api/auth/device/authorize → receives device_code + user_code
-- 2. User opens verification_uri in browser, authenticates, enters user_code
-- 3. Client polls /api/auth/device/token with device_code
-- 4. Once approved, client receives access_token + refresh_token
-- ============================================================
-- Device code status enum
DO $BODY$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_type t
JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
WHERE t.typname = 'device_code_status' AND n.nspname = 'auth'
) THEN
CREATE TYPE auth.device_code_status AS ENUM (
'pending', -- Waiting for user to authorize
'authorized', -- User approved, tokens ready for polling client
'denied', -- User denied the request
'expired' -- TTL exceeded without user action
);
END IF;
END $BODY$;
-- Device authorization codes table
CREATE TABLE IF NOT EXISTS auth.device_codes (
-- Unique row ID
id VARCHAR(36) PRIMARY KEY,
-- RFC 8628 §3.2: device_code — long opaque token sent to the client for polling
device_code VARCHAR(128) UNIQUE NOT NULL,
-- RFC 8628 §3.2: user_code — short human-readable code shown on the client
-- and entered by the user on the verification page (e.g. "ABCD-1234")
user_code VARCHAR(16) UNIQUE NOT NULL,
-- Name/description of the client requesting access (shown to user)
client_name VARCHAR(255) NOT NULL DEFAULT 'Unknown Client',
-- Comma-separated scopes requested (e.g. "webdav,caldav,carddav")
scopes VARCHAR(512) NOT NULL DEFAULT 'webdav,caldav,carddav',
-- Current status of the device flow
status auth.device_code_status NOT NULL DEFAULT 'pending',
-- User who authorized the request (NULL until status = 'authorized')
user_id VARCHAR(36) REFERENCES auth.users(id) ON DELETE CASCADE,
-- Tokens generated after authorization (NULL until status = 'authorized')
-- Stored encrypted/hashed depending on sensitivity
access_token TEXT,
refresh_token TEXT,
-- RFC 8628 §3.2: verification_uri — full URL the user must visit
verification_uri TEXT NOT NULL,
-- RFC 8628 §3.2: verification_uri_complete — URL with user_code pre-filled
verification_uri_complete TEXT,
-- RFC 8628 §3.2: expires_in — encoded as an absolute timestamp
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
-- RFC 8628 §3.2: interval — minimum polling interval in seconds
poll_interval_secs INTEGER NOT NULL DEFAULT 5,
-- Last time the client polled (for slow_down enforcement)
last_poll_at TIMESTAMP WITH TIME ZONE,
-- Timestamps
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
authorized_at TIMESTAMP WITH TIME ZONE
);
-- Index for client polling by device_code (hot path)
CREATE INDEX IF NOT EXISTS idx_device_codes_device_code
ON auth.device_codes(device_code);
-- Index for user verification page lookup by user_code
CREATE INDEX IF NOT EXISTS idx_device_codes_user_code
ON auth.device_codes(user_code)
WHERE status = 'pending';
-- Index for cleanup of expired entries
CREATE INDEX IF NOT EXISTS idx_device_codes_expires_at
ON auth.device_codes(expires_at)
WHERE status = 'pending';
-- Index for user's authorized devices
CREATE INDEX IF NOT EXISTS idx_device_codes_user_id
ON auth.device_codes(user_id)
WHERE status = 'authorized';
COMMENT ON TABLE auth.device_codes IS 'OAuth 2.0 Device Authorization Grant (RFC 8628) codes for DAV client authentication';
-43
View File
@@ -1,43 +0,0 @@
-- Migration 004: Add GIN trigram indexes for ILIKE/LIKE substring search
--
-- Eliminates full table scans on text search queries by enabling
-- PostgreSQL's pg_trgm extension and creating GIN indexes with
-- gin_trgm_ops on all columns used in ILIKE / LIKE '%text%' patterns.
--
-- CONCURRENTLY is used so that no table locks are held during index
-- creation — zero downtime for existing installations.
--
-- NOTE: CREATE INDEX CONCURRENTLY cannot run inside a transaction block.
-- If using sqlx migrate, run this file manually:
-- psql -f db/migrations/004_add_trigram_indexes.sql
-- 0. Enable the pg_trgm extension (idempotent)
CREATE EXTENSION IF NOT EXISTS pg_trgm;
-- 1. Contacts — search_contacts(), get_contacts_by_email()
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_contacts_full_name_trgm
ON carddav.contacts USING gin (full_name gin_trgm_ops);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_contacts_first_name_trgm
ON carddav.contacts USING gin (first_name gin_trgm_ops);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_contacts_last_name_trgm
ON carddav.contacts USING gin (last_name gin_trgm_ops);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_contacts_nickname_trgm
ON carddav.contacts USING gin (nickname gin_trgm_ops);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_contacts_organization_trgm
ON carddav.contacts USING gin (organization gin_trgm_ops);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_contacts_email_text_trgm
ON carddav.contacts USING gin ((email::text) gin_trgm_ops);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_contacts_phone_text_trgm
ON carddav.contacts USING gin ((phone::text) gin_trgm_ops);
-- 2. Calendar events — find_events_by_summary()
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_calendar_events_summary_trgm
ON caldav.calendar_events USING gin (summary gin_trgm_ops);
-- 3. Files — search_files_paginated(), search_files_in_subtree(), suggest_files_by_name()
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_files_name_trgm
ON storage.files USING gin (name gin_trgm_ops);
-- 4. Folders — search_folders(), list_descendant_folders(), suggest_folders_by_name()
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_folders_name_trgm
ON storage.folders USING gin (name gin_trgm_ops);