Files
platform/OFFICERDEV_BACKEND.md
T
2026-02-22 16:49:30 +00:00

1180 lines
31 KiB
Markdown

# Officer.dev Backend Architecture
## Executive Summary
Officer is a full-stack AI-assisted personal backend and frontend for life management. The backend is a **Bun-based monorepo** using:
- **Hono** framework for REST API (port 5000)
- **PostgreSQL** with Drizzle ORM for persistent data
- **WebSockets** for real-time terminal and AI chat functionality
- **Multi-workspace** shared libraries for code reuse
- **Node.js PTY sidecars** for terminal emulation
- **Pi coding agent integration** for AI-powered development assistance
This document covers the backend architecture, data flow, and technical patterns.
---
## Table of Contents
1. [Architecture Overview](#architecture-overview)
2. [Technology Stack](#technology-stack)
3. [Directory Structure](#directory-structure)
4. [Core Server](#core-server)
5. [API Architecture](#api-architecture)
6. [Database Design](#database-design)
7. [WebSocket Services](#websocket-services)
8. [Shared Workspaces](#shared-workspaces)
9. [Error Handling](#error-handling)
10. [Development & Deployment](#development--deployment)
11. [Key Features](#key-features)
---
## Architecture Overview
### High-Level Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ Web Browser (Frontend) │
└──────────────┬──────────────────────────────────────────────┘
├─ HTTP REST API (port 5000)
├─ WebSocket: Terminal (ws://api:5000/api/terminal/ws)
├─ WebSocket: Pi Chat (ws://api:5000/api/pi/chat/ws)
└─ Dev Server Proxy (ws://api:5000/api/dev-server-proxy/*)
┌──────────────▼──────────────────────────────────────────────┐
│ Bun Server (src/server.tsx + Hono Router) │
├─────────────────────────────────────────────────────────────┤
│ Middleware: │
│ - CORS handler │
│ - User authentication (JWT + token blacklist) │
│ - Request body parser │
│ │
│ Routes: │
│ - /api/auth → Authentication (login, signup) │
│ - /api/plans → Plans management │
│ - /api/skills → Skills (Pi integration) │
│ - /api/tasks → Tasks & processes │
│ - /api/upload → File uploads │
│ - /api/workspaces → Workspace management │
│ - /api/settings → User settings │
│ - /api/dev-server → Local dev server routing │
│ - WebSocket handlers → Real-time communication │
└──────────────┬──────────────────────────────────────────────┘
┌──────┴──────────────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────────┐
│ PostgreSQL DB │ │ Node.js PTY Sidecar │
│ (officer_db) │ │ (Terminal Emulation)│
│ │ │ │
│ Users, Plans, │ │ xterm-js │
│ Skills, Tasks, │ │ node-pty │
│ Sessions, etc │ │ Docker container │
└──────────────────┘ └──────────────────────┘
```
### Request/Response Flow
```
Client Request
Server Router (Bun)
Authentication Middleware
Protected/Public Handler
Database Query (Drizzle ORM) OR External Service
Response (JSON/WebSocket)
Client
```
---
## Technology Stack
### Core Runtime & Framework
- **Bun** (v1.30+) - Fast JavaScript runtime with built-in tooling
- **TypeScript** (v5.9+) - Strict mode enabled
- **Hono** (v4.11+) - Lightweight, type-safe web framework
- **Node.js** - For PTY sidecar processes
### Database & ORM
- **PostgreSQL** - Primary persistent data store
- **Drizzle ORM** (v0.45+) - Type-safe SQL query builder
- **Drizzle Kit** (v0.31+) - Schema management and migrations
### Real-Time Communication
- **WebSockets** (native Bun) - Bidirectional communication
- **Redis** (optional) - Session/cache storage
### Authentication & Security
- **JWT** - Token-based authentication
- **Argon2** - Password hashing (bcrypt alternative)
- **SimpleWebAuthn** - WebAuthn/FIDO2 passkey support
- **Token Blacklist** - Revocation tracking
### AI & Automation
- **@anthropic-ai/claude-agent-sdk** - Claude integration
- **Pi Coding Agent** - CLI-based AI development assistant
- **Nodemailer** - Email notifications
- **Googleapis** - Google integration for services
### Utilities
- **node-pty** - Cross-platform pseudoterminal support
- **Cron** (v4.3+) - Scheduled task execution
- **Date-fns** (v4.1+) - Date manipulation
- **Zod** (v4.2+) - Schema validation
---
## Directory Structure
### Complete Backend Layout
```
monorepo/
├── src/
│ ├── server.tsx # Main Bun server entry point
│ │
│ ├── servers/ # Backend core
│ │ ├── bootstrap.ts # Server initialization
│ │ ├── hono.ts # Hono app & router setup
│ │ ├── jwt.ts # JWT token handling
│ │ ├── custom-errors.ts # Custom error classes
│ │ ├── create-router.ts # Router factory with context
│ │ ├── data-path.ts # Path management
│ │ │
│ │ ├── _middlewares/ # Shared middleware
│ │ │ ├── user-middleware.ts # Auth verification
│ │ │ └── body-parser.ts # Request parsing
│ │ │
│ │ └── api/ # API routes
│ │ ├── auth/ # Authentication routes
│ │ │ ├── signin.ts # Login endpoint
│ │ │ ├── signup.ts # Registration endpoint
│ │ │ ├── signout.ts # Logout endpoint
│ │ │ ├── verify.ts # Email verification
│ │ │ ├── passkey-router.ts # WebAuthn endpoints
│ │ │ ├── reset-password.ts # Password reset
│ │ │ └── auth.ts # Core auth logic
│ │ │
│ │ ├── terminal/ # Terminal WebSocket
│ │ │ ├── websocket.ts # WS handler
│ │ │ └── pty-sidecar.mjs # PTY subprocess
│ │ │
│ │ ├── pi/ # Pi coding agent integration
│ │ │ ├── websocket.ts # Chat WS handler
│ │ │ ├── rest.ts # REST endpoints
│ │ │ ├── pi-bridge.ts # Pi SDK bridge
│ │ │ ├── storage.ts # Chat session storage
│ │ │ └── session-manager.ts # Session management
│ │ │
│ │ ├── dev-server/ # Local dev server routing
│ │ │ └── router.ts # Dev server proxy
│ │ │
│ │ ├── plans/ # Plans management
│ │ ├── skills/ # Skills routes
│ │ ├── tasks/ # Tasks & processes
│ │ ├── workspaces/ # Workspace management
│ │ ├── settings/ # User settings
│ │ ├── upload/ # File upload
│ │ ├── file-browser/ # File browser API
│ │ ├── scrape/ # Web scraping
│ │ ├── sessions/ # Chat sessions
│ │ ├── task-logs/ # Task execution logs
│ │ ├── server-settings/ # System configuration
│ │ └── users/ # User management
│ │
│ ├── databases/ # Data layer
│ │ └── officer_db/ # Main database package
│ │ ├── drizzle.config.ts # Drizzle configuration
│ │ ├── migrations/ # Database migrations
│ │ ├── src/
│ │ │ ├── schema.ts # Table definitions
│ │ │ ├── types.ts # Inferred types
│ │ │ └── index.ts # Exports
│ │ └── package.json # Workspace manifest
│ │
│ └── workspaces/ # Shared libraries
│ ├── components/ # React components
│ ├── hooks/ # React hooks
│ ├── helpers/ # Utility functions
│ ├── types/ # Shared types
│ ├── state/ # State management
│ ├── config/ # Configuration
│ ├── definitions/ # Constants
│ ├── emailer/ # Email service
│ ├── injector/ # Dependency injection
│ └── i18n/ # Internationalization
├── package.json # Root workspace config
├── bunfig.toml # Bun configuration
├── tsconfig.json # TypeScript config
└── .env # Environment variables
```
---
## Core Server
### Entry Point: `src/server.tsx`
The main server file initializes the Bun HTTP server and handles:
1. Route registration (static files, API, WebSockets)
2. WebSocket upgrade logic and authentication
3. Dev server proxy for HMR and local dev environments
4. PI coding agent installation/verification
#### Key Responsibilities
```typescript
// 1. Static file serving
'/static/*' public/ directory files
// 2. HTML fallback for SPA routing
'/' and '/*' officer-web app
// 3. API routing
'/api/*' honoServer (REST endpoints)
// 4. WebSocket routing with auth
'/api/terminal/ws' Terminal WebSocket
'/api/pi/chat/ws' Pi Chat WebSocket
// 5. Dev server proxy
'/api/dev-server-proxy/*' Proxied WS for local dev servers
```
#### WebSocket Authentication Pattern
```typescript
async function upgradeWs(req: Request, server: any, provider: 'terminal' | 'pi') {
// 1. Extract JWT token from query params
const token = new URL(req.url).searchParams.get('token');
// 2. Verify token and extract user
const user = await verify(token);
// 3. Check token blacklist (for revoked tokens)
const blacklisted = await officerdb.query.TokenBlacklist.findFirst({...});
// 4. Extract WS-specific parameters
const sessionId = url.searchParams.get('sessionId');
const cwd = url.searchParams.get('cwd');
const cols = url.searchParams.get('cols'); // terminal dimensions
// 5. Upgrade connection with authenticated data
server.upgrade(req, { data: { userId, email, role, provider, ... } });
}
```
### Hono Server: `src/servers/hono.ts`
Hono is a lightweight web framework perfect for edge computing and Bun.
#### Server Initialization
```typescript
const honoServer = new Hono<{ Variables: HonoVariables }>();
honoServer.use(cors({ origin: '*', allowMethods: [...] }));
// Public routes
honoServer.get('/api', (ctx) => ctx.json({ officerAPI: 'ok' }));
honoServer.route('/api/auth', authRouter);
honoServer.route('/api/server-settings', serverSettingsRouter);
// Protected routes
const protectedRouter = createRouter();
protectedRouter.use(bodyParser());
protectedRouter.use(userMiddleware);
protectedRouter.route('/plans', plansRouter);
protectedRouter.route('/tasks', tasksRouter);
// ... other routes
honoServer.route('/api', protectedRouter);
// Error handling
honoServer.onError((error, ctx) => {
if (error instanceof CustomError) {
return ctx.json(error.returnValue, error.statusCode);
}
return ctx.text('Internal Server Error', 500);
});
```
#### Hono Variables Context
```typescript
type HonoVariables = {
userId: number;
email: string;
role: 'admin' | 'user';
// Accessible in all routes via ctx.get('userId')
};
```
---
## API Architecture
### Route Organization
The API is organized by feature domain:
```
/api/
├── auth/ # User authentication (public)
│ ├── POST /signin
│ ├── POST /signup
│ ├── POST /signout
│ ├── GET /verify
│ ├── POST /passkeys (WebAuthn)
│ └── ...
├── plans/ # Plans management (protected)
├── skills/ # Skills endpoints
├── tasks/ # Task operations
├── workspaces/ # Workspace operations
├── settings/ # User preferences
├── upload/ # File uploads
├── file-browser/ # File system access
├── terminal/ws # Terminal emulation (WS)
├── pi/ # AI assistant integration
│ ├── /ws # Chat (WebSocket)
│ └── /rest # REST endpoints
└── dev-server/ # Local dev server routing
```
### Router Creation Pattern: `src/servers/create-router.ts`
```typescript
// Factory function for creating contextualized routers
export function createRouter() {
return new Hono<{ Variables: HonoVariables }>();
}
// Usage in route handlers:
const router = createRouter();
router.get('/endpoint', (ctx) => {
const userId = ctx.get('userId');
// Route logic
});
```
### Error Handling: `src/servers/custom-errors.ts`
```typescript
class CustomError extends Error {
constructor(
public statusCode: number,
message: string,
public returnValue?: Record<string, any> | string,
) {
super(message);
}
}
// Usage patterns
throw new CustomError(400, 'Bad request', { error: 'Invalid input' });
throw new CustomError(401, 'Unauthorized');
throw new CustomError(500, 'Internal error', { error: 'Database failed' });
```
---
## Database Design
### Primary Database: `officer_db`
Located in `src/databases/officer_db/`, this is the main persistent data store.
#### Drizzle Configuration
```typescript
// drizzle.config.ts
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './src/schema.ts',
out: './migrations',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!,
},
});
```
#### Schema Structure
The schema defines all tables and their relationships:
```typescript
// src/databases/officer_db/src/schema.ts
// Core tables
export const Users = pgTable('users', {
id: serial('id').primaryKey(),
email: text('email').unique().notNull(),
password: text('password'),
role: text('role').$type<'admin' | 'user'>().default('user'),
verified: boolean('verified').default(false),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
export const Plans = pgTable('plans', {
id: serial('id').primaryKey(),
userId: integer('user_id').references(() => Users.id),
title: text('title').notNull(),
description: text('description'),
// ... other fields
});
export const Skills = pgTable('skills', {
id: serial('id').primaryKey(),
userId: integer('user_id').references(() => Users.id),
name: text('name').notNull(),
content: text('content'),
// ... other fields
});
// ... many more tables for tasks, sessions, workspaces, etc.
// Relations
export const usersRelations = relations(Users, ({ many }) => ({
plans: many(Plans),
skills: many(Skills),
}));
```
#### Type Generation
Types are automatically inferred from schema:
```typescript
// src/databases/officer_db/src/types.ts
// Simple table types
export type User = typeof Users.$inferSelect;
export type UserInsert = typeof Users.$inferInsert;
// Extended types for API responses
export type UserWithRelations = User & {
plans: Plan[];
skills: Skill[];
};
```
#### Database Operations in Routes
```typescript
import { officerdb, eq, Users } from 'officerdb';
// Simple query
const user = await officerdb.query.Users.findFirst({
where: eq(Users.id, userId),
});
// Query with relations
const user = await officerdb.query.Users.findFirst({
where: eq(Users.id, userId),
with: {
plans: true,
skills: true,
},
});
// Insert with returning
const [newUser] = await officerdb.insert(Users).values({
email: 'user@example.com',
password: hashedPassword,
}).returning();
// Update
await officerdb.update(Users).set({
verified: true,
}).where(eq(Users.id, userId));
```
#### Token Blacklist Table
```typescript
export const TokenBlacklist = pgTable('token_blacklist', {
id: serial('id').primaryKey(),
jti: text('jti').unique().notNull(), // JWT ID
expiresAt: timestamp('expires_at').notNull(),
createdAt: timestamp('created_at').defaultNow(),
});
// Used for token revocation (logout, password change, etc.)
```
### Database Migrations
Migrations are generated by Drizzle and stored in `src/databases/officer_db/migrations/`:
```bash
# Generate new migration
bun run db:gen
# Apply migrations
bun run db:push
# Open Drizzle Studio for visual management
bun run db:studio
```
---
## WebSocket Services
### 1. Terminal WebSocket: `src/servers/api/terminal/`
Provides an interactive terminal emulator in the browser using xterm.js.
#### Architecture
```
Browser (xterm.js)
↓ WebSocket
Officer Server (websocket.ts)
↓ IPC/Stdio
PTY Sidecar (pty-sidecar.mjs)
↓ Shell Process
System Shell (bash/zsh)
```
#### Handler: `websocket.ts`
```typescript
export const terminalWebsocket = {
// Connection established
open(ws: ServerWebSocket<WSData>) {
const { userId, cwd, cols, rows, sandboxed } = ws.data;
// 1. Spawn or reuse PTY sidecar
// 2. Set terminal dimensions
// 3. Send initial prompt
},
// Client sends data (typing, etc.)
message(ws: ServerWebSocket<WSData>, raw: string | Buffer) {
// 1. Parse message type (input, resize, etc.)
// 2. Forward to PTY process
},
// Connection closed
close(ws: ServerWebSocket<WSData>) {
// 1. Kill PTY process
// 2. Cleanup resources
},
};
```
#### PTY Sidecar: `pty-sidecar.mjs`
A Node.js subprocess that manages the actual pseudoterminal:
```javascript
// Uses node-pty for cross-platform terminal support
const pty = require('node-pty');
const term = pty.spawn('bash', [], {
name: 'xterm-color',
cols: 120,
rows: 40,
cwd: process.env.CWD,
});
// stdout → send to client
term.on('data', (data) => {
process.stdout.write(JSON.stringify({ type: 'output', data }));
});
// stdin from client → write to terminal
process.stdin.on('data', (chunk) => {
const msg = JSON.parse(chunk);
if (msg.type === 'input') term.write(msg.data);
if (msg.type === 'resize') term.resize(msg.cols, msg.rows);
});
```
#### Sandboxed vs. Real Terminals
- **Sandboxed**: Limited to specific directories, no system access
- **Real**: Full system access from user's working directory
### 2. Pi Coding Agent WebSocket: `src/servers/api/pi/`
Integrates the Pi coding agent for AI-assisted development.
#### Architecture
```
Browser (Chat UI)
↓ WebSocket
Officer Server (pi/websocket.ts)
↓ SDK
Pi Coding Agent (pi-bridge.ts)
↓ RPC/Tools
LLM API (Claude, GPT, etc.)
```
#### Components
**websocket.ts**: WebSocket message handler
- Routes incoming chat messages to Pi
- Streams responses back to client
- Manages session state
**pi-bridge.ts**: SDK integration layer
```typescript
export async function createPiSession(
cwd: string,
userEmail: string,
sessionId?: string,
) {
// 1. Initialize Pi SDK
const { session } = await createAgentSession({
cwd,
model: selectedModel,
tools: createCodingTools(cwd),
});
// 2. Subscribe to events
session.subscribe((event) => {
// Stream events back to client via WS
});
// 3. Return session for messaging
return session;
}
```
**rest.ts**: REST endpoints for Pi operations
- Create new sessions
- List sessions
- Get session details
- Export conversations
**storage.ts**: Chat session persistence
```typescript
// Store conversation history in database
interface PiSession {
id: string;
userId: number;
cwd: string;
model: string;
createdAt: timestamp;
messages: PiMessage[];
}
// Retrieve from database when resuming
```
**session-manager.ts**: Session lifecycle management
#### Message Flow
```
Client: "ls -la"
→ WebSocket to Officer
→ Pi process stdin
→ Pi executes bash tool
→ Tool output
→ Stream back to client
```
#### Integration with Tools
Pi can execute:
- `read` - Read files
- `bash` - Run shell commands
- `edit` - Modify files
- `write` - Create files
- Custom tools via extensions
---
## Shared Workspaces
Shared code is organized in `src/workspaces/` as Bun workspace packages:
### Key Workspaces
**types/** - TypeScript type definitions
- Centralized, exported via `'types'` alias
- Shared by frontend and backend
- Database types imported and re-exported
**helpers/** - Utility functions
- Formatters, validators, converters
- Pure functions with no side effects
**hooks/** - React hooks
- Frontend-only
- `useAuth`, `useQuery`, `useMutation`, etc.
**state/** - State management
- Global state stores
- Context providers
- Zustand/React Context usage
**components/** - React components
- UI components (buttons, inputs, etc.)
- Complex feature components
- Reusable across apps
**config/** - Configuration
- Constants
- Environment-specific settings
**definitions/** - Enum and constant definitions
- User roles
- Status values
- Feature flags
**emailer/** - Email service
```typescript
// Nodemailer-based email sending
export async function sendEmail(to: string, subject: string, html: string) {
const transporter = nodemailer.createTransport({...});
return transporter.sendMail({ to, subject, html });
}
```
**injector/** - Dependency injection
- Service locator pattern
- Configuration management
**i18n/** - Internationalization
- Multi-language support
- Locale management
**sounds/** - Audio assets
- Notification sounds
- UI feedback audio
**widgets/** - Complex UI widgets
- Feature-rich components
- Composed from basic components
### Workspace Configuration
Each workspace has a `package.json`:
```json
{
"name": "components",
"version": "0.1.0",
"type": "module",
"exports": {
".": "./index.ts"
},
"main": "./index.ts"
}
```
### Import Pattern in Code
```typescript
// In any app (frontend/backend)
import { User, Plan } from 'types';
import { formatDate } from 'helpers';
import { useAuth } from 'hooks';
import { useGlobalState } from 'state';
import { Button } from 'components';
```
---
## Error Handling
### Error Classification
```typescript
// Custom error hierarchy
class CustomError extends Error {
constructor(
public statusCode: number,
message: string,
public returnValue?: any,
) {}
}
// Usage patterns
throw new CustomError(400, 'Bad request', { field: 'email', error: 'Invalid' });
throw new CustomError(401, 'Unauthorized');
throw new CustomError(403, 'Forbidden');
throw new CustomError(404, 'Not found', { resource: 'Plan' });
throw new CustomError(409, 'Conflict', { error: 'Email already exists' });
throw new CustomError(500, 'Internal server error');
```
### Middleware Error Handling
```typescript
honoServer.onError((error, ctx) => {
// CustomError → formatted response
if (error instanceof CustomError) {
return ctx.json(error.returnValue || error.message, error.statusCode);
}
// Unexpected error → 500
console.error('Unexpected error:', error.message);
return ctx.text('Internal Server Error', 500);
});
```
### Try/Catch Pattern
```typescript
// In route handlers
router.post('/endpoint', async (ctx) => {
try {
const body = await ctx.req.json();
// Validation
if (!body.email) {
throw new CustomError(400, 'Email required', { field: 'email' });
}
// Database operation
const user = await officerdb.insert(Users).values({...}).returning();
if (!user) throw new CustomError(500, 'Failed to create user');
return ctx.json({ success: true, user });
} catch (error) {
// Re-throw CustomErrors, let middleware handle
if (error instanceof CustomError) throw error;
// Unexpected error
console.error('Route error:', error);
throw new CustomError(500, 'Internal server error');
}
});
```
---
## Authentication System
### JWT Flow
```
User Login
Verify credentials (email + password)
Generate JWT token
{
"sub": userId,
"email": email,
"role": "user",
"iat": timestamp,
"exp": timestamp,
"jti": unique-token-id
}
Return token to client
Client stores in localStorage
Client sends in Authorization header
Server verifies signature & expiration
Grant access
```
### Token Verification: `src/servers/jwt.ts`
```typescript
export async function verify(token: string) {
try {
// 1. Verify signature and expiration
const decoded = jwt.verify(token, JWT_SECRET) as JWTPayload;
// 2. Check token blacklist (for revoked tokens)
if (decoded.jti) {
const blacklisted = await officerdb.query.TokenBlacklist.findFirst({
where: eq(TokenBlacklist.jti, decoded.jti),
});
if (blacklisted) return null; // Token revoked
}
return { id: decoded.sub, email: decoded.email, role: decoded.role };
} catch {
return null; // Invalid token
}
}
```
### Logout with Token Blacklist
```typescript
router.post('/signout', async (ctx) => {
const token = ctx.req.header('Authorization')?.replace('Bearer ', '');
const decoded = jwt.decode(token) as JWTPayload;
// Add to blacklist
await officerdb.insert(TokenBlacklist).values({
jti: decoded.jti,
expiresAt: new Date(decoded.exp * 1000),
});
return ctx.json({ success: true });
});
```
### WebAuthn/Passkey Support
```typescript
// Registration
router.post('/passkeys/register/options', async (ctx) => {
const user = ctx.get('userId');
const options = await generateRegistrationOptions({
rpID: 'officer.dev',
rpName: 'Officer',
userID: Buffer.from(String(user.id)),
userName: user.email,
});
return ctx.json(options);
});
// Verification
router.post('/passkeys/register/verify', async (ctx) => {
const credential = await ctx.req.json();
const verification = await verifyRegistrationResponse({
credential,
expectedOrigin: 'https://officer.dev',
expectedRPID: 'officer.dev',
});
if (verification.verified) {
// Store passkey
await officerdb.insert(Passkeys).values({...});
}
return ctx.json({ verified: verification.verified });
});
```
---
## Development & Deployment
### Development Server
```bash
# Start with hot reload
bun dev
# Server runs on http://localhost:5000
# Frontend available at http://localhost:5000/
```
### Database Operations
```bash
# Generate migration from schema changes
bun run db:gen
# Apply pending migrations
bun run db:push
# Open Drizzle Studio (UI for database)
bun run db:studio
```
### Build & Production
```bash
# Full build
bun run build
# Production server
NODE_ENV=production bun src/server.tsx
# Runs on port specified by PORT env var (default 5000)
```
### Environment Variables
```bash
# .env
DATABASE_URL=postgresql://user:pass@localhost:5432/officer
JWT_SECRET=your-secret-key
NODE_ENV=development
PORT=5000
```
---
## Key Features
### 1. Real-Time Terminal
- Interactive shell in browser
- File operations
- Code execution
- Multi-session support
- Sandboxed mode option
### 2. AI-Powered Development with Pi
- Chat interface with Claude
- File reading/writing capabilities
- Shell command execution
- Session persistence
- Model selection
### 3. Task Management
- Create and track tasks
- Task dependencies
- Scheduled execution (cron)
- Task logs and history
- Process management
### 4. Workspace Management
- Multi-workspace support
- Project organization
- Settings per workspace
- Resource management
### 5. File Management
- File browser with preview
- Upload support (50GB max)
- Web scraping
- Export/import
### 6. Skills System
- Pi agent skills
- Custom task templates
- Reusable automation
### 7. Settings & Configuration
- User preferences
- System configuration
- Integration settings
- Resource limits
---
## Performance Considerations
### Connection Pooling
PostgreSQL connections are managed by Drizzle ORM with configurable pool size.
### Caching
- Redis support for session data (optional)
- Database query result caching
- Static asset caching
### Rate Limiting
- Per-user API limits (todo)
- WebSocket message throttling
- File upload size limits (50GB max)
### Database Optimization
- Proper indexing on foreign keys
- Query optimization with relations
- Pagination for large datasets
---
## Security
### CORS
```typescript
honoServer.use(cors({
origin: '*',
allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization'],
}));
```
### JWT Security
- Secret stored in env variables
- Token expiration enforced
- Token blacklist for revocation
- jti (JWT ID) for tracking
### Password Security
- Argon2 hashing (modern, secure)
- No plain-text storage
- Email verification required
- Password reset via email
### WebAuthn/FIDO2
- Hardware key support
- Phishing-resistant
- No passwords stored for passkeys
---
## Monitoring & Logging
### Current Logging
- Console.log for debugging
- Error stack traces printed to console
### Future Monitoring (Signoz Integration)
- Distributed tracing
- Performance monitoring
- Error tracking
- Log aggregation
---
## Testing
### Current Test Setup
- `@testing-library/react` for component tests
- `@playwright/test` for E2E tests
- `happy-dom` for DOM testing
### Test Command
```bash
# Not yet fully configured
bun test
```
---
## Related Documentation
- **Frontend Architecture**: See `OFFICERDEV_FRONTEND.md`
- **CONVENTIONS.md**: Detailed code patterns and style guide
- **CLAUDE.md**: Project overview and patterns
- **Each folder CLAUDE.md**: Feature-specific documentation
---
## Summary
Officer's backend is a modern, type-safe Bun monorepo with:
- RESTful API using Hono framework
- Real-time capabilities via WebSockets
- PostgreSQL persistence with Drizzle ORM
- AI integration through Pi coding agent
- Modular architecture with shared workspaces
- Strong TypeScript support throughout
- Robust authentication with JWT and WebAuthn
The architecture prioritizes developer experience, type safety, and maintainability while providing powerful real-time and AI-powered features to users.