24 KiB
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:
- Unit tests (backend + frontend)
- Coverage target: >70%
- PHPUnit (Laravel), Vitest (SvelteKit)
- E2E tests (Playwright)
- Happy path + critical error cases
- 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:
Types:
[Type] Brief description (50 chars max) Detailed explanation (optional, 72 char wrap) Refs: #issue-number (if applicable)feat,fix,refactor,test,docs,chore
Issue-Driven Test Loop (Phase 2)
For E2E/integration failures:
- Test fails → Create GitHub issue
- Fix implementation
- Retest + regression test
- 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)
- No real-time updates: Users must refresh to see allocation changes
- Manual time entry: No automated time-tracking integration
- Single organization: No multi-tenancy support
- English only: No i18n support
- 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:
-
Project setup (1 week)
- Docker Compose setup
- Laravel + SvelteKit scaffolding
- Database schema design
- Authentication (JWT)
-
Capacity planning (1.5 weeks)
- Team member CRUD
- Holiday/PTO calendar
- Availability tracking
- Capacity calculations
-
Project management (1.5 weeks)
- Project CRUD
- Status state machine
- Approved estimate tracking
- Forecasted effort
-
Resource allocation (2 weeks)
- Allocation matrix UI
- Validation rules
- Over/under indicators
- Untracked resource bucket
-
Actuals & reporting (2 weeks)
- Time logging interface
- Utilization calculations
- 5 core reports
- Filters & customization
-
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):
-
Roles/Teams:
- Frontend Developer
- Backend Developer
- QA Engineer
- DevOps Engineer
- UX Designer
- Project Manager
- Architect
-
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
-
Project Types:
- Project (billable)
- Support (ongoing ops)
-
Availability Options:
- 0 (unavailable/PTO)
- 0.5 (half day)
- 1.0 (full day)
-
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