diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66eccad..240e94b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,6 +37,4 @@ jobs: run: npm run build:pages - name: Run tests - run: | - npm run test - npm run test:pages + run: npm run test diff --git a/AGENTS.md b/AGENTS.md index 1e3326d..6c5589c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,7 +30,7 @@ vitest run src/path/to.test.ts # single test (no npx needed) ```bash npm run dev:pages # astro dev npm run build:pages # astro build → status-page/dist/ -npm run test:pages # vitest run (auth tests) + npm run check:pages # astro check + tsc --noEmit npm run lint:pages # eslint (astro plugin) ``` @@ -39,6 +39,8 @@ npm run lint:pages # eslint (astro plugin) Before commit: `npm run check && npm run test && npm run build:pages && npm run check:pages` +## Verification order + `npm run check` = typecheck + Oxlint (worker) + ESLint (dedup via `eslint-plugin-oxlint`). Pages uses `eslint-plugin-astro`. ## Gotchas diff --git a/README.md b/README.md index 84ac4c1..93d29d2 100644 --- a/README.md +++ b/README.md @@ -387,9 +387,6 @@ npm run build:pages # Worker tests npm run test -# Status page tests -npm run test:pages - # Type checking and linting npm run check # worker npm run check:pages # pages (astro check + tsc) diff --git a/package.json b/package.json index 65a5947..bf070e8 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "check:fix": "npm run lint:fix && npm run format", "dev:pages": "npm run dev --workspace=status-page", "build:pages": "npm run build --workspace=status-page", - "test:pages": "npm run test --workspace=status-page", "check:pages": "npm run typecheck --workspace=status-page && npm run lint:pages && npm run format:pages:check", "lint:pages": "npm run lint --workspace=status-page", "lint:pages:fix": "npm run lint:fix --workspace=status-page", diff --git a/src/index.test.ts b/src/index.test.ts index 5dcaa00..5d4d3e2 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -11,7 +11,7 @@ vi.mock('cloudflare:workers', () => ({ })); // Mock the auth module -vi.mock('../status-page/src/lib/auth.js', () => ({ +vi.mock('./lib/auth.js', () => ({ checkAuth: vi.fn().mockResolvedValue(undefined), })); @@ -62,7 +62,7 @@ describe('worker fetch handler', () => { }); it('should return 401 when auth fails', async () => { - const { checkAuth } = await import('../status-page/src/lib/auth.js'); + const { checkAuth } = await import('./lib/auth.js'); vi.mocked(checkAuth).mockResolvedValueOnce( new Response('Unauthorized', { status: 401, diff --git a/src/index.ts b/src/index.ts index 70441e4..8a19dd9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { checkAuth } from '../status-page/src/lib/auth.js'; +import { checkAuth } from './lib/auth.js'; import { handleAggregation } from './aggregation.js'; import { executeDnsCheck } from './checks/dns.js'; import { executeHttpCheck } from './checks/http.js'; diff --git a/status-page/src/lib/auth.test.ts b/src/lib/auth.test.ts similarity index 100% rename from status-page/src/lib/auth.test.ts rename to src/lib/auth.test.ts diff --git a/status-page/src/lib/auth.ts b/src/lib/auth.ts similarity index 87% rename from status-page/src/lib/auth.ts rename to src/lib/auth.ts index 1a6474a..dfe1bba 100644 --- a/status-page/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -10,11 +10,6 @@ const unauthorizedResponse = (): Response => headers: { 'WWW-Authenticate': 'Basic realm="Status Page"' }, }); -/** - * Timing-safe string comparison using SHA-256 hashing. - * Hashing both values to a fixed size prevents leaking length information. - * Uses constant-time byte comparison to prevent timing side-channel attacks. - */ async function timingSafeCompare(a: string, b: string): Promise { const encoder = new TextEncoder(); const [hashA, hashB] = await Promise.all([ @@ -25,7 +20,6 @@ async function timingSafeCompare(a: string, b: string): Promise { const viewA = new Uint8Array(hashA); const viewB = new Uint8Array(hashB); - // Constant-time comparison: always check every byte let mismatch = 0; for (let i = 0; i < viewA.length; i++) { mismatch |= viewA[i] ^ viewB[i];