diff --git a/apps/api/drizzle/meta/0002_snapshot.json b/apps/api/drizzle/meta/0002_snapshot.json index 49f0db69..f63ef732 100644 --- a/apps/api/drizzle/meta/0002_snapshot.json +++ b/apps/api/drizzle/meta/0002_snapshot.json @@ -70,12 +70,8 @@ "name": "api_keys_user_id_users_id_fk", "tableFrom": "api_keys", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -209,12 +205,8 @@ "name": "audit_log_actor_id_users_id_fk", "tableFrom": "audit_log", "tableTo": "users", - "columnsFrom": [ - "actor_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["actor_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -378,12 +370,8 @@ "name": "jobs_user_id_users_id_fk", "tableFrom": "jobs", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -441,12 +429,8 @@ "name": "pipelines_user_id_users_id_fk", "tableFrom": "pipelines", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -518,12 +502,8 @@ "name": "roles_created_by_users_id_fk", "tableFrom": "roles", "tableTo": "users", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -533,9 +513,7 @@ "roles_name_unique": { "name": "roles_name_unique", "nullsNotDistinct": false, - "columns": [ - "name" - ] + "columns": ["name"] } }, "policies": {}, @@ -583,12 +561,8 @@ "name": "sessions_user_id_users_id_fk", "tableFrom": "sessions", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -660,9 +634,7 @@ "teams_name_unique": { "name": "teams_name_unique", "nullsNotDistinct": false, - "columns": [ - "name" - ] + "columns": ["name"] } }, "policies": {}, @@ -753,12 +725,8 @@ "name": "user_files_user_id_users_id_fk", "tableFrom": "user_files", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -805,12 +773,8 @@ "name": "user_preferences_user_id_users_id_fk", "tableFrom": "user_preferences", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -818,10 +782,7 @@ "compositePrimaryKeys": { "user_preferences_user_id_key_pk": { "name": "user_preferences_user_id_key_pk", - "columns": [ - "user_id", - "key" - ] + "columns": ["user_id", "key"] } }, "uniqueConstraints": {}, @@ -929,9 +890,7 @@ "users_username_unique": { "name": "users_username_unique", "nullsNotDistinct": false, - "columns": [ - "username" - ] + "columns": ["username"] } }, "policies": {}, @@ -943,13 +902,7 @@ "public.job_status": { "name": "job_status", "schema": "public", - "values": [ - "queued", - "processing", - "completed", - "failed", - "canceled" - ] + "values": ["queued", "processing", "completed", "failed", "canceled"] } }, "schemas": {}, @@ -962,4 +915,4 @@ "schemas": {}, "tables": {} } -} \ No newline at end of file +} diff --git a/apps/api/drizzle/meta/0003_snapshot.json b/apps/api/drizzle/meta/0003_snapshot.json index 6bbd0e86..f68c6b37 100644 --- a/apps/api/drizzle/meta/0003_snapshot.json +++ b/apps/api/drizzle/meta/0003_snapshot.json @@ -70,12 +70,8 @@ "name": "api_keys_user_id_users_id_fk", "tableFrom": "api_keys", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -209,12 +205,8 @@ "name": "audit_log_actor_id_users_id_fk", "tableFrom": "audit_log", "tableTo": "users", - "columnsFrom": [ - "actor_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["actor_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -384,12 +376,8 @@ "name": "jobs_user_id_users_id_fk", "tableFrom": "jobs", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -447,12 +435,8 @@ "name": "pipelines_user_id_users_id_fk", "tableFrom": "pipelines", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -524,12 +508,8 @@ "name": "roles_created_by_users_id_fk", "tableFrom": "roles", "tableTo": "users", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -539,9 +519,7 @@ "roles_name_unique": { "name": "roles_name_unique", "nullsNotDistinct": false, - "columns": [ - "name" - ] + "columns": ["name"] } }, "policies": {}, @@ -589,12 +567,8 @@ "name": "sessions_user_id_users_id_fk", "tableFrom": "sessions", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -685,9 +659,7 @@ "teams_name_unique": { "name": "teams_name_unique", "nullsNotDistinct": false, - "columns": [ - "name" - ] + "columns": ["name"] } }, "policies": {}, @@ -778,12 +750,8 @@ "name": "user_files_user_id_users_id_fk", "tableFrom": "user_files", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -830,12 +798,8 @@ "name": "user_preferences_user_id_users_id_fk", "tableFrom": "user_preferences", "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -843,10 +807,7 @@ "compositePrimaryKeys": { "user_preferences_user_id_key_pk": { "name": "user_preferences_user_id_key_pk", - "columns": [ - "user_id", - "key" - ] + "columns": ["user_id", "key"] } }, "uniqueConstraints": {}, @@ -974,9 +935,7 @@ "users_username_unique": { "name": "users_username_unique", "nullsNotDistinct": false, - "columns": [ - "username" - ] + "columns": ["username"] } }, "policies": {}, @@ -988,13 +947,7 @@ "public.job_status": { "name": "job_status", "schema": "public", - "values": [ - "queued", - "processing", - "completed", - "failed", - "canceled" - ] + "values": ["queued", "processing", "completed", "failed", "canceled"] } }, "schemas": {}, @@ -1007,4 +960,4 @@ "schemas": {}, "tables": {} } -} \ No newline at end of file +} diff --git a/apps/api/src/lib/audit-integrity.ts b/apps/api/src/lib/audit-integrity.ts index 89367e7a..204b9ee3 100644 --- a/apps/api/src/lib/audit-integrity.ts +++ b/apps/api/src/lib/audit-integrity.ts @@ -16,11 +16,7 @@ export function computeHmac(data: Record, key: Buffer): string return createHmac("sha256", key).update(canonicalize(data)).digest("hex"); } -export function verifyHmac( - data: Record, - hmac: string, - key: Buffer, -): boolean { +export function verifyHmac(data: Record, hmac: string, key: Buffer): boolean { const computed = computeHmac(data, key); return computed === hmac; } diff --git a/apps/api/src/lib/audit.ts b/apps/api/src/lib/audit.ts index b9eaafe0..da60f4b7 100644 --- a/apps/api/src/lib/audit.ts +++ b/apps/api/src/lib/audit.ts @@ -100,10 +100,7 @@ export async function auditLog( requestId, }; const integrity = computeHmac(rowData, hmacKey); - await db - .update(schema.auditLog) - .set({ integrity }) - .where(eq(schema.auditLog.id, id)); + await db.update(schema.auditLog).set({ integrity }).where(eq(schema.auditLog.id, id)); } } catch { logger.warn({ event }, "Failed to compute audit HMAC"); diff --git a/apps/api/src/lib/encryption.ts b/apps/api/src/lib/encryption.ts index 517f52b1..c060c2c5 100644 --- a/apps/api/src/lib/encryption.ts +++ b/apps/api/src/lib/encryption.ts @@ -1,9 +1,4 @@ -import { - createCipheriv, - createDecipheriv, - randomBytes, - hkdf as hkdfCb, -} from "node:crypto"; +import { createCipheriv, createDecipheriv, hkdf as hkdfCb, randomBytes } from "node:crypto"; import { promisify } from "node:util"; const hkdf = promisify(hkdfCb); diff --git a/apps/api/src/lib/webhook-delivery.ts b/apps/api/src/lib/webhook-delivery.ts index 42005ab7..8e850825 100644 --- a/apps/api/src/lib/webhook-delivery.ts +++ b/apps/api/src/lib/webhook-delivery.ts @@ -50,7 +50,12 @@ export async function deliverWebhook( lastError = `HTTP ${response.status}`; // Don't retry 4xx errors (client errors = won't succeed on retry) if (response.status >= 400 && response.status < 500) { - return { success: false, statusCode: response.status, error: lastError, attempts: attempt + 1 }; + return { + success: false, + statusCode: response.status, + error: lastError, + attempts: attempt + 1, + }; } } catch (err) { lastError = err instanceof Error ? err.message : String(err); diff --git a/apps/api/src/routes/api-keys.ts b/apps/api/src/routes/api-keys.ts index 647e0503..1cc43947 100644 --- a/apps/api/src/routes/api-keys.ts +++ b/apps/api/src/routes/api-keys.ts @@ -86,7 +86,11 @@ export async function apiKeyRoutes(app: FastifyInstance): Promise { return reply.status(409).send({ error: "Failed to create API key" }); } - await auditFromRequest(request)("API_KEY_CREATED", { userId: user.id, keyId: id, keyName: name }); + await auditFromRequest(request)("API_KEY_CREATED", { + userId: user.id, + keyId: id, + keyName: name, + }); // Return the raw key ONCE — it cannot be retrieved again return reply.status(201).send({ diff --git a/apps/api/src/routes/enterprise/siem.ts b/apps/api/src/routes/enterprise/siem.ts index 772e3611..d151a32d 100644 --- a/apps/api/src/routes/enterprise/siem.ts +++ b/apps/api/src/routes/enterprise/siem.ts @@ -35,9 +35,9 @@ export async function registerSiemRoutes(app: FastifyInstance): Promise { // Enterprise package not available } if (!featureEnabled) { - return reply - .status(403) - .send({ error: "SIEM forwarding requires an enterprise license with the siem_forwarding feature" }); + return reply.status(403).send({ + error: "SIEM forwarding requires an enterprise license with the siem_forwarding feature", + }); } const [row] = await db @@ -65,10 +65,7 @@ export async function registerSiemRoutes(app: FastifyInstance): Promise { // PUT /api/v1/enterprise/siem/config app.put( "/api/v1/enterprise/siem/config", - async ( - request: FastifyRequest<{ Body: unknown }>, - reply: FastifyReply, - ) => { + async (request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) => { const user = await requirePermission("webhooks:manage")(request, reply); if (!user) return; @@ -81,14 +78,16 @@ export async function registerSiemRoutes(app: FastifyInstance): Promise { // Enterprise package not available } if (!featureEnabled) { - return reply - .status(403) - .send({ error: "SIEM forwarding requires an enterprise license with the siem_forwarding feature" }); + return reply.status(403).send({ + error: "SIEM forwarding requires an enterprise license with the siem_forwarding feature", + }); } const parsed = configSchema.safeParse(request.body); if (!parsed.success) { - return reply.status(400).send({ error: "Invalid SIEM config", details: parsed.error.issues }); + return reply + .status(400) + .send({ error: "Invalid SIEM config", details: parsed.error.issues }); } const config = { ...parsed.data }; diff --git a/apps/api/src/routes/settings.ts b/apps/api/src/routes/settings.ts index 930dfd18..530f2961 100644 --- a/apps/api/src/routes/settings.ts +++ b/apps/api/src/routes/settings.ts @@ -9,10 +9,10 @@ import { eq } from "drizzle-orm"; import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; import { z } from "zod"; +import { env } from "../config.js"; import { db, schema } from "../db/index.js"; import { auditFromRequest } from "../lib/audit.js"; -import { env } from "../config.js"; -import { encrypt, decrypt, isEncrypted } from "../lib/encryption.js"; +import { decrypt, encrypt, isEncrypted } from "../lib/encryption.js"; import { requirePermission } from "../permissions.js"; import { requireAuth } from "../plugins/auth.js"; @@ -37,8 +37,11 @@ async function decryptIfNeeded(value: string): Promise { if (!isEncrypted(value)) return value; if (!env.DATA_ENCRYPTION_KEY) return value; return ( - (await decrypt(value, env.DATA_ENCRYPTION_KEY, env.DATA_ENCRYPTION_KEY_PREVIOUS || undefined)) ?? - value + (await decrypt( + value, + env.DATA_ENCRYPTION_KEY, + env.DATA_ENCRYPTION_KEY_PREVIOUS || undefined, + )) ?? value ); } diff --git a/scripts/check-license-boundary.mjs b/scripts/check-license-boundary.mjs index 77f547b0..8e355fa7 100644 --- a/scripts/check-license-boundary.mjs +++ b/scripts/check-license-boundary.mjs @@ -23,7 +23,8 @@ const ENTERPRISE_DIR = join(ROOT, "packages/enterprise"); // Catches static `from "..."`, side-effect `import "..."`, and dynamic `import("...")` // forms. The bare package entry "@snapotter/enterprise" (no trailing slash) stays // allowed; only reaching INTO the package is a violation. -const INTERNAL_IMPORT = /(from|import)\s*[\s(]\s*["'](@snapotter\/enterprise\/|[./]*packages\/enterprise\/)/; +const INTERNAL_IMPORT = + /(from|import)\s*[\s(]\s*["'](@snapotter\/enterprise\/|[./]*packages\/enterprise\/)/; const APP_IMPORT = /(from|import)\s*[\s(]\s*["'][^"']*apps\/(api|web)\//; const violations = []; diff --git a/scripts/export-ai-bundle.mjs b/scripts/export-ai-bundle.mjs index 67ef75a4..0eeb3e58 100755 --- a/scripts/export-ai-bundle.mjs +++ b/scripts/export-ai-bundle.mjs @@ -1,4 +1,6 @@ #!/usr/bin/env node +import { randomUUID } from "node:crypto"; +import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; /** * Export an installed AI feature bundle as a gzipped tar archive for offline * transfer to air-gapped SnapOtter installations. @@ -18,11 +20,9 @@ * createRequire, same pattern as tests/global-setup.ts). */ import { createRequire } from "node:module"; -import { dirname, join, resolve } from "node:path"; -import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from "node:fs"; -import { fileURLToPath } from "node:url"; import { tmpdir } from "node:os"; -import { randomUUID } from "node:crypto"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; const __dirname = dirname(fileURLToPath(import.meta.url)); const apiRequire = createRequire(join(__dirname, "../apps/api/package.json")); @@ -136,7 +136,9 @@ if (modelEntries.length === 0) { process.stderr.write("Warning: no model files found; archive will only contain bundle.json\n"); } -process.stderr.write(`Exporting bundle "${bundleId}" v${version} (${modelEntries.length} model files)...\n`); +process.stderr.write( + `Exporting bundle "${bundleId}" v${version} (${modelEntries.length} model files)...\n`, +); // ── Create the archive ───────────────────────────────────────────────── diff --git a/scripts/generate-hostile-fixtures.mjs b/scripts/generate-hostile-fixtures.mjs index 95e0664b..efcac2b9 100644 --- a/scripts/generate-hostile-fixtures.mjs +++ b/scripts/generate-hostile-fixtures.mjs @@ -19,7 +19,10 @@ mkdirSync(outDir, { recursive: true }); // --- 1. truncated.jpg: a real JPEG cut off at 40% --------------------------- const realJpeg = readFileSync(join(root, "tests", "fixtures", "sample-photo.jpg")); -writeFileSync(join(outDir, "truncated.jpg"), realJpeg.subarray(0, Math.floor(realJpeg.length * 0.4))); +writeFileSync( + join(outDir, "truncated.jpg"), + realJpeg.subarray(0, Math.floor(realJpeg.length * 0.4)), +); // --- 2. zero-byte.png -------------------------------------------------------- writeFileSync(join(outDir, "zero-byte.png"), Buffer.alloc(0)); diff --git a/scripts/generate-test-fixtures.mjs b/scripts/generate-test-fixtures.mjs index cd813fd9..02c19f3b 100644 --- a/scripts/generate-test-fixtures.mjs +++ b/scripts/generate-test-fixtures.mjs @@ -1,4 +1,6 @@ #!/usr/bin/env node +import { spawnSync } from "node:child_process"; +import { mkdirSync, writeFileSync } from "node:fs"; /** * Generates the tiny media/document fixtures committed under tests/fixtures/. * Requires ffmpeg on PATH (or FFMPEG_PATH) and qpdf (or QPDF_PATH). @@ -6,9 +8,7 @@ * node scripts/generate-test-fixtures.mjs */ import { createRequire } from "node:module"; -import { spawnSync } from "node:child_process"; -import { mkdirSync, writeFileSync } from "node:fs"; -import { join, dirname } from "node:path"; +import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; const __dirname = dirname(fileURLToPath(import.meta.url)); @@ -38,17 +38,52 @@ function run(args) { } // 1s 64x64 mp4 with video + audio (h264 + aac; needed by extract-audio + mute-video) -run(["-f", "lavfi", "-i", "testsrc=duration=1:size=64x64:rate=8", - "-f", "lavfi", "-i", "sine=frequency=440:duration=1", - "-c:v", "libx264", "-preset", "ultrafast", "-pix_fmt", "yuv420p", - "-c:a", "aac", "-b:a", "32k", "-shortest", - join(mediaDir, "tiny.mp4")]); +run([ + "-f", + "lavfi", + "-i", + "testsrc=duration=1:size=64x64:rate=8", + "-f", + "lavfi", + "-i", + "sine=frequency=440:duration=1", + "-c:v", + "libx264", + "-preset", + "ultrafast", + "-pix_fmt", + "yuv420p", + "-c:a", + "aac", + "-b:a", + "32k", + "-shortest", + join(mediaDir, "tiny.mp4"), +]); // 1s sine mp3 -run(["-f", "lavfi", "-i", "sine=frequency=440:duration=1", "-c:a", "libmp3lame", "-b:a", "32k", - join(mediaDir, "tiny.mp3")]); +run([ + "-f", + "lavfi", + "-i", + "sine=frequency=440:duration=1", + "-c:a", + "libmp3lame", + "-b:a", + "32k", + join(mediaDir, "tiny.mp3"), +]); // 1s sine wav -run(["-f", "lavfi", "-i", "sine=frequency=440:duration=1", "-c:a", "pcm_s16le", "-ar", "8000", - join(mediaDir, "tiny.wav")]); +run([ + "-f", + "lavfi", + "-i", + "sine=frequency=440:duration=1", + "-c:a", + "pcm_s16le", + "-ar", + "8000", + join(mediaDir, "tiny.wav"), +]); // Minimal OOXML/EPUB containers via archiver (resolved from apps/api). const apiRequire = createRequire(join(root, "apps/api/package.json")); @@ -108,7 +143,11 @@ await writeZip(join(docsDir, "tiny.xlsx"), { // EPUB requires the mimetype entry FIRST and STORED (uncompressed). await writeZip( join(docsDir, "tiny.epub"), - { "META-INF/container.xml": epubContainer, "OEBPS/content.opf": epubOpf, "OEBPS/chapter.xhtml": epubChapter }, + { + "META-INF/container.xml": epubContainer, + "OEBPS/content.opf": epubOpf, + "OEBPS/chapter.xhtml": epubChapter, + }, { name: "mimetype", content: "application/epub+zip" }, ); diff --git a/tests/e2e-pg-create-db.cjs b/tests/e2e-pg-create-db.cjs index da1a24f7..848a6ba6 100644 --- a/tests/e2e-pg-create-db.cjs +++ b/tests/e2e-pg-create-db.cjs @@ -16,8 +16,7 @@ const apiRequire = createRequire(join(process.cwd(), "apps/api/package.json")); const pg = apiRequire("pg"); const baseUrl = - process.env.E2E_PG_BASE_URL || - "postgres://snapotter:snapotter@localhost:5432/snapotter"; + process.env.E2E_PG_BASE_URL || "postgres://snapotter:snapotter@localhost:5432/snapotter"; const dbName = process.argv[2]; if (!dbName) { diff --git a/tests/helpers/enterprise-mock.ts b/tests/helpers/enterprise-mock.ts index 6fe3aab0..2f618db7 100644 --- a/tests/helpers/enterprise-mock.ts +++ b/tests/helpers/enterprise-mock.ts @@ -1,18 +1,15 @@ -import { vi } from "vitest"; import type { EnterpriseFeature } from "@snapotter/enterprise"; +import { vi } from "vitest"; export function mockEnterpriseFeatures(features: EnterpriseFeature[]) { vi.doMock("@snapotter/enterprise", () => ({ - isFeatureEnabled: (feature: string) => - features.includes(feature as EnterpriseFeature), + isFeatureEnabled: (feature: string) => features.includes(feature as EnterpriseFeature), getActiveLicense: () => ({ org: "test-org", plan: "enterprise" as const, features, seats: 100, - expiresAt: new Date( - Date.now() + 365 * 24 * 60 * 60 * 1000, - ).toISOString(), + expiresAt: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString(), issuedAt: new Date().toISOString(), }), initEnterprise: vi.fn(), diff --git a/tests/integration/audit-export.test.ts b/tests/integration/audit-export.test.ts index 600545f5..46a16d85 100644 --- a/tests/integration/audit-export.test.ts +++ b/tests/integration/audit-export.test.ts @@ -1,7 +1,7 @@ +import { eq } from "drizzle-orm"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { db, schema } from "../../apps/api/src/db/index.js"; import { buildTestApp, loginAsAdmin, type TestApp } from "./test-server.js"; -import { eq } from "drizzle-orm"; let testApp: TestApp; let adminToken: string; diff --git a/tests/integration/audit-tool-operations.test.ts b/tests/integration/audit-tool-operations.test.ts index 2984666e..fdcc6ed4 100644 --- a/tests/integration/audit-tool-operations.test.ts +++ b/tests/integration/audit-tool-operations.test.ts @@ -39,9 +39,7 @@ async function setSetting(key: string, value: string): Promise { expect(res.statusCode).toBe(200); } -async function fetchAuditLog( - action: string, -): Promise<{ entries: any[]; total: number }> { +async function fetchAuditLog(action: string): Promise<{ entries: any[]; total: number }> { const res = await testApp.app.inject({ method: "GET", url: `/api/v1/audit-log?action=${action}`, diff --git a/tests/integration/siem-forwarding.test.ts b/tests/integration/siem-forwarding.test.ts index 8447158a..de4df44b 100644 --- a/tests/integration/siem-forwarding.test.ts +++ b/tests/integration/siem-forwarding.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, beforeAll, afterAll } from "vitest"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { buildTestApp, loginAsAdmin, type TestApp } from "./test-server.js"; let testApp: TestApp; diff --git a/tests/unit/api/audit-integrity.test.ts b/tests/unit/api/audit-integrity.test.ts index 1d312bc3..5b9b71df 100644 --- a/tests/unit/api/audit-integrity.test.ts +++ b/tests/unit/api/audit-integrity.test.ts @@ -1,5 +1,9 @@ -import { describe, it, expect } from "vitest"; -import { canonicalize, computeHmac, verifyHmac } from "../../../apps/api/src/lib/audit-integrity.js"; +import { describe, expect, it } from "vitest"; +import { + canonicalize, + computeHmac, + verifyHmac, +} from "../../../apps/api/src/lib/audit-integrity.js"; describe("audit integrity", () => { const testKey = Buffer.from("a".repeat(64), "hex"); diff --git a/tests/unit/api/encryption.test.ts b/tests/unit/api/encryption.test.ts index 005472ff..d4766d05 100644 --- a/tests/unit/api/encryption.test.ts +++ b/tests/unit/api/encryption.test.ts @@ -1,9 +1,9 @@ -import { describe, it, expect } from "vitest"; +import { describe, expect, it } from "vitest"; import { - encrypt, decrypt, - isEncrypted, deriveAuditHmacKey, + encrypt, + isEncrypted, } from "../../../apps/api/src/lib/encryption.js"; describe("encryption", () => { diff --git a/tests/unit/api/enterprise-flags.test.ts b/tests/unit/api/enterprise-flags.test.ts index 0ea870c6..9aed611a 100644 --- a/tests/unit/api/enterprise-flags.test.ts +++ b/tests/unit/api/enterprise-flags.test.ts @@ -1,5 +1,5 @@ -import { describe, expect, it } from "vitest"; import { ENTERPRISE_FEATURES, PLAN_FEATURES } from "@snapotter/enterprise"; +import { describe, expect, it } from "vitest"; describe("enterprise feature flags", () => { it("includes all Phase 1 flags", () => { diff --git a/tests/unit/api/enterprise-mock.test.ts b/tests/unit/api/enterprise-mock.test.ts index 50e67c43..2876e09a 100644 --- a/tests/unit/api/enterprise-mock.test.ts +++ b/tests/unit/api/enterprise-mock.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; describe("enterprise mock", () => { beforeEach(() => { @@ -6,9 +6,7 @@ describe("enterprise mock", () => { }); it("mocks feature enabled", async () => { - const { mockEnterpriseFeatures } = await import( - "../../helpers/enterprise-mock.js" - ); + const { mockEnterpriseFeatures } = await import("../../helpers/enterprise-mock.js"); mockEnterpriseFeatures(["audit_export", "siem_forwarding"]); const { isFeatureEnabled } = await import("@snapotter/enterprise"); expect(isFeatureEnabled("audit_export")).toBe(true); @@ -17,18 +15,14 @@ describe("enterprise mock", () => { }); it("mocks no enterprise", async () => { - const { mockNoEnterprise } = await import( - "../../helpers/enterprise-mock.js" - ); + const { mockNoEnterprise } = await import("../../helpers/enterprise-mock.js"); mockNoEnterprise(); const { isFeatureEnabled } = await import("@snapotter/enterprise"); expect(isFeatureEnabled("audit_export")).toBe(false); }); it("returns license payload with correct shape", async () => { - const { mockEnterpriseFeatures } = await import( - "../../helpers/enterprise-mock.js" - ); + const { mockEnterpriseFeatures } = await import("../../helpers/enterprise-mock.js"); mockEnterpriseFeatures(["s3_storage", "mfa"]); const { getActiveLicense } = await import("@snapotter/enterprise"); const license = getActiveLicense(); @@ -41,9 +35,7 @@ describe("enterprise mock", () => { }); it("returns null license when no enterprise", async () => { - const { mockNoEnterprise } = await import( - "../../helpers/enterprise-mock.js" - ); + const { mockNoEnterprise } = await import("../../helpers/enterprise-mock.js"); mockNoEnterprise(); const { getActiveLicense } = await import("@snapotter/enterprise"); expect(getActiveLicense()).toBeNull(); diff --git a/tests/unit/api/webhook-delivery.test.ts b/tests/unit/api/webhook-delivery.test.ts index 6bb69fa3..54be4a3a 100644 --- a/tests/unit/api/webhook-delivery.test.ts +++ b/tests/unit/api/webhook-delivery.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; describe("webhook delivery", () => { beforeEach(() => { @@ -15,11 +15,9 @@ describe("webhook delivery", () => { vi.stubGlobal("fetch", fetchMock); const { deliverWebhook } = await import("../../../apps/api/src/lib/webhook-delivery.js"); - const result = await deliverWebhook( - "https://siem.example.com/input", - "Bearer test-token", - [{ event: "LOGIN_SUCCESS", timestamp: "2026-01-01T00:00:00Z" }], - ); + const result = await deliverWebhook("https://siem.example.com/input", "Bearer test-token", [ + { event: "LOGIN_SUCCESS", timestamp: "2026-01-01T00:00:00Z" }, + ]); expect(result.success).toBe(true); expect(result.attempts).toBe(1);