- Extract validateAssumeRoleInput() - CRAP ~2 - Extract resolveAssumeRoleConfig() with getOrEnv() helper - CRAP ~4 * Fixes DRY violation (config resolution was repeated 3x) - Extract requestAuthToken() - CRAP ~4 (sequential, easy to test) - Extract buildAssumeRoleOutput() - CRAP ~1 - Main AssumeRoleActivity now ~CRAP 3 (orchestrates high-level flow) Overall CRAP reduction: 40+ → 6-8 total complexity Improves: - Single Responsibility: Each function does one thing - DRY: Config resolution centralized - Testability: Each step independently unit-testable - Readability: Main function reads like pseudocode
Implements AWS AssumeRole-like pattern for Poimen: - User/service requests temporary access with identity + scope - AssumeRoleActivity exchanges credentials with OAuth2 auth server - Returns JWT token valid for limited time (default: 1hr, max: 24hrs) - Token used in all subsequent LLM API calls to api.riotpiao.com Key features: - Credentials from vault/K8s secrets (never hardcoded) - Scope-based access control (llm:read, llm:read llm:write, llm:admin) - Automatic token expiration tracking - Retry support for transient auth failures (2x, 1.5s backoff) - Configurable auth server endpoint Usage pattern: 1. AssumeRoleActivity(identity, scope) → JWT token 2. LLMRouter uses token in LLMAuth config 3. All activity calls validated against token + scopes 4. Workflow optionally refreshes token before expiry Security: - No credentials in code/logs (env or vault only) - Short-lived tokens (1hr default, 24hr max) - Server-enforced scope validation - Token revocation support Activity registered: #10 (authentication category) Knowledge base updated with full activity spec New file: action/assume_role.go (5.2 KB)