Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
8b8e2fc
chore: merge release v3.13.1 back to main [skip ci]
github-actions[bot] Mar 30, 2026
90283b6
chore: update error logs for GCP
github-actions[bot] Mar 31, 2026
f461c4d
fix(company): make Access Request form options in Documents (#2369)
github-actions[bot] Mar 31, 2026
0586dfe
fix(app): comment button gets disabled with numbered formatting (#2368)
github-actions[bot] Mar 31, 2026
b824384
chore(email): remove unused next dependency (#2407)
Marfuen Mar 31, 2026
645dd48
chore(deps-dev): bump electron (#2345)
dependabot[bot] Mar 31, 2026
12e5e3a
fix: Enable 'Ready for Review' menu for client on Document Finding (#…
github-actions[bot] Mar 31, 2026
a04c486
feat: remove Ramp integration entirely
tofikwest Mar 31, 2026
3d6d1d4
fix: handle stale Ramp sync provider in legacy orgs
tofikwest Mar 31, 2026
a3313cd
fix: scope stale provider cleanup to ramp only
tofikwest Mar 31, 2026
da6ab06
Merge pull request #2408 from trycompai/tofik/remove-ramp-integration
tofikwest Mar 31, 2026
67aacf5
fix(portal): remove getJwtToken and use session-cookie auth directly
chasprowebdev Apr 1, 2026
52d5288
Merge pull request #2413 from trycompai/chas/portal-submit-error
tofikwest Apr 1, 2026
ffb260b
fix(auth): make Microsoft OAuth tenantId configurable via env var (#2…
paradoxbound Apr 1, 2026
30516d4
feat(app, api, framework-editor): restructure compliance app and add …
github-actions[bot] Apr 1, 2026
59e0db9
feat: migrate prisma from v6 to v7
github-actions[bot] Apr 2, 2026
3e29382
fix(db): use process.env fallback for DATABASE_URL in prisma.config.t…
github-actions[bot] Apr 2, 2026
977a705
fix: use process.env fallback for DATABASE_URL in all prisma.config.t…
github-actions[bot] Apr 2, 2026
451c6a1
fix: add SSL support to PrismaPg adapter for RDS/staging (rejectUnaut…
github-actions[bot] Apr 2, 2026
f688334
fix: set trigger.dev runtime to node-22 (Prisma v7 requires node >=20…
github-actions[bot] Apr 2, 2026
00e6f13
fix: strip sslmode from connection string before passing to pg (preve…
github-actions[bot] Apr 2, 2026
8a05e29
fix(db): point prisma.config.ts to schema directory for multi-file sc…
Marfuen Apr 2, 2026
13a7b77
fix(api): pin prisma@7.6.0 in Dockerfile generate step (prevents stal…
github-actions[bot] Apr 2, 2026
dc9351c
fix(api): upgrade Dockerfile base images for Prisma v7 Node.js requir…
Marfuen Apr 2, 2026
a98cf93
fix(db): remove dotenv/config import from prisma.config.ts (not avail…
Marfuen Apr 2, 2026
fab6693
fix: use installed prisma binary instead of bunx (fixes prisma/config…
Marfuen Apr 2, 2026
c58045f
refactor: simplify prisma schema sharing using native v7 multi-file s…
github-actions[bot] Apr 2, 2026
98213f8
fix: default to SSL for non-localhost connections, remove buggy clean…
github-actions[bot] Apr 2, 2026
863f14b
fix: use AWS RDS CA bundle for proper SSL verification, simplify clie…
Marfuen Apr 2, 2026
772ac48
fix: install ca-certificates before wget, clean apt after download (#…
Marfuen Apr 2, 2026
b7b7944
fix: install ca-certificates before wget, clean apt after download (#…
github-actions[bot] Apr 2, 2026
335dcd2
fix: strip sslmode from DATABASE_URL to avoid conflict with explicit …
Marfuen Apr 2, 2026
64e7e0a
[dev] [Marfuen] mariano/fix-strip-sslmode-from-connection-string (#2436)
github-actions[bot] Apr 2, 2026
cf9990b
[dev] [Marfuen] mariano/fix-strip-sslmode-from-connection-string (#2437)
github-actions[bot] Apr 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 3 additions & 4 deletions .github/workflows/trigger-api-tasks-deploy-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ jobs:
- name: Build DB package
working-directory: ./packages/db
run: bun run build
- name: Copy schema to api and generate client
- name: Copy model files to api schema dir and generate client
working-directory: ./apps/api
run: |
mkdir -p prisma
cp ../../packages/db/dist/schema.prisma prisma/schema.prisma
bunx prisma generate
find ../../packages/db/prisma/schema -name '*.prisma' ! -name 'schema.prisma' -exec cp {} prisma/schema/ \;
bunx prisma generate --schema=prisma/schema
- name: 🚀 Deploy Trigger.dev
working-directory: ./apps/api
timeout-minutes: 20
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/trigger-api-tasks-deploy-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,11 @@ jobs:
working-directory: ./packages/db
run: bun run build

- name: Copy schema to api and generate client
- name: Copy model files to api schema dir and generate client
working-directory: ./apps/api
run: |
mkdir -p prisma
cp ../../packages/db/dist/schema.prisma prisma/schema.prisma
bunx prisma generate
find ../../packages/db/prisma/schema -name '*.prisma' ! -name 'schema.prisma' -exec cp {} prisma/schema/ \;
bunx prisma generate --schema=prisma/schema

- name: 🚀 Deploy Trigger.dev
working-directory: ./apps/api
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/trigger-tasks-deploy-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ jobs:
- name: Copy schema to app and generate client
working-directory: ./apps/app
run: |
mkdir -p prisma
cp ../../packages/db/dist/schema.prisma prisma/schema.prisma
bunx prisma generate
mkdir -p prisma/schema
find ../../packages/db/prisma/schema -name '*.prisma' ! -name 'schema.prisma' -exec cp {} prisma/schema/ \;
bunx prisma generate --schema=prisma/schema
- name: 🚀 Deploy Trigger.dev
working-directory: ./apps/app
timeout-minutes: 20
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/trigger-tasks-deploy-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ jobs:
- name: Copy schema to app and generate client
working-directory: ./apps/app
run: |
mkdir -p prisma
cp ../../packages/db/dist/schema.prisma prisma/schema.prisma
bunx prisma generate
mkdir -p prisma/schema
find ../../packages/db/prisma/schema -name '*.prisma' ! -name 'schema.prisma' -exec cp {} prisma/schema/ \;
bunx prisma generate --schema=prisma/schema

- name: 🚀 Deploy Trigger.dev
working-directory: ./apps/app
Expand Down
5 changes: 5 additions & 0 deletions apps/api/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ APP_AWS_SECRET_ACCESS_KEY=
APP_AWS_ORG_ASSETS_BUCKET=
APP_AWS_ENDPOINT="" # optional for using services like MinIO

# Microsoft sign-in (Entra ID / Azure AD)
AUTH_MICROSOFT_CLIENT_ID=
AUTH_MICROSOFT_CLIENT_SECRET=
AUTH_MICROSOFT_TENANT_ID= # 'common' (default), 'organizations', or your tenant GUID

DATABASE_URL=

NOVU_API_KEY=
Expand Down
4 changes: 3 additions & 1 deletion apps/api/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ pids
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json


prisma/schema.prisma
# Model files are copied here by db:getschema — only schema.prisma is committed
prisma/schema/*.prisma
!prisma/schema/schema.prisma
trigger.config.js
test/**/*.js
23 changes: 14 additions & 9 deletions apps/api/Dockerfile.multistage
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/package.json ./package.json
COPY --from=deps /app/bun.lock ./bun.lock

# Copy workspace packages source
# Copy workspace packages source (node_modules excluded by .dockerignore,
# but COPY replaces directories so workspace node_modules from deps get wiped)
COPY packages/auth ./packages/auth
COPY packages/db ./packages/db
COPY packages/utils ./packages/utils
Expand All @@ -58,7 +59,7 @@ COPY packages/company ./packages/company
# Copy API source
COPY apps/api ./apps/api

# Build db first — generates Prisma client needed by other packages
# Build db — generates Prisma client + compiles dist/ for @trycompai/db consumers
RUN cd packages/db && bun run build

# Build remaining workspace packages
Expand All @@ -67,24 +68,28 @@ RUN cd packages/auth && bun run build \
&& cd ../email && bun run build \
&& cd ../company && bun run build

# Generate Prisma schema for API and build NestJS app
RUN cd packages/db && node scripts/combine-schemas.js \
&& cp /app/packages/db/dist/schema.prisma /app/apps/api/prisma/schema.prisma \
&& cd /app/apps/api && bunx prisma generate && bunx nest build
# Copy model files to api schema dir, then build NestJS app
# Note: @prisma/client is already generated by packages/db build (generate-prisma-client-js.js)
RUN find /app/packages/db/prisma/schema -name '*.prisma' ! -name 'schema.prisma' -exec cp {} /app/apps/api/prisma/schema/ \; \
&& cd /app/apps/api && bunx nest build

# =============================================================================
# STAGE 3: Production Runtime
# =============================================================================
FROM node:20-slim AS production
FROM node:22-slim AS production

# Create non-root user before copying files so COPY --chown can use it
RUN groupadd --system nestjs && useradd --system --gid nestjs --create-home nestjs

WORKDIR /app
RUN chown nestjs:nestjs /app

# Install runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends wget openssl && rm -rf /var/lib/apt/lists/*
# Install runtime dependencies + AWS RDS CA certificate bundle
RUN apt-get update && apt-get install -y --no-install-recommends wget ca-certificates \
&& wget -q -O /usr/local/share/aws-rds-ca-bundle.pem https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem \
&& apt-get clean && rm -rf /var/lib/apt/lists/*

ENV NODE_EXTRA_CA_CERTS=/usr/local/share/aws-rds-ca-bundle.pem

# Copy built NestJS app
COPY --from=builder --chown=nestjs:nestjs /app/apps/api/dist ./dist
Expand Down
44 changes: 30 additions & 14 deletions apps/api/customPrismaExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ export class PrismaExtension implements BuildExtension {
constructor(private options: PrismaExtensionOptions) {
this.moduleExternals = [
'@prisma/client',
'@prisma/engines',
'@trycompai/db', // Add the published package to externals
'@trycompai/db',
];
}

Expand Down Expand Up @@ -115,17 +114,23 @@ export class PrismaExtension implements BuildExtension {
const env: Record<string, string | undefined> = {};

// Copy the prisma schema from the published package to the build output path
const schemaDestinationPath = join(manifest.outputPath, 'prisma', 'schema.prisma');
const schemaDestinationDir = dirname(schemaDestinationPath);
// Copy the entire schema directory (multi-file schema)
const sourceDir = dirname(schemaPath);
const schemaDestinationDir = join(manifest.outputPath, 'prisma', 'schema');
context.logger.debug(
`Copying the prisma schema from ${schemaPath} to ${schemaDestinationPath}`,
`Copying the prisma schema directory from ${sourceDir} to ${schemaDestinationDir}`,
);
await mkdir(schemaDestinationDir, { recursive: true });
await cp(schemaPath, schemaDestinationPath);
await cp(sourceDir, schemaDestinationDir, { recursive: true });

// Add prisma generate command to generate the client from the copied schema
// Patch schema.prisma to use prisma-client-js (populates @prisma/client at runtime)
commands.push(
`${binaryForRuntime(manifest.runtime)} node_modules/prisma/build/index.js generate --schema=./prisma/schema.prisma`,
`sed -i 's/provider.*=.*"prisma-client"/provider = "prisma-client-js"/' ./prisma/schema/schema.prisma && sed -i '/output.*=.*"/d' ./prisma/schema/schema.prisma`,
);

// Generate client from the multi-file schema directory
commands.push(
`${binaryForRuntime(manifest.runtime)} node_modules/prisma/build/index.js generate --schema=./prisma/schema`,
);

// Only handle migrations if requested
Expand Down Expand Up @@ -186,11 +191,22 @@ export class PrismaExtension implements BuildExtension {
context: ExtendedBuildContext,
schemaSourcePath: string,
): Promise<void> {
const schemaDir = resolve(context.workingDir, 'prisma');
const schemaDestinationPath = resolve(schemaDir, 'schema.prisma');

await mkdir(schemaDir, { recursive: true });
await cp(schemaSourcePath, schemaDestinationPath);
// schemaSourcePath points to a file inside the schema directory.
// Copy the entire directory (multi-file schema) to the local prisma/schema/ dir.
const sourceDir = dirname(schemaSourcePath);
const localSchemaDir = resolve(context.workingDir, 'prisma', 'schema');

await mkdir(localSchemaDir, { recursive: true });
await cp(sourceDir, localSchemaDir, { recursive: true });

// Patch schema.prisma to use prisma-client-js (default output → @prisma/client)
const localSchemaFile = resolve(localSchemaDir, 'schema.prisma');
const { readFileSync, writeFileSync } = await import('node:fs');
let schemaContent = readFileSync(localSchemaFile, 'utf8');
schemaContent = schemaContent
.replace(/provider\s*=\s*"prisma-client"/g, 'provider = "prisma-client-js"')
.replace(/\s*output\s*=\s*"[^"]*"\n?/g, '\n');
writeFileSync(localSchemaFile, schemaContent);

const clientEntryPoint = resolve(context.workingDir, 'node_modules/.prisma/client/default.js');

Expand All @@ -209,7 +225,7 @@ export class PrismaExtension implements BuildExtension {
}

context.logger.log('Prisma client missing. Generating before Trigger indexing.');
await this.runPrismaGenerate(context, prismaBinary, schemaDestinationPath);
await this.runPrismaGenerate(context, prismaBinary, localSchemaDir);
}

private runPrismaGenerate(
Expand Down
15 changes: 8 additions & 7 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@
"@nestjs/platform-express": "^11.1.5",
"@nestjs/swagger": "^11.2.0",
"@nestjs/throttler": "^6.5.0",
"@prisma/client": "6.18.0",
"@prisma/instrumentation": "^6.13.0",
"@prisma/adapter-pg": "7.6.0",
"@prisma/client": "7.6.0",
"@prisma/instrumentation": "7.6.0",
"@react-email/components": "^0.0.41",
"@react-email/render": "^2.0.4",
"@thallesp/nestjs-better-auth": "^2.4.0",
"@trigger.dev/build": "4.4.3",
"@trigger.dev/sdk": "4.4.3",
"@trycompai/auth": "workspace:*",
"@trycompai/company": "workspace:*",
"@trycompai/db": "1.3.22",
"@trycompai/db": "workspace:*",
"@trycompai/email": "workspace:*",
"@trycompai/integration-platform": "workspace:*",
"@upstash/ratelimit": "^2.0.8",
Expand All @@ -54,7 +55,7 @@
"nanoid": "^5.1.6",
"pdf-lib": "^1.17.1",
"playwright-core": "^1.57.0",
"prisma": "6.18.0",
"prisma": "7.6.0",
"react": "^19.1.1",
"react-dom": "^19.1.0",
"reflect-metadata": "^0.2.2",
Expand Down Expand Up @@ -121,9 +122,9 @@
"private": true,
"scripts": {
"build": "nest build",
"build:docker": "bunx prisma generate && nest build",
"db:generate": "bun run db:getschema && bunx prisma generate",
"db:getschema": "node ../../packages/db/scripts/combine-schemas.js && cp ../../packages/db/dist/schema.prisma prisma/schema.prisma",
"build:docker": "bunx prisma generate --schema=prisma/schema && nest build",
"db:generate": "bun run db:getschema && bunx prisma generate --schema=prisma/schema",
"db:getschema": "find ../../packages/db/prisma/schema -name '*.prisma' ! -name 'schema.prisma' -exec cp {} prisma/schema/ \\;",
"db:migrate": "cd ../../packages/db && bunx prisma migrate dev && cd ../../apps/api",
"deploy:trigger-prod": "npx trigger.dev@4.4.3 deploy",
"dev": "bunx concurrently --kill-others --names \"nest,trigger\" --prefix-colors \"green,blue\" \"nest start --watch\" \"trigger dev\"",
Expand Down
2 changes: 0 additions & 2 deletions apps/api/prisma/client.d.ts

This file was deleted.

22 changes: 21 additions & 1 deletion apps/api/prisma/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
import { PrismaClient } from '@prisma/client';
import { PrismaPg } from '@prisma/adapter-pg';

const globalForPrisma = global as unknown as { prisma: PrismaClient };

export const db = globalForPrisma.prisma || new PrismaClient();
function stripSslMode(connectionString: string): string {
const url = new URL(connectionString);
url.searchParams.delete('sslmode');
return url.toString();
}

function createPrismaClient(): PrismaClient {
const rawUrl = process.env.DATABASE_URL!;
const isLocalhost = /localhost|127\.0\.0\.1|::1/.test(rawUrl);
// Use verified SSL when NODE_EXTRA_CA_CERTS is set (Docker with RDS CA bundle),
// otherwise fall back to unverified SSL (Trigger.dev, Vercel, other environments).
const hasCABundle = !!process.env.NODE_EXTRA_CA_CERTS;
const ssl = isLocalhost ? undefined : hasCABundle ? true : { rejectUnauthorized: false };
// Strip sslmode from the connection string to avoid conflicts with the explicit ssl option
const url = ssl !== undefined ? stripSslMode(rawUrl) : rawUrl;
const adapter = new PrismaPg({ connectionString: url, ssl });
return new PrismaClient({ adapter });
}

export const db = globalForPrisma.prisma || createPrismaClient();

if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db;
9 changes: 9 additions & 0 deletions apps/api/prisma/schema/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
generator client {
provider = "prisma-client-js"
previewFeatures = ["postgresqlExtensions"]
}

datasource db {
provider = "postgresql"
extensions = [pgcrypto]
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jest.mock('../auth/auth.server', () => ({
auth: { api: {} },
}));

jest.mock('@trycompai/db', () => ({ db: {} }));
jest.mock('@db', () => ({ db: {} }));

describe('AdminContextController', () => {
let controller: AdminContextController;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jest.mock('../auth/auth.server', () => ({
auth: { api: {} },
}));

jest.mock('@trycompai/db', () => ({ db: {} }));
jest.mock('@db', () => ({ db: {} }));

describe('AdminEvidenceController', () => {
let controller: AdminEvidenceController;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jest.mock('../auth/auth.server', () => ({
auth: { api: {} },
}));

jest.mock('@trycompai/db', () => ({
jest.mock('@db', () => ({
db: {},
FindingStatus: {
open: 'open',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { Throttle } from '@nestjs/throttler';
import { FindingStatus } from '@trycompai/db';
import { FindingStatus } from '@db';
import { PlatformAdminGuard } from '../auth/platform-admin.guard';
import { FindingsService } from '../findings/findings.service';
import { CreateFindingDto } from '../findings/dto/create-finding.dto';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jest.mock('../auth/auth.server', () => ({
},
}));

jest.mock('@trycompai/db', () => ({
jest.mock('@db', () => ({
db: {
user: {
findUnique: (...args: unknown[]) => mockFindUnique(...args),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jest.mock('../auth/auth.server', () => ({
auth: { api: {} },
}));

jest.mock('@trycompai/db', () => ({ db: {} }));
jest.mock('@db', () => ({ db: {} }));

describe('AdminOrganizationsController', () => {
let controller: AdminOrganizationsController;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NotFoundException, BadRequestException } from '@nestjs/common';
import { AdminOrganizationsService } from './admin-organizations.service';

jest.mock('@trycompai/db', () => ({
jest.mock('@db', () => ({
db: {
organization: {
findMany: jest.fn(),
Expand Down Expand Up @@ -33,7 +33,7 @@ jest.mock('../email/templates/invite-member', () => ({
InviteEmail: jest.fn().mockReturnValue(null),
}));

import { db } from '@trycompai/db';
import { db } from '@db';

const mockDb = db as jest.Mocked<typeof db>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
BadRequestException,
Logger,
} from '@nestjs/common';
import { AuditLogEntityType, db } from '@trycompai/db';
import { AuditLogEntityType, db } from '@db';
import { triggerEmail } from '../email/trigger-email';
import { InviteEmail } from '../email/templates/invite-member';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jest.mock('../auth/auth.server', () => ({
auth: { api: {} },
}));

jest.mock('@trycompai/db', () => ({
jest.mock('@db', () => ({
db: {
frameworkInstance: { findMany: jest.fn().mockResolvedValue([]) },
context: { findMany: jest.fn().mockResolvedValue([]) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { Throttle } from '@nestjs/throttler';
import { db } from '@trycompai/db';
import { db } from '@db';
import {
PolicyStatus,
Frequency,
Expand Down
Loading
Loading