# CA Grow Ops Manager — Backend

**Version**: 0.1.0  
**Stack**: TypeScript, Node.js, Express/Fastify, PostgreSQL, Prisma

---

## Overview

The backend is a **feature-first, domain-driven** Node.js application that provides typed HTTP/JSON APIs for all platform features. It uses Prisma ORM for type-safe database access and follows strict security and testing practices.

---

## Tech Stack

- **Language**: TypeScript 5.x
- **Runtime**: Node.js 20.x LTS
- **Framework**: Express or Fastify (to be decided during implementation)
- **Database**: PostgreSQL 15.x
- **ORM**: Prisma 5.x
- **Authentication**: JWT (access + refresh tokens)
- **Testing**: Jest + Supertest
- **Validation**: Zod or Joi
- **Logging**: Winston or Pino
- **Email**: SendGrid or Mailgun

---

## Project Structure

```
backend/
├── src/
│   ├── modules/              # Feature-first modules
│   │   ├── cultivation-ops/  # Tasks, batches, rooms
│   │   │   ├── tasks/
│   │   │   │   ├── tasks.controller.ts
│   │   │   │   ├── tasks.service.ts
│   │   │   │   ├── tasks.schema.ts
│   │   │   │   └── tasks.test.ts
│   │   │   ├── batches/
│   │   │   └── rooms/
│   │   ├── compliance/       # Documents, audit packets
│   │   ├── labor/            # Timeclock, hours, reports
│   │   ├── inventory/        # Materials, lots, transactions
│   │   ├── integrations/     # METRC, environmental, hardware
│   │   ├── communications/   # Comments, announcements, notifications
│   │   └── auth/             # Authentication, authorization
│   ├── shared/               # Shared utilities
│   │   ├── middleware/       # Auth, validation, error handling
│   │   ├── utils/            # Helpers, formatters
│   │   └── types/            # Shared TypeScript types
│   ├── prisma/               # Prisma schema and migrations
│   │   ├── schema.prisma
│   │   └── migrations/
│   ├── config/               # Configuration
│   │   ├── database.ts
│   │   ├── auth.ts
│   │   └── email.ts
│   ├── app.ts                # Express/Fastify app setup
│   └── server.ts             # Server entry point
├── tests/                    # Integration tests
│   ├── setup.ts
│   └── integration/
├── .env.example              # Environment variables template
├── package.json
├── tsconfig.json
└── README.md
```

---

## Domain Modules

Each module follows this structure:

```
module-name/
├── entity.controller.ts   # HTTP route handlers
├── entity.service.ts      # Business logic
├── entity.schema.ts       # Validation schemas (Zod/Joi)
├── entity.test.ts         # Unit tests
└── index.ts               # Module exports
```

### Example: Tasks Module

```typescript
// tasks.controller.ts
export const getTasks = async (req, res) => {
  const tasks = await tasksService.findAll(req.query);
  res.json(tasks);
};

// tasks.service.ts
export const findAll = async (filters) => {
  return prisma.task.findMany({ where: filters });
};

// tasks.schema.ts
export const createTaskSchema = z.object({
  name: z.string().min(1),
  dueDate: z.string().datetime(),
  assigneeId: z.string().optional(),
});
```

---

## API Design

### RESTful Conventions

- `GET /api/tasks` - List tasks
- `GET /api/tasks/:id` - Get task detail
- `POST /api/tasks` - Create task
- `PATCH /api/tasks/:id` - Update task
- `DELETE /api/tasks/:id` - Delete task

### Response Format

```json
{
  "success": true,
  "data": { ... },
  "meta": {
    "page": 1,
    "pageSize": 20,
    "total": 100
  }
}
```

### Error Format

```json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input",
    "details": [
      { "field": "dueDate", "message": "Required" }
    ]
  }
}
```

---

## Authentication & Authorization

### JWT-Based Auth

- **Access Token**: 15-minute expiry, stored in httpOnly cookie
- **Refresh Token**: 7-day expiry, stored in localStorage
- **Token Payload**: `{ userId, roleId, iat, exp }`

### RBAC (Role-Based Access Control)

Roles:

- `Owner`: Full access
- `Compliance Manager`: Full compliance, read-only operations
- `Head Grower`: Full cultivation ops, read-only compliance
- `Staff`: Limited access to tasks and timeclock
- `Accountant`: Read-only reports

Middleware:

```typescript
export const requireRole = (roles: string[]) => {
  return (req, res, next) => {
    if (!roles.includes(req.user.role)) {
      return res.status(403).json({ error: 'Forbidden' });
    }
    next();
  };
};
```

---

## Database (Prisma)

### Schema Example

```prisma
model Task {
  id          String   @id @default(cuid())
  name        String
  description String?
  status      TaskStatus @default(PENDING)
  dueDate     DateTime
  assigneeId  String?
  assignee    User?    @relation(fields: [assigneeId], references: [id])
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

enum TaskStatus {
  PENDING
  IN_PROGRESS
  COMPLETE
  OVERDUE
}
```

### Migrations

```bash
# Create migration
npx prisma migrate dev --name add_tasks_table

# Apply migrations
npx prisma migrate deploy

# Generate Prisma Client
npx prisma generate
```

---

## Testing

### Unit Tests (Jest)

```typescript
describe('TasksService', () => {
  it('should create a task', async () => {
    const task = await tasksService.create({
      name: 'Water plants',
      dueDate: new Date(),
    });
    expect(task.name).toBe('Water plants');
  });
});
```

### Integration Tests (Supertest)

```typescript
describe('POST /api/tasks', () => {
  it('should create a task', async () => {
    const res = await request(app)
      .post('/api/tasks')
      .send({ name: 'Water plants', dueDate: '2025-12-10' })
      .expect(201);
    expect(res.body.data.name).toBe('Water plants');
  });
});
```

---

## Environment Variables

```bash
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/ca_grow_ops

# Auth
JWT_SECRET=your-secret-key
JWT_ACCESS_EXPIRY=15m
JWT_REFRESH_EXPIRY=7d

# Email
EMAIL_SERVICE=sendgrid
EMAIL_API_KEY=your-api-key
EMAIL_FROM=noreply@example.com

# Integrations
METRC_API_KEY=your-metrc-key
METRC_API_URL=https://api-ca.metrc.com

# Server
PORT=3000
NODE_ENV=development
```

---

## Development Workflow

### Setup

```bash
# Install dependencies
npm install

# Set up environment variables
cp .env.example .env

# Run database migrations
npx prisma migrate dev

# Seed database (optional)
npx prisma db seed

# Start dev server
npm run dev
```

### Scripts

```json
{
  "scripts": {
    "dev": "tsx watch src/server.ts",
    "build": "tsc",
    "start": "node dist/server.js",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage",
    "lint": "eslint src --ext .ts",
    "format": "prettier --write src",
    "migrate": "prisma migrate dev",
    "migrate:deploy": "prisma migrate deploy",
    "prisma:generate": "prisma generate"
  }
}
```

---

## Security Best Practices

- **Input Validation**: Validate all inputs with Zod/Joi
- **SQL Injection**: Use Prisma parameterized queries
- **XSS**: Sanitize user inputs; use Content Security Policy
- **CSRF**: Use CSRF tokens for state-changing operations
- **Rate Limiting**: Limit API requests per user/IP
- **Audit Logging**: Log all critical operations

---

## Deployment

### Docker

```dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npx prisma generate
RUN npm run build
CMD ["npm", "start"]
```

### Docker Compose

```yaml
version: '3.8'
services:
  backend:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://user:password@db:5432/ca_grow_ops
    depends_on:
      - db
  db:
    image: postgres:15
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: ca_grow_ops
    volumes:
      - postgres_data:/var/lib/postgresql/data
volumes:
  postgres_data:
```

---

## Next Steps

1. **Choose Framework**: Decide between Express and Fastify
2. **Set Up Project**: Initialize Node.js project with TypeScript
3. **Configure Prisma**: Set up Prisma schema and migrations
4. **Implement Auth**: Build authentication and RBAC
5. **Build Modules**: Implement feature modules per spec
6. **Write Tests**: Unit and integration tests for all modules
7. **Deploy**: Set up CI/CD and deploy to staging

---

## Resources

- [Prisma Documentation](https://www.prisma.io/docs)
- [Express Documentation](https://expressjs.com)
- [Fastify Documentation](https://www.fastify.io)
- [Jest Documentation](https://jestjs.io)
- [TypeScript Documentation](https://www.typescriptlang.org/docs)
