Files
mcr/internal/db/migrate.go
Kyle Isom 78f3eae651 Migrate db, auth, and config to mcdsl
- db.Open: delegate to mcdsl/db.Open
- db.Migrate: rewrite migrations as mcdsl/db.Migration SQL strings,
  delegate to mcdsl/db.Migrate; keep SchemaVersion via mcdsl
- auth: thin shim wrapping mcdsl/auth.Authenticator, keeps Claims
  type (with Subject, AccountType, Roles) for policy engine compat;
  delete cache.go (handled by mcdsl/auth); add ErrForbidden
- config: embed mcdsl/config.Base for standard sections (Server with
  Duration fields, Database, MCIAS, Log); keep StorageConfig and
  WebConfig as MCR-specific; use mcdsl/config.Load[T] + Validator
- WriteTimeout now defaults to 30s (mcdsl default, was 0)
- All existing tests pass (auth tests rewritten for new shim API,
  cache expiry test removed — caching tested in mcdsl)
- Net -464 lines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 17:10:46 -07:00

111 lines
3.7 KiB
Go

package db
import (
mcdsldb "git.wntrmute.dev/kyle/mcdsl/db"
)
// Migrations is the ordered list of MCR schema migrations.
var Migrations = []mcdsldb.Migration{
{
Version: 1,
Name: "core registry tables",
SQL: `
CREATE TABLE IF NOT EXISTS repositories (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now'))
);
CREATE TABLE IF NOT EXISTS manifests (
id INTEGER PRIMARY KEY,
repository_id INTEGER NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
digest TEXT NOT NULL,
media_type TEXT NOT NULL,
content BLOB NOT NULL,
size INTEGER NOT NULL,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
UNIQUE(repository_id, digest)
);
CREATE INDEX IF NOT EXISTS idx_manifests_repo ON manifests (repository_id);
CREATE INDEX IF NOT EXISTS idx_manifests_digest ON manifests (digest);
CREATE TABLE IF NOT EXISTS tags (
id INTEGER PRIMARY KEY,
repository_id INTEGER NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
name TEXT NOT NULL,
manifest_id INTEGER NOT NULL REFERENCES manifests(id) ON DELETE CASCADE,
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
UNIQUE(repository_id, name)
);
CREATE INDEX IF NOT EXISTS idx_tags_repo ON tags (repository_id);
CREATE INDEX IF NOT EXISTS idx_tags_manifest ON tags (manifest_id);
CREATE TABLE IF NOT EXISTS blobs (
id INTEGER PRIMARY KEY,
digest TEXT NOT NULL UNIQUE,
size INTEGER NOT NULL,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now'))
);
CREATE TABLE IF NOT EXISTS manifest_blobs (
manifest_id INTEGER NOT NULL REFERENCES manifests(id) ON DELETE CASCADE,
blob_id INTEGER NOT NULL REFERENCES blobs(id),
PRIMARY KEY (manifest_id, blob_id)
);
CREATE INDEX IF NOT EXISTS idx_manifest_blobs_blob ON manifest_blobs (blob_id);
CREATE TABLE IF NOT EXISTS uploads (
id INTEGER PRIMARY KEY,
uuid TEXT NOT NULL UNIQUE,
repository_id INTEGER NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
byte_offset INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now'))
);`,
},
{
Version: 2,
Name: "policy and audit tables",
SQL: `
CREATE TABLE IF NOT EXISTS policy_rules (
id INTEGER PRIMARY KEY,
priority INTEGER NOT NULL DEFAULT 100,
description TEXT NOT NULL,
rule_json TEXT NOT NULL,
enabled INTEGER NOT NULL DEFAULT 1 CHECK (enabled IN (0,1)),
created_by TEXT,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now'))
);
CREATE TABLE IF NOT EXISTS audit_log (
id INTEGER PRIMARY KEY,
event_time TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
event_type TEXT NOT NULL,
actor_id TEXT,
repository TEXT,
digest TEXT,
ip_address TEXT,
details TEXT
);
CREATE INDEX IF NOT EXISTS idx_audit_time ON audit_log (event_time);
CREATE INDEX IF NOT EXISTS idx_audit_actor ON audit_log (actor_id);
CREATE INDEX IF NOT EXISTS idx_audit_event ON audit_log (event_type);`,
},
}
// Migrate applies all pending migrations. It creates the schema_migrations
// tracking table if it does not exist. Migrations are idempotent.
func (d *DB) Migrate() error {
return mcdsldb.Migrate(d.DB, Migrations)
}
// SchemaVersion returns the highest applied migration version, or 0 if
// no migrations have been applied.
func (d *DB) SchemaVersion() (int, error) {
return mcdsldb.SchemaVersion(d.DB)
}