Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/scripts/next-version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# next-version.sh — compute THIS repo's next release tag for release-on-upstream.yml.
#
# Single source of truth for the version math, exercised in CI by release-selftest.yml so the
# release automation can't silently rot (guard #135.8). Prints "v<MAJOR>.<MINOR>.<PATCH>" to stdout.
# release automation cannot silently rot. Prints "v<MAJOR>.<MINOR>.<PATCH>" to stdout.
#
# Inputs (env, all optional):
# INPUT_VERSION explicit version to cut (leading "v" tolerated) -> used verbatim.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-selftest.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# CI self-test for the release-on-upstream version-compute logic (guard #135.8).
# CI self-test for the release-on-upstream version-compute logic.
# Runs the REAL .github/scripts/next-version.sh against synthetic repos and asserts it produces a
# valid next version for BOTH the has-prior-tag and no-prior-tag cases — WITHOUT publishing anything.
# This is what keeps the release automation from silently rotting before the fleet fan-out is armed.
Expand Down
38 changes: 19 additions & 19 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Contributing to store-postgres
# Contributing to store-mysql

Thanks for your interest in improving `store-postgres`. This document covers
how to build, test, and submit changes.
Thanks for your interest in improving `store-mysql`. This document covers how
to build, test, and submit changes.

## Ground rules

Expand All @@ -13,23 +13,22 @@ how to build, test, and submit changes.

## Development setup

`store-postgres` is a Rust `cdylib` plugin. You need a recent stable toolchain
`store-mysql` is a Rust `cdylib` plugin. You need a recent stable toolchain
(`rustup` recommended), and — until [busbarAI](https://github.com/GetBusbar/busbar)
ships publicly — a sibling checkout of it at `../busbarAI`, since this crate's
`Cargo.toml` points at busbar's crates as local path dependencies. See the
README's [Dependencies](README.md#dependencies) section for the exact layout;
CI checks out `GetBusbar/busbar` at the branch named in the reusable
`plugin-ci.yml` workflow reference in [`ci.yml`](.github/workflows/ci.yml).
`Cargo.toml` points at busbar's crates as local path dependencies. CI checks out
`GetBusbar/busbar` at the branch named in the reusable `plugin-ci.yml` workflow
reference in [`ci.yml`](.github/workflows/ci.yml).

The meaningful test coverage here needs a **live Postgres** — see the README's
[Tests need a real Postgres](README.md#tests-need-a-real-postgres) section.
Locally, `cargo test` skips that coverage cleanly if `BUSBAR_TEST_POSTGRES_URL`
is unset; set it to point at a real Postgres 16+ database to exercise it:
The meaningful test coverage here needs a **live MySQL** — see the README's
[Testing](README.md#testing) section. Locally, `cargo test` skips that coverage
cleanly if `BUSBAR_TEST_MYSQL_URL` is unset; set it to point at a real MySQL 8
database to exercise it:

```bash
export BUSBAR_TEST_POSTGRES_URL=postgres://busbar:busbar@localhost:5432/busbar_test
export BUSBAR_TEST_MYSQL_URL=mysql://busbar:busbar@127.0.0.1:3306/busbar_test
cargo build --release # cdylib
cargo test # unit tests + the e2e dlopen/live-Postgres test
cargo test # unit tests + the e2e dlopen/live-MySQL test
cargo clippy --all-targets -- -D warnings # lints must be clean
cargo fmt --all -- --check # format before committing
```
Expand All @@ -38,20 +37,21 @@ cargo fmt --all -- --check # format before committing

1. **`cargo fmt --all`** — code must be rustfmt-clean.
2. **`cargo clippy --all-targets -- -D warnings`** — no warnings.
3. **`cargo build && cargo test`** — green, including the live-Postgres
3. **`cargo build && cargo test`** — green, including the live-MySQL
end-to-end test in `tests/e2e.rs` (it hard-fails under `CI=1` rather than
silently skipping — never let that coverage quietly vanish).
4. Add or update tests for any behavior change.
5. Update documentation (`README.md`, doc comments) when you change behavior or config.

## Architecture

This repo is deliberately a thin adapter (`src/lib.rs`): it turns the engine's
JSON `open` config into a `PostgresStore` and hands the trait object to
The plugin crate (`store-mysql-plugin/`) is deliberately a thin adapter: it
turns the engine's JSON `open` config into a `MysqlStore` and hands the trait
object to
[`busbar-plugin-sdk`](https://github.com/GetBusbar/busbar/tree/main/crates/plugin-sdk),
which emits the C ABI symbols the loader resolves. All the SQL and schema logic
lives in the `busbar-store-postgres` library crate this plugin wraps, in the
`busbarAI` monorepo — most substantive changes belong there, not here.
lives in the `busbar-store-mysql` library crate in the `store-mysql/` directory
of THIS repository, so most substantive changes belong there.

## Commit & PR conventions

Expand Down
31 changes: 15 additions & 16 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ requests, or discussions.**
Instead, report privately through either channel:

- Email **security@getbusbar.com**, or
- GitHub's [private vulnerability reporting](https://github.com/GetBusbar/store-postgres/security/advisories/new)
- GitHub's [private vulnerability reporting](https://github.com/GetBusbar/store-mysql/security/advisories/new)
(the **Security** tab on this repository).

Please include:
Expand All @@ -20,38 +20,37 @@ Please include:

We aim to **acknowledge your report within 48 hours**, work with you on a fix, and
coordinate disclosure timing. Confirmed vulnerabilities are published as
[GitHub Security Advisories](https://github.com/GetBusbar/store-postgres/security/advisories),
[GitHub Security Advisories](https://github.com/GetBusbar/store-mysql/security/advisories),
through which we request and issue **CVE** identifiers. We credit reporters who wish to be
credited once a fix is released.

## Scope

`store-postgres` is a `kind: store` busbar plugin: it persists busbar's governance
data — virtual keys, budgets, and usage — in a shared Postgres database behind a
fleet of busbar nodes. Issues of particular interest include:
`store-mysql` is a `kind: store` busbar plugin: it persists busbar's governance
data — virtual keys, budgets, and usage — in a shared MySQL/MariaDB database
behind a fleet of busbar nodes. Issues of particular interest include:

- SQL injection or any path where request-derived data reaches a query
unparameterized.
- Connection-string (`url`) handling that could leak credentials into logs or
error strings.
- Identifier-comparison gaps: opaque handles (credential lookup handles, key
ids, group names) are stored with `ascii_bin` collation for byte-exact,
case-sensitive comparison — anything that reintroduces MySQL's default
case-insensitive matching on such a column is in scope.
- Cross-node data races that corrupt shared governance state (budgets, usage
ledgers) under concurrent writers.
- A boot-probe bypass: the plugin refuses to start when `CHECK` constraints are
unenforced or `sql_mode` is non-strict — anything that lets it run anyway and
silently accept unvalidated data is in scope.
- A load-time config error surfacing as a silent success instead of a clean
`Err` across the plugin ABI.

**Known, documented limitation, not a vulnerability report:** this build
connects `NoTls` (see the README's [Known limitations](README.md#known-limitations-documented-honestly-not-papered-over)
section) — run it over a trusted network segment, a local socket, or a
TLS-terminating proxy. This is a deployment consideration, not something we
consider a defect in the plugin itself, but we're glad to hear if you think
otherwise.

See busbar's own [threat model](https://github.com/GetBusbar/busbar/blob/main/THREAT_MODEL.md)
for the trust boundaries this plugin operates inside.

## Supported versions

This plugin is versioned independently of busbar (see the README's
[Versioning](README.md#versioning) section). Security fixes are applied to the
latest `main` and the most recent tagged release of **this repository**. Pin to a
tag for production use.
This plugin is versioned independently of busbar. Security fixes are applied to
the latest `main` and the most recent tagged release of **this repository**. Pin
to a tag for production use.
11 changes: 5 additions & 6 deletions store-mysql/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,8 @@ impl MysqlStore {
/// private scratch table instead of racing every other concurrently-running test's legitimate
/// writes to the real, shared `usage_windows`.
///
/// KNOWN, DOCUMENTED, NOT-YET-CLOSED GAP (found in `/codeaudit`, confirmed by two independent
/// adversarial design reviews — do not "fix" this with a lock; both reviews independently showed
/// a lock here is the wrong tool, see below): this UPDATE is UNSCOPED and assumes "a one-time
/// KNOWN, DOCUMENTED, NOT-YET-CLOSED GAP (a lock is the wrong tool here — see below for why
/// a `GET_LOCK`-based approach cannot close it): this UPDATE is UNSCOPED and assumes "a one-time
/// boot migration runs before any concurrent traffic exists" — true for a full-fleet restart, but
/// this store's own target topology is a ROLLING upgrade (README: multiple busbar nodes sharing
/// one MySQL server). In a rolling upgrade, some nodes are ALREADY LIVE on v2 — genuinely writing
Expand All @@ -290,13 +289,13 @@ impl MysqlStore {
/// predicate (`billable_requests = 0 AND requests > 0`) no longer matches it, and that row's
/// PRE-v2 historical `requests` are PERMANENTLY never reclassified as billable — a silent,
/// unrepairable billing undercount, i.e. exactly the `hydrate_budgets` bug class this migration
/// exists to close, reintroduced by a race in the migration itself. A `GET_LOCK`-based fix was
/// designed and rejected in review: it can only serialize NODES STILL BOOTING against each
/// exists to close, reintroduced by a race in the migration itself. A `GET_LOCK`-based fix
/// does not work: it can only serialize NODES STILL BOOTING against each
/// other (the backfill's own re-run is already idempotent, so that case was never actually
/// unsafe) — it does nothing for a node that is ALREADY LIVE and never touches this function at
/// all, which is the actual race. Closing this for real needs pre-v2 rows to be identifiable by
/// something live traffic cannot change (a captured `window_start`/time cutoff, or a per-row
/// provenance marker) — real redesign work, out of scope for this pass. OPERATIONAL MITIGATION
/// provenance marker) — a schema redesign this store does not yet have. OPERATIONAL MITIGATION
/// until that redesign lands: either pause the whole fleet briefly for a v1->v2 upgrade
/// specifically (not required for any OTHER version bump), or re-run this same predicate as a
/// manual reconciliation query after a rolling upgrade completes — safe to do since the
Expand Down
Loading