headplane/DEBUGGING_ANALYSIS_REPORT.md
Ryan Malloy 7c21720519
Some checks are pending
Build / native (push) Waiting to run
Build / nix (push) Waiting to run
Complete the Astro rewrite
Drop the entire app/ Remix tree (144 deletions) and replace with the
Astro + Alpine.js architecture under src/. The Remix entrypoint, routes,
components, layouts, server bindings, and types are all gone; the Astro
pages (acls, dns, machines, settings, terminal, users, login, index)
plus their API endpoints under src/pages/api/ now own the surface.

Other surfaces touched:
- package.json: drop react-router, react-router-hono-server, remix-utils
  and the rest of the Remix stack; pull in Astro + integrations + Alpine
- pnpm-lock.yaml: regenerated against the new dependency set
- astro.config.mjs added; vite.config.ts, react-router.config.ts dropped
- New src/lib/auth/ (oidc-client, role-mapper, session-manager) and
  src/lib/config/authentik.ts for env-driven config
- biome.json: enable VCS-aware filtering, exclude .astro/dist/data/
  upstream/ and the React Router backup
- Extensive docs (HEADY_MANIFESTO, AUTHENTIK_*, BETTER_ROLE_MAPPING* etc.)
  and example role-mapping yamls added under examples/
- New remote-access/ tree for the Guacamole-Lite integration
- terminal.astro: prerender disabled (data is request-time only)

Committed with --no-verify; biome auto-fix was applied first but there
are still lint warnings in the new code worth a separate cleanup pass.
The legacy app/ tree was never re-pushed after the rewrite, which is
why the Gitea/Docker builds were trying to compile app/routes/ssh/
console.tsx.
2026-06-06 13:05:35 -06:00

363 lines
12 KiB
Markdown

# Headplane Debugging Analysis Report
## Executive Summary
This report provides a systematic debugging analysis of identified bug-related issues in Headplane, a web UI for Headscale. The analysis covers authentication, permissions, configuration management, and UI interaction bugs using root cause analysis methodologies.
## Methodology
This analysis employs:
- **Root Cause Analysis**: 5 Whys methodology and causal chain analysis
- **Pattern Recognition**: Identifying common themes across bugs
- **System Architecture Analysis**: Understanding component interactions
- **Code Flow Analysis**: Tracing execution paths for bug reproduction
---
## Critical Bug Analysis
### 1. Issue #310: NixOS Module OIDC Configuration Bug
**Category**: Configuration Management / Authentication
**Impact**: High - Prevents OIDC authentication setup in NixOS deployments
#### Root Cause Analysis
**Problem**: NixOS module doesn't properly handle OIDC configuration validation and data directory creation.
**Evidence from Code**:
- `/home/rpm/claude/headplane/nix/module.nix` - Missing data directory creation logic
- Configuration schema validation issues in `/home/rpm/claude/headplane/app/server/config/schema.ts`
- OIDC client creation in `/home/rpm/claude/headplane/app/server/web/oidc.ts` has strict validation
**Causal Chain**:
1. User configures OIDC in NixOS module
2. Module generates config but doesn't ensure required directories exist
3. Headplane service starts but can't write OIDC user storage file
4. Authentication fails silently or with permission errors
5. User sees "no permissions" behavior
**5 Whys Analysis**:
- **Why does OIDC fail?** → Data directory doesn't exist or has wrong permissions
- **Why doesn't the directory exist?** → NixOS module doesn't create it
- **Why doesn't the module create it?** → Missing directory creation logic in systemd service
- **Why is this missing?** → Module focuses on service definition, not data directory management
- **Why wasn't this caught?** → Testing likely done with manual directory creation
#### Reproduction Steps
1. Configure NixOS module with OIDC settings
2. Deploy without manual data directory creation
3. Attempt OIDC login
4. Observe authentication failure
#### Fix Strategy
- Add `StateDirectory` and `StateDirectoryMode` to systemd service configuration
- Ensure proper ownership assignment in NixOS module
- Add validation for required directories in startup process
---
### 2. Issue #299: No Permissions with OIDC Login
**Category**: Authentication / Authorization
**Impact**: High - Users can authenticate but have no access rights
#### Root Cause Analysis
**Problem**: OIDC users are created without proper role assignment, defaulting to 'member' role with zero capabilities.
**Evidence from Code**:
- `/home/rpm/claude/headplane/app/server/web/roles.ts` shows 'member' role has 0 capabilities
- `/home/rpm/claude/headplane/app/routes/auth/oidc-callback.ts` doesn't assign roles during user creation
- No automatic role elevation logic for first-time OIDC users
**Causal Chain**:
1. User authenticates via OIDC successfully
2. User object created with default 'member' role
3. Member role has 0 capabilities (line 126 in roles.ts)
4. User session established but UI access blocked
5. User sees blank/restricted interface
**5 Whys Analysis**:
- **Why do users have no permissions?** → They get 'member' role with 0 capabilities
- **Why do they get member role?** → Default assignment without admin intervention
- **Why no automatic elevation?** → No first-user admin logic implemented
- **Why isn't this documented?** → OIDC configuration docs don't mention role management
- **Why no UI feedback?** → No clear permission denied messages
#### Fix Strategy
- Implement first-user-admin logic for OIDC deployments
- Add role management UI for OIDC administrators
- Improve error messaging for permission denied scenarios
- Document role assignment process
---
### 3. Issue #278: NixOS Module - Create dataDir Automatically
**Category**: Configuration Management / File System
**Impact**: Medium - Deployment friction and manual intervention required
#### Root Cause Analysis
**Problem**: Services expect data directories to exist but NixOS module doesn't create them.
**Evidence from Code**:
- Default paths in config schema expect `/var/lib/headplane/` directories
- NixOS module runs services as headscale user but doesn't ensure directory ownership
- No `StateDirectory` directive in systemd service configuration
**Architectural Issue**: Mismatch between application expectations and deployment automation.
#### Fix Strategy
- Add `StateDirectory = "headplane"` to systemd service
- Ensure proper user/group ownership
- Add validation checks in application startup
---
### 4. Issue #266: Automated Ownership Permissions Rework
**Category**: System Security / File Permissions
**Impact**: Medium - Security and operational issues
#### Root Cause Analysis
**Problem**: Inconsistent file ownership and permission handling across different deployment methods.
**Evidence from Code**:
- Services run as headscale user but may create files as different users
- No systematic permission validation at startup
- Integration modules (Docker, Kubernetes, proc) have different permission requirements
#### Fix Strategy
- Implement startup permission validation
- Standardize file ownership patterns
- Add permission repair functionality
---
## Code-Level Bug Analysis
### 1. Menu onAction Called Twice (app/components/Menu.tsx:27)
**Category**: UI/UX Bug
**Impact**: Low-Medium - Potential double execution of actions
#### Root Cause Analysis
**Problem**: React event handling in Menu component triggers action callbacks multiple times.
**Evidence from Code**:
```typescript
// Line 27: TODO: onAction is called twice for some reason?
```
**Likely Causes**:
- Event bubbling in nested React components
- useMenuTrigger and useMenuItem both handling same events
- cloneElement pattern may be duplicating event handlers
**Debugging Strategy**:
1. Add console.log to track event propagation
2. Use React DevTools to inspect event handlers
3. Check if useMenuTrigger and useMenuItem have conflicting event handling
#### Fix Strategy
- Add `event.stopPropagation()` in appropriate handlers
- Consolidate event handling logic
- Add unit tests for action execution count
---
### 2. API Generation Issues (app/routes/auth/oidc-callback.ts:49)
**Category**: Authentication / API Management
**Impact**: High - API key proliferation and database bloat
#### Root Cause Analysis
**Problem**: OIDC authentication generates new API keys without cleanup, causing database accumulation.
**Evidence from Code**:
```typescript
// TODO: This is breaking, to stop the "over-generation" of API
// keys because they are currently non-deletable in the headscale
// database. Look at this in the future once we have a solution
```
**Architectural Issue**: Headscale API key management limitations combined with session management needs.
#### Fix Strategy
- Implement API key reuse for existing users
- Add key rotation/cleanup strategy
- Investigate Headscale API key deletion capabilities
---
### 3. Headscale API Problems (app/routes/auth/login/action.ts:86)
**Category**: API Integration / Error Handling
**Impact**: Medium - Poor error handling and debugging difficulty
#### Root Cause Analysis
**Problem**: Inconsistent and unclear error responses from Headscale API.
**Evidence from Code**:
```typescript
// TODO: What in gods name is wrong with the headscale API?
if (error.status === 401 || error.status === 403 ||
(error.status === 500 && error.response.trim() === 'Unauthorized'))
```
**Issue**: Headscale returns HTTP 500 with "Unauthorized" text instead of proper 401/403 codes.
#### Fix Strategy
- Normalize error handling across all Headscale API interactions
- Add retry logic for transient failures
- Improve error logging and user feedback
---
## Cross-Cutting Issues and Patterns
### 1. Configuration Validation Gaps
**Pattern**: Inconsistent validation between schema definition and runtime validation.
**Evidence**:
- Strong schema validation in `app/server/config/schema.ts`
- Runtime failures due to missing directories/permissions
- NixOS module doesn't validate generated configurations
**Impact**: Silent failures and difficult debugging
### 2. Error Handling Inconsistencies
**Pattern**: Mixed error handling strategies across the codebase.
**Evidence**:
- Some components use try/catch with detailed logging
- Others use simple error returns
- Inconsistent user-facing error messages
### 3. Integration Permission Complexity
**Pattern**: Different deployment methods (Docker, Kubernetes, NixOS, proc) have varying permission requirements.
**Evidence**:
- Each integration has different systemd/container security contexts
- No unified permission validation strategy
- Manual intervention often required
---
## Testing and Quality Assurance Gaps
### 1. Integration Testing Deficiencies
**Missing Coverage**:
- End-to-end OIDC authentication flows
- NixOS module deployment scenarios
- Permission boundary validation
- API key lifecycle management
### 2. Error Condition Testing
**Missing Scenarios**:
- Missing directory permissions on startup
- Malformed OIDC responses
- Headscale API downtime/errors
- Role assignment edge cases
---
## Risk Assessment
### High Risk Issues
1. **OIDC Authentication Failures** - Blocks user access entirely
2. **Permission Escalation Gaps** - Users stuck with no permissions
3. **API Key Proliferation** - Database performance degradation
### Medium Risk Issues
1. **Configuration Deployment Friction** - Increases support burden
2. **Error Handling Inconsistencies** - Poor debugging experience
3. **UI Action Reliability** - User experience degradation
### Low Risk Issues
1. **TODO Comments** - Technical debt accumulation
2. **Logging Inconsistencies** - Debugging difficulty
---
## Recommended Debugging Strategies
### 1. Systematic OIDC Flow Testing
**Approach**:
- Create minimal reproducible environment for OIDC testing
- Implement comprehensive logging at each authentication step
- Add health check endpoints for OIDC configuration validation
**Tools**:
- Add OIDC flow tracing middleware
- Implement configuration validation API endpoints
- Create automated integration tests
### 2. Permission System Audit
**Approach**:
- Audit all permission checks across the application
- Implement permission debugging UI for administrators
- Add startup permission validation with clear error reporting
### 3. Error Handling Standardization
**Approach**:
- Create unified error handling middleware
- Implement structured error logging
- Add user-friendly error message system
---
## Prevention Strategies
### 1. Development Process Improvements
- **Pre-commit Hooks**: Add validation for TODO comments that indicate bugs
- **Integration Testing**: Mandatory OIDC and permission flow testing
- **Documentation**: Update deployment guides with troubleshooting sections
### 2. Monitoring and Observability
- **Health Checks**: Add comprehensive application health endpoints
- **Metrics**: Track authentication success/failure rates
- **Alerts**: Monitor API key creation patterns and permission errors
### 3. Configuration Management
- **Validation**: Add runtime configuration validation with clear error messages
- **Migration**: Implement configuration migration and validation tools
- **Documentation**: Provide troubleshooting guides for common deployment issues
---
## Conclusion
The analyzed bugs primarily stem from:
1. **Configuration and deployment complexity** across different platforms
2. **Authentication and authorization system gaps** particularly around OIDC
3. **Error handling inconsistencies** that make debugging difficult
4. **Integration testing gaps** that allow regressions
The recommended approach focuses on systematic testing, improved error handling, and better deployment automation to prevent these classes of issues from recurring.
**Priority Fix Order**:
1. OIDC permission assignment (Issue #299)
2. NixOS data directory creation (Issue #278, #310)
3. API key lifecycle management (oidc-callback.ts:49)
4. Error handling standardization (login/action.ts:86)
5. UI event handling (Menu.tsx:27)
This systematic approach will improve both user experience and maintainability while reducing the support burden for common deployment issues.