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>
This commit is contained in:
@@ -3,10 +3,8 @@ package db
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
mcdsldb "git.wntrmute.dev/kyle/mcdsl/db"
|
||||
)
|
||||
|
||||
// DB wraps a SQLite database connection.
|
||||
@@ -16,34 +14,11 @@ type DB struct {
|
||||
|
||||
// Open opens (or creates) a SQLite database at the given path with the
|
||||
// standard Metacircular pragmas: WAL mode, foreign keys, busy timeout.
|
||||
// The file is created with 0600 permissions.
|
||||
func Open(path string) (*DB, error) {
|
||||
dir := filepath.Dir(path)
|
||||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
return nil, fmt.Errorf("db: create directory %s: %w", dir, err)
|
||||
}
|
||||
|
||||
sqlDB, err := sql.Open("sqlite", path)
|
||||
sqlDB, err := mcdsldb.Open(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("db: open %s: %w", path, err)
|
||||
return nil, fmt.Errorf("db: %w", err)
|
||||
}
|
||||
|
||||
pragmas := []string{
|
||||
"PRAGMA journal_mode = WAL",
|
||||
"PRAGMA foreign_keys = ON",
|
||||
"PRAGMA busy_timeout = 5000",
|
||||
}
|
||||
for _, p := range pragmas {
|
||||
if _, err := sqlDB.Exec(p); err != nil {
|
||||
_ = sqlDB.Close()
|
||||
return nil, fmt.Errorf("db: %s: %w", p, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Set file permissions to 0600 (owner read/write only).
|
||||
if err := os.Chmod(path, 0600); err != nil {
|
||||
_ = sqlDB.Close()
|
||||
return nil, fmt.Errorf("db: chmod %s: %w", path, err)
|
||||
}
|
||||
|
||||
return &DB{sqlDB}, nil
|
||||
}
|
||||
|
||||
@@ -1,23 +1,15 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
mcdsldb "git.wntrmute.dev/kyle/mcdsl/db"
|
||||
)
|
||||
|
||||
// migration is a numbered schema change.
|
||||
type migration struct {
|
||||
version int
|
||||
name string
|
||||
sql string
|
||||
}
|
||||
|
||||
// migrations is the ordered list of schema migrations.
|
||||
var migrations = []migration{
|
||||
// Migrations is the ordered list of MCR schema migrations.
|
||||
var Migrations = []mcdsldb.Migration{
|
||||
{
|
||||
version: 1,
|
||||
name: "core registry tables",
|
||||
sql: `
|
||||
Version: 1,
|
||||
Name: "core registry tables",
|
||||
SQL: `
|
||||
CREATE TABLE IF NOT EXISTS repositories (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
@@ -71,13 +63,12 @@ CREATE TABLE IF NOT EXISTS uploads (
|
||||
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: `
|
||||
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,
|
||||
@@ -102,73 +93,18 @@ CREATE TABLE IF NOT EXISTS audit_log (
|
||||
|
||||
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);
|
||||
`,
|
||||
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 {
|
||||
_, err := d.Exec(`CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||
version INTEGER PRIMARY KEY,
|
||||
applied_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now'))
|
||||
)`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("db: create schema_migrations: %w", err)
|
||||
}
|
||||
|
||||
for _, m := range migrations {
|
||||
applied, err := d.migrationApplied(m.version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if applied {
|
||||
continue
|
||||
}
|
||||
|
||||
tx, err := d.Begin()
|
||||
if err != nil {
|
||||
return fmt.Errorf("db: begin migration %d (%s): %w", m.version, m.name, err)
|
||||
}
|
||||
|
||||
if _, err := tx.Exec(m.sql); err != nil {
|
||||
_ = tx.Rollback()
|
||||
return fmt.Errorf("db: migration %d (%s): %w", m.version, m.name, err)
|
||||
}
|
||||
|
||||
if _, err := tx.Exec(`INSERT INTO schema_migrations (version) VALUES (?)`, m.version); err != nil {
|
||||
_ = tx.Rollback()
|
||||
return fmt.Errorf("db: record migration %d: %w", m.version, err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return fmt.Errorf("db: commit migration %d: %w", m.version, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) migrationApplied(version int) (bool, error) {
|
||||
var count int
|
||||
err := d.QueryRow(`SELECT COUNT(*) FROM schema_migrations WHERE version = ?`, version).Scan(&count)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("db: check migration %d: %w", version, err)
|
||||
}
|
||||
return count > 0, nil
|
||||
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) {
|
||||
var version sql.NullInt64
|
||||
err := d.QueryRow(`SELECT MAX(version) FROM schema_migrations`).Scan(&version)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("db: schema version: %w", err)
|
||||
}
|
||||
if !version.Valid {
|
||||
return 0, nil
|
||||
}
|
||||
return int(version.Int64), nil
|
||||
return mcdsldb.SchemaVersion(d.DB)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user