ci: fix port 5432 collision and include read-only-prisma helper
CI / Architecture Guardrails (push) Successful in 1m37s
CI / Assistant Split Regression (push) Failing after 4m58s
CI / Typecheck (push) Failing after 5m18s
CI / Build (push) Has been skipped
CI / E2E Tests (push) Has been skipped
CI / Fresh-Linux Docker Deploy (push) Has been skipped
CI / Lint (push) Successful in 6m18s
CI / Unit Tests (push) Failing after 5m16s
CI / Release Images (push) Has been skipped

- Remove host port mappings from postgres/redis services in ci.yml;
  QNAP runner already occupies 5432. Use service DNS names
  (postgres/redis) instead of localhost for DB/Redis URLs.
- Track packages/api/src/lib/read-only-prisma.ts which was imported
  by assistant-tools.ts but never committed, breaking check:imports.
This commit is contained in:
2026-04-12 16:25:19 +02:00
parent 3391ae5ce6
commit 561c7bf42d
2 changed files with 61 additions and 12 deletions
+4 -12
View File
@@ -161,8 +161,6 @@ jobs:
POSTGRES_DB: capakraken_test
POSTGRES_USER: capakraken
POSTGRES_PASSWORD: capakraken_test
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U capakraken -d capakraken_test"
--health-interval=10s
@@ -170,16 +168,14 @@ jobs:
--health-retries=5
redis:
image: redis:7
ports:
- 6379:6379
options: >-
--health-cmd="redis-cli ping"
--health-interval=10s
--health-timeout=5s
--health-retries=5
env:
DATABASE_URL: postgresql://capakraken:capakraken_test@localhost:5432/capakraken_test
REDIS_URL: redis://localhost:6379
DATABASE_URL: postgresql://capakraken:capakraken_test@postgres:5432/capakraken_test
REDIS_URL: redis://redis:6379
NEXTAUTH_URL: ${{ env.CI_AUTH_URL }}
AUTH_URL: ${{ env.CI_AUTH_URL }}
NEXTAUTH_SECRET: ${{ env.CI_AUTH_SECRET }}
@@ -286,8 +282,6 @@ jobs:
POSTGRES_DB: capakraken_test
POSTGRES_USER: capakraken
POSTGRES_PASSWORD: capakraken_test
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U capakraken -d capakraken_test"
--health-interval=10s
@@ -295,18 +289,16 @@ jobs:
--health-retries=5
redis:
image: redis:7
ports:
- 6379:6379
options: >-
--health-cmd="redis-cli ping"
--health-interval=10s
--health-timeout=5s
--health-retries=5
env:
DATABASE_URL: postgresql://capakraken:capakraken_test@localhost:5432/capakraken_test
DATABASE_URL: postgresql://capakraken:capakraken_test@postgres:5432/capakraken_test
ALLOW_DESTRUCTIVE_DB_TOOLS: "true"
CONFIRM_DESTRUCTIVE_DB_NAME: capakraken_test
REDIS_URL: redis://localhost:6379
REDIS_URL: redis://redis:6379
PORT: 3100
NEXTAUTH_URL: ${{ env.CI_AUTH_URL }}
AUTH_URL: ${{ env.CI_AUTH_URL }}
+57
View File
@@ -0,0 +1,57 @@
/**
* Read-only Prisma proxy.
*
* Wraps a PrismaClient and blocks write operations at the application level.
* Used to enforce read-only access for AI read-tools (EGAI 4.1.1.2 / IAAI 3.6.22).
*/
import type { prisma } from "@capakraken/db";
type PrismaClient = typeof prisma;
const WRITE_METHODS = new Set([
"create",
"createMany",
"createManyAndReturn",
"update",
"updateMany",
"upsert",
"delete",
"deleteMany",
]);
function readOnlyModelProxy(model: Record<string, unknown>, modelName: string): unknown {
return new Proxy(model, {
get(target, prop) {
if (typeof prop === "string" && WRITE_METHODS.has(prop)) {
return () => {
throw new Error(
`Write operation "${prop}" on "${modelName}" not permitted on read-only context`,
);
};
}
return Reflect.get(target, prop);
},
});
}
export function createReadOnlyProxy(client: PrismaClient): PrismaClient {
return new Proxy(client, {
get(target, prop) {
const value = Reflect.get(target, prop);
// If accessing a model delegate (object with findMany, etc.), wrap it
if (value && typeof value === "object" && "findMany" in (value as Record<string, unknown>)) {
return readOnlyModelProxy(value as Record<string, unknown>, String(prop));
}
// Block $executeRaw and $executeRawUnsafe at the client level
if (prop === "$executeRaw" || prop === "$executeRawUnsafe") {
return () => {
throw new Error(
`Raw write operation "${String(prop)}" not permitted on read-only context`,
);
};
}
return value;
},
}) as PrismaClient;
}