Skip to content
quarry Artifact [d24f6216dc]
Login

Artifact [d24f6216dc]

Artifact d24f6216dcabe76b14bfeb4507058dbcdc2ce268149eb6c28eb0bcfa833f69e0:


package oltp

import "time"

// The gate-bypass tripwire (RFC 0007/0009 follow-through). A stock zit
// client can accept a landing against the shared store without ever
// consulting the forge's required checks, and the store cannot refuse
// it. What the forge CAN do is notice: it records every accept it
// wrote itself, watches each protected branch's tip, and any check-in
// that arrives on one without a forge accept behind it is named — on
// the CI page and in the log — within a poll tick.

const gateSchema = `
CREATE TABLE IF NOT EXISTS forge_accept (
	repo    TEXT NOT NULL,
	checkin TEXT NOT NULL, -- the merge check-in a forge accept wrote
	PRIMARY KEY (repo, checkin)
);
CREATE TABLE IF NOT EXISTS gate_watch (
	repo   TEXT NOT NULL,
	branch TEXT NOT NULL,
	tip    TEXT NOT NULL, -- last swept tip
	PRIMARY KEY (repo, branch)
);
CREATE TABLE IF NOT EXISTS gate_bypass (
	repo    TEXT NOT NULL,
	branch  TEXT NOT NULL,
	checkin TEXT NOT NULL,
	seen    TEXT NOT NULL,
	-- who committed it, so the finding names a person, not a hash.
	who     TEXT NOT NULL DEFAULT '',
	-- acked is when a maintainer marked it seen. A finding is a
	-- tripwire, and a tripwire that cannot be reset is an alarm that
	-- rings forever: the record stays (it is history), the strip
	-- stops showing it.
	acked   TEXT NOT NULL DEFAULT '',
	PRIMARY KEY (repo, checkin)
);`

// gateMigrations are additive columns for stores written before them.
var gateMigrations = []string{
	`ALTER TABLE gate_bypass ADD COLUMN who TEXT NOT NULL DEFAULT ''`,
	`ALTER TABLE gate_bypass ADD COLUMN acked TEXT NOT NULL DEFAULT ''`,
}

// GateBypass is one tripwire finding.
type GateBypass struct {
	Repo    string `json:"repo"`
	Branch  string `json:"branch"`
	Checkin string `json:"checkin"`
	Seen    string `json:"seen"`
	Who     string `json:"who,omitempty"`
	Acked   string `json:"acked,omitempty"`
}

// RecordForgeAccept remembers that the forge itself wrote this merge.
func (d *DB) RecordForgeAccept(repo, checkin string) error {
	_, err := d.db.Exec(`INSERT OR IGNORE INTO forge_accept (repo, checkin) VALUES (?, ?)`,
		repo, checkin)
	return err
}

// ForgeAccepted reports whether a check-in was a forge accept's merge.
func (d *DB) ForgeAccepted(repo, checkin string) (bool, error) {
	var one int
	err := d.db.QueryRow(`SELECT 1 FROM forge_accept WHERE repo = ? AND checkin = ?`,
		repo, checkin).Scan(&one)
	if err == nil {
		return true, nil
	}
	return false, nil
}

// GateWatch reads a protected branch's last swept tip.
func (d *DB) GateWatch(repo, branch string) (string, bool) {
	var tip string
	err := d.db.QueryRow(`SELECT tip FROM gate_watch WHERE repo = ? AND branch = ?`,
		repo, branch).Scan(&tip)
	return tip, err == nil
}

// SetGateWatch records how far the sweep has looked.
func (d *DB) SetGateWatch(repo, branch, tip string) error {
	_, err := d.db.Exec(`INSERT OR REPLACE INTO gate_watch (repo, branch, tip) VALUES (?, ?, ?)`,
		repo, branch, tip)
	return err
}

// AddGateBypass records a finding; seeing the same check-in twice is
// one finding, not two.
func (d *DB) AddGateBypass(repo, branch, checkin, who string) error {
	_, err := d.db.Exec(`INSERT OR IGNORE INTO gate_bypass (repo, branch, checkin, seen, who)
		VALUES (?, ?, ?, ?, ?)`, repo, branch, checkin, time.Now().UTC().Format(time.RFC3339), who)
	return err
}

// GateBypasses lists a repository's OPEN findings, newest first — what
// the CI page's strip shows. Acknowledged ones live in the history.
func (d *DB) GateBypasses(repo string, limit int) ([]GateBypass, error) {
	if limit <= 0 {
		limit = 5
	}
	return d.gateRows(`WHERE repo = ? AND acked = '' ORDER BY seen DESC LIMIT `+itoa(limit), repo)
}

// GateBypassHistory pages every finding, open or acknowledged, newest
// first, and says how many there are in all — a page that grows
// forever is the failure this exists to prevent.
func (d *DB) GateBypassHistory(repo string, offset, limit int) (rows []GateBypass, total int, err error) {
	if limit <= 0 {
		limit = 50
	}
	if offset < 0 {
		offset = 0
	}
	if err = d.db.QueryRow(`SELECT count(*) FROM gate_bypass WHERE repo = ?`, repo).Scan(&total); err != nil {
		return nil, 0, err
	}
	rows, err = d.gateRows(`WHERE repo = ? ORDER BY seen DESC LIMIT `+itoa(limit)+` OFFSET `+itoa(offset), repo)
	return rows, total, err
}

// AckGateBypass marks one finding seen; AckAllGateBypasses clears the
// strip. Neither deletes: the tripwire's record is history.
func (d *DB) AckGateBypass(repo, checkin string) error {
	_, err := d.db.Exec(`UPDATE gate_bypass SET acked = ? WHERE repo = ? AND checkin = ? AND acked = ''`,
		time.Now().UTC().Format(time.RFC3339), repo, checkin)
	return err
}

func (d *DB) AckAllGateBypasses(repo string) (int, error) {
	res, err := d.db.Exec(`UPDATE gate_bypass SET acked = ? WHERE repo = ? AND acked = ''`,
		time.Now().UTC().Format(time.RFC3339), repo)
	if err != nil {
		return 0, err
	}
	n, _ := res.RowsAffected()
	return int(n), nil
}

func (d *DB) gateRows(where string, args ...any) ([]GateBypass, error) {
	rows, err := d.db.Query(`SELECT repo, branch, checkin, seen, who, acked FROM gate_bypass `+where, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var out []GateBypass
	for rows.Next() {
		var g GateBypass
		if err := rows.Scan(&g.Repo, &g.Branch, &g.Checkin, &g.Seen, &g.Who, &g.Acked); err != nil {
			return nil, err
		}
		out = append(out, g)
	}
	return out, rows.Err()
}