# Headroom - Project Charter & Specifications **Version:** 1.0 **Date:** February 17, 2026 **Status:** Approved for Development --- ## Executive Summary **Headroom** is a resource planning and capacity management tool designed to solve the allocation chaos faced by engineering managers juggling multiple projects and team members. It replaces error-prone spreadsheets with a structured system that tracks capacity, forecasts utilization, prevents over/under-billing, and provides clear visibility into team allocation. **Target Users:** - Engineering managers (10-15 person teams) - Managing 10-12 concurrent projects in various stages - Need month-by-month capacity planning and allocation tracking **Core Value Proposition:** - Know exactly who has headroom for new work - Prevent billing errors (over-allocation → overcharge, under-allocation → undercharge) - Forecast revenue based on approved estimates and current allocations - Track planned vs actual hours to understand team utilization --- ## Problem Statement ### Current Pain Points **The Spreadsheet Nightmare:** - Manual capacity calculations across holidays, PTO, weekends - No validation (easy to over-allocate people or projects) - Hard to see at a glance: "Who has capacity this month?" - Billing forecasts require manual formula updates - No audit trail of allocation changes - Difficult to track planned vs actual hours **Business Impact:** - **Over-allocation:** Leads to overcharging clients → escalations, unhappy customers - **Under-allocation:** Leads to undercharging → revenue loss, unhappy management - **Resource conflicts:** Multiple managers allocating the same person without visibility - **Forecast inaccuracy:** Can't reliably predict revenue or capacity needs --- ## Solution Overview Headroom provides a structured workflow for capacity planning and resource allocation: ``` ┌─────────────────────────────────────────────────────────────────┐ │ MONTHLY CAPACITY PLANNING CYCLE │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ STEP 1: CAPACITY PLANNING │ │ ──────────────────────────────────────────────────── │ │ • Define team members (name, role, hourly rate) │ │ • Mark holidays, PTO, weekends for the month │ │ • Set availability per day (1=full, 0.5=half, 0=unavailable)│ │ │ │ OUTPUT: │ │ • Individual capacity (person-days per month) │ │ • Team capacity (total available person-days) │ │ • Possible revenue (capacity × hourly rates) │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ STEP 2: PROJECT SETUP │ │ ──────────────────────────────────────────────────── │ │ • Track project status (Initial → Estimates → Funded → ...) │ │ • Define approved estimate (total billable hours) │ │ • Forecast effort distribution across months │ │ │ │ OUTPUT: │ │ • Month-wise project forecast │ │ • Alerts when forecast ≠ approved estimate │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ STEP 3: RESOURCE ALLOCATION │ │ ────────────────────────────────────────────────────────────│ │ • Allocate hours per person per project per month │ │ • Validation: total allocation ≤ team capacity │ │ • Validation: project allocation = approved estimate │ │ • "Untracked" bucket for external team time │ │ │ │ OUTPUT: │ │ • Clear view: who's allocated to what │ │ • Over/under allocation indicators (RED flags) │ │ • Running utilization % per person │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ STEP 4: ACTUALS TRACKING │ │ ────────────────────────────────────────────────────────────│ │ • Team members log hours worked (monthly aggregate) │ │ • Manual entry (no time-tracking tool integration for MVP) │ │ │ │ OUTPUT: │ │ • Running utilization (allocated vs capacity YTD) │ │ • Overall utilization (allocated % per month) │ │ • Variance: planned vs actual │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## Complete Requirements ### 1. Capacity Planning **Inputs:** - Team member list (name, role/team, hourly rate) - Calendar data per month (holidays, weekends) - Individual PTO requests - Daily availability (1.0 = full day, 0.5 = half day, 0 = unavailable) **Calculations:** - Individual capacity = Σ(working days × availability) - Team capacity = Σ(individual capacities) - Possible revenue = Σ(individual capacity × hourly rate) **Outputs:** - Individual capacity report (person-days per month) - Team capacity summary - Revenue potential (if fully utilized) **Validation Rules:** - Availability must be 0, 0.5, or 1.0 - Hourly rate must be > 0 - Working days must exclude holidays, weekends, PTO --- ### 2. Project Management **Project Attributes:** - Project ID (unique identifier) - Project title - Type: Project (billable) / Support (ongoing ops) - Status (see state machine below) - Approved estimate (total billable hours) - Forecasted effort (month-by-month breakdown) **Project Status State Machine:** ``` NA/Support → Initial → Gathering Estimates → Estimate Pending Approval ↓ Estimate Rework ←───────┘ ↓ Estimate Approved → Funded → Scheduled → In-Progress ↓ Ready for Prod → Done ↓ [Optional: On-Hold, Cancelled] ``` **Outputs:** - Month-wise forecast per project - Alert when Σ(forecasted effort) ≠ approved estimate (RED flag) - Alert when monthly team allocation > team capacity (RED flag) **Validation Rules:** - Approved estimate must be > 0 - Forecasted effort sum must equal approved estimate (±tolerance) - Cannot allocate hours to projects in status "Done" or "Cancelled" --- ### 3. Resource Allocation **Allocation Matrix:** ``` For selected month M: ┌────────────────────────────────────────────────────┐ │ Project │ Dev A │ Dev B │ Dev C │ Untracked │ │ ├────────────┼───────┼───────┼───────┼───────────┼──┤ │ Project X │ 40h │ 20h │ 0 │ 10h │ │ │ Project Y │ 20h │ 40h │ 30h │ 0 │ │ │ Project Z │ 0 │ 80h │ 60h │ 0 │ │ ├────────────┼───────┼───────┼───────┼───────────┼──┤ │ Total │ 60h │ 140h │ 90h │ 10h │ │ │ Capacity │ 160h │ 160h │ 120h │ ∞ │ │ │ % Util │ 38% │ 88% │ 75% │ N/A │ │ └────────────────────────────────────────────────────┘ ``` **Features:** - Allocate hours per person per project per month - "Untracked" resource for external team time (no billing tracked) - Visual indicators: - GREEN: Allocation = Approved estimate (100%) - YELLOW: Under-allocated (< 100%) - RED: Over-allocated (> 100%) **Outputs:** - Allocation summary per month - Per-project allocation % (allocated / approved estimate) - Per-person utilization % (allocated / capacity) - Over/under allocation flags **Validation Rules:** - Cannot allocate negative hours - Cannot allocate more than person's monthly capacity (warning, not hard block) - Cannot allocate to non-existent project or person - Sum of project allocations should equal approved estimate (tolerance: ±5%) --- ### 4. Actuals & Utilization Tracking **Data Entry:** - Team members log hours worked per project per month - Entry method: Manual (monthly aggregate) - Updates: Can be incremental (weekly updates accumulate) **Calculations:** - **Running utilization:** (Allocated hours YTD) / (Capacity YTD) × 100% - **Overall utilization:** (Allocated hours this month) / (Capacity this month) × 100% - **Variance:** Actual hours - Allocated hours (per project, per person) **Outputs:** - Actuals vs Planned comparison - Utilization metrics (running, overall) - Variance reports (where did we over/under-deliver?) **Validation Rules:** - Cannot log negative hours - Cannot log hours for future months - Cannot log hours after project status = "Done" (configurable) --- ### 5. Reports & Analytics **Core Reports:** | Report | Description | Filters | |--------|-------------|---------| | **Forecast Summary** | Multi-period forecast of allocations and revenue | Date range, team, project, status | | **Utilization Summary** | Team and individual utilization trends | Date range, team member, role | | **Cost Summary** | Revenue forecasts based on allocations × hourly rates | Date range, project, client | | **Allocation Report** | Who's allocated to what, month-by-month | Month, team, project | | **Variance Report** | Planned vs Actual analysis | Date range, project, person | **Report Features:** - **Highly customizable filters** (team, person, project, status, date range, type) - **Export capabilities:** Defer to Phase 2 (PDF/CSV) - **Caching:** Redis caching for expensive queries --- ### 6. Role-Based Access Control (RBAC) **Personas & Permissions:** | Persona | Access Rights | Restrictions | |---------|---------------|--------------| | **Superuser** | Full access: setup, config, all projects, all teams | None | | **Manager** | • Create/edit projects
• Allocate resources to own team
• View all projects (read-only for other teams)
• Approve estimates
• View team's utilization reports | • Cannot allocate other teams' members
• Cannot edit other managers' projects | | **Developer** | • View own allocations
• Log own hours (actuals)
• View project details for assigned projects | • Cannot allocate resources
• Cannot change estimates
• Cannot view other developers' allocations | | **Top Brass** | • View all reports (read-only)
• Forecast summaries
• Utilization dashboards
• Cost summaries | • Cannot modify anything
• Read-only access only | **Access Control Implementation:** - Laravel Policies for model-level authorization - Middleware for route-level guards - JWT tokens with role claims --- ## Data Validation Rules **These rules drive API validation, tests, and verification:** ### Team Members - Name: Required, max 255 chars - Role/Team: Required, must exist in master data - Hourly rate: Required, > 0, numeric (2 decimal places) - Availability: Must be 0, 0.5, or 1.0 ### Projects - Project ID: Unique, required - Title: Required, max 255 chars - Type: Must be "Project" or "Support" - Status: Must be valid state (see state machine) - Approved estimate: Required if status ≥ "Estimate Approved", > 0 - Forecasted effort: Sum must equal approved estimate (±5% tolerance) ### Allocations - Person ID: Must exist in team members - Project ID: Must exist in projects - Hours: >= 0, numeric (2 decimal places) - Month: Valid date (YYYY-MM format) - Sum of allocations per project ≤ approved estimate + 5% - Sum of allocations per person ≤ capacity + 20% (warning threshold) ### Actuals - Person ID: Must exist in team members - Project ID: Must exist in projects - Hours: >= 0, numeric (2 decimal places) - Month: Must be current or past month (cannot log future hours) - Cannot log hours if project status = "Cancelled" or "Done" (configurable) ### Holidays/PTO - Date: Valid date - Type: "Holiday" or "PTO" - If PTO: must be associated with a team member --- ## Technical Stack ### Backend (Laravel API) | Component | Technology | Rationale | |-----------|------------|-----------| | Framework | Laravel 12 (latest) | Robust PHP framework, rich ecosystem | | Database | PostgreSQL | Production-grade, ACID compliant, great for reporting | | Caching | Redis | Query + response caching from day 1 | | Authentication | JWT (tymon/jwt-auth) | Token-based, suitable for SPA frontend | | API Design | REST + Laravel API Resources | Standard, well-understood, consistent JSON | | API Docs | Laravel Scribe (SwaggerUI) | Auto-generated from code comments | | Testing | PHPUnit (unit) + Pest (feature) | Laravel standard | | Code Style | PSR-12, Laravel conventions | Industry standard | | Containerization | Docker (port 3000) | Isolated, reproducible | | Environment | .env files | Simple configuration management | ### Frontend (SvelteKit) | Component | Technology | Rationale | |-----------|------------|-----------| | Framework | SvelteKit | Modern, reactive, great for dashboards | | Styling | Tailwind CSS + DaisyUI | Fast development, consistent theming | | Charts | Recharts | Good balance of power and simplicity | | Tables | TanStack Table (React Table) | Industry standard, powerful filtering/sorting | | Forms | Superforms + Zod | Type-safe validation, seamless SvelteKit integration | | Form Actions | SvelteKit native | Server-side form handling | | State Management | Svelte stores (minimal) | UI state only (filters, modals) | | HTTP Client | fetch (native) | No extra dependencies | | Testing | Vitest (unit) + Playwright (E2E) | Fast, modern testing tools | | Containerization | Docker (port 5173) | Isolated, hot-reload for dev | ### Infrastructure & Deployment | Component | Technology | Rationale | |-----------|------------|-----------| | Local Dev | Docker Compose | Code-mounted volumes, hot reload | | Reverse Proxy | Nginx Proxy Manager (existing) | Already running in environment | | Database Volume | Mounted directory | Portability, easy backup | | Secrets | .env files (all environments) | Simple, consistent across envs | | Background Jobs | Laravel Queue + Redis (Phase 2) | Deferred for MVP, easy to add | --- ## Quality Standards & Testing Strategy ### Test Requirements (Per Change) **Every OpenSpec change must include:** 1. **Unit tests** (backend + frontend) - Coverage target: >70% - PHPUnit (Laravel), Vitest (SvelteKit) 2. **E2E tests** (Playwright) - Happy path + critical error cases 3. **Regression tests** - Run full test suite on each change ### Code Review Checklist Before merge, verify: - **Style:** PSR-12 (PHP), Prettier (JS), ESLint (SvelteKit) - **Standards:** Laravel conventions, SvelteKit best practices - **Security:** Input validation, SQL injection prevention, XSS protection, CSRF tokens - **Tests:** All tests passing, coverage >70% ### Verification Workflow **`/opsx-verify` must check:** - All tests passing - Code coverage >70% - No uncovered code (files without tests) - API docs up-to-date (Scribe generation) - No linting errors ### Commit Standards - **Granular commits:** One fix = one commit - **Commit message format:** ``` [Type] Brief description (50 chars max) Detailed explanation (optional, 72 char wrap) Refs: #issue-number (if applicable) ``` Types: `feat`, `fix`, `refactor`, `test`, `docs`, `chore` ### Issue-Driven Test Loop (Phase 2) For E2E/integration failures: 1. Test fails → Create GitHub issue 2. Fix implementation 3. Retest + regression test 4. Close issue when all tests pass **For MVP:** Run tests, fix inline (no issue creation yet). --- ## Deferred Features (Phase 2+) ### Deferred to Phase 2 | Feature | Rationale for Deferral | Estimated Lift | |---------|------------------------|----------------| | **Notifications** (WebSocket) | Allocations are monthly - not time-critical. Users can refresh. | ~6 hours | | **PDF/CSV Exports** | On-screen reports sufficient for MVP. Easy to add later. | ~4 hours | | **Background Jobs** (async) | No heavy processing in MVP. Laravel Queue ready when needed. | ~2 hours | | **Audit Logging** | No compliance requirement for MVP. | ~3 hours | | **Advanced Caching** (pre-calculated reports) | Start with on-demand queries. Cache if slow. | ~4 hours | | **API Versioning** (`/api/v1/`) | Not needed until breaking changes. | ~2 hours | | **Multi-language Support** | English-only for MVP. | ~8 hours | | **Resource Over-allocation (advanced)** | MVP shows RED flag. Phase 2: predictive warnings, auto-balancing. | ~6 hours | ### Explicitly Out of Scope | Feature | Why Not Included | |---------|------------------| | **Time-tracking tool integration** | Manual entry sufficient. Integration adds vendor lock-in. | | **Mobile app** | Desktop web app is primary use case. | | **Invoicing integration** | Billing forecasts only. Actual invoicing is external. | | **Project task management** | Project-level tracking only, not task-level. | | **Calendar sync** (Google, Outlook) | Manual PTO/holiday entry is acceptable. | | **AI-powered forecasting** | Rule-based validation is sufficient for MVP. | --- ## Considerations & Trade-offs ### Decision Log | Decision | Option Chosen | Alternative Considered | Rationale | |----------|---------------|------------------------|-----------| | **Multi-tenancy** | Single-tenant MVP, add `tenant_id` later | Multi-tenant from day 1 | Reduces complexity, easy to add later | | **Frontend framework** | SvelteKit | Laravel + Vue, React | Modern, reactive, great for dashboards | | **Authentication** | JWT | Session-based | Suitable for SPA, easier mobile support later | | **Caching** | Redis from day 1 | Add later if needed | Prevents refactoring technical debt | | **Notifications** | Defer to Phase 2 | WebSocket PoC in MVP | Not time-critical, saves 6 hours | | **Exports** | Defer to Phase 2 | Include in MVP | On-screen reports sufficient initially | | **Issue-driven tests** | Phase 2 | From day 1 | Slower velocity for MVP, add when more tests exist | | **API versioning** | Not included | `/api/v1/` from start | No breaking changes expected in MVP | ### Known Limitations (MVP) 1. **No real-time updates:** Users must refresh to see allocation changes 2. **Manual time entry:** No automated time-tracking integration 3. **Single organization:** No multi-tenancy support 4. **English only:** No i18n support 5. **No mobile optimization:** Desktop-first design --- ## Success Metrics ### MVP Success Criteria **Functional Completeness:** - ✅ Users can define team capacity (members, holidays, PTO, availability) - ✅ Users can create projects with approved estimates - ✅ Users can allocate resources to projects month-by-month - ✅ Users can log actual hours worked - ✅ System validates allocations (over/under warnings) - ✅ Users can view 5 core reports (forecast, utilization, cost, allocation, variance) - ✅ RBAC enforced (4 personas: Superuser, Manager, Dev, Top Brass) **Quality Metrics:** - ✅ All tests passing (unit + E2E) - ✅ Code coverage >70% - ✅ Zero linting errors - ✅ API documentation auto-generated (SwaggerUI) - ✅ Docker Compose setup working (local dev) **Usability Metrics (Post-Launch):** - Manager can complete monthly allocation in <30 minutes (vs 2+ hours in spreadsheet) - Zero billing errors in first 3 months (over/under allocation caught before invoicing) - 90% of team members log actuals weekly (adoption metric) ### Phase 2 Success Criteria - ✅ Real-time notifications working (WebSocket) - ✅ PDF/CSV exports available for all reports - ✅ Background jobs processing heavy reports - ✅ Audit logging capturing all changes --- ## Timeline & Phases ### MVP (Phase 1) - Core Functionality **Target:** 6-8 weeks **Sprints:** 1. **Project setup** (1 week) - Docker Compose setup - Laravel + SvelteKit scaffolding - Database schema design - Authentication (JWT) 2. **Capacity planning** (1.5 weeks) - Team member CRUD - Holiday/PTO calendar - Availability tracking - Capacity calculations 3. **Project management** (1.5 weeks) - Project CRUD - Status state machine - Approved estimate tracking - Forecasted effort 4. **Resource allocation** (2 weeks) - Allocation matrix UI - Validation rules - Over/under indicators - Untracked resource bucket 5. **Actuals & reporting** (2 weeks) - Time logging interface - Utilization calculations - 5 core reports - Filters & customization 6. **Testing & polish** (1 week) - E2E test coverage - Code review - Bug fixes - Documentation ### Phase 2 - Enhancements **Target:** 3-4 weeks (post-MVP) - Notifications (WebSocket) - Exports (PDF/CSV) - Background jobs - Audit logging - Advanced caching - Bug fixes from production use ### Phase 3 - Scale & Optimize **Target:** TBD (based on usage) - Multi-tenancy - Mobile optimization - AI-powered forecasting - Integration APIs (time-tracking, accounting) --- ## Appendix: Master Data & Taxonomy **Configurable Lists (Admin-managed):** 1. **Roles/Teams:** - Frontend Developer - Backend Developer - QA Engineer - DevOps Engineer - UX Designer - Project Manager - Architect 2. **Project Statuses:** - NA/Support - Initial - Gathering Estimates - Estimate Pending Approval - Estimate Rework - Estimate Approved - Funded - Scheduled - In-Progress - Ready for Prod - Done - On-Hold - Cancelled 3. **Project Types:** - Project (billable) - Support (ongoing ops) 4. **Availability Options:** - 0 (unavailable/PTO) - 0.5 (half day) - 1.0 (full day) 5. **Report Filters:** - Date range (from/to) - Team member - Role/Team - Project - Project status - Project type --- **Document Control:** - **Owner:** Santhosh J - **Approver:** Santhosh J - **Next Review:** Post-MVP completion - **Change History:** - v1.0 (2026-02-17): Initial charter approved --- *End of Project Charter*