ca-grow-ops-manager/backend/README.md
fullsizemalt da7729d6e4
Some checks failed
Deploy to Production / deploy (push) Failing after 0s
Test / backend-test (push) Failing after 0s
Test / frontend-test (push) Failing after 0s
Initial commit: Spec Kit foundation complete
- Constitution and project spec (spec.yml)
- 7 comprehensive feature specs (tasks, batches, labor, compliance, inventory, integrations, comms)
- Phase 1 implementation plan (6-week roadmap)
- Week 1 task breakdown (15 concrete tasks)
- Architecture and compliance documentation
- Backend and frontend setup guides
- Deployment guide for nexus-vector
- CI/CD workflows (Forgejo Actions)
- Quick start guide for developers

Project is ready for implementation with:
- Automated testing on every push
- Automatic deployment to nexus-vector on push to main
- Database migrations handled automatically
- Health checks and monitoring

Stack: TypeScript, Fastify, React, Vite, PostgreSQL, Prisma, Docker
2025-12-08 23:54:12 -08:00

397 lines
8.7 KiB
Markdown

# 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)