Bluewoo HRMS
AI Development GuideDevelopment

Constraints

Hard rules, limitations, and .cursorrules for AI agents

Constraints

These are hard rules that must never be violated. AI assistants must respect these constraints without exception.

Version Requirements

MANDATORY VERSIONS:

PackageVersionNotes
Prisma5.xNOT 6.x (breaking changes)
Express4.xNOT 5.x (beta)
Redis7.xNOT 8.x
Zod3.xLatest stable
PostgreSQL17.xLatest stable
Node.js20.x LTSBetter AI training data
NestJS10.xStable release
Next.js15.xApp Router

Why: These versions are tested, stable, and compatible. Using other versions breaks the stack.

Technology Restrictions

FORBIDDEN:

TechnologyReason
GraphQLToo complex for our scale
MicroservicesMonolith is simpler
Event-driven architectureUse direct calls
Custom frameworksUse NestJS/Next.js
Alternative databasesPostgreSQL only
Redux/MobXUse React Query

Why: These add unnecessary complexity. The architecture is optimized for the target scale without them.

Architecture Boundaries

HRMS Core:

  • Next.js frontend + NestJS backend + PostgreSQL
  • Monolithic application
  • REST APIs only

Web App Database Access:

  • apps/web/lib/prisma.ts exists ONLY for Auth.js
  • ALL other data access MUST go through apps/api
  • DO NOT import prisma.ts in any other web app files
// WRONG - bypasses API layer
import { prisma } from '@/lib/prisma';
const employees = await prisma.employee.findMany(); // ❌

// CORRECT - use API
const response = await fetch('/api/v1/employees'); // ✅

AI Service:

  • Separate Express service
  • MongoDB for vectors only
  • No HRMS data in MongoDB

Org Structure Rules (CRITICAL)

Model Split

  • EmployeeCore = WHO (identity, job info, employment)
  • EmployeeOrgRelations = HOW (managers, teams, departments, roles)

Multi-Everything Support

primaryManagerId: string?        // 0..1 (direct manager)
dottedLineManagerIds: string[]   // 0..N (matrix reporting)
additionalManagerIds: string[]   // 0..N (secondary real managers)
teamIds: string[]                // 0..N (multi-team membership)
departmentIds: string[]          // 0..N (cross-department)
roleIds: string[]                // 0..N (multi-role)

Org Rules

  • Every manager IS an employee (no separate Manager table)
  • Self-management BLOCKED (employeeId !== managerId)
  • Circular management ALLOWED by default (startup flexibility)
  • No limits on any relations

Valid Examples

// CTO with multiple responsibilities
CTO: {
  primaryManagerId: "ceo-id",
  dottedLineManagerIds: ["cfo-id"],
  roleIds: ["cto", "sales-manager"],
  teamIds: ["leadership", "sales"]
}

// Developer in multiple teams
Developer: {
  primaryManagerId: "dev-lead-id",
  additionalManagerIds: ["cto-id"],
  teamIds: ["saas", "web"],
  departmentIds: ["engineering", "product"]
}

Complexity Limits

Per Module:

  • Maximum 5 files
  • Maximum 150 lines per service file
  • Maximum 100 lines per controller file

Per Building Block:

  • Complete one block before starting next
  • No parallel work on multiple blocks
  • All gates must pass before moving on

Pattern Enforcement

NO VARIATIONS:

  • Use exact patterns from Patterns
  • No "better" ways or "improvements"
  • Copy-paste similar code (don't abstract)

.cursorrules Content

Use this as your .cursorrules file:

# Project Context
Multi-tenant HRMS SaaS with flexible org structure.
- Next.js 15 (App Router) + NestJS 10 + PostgreSQL 17 + Prisma 5
- Shadcn/ui + Tailwind CSS
- Auth.js for authentication

## Architecture Principles
1. SIMPLICITY FIRST - No premature optimization
2. Single PostgreSQL with Row-Level Security
3. REST APIs only (no GraphQL)
4. Feature modules in NestJS

## ORG STRUCTURE RULES (CRITICAL)

### Model Split
- EmployeeCore = WHO (identity, job info, employment)
- EmployeeOrgRelations = HOW (managers, teams, departments, roles)

### Multi-Everything
- primaryManagerId: 0..1 (direct manager)
- dottedLineManagerIds: 0..N (matrix reporting)
- additionalManagerIds: 0..N (secondary real managers)
- teamIds: 0..N (multi-team membership)
- departmentIds: 0..N (cross-department)
- roleIds: 0..N (multi-role)

### Rules
- Every manager IS an employee (no separate Manager table)
- Self-management BLOCKED (employeeId !== managerId)
- Circular management ALLOWED by default (startup flexibility)
- No limits on any relations

## Code Style
- TypeScript strict (no `any`)
- Functional components with hooks
- Early returns for guards
- Descriptive names (no abbreviations)

## Database
- All tables have tenantId
- Always filter by tenantId
- Use Prisma transactions for multi-table ops
- Junction tables for many-to-many

## API Design
- REST with proper HTTP methods
- Consistent response shapes
- Pagination for lists

## Security
- Never trust client input
- Verify tenant context always
- Use isManagerOf() for permission checks
- Log security actions

## DO NOT
- GraphQL or event sourcing
- Separate microservices
- Abstractions without 3+ implementations
- Redux/MobX (use React Query)
- Separate Manager table
- Limit org relationships
- Block circular management by default

## COMMIT MESSAGE FORMAT (ENFORCED)
All commits MUST use conventional commits:
- Format: <type>: <description>
- Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
- feat = minor bump, fix/others = patch bump
- Add ! after type for breaking changes (major bump)

Good: feat: add employee dashboard
Bad: update stuff (CI rejects)

Exception Process

To Add Technology:

  1. Create ADR explaining why (See ADR Guide)
  2. Get approval
  3. Follow technology addition process
  4. Update boilerplate definition

To Change Pattern:

  1. Create ADR explaining why
  2. Get approval
  3. Update Patterns
  4. Update all affected code

UI Development Constraints

All UI work MUST follow the Design System:

Mandatory UI Rules

#RuleRationale
1NEVER create plain white cards with gray bordersLooks like wireframe, not shipped product
2ALWAYS use gradient backgrounds for stats cardsVisual hierarchy and polish
3ALWAYS use shadow-lg on content cardsSoft, modern aesthetic
4ALWAYS use rounded-2xl (16px) on cardsApple/iOS design language
5ALWAYS use CSS variables (bg-card, not bg-white)Dark mode support
6ALWAYS support dark mode with dark: variantsRequired feature
7NEVER use spacing less than p-6 on cardsGenerous whitespace
8NEVER create new button/component variants without updating design systemPrevents drift

Before Writing UI Code

UI Code Review Criteria

REJECT if:

  • Plain white cards with gray borders
  • Hard-coded colors (bg-white instead of bg-card)
  • Missing dark mode support
  • Spacing below minimum (p-4 instead of p-6)
  • Stats cards without gradient backgrounds

See Design System for complete specifications.


Enforcement

AI Must:

  • Check constraints before suggesting changes
  • Reject own suggestions that violate constraints
  • Reference constraints when user asks for forbidden features
  • Follow UI design system for all frontend work

User Must:

  • Enforce constraints when AI suggests violations
  • Create ADR for any exceptions
  • Update constraints when decisions change

Platform Admin Constraints

Platform Admin functionality (Phase 10) has specific rules:

Authorization

RuleRequirement
GuardALL Platform Admin endpoints MUST use @PlatformAdminOnly()
RoleOnly SYSTEM_ADMIN users can access Platform Admin features
Tenant ContextPlatform Admin endpoints do NOT require X-Tenant-ID header
Cross-tenantPlatform Admin CAN access data across all tenants

API Design

// CORRECT - Platform Admin endpoint pattern
@Controller('api/v1/admin/tenants')
@PlatformAdminOnly()
export class AdminTenantController { ... }

// WRONG - Missing guard
@Controller('api/v1/admin/tenants')
export class AdminTenantController { ... }

Data Access

ConstraintReason
Tenant creation MUST validate unique tenant namePrevent duplicates
Tenant status changes MUST be loggedAudit trail
Tenant Admin assignment creates user with null passwordForces password reset
Platform Admin CANNOT modify tenant-specific data directlyUse tenant-scoped endpoints

UI Constraints

  • Platform Admin sidebar section MUST only render for SYSTEM_ADMIN users
  • Platform Admin pages MUST be under /admin/* route
  • Platform Admin UI MUST follow the same design system as tenant UI

Domain Registration Rules

ConstraintReason
Domain format MUST be validated (lowercase, no protocol)Prevent duplicates and normalize format
Domain MUST be unique across all tenantsOne domain = one tenant ownership
Registration with unrecognized domain MUST be rejectedEnterprise-only mode
New users joining via domain MUST get EMPLOYEE roleSecurity - not admin by default
Cannot delete last domain if tenant has usersPrevents orphaned users
Primary domain MUST be settable per tenantDisplay and identification

Implementation Notes:

  • Domain validation regex: /^[a-z0-9]+([\-\.][a-z0-9]+)*\.[a-z]{2,}$/
  • Always lowercase domains before storing
  • Auth.js createUser event handles domain matching
  • Delete user record if domain not recognized (rollback)

Employee Management Constraints

Employee Status Rules

StatusUsage
ACTIVENormal working employee
INACTIVETemporarily not working (sabbatical, long-term leave without pay)
ON_LEAVECurrently on approved paid leave
TERMINATEDEmployment ended, soft-deleted from active queries

Status Transitions:

  • ACTIVE → INACTIVE: Manual HR action (sabbatical, extended leave)
  • ACTIVE → ON_LEAVE: Automatic when leave request approved
  • ON_LEAVE → ACTIVE: Automatic when leave period ends
  • Any → TERMINATED: Manual HR action (irreversible soft-delete)

Profile Picture Rules

ConstraintValueReason
Max file size5MBPerformance and storage costs
Allowed formatsJPG, PNG, WebPBrowser compatibility
Storage path/uploads/profile-pictures/{employeeId}Organized storage
Image processingResize to 400x400 maxConsistent display, reduced storage

Implementation:

const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp'];
const MAX_SIZE = 5 * 1024 * 1024; // 5MB

Validation:

  • MUST validate file type on server (don't trust client MIME type)
  • MUST resize large images before storage
  • MUST delete old picture when uploading new one
  • SHOULD return 413 Payload Too Large for oversized files

Conventional Commits Constraint (ENFORCED)

CI ENFORCED

All commits MUST use conventional commit format. GitHub Actions rejects PRs with non-conforming commits.

Commit Message Format

<type>: <description>

Allowed Types

TypeVersion BumpWhen to Use
featMinor (0.X.0)New feature
fixPatch (0.0.X)Bug fix
docsPatchDocumentation only
stylePatchFormatting, no code change
refactorPatchCode restructuring
perfPatchPerformance improvement
testPatchAdding/updating tests
buildPatchBuild system changes
ciPatchCI/CD changes
chorePatchMaintenance tasks
revertPatchReverting previous commit

Breaking Changes

Add ! after type for Major version bump (X.0.0):

feat!: redesign API endpoints

# Or use footer
feat: redesign API endpoints

BREAKING CHANGE: API endpoints have changed

Rules

RuleEnforcement
Type MUST be lowercaseCI validates
Type MUST be from allowed listCI validates
Colon MUST follow typeCI validates
Description MUST not be emptyCI validates
Header MUST be ≤100 charactersCI validates

Examples

# Correct
git commit -m "feat: add employee dashboard"
git commit -m "fix: resolve login timeout"
git commit -m "docs: update API guide"
git commit -m "refactor: simplify auth flow"

# Incorrect (CI will reject)
git commit -m "update stuff"         # Missing type
git commit -m "Feature: add login"   # Wrong case
git commit -m "feat add login"       # Missing colon
git commit -m "FEAT: add login"      # Uppercase type

.cursorrules Addition for Commits

Add to your .cursorrules:

## COMMIT MESSAGE FORMAT (ENFORCED)

All commits MUST use conventional commits format:
- Format: <type>: <description>
- Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
- feat = minor version bump, fix/others = patch version bump
- Add ! after type for breaking changes (major version bump)

Examples:
- feat: add employee dashboard
- fix: resolve login timeout
- docs: update deployment guide
- feat!: redesign authentication API

NEVER commit with messages like "update stuff" or "WIP" - CI will reject.

Deployment Checkpoint Constraints (MANDATORY)

ENFORCED BY GITHUB

These constraints are enforced at the GitHub level. Violations are technically impossible.

Hard Rules

RuleEnforcement
NEVER push directly to mainGitHub blocks direct pushes
NEVER merge without PRPRs required for all changes
NEVER skip CI testsTests must pass before merge
NEVER bypass as adminEnforce for admins enabled

AI Agent Checkpoint Rules

#RuleConsequence of Violation
1NEVER push without human saying "OK to push"Session restart required
2NEVER merge without human verifying previewPR rejected
3NEVER deploy production without human verifying stagingDeployment blocked
4ALWAYS stop and wait at each checkpointTrust broken

Checkpoint Protocol

At each deployment gate, AI agents MUST:

  1. STOP - Halt all execution
  2. SHOW - Display relevant information (diff, URL, status)
  3. ASK - Request explicit confirmation
  4. WAIT - Do NOT proceed until human responds
  5. VERIFY - Check response before continuing

.cursorrules Addition

Add to your .cursorrules file:

## DEPLOYMENT CHECKPOINT RULES (CRITICAL)

AI MUST pause and ask for human confirmation at these 4 gates:

1. CHECKPOINT 1: After commit, before push
   - Show diff, ask "OK to push?"
   - WAIT for "OK to push"

2. CHECKPOINT 2: After preview deploys
   - Show preview URL, ask "OK to merge?"
   - WAIT for "OK to merge"

3. CHECKPOINT 3: After staging deploys
   - Show staging URL, ask "OK to deploy production?"
   - WAIT for "OK to deploy"

4. CHECKPOINT 4: After production deploys
   - Show production URL, ask "Confirm complete?"
   - WAIT for "Complete"

NEVER proceed past a checkpoint without explicit human confirmation.
This is non-negotiable. Violations require session restart.

Agent Boundaries

File Modification Rules

Safe to Modify (within current task):

  • Files explicitly mentioned in current building block
  • New files being created for the task
  • Test files for code being written

Requires Confirmation:

  • Any file in packages/database/prisma/
  • Configuration files (*.config.*, docker-compose.yml)
  • Files in apps/*/src/lib/ (shared utilities)

Never Modify Without ADR:

  • Files marked as locked in previous phases
  • Authentication/authorization code after Phase 1
  • Core middleware and guards

Dependency Rules

Before Installing ANY New Package:

  1. Check if functionality exists in current stack
  2. Verify package is in Technology Stack
  3. If not listed, ASK before installing
  4. Never install alternative packages (e.g., moment.js when date-fns is standard)

Forbidden Without Approval:

  • Any ORM except Prisma
  • Any UI library except shadcn/ui
  • Any state management except React Query
  • Any new testing framework

Automatic Progression Forbidden

After completing any task:

  1. Report completion status
  2. Show gate verification result
  3. STOP and ASK: "Task complete. What's next?"

DO NOT:

  • Automatically start the next step
  • Suggest improvements to working code
  • Refactor "while we're here"
  • Add "nice to have" features

Anti-Improvement Pledge (CRITICAL)

MANDATORY

AI agents MUST NOT "improve" code beyond the current task scope.

Forbidden Actions

Forbidden ActionWhy It Causes Chaos
"Improve" working codeCreates inconsistency, breaks tests
Suggest "better" alternativesDelays progress, scope creep
Refactor "while we're here"Uncontrolled changes, harder reviews
Add "helpful" featuresNot in specification, untested
"Clean up" unrelated codeBreaks what works, wasted effort
Premature optimizationYAGNI violation, complexity
Add extra error handlingOver-engineering, noise
Create abstractions for one useUnnecessary complexity
Rename variables for "clarity"Churn, diff noise
Add comments to existing codeOut of scope, opinion

When Tempted to Improve

Instead of improving, ASK:

"I notice [X] could be improved. Is this in scope for the current step? If not, I'll add it to a future enhancement list and continue with the current task."

Valid Exceptions

Improvements are ONLY allowed when:

  1. Explicitly requested by user: "Please refactor this function"
  2. Required for current task: Can't implement feature without fixing bug
  3. Security vulnerability: Must fix immediately, document as blocker
  4. Build/test failure: Must fix to continue, document as blocker

Improvement Detection Self-Check

Before any edit, AI must verify:

□ Is this edit required for the current step?
□ Is this edit explicitly requested?
□ Does this file appear in the current task specification?
□ Am I changing MORE than what the task requires?

If any checkbox fails → STOP and ASK

Consequence of Violation

If AI violates Anti-Improvement Pledge:

  1. User should reject the changes
  2. User should point to this document
  3. AI should revert to task-only changes
  4. Session may need to restart with clearer scope