Conformance tests

A broker built on unYOLO inherits the control plane but not a guarantee that it wired it up correctly. The conformance suite exists to catch the difference. broker/conformance runs the shared contract against your real HTTP handlers, and every broker invokes it from its own tests.

Required proofs

Seven properties, taken from the shared contract:

  • The broker registers only its own provider vocabulary.
  • Valid requests go through unYOLO decisions rather than around them.
  • Malformed or unclassified requests fail closed before execution.
  • Deny overrides active grants.
  • Active grants match only the approved client, operation, target, attrs, duration, and use budget.
  • Audit output contains no secrets, request bodies, Git pack contents, command output, approval tokens, or upstream credential metadata.
  • Telegram callbacks cannot approve a different grant than the one displayed.

The second is the one that catches real mistakes. A provider handler that reaches its executor without passing through the decision path will pass every unit test you wrote for it and fail this.

The shared setup contract

Alongside the runtime behaviour, every broker is expected to test its installation surface:

  • install script platform selection and checksum handling
  • setup systemd --dry-run
  • setup systemd --no-start file rendering in temporary directories
  • service unit content, without starting real services
  • client config rendering, without printing secrets
  • authentication accepting valid clients and rejecting invalid ones
  • policy rejecting unknown operations, targets, attrs, and fields
  • deny overriding active grants
  • generated grants matching only what was approved
  • audit output containing no secrets

Telegram is covered by a fake Bot API server or a fake notifier. CI never sends real Telegram messages and never mutates real external repositories, so live provider tests stay explicit manual or staging checks.

Test doubles

operator/fake runs the production handler and store behaviour inside consumer tests, so a trusted host or plugin can be tested against real inbox semantics without a broker process. Checked-in wire examples live under operator/api/testdata.

The framework injects a clock into the grant store, so expiry, lease, and rate-window behaviour is testable without sleeping.

Failure drills

Correct behaviour under normal load is the easy half. unYOLO keeps deterministic drills beside the boundary they exercise, and a new broker should expect to be held to the same list:

Failure classRequired invariant
SQLite corruption or incompatible restoreStartup and restore fail closed without replacing current state.
Read-only or failed durable writeNo decision or notification transition is reported as committed.
Backward or forward wall clockLeases do not reopen authority and rate windows do not reset backward.
Provider timeout or ambiguous completionNo automatic mutation retry; authority retained only for reconciliation.
Crash before or during executionCommitted plans recover; unprovable outcomes fail explicitly.
Listener or service activation failureNo transport fallback; previous managed configuration restored.
Submission overloadNew work receives a stable 429 while replay, cancellation, approval, and readiness stay available.
Shutdown with a live parent contextOwned workers stop before SQLite closes.

Every drill asserts durable terminal state or rollback state rather than an HTTP status. Fixtures use bounded timeouts and synthetic local upstreams. The full matrix, with the test file that covers each row, is in failure drills.

Security verification

Beyond functional tests, the required verification is race tests, cursor and callback fuzzing, protocol schema drift tests, provider activation and execution tests, restart tests, secret scanning, dependency vulnerability scanning, and the adversarial fixtures in the Operator V1 conformance suite.

Mutation targets stay broker-local and checked in, but they are disabled and non-blocking until an explicit decision re-enables them.

Quality and release tooling

unyolo-coverage and unyolo-release provide the common quality and release behaviour, so a new broker gets the same coverage gate and release asset conventions as the shipped three.

The release shape is fixed: four platform archives plus checksums.txt, each archive containing the binary, README.md, and LICENSE, and both <broker> --version and <broker> version supported.

CI in this repository

For reference, the CI job for the shipped brokers runs go mod tidy with a clean-diff check, go mod verify, a gofmt check, architecture and generated-code and SQL checks, the protocol test, go vet, the race-enabled suite, a coverage gate, golangci-lint, govulncheck, gitleaks with redaction, and the Slophammer complexity and duplication gates. A separate macOS job runs the race-enabled suite on Darwin.

The architecture check is the one specific to this framework: it fails a build where shared code imports a provider, or where one provider imports another.

Esc

Type to search across every documentation page.