# TekDek Command Center API

A lightweight project and task management REST API built with Node.js, Express, and PostgreSQL.

## Quick Start

### 1. Install Dependencies

```bash
npm install
```

### 2. Set Up Environment

```bash
cp .env.example .env
# Edit .env with your database connection
```

### 3. Set Up Database

```bash
npm run db:setup
npm run db:seed
```

### 4. Start Server

```bash
npm start
```

Server runs at `http://localhost:3000` by default.

## API Endpoints

### Projects

#### Create Project
```http
POST /api/v1/projects
Content-Type: application/json

{
  "name": "Persona Portal v2.0",
  "description": "Redesign and relaunch the persona publishing platform",
  "color_hex": "#3498db",
  "icon_name": "rocket"
}
```

**Response (201)**:
```json
{
  "status": "success",
  "data": {
    "id": 1,
    "name": "Persona Portal v2.0",
    "description": "...",
    "status": "active",
    "color_hex": "#3498db",
    "icon_name": "rocket",
    "owner_id": 1,
    "created_at": "2026-04-13T15:42:00Z",
    "updated_at": "2026-04-13T15:42:00Z"
  },
  "meta": {
    "timestamp": "2026-04-13T15:42:00Z",
    "request_id": "uuid"
  }
}
```

#### List Projects
```http
GET /api/v1/projects?status=active&limit=50&offset=0
```

**Query Parameters**:
- `status`: active, archived, paused (default: active)
- `limit`: 1-100 (default: 50)
- `offset`: pagination offset (default: 0)

**Response (200)**:
```json
{
  "status": "success",
  "data": [
    {
      "id": 1,
      "name": "Project 1",
      "status": "active",
      "task_count": 12,
      "completed_count": 3,
      "overdue_count": 0,
      ...
    }
  ],
  "meta": {
    "total": 17,
    "limit": 50,
    "offset": 0,
    "timestamp": "2026-04-13T15:42:00Z",
    "request_id": "uuid"
  }
}
```

#### Get Project
```http
GET /api/v1/projects/{id}
```

#### Update Project
```http
PUT /api/v1/projects/{id}
Content-Type: application/json

{
  "name": "Updated Name",
  "status": "archived",
  "color_hex": "#e74c3c"
}
```

#### Delete Project
```http
DELETE /api/v1/projects/{id}
```

**Response (204)**: No content

---

### Tasks

#### Create Task
```http
POST /api/v1/projects/{projectId}/tasks
Content-Type: application/json

{
  "title": "Design new UI components",
  "description": "Create reusable button, card, and modal components",
  "status": "backlog",
  "due_date": "2026-04-20",
  "assignee_id": 1
}
```

**Response (201)**:
```json
{
  "status": "success",
  "data": {
    "id": 42,
    "project_id": 1,
    "title": "Design new UI components",
    "status": "backlog",
    "position": 5,
    "due_date": "2026-04-20",
    "assignee_id": 1,
    "created_by": 1,
    "created_at": "2026-04-13T15:42:00Z",
    "updated_at": "2026-04-13T15:42:00Z"
  },
  "meta": {
    "timestamp": "2026-04-13T15:42:00Z",
    "request_id": "uuid"
  }
}
```

#### List Tasks
```http
GET /api/v1/projects/{projectId}/tasks?status=all&sort=position&limit=200
```

**Query Parameters**:
- `status`: backlog, in_progress, done, blocked, all (default: all)
- `sort`: position, due_date, created_at, -updated_at (default: position)
- `limit`: 1-500 (default: 200)
- `offset`: pagination offset (default: 0)

#### Get Task
```http
GET /api/v1/projects/{projectId}/tasks/{taskId}
```

#### Update Task
```http
PUT /api/v1/projects/{projectId}/tasks/{taskId}
Content-Type: application/json

{
  "title": "Updated title",
  "status": "in_progress",
  "position": 3
}
```

**Position Reordering**: When `position` is provided, the task is moved to that position and all affected tasks are renumbered in a transaction.

#### Delete Task
```http
DELETE /api/v1/projects/{projectId}/tasks/{taskId}
```

**Response (204)**: No content

#### Bulk Reorder Tasks
```http
POST /api/v1/projects/{projectId}/tasks/reorder
Content-Type: application/json

{
  "order": [42, 15, 8, 23, 99]
}
```

**Response (200)**:
```json
{
  "status": "success",
  "data": {
    "updated_count": 5
  },
  "meta": {
    "timestamp": "2026-04-13T15:42:00Z",
    "request_id": "uuid"
  }
}
```

---

## Error Handling

All errors follow a standard format:

```json
{
  "status": "error",
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable message",
    "details": { /* optional */ }
  },
  "meta": {
    "timestamp": "2026-04-13T15:42:00Z",
    "request_id": "uuid"
  }
}
```

### Error Codes

| Code | Status | Meaning |
|------|--------|---------|
| `RESOURCE_NOT_FOUND` | 404 | Project/task does not exist |
| `BAD_REQUEST` | 400 | Validation failed |
| `UNPROCESSABLE_ENTITY` | 422 | Logically invalid request |
| `CONFLICT` | 409 | State conflict |
| `INTERNAL_SERVER_ERROR` | 500 | Server error |

---

## Validation Rules

### Projects

- **name**: Required, 1-255 characters
- **description**: Optional, max 5000 characters
- **color_hex**: Optional, format `#RRGGBB`, defaults to `#3498db`
- **icon_name**: Optional, must be one of: rocket, bug, feature, docs, deploy, design
- **status**: active, archived, or paused

### Tasks

- **title**: Required, 1-500 characters
- **description**: Optional, max 10000 characters
- **status**: backlog, in_progress, done, or blocked
- **due_date**: Optional, ISO 8601 format (YYYY-MM-DD)
- **assignee_id**: Optional, must be valid user ID
- **position**: Optional, 0 <= position < total_tasks

---

## Development

### Run Tests

```bash
npm test
npm run test:coverage
```

### Run in Development Mode

```bash
npm run dev
```

Uses nodemon for auto-reload.

---

## Database Schema

### Projects Table
```sql
id: BIGSERIAL PRIMARY KEY
name: VARCHAR(255) NOT NULL
description: TEXT
status: VARCHAR(50) CHECK (status IN ('active', 'archived', 'paused'))
color_hex: VARCHAR(7) FORMAT #RRGGBB
icon_name: VARCHAR(50)
owner_id: BIGINT -> users.id
created_at, updated_at: TIMESTAMP WITH TIME ZONE
```

### Tasks Table
```sql
id: BIGSERIAL PRIMARY KEY
project_id: BIGINT -> projects.id (CASCADE DELETE)
title: VARCHAR(500) NOT NULL
description: TEXT
status: VARCHAR(50) CHECK (status IN ('backlog', 'in_progress', 'done', 'blocked'))
position: INTEGER (0-indexed, per project)
due_date: DATE
assignee_id: BIGINT -> users.id (SET NULL)
created_by: BIGINT -> users.id
created_at, updated_at: TIMESTAMP WITH TIME ZONE
```

### Indexes
- projects: owner_id, status, updated_at
- tasks: project_id, status, project_id+status, project_id+position, assignee_id, due_date, updated_at

---

## Performance Targets

All endpoints should complete under their target response time with proper indexes:

| Endpoint | Target | Data Size |
|----------|--------|-----------|
| GET /projects | <100ms | 20 projects |
| GET /projects/{id}/tasks | <200ms | 500 tasks |
| POST /tasks | <150ms | - |
| PUT /tasks/{id} (with reorder) | <300ms | 500 tasks |
| DELETE /tasks/{id} | <100ms | - |

---

## Deployment

### Environment Variables

```bash
# Database
DATABASE_URL=postgresql://user:pass@host:5432/tekdek_command_center
DATABASE_POOL_MIN=5
DATABASE_POOL_MAX=20

# Server
PORT=3000
NODE_ENV=production
LOG_LEVEL=info

# CORS
CORS_ORIGIN=https://web.tekdek.dev
```

### Health Check

```http
GET /health
```

```json
{
  "status": "ok",
  "db": "connected",
  "uptime_ms": 12345,
  "timestamp": "2026-04-13T15:42:00Z"
}
```

---

## Implementation Notes

### Position Reordering Algorithm

When updating a task's position, the following algorithm is used:

1. Fetch all tasks in the project sorted by position
2. Remove the task from its current position
3. Insert it at the new position
4. Renumber all affected tasks (0-indexed)
5. Batch update in a single transaction

This ensures positions remain contiguous and consistent.

### Transaction Safety

Operations that modify multiple rows (e.g., reordering) use explicit transactions with ROLLBACK on failure to maintain data consistency.

### Cascade Delete

Deleting a project automatically deletes all its tasks (enforced at database level with CASCADE DELETE constraint).

---

## Architecture Decisions

- **Express.js**: Lightweight, familiar, proven for REST APIs
- **Zod**: Type-safe validation with clear error messages
- **PostgreSQL**: Relational DB with ACID compliance for data integrity
- **Connection Pooling**: Min 5, Max 20 connections for efficient resource usage
- **Real-time Saves**: Every POST/PUT immediately commits (no batching)
- **Structured Logging**: JSON format for easy parsing and monitoring

---

## Future Enhancements (Phase 2+)

- [ ] JWT authentication
- [ ] Role-based access control (RBAC)
- [ ] Audit trail logging
- [ ] Soft deletes for data recovery
- [ ] Task comments and activity feed
- [ ] Notifications
- [ ] API rate limiting per user
- [ ] GraphQL endpoint

---

**Built by**: Talos, Technical Coder of TekDek  
**Architecture**: Daedalus, Chief Architect  
**Status**: Production Ready ✅
