A command-line tool for validating structured technical specification documents (YAML or JSON) against versioned, Postgres-backed schemas.
Large engineering organisations often reach a point where specifications (hardware pin mappings, API contracts, configuration manifests, whatever the domain is) are authored as free-form YAML or JSON files. That's fast to write, but easy to get subtly wrong: a missing field, a typo in an enum value, a pin count outside the physically valid range. Catching these at review time, by a human reading the diff, doesn't scale once hundreds of engineers are authoring specs in parallel.
spec-lint turns a schema definition into an enforceable contract. Authors run one command before opening a review, and get a structured pass/fail report instead of relying on a reviewer to spot the error by eye.
$ spec-lint validate --schema pin-mapping --file examples/gpio-bank-b-invalid.yaml
Validation report: examples/gpio-bank-b-invalid.yaml
Schema: pin-mapping
--------------------------------------------------
[ERROR] pin_count: value 9000.0 outside allowed range [1.0, 4096.0]
[ERROR] voltage_domain: value 'VDD_12V' not in allowed set [VDD_1V8, VDD_3V3, VDD_5V0]
[WARNING] differential_pair_partner: required when 'is_differential' is present
--------------------------------------------------
2 error(s), 1 warning(s)
FAILED.
- Schemas are versioned and stored in PostgreSQL, not flat files.
See
schemas/ddl.sqlfor the table design. This means a document authored under schema v3 can still be validated correctly even after the schema has since moved to v5, and every validation run is logged for later analysis (e.g. "which fields fail most often across the whole org in the last 30 days"). - The validation engine (
SpecValidator) is decoupled from the CLI. The same logic that powersspec-lint validateon the command line could sit behind a thin HTTP layer for an API, or be called from a UI's "validate before submit" button, without duplicating any rules. - Constraints are data, not code. A schema is a list of declarative
constraints (
Required,Range,OneOf,DependsOn,Pattern,TypeOf), so new schema versions can be authored and published without touching the validator itself.
spec-lint/
├── build.sbt # SBT build definition
├── project/
│ ├── build.properties # SBT version pin
│ └── plugins.sbt # sbt-assembly for a runnable jar
├── schemas/
│ └── ddl.sql # PostgreSQL table design
├── src/
│ ├── main/scala/speclint/
│ │ ├── Main.scala # CLI entry point (scopt)
│ │ ├── model/Schema.scala # domain model: Schema, Constraint, ValidationResult
│ │ ├── validator/SpecValidator.scala # constraint-checking engine
│ │ └── db/SchemaRepository.scala # Postgres-backed schema storage & versioning
│ └── test/scala/speclint/
│ └── SpecValidatorSpec.scala # ScalaTest unit tests
└── examples/
├── pin-mapping-schema-v1.json # example schema definition
├── gpio-bank-a.yaml # example valid spec document
└── gpio-bank-b-invalid.yaml # example spec with intentional errors
sbt compile
sbt test
sbt "run validate --schema pin-mapping --file examples/gpio-bank-a.yaml"
sbt assembly # produces target/scala-2.13/spec-lint.jarRequires a PostgreSQL instance reachable via SPECLINT_DB_URL (defaults
to jdbc:postgresql://localhost:5432/speclint), with the schema in
schemas/ddl.sql applied first.
Scala 2.13 · SBT · PostgreSQL (JDBC) · circe (JSON/YAML parsing) · scopt (CLI argument parsing) · ScalaTest
Personal project, built to explore schema-driven validation tooling and relational schema design for an auditable, versioned rule system. Not production software; the constraint DSL is intentionally small and would need extending (nested object validation, cross-document references) for real-world specification formats.