You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-**Bun version is single-sourced** via `.tool-versions` (`bun 1.3.12`). All workflows use `oven-sh/setup-bun@v2` with `bun-version-file: .tool-versions`.
104
104
-**`audit:ci` (`scripts/audit-ci.ts`)** wraps `bun audit --json` to gate on severity: blocks on high+critical, warns on moderate+low, with an inline `IGNORED` GHSA allowlist (each entry must carry an `expires` date). Required because `bun audit` exits 1 on **any** finding regardless of `--audit-level`.
@@ -151,6 +151,7 @@ The `docs.yml` `pull_request:` trigger has no `paths:` filter, so these gates ru
151
151
152
152
## Recent Changes
153
153
154
+
- 20260502-supply-chain-attestations: `.github/workflows/docker-build.yml` now publishes SLSA v1 provenance + SBOM attestations on every release tag. The build step sets `provenance: mode=max` + `sbom: true` (overriding `docker/build-push-action`'s default of off-when-`push-by-digest=true`), so BuildKit emits per-arch attestation manifests that survive `imagetools create` via the index-digest references. The merge job additionally runs `anchore/sbom-action` + `actions/attest-build-provenance` + `actions/attest-sbom` to publish Sigstore-signed CycloneDX SBOM and SLSA provenance bound to the merged manifest digest, surfaced via the GitHub Attestations API and Docker Hub's "Build attestations" badge. The merge job carries scoped `id-token: write` + `attestations: write`; build/scan stay read-only via the new top-level `attestations: read`. The scan job calls `gh attestation verify` for both predicate types (`https://slsa.dev/provenance/v1` + `https://cyclonedx.org/bom`) before Trivy — a hard regression gate that fails the workflow if either attestation is silently dropped by a future refactor. Consumer-side `gh attestation verify` and `docker buildx imagetools inspect` recipes documented in `docs/operate/deployment.md` (Verifying image attestations) and the registry / API storage matrix is in `docs/operate/observability.md` (Supply-chain attestations). Closes #58.
154
155
- 20260416-pipeline-redesign: CI/CD pipeline restructured for single-responsibility separation. Replaced `push.yml` + `semantic-release.yml` (which entangled lint-and-test, dev release, and docker build) with four single-purpose workflows: `ci.yml` (quality gates only), `dev-release.yml` (feature-branch orchestrator: ci → semrel-dev → docker), `release.yml` (manual prod orchestrator: ci → semrel-prod → docker), and a rewritten reusable `docker-build.yml` (matrix split-and-merge native amd64+arm64, no QEMU). Bun version single-sourced via `.tool-versions` (resolved drift between 1.3.8 in push.yml/semrel.yml and 1.3.12 in docker-build.yml/Dockerfile/package.json). `audit:ci` script (`scripts/audit-ci.ts`) wraps `bun audit --json` to restore severity-based gating (block high+critical, warn moderate+low, time-boxed GHSA allowlist) — `bun audit` itself exits 1 on any finding regardless of `--audit-level`. Single env-switched `release.config.mjs` (`SEMREL_CHANNEL=dev|prod`) replaces the file-swap hack. Prod release is now manual (`gh workflow run release.yml`); push-to-main only runs `ci.yml`. Job-spawner pod entrypoint moved from `src/k8s/job-entrypoint.ts` (TS source absent from production image) to `dist/k8s/job-entrypoint.js` (built by `scripts/build.ts`) — fixes a latent isolated-job-target bug. Defense-in-depth: every dynamic workflow input passes through `env:` before reaching any `run:` block.
155
156
- 20260410-164348-scheduled-research-workflow: Config-only (no `src/` changes) — adds `.github/workflows/research.yml` invoking `anthropics/claude-code-action@v1` once daily (`cron: "0 5 * * *"` = 3pm AEST / 4pm AEDT) and on `workflow_dispatch` with an optional `focus_area` input. Hard 1-hour wall-clock budget (`timeout-minutes: 60`), at most one labelled GitHub issue per run, agent restricted to read + `WebSearch`/`WebFetch` + `gh issue/label create`, two repo secrets (`CLAUDE_CODE_OAUTH_TOKEN`, `PERSONAL_ACCESS_TOKEN`), `permissions: contents:read + issues:write + id-token:write`, `concurrency: research-workflow / cancel-in-progress: false`. 10 fixed focus areas mapped to `src/` subsystems. Two-label scheme (`research` + `area: <name>`). Inherits documented workarounds from `chrisleekr/personal-claw` `research.yml` (`allowed_bots: '*'`, `--disallowedTools ""`, PAT instead of OIDC). **Defense-in-depth against workflow injection**: every GitHub-context value (including `github.event.inputs.focus_area`) is passed via `env:` blocks rather than interpolated into `run:` scripts; the user-supplied `focus_area` is additionally validated against `^[a-z][a-z0-9-]{0,31}$` BEFORE being used (rejected values fall back to a random pick and log only their length, never the value itself) — satisfies Constitution Principle IV. **Failure surfacing**: relies on GitHub Actions' built-in workflow-failure email; no custom alerting. **Cost observability**: per Constitution Principle VI bullet 2, `claude-code-action`'s own per-turn cost output is captured by GitHub Actions stdout and retrieved post-mortem via `gh run view <run-id> --log | grep -iE 'cost|tokens|duration|usage'` (see `specs/.../research.md` §19 and `quickstart.md` Day-2 ops). **Test coverage gap** (Constitution Principle V) justified in `plan.md` Complexity Tracking; mitigated via `actionlint` static check + mandatory manual smoke test before merge (see `quickstart.md`).
156
157
- 20260409-081113-project-housekeeping: Housekeeping — test coverage raised to 90% per-file threshold (lines + functions; Bun's `coverageThreshold` is applied per-file, not aggregated), ESLint migrated to unified `typescript-eslint` with `strictTypeChecked` preset, CI security scanning added (`bun audit`, `trivy` container scan with blocking `exit-code: "1"`, `gitleaks` full-history scan with `fetch-depth: 0`), Docker HEALTHCHECK on `/healthz`, gitleaks pre-commit hook, retry.ts input validation (maxAttempts/initialDelayMs/maxDelayMs/backoffFactor all reject NaN/Infinity/below-min with descriptive errors), `package.json` security overrides converted to exact version pins.
0 commit comments