Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ updates:
time: "06:00"
timezone: Asia/Baku
open-pull-requests-limit: 5
# One pull request for routine updates; majors stay separate for review.
groups:
npm-minor-and-patch:
update-types: [minor, patch]
ignore:
# chalk 6 requires Node 22; CodeDiag supports Node 20.19 and newer.
- dependency-name: chalk
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
branches: [main]
pull_request:
branches: [main]
# Started by dependabot-bundle.yml after it commits a rebuilt bundle, since
# commits pushed with GITHUB_TOKEN do not trigger pull_request runs.
workflow_dispatch:

jobs:
build:
Expand Down
75 changes: 75 additions & 0 deletions .github/workflows/dependabot-bundle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Dependabot bundle

# A dependency update can change the committed Action bundle, which CI
# compares with a fresh build. This rebuilds it on Dependabot pull requests:
# the dependency's code runs only in a read-only job, and the job that
# pushes runs nothing from the repository or its dependencies.

on:
pull_request:
branches: [main]

permissions:
contents: read

jobs:
build:
if: github.event.pull_request.user.login == 'dependabot[bot]'
runs-on: ubuntu-latest
outputs:
changed: ${{ steps.diff.outputs.changed }}
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- uses: actions/setup-node@v7
with:
node-version: 22
- run: npm ci
- run: npm run build
- id: diff
run: |
if git diff --quiet -- dist/action.cjs dist/action.cjs.LEGAL.txt; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- if: steps.diff.outputs.changed == 'true'
uses: actions/upload-artifact@v7
with:
name: action-bundle
path: |
dist/action.cjs
dist/action.cjs.LEGAL.txt
if-no-files-found: error

commit:
needs: build
if: needs.build.outputs.changed == 'true'
runs-on: ubuntu-latest
permissions:
contents: write
actions: write
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.ref }}
- uses: actions/download-artifact@v7
with:
name: action-bundle
path: rebuilt
- name: Commit the rebuilt bundle
run: |
cp rebuilt/action.cjs rebuilt/action.cjs.LEGAL.txt dist/
rm -rf rebuilt
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add dist/action.cjs dist/action.cjs.LEGAL.txt
git commit -m "chore(deps): rebuild the Action bundle"
git push
- name: Run CI for the new commit
env:
GH_TOKEN: ${{ github.token }}
BRANCH: ${{ github.event.pull_request.head.ref }}
run: gh workflow run ci.yml --repo "$GITHUB_REPOSITORY" --ref "$BRANCH"
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,45 @@

All notable changes to CodeDiag are documented in this file.

## [0.9.0] - 2026-10-30

The "Perimeter" release: tRPC apps that authenticate in front of their
procedures stop getting missing-auth warnings, dependency audits are cached
and run concurrently across monorepo packages, and Dependabot updates keep
the Action bundle in step.

### Added

- tRPC mutations are no longer reported as missing auth middleware when the
whole router is authenticated before procedures run: a `createContext` (or
a project function it calls) that throws `TRPCError` `UNAUTHORIZED` or
`FORBIDDEN`, or throws when the session is missing; auth middleware ahead
of the Express mount that serves the adapter; or a Next.js `middleware.ts`
(`proxy.ts` in Next.js 16) that rejects anonymous requests
(`next-auth/middleware`, Clerk's `auth.protect()` under a route matcher, or
a redirect or 401/403 when the session is missing) and whose `matcher`
covers the tRPC route. A `createContext` that only reads the session, as
T3's does, and the common `/((?!api|...).*)` matcher that skips the API do
not count. The API Health summary names where the perimeter was found.
- Successful dependency audits are kept for an hour in
`node_modules/.cache/codediag`, keyed by the audit command and the exact
lock file and `package.json` contents, and reused by later scans and
editor saves. Entries are validated on read, failed audits are never kept,
nothing is written without a `node_modules` directory, and the Dependencies
summary says when a result was reused.
- Dependabot pull requests that change the Action bundle get it rebuilt: a
read-only job builds it, and a job that runs no repository or dependency
code commits the two bundle files and starts CI for the new commit.
Dependabot groups minor and patch npm updates into one pull request.

### Changed

- `--workspaces` scans run every package's audit up front, four at a time,
and the package scans reuse those outcomes, so audit waits overlap instead
of adding up.
- VS Code extension 0.7.0: scans on save also reuse an audit cached on disk
within the hour.

## [0.8.0] - 2026-10-30

The "Depth" release: tRPC procedures, request data followed through fields,
Expand Down
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ verification performed. Keep unrelated refactors in separate pull requests.
4. Move the Action's major tag (for example `v0`) to the release commit so
`uses: sabahattink/codediag@v0` picks it up.

The GitHub Action runs the committed bundle in `dist/action.cjs`, and CI
fails when it differs from a fresh build. Dependabot pull requests that
change the bundle get it rebuilt by the Dependabot bundle workflow, which
builds without write access, commits only the two bundle files, and starts CI
for the new commit.

## Reporting security issues

Do not open a public issue for a suspected vulnerability. Follow the private
Expand Down
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,13 @@ AST analysis (ts-morph, not regex) of the routes your app actually exposes.
routers across files (including `~/` path aliases); mutations without auth
middleware (judged by what the middleware checks, not its name), `.input()`
parsers that accept anything, and error formatters or `isDev: true` that
expose stack traces. The checks run inside whichever server hosts tRPC
(T3/Next.js, Express, Fastify), and a standalone tRPC server is its own
stack.
expose stack traces. Auth in front of every procedure counts too: a
`createContext` that rejects anonymous callers, auth middleware ahead of
the Express mount, or a Next.js `middleware.ts` (`proxy.ts` in Next.js 16)
whose matcher covers the tRPC route. The checks run inside whichever server
hosts tRPC (T3/Next.js, Express, Fastify), and a standalone tRPC server is
its own stack. An intentionally public mutation, such as sign-up, is
accepted with a reasoned `codediag-ignore-next-line` directive.

### Security

Expand Down Expand Up @@ -119,7 +123,10 @@ Runs the matching npm, pnpm, Yarn Classic, or Yarn Berry audit (skipped with
names the affected packages and their advisories in each vulnerability
finding, checks the lock file and `packageManager` consistency, flags
deprecated packages, and validates engine specs and essential scripts.
Monorepo lock files are found up to three parent directories.
Monorepo lock files are found up to three parent directories. A successful
audit is kept for an hour in `node_modules/.cache/codediag`, keyed by the lock
file and `package.json`, so repeated scans reuse it (the Dependencies summary
says when); delete that directory to force a fresh audit.

### Testing

Expand Down Expand Up @@ -237,7 +244,8 @@ workspaces). Each package gets its own stack detection and score, using its
own `.codediag.yml` if it has one and otherwise the root configuration, with
root `ignore` paths rebased into the package. The combined report lists every
package and averages each analyzer over the packages it ran in; the total
uses the usual analyzer weights. Findings are located relative to the root,
uses the usual analyzer weights. Package audits run four at a time before
the packages are analyzed. Findings are located relative to the root,
and project-level findings point at the package's `package.json`, so
baselines, `--compare`, `--changed-since`, SARIF, and the GitHub Action
(`workspaces: true`) work across the whole repository.
Expand Down Expand Up @@ -485,8 +493,11 @@ results in GitHub Code Scanning.
callbacks, and injected providers; `@fastify/autoload` projects; secrets
removed from the tree but kept in Git history; per-package thresholds and
`--fail-on` gates; remediation quick fixes in VS Code.
- **0.9 "Perimeter":** tRPC auth in `createContext`, Express mounts, and
Next.js middleware; audits cached for an hour and run concurrently across
workspace packages; Dependabot updates that rebuild the Action bundle.
- **Next:** see [docs/roadmap.md](docs/roadmap.md) for planned framework
support, editor improvements, and faster monorepo scans.
support, editor improvements, and deeper taint tracking.

## Contributing

Expand Down
Loading
Loading