headplane/TESTING_PLAN.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

239 lines
7.0 KiB
Markdown

# OIDC Improvements Testing Plan
## Testing Philosophy
Our improvements follow "convention over configuration" - we need tests that verify:
1. **Smart defaults work automatically** (zero config scenarios)
2. **Explicit configuration overrides defaults** (progressive enhancement)
3. **Error cases provide helpful guidance** (user-friendly failures)
4. **Edge cases are handled gracefully** (production resilience)
## Test Priority Matrix
### 🔴 HIGH PRIORITY (Must Have)
These tests cover the core functionality users will depend on daily.
#### 1. Group Discovery (`app/utils/oidc.ts`)
```typescript
describe('Smart Group Discovery', () => {
test('finds groups in userInfo.groups (priority 1)')
test('falls back to claims.groups when userInfo missing')
test('handles Keycloak resource_access.headplane.roles')
test('handles Azure cognito:groups')
test('handles nested paths correctly')
test('filters out non-string values')
test('returns empty array when no groups found')
test('handles malformed/null data gracefully')
})
```
#### 2. Role Mapping (`app/server/web/roles.ts`)
```typescript
describe('Environment-First Role Mapping', () => {
test('uses environment variables when configured')
test('falls back to convention-based mapping')
test('respects role hierarchy (owner > admin > etc.)')
test('handles case-insensitive group matching')
test('returns member for unrecognized groups')
test('handles empty/null groups array')
})
describe('Convention-Based Role Assignment', () => {
test('ceo/cto/founder → owner')
test('admin/administrator → admin')
test('devops/sre/network → network_admin')
test('helpdesk/support → it_admin')
test('audit/compliance → auditor')
test('random-group → member')
test('multiple groups picks highest privilege')
})
```
#### 3. Configuration Enhancement (`app/server/config/oidc-enhancer.ts`)
```typescript
describe('Configuration Self-Healing', () => {
test('auto-adds groups scope when missing')
test('detects optimal scope for known providers')
test('generates redirect_uri from environment')
test('provides provider-specific insights')
test('validates configuration correctly')
test('handles unknown providers gracefully')
})
```
### 🟡 MEDIUM PRIORITY (Should Have)
These tests cover important edge cases and integration scenarios.
#### 4. Environment Variable Parsing
```typescript
describe('Environment Variable Role Mapping', () => {
test('parses comma-separated group lists')
test('handles whitespace in group names')
test('ignores empty environment variables')
test('overrides work correctly')
})
```
#### 5. Error Handling Enhancement
```typescript
describe('Enhanced Error Messages', () => {
test('provides helpful suggestions for invalid_grant')
test('guides users on scope configuration issues')
test('logs authentication success with details')
test('suggests environment variables for missing groups')
})
```
### 🟢 LOW PRIORITY (Nice to Have)
These tests cover advanced scenarios and comprehensive edge cases.
#### 6. Provider-Specific Optimizations
```typescript
describe('Provider Detection', () => {
test('detects Google Workspace correctly')
test('detects Azure AD correctly')
test('detects Keycloak correctly')
test('provides appropriate scope for each')
test('gives relevant setup tips')
})
```
#### 7. Integration Scenarios
```typescript
describe('Full Authentication Flow', () => {
test('complete authentication with role assignment')
test('database storage of groups and capabilities')
test('first user becomes owner regardless of groups')
test('subsequent users follow role mapping')
})
```
## Test Implementation Strategy
### Phase 1: Core Unit Tests (Required for PR)
Focus on the business logic that users depend on:
1. Group discovery with all fallback paths
2. Role mapping with environment variables and conventions
3. Configuration enhancement and validation
### Phase 2: Integration Tests (Follow-up PR)
Focus on the full user experience:
1. End-to-end authentication flow
2. Database integration with role assignment
3. Real provider configuration testing
### Phase 3: Comprehensive Coverage (Future Enhancement)
Focus on edge cases and advanced scenarios:
1. Provider-specific testing with real examples
2. Performance testing with large group lists
3. Security testing for malicious input
## Mock Data Strategy
### Realistic Test Data
Use actual examples from popular identity providers:
```typescript
// Google Workspace
const googleClaims = {
iss: 'https://accounts.google.com',
email: 'alice@company.com',
// Google doesn't provide groups in standard claims
}
// Azure AD
const azureClaims = {
groups: ['IT Administrators', 'Company Employees'],
roles: ['Application.Admin']
}
// Keycloak
const keycloakClaims = {
resource_access: {
headplane: { roles: ['admin', 'developer'] }
},
realm_access: { roles: ['user'] }
}
// AWS Cognito
const cognitoClaims = {
'cognito:groups': ['admins', 'users']
}
```
### Edge Case Data
Test boundary conditions and error scenarios:
```typescript
const edgeCases = {
emptyGroups: { groups: [] },
nullGroups: { groups: null },
stringGroups: { groups: "not-an-array" },
mixedTypes: { groups: ['admin', 123, null, 'user'] },
malformedNested: { resource_access: 'not-an-object' },
deeplyNested: { a: { b: { c: { groups: ['deep-admin'] } } } }
}
```
## Success Criteria
### For Production Readiness
-**90%+ test coverage** of new OIDC functionality
-**All happy path scenarios** work correctly
-**Common error cases** provide helpful guidance
-**Edge cases** don't crash the application
### For Upstream PR
-**Core business logic** thoroughly tested
-**Environment variable integration** verified
-**Configuration enhancement** validated
-**Backward compatibility** confirmed
### For User Confidence
-**Real-world scenarios** covered with actual provider data
-**Migration scenarios** tested (existing → enhanced)
-**Deployment scenarios** verified (env vars, containers)
-**Documentation** includes testing examples
## Testing Tools & Patterns
### Test Structure
```typescript
// Arrange - Set up test data
const mockClaims = { groups: ['admin', 'users'] }
const mockUserInfo = { email: 'test@example.com' }
// Act - Execute the function
const result = extractGroups(mockClaims, mockUserInfo)
// Assert - Verify expected behavior
expect(result).toEqual(['admin', 'users'])
```
### Environment Variable Testing
```typescript
beforeEach(() => {
// Clear environment variables
delete process.env.HEADPLANE_ADMIN_GROUPS
})
afterEach(() => {
// Restore original environment
Object.assign(process.env, originalEnv)
})
```
### Provider-Specific Testing
```typescript
describe.each([
['Google', googleTestData],
['Azure', azureTestData],
['Keycloak', keycloakTestData]
])('%s Provider', (providerName, testData) => {
test('detects groups correctly', () => {
// Provider-specific test logic
})
})
```
This testing plan ensures our improvements are production-ready while maintaining the simplicity and reliability that makes them valuable.