Changelog

The corpus, release by release

Currently 69 Postgres rules; the rule corpus is versioned separately from these releases and stands at v0.9.1. Every entry below shipped with fixtures both directions, see the rule reference for the live list.

v0.15.0

SurrealDB in beta

  • SurrealDB support, in beta: the SR corpus, 31 static rules over the official SurrealQL grammar, runs in the CLI behind --engine=surrealdb on .surql migrations. It covers the schema changes SurrealDB accepts without checking the records already stored (a required TYPE, a new ASSERT, READONLY, a switch to SCHEMAFULL or TYPE RELATION, REMOVE FIELD), DEFINE TABLE OVERWRITE resetting permissions to NONE, DROP tables that keep no writes, whole-table UPDATE, DELETE and FOR loops, unclosed and nested transactions, index builds without CONCURRENTLY, duplicate indexes, and syntax SurrealDB 2 and 3 removed.
  • Credentials in SurrealQL are rules of the corpus: plaintext DEFINE USER passwords, JWT signing keys, literal passwords passed to crypto::argon2::generate, root OWNER users and PERMISSIONS FULL on writes. Every finding on such a statement carries it with the secret masked, and the credential rules check runs on every engine (BC003, BC004) run here too.
  • Every "SurrealDB does this" claim is re-proven against a real SurrealDB 3 in the test suite, which also checks that every fixture parses there. A surrealdb-migrations project is detected and its migrations checked without a flag; the MCP check tool takes engine "surrealdb". CLI only, like SQLite: no live-schema context, no hosted checks, not governed by team policy yet.
v0.14.0

SQLite moves to beta

  • The SQLite corpus is out of alpha: 35 rules covering the ADD COLUMN forms SQLite refuses, the whole-table rewrite DROP COLUMN performs, the twelve-step rebuild and the pragmas around it, dependent views and triggers, transactions, index hygiene and the performance traps of rowid tables and journal modes. Every "SQLite refuses this" claim is proven against a real SQLite in the test suite, and the credential rules run under --engine=sqlite as well.
  • Still CLI only: no live-schema context, no hosted checks, not governed by team policy. Beta means the corpus is complete enough to rely on for what it covers; the rule pages say exactly what that is.
  • A stored connection can carry a database label, free text naming the database it stands in for, edited in place in the Database column of the Connections page, with the labels already in use suggested as you type. Plans count stored connections only; nothing counts labels.
v0.13.0

The MCP server and the skills library; the audit log grows up

  • The verifier as a Model Context Protocol server. npx bolvrk mcp serves check, secrets and explain over stdio on every plan, with the rules the CLI bundles; the hosted server at bolvrk.com/api/mcp adds the full corpus, stored connections, the team policy and the run log for Team and above, with tools check, policy, rules and rule. Every tool result carries the findings JSON contract.
  • A skills library in the public repository: SKILL.md files that tell an agent when to check a migration, scan output for secrets, or explain a backfill.
  • An org admin role. The person who creates a team is its org admin; only org admins invite people, change roles, delete the team or touch billing (the billing role keeps its page). Members keep every other write. Existing teams got their earliest member promoted.
  • The audit log records sign-in, sign-out, failed sign-in and refused writes, and every team token records where it was last used, its first use and every new address are audit events. A test keeps every mutating route audited.
  • bolvrk secrets - scans piped output: a deploy log, CI output, a git diff. The run log filters by database class, rule category and rule, and every rule chip opens the rule reference.
v0.12.0

SQLite in alpha, and a database filter

  • SQLite support, in alpha: the SL corpus, static rules over a real SQLite grammar, runs in the CLI behind --engine=sqlite. The ADD COLUMN forms SQLite refuses, the whole-table rewrite DROP COLUMN performs, the twelve-step table rebuild and the pragmas around it, unbounded writes, VACUUM and REINDEX, index builds under the single write lock, and the rowid traps. Every "SQLite refuses this" claim is re-proven against a real SQLite in the test suite. CLI only for now: no --db, no --remote, not on any plan, and silence is not yet a guarantee.
  • The rule reference and the Policy page filter by database, with the database mark on every rule. SQLite rules are listed on the Policy page for reference and paused there, the hosted service does not run them yet.
  • Every SQLite rule has its own page, in the same shape as the Postgres rules. The credential rules check runs on Postgres (BC003, BC004) run under --engine=sqlite as well, anchored to the statement and masked.
v0.11.0

Audit log, roles, retention, repository ignores

  • Audit log: every team-level action, policy edits, token rotation, connections added or removed, members and roles, plan changes, recorded with its actor and browsable from the dashboard.
  • Two more roles: viewer sees everything and changes nothing; billing manages the subscription and nothing else. Invites carry a role.
  • Retention and export: set how long the run log is kept, and export checks and findings as CSV or JSON at any time.
  • Repository ignores: an ignore map in bolvrk.json silences a rule for the whole repository, reason required. The CLI and the Action send it with hosted checks, honored on Startup and above; --ignore=RULE does the same for one run. Every report states how many findings it hid.
  • The run log and Insights filter by repository.
  • Read-only role warning: the CLI and the Connections page flag a connection whose role is a superuser, owns tables or holds a write grant. Bolvrk reads catalogs only, so the read-only role from the setup guide is all it needs.
  • Output copy says what actually ran: a clean result reads "no findings (no rule fired)", and a Free-plan hosted check ends with how many rules were skipped rather than listing them.
  • Startup is now $29 a month. Prices exclude VAT, stated once under the pricing grid.
v0.10.0

Team tier and Insights windows

  • A new plan between Startup and Scale: Team, $99 a month flat per team. The full corpus and live-schema context of Startup, plus team policy, the block threshold and per-rule overrides, applied to every connected check: CI, bolvrk check --remote and the API alike, and 8 stored connections.
  • Insights now look back over a window set by the plan: 30 days on Startup, a year on Team, unlimited on Scale. A window over the run log, never a deletion, the run log is kept in full on every plan.
  • AI migration review is removed. Bolvrk runs no model: no model output can pass or fail a check, and the verdict is the deterministic corpus alone. Bring your own AI against bolvrk check --json as before.
  • Checks remain unmetered on every plan, Free included. Paid plans buy scale and governance, connections, team policy and the Insights window, never a check count.
v0.9.0

The credential corpus: no secret reaches the repo

  • A new rule family, BC, for credentials written into a migration: a role created or altered with a plaintext password (BC001; an md5 verifier is a warning, a SCRAM verifier stays silent), a foreign server, user mapping or subscription carrying an embedded credential (BC002), a connection string with the password inline in any string literal (BC003), a vendor-format API key, JWT or PEM private key in any literal (BC004), and a secret-named column given a literal value (BC005).
  • Published formats only, never entropy: sk_live_, AKIA, ghp_, xoxb-, -----BEGIN PRIVATE KEY----- and friends fire; a uuid, a bcrypt hash, a placeholder or an empty string stays silent.
  • Every finding masks the value. When a BC rule fires on a statement, the engine redacts the secret in every finding on that statement, the report, the PR comment and the run log never repeat it.
  • New command: bolvrk secrets runs the same credential rules over any file, .env, YAML, JSON, source, shell, line by line, with a text-only rule for secret-named settings assigned a literal (BC006). Same findings contract, same policy overrides, same SARIF output. Always local: the scanner has no remote mode by design.
  • Suppression works the same way: bolvrk-ignore BC006: reason on the line or the line above, in any comment syntax, reason required.
v0.8.0

The performance corpus: indexing and query health

  • A new rule family, BP, for migrations that work and then quietly slow you down. Advisory by default: notes never block CI unless your policy says so.
  • Eleven rules to start: redundant indexes covered by a wider prefix (BP001), indexes led by a boolean or near-constant column (BP002), B-tree on jsonb, array, or tsvector columns (BP003), DROP INDEX removing the only index covering a foreign key (BP004), one more index on a hot table already carrying many (BP005), composite indexes led by a range column ahead of an equality column (BP006), partial or expression indexes the migration's own queries cannot use (BP007), backfills filtering a large table on columns no index leads with (BP008), column statistics disabled with SET STATISTICS 0 (BP009), autovacuum scale factors raised past the point of usefulness (BP010), and DROP INDEX on an index the planner is demonstrably using (BP011).
  • Connection health: stored connections are reached on a schedule and on every use; the Connections page shows the last result, and a check page warns when the connection its live context came from is unreachable, removed, or has not been reached in a day.
  • SARIF export: bolvrk check --format=sarif and the GitHub Action's sarif-file input write a SARIF 2.1.0 log with every rule's description and fix, so findings appear in GitHub code scanning next to the PR comment.
  • Set-ordering rules: a constraint added NOT VALID with no later VALIDATE (BS001), and a migration naming a column an earlier one dropped or renamed (BS002). They read the whole set, locally, through --remote, and on pull requests, and stay silent when only one file is visible.
  • Multi-file awareness: when several files are checked together, each one sees the tables, column types, indexes and foreign keys the earlier files declared, so an index on a boolean column created two migrations ago is judged correctly. Structure only; size and traffic still come from a connected database.
  • CLI workflow parity: check many files or globs at once (or stdin), keep defaults in bolvrk.json, silence one finding with -- bolvrk-ignore RULE: reason directly above the statement (reason required, every attempt recorded in the report), and run bolvrk policy pull so local runs block on exactly what CI blocks on, the same policy function now lives in the engine.
  • New command: bolvrk explain runs the file's own queries through EXPLAIN, read-only, never executed, against your shadow database and reports sequential scans of large tables, nested loops over sequential scans, and large sorts, in the same findings format as check.
  • Three of those read the migration's own UPDATE, DELETE, and INSERT ... SELECT clauses as evidence, never guessing at application queries. No query in the file, no finding.
  • The live-schema snapshot now carries index metadata (access method, partial and expression flags, validity, size, scan counts) and column statistics where the read role may see them, still structure only, never rows.
v0.7.0

The corpus reaches 50: operations out of schema history

  • Five new rules: unbounded INSERT ... SELECT backfills (BV046), timeout guards disabled with SET ... = 0 (BV047), ALTER SYSTEM in a migration (BV048), row-level security switched off on a live table (BV049), and write privileges granted to PUBLIC (BV050).
  • A zero-valued lock_timeout no longer counts as a guard, zero means "wait forever", the opposite of protection.
  • Fewer false alarms: DETACH PARTITION CONCURRENTLY, standalone VALIDATE CONSTRAINT, and DROP INDEX CONCURRENTLY hold only weak locks and no longer trip the lock_timeout advisory.
v0.6.1

Every rule tells you what to do instead

  • All 45 rules now ship remediation guidance, a "do this instead" description and a corrected example, validated against the checker itself.
  • Rule documentation pages redesigned around the fix: what fires, why it is dangerous, and the safe pattern side by side.
  • A 34-case near-miss battery pins down safe lookalikes: statements that resemble dangerous ones and must stay silent.
v0.6.0

Hot-table awareness and database-wide REINDEX

  • Tier-2 checks now read table activity (pg_stat_user_tables): lock-heavy operations escalate to critical on tables under heavy sustained write traffic, not just large ones.
  • BV045: REINDEX SYSTEM / REINDEX DATABASE: a database-wide rebuild is a scope failure in a migration; system catalog indexes can never rebuild concurrently.
  • Non-concurrent index creation (BV003) no longer goes silent on small tables with heavy write traffic.
v0.5.0

The corpus reaches 44 rules

  • Twenty-one new rules across rewrite traps, destructive operations, lock hygiene, replication configuration, and column-type advisories.
  • New "note" severity: this will work, and then likely regress performance. Advisories for humans, and for any AI loop iterating against the checker.
  • Every rule now carries a minimal firing example; the docs and this site derive their rule lists straight from the engine.
v0.3.0

Schema-aware refinements

  • Foreign keys without a covering index (BV017), escalates using the live index list.
  • Tables created without a primary key (BV018).
  • Severity taxonomy ratified: critical / warning / note.
v0.1.0

First public corpus

  • Sixteen rules covering the classics: non-concurrent indexes, NOT NULL without default, inline constraint validation, type-change rewrites, unbounded writes.
  • Two-tier design: static parse-tree analysis everywhere, live-schema refinement when a shadow database is connected.
  • Fixtures in both directions for every rule, validated against Postgres 13–17 in CI.