Add test and security baseline

- make quick/check/mutation from cj/security-baseline (Makefile unchanged,
  settings in baseline.mk), pre-commit, gitleaks, Semgrep rules, ESLint
  security rules, Forgejo workflow
- tests/security: generic baseline tests plus app config and role tests
  against createApp() with an in-memory database
- extract createApp() from src/server/index.ts; LB_DATABASE_PATH for tests
- fix gaps found by the tests: reject unknown fields on project create,
  answer malformed JSON with 400 instead of 500, set nosniff on the API
- npm audit fix (next 16.4.1 and others, no high/critical left)
- clear ESLint errors, safeFileName without control-character regex
- per-project ownership stays an open, documented gap (idorGap -> TODO)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Grovy311 2026-10-15 09:40:33 +02:00
parent 67476ea59b
commit a7a1595cbf
38 changed files with 5852 additions and 442 deletions

View file

@ -14,6 +14,10 @@ import { circuits } from "../schema/circuits.js";
import { distributionBoardComponents } from "../schema/distribution-board-components.js";
import { executeProjectCommandTransaction } from "./project-command-transaction.persistence.js";
function temporaryIdentifierKey(table: "circuit" | "component", id: string): string {
return `${table}:${id}`;
}
export class CircuitGroupRenumberProjectCommandRepository
implements CircuitGroupRenumberProjectCommandStore
{
@ -69,7 +73,7 @@ export class CircuitGroupRenumberProjectCommandRepository
table: "component" as const,
})),
]) {
const key = `${assignment.table}:${assignment.id}`;
const key = temporaryIdentifierKey(assignment.table, assignment.id);
const temporary = createTemporaryIdentifier(
key,
occupiedIdentifiers
@ -145,7 +149,7 @@ export class CircuitGroupRenumberProjectCommandRepository
"circuit",
assignment.circuitId,
circuitListId,
temporaryIdentifiers.get(`circuit:${assignment.circuitId}`)!,
temporaryIdentifiers.get(temporaryIdentifierKey("circuit", assignment.circuitId))!,
assignment.targetEquipmentIdentifier
);
}
@ -155,7 +159,7 @@ export class CircuitGroupRenumberProjectCommandRepository
"component",
assignment.componentId,
circuitListId,
temporaryIdentifiers.get(`component:${assignment.componentId}`)!,
temporaryIdentifiers.get(temporaryIdentifierKey("component", assignment.componentId))!,
assignment.targetEquipmentIdentifier
);
}