Conventions this system depends on, written as semgrep rules that fail CI — 5 rules, read from the rule file when this site is built. A convention that lives only in a reviewer's memory is not enforced.
Rules specific to this repository. The community rulesets cover the generic classes of bug. These five encode invariants this codebase actually depends on, three of which were defects here before they were rules. A convention that lives only in a reviewer's memory is not enforced.
R-01
Broad exception handler
A catch-all @ExceptionHandler in a class that does not extend ResponseEntityExceptionHandler swallows Spring MVC's own exceptions, so an unmapped path returns 500 instead of 404 and ordinary client mistakes burn the error budget. Extend ResponseEntityExceptionHandler, which maps those to their real status codes and leaves the catch-all for genuinely unexpected failures.
Secrets are delivered as mounted files and read through Spring's configtree:, never from the environment. Environment variables are inherited by every child process, readable through /proc, and captured verbatim in crash dumps and container inspect output. See docs/security.md.
Rule
blueprint-no-secrets-from-environmentERROR
Applies to
/services/*/src/main/**
yaml
pattern: System.getenv(...)
R-03
Readiness must not include kafka
Kafka must not gate readiness. The transactional outbox absorbs a broker outage, so pulling the service out of the load balancer when the broker is down converts a degraded async path into a full outage. See docs/adr/0007-readiness-excludes-kafka.md.
Migrations must keep the previous release working: they add, and never drop, rename, retype, or add NOT NULL without a default in the same release as the code that stops needing it. Split the change into expand and contract steps across releases. A contract step that is safe now is marked with a nosemgrep comment and the reason on the line before it. See docs/runbooks/zero-downtime-migration.md.
Pass credentials to containers as a file reference (*_PASSWORD_FILE) pointing at a mounted secret, not as a plaintext environment variable.
Rule
blueprint-no-plaintext-password-envERROR
Applies to
/deploy/**/*.yml · /deploy/**/*.yaml
yaml
pattern-regex: ^\s+[A-Z_]*PASSWORD:\s*\S
The security workflow runs these alongside the community p/java, p/secrets and
p/dockerfile rulesets, with --error, so a match fails the build. Each rule was proven to fire
against deliberately bad input before it was trusted to pass good input.