Skip to content

[1a] Project scaffolding + core schema#20

Merged
andrmaz merged 6 commits into
mainfrom
cursor/project-scaffolding-core-schema-65bb
Jun 4, 2026
Merged

[1a] Project scaffolding + core schema#20
andrmaz merged 6 commits into
mainfrom
cursor/project-scaffolding-core-schema-65bb

Conversation

@andrmaz

@andrmaz andrmaz commented Jun 4, 2026

Copy link
Copy Markdown
Owner

Summary

This PR sets up the TypeScript monorepo infrastructure and defines the foundational Prisma schema for the Cortex platform.

Changes

Monorepo Configuration

  • Fixed all package references from @repo/* to @cortex/* namespace
  • Added check-types and build scripts to db and shared packages
  • Updated turbo.json with proper output configurations
  • Added .prettierignore to exclude generated files

Prisma Schema (packages/db)

  • Organization: Tenant boundary representing one customer company
  • User: Authenticated identity with Google SSO, belonging to one Organization
  • Department: Policy scope within an Organization
  • UserDepartment: Join table for many-to-many user-department mapping with primary department designation
  • Source: Upstream knowledge origins (uploads, Slack, Confluence)
  • Document: Normalized content units for retrieval
  • Chunk: Retrievable segments with embedding support
  • Policy: Versioned department-scoped rule sets
  • QueryLog: Immutable audit records

All models include:

  • Proper foreign key relationships with cascade deletes
  • Indexes for common query patterns
  • Organization-scoped unique constraints where appropriate

CI/CD

  • Added GitHub Actions workflow (.github/workflows/ci.yml) with:
    • Type checking
    • Linting
    • Build verification
    • Prisma schema validation

Infrastructure

  • docker-compose.yml provides PostgreSQL 16 and Redis 7
  • Initial migration SQL created at packages/db/prisma/migrations/0001_initial_schema/

Verification

# All passing:
pnpm install          #
pnpm check-types      #
pnpm build            #
pnpm lint             #
pnpm --filter db db:validate  #

Acceptance Criteria

  • Monorepo structure boots cleanly (pnpm install, pnpm check-types, pnpm build)
  • docker-compose up starts PostgreSQL and Redis with no manual steps
  • Prisma schema includes Organization, User, Department, UserDepartment models and passes prisma validate
  • First migration is created and baseline CI passes
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Established comprehensive database schema supporting multi-tenant organizations, users, departments, and policy management
    • Added audit logging for query tracking and policy decisions
  • Chores

    • Configured CI/CD pipeline with automated linting, type checking, building, and schema validation
    • Updated project configuration files and build tooling for improved development workflow
    • Restructured shared configuration and package exports across the monorepo

- Fix package references from @repo/* to @cortex/*
- Update Prisma schema with Organization, User, Department, UserDepartment models
- Add proper multi-tenant design with indexes and relations
- Add UserDepartment join table for many-to-many user-department mapping
- Add check-types and build scripts to db and shared packages
- Create initial Prisma migration SQL
- Add GitHub Actions CI workflow for type-check, lint, and build
- Update README with Cortex-specific documentation
- Add .prettierignore to exclude generated files
- Fix lint errors in API controller

Acceptance criteria:
- pnpm install, pnpm check-types, pnpm build all pass
- docker-compose.yml configured for PostgreSQL and Redis
- Prisma schema validates successfully
- CI skeleton established

Co-authored-by: Andrea Mazzucchelli <andrmaz@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@andrmaz, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 1 minute and 22 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f0f311f6-e360-48d0-a1f8-31179f74b57e

📥 Commits

Reviewing files that changed from the base of the PR and between 03047f1 and ba18bae.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (27)
  • .github/workflows/ci.yml
  • .prettierignore
  • README.md
  • apps/api/eslint.config.js
  • apps/api/package.json
  • apps/api/src/app.module.ts
  • apps/api/src/main.ts
  • apps/api/src/mcp/mcp.controller.ts
  • apps/api/src/mcp/mcp.module.ts
  • apps/docs/app/page.tsx
  • apps/docs/eslint.config.js
  • apps/docs/tsconfig.json
  • apps/web/app/page.tsx
  • apps/web/eslint.config.js
  • apps/web/tsconfig.json
  • packages/db/package.json
  • packages/db/prisma/migrations/0001_initial_schema/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/db/src/index.ts
  • packages/db/tsconfig.json
  • packages/shared/package.json
  • packages/shared/src/index.ts
  • packages/shared/src/types.ts
  • packages/shared/tsconfig.json
  • packages/ui/eslint.config.mjs
  • packages/ui/tsconfig.json
  • turbo.json
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/project-scaffolding-core-schema-65bb

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cursor cursor Bot mentioned this pull request Jun 4, 2026
4 tasks
@andrmaz

andrmaz commented Jun 4, 2026

Copy link
Copy Markdown
Owner Author

@cursoragent some checks are failing

@cursor

cursor Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Fixed the CI failure. The issue was a version conflict - the GitHub Actions workflow was explicitly specifying version: 9 for pnpm, but package.json already declares "packageManager": "pnpm@9.0.0". The pnpm/action-setup@v4 action detects both specifications and fails to prevent version mismatches.

I removed the explicit version: 9 from all three jobs in the workflow. The action will now automatically read the pnpm version from the packageManager field in package.json, which is the recommended approach.

The fix has been pushed and CI should re-run automatically.

View PR

Open in Web Open in Cursor 

The pnpm/action-setup@v4 action now reads the version from the
packageManager field in package.json, avoiding version mismatch errors.

Co-authored-by: Andrea Mazzucchelli <andrmaz@users.noreply.github.com>
@andrmaz andrmaz marked this pull request as ready for review June 4, 2026 21:13

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
packages/db/prisma/schema.prisma (1)

180-195: ⚡ Quick win

Consider adding organizationId and departmentId to QueryLog for direct audit filtering.

The acceptance criteria in plans/cortex-mvp-prd-plan.md state: "Admin can filter logs by time, user, and department." Currently, filtering by department requires joining QueryLog → User → UserDepartment → Department, which is complex and slower for large audit tables.

Adding organizationId and departmentId fields would enable:

  • Direct composite indexes on (organizationId, createdAt) and (departmentId, createdAt)
  • Simpler query patterns for the admin audit viewer
  • Better query performance at scale
📊 Proposed schema enhancement
 model QueryLog {
   id             String   `@id` `@default`(uuid())
   userId         String   `@map`("user_id")
+  organizationId String   `@map`("organization_id")
+  departmentId   String   `@map`("department_id")
   query          String
   contextBundle  Json?    `@map`("context_bundle")
   policyDecision Json?    `@map`("policy_decision")
   response       String?
   createdAt      DateTime `@default`(now())

   // Relations
   user User `@relation`(fields: [userId], references: [id], onDelete: Cascade)
+  organization Organization `@relation`(fields: [organizationId], references: [id], onDelete: Cascade)
+  department   Department   `@relation`(fields: [departmentId], references: [id], onDelete: Cascade)

   @@index([userId])
+  @@index([organizationId, createdAt])
+  @@index([departmentId, createdAt])
   @@index([createdAt])
   @@map("query_logs")
 }

Don't forget to add the queryLogs QueryLog[] relation back-reference to Organization and Department models.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/db/prisma/schema.prisma` around lines 180 - 195, Add nullable
organizationId and departmentId fields to the QueryLog model and create indexes
to support filtering by time (e.g., add organizationId String?
`@map`("organization_id") and departmentId String? `@map`("department_id") and then
@@index([organizationId, createdAt]) and @@index([departmentId, createdAt]));
update the User relation declaration in QueryLog if needed to keep existing
onDelete behavior, and add reciprocal back-reference relations queryLogs on the
Organization and Department models (e.g., Organization.queryLogs and
Department.queryLogs) so Prisma relations remain consistent; ensure field types,
mapping names, and cascade behavior match your existing id fields and re-run
prisma migrate to apply the schema change.
.github/workflows/ci.yml (1)

1-98: ⚡ Quick win

Improve workflow security posture.

Static analysis identified several security improvements:

  1. Credential persistence risk: Add persist-credentials: false to checkout steps to prevent credential leakage through artifacts.
  2. Overly broad permissions: Add explicit permissions: blocks to restrict what each job can access.
  3. Unpinned actions: Pin actions to commit SHAs for supply-chain security.
🔒 Security enhancements

1. Add workflow-level permissions (top of file after concurrency:):

permissions:
  contents: read

2. Update checkout steps to prevent credential persistence:

- name: Checkout
  uses: actions/checkout@v4
  with:
    persist-credentials: false

3. Pin actions to commit SHAs (example for lint-and-typecheck job):

- name: Checkout
  uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
  with:
    persist-credentials: false

- name: Setup pnpm
  uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0

- name: Setup Node.js
  uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
  with:
    node-version: '22'
    cache: 'pnpm'

Apply the same pinning pattern to the build and validate-schema jobs.

As per static analysis hints from zizmor (1.25.2), these changes reduce the risk of credential leakage and supply-chain attacks.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 1 - 98, Add a workflow-level
permissions block after concurrency (permissions: contents: read), set with:
persist-credentials: false on every Checkout step (in jobs lint-and-typecheck,
build, validate-schema) and replace floating action tags with pinned SHAs for
each uses entry (e.g., actions/checkout@v4, pnpm/action-setup@v4,
actions/setup-node@v4) by updating those uses to the repository@<commit-sha>
values; also add restrictive job-level permissions blocks for each job
(lint-and-typecheck, build, validate-schema) to explicitly limit access instead
of inheriting broader rights.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 33-36: The CI step that runs the "Generate Prisma client" job sets
DATABASE_URL to postgresql://localhost:5432/test but does not start a PostgreSQL
service, so add a postgres service to any job that runs Prisma (the job
containing the "Generate Prisma client" step and the other similar steps) using
image postgres:16 with POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB (e.g.,
cortex/cortex/cortex_test) and appropriate health checks, and update the step's
env DATABASE_URL to postgresql://cortex:cortex@localhost:5432/cortex_test so
Prisma can perform full DB-specific validation and migrations; ensure each job
that runs pnpm --filter db db:generate or similar Prisma commands gets the same
services block and env update.

In `@apps/api/src/mcp/mcp.controller.ts`:
- Around line 3-6: The local interface MCPRequestBody narrows the expected
request shape and omits tenant fields; replace the local definition and any
usages (e.g., where MCPRequestBody is used around the MCP controller request
params at lines ~19-20) with the shared MCPRequest contract from packages/shared
(import MCPRequest) so the controller uses the canonical type (MCPRequest)
including organizationId and departmentId; update the import and all references
to use MCPRequest instead of the local MCPRequestBody.

In `@packages/db/prisma/migrations/0001_initial_schema/migration.sql`:
- Around line 38-48: The migration is missing a uniqueness constraint to enforce
one primary department per user; add a partial unique index named
user_departments_one_primary_per_user on the user_departments table targeting
user_id where is_primary = true (i.e., create the index after the
user_departments table definition so the DB enforces at most one row with
is_primary=true per user_id). Ensure the index name is exactly
user_departments_one_primary_per_user and the predicate references is_primary =
true.

In `@packages/db/prisma/schema.prisma`:
- Around line 73-92: Add a DB-level constraint to enforce exactly one primary
department per user by creating a UNIQUE partial index on the user_departments
table for rows where is_primary = true; after the UserDepartment model/table is
created (model: UserDepartment, columns: userId/@map("user_id") and
isPrimary/@map("is_primary")), add a migration SQL statement to create a unique
index like user_departments_one_primary_per_user ON user_departments(user_id)
WHERE is_primary = true (Postgres 9.5+); include a short comment in the
schema/migration documenting this constraint so future maintainers know it
enforces the "one Primary Department per User" business rule.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 1-98: Add a workflow-level permissions block after concurrency
(permissions: contents: read), set with: persist-credentials: false on every
Checkout step (in jobs lint-and-typecheck, build, validate-schema) and replace
floating action tags with pinned SHAs for each uses entry (e.g.,
actions/checkout@v4, pnpm/action-setup@v4, actions/setup-node@v4) by updating
those uses to the repository@<commit-sha> values; also add restrictive job-level
permissions blocks for each job (lint-and-typecheck, build, validate-schema) to
explicitly limit access instead of inheriting broader rights.

In `@packages/db/prisma/schema.prisma`:
- Around line 180-195: Add nullable organizationId and departmentId fields to
the QueryLog model and create indexes to support filtering by time (e.g., add
organizationId String? `@map`("organization_id") and departmentId String?
`@map`("department_id") and then @@index([organizationId, createdAt]) and
@@index([departmentId, createdAt])); update the User relation declaration in
QueryLog if needed to keep existing onDelete behavior, and add reciprocal
back-reference relations queryLogs on the Organization and Department models
(e.g., Organization.queryLogs and Department.queryLogs) so Prisma relations
remain consistent; ensure field types, mapping names, and cascade behavior match
your existing id fields and re-run prisma migrate to apply the schema change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 86808225-228c-4e61-b45c-14b1ce3bdcc9

📥 Commits

Reviewing files that changed from the base of the PR and between 03047f1 and d7f686e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (27)
  • .github/workflows/ci.yml
  • .prettierignore
  • README.md
  • apps/api/eslint.config.js
  • apps/api/package.json
  • apps/api/src/app.module.ts
  • apps/api/src/main.ts
  • apps/api/src/mcp/mcp.controller.ts
  • apps/api/src/mcp/mcp.module.ts
  • apps/docs/app/page.tsx
  • apps/docs/eslint.config.js
  • apps/docs/tsconfig.json
  • apps/web/app/page.tsx
  • apps/web/eslint.config.js
  • apps/web/tsconfig.json
  • packages/db/package.json
  • packages/db/prisma/migrations/0001_initial_schema/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/db/src/index.ts
  • packages/db/tsconfig.json
  • packages/shared/package.json
  • packages/shared/src/index.ts
  • packages/shared/src/types.ts
  • packages/shared/tsconfig.json
  • packages/ui/eslint.config.mjs
  • packages/ui/tsconfig.json
  • turbo.json

Comment thread .github/workflows/ci.yml
Comment on lines +33 to +36
- name: Generate Prisma client
run: pnpm --filter db db:generate
env:
DATABASE_URL: "postgresql://localhost:5432/test"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add a PostgreSQL service for proper Prisma validation.

The workflow sets DATABASE_URL to postgresql://localhost:5432/test, but there's no PostgreSQL service configured. While prisma generate and basic prisma validate can work without a live database, using a proper PostgreSQL service ensures:

  1. Full schema validation including database-specific features (like partial indexes, check constraints)
  2. Migration compatibility testing
  3. Consistency with the production environment (PostgreSQL 16 per docker-compose.yml)
🐘 Add PostgreSQL service to each job

Add this services block to each job that needs database access:

services:
  postgres:
    image: postgres:16
    env:
      POSTGRES_USER: cortex
      POSTGRES_PASSWORD: cortex
      POSTGRES_DB: cortex_test
    options: >-
      --health-cmd pg_isready
      --health-interval 10s
      --health-timeout 5s
      --health-retries 5
    ports:
      - 5432:5432

Then update the DATABASE_URL to match:

env:
  DATABASE_URL: "postgresql://cortex:cortex@localhost:5432/cortex_test"

Also applies to: 67-70, 94-97

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 33 - 36, The CI step that runs the
"Generate Prisma client" job sets DATABASE_URL to
postgresql://localhost:5432/test but does not start a PostgreSQL service, so add
a postgres service to any job that runs Prisma (the job containing the "Generate
Prisma client" step and the other similar steps) using image postgres:16 with
POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB (e.g., cortex/cortex/cortex_test)
and appropriate health checks, and update the step's env DATABASE_URL to
postgresql://cortex:cortex@localhost:5432/cortex_test so Prisma can perform full
DB-specific validation and migrations; ensure each job that runs pnpm --filter
db db:generate or similar Prisma commands gets the same services block and env
update.

Comment thread apps/api/src/mcp/mcp.controller.ts Outdated
Comment thread packages/db/prisma/migrations/0001_initial_schema/migration.sql
Comment thread packages/db/prisma/schema.prisma
cursoragent and others added 2 commits June 4, 2026 21:22
Add database-level constraint to enforce business rule from
UBIQUITOUS_LANGUAGE.md: 'A User is mapped to one or more Departments,
with one Primary Department.'

- Add unique partial index on user_departments(user_id) WHERE is_primary = true
- Add documenting comment in Prisma schema referencing the migration

Co-authored-by: Andrea Mazzucchelli <andrmaz@users.noreply.github.com>
Replace local MCPRequestBody interface with the shared MCPRequest contract
from @cortex/shared to maintain consistency across the API boundary and
include tenant fields (organizationId, departmentId).

Co-authored-by: Andrea Mazzucchelli <andrmaz@users.noreply.github.com>
@andrmaz

andrmaz commented Jun 4, 2026

Copy link
Copy Markdown
Owner Author

@cursoragent some checks are failing

@cursor

cursor Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Fixed. The CI was failing because the pnpm-lock.yaml was out of sync after I added @cortex/shared to the API package dependencies. The lockfile has now been updated and pushed. CI should pass on the next run.

View PR

Open in Web Open in Cursor 

cursoragent and others added 2 commits June 4, 2026 21:33
Co-authored-by: Andrea Mazzucchelli <andrmaz@users.noreply.github.com>
…attern

Use the internal packages pattern where shared types export .ts source
files directly, avoiding the need to build before type-checking in CI.

Co-authored-by: Andrea Mazzucchelli <andrmaz@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@andrmaz andrmaz linked an issue Jun 4, 2026 that may be closed by this pull request
4 tasks
@andrmaz andrmaz added the enhancement New feature or request label Jun 4, 2026
@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ Created PR with unit tests: #21

@andrmaz

andrmaz commented Jun 4, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the CI status of PR `#20`
gh pr checks 20 --repo andrmaz/cortex

Length of output: 464



@andrmaz It looks like all checks on PR #20 are now passing! ✅

Check Status
Build ✅ Pass
Lint & Type Check ✅ Pass
Validate Prisma Schema ✅ Pass
CodeRabbit Review ✅ Pass

Is there something specific you'd like me to help with?

@andrmaz

andrmaz commented Jun 4, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai code review

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

@andrmaz Sure! I'll kick off a full review of PR #20 right away.

✅ Action performed

Full review finished.

@andrmaz andrmaz merged commit 22a1039 into main Jun 4, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[1a] Project scaffolding + core schema

2 participants