5.7 KiB
Harness-Free Quality and Security CI Design
- Date: 2026-07-25
- Status: Approved Mode B reconstruction
- Scope: Repository-internal quality, dependency-vulnerability, and link-check controls
Decision and provenance
Mode B reconstructs observable CI contracts from the current Gradle build, active documentation,
and the incomplete /home/donghyeon/dev/ca-tmpl checkout. The candidate checkout is evidence, not
an authoritative or byte-identical restoration source. Its useful policy is adapted to the current
main branch and current tasks; stale master, feature-branch ownership, and absent workflow
claims are removed.
.github/workflows/ is the canonical workflow path. No .gitea/workflows shadow is created. The
origin is Gitea, but server-side Actions is externally disabled, so these files define repository
controls without claiming that remote jobs currently execute.
Every external uses: reference is pinned to a verified 40-character commit SHA. Its immutable
release tag remains beside the SHA as an inline review label; moving major-version tags are not an
execution authority.
Scope boundary
This slice owns:
- pinned Java tool evidence and text/binary normalization;
- structured Trivy suppression governance and CODEOWNERS review surfaces;
- the quality-gate matrix and its drift verifier;
- quality, filesystem vulnerability, and documentation-link workflows;
- human-readable dependency severity, suppression, network, and forge-compatibility policy.
The development harness remains excluded: no .harness, .agents, .claude, or .codex
runtime is reconstructed. Build/release supply-chain, tag release, image scanning, signing,
provenance, SBOM, retention, and Docker root-context work belongs to the later Phase A2 slice and
is not represented as a present workflow job.
Considered approaches
- Copy the candidate files unchanged. Rejected because they target
master, refer to missing supply-chain scripts/jobs, and describe obsolete branch ownership. - Reconstruct a minimal current control plane from repository evidence. Selected because every gate can be checked against a present Gradle task, test, script, or workflow job.
- Merge all checks into one workflow. Rejected because GitHub-only dependency APIs need forge guards, scheduled vulnerability scans have different triggers, and link checks are path-scoped.
Components and gate flow
ci-quality-gates.yml runs three required jobs: the aggregate Gradle quality suite, the sample-off
axis, and gate-matrix lint. Before Java setup or Gradle, the quality job requires
docs/security/public-paths-snapshot.txt to be committed and non-empty. The worktree now contains
the canonical baseline for /api/healthcheck; because agents do not stage or commit, a human must
track and commit it before CI's git ls-files precondition can pass. This prevents
verifyPublicPathSnapshot from creating a first-run baseline inside CI and passing without
comparison.
release-gate uses if: always() and accepts only success from those three jobs; the advisory
quarantine job is deliberately outside its needs.
The quality aggregate runs check, verifyPublicPathSnapshot, and verifyDependencyLocks
explicitly. check already pulls in Clean Architecture dependency enforcement, environment/readme
drift checks, Trivy-ignore governance, format/static analysis, normal tests, and quarantine sunset.
dependency-vulnerability.yml keeps GitHub Dependency Graph operations behind
github.server_url == 'https://github.com'. Platform-neutral trivy-fs runs for PR, main push,
daily schedule, and manual dispatch. Trivy and jq install into ${RUNNER_TEMP} and expose their
directories through ${GITHUB_PATH}. Every Trivy scan names .trivyignore.yaml; High/Critical and
KEV matches block, while Medium/Low only report. The KEV gate first rejects blank metadata,
non-positive/non-integral or mismatched counts, empty arrays, invalid CVE identifiers, and duplicate
identifiers. It separately rejects malformed/empty Trivy JSON before extracting candidate IDs.
Dependency review reports through its check only and does not request permission to write a PR
summary comment. Vulnerability DB, tool release, malformed/empty KEV or Trivy data, and KEV feed
network failures remain blocking unless internal mirrors are configured.
link-check.yml is path-scoped for PR and main push, and remains manually runnable.
Drift verification and failure behavior
.github/ci-gate-matrix.yml lists only current mechanisms/jobs. The verifier resolves the
repository root from its own physical location, rejects incomplete/duplicate records, and checks
referenced Gradle custom tasks, plugins, contract-test files, workflow files, and job IDs.
Delegated-pending is supported only when a row is explicitly marked; no absent supply-chain job is
invented in this slice.
The CI release fan-in fails for failed, cancelled, or unexpectedly skipped required jobs. Trivy's KEV feed cross-check is fail-closed. GitHub-only jobs may skip by their explicit forge/event conditions and are not dependencies of the quality release fan-in.
Verification
Acceptance requires the prescribed RED for the absent .trivyignore.yaml, GREEN
verifyTrivyignore, proof that the snapshot precondition rejects missing, empty, or untracked
baselines, and a human-tracked canonical snapshot for CI. It also requires strict synthetic KEV
catalog negative/positive cases, shell syntax and matrix verification, workflow YAML/static checks,
evidence that main is the only active branch trigger, Trivy ignorefile coverage, exact release
fan-in, absence of harness/Gitea shadow workflows, git diff --check, and reviewed working-tree
status. Network Trivy scans are intentionally not run locally.