Skip to content

feat: v1 product surface: policy, fleet, gray-box evidence, server kit, fleet service - #21

Merged
patsypppe merged 12 commits into
mainfrom
feat/v1-product
Oct 22, 2026
Merged

patsypppe merged 12 commits into
mainfrom
feat/v1-product

Conversation

@patsypppe

Copy link
Copy Markdown
Owner

Summary

  • Operating it: sentinel.toml with tested precedence, waivers with required expiry, severity overrides that only tighten, baselines, snapshot/diff rug-pull detection, fleet scans, six report formats, concurrent rules.
  • Gray-box evidence settles the five unverifiable MUSTs; absence of evidence is never a pass. Commands run with shell=False; --no-exec disables them.
  • 17 new rules (x-mcp-header, tool names, MRTR, capabilities, and beyond-spec injection, wildcard scopes, drift, TLS, latency) and a partial fixture.
  • Distribution: Docker image, Action inputs, GitLab template, pre-commit hooks, cosign + SBOM in the release workflow.
  • mcp/: the reusable Go kit extracted from the broker, with server.New and a one-tool example the build scans.
  • fleet/: sentinel-server (ingest, history, posture, drift, expiring waivers, dashboard) and scan --publish.
  • Docs (USING, FLEET, KIT, CITATIONS), changelog, regenerated measurements, version 0.4.0.

Not verified / known limits

  • No GitHub Actions workflow has run on this branch (CI, Action, release signing).
  • Broker and fleet Docker images were not built (Docker Hub rate limit); the scanner image was built and run locally.
  • 11 new MCP/ rules cite a spec page, not an anchor; the spec host was unreachable. See docs/CITATIONS.md.
  • handles/mrtr/Postgres audit still carry pgx in the same packages; the storage split is follow-up.
  • OTLP exporter not wired; compose e2e not run.

Test plan

  • make check: golangci-lint, go vet/test across broker, mcp, fleet; ruff, mypy; 391 Python tests
  • Fleet store contract against local Postgres 16 (integration tag)
  • Kit example built, served and scanned with --gate must and --gate security
  • Real server binary + real CLI --publish round trip
  • CI on GitHub
  • make test-e2e against compose

Generated by Claude Code

claude added 12 commits October 21, 2026 18:33
sentinel.toml with a tested precedence matrix (CLI > env > file > extends >
default), severity overrides that can only tighten, waivers whose expiry is
required and whose malformed dates are errors, semantic finding fingerprints,
baselines that show what was fixed, snapshot/diff rug-pull detection, and
markdown, junit, html, JSON schema v2 and SARIF with suppressions. Rules now
run concurrently, each on its own probe.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pdv7R172x4XFq6AxwmmBBF
Fleet scanning with per-target credentials, gates and waivers and a rollup.
New rules: x-mcp-header constraints, tool-name hygiene, tools capability
agreement, tampered requestState, input-required shape and declared
capabilities. Beyond-spec: tool-description injection, wildcard scopes,
manifest drift, TLS posture, latency budget. A third fixture exercises every
NOT_APPLICABLE branch. Unit tests run in parallel: 94s to 28s.

Citations for the new rules are page-level; the spec host was unreachable from
this environment, so no unverified anchor was added.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pdv7R172x4XFq6AxwmmBBF
A wrong-audience token, a second principal, an egress capture, an effect
counter and an audit verifier each settle one INDETERMINATE rule, and the
verdict names the evidence in verifiedBy. Absence of evidence is never a pass.
Commands come only from the config file, run with shell=False, a timeout and a
minimal environment; --no-exec disables them. A fixture with one knob per
defect proves each kind catches its own defect and no other.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pdv7R172x4XFq6AxwmmBBF
The Action now takes a config, baseline, snapshot, fleet file and --no-exec, writes
a Markdown job summary and SARIF from one scan (--also), and is tested by
executing its scan step. Releases push a multi-arch image, sign the image and the
wheel keylessly with cosign, and attach a CycloneDX SBOM.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pdv7R172x4XFq6AxwmmBBF
…a runnable example

broker/internal/{envelope,canonical,registry,authz,transport,handles,mrtr,audit,store}
move to a module of their own at github.com/patsypppe/sentinel/mcp, so a stranger can
import them. transport now takes a two-field Settings instead of the broker's
configuration; the broker maps onto it. server.New wires the default pipeline in one
call and refuses a server that has not said how it identifies callers. mcp/example is
one tool, no database, and a test builds it, serves it and requires the harness's
--gate must and --gate security to pass against it, so the example cannot rot.

Not done: handles, mrtr and audit still carry their pgx implementations in the same
packages; splitting them behind storage interfaces into mcp/postgres is follow-up.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pdv7R172x4XFq6AxwmmBBF
A Go service that ingests schema-2 reports, keeps their history in memory or Postgres
behind one store contract, and computes what one scan cannot: failing findings per day,
how long each finding has been open (restarting when a fixed one regresses), time to
remediation per rule, manifest drift, and waivers about to lapse over findings that
still fail. Ingest and read are separate credentials; a server with no ingest token
will not start; the dashboard is server-rendered with a strict CSP and no external
request. sentinel scan --publish sends the report and never changes the exit code.

Also: baseline create/prune take --target-name, since a finding's identity includes it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pdv7R172x4XFq6AxwmmBBF
….4.0

USING.md covers baselines, waivers, severity overrides, drift, gray-box evidence,
formats and CI wiring; FLEET.md the fleet scan and sentinel-server; KIT.md the Go kit.
Examples are loaded by tests so they cannot drift. CITATIONS.md lists the eleven rules
that cite a page rather than an anchor, and a test keeps it equal to the catalog.

MEASUREMENTS.md regenerated: recall 52/52, scan wall-clock measured against a fixture in
its own process (the in-process figure was GIL contention, not scan cost).

CI: the Python job now has Go and requires it, so the Go-backed tests fail instead of
skipping.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pdv7R172x4XFq6AxwmmBBF
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pdv7R172x4XFq6AxwmmBBF
Rich renders --help differently on a CI runner, so parsing it found no flags there.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pdv7R172x4XFq6AxwmmBBF
@patsypppe
patsypppe merged commit 0903f5b into main Oct 22, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants