🔒 add no-unauth-routes lint check#2334
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Coverage Report for API Unit Tests Coverage (./packages/api)
File CoverageNo changed files found. |
Coverage Report for Expo Unit Tests Coverage (./apps/expo)
File CoverageNo changed files found. |
There was a problem hiding this comment.
Pull request overview
Adds a custom lint check to prevent accidentally-public API endpoints by scanning Elysia route definitions in packages/api/src/routes/** and requiring an auth macro or an explicit opt-out annotation.
Changes:
- Added
scripts/lint/no-unauth-routes.tsto detect routes missingisAuthenticated,isAdmin, andisValidApiKeyunless annotated with// public-route: .... - Wired the new check into
check-all,lint:custom, lefthook pre-push, and GitHub Actions. - Annotated intentionally-public auth endpoints with
// public-route:reasons.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/lint/no-unauth-routes.ts | New lint script to flag unauthenticated Elysia routes unless explicitly annotated. |
| scripts/check-all.ts | Registers the new lint script in the unified custom checks runner. |
| packages/api/src/routes/auth/index.ts | Adds // public-route: annotations for intentionally public auth endpoints. |
| package.json | Adds the new lint script to lint:custom. |
| lefthook.yml | Adds the new lint script to the pre-push gate. |
| .github/workflows/checks.yml | Adds CI invocation for the new lint script (currently duplicated with lint:custom). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| function extractRoutePath(content: string, afterOffset: number): string { | ||
| // Extract the string literal that is the first argument of the route call. | ||
| const slice = content.slice(afterOffset, afterOffset + 200); | ||
| const m = slice.match(/^['"`]([^'"`\n]*)/); |
| - name: Check for unauthenticated routes | ||
| run: bun scripts/lint/no-unauth-routes.ts |
1b404df to
8241453
Compare
cc4f0cc to
04caea9
Compare
8241453 to
5636103
Compare
…acros Adds scripts/lint/no-unauth-routes.ts which scans packages/api/src/routes for Elysia route handlers (.get/.post/.put/.patch/.delete/.all) that lack isAuthenticated/isAdmin/isValidApiKey and have no // public-route: annotation. - Excludes the admin/ subtree (uses Cloudflare Access + Basic/JWT auth via onBeforeHandle, not Elysia macros) - Annotates the 10 intentionally-public auth routes (login, register, verify-email, resend-verification, forgot-password, reset-password, refresh, logout, apple, google) with descriptive // public-route: reasons - Wired into check-all.ts, lint:custom, lefthook.yml pre-push gate, and CI
04caea9 to
4c70867
Compare
- no-duplicate-guards.ts: use template literal for path separator (useTemplate) - no-unauth-routes.ts: restructure while loop to for(;;) to avoid noAssignInExpressions
The /alltrails/preview endpoint is a link-preview proxy that fetches OG metadata from AllTrails. No user data is accessed or modified, so it intentionally omits auth macros.
🔒 add no-unauth-routes lint check
Summary
scripts/lint/no-unauth-routes.ts— scanspackages/api/src/routes/**/*.tsfor Elysia route handlers missing all three auth macros (isAuthenticated,isAdmin,isValidApiKey) with no// public-route:opt-out annotationadmin/subtree (uses Cloudflare Access + Basic/JWT auth viaonBeforeHandle, not Elysia macros — correct by design)// public-route:reasonscheck-all.ts,lint:custom,lefthook.ymlpre-push gate, and CIHow it works
.get('/'…,.post('/…etc. — requiring a/prefix on the path string to avoid false positives fromURLSearchParams.get('key')calls// public-route:annotationTest plan
bun scripts/lint/no-unauth-routes.tsexits 0.get('/test', () => {})to any route file → script exits 1 and names it// public-route: reasonabove it → exits 0 again🤖 Generated with Claude Code