From 60525656b8ecdc4b63956f0d7b77e4286961edc4 Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Mon, 24 Aug 2026 11:21:28 +0300 Subject: [PATCH] fix: harden backend runtime artifact hygiene --- .gitignore | 7 +++- dev.db | 0 package.json | 1 + scripts/repository-hygiene-check.mjs | 60 ++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) delete mode 100644 dev.db create mode 100644 scripts/repository-hygiene-check.mjs diff --git a/.gitignore b/.gitignore index 960107d..d7fc961 100644 --- a/.gitignore +++ b/.gitignore @@ -58,5 +58,8 @@ pids # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json -# SQLite data -prisma/*.db +# SQLite runtime data +/dev.db +/dev.db-* +/prisma/*.db +/prisma/*.db-* diff --git a/dev.db b/dev.db deleted file mode 100644 index e69de29..0000000 diff --git a/package.json b/package.json index 829434a..6fe94a3 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "lint": "npm run lint:check", "lint:check": "eslint \"{src,apps,libs,test}/**/*.ts\" --max-warnings=0", "lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "hygiene:check": "node scripts/repository-hygiene-check.mjs", "typecheck:app": "tsc --project tsconfig.typecheck.app.json", "typecheck:test": "tsc --project tsconfig.typecheck.test.json", "test": "jest", diff --git a/scripts/repository-hygiene-check.mjs b/scripts/repository-hygiene-check.mjs new file mode 100644 index 0000000..1197bdc --- /dev/null +++ b/scripts/repository-hygiene-check.mjs @@ -0,0 +1,60 @@ +import { execFileSync } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; +import { dirname, resolve } from 'node:path'; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); + +function git(args) { + return execFileSync('git', args, { cwd: root, encoding: 'utf8' }).trim(); +} + +function isIgnored(file) { + try { + execFileSync('git', ['check-ignore', '--no-index', '-q', file], { + cwd: root, + stdio: 'ignore', + }); + return true; + } catch (error) { + if (error.status === 1) return false; + throw error; + } +} + +function assert(condition, message) { + if (!condition) throw new Error(message); +} + +const trackedDatabases = git([ + 'ls-files', + '--', + 'dev.db', + 'dev.db-*', + 'prisma/*.db', + 'prisma/*.db-*', +]) + .split('\n') + .filter(Boolean); + +assert( + trackedDatabases.length === 0, + `Runtime SQLite files in supported locations must not be tracked; found: ${trackedDatabases.join(', ')}`, +); + +for (const file of [ + 'dev.db', + 'dev.db-wal', + 'dev.db-shm', + 'prisma/dev.db', + 'prisma/dev.db-wal', + 'prisma/dev.db-shm', +]) { + assert(isIgnored(file), `Runtime SQLite file must be ignored: ${file}`); +} + +assert( + !isIgnored('test/fixtures/reference.db'), + 'Intentional fixture must remain versionable', +); + +console.log('Backend repository hygiene verified');