Artifact 41b1804fabbc84dc51e55ec966a00ad0b06cc9f7228c42dffe93d38c4ecbd97d:
- File
internal/oltp/oltp.go
— part of check-in
[bf5ba9d2fc]
at
2026-08-16 17:07:31
on branch trunk
— oltp: accounts and per-repo roles
0001 §8's v2 tables. Accounts are the web/API identity (argon2id verifier, site-admin flag, read/write/admin per repo); the RFC §6.3 shared secret stays the sync credential, since the protocol fixes its derivation and the server must recompute it.
ops.Auth becomes the required role, so the Admin level that was already declared now means something. The gate stays open until the first account exists, mirroring the sync-user policy, so existing deployments and local single-user serving are unaffected. (user: dmestas, size: 2094) [annotate] [blame] [check-ins using]
// Package oltp is quarry's forge OLTP database (0001 §8): the only // authoritative non-DAG state. v1 holds sync users — per-repo login // credentials for push gating. Small by construction; the litestream // replica is the recovery story when deployment warrants it. package oltp import ( "database/sql" "fmt" "github.com/ncruces/go-sqlite3/driver" ) const schema = ` CREATE TABLE IF NOT EXISTS sync_user ( repo TEXT NOT NULL, user TEXT NOT NULL, secret TEXT NOT NULL, -- RFC §6.3 shared secret (40 hex); plaintext never stored PRIMARY KEY (repo, user) );` type DB struct { db *sql.DB } func Open(path string) (*DB, error) { db, err := driver.Open("file:" + path) if err != nil { return nil, err } if _, err := db.Exec(`PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;`); err != nil { db.Close() return nil, fmt.Errorf("oltp: pragmas: %w", err) } if _, err := db.Exec(schema); err != nil { db.Close() return nil, fmt.Errorf("oltp: schema: %w", err) } if _, err := db.Exec(accountSchema); err != nil { db.Close() return nil, fmt.Errorf("oltp: account schema: %w", err) } return &DB{db: db}, nil } func (d *DB) Close() error { return d.db.Close() } // SetSyncUser stores (replacing) one repo user's shared secret. func (d *DB) SetSyncUser(repo, user, secret string) error { _, err := d.db.Exec(`INSERT OR REPLACE INTO sync_user (repo, user, secret) VALUES (?, ?, ?)`, repo, user, secret) return err } // Secret returns the stored shared secret for one repo user. func (d *DB) Secret(repo, user string) (string, bool) { var s string err := d.db.QueryRow(`SELECT secret FROM sync_user WHERE repo = ? AND user = ?`, repo, user).Scan(&s) return s, err == nil } // Gated reports whether a repo has any sync users — the v1 policy // switch: no users means anonymous push stays allowed (local use), // one or more users means pushes must authenticate. func (d *DB) Gated(repo string) bool { var n int if err := d.db.QueryRow(`SELECT count(*) FROM sync_user WHERE repo = ?`, repo).Scan(&n); err != nil { return false } return n > 0 }