Work Order Management System — Technical Design Document
Classification: Internal — Engineering Date: 2026-02-13 Status: Proposed
1. APIs & Extension Points
1.1 REST API Surface
POST /api/v1/work-orders # Create WO (master or linked)
GET /api/v1/work-orders/:id # Get WO by ID
GET /api/v1/work-orders # List WOs (filtered, paginated)
PATCH /api/v1/work-orders/:id/status # Transition status
PUT /api/v1/work-orders/:id # Update WO fields
DELETE /api/v1/work-orders/:id # Soft-delete (draft only)
GET /api/v1/work-orders/:id/linked # List linked WOs for a master
GET /api/v1/work-orders/:id/dependency-graph # Get dependency DAG (JSON)
GET /api/v1/work-orders/:id/critical-path # Get critical path analysis
GET /api/v1/work-orders/:id/progress # Master WO progress summary
POST /api/v1/work-orders/:id/approvals # Request approval
PATCH /api/v1/work-orders/:id/approvals/:aid # Submit approval decision
GET /api/v1/work-orders/:id/approvals # List approval status
POST /api/v1/work-orders/:id/job-plan # Create/update job plan
GET /api/v1/work-orders/:id/job-plan # Get job plan
GET /api/v1/work-orders/:id/audit-trail # Get audit trail (paginated)
POST /api/v1/resources/match # Resource matching query
GET /api/v1/assets # List assets
GET /api/v1/tools # List tools
GET /api/v1/persons # List persons with experience
1.2 Event API (Event Bus)
// Published events (to NATS/Redis Streams)
type WOEventTopic =
| 'wo.lifecycle' // All state transitions
| 'wo.approval' // Approval requests and decisions
| 'wo.resource' // Resource allocation/release
| 'wo.compliance' // Compliance validation results
| 'wo.schedule' // Schedule changes and actuals
// Subscription patterns
// Compliance Engine: wo.lifecycle.*, wo.approval.*
// Agent Orchestrator: wo.lifecycle.status_changed, wo.lifecycle.blocked
// Observability: wo.* (all events)
// Schedule Service: wo.schedule.*, wo.lifecycle.completed
1.3 Extension Points
| Extension | Mechanism | Use Case |
|---|---|---|
| Custom WO fields | JSONB detail column + tenant-specific JSON Schema validation | Industry-specific metadata |
| Custom approval chains | Tenant-configurable approval rules in tenant_config | Different approval requirements per WO type |
| Job plan templates | Template library with parameterized job plans | Standardize common tasks across tenants |
| Resource matching plugins | Strategy pattern for matching algorithm | Different prioritization per tenant/domain |
| PM schedule generators | Plugin interface for schedule calculation | Custom maintenance intervals |
| Notification channels | Event subscriber plugins | Slack, email, PagerDuty, etc. |
2. Configuration Surfaces
2.1 Tenant Configuration
interface WOTenantConfig {
// Regulatory settings
defaultRegulatory: boolean; // Default regulatory flag for new WOs
approvalChains: ApprovalChainConfig[]; // Per WO-type approval requirements
complianceStandards: string[]; // ["21CFR11", "HIPAA", "SOC2"]
// Workflow settings
allowParallelLinkedWOs: boolean; // Allow concurrent linked WO execution
maxLinkedWOsPerMaster: number; // Limit linked WO count
autoAssignFromExperience: boolean; // Auto-match assignees by experience
// Schedule settings
businessSchedule: BusinessSchedule; // Working hours, holidays
approvalSLAHours: number; // SLA for approval response
escalationChain: string[]; // Escalation path for SLA breaches
// PM Automation
pmSchedules: PMScheduleConfig[]; // Automated WO generation rules
pmBatchSize: number; // Max WOs per batch generation
}
interface ApprovalChainConfig {
woType: WOSource;
regulatory: boolean;
requiredRoles: ('system_owner' | 'qa' | 'manager' | 'custom')[];
customApprovers?: string[]; // Person IDs for custom role
parallelApproval: boolean; // All at once vs. sequential
}
2.2 Environment Configuration
# config/wo-service.yaml
database:
url: ${DATABASE_URL}
pool_size: 20
statement_timeout_ms: 30000
events:
provider: nats # nats | redis_streams
url: ${NATS_URL}
prefix: wo
secrets:
provider: vault # vault | gcp_secret_manager
path: secret/data/wo-service
observability:
otel_endpoint: ${OTEL_COLLECTOR_URL}
metrics_port: 9090
log_level: info
wo:
audit_trail_retention_days: 2555 # 7 years for FDA
max_dependency_depth: 20
cycle_detection_interval_seconds: 300
approval_reminder_interval_hours: 24
3. Packaging & Deployment
3.1 Container Image
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production=false
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
USER node
EXPOSE 3000 9090
CMD ["node", "dist/server.js"]
3.2 GCP Cloud Run Deployment
# deploy/cloudrun.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: wo-service
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/minScale: "1"
autoscaling.knative.dev/maxScale: "10"
spec:
containers:
- image: gcr.io/${PROJECT}/wo-service:${VERSION}
ports: [{containerPort: 3000}]
resources:
limits: {cpu: "2", memory: 1Gi}
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef: {name: wo-db-url, key: url}
3.3 Database Migrations
migrations/
├── 001_create_base_types.sql
├── 002_create_persons_table.sql
├── 003_create_assets_table.sql
├── 004_create_tools_table.sql
├── 005_create_experience_ratings.sql
├── 006_create_work_orders.sql
├── 007_create_wo_approvals.sql
├── 008_create_wo_audit_trail.sql
├── 009_create_job_plans.sql
├── 010_enable_rls.sql
├── 011_create_indexes.sql
└── 012_create_audit_trigger.sql
4. Data Model
4.1 Entity Relationship Summary
work_orders (1) ←→ (0..N) work_orders [master_wo_id — self-referential hierarchy]
work_orders (1) ←→ (0..N) wo_approvals [approval chain]
work_orders (1) ←→ (0..N) wo_audit_trail [immutable history]
work_orders (1) ←→ (0..1) job_plans [execution plan]
work_orders (N) ←→ (1) persons [originator, assigner, assignee]
work_orders (N) ←→ (0..1) assets [target asset]
job_plans → tools [required tools - JSONB reference]
job_plans → experience_ratings [required experience - JSONB reference]
persons (1) ←→ (0..N) experience_ratings [skill certifications]
4.2 Key Constraints
wo_audit_trailhas no UPDATE/DELETE permissions. Enforced by PostgreSQL trigger:CREATE OR REPLACE FUNCTION prevent_audit_modification() RETURNS TRIGGER AS $$
BEGIN RAISE EXCEPTION 'Audit trail records cannot be modified'; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER audit_immutable BEFORE UPDATE OR DELETE ON wo_audit_trail
FOR EACH ROW EXECUTE FUNCTION prevent_audit_modification();work_orders.versionincremented on every UPDATE (optimistic locking).wo_approvals.signature_hashis non-nullable whenstatus = 'approved'.
5. Security Integration
| Layer | Implementation |
|---|---|
| Authentication | API Gateway validates JWT, extracts tenant_id + user_id |
| Authorization | RBAC: wo.create, wo.assign, wo.approve, wo.transition, wo.admin |
| Tenant isolation | PostgreSQL RLS, SET app.tenant_id on every connection |
| Credential management | Job Plan credential references → Vault lookup at execution time (never stored in PostgreSQL) |
| E-signature | SHA-256 hash of (approver_id ∥ wo_id ∥ wo_version ∥ timestamp ∥ role), signed with approver's private key |
| Transport | TLS 1.3 for all API calls, mTLS for inter-service communication |
| Audit | All API calls logged with correlation ID, actor, action, resource |
6. Example Interfaces
TypeScript
// src/interfaces/wo-service.interface.ts
export interface IWorkOrderService {
create(params: CreateWOParams): Promise<WorkOrder>;
createLinked(masterWoId: string, params: CreateLinkedWOParams): Promise<{ wo: WorkOrder; jobPlan: JobPlan }>;
getById(id: string): Promise<WorkOrder | null>;
list(filters: WOFilters, pagination: Pagination): Promise<PaginatedResult<WorkOrder>>;
transitionStatus(woId: string, newStatus: WOStatus, actorId: string, reason: string): Promise<WorkOrder>;
update(woId: string, updates: Partial<WorkOrder>, actorId: string, reason: string): Promise<WorkOrder>;
}
export interface IApprovalService {
requestApproval(woId: string, approverIds: string[], roles: string[]): Promise<WOApproval[]>;
submitDecision(approvalId: string, decision: 'approved' | 'rejected', signature: string, comments?: string): Promise<WOApproval>;
getApprovalStatus(woId: string): Promise<ApprovalSummary>;
}
export interface IResourceMatcher {
match(requirements: JobPlanRequirements): Promise<CandidateList>;
checkAvailability(personIds: string[], dateRange: DateRange): Promise<AvailabilityResult>;
getCapacity(dateRange: DateRange): Promise<CapacityForecast>;
}
export interface IHierarchyManager {
getLinkedWOs(masterWoId: string): Promise<WorkOrder[]>;
getDependencyGraph(masterWoId: string): Promise<DAG<WorkOrder>>;
getCriticalPath(masterWoId: string): Promise<WorkOrder[]>;
getProgress(masterWoId: string): Promise<MasterWOProgress>;
validateDAG(masterWoId: string, newDependency: WODependency): Promise<DAGValidationResult>;
}
Python (Agent Adapter)
# src/adapters/wo_agent_adapter.py
from dataclasses import dataclass
from typing import Protocol
@dataclass(frozen=True)
class AgentWOContext:
"""Context passed to agent workers for WO execution."""
wo_id: str
master_wo_id: str | None
summary: str
job_plan_description: str
required_tools: list[str]
required_experience: list[dict]
dependencies_satisfied: bool
regulatory: bool
compliance_standards: list[str]
class WOAgentAdapter(Protocol):
async def create_wo_from_task(self, task: 'AgentTask') -> str: ...
async def get_execution_context(self, wo_id: str) -> AgentWOContext: ...
async def report_completion(self, wo_id: str, result: 'AgentResult') -> None: ...
async def report_failure(self, wo_id: str, error: 'AgentError') -> None: ...
async def request_human_checkpoint(self, wo_id: str, reason: str) -> None: ...
7. Performance Characteristics
| Operation | Target Latency | Throughput | Notes |
|---|---|---|---|
| Create WO | < 50ms | 500/s | Single INSERT + audit entry |
| Transition status | < 100ms | 200/s | SELECT FOR UPDATE + UPDATE + audit + event |
| List WOs (paginated) | < 200ms | 100 req/s | Index scan on tenant + status + created_at |
| Dependency graph resolution | < 500ms | 50/s | Recursive CTE, max depth 20 |
| Critical path calculation | < 1s | 20/s | Graph traversal, cached per Master WO |
| Resource matching | < 2s | 50/s | Multi-table join with scoring |
| PM batch generation | < 30s per 1000 WOs | 1 batch/min | Async, background worker |
| Audit trail query | < 500ms | 100 req/s | Partitioned by month, indexed by wo_id + timestamp |
Connection pooling: 20 connections per service instance. Connection acquired per request, released after transaction. Caching: Master WO progress and critical path cached in application memory (1-minute TTL). Invalidated on linked WO status change.