diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2bbbf8e..36dc5f6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,32 +6,47 @@ on: pull_request: branches: [main, develop] +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + jobs: test: name: Run tests runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4.2.2 - - uses: actions/setup-node@v4 + - uses: pnpm/action-setup@v4 with: - node-version: '22' + version: 9 - - uses: pnpm/action-setup@v3 + - uses: actions/setup-node@v4.4.0 with: - version: 9 + node-version: '22' + cache: 'pnpm' + + - name: Install system dependencies for better-sqlite3 + run: sudo apt-get install -y python3 make g++ - - run: pnpm install --build-from-source + - name: Install dependencies + run: pnpm install - - run: pnpm typecheck + - name: Rebuild better-sqlite3 for CI environment + run: pnpm rebuild better-sqlite3 - - run: pnpm test + - name: Type check + run: pnpm typecheck + + - name: Run tests + run: pnpm test privacy-audit: name: Privacy constraint check runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4.2.2 - name: Check for forbidden patterns run: | @@ -48,4 +63,4 @@ jobs: echo "Privacy check FAILED" exit 1 fi - echo "✅ Privacy check passed" + echo "✅ Privacy check passed" \ No newline at end of file diff --git a/package.json b/package.json index d091c5c..30d717c 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ }, "devDependencies": { "@types/better-sqlite3": "^7.6.13", + "typescript": "~5.4.5", "vitest": "^4.1.8" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 173b801..cf3060c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,6 +15,9 @@ importers: '@types/better-sqlite3': specifier: ^7.6.13 version: 7.6.13 + typescript: + specifier: ~5.4.5 + version: 5.4.5 vitest: specifier: ^4.1.8 version: 4.1.8(@types/node@25.9.1)(vite@8.0.16(@types/node@25.9.1)) @@ -475,6 +478,11 @@ packages: tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + engines: {node: '>=14.17'} + hasBin: true + undici-types@7.24.6: resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} @@ -987,6 +995,8 @@ snapshots: dependencies: safe-buffer: 5.2.1 + typescript@5.4.5: {} + undici-types@7.24.6: {} util-deprecate@1.0.2: {} diff --git a/src/privacy/audit-log.ts b/src/privacy/audit-log.ts index 31ef386..cf10c2e 100644 --- a/src/privacy/audit-log.ts +++ b/src/privacy/audit-log.ts @@ -125,7 +125,7 @@ export class AuditLog { * This can be called by the user from the Privacy Dashboard to prove * that no historical records have been modified. */ - verifyChain(): { valid: boolean; broken_at?: number; total_records: number } { + verifyChain(): { valid: boolean; broken_at: number | undefined; total_records: number } { const rows = this.db.prepare(` SELECT * FROM audit_log ORDER BY id ASC `).all() as AuditEntry[] @@ -133,7 +133,7 @@ export class AuditLog { let prevHash: string | null = null for (const row of rows) { - const content = [ + const content: string = [ row.timestamp, row.event_type, row.app_name, @@ -143,8 +143,7 @@ export class AuditLog { row.details, prevHash, ].join('|') - - const expectedHash = createHash('sha256').update(content).digest('hex') + const expectedHash: string = createHash('sha256').update(content).digest('hex') if (expectedHash !== row.record_hash) { return { valid: false, broken_at: row.id, total_records: rows.length } @@ -153,7 +152,7 @@ export class AuditLog { prevHash = row.record_hash } - return { valid: true, total_records: rows.length } + return { valid: true, broken_at: undefined, total_records: rows.length } } /**