Repository navigation
Releases: codeaiforge/git-native-sdlc-controls
Release list
v0.3.0
Adds a report over a period, and prebuilt binaries. sdlc-controls tier still assigns a risk tier to a change from its git diff and a declared component map, enforces that tier's controls in CI, and writes an evidence record for each run. Now sdlc-controls report reads a directory of those records back and writes one document an auditor or reviewer can read. It still needs no build tool and no network.
See what changed:
sdlc-controls report --evidence evidence/ --since 2026-07-01 --until 2026-09-30 --out report.md
sdlc-controls version
The report covers tiers and gate results, approvals, AI-assisted work, map drift, every exception with its reasons, and a standards view. It closes with a fixed statement of what it does not establish. Approvals keep verified and recorded, not verified in separate columns everywhere, and a record from 0.2.0 shows "not available" rather than a guess. Every file it does
not count is listed with the reason. The same records always produce the same bytes, and it is a report, not a gate: it exits 0 or 2, never 1. The worked example over the TraderX demo is examples/traderx/report.md, and docs/report.md says what each number means and does not mean. The standards view reads indicative ISO/IEC 27001:2022 and 42001:2023 mappings, embedded in the binary and written up row by row in docs/mappings/. They are indicative, not a certification or legal opinion. --mapping also takes a mapping file of your own, so an organisation's mapping never has to live in this repository.
Install: each release now carries a static binary for Linux, macOS and Windows on amd64 and arm64, built by GoReleaser from the tag, with a SHA-256 checksums.txt. Verify the archive before you run what is in it:
f=sdlc-controls_0.3.0_linux_amd64.tar.gz
grep " $f\$" checksums.txt | sha256sum -c - # macOS: shasum -a 256 -c -
or go install github.com/codeaiforge/git-native-sdlc-controls/cmd/sdlc-controls@v0.3.0.
Example jobs for GitLab CI, Jenkins and Azure DevOps are in docs/ci-adapters.md, and are not exercised in this repository's CI.
Not a purely additive upgrade: the binding moves to git-native-baseline@2 (ADR-0002). min_approvers is now met by approvers other than the author, at every tier. Under @1, a T3 change written by alice and approved by alice and bob met "2 approvers"; under @2 it has one. On GitHub and Gitea, which refuse self-approval, nothing changes in practice. A CI adapter
that passes the author in --approvers will see the gate fail where it passed before. binding_used tells the two apart. The text output changes in the binding line and the approver violation wording, and nowhere else.
The evidence record gains five additive fields: approvers_other_than_author, result.violated, author, head and self_escalated. A consumer no longer parses sentences to learn which control failed or which commit a record describes. evidence/0 stays at major 0, none of the new fields is required, and 0.2.0 records still validate. In a 0.2.0 record their absence means not recorded, never false. The component map gains a published schema, component-map/0, and provenance.generated_by, so a change to whatever generates a map self-escalates like a change to the map. The binary's only runtime dependency is still gopkg.in/yaml.v3.
Worth knowing before relying on it: the earlier limits are unchanged. Blast radius still comes from a hand-maintained map, not a computed dependency graph, so an undeclared high fan-in component is under-tiered. CAF-SDLC-011 still compares forge accounts, and it cannot tell who prompted the model. The report describes the records and nothing else. It cannot show that
branch protection or the named CI checks ran, and a change that never ran the gate is not in it. All of this is written up in docs/controls/ and docs/report.md.
Apache-2.0. Go 1.22+. Reference implementation, not a product.
v0.2.0
Adds a machine-readable form of the same gate. sdlc-controls tier still assigns a risk
tier to a change from its git diff and a declared component map, and enforces that tier's
controls in CI; now --format json emits the evidence record — the tier, why that tier,
what it required, and what the run actually verified — as a schema-validated document. A
new sdlc-controls binding prints the active policy the same way. Text output is unchanged
and remains the default. It still needs no build tool and no network.
See what changed:
sdlc-controls tier --base main --head HEAD --config config/components.yaml --format json
sdlc-controls binding --config config/components.yaml --format json
Each evidence record now carries its own schema_version, the tool name and version that produced it, a verification block separating what the run checked from what it only recorded, and a result block with the pass, exit code, and violations, so a consumer no longer has to observe a process exit code to know the gate blocked the change. The shapes are published as JSON Schema (Draft 2020-12) under schemas/, validated in CI against the JSON the tool actually emits, and versioned independently of the binary: a pinned copy of a schema keeps validating documents from a newer binary, because
every extension point leaves additionalProperties open. The tier scale and exit_code — the sets the algorithm itself fixes — stay closed. docs/contract.md and ADR-0001 write up the three version axes and the stability promise.
Additive upgrade: text output is byte-identical to v0.1.0 and a golden test enforces it, exit codes are unchanged in both formats, and --format json still prints its record on a failing gate. The JSON path serializes explicit wire DTOs rather than marshalling the engine struct, so a future rename inside the engine breaks a build instead of a consumer. The JSON Schema validator is a test-only dependency; the binary is still a single static artifact whose only runtime dependency is gopkg.in/yaml.v3.
Worth knowing before relying on it: the v0.1.0 limits are unchanged. Blast radius still comes from a hand-maintained map, not a computed dependency graph, so an undeclared high fan-in component is under-tiered. CAF-SDLC-011 still checks that two different forge accounts were involved — it cannot tell who prompted the model. Both are written up in docs/controls/. The published schemas are experimental at major 0 while the binary is 0.x: fields may be
added, and a removal or rename bumps the major to evidence/1.
Apache-2.0. Go 1.22+. Reference implementation, not a product.
v0.1.0
Assigns a risk tier to a change from its git diff and a declared component map, then enforces that tier's controls in CI: how many approvers, which checks, and an evidence record for each run. It needs no build tool and no network.
Run the demo:
make demo
It builds a throwaway TraderX-shaped repository and tiers four changes against examples/traderx/components.yaml, blocking two of them. Go and git are the only prerequisites.
Install:
go install github.com/codeaiforge/git-native-sdlc-controls/cmd/sdlc-controls@v0.1.0
On your own repository, copy config/components.example.yaml to config/components.yaml, describe your components in it, and tier a change:
sdlc-controls tier --base main --head HEAD --config config/components.yaml
Exit code 0 when the change meets its tier's controls, 1 when it does not, 2 on error. That
is the whole CI integration.
Worth knowing before relying on it: blast radius comes from a hand-maintained map, not a computed dependency graph, so an undeclared high fan-in component is under-tiered. CAF-SDLC-011 checks that two different forge accounts were involved — it cannot tell who prompted the model. Both limits are written up in docs/controls/.
The gate runs on this repository's own changes, on both Gitea and the GitHub mirror and the controls badge in the README is that history.
Apache-2.0. Go 1.22+. Reference implementation, not a product.