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
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:
@@ -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 }}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user