Files
tech-log-backend/docs/superpowers/specs/2026-07-25-harness-free-quality-security-ci-design.md
T

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

  1. Copy the candidate files unchanged. Rejected because they target master, refer to missing supply-chain scripts/jobs, and describe obsolete branch ownership.
  2. 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.
  3. 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.