ci: upload combined code coverage artifact#3
Conversation
Reframe the MVP-only bootstrap checklist as a project-wide status doc covering all six roadmap phases. Adds spec coverage (15 specs), ADR coverage (66 ADRs with status + gap), phase status, and an ordered 15-item backlog with verifiable Done criteria so a fresh session can pick up "the next step" without rediscovering scope. Wires AGENTS.md to point at it as the first read. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a root vitest config that aggregates v8 coverage across every apps/* and packages/* project in one run. CI executes `pnpm test:coverage` after `pnpm verify` and uploads `coverage-final.json` + `lcov.info` as a GitHub artifact for downstream ingestion. The coverage config lives at `vitest.coverage.config.ts` (non-default name) so per-package `vitest run` invocations under Turbo don't auto-discover it and try to resolve workspace globs from a subpackage.
WalkthroughThis PR establishes test coverage reporting infrastructure and restructures project status tracking. A new Vitest coverage configuration with V8 reporting is added alongside npm scripts and CI integration to generate and archive coverage artifacts. The substantial Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
|
agent-paste PR preview is ready. API: https://agent-paste-api-pr-3.isaac-a46.workers.dev |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/ci.yml:
- Line 94: The workflow step currently uses the mutable tag
actions/upload-artifact@v7; replace that tag with the action's immutable full
40-character commit SHA (i.e., use actions/upload-artifact@<full-commit-sha>) to
pin the dependency. Locate the line containing the reference
"actions/upload-artifact@v7" in the CI workflow and update it to the exact
commit SHA from the upload-artifact repository release you intend to use,
ensuring the workflow references that specific hash instead of a mutable tag.
In `@docs/ops/project-status.md`:
- Line 5: The sentence in docs/ops/project-status.md is self-contradictory;
reword the header line "First doc a fresh agent reads after `AGENTS.md`,
`CONTEXT.md`, `docs/specs/README.md`, and `docs/adr/README.md`..." to remove the
contradiction—for example change it to "First doc a fresh agent should read
(after `AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, and
`docs/adr/README.md`)" or "The first document a fresh agent reads following
`AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, and `docs/adr/README.md`" so
the intent is clear; update the exact sentence in project-status.md accordingly.
- Around line 166-236: The Next Steps Backlog headings in
docs/ops/project-status.md (e.g., the "### 1. Wire `runCommand` and
`createOperationEvent` into mutation routes", "### 2. Enforce native rate-limit
bindings", etc. through item 15) are missing surrounding blank lines; edit the
Markdown so each "### N. ..." heading is preceded and followed by an empty line
(apply the same pattern used in the example fix for items 1–3) across all 15
items to satisfy markdownlint and ensure parser compatibility.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 77ee46e4-1c5e-4714-ac74-b8273af347c8
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (8)
.github/workflows/ci.ymlAGENTS.mddocs/ops/mvp-bootstrap-checklist.mddocs/ops/project-status.mddocs/specs/mvp.mdpackage.jsonpnpm-workspace.yamlvitest.coverage.config.ts
💤 Files with no reviewable changes (1)
- docs/ops/mvp-bootstrap-checklist.md
|
|
||
| - name: Upload coverage artifact | ||
| if: always() | ||
| uses: actions/upload-artifact@v7 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify workflow actions are SHA-pinned (40-hex) instead of mutable tags.
# Expected: no output. Any output indicates unpinned action references.
rg -nP '^\s*uses:\s*[^@\s]+@(?!(?:[a-f0-9]{40})$).+$' .github/workflowsRepository: zaks-io/agent-paste
Length of output: 1405
Pin actions/upload-artifact@v7 to a full commit SHA.
Mutable version tags create a supply-chain risk since the action can change between runs. Replace with the full 40-character commit SHA for immutability.
Suggested change
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@<full-length-commit-sha>🧰 Tools
🪛 zizmor (1.25.2)
[error] 94-94: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/ci.yml at line 94, The workflow step currently uses the
mutable tag actions/upload-artifact@v7; replace that tag with the action's
immutable full 40-character commit SHA (i.e., use
actions/upload-artifact@<full-commit-sha>) to pin the dependency. Locate the
line containing the reference "actions/upload-artifact@v7" in the CI workflow
and update it to the exact commit SHA from the upload-artifact repository
release you intend to use, ensuring the workflow references that specific hash
instead of a mutable tag.
|
|
||
| Last updated: 2026-05-21. | ||
|
|
||
| First doc a fresh agent reads after `AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, and `docs/adr/README.md`. Answers: what is built, what is scaffolded, where the code diverges from the ADRs/specs, what the next concrete step is. |
There was a problem hiding this comment.
Clarify the reading order statement.
The phrase "First doc a fresh agent reads after AGENTS.md, CONTEXT.md..." is contradictory—if it's read after those docs, it's not the first doc.
📝 Suggested rewording
-First doc a fresh agent reads after `AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, and `docs/adr/README.md`. Answers: what is built, what is scaffolded, where the code diverges from the ADRs/specs, what the next concrete step is.
+After reading `AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, and `docs/adr/README.md`, agents should read this doc next. It answers: what is built, what is scaffolded, where the code diverges from the ADRs/specs, what the next concrete step is.Or more concisely:
-First doc a fresh agent reads after `AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, and `docs/adr/README.md`. Answers: what is built, what is scaffolded, where the code diverges from the ADRs/specs, what the next concrete step is.
+Read after the onboarding docs (`AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, `docs/adr/README.md`). Answers: what is built, what is scaffolded, where the code diverges from the ADRs/specs, what the next concrete step is.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| First doc a fresh agent reads after `AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, and `docs/adr/README.md`. Answers: what is built, what is scaffolded, where the code diverges from the ADRs/specs, what the next concrete step is. | |
| After reading `AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, and `docs/adr/README.md`, agents should read this doc next. It answers: what is built, what is scaffolded, where the code diverges from the ADRs/specs, what the next concrete step is. |
| First doc a fresh agent reads after `AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, and `docs/adr/README.md`. Answers: what is built, what is scaffolded, where the code diverges from the ADRs/specs, what the next concrete step is. | |
| Read after the onboarding docs (`AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`, `docs/adr/README.md`). Answers: what is built, what is scaffolded, where the code diverges from the ADRs/specs, what the next concrete step is. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/ops/project-status.md` at line 5, The sentence in
docs/ops/project-status.md is self-contradictory; reword the header line "First
doc a fresh agent reads after `AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`,
and `docs/adr/README.md`..." to remove the contradiction—for example change it
to "First doc a fresh agent should read (after `AGENTS.md`, `CONTEXT.md`,
`docs/specs/README.md`, and `docs/adr/README.md`)" or "The first document a
fresh agent reads following `AGENTS.md`, `CONTEXT.md`, `docs/specs/README.md`,
and `docs/adr/README.md`" so the intent is clear; update the exact sentence in
project-status.md accordingly.
| ### 1. Wire `runCommand` and `createOperationEvent` into mutation routes | ||
| - Drives: ADR 0022, ADR 0035, `docs/specs/api.md` | ||
| - Files: `apps/api/src/index.ts`, `apps/upload/src/index.ts`, `packages/commands/src/index.ts` | ||
| - Done: every POST/PUT/DELETE route in `api` and `upload` is wrapped via `runCommand`; idempotency keys are honored from `Idempotency-Key` header; replay of the same idempotency key returns the original result; vitest covers replay for at least workspace-create, api-key-create, artifact-delete. | ||
|
|
||
| ### 2. Enforce native rate-limit bindings | ||
| - Drives: ADR 0039, ADR 0064 | ||
| - Files: `apps/api/src/index.ts`, `apps/upload/src/index.ts`, `apps/*/wrangler.jsonc` | ||
| - Done: every authenticated mutation calls `env.ACTOR_RATE_LIMIT.limit(...)` and `env.WORKSPACE_BURST_CAP.limit(...)`; over-limit returns 429 with envelope; a smoke test triggers 429 from an in-test client. | ||
|
|
||
| ### 3. Generate OpenAPI from Zod contracts | ||
| - Drives: ADR 0016, ADR 0017, ADR 0038 | ||
| - Files: `packages/contracts/src/*`, `apps/api/src/index.ts`, `apps/upload/src/index.ts`, `apps/content/src/index.ts` | ||
| - Done: `/openapi.json` on api/upload/content is generated from `packages/contracts` via `@hono/zod-openapi` (or equivalent); `pnpm verify` runs a schema-diff check against a checked-in golden; CI fails if contracts drift from served OpenAPI. | ||
|
|
||
| ### 4. Add `--yes` guards to destructive admin CLI commands | ||
| - Drives: `docs/specs/admin.md` | ||
| - Files: `apps/cli/src/index.ts` | ||
| - Done: `agent-paste admin api-key revoke`, `artifacts delete`, and `cleanup run` (non-dry-run) refuse to run without `--yes`; CLI test asserts refusal and a `--yes` happy path. | ||
|
|
||
| ### 5. Consolidate content-signing secret names | ||
| - Drives: ADR 0028, ADR 0058 | ||
| - Files: `scripts/bootstrap-secrets.mjs`, `apps/*/wrangler.jsonc`, `apps/api/src/index.ts`, `apps/content/src/index.ts` | ||
| - Done: only one of `CONTENT_SIGNING_SECRET` / `CONTENT_GATEWAY_SIGNING_KEY_V1` remains, named consistently across code, bootstrap script, and ADRs; a one-time rotation note is added to `docs/ops/runbook` (or this doc) for any environment that already holds both. | ||
|
|
||
| ### 6. Move runtime queries to Drizzle | ||
| - Drives: ADR 0018 | ||
| - Files: `packages/db/src/**`, callers in `apps/api`, `apps/upload` | ||
| - Done: workspace/api-key/artifact/upload-session reads and writes flow through Drizzle query objects (not raw SQL templates); `pnpm verify` runs a Drizzle introspection check against the migration file. Scope this to MVP routes; leave admin/cleanup queries as a follow-up if the change balloons. | ||
|
|
||
| ### 7. Apply Postgres RLS at runtime | ||
| - Drives: ADR 0044 | ||
| - Files: `packages/db/src/**`, `apps/api/src/index.ts`, `apps/upload/src/index.ts`, `packages/db/migrations/*` | ||
| - Done: Hyperdrive role is `NOBYPASSRLS`; every request opens a Postgres txn that issues `SET LOCAL app.workspace_id = $1` before any query; a vitest scenario inserts two workspaces and confirms cross-workspace reads return zero rows. | ||
|
|
||
| ### 8. Complete error envelope (`request_id`, `docs`) | ||
| - Drives: ADR 0036, `docs/specs/contracts.md` | ||
| - Files: `apps/api/src/index.ts`, `apps/upload/src/index.ts`, `apps/content/src/index.ts`, `packages/contracts/src/*` | ||
| - Done: every error response includes `request_id`; an optional `docs` URL is attached for codes that have a documented remediation; `X-Request-Id` header is echoed on every response (error or success); golden tests cover at least 404/401/409/422/429/500. | ||
|
|
||
| ### 9. Verify bytes-after-delete and bytes-after-expiry cleanup | ||
| - Drives: ADR 0048, `docs/specs/acceptance.md` | ||
| - Files: `apps/api/src/index.ts` (scheduled handler), `scripts/smoke-local-mvp.mjs`, `scripts/smoke-hosted.mjs` | ||
| - Done: smoke creates an artifact with a 1-day TTL, advances clock (or uses a forced-expiry test endpoint), runs cleanup, confirms R2 prefix is empty and signed URL returns 404 with denylist hit logged. | ||
|
|
||
| ### 10. Exercise PR preview lifecycle on a same-repo PR | ||
| - Drives: ADR 0007, ADR 0012, `.github/workflows/pr-preview.yml` | ||
| - Files: workflow itself, `scripts/deploy-pr-preview.mjs`, `scripts/cleanup-pr-preview.mjs` | ||
| - Done: a same-repo PR (the one carrying items 1-9 above is the natural candidate) creates a Neon branch, deploys preview Workers, runs hosted smoke, posts a comment with URLs, and tears everything down on close. Captured run links recorded in this doc. | ||
|
|
||
| ### 11. Wire Logpush → Axiom for `api`/`upload`/`content` | ||
| - Drives: ADR 0011, `docs/specs/phases.md` Phase 2 | ||
| - Files: Cloudflare console + `docs/ops/` runbook (no Worker code change required if using Cloudflare Logs config) | ||
| - Done: an Axiom dataset receives Worker logs for all three Workers; a basic dashboard shows 5xx rate and p95 latency; secrets/PII redaction confirmed (no API key secret or signed-URL token in logs). | ||
|
|
||
| ### 12. Review and merge `t3code/7bcd4587` | ||
| - Drives: this branch holds Apex/front-end and CI work that needs to land or be discarded. | ||
| - Files: TBD until review. | ||
| - Done: branch is either merged to `main` (with conflicts resolved and CI green) or closed with a written reason. Same decision for `t3code/5b6355f9` if still extant. | ||
|
|
||
| ### 13. Decide on remaining ADR 0046 drift (operator identity) | ||
| - Drives: ADR 0046 | ||
| - Files: ADR 0046 itself, possibly a new ADR | ||
| - Done: ADR 0046 is amended (or a new ADR supersedes it) to either accept the single-bearer admin token as the production model or to commit Cloudflare Access + email allowlist before Phase 3. No code change in this item — just a written decision. | ||
|
|
||
| ### 14. CSP allowlist audit | ||
| - Drives: ADR 0029, ADR 0030, `docs/specs/content-rendering.md` | ||
| - Files: `apps/content/src/index.ts` | ||
| - Done: CSP `script-src` and `connect-src` allowlists are validated against the current ADR 0029 list; SVG responses use a strict CSP override; a vitest snapshot pins the CSP header for HTML, CSS, JS, SVG, and PNG. | ||
|
|
||
| ### 15. Complete bootstrap hosting checklist |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | 💤 Low value
Add blank lines around backlog item headings for Markdown compliance.
Markdownlint flags missing blank lines around 15 headings in the Next Steps Backlog section (items 1-15). While the document is readable, adding blank lines improves Markdown parser compatibility and consistency with the rest of the file.
🧹 Example fix for items 1-3
Ordered. Each item has a verifiable Done. Items 1-10 close Phase 1; items 11-15 prep Phase 2.
When you say "implement the next step," start with item 1 unless we have agreed to skip it.
### 1. Wire `runCommand` and `createOperationEvent` into mutation routes
+
- Drives: ADR 0022, ADR 0035, `docs/specs/api.md`
- Files: `apps/api/src/index.ts`, `apps/upload/src/index.ts`, `packages/commands/src/index.ts`
- Done: every POST/PUT/DELETE route in `api` and `upload` is wrapped via `runCommand`; idempotency keys are honored from `Idempotency-Key` header; replay of the same idempotency key returns the original result; vitest covers replay for at least workspace-create, api-key-create, artifact-delete.
### 2. Enforce native rate-limit bindings
+
- Drives: ADR 0039, ADR 0064
- Files: `apps/api/src/index.ts`, `apps/upload/src/index.ts`, `apps/*/wrangler.jsonc`
- Done: every authenticated mutation calls `env.ACTOR_RATE_LIMIT.limit(...)` and `env.WORKSPACE_BURST_CAP.limit(...)`; over-limit returns 429 with envelope; a smoke test triggers 429 from an in-test client.
### 3. Generate OpenAPI from Zod contracts
+
- Drives: ADR 0016, ADR 0017, ADR 0038Apply the same pattern to items 4-15.
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 166-166: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 171-171: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 176-176: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 181-181: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 186-186: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 191-191: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 196-196: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 201-201: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 206-206: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 211-211: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 216-216: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 221-221: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 226-226: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 231-231: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 236-236: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/ops/project-status.md` around lines 166 - 236, The Next Steps Backlog
headings in docs/ops/project-status.md (e.g., the "### 1. Wire `runCommand` and
`createOperationEvent` into mutation routes", "### 2. Enforce native rate-limit
bindings", etc. through item 15) are missing surrounding blank lines; edit the
Markdown so each "### N. ..." heading is preceded and followed by an empty line
(apply the same pattern used in the example fix for items 1–3) across all 15
items to satisfy markdownlint and ensure parser compatibility.
|
Thanks @coderabbitai. Triage of the 3 actionable findings:
All CI gates are green: |
|
Tip For best results, initiate chat on the files or code changes.
The coverage wiring looks solid — V8 reporters, correct monorepo glob scopes, 🐇 ✨ ✏️ Learnings added
|
The rebase onto origin/main silently regressed the @vitest/coverage-v8 catalog and importer entries that PR #3 added. Frozen-lockfile install on CI failed because the root package.json still referenced the catalog spec.
* feat(commands): wire runCommand into api and upload mutation routes Every POST/PUT/DELETE in api and upload now flows through the shared runCommand wrapper from packages/commands. The wrapper claims an idempotency_records row, executes the handler in the same transaction, persists result_json, and writes the audit event. Replay returns the cached body; an in-flight collision returns 409. A new migration (0002_idempotency_admin_ops) drops the workspace_id FK and adds a NULLS NOT DISTINCT unique index so admin-without-workspace mutations (workspace create, cleanup) can claim records cleanly. Closes backlog item 1 in docs/ops/project-status.md; advances ADR 0004, 0022, and 0035 from Partial to Done. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(db): drop unused withTransaction helper on PostgresRepository Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: address CodeRabbit review - adminActor now throws on unexpected actor types instead of silently mapping non-system actors to admin. - createApiKey defers generateApiKey until inside the idempotent path (both LocalRepository and PostgresRepository) so replays skip the unused crypto work. - Clarify backlog wording so item 9 (PR preview exercise) is not read as a deployment blocker. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: address CodeRabbit review (round 2) Reorder idempotency-key validation to run before database availability checks in all admin handlers. Eliminate redundant mustApiKey call in PostgresRepository.revokeApiKey by reusing the initially fetched row. * fix: restore @vitest/coverage-v8 catalog entry dropped during rebase The rebase onto origin/main silently regressed the @vitest/coverage-v8 catalog and importer entries that PR #3 added. Frozen-lockfile install on CI failed because the root package.json still referenced the catalog spec. * fix(db): apply all migrations, not just 0001 The migrate runner was hardcoded to apply only 0001_mvp_postgres.sql, so the new 0002_idempotency_admin_ops.sql was never running on PR preview Neon branches. Switch to enumerating the migrations directory in lex order so future migrations land automatically. All current migrations are idempotent (if exists / if not exists), so re-running 0001 on already-migrated branches is safe. * fix(db): drop idempotency_records PK before dropping NOT NULL Postgres refuses to drop NOT NULL on a column that's part of a primary key (error 42P16). Reorder 0002 to drop the composite PK first, then the FK and NOT NULL, then recreate the unique index with NULLS NOT DISTINCT. * fix: address CodeRabbit review (round 3) - apps/api: use adminActor helper for cleanup so system tokens record correct actor.type. - packages/commands, packages/db: make SqlExecutor.transaction required; drop silent fallback that ran handlers without a transaction. createPostgresHttpExecutor now throws since HTTP cannot span transactions. - packages/db: include actor.type in LocalRepository admin idempotency cache keys so admin+system with the same id cannot collide. - packages/db/schema: switch idempotency_records unique to unique(...).nullsNotDistinct() to reflect 0002 migration. * fix(db): honor batchSize in LocalRepository.runCleanupSync Mirror PostgresRepository.runCleanupInternal: order expired artifacts/sessions by expires_at, slice to batchSize (default 100), and set artifact.updated_at when expiring. Prevents the local path from blowing past the cap during smoke and manual preview runs. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
CodeRabbit flagged that the same task was listed both as Done in 'Recently Completed' and as pending in 'Next Steps Backlog' (#3). Remove the backlog entry and renumber subsequent items 4-12 to 3-11. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ING_SECRET (#7) * refactor(secrets): consolidate content-signing secret to CONTENT_SIGNING_SECRET Drop CONTENT_GATEWAY_SIGNING_KEY_V1 from bootstrap-secrets.mjs; code already read only CONTENT_SIGNING_SECRET. Add rotation note with wrangler secret delete commands for envs that hold the dropped binding. * docs: address CR feedback on Recently-Completed entry - Drop the pre-merge `<SHA>` placeholder; record completion via PR #7 reference instead (verifiable via `gh pr view 7`). - Add blank line before the fenced rotation block to satisfy markdownlint MD031. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs: drop completed secret-name item from backlog CodeRabbit flagged that the same task was listed both as Done in 'Recently Completed' and as pending in 'Next Steps Backlog' (#3). Remove the backlog entry and renumber subsequent items 4-12 to 3-11. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Adds a combined code coverage report to CI as a GitHub artifact so a downstream ingestor can consume it. Single Vitest run aggregates v8 coverage across every
apps/*andpackages/*project; no merge tooling needed.Changes
vitest.coverage.config.tsat the repo root withtest.projects: ['apps/*', 'packages/*']and v8 coverage reporters (json,lcov,text-summary).pnpm test:coveragethat runsvitest run --coverage --config vitest.coverage.config.ts.Coveragestep (afterpnpm verify) plus anactions/upload-artifact@v7step that publishescoverage/coverage-final.jsonandcoverage/lcov.infoas acoverageartifact (14-day retention,if: always()so partial coverage still uploads on red builds).@vitest/coverage-v8added to the pnpm catalog (pinned to the same^4.1.7asvitest) and to root devDependencies.The config file is named
vitest.coverage.config.ts(not the defaultvitest.config.ts) so per-packagevitest runinvocations under Turbo don't auto-discover it and fail trying to resolve workspace globs from inside a subpackage.Risk: LOW
@vitest/coverage-v8.pnpm verifyper-package, once via rootpnpm test:coverage); ~10s of extra CI wall time given 16 small test files. Acceptable.Test plan
pnpm installsucceeds with@vitest/coverage-v8@4.1.7resolvedpnpm verifypasses (per-package vitest unaffected by the new root config)pnpm test:coverageexits 0 — 16 test files / 64 tests pass; emitscoverage/coverage-final.json(34 source files) andcoverage/lcov.info(3,875 lines)coverageartifact containing both filesif: always())CodeRabbit notes
if-no-files-found: errorflagged as conflicting withif: always(). Keepingerror: the flags are orthogonal (if: always()controls step execution;if-no-files-foundcontrols behavior when files are missing). If coverage silently breaks while tests pass, we want CI to fail loudly so the ingestor never sees a stale build.actions/upload-artifact@v7recommended. The existing workflow tag-pins all other actions (checkout@v6,setup-node@v6,cache@v5,pnpm/action-setup@v6). Pinning only this one to a SHA would be inconsistent; SHA-pinning should be a separate sweep across all actions.Summary by CodeRabbit
New Features
Documentation
Chores