Files
stack/docs/scratchpads/358-credential-frontend.md
Jason Woltje 6521cba735
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
feat: add flexible docker-compose architecture with profiles
- Add OpenBao services to docker-compose.yml with profiles (openbao, full)
- Add docker-compose.build.yml for local builds vs registry pulls
- Make PostgreSQL and Valkey optional via profiles (database, cache)
- Create example compose files for common deployment scenarios:
  - docker/docker-compose.example.turnkey.yml (all bundled)
  - docker/docker-compose.example.external.yml (all external)
  - docker/docker.example.hybrid.yml (mixed deployment)
- Update documentation:
  - Enhance .env.example with profiles and external service examples
  - Update README.md with deployment mode quick starts
  - Add deployment scenarios to docs/OPENBAO.md
  - Create docker/DOCKER-COMPOSE-GUIDE.md with comprehensive guide
- Clean up repository structure:
  - Move shell scripts to scripts/ directory
  - Move documentation to docs/ directory
  - Move docker compose examples to docker/ directory
- Configure for external Authentik with internal services:
  - Comment out Authentik services (using external OIDC)
  - Comment out unused volumes for disabled services
  - Keep postgres, valkey, openbao as internal services

This provides a flexible deployment architecture supporting turnkey,
production (all external), and hybrid configurations via Docker Compose
profiles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 16:55:33 -06:00

181 lines
5.9 KiB
Markdown

# Issue #358: Build frontend credential management pages
## Objective
Create frontend credential management pages at `/settings/credentials` with full CRUD operations, following PDA-friendly design principles and existing UI patterns.
## Backend API Reference
- `POST /api/credentials` - Create (encrypt + store)
- `GET /api/credentials` - List (masked values only)
- `GET /api/credentials/:id` - Get single (masked)
- `GET /api/credentials/:id/value` - Decrypt and return value (rate-limited)
- `PATCH /api/credentials/:id` - Update metadata only
- `POST /api/credentials/:id/rotate` - Replace value
- `DELETE /api/credentials/:id` - Soft delete
## Approach
### 1. Component Architecture
```
/app/(authenticated)/settings/credentials/
└── page.tsx (main list + modal orchestration)
/components/credentials/
├── CredentialList.tsx (card grid)
├── CredentialCard.tsx (individual credential display)
├── CreateCredentialDialog.tsx (create form)
├── EditCredentialDialog.tsx (metadata edit)
├── ViewCredentialDialog.tsx (reveal value)
├── RotateCredentialDialog.tsx (rotate value)
└── DeleteCredentialDialog.tsx (confirm deletion)
/lib/api/
└── credentials.ts (API client functions)
```
### 2. UI Patterns (from existing code)
- Use shadcn/ui components: `Card`, `Button`, `Badge`, `AlertDialog`
- Follow personalities page pattern for list/modal state management
- Use lucide-react icons: `Plus`, `Eye`, `EyeOff`, `Pencil`, `RotateCw`, `Trash2`
- Mobile-first responsive design
### 3. Security Requirements
- **NEVER display plaintext in list** - only `maskedValue`
- **Reveal button** requires explicit click
- **Auto-hide revealed value** after 30 seconds
- **Warn user** before revealing (security-conscious UX)
- Show rate-limit warnings (10 requests/minute)
### 4. PDA-Friendly Language
```
❌ NEVER ✅ ALWAYS
─────────────────────────────────────────
"Delete credential" "Remove credential"
"EXPIRED" "Past target date"
"CRITICAL" "High priority"
"You must rotate" "Consider rotating"
```
## Progress
- [x] Read issue details and design doc
- [x] Study existing patterns (personalities page)
- [x] Identify available UI components
- [x] Create API client functions (`lib/api/credentials.ts`)
- [x] Create dialog component (`components/ui/dialog.tsx`)
- [x] Create credential components
- [x] CreateCredentialDialog.tsx
- [x] ViewCredentialDialog.tsx (with reveal + auto-hide)
- [x] EditCredentialDialog.tsx
- [x] RotateCredentialDialog.tsx
- [x] CredentialCard.tsx
- [x] Create settings page (`app/(authenticated)/settings/credentials/page.tsx`)
- [x] TypeScript typecheck passes
- [x] Build passes
- [ ] Add navigation link to settings
- [ ] Manual testing
- [ ] Verify PDA language compliance
- [ ] Mobile responsiveness check
## Implementation Notes
### Missing UI Components
- Need to add `dialog.tsx` from shadcn/ui
- Have: `alert-dialog`, `card`, `button`, `badge`, `input`, `label`, `textarea`
### Provider Icons
Support providers: GitHub, GitLab, OpenAI, Bitbucket, Custom
- Use lucide-react icons or provider-specific SVGs
- Fallback to generic `Key` icon
### State Management
Follow personalities page pattern:
```typescript
const [mode, setMode] = useState<"list" | "create" | "edit" | "view" | "rotate">("list");
const [selectedCredential, setSelectedCredential] = useState<Credential | null>(null);
```
## Testing
- [ ] Create credential flow
- [ ] Edit metadata (name, description)
- [ ] Reveal value (with auto-hide)
- [ ] Rotate credential
- [ ] Delete credential
- [ ] Error handling (validation, API errors)
- [ ] Rate limiting on reveal
- [ ] Empty state display
- [ ] Mobile layout
## Notes
- Backend API complete (commit 46d0a06)
- RLS enforced - users only see own credentials
- Activity logging automatic on backend
- Custom UI components (no Radix UI dependencies)
- Dialog component created matching existing alert-dialog pattern
- Navigation: Direct URL access at `/settings/credentials` (no nav link added - settings accessed directly)
- Workspace ID: Currently hardcoded as placeholder - needs context integration
## Files Created
```
apps/web/src/
├── components/
│ ├── ui/
│ │ └── dialog.tsx (new custom dialog component)
│ └── credentials/
│ ├── index.ts
│ ├── CreateCredentialDialog.tsx
│ ├── ViewCredentialDialog.tsx
│ ├── EditCredentialDialog.tsx
│ ├── RotateCredentialDialog.tsx
│ └── CredentialCard.tsx
├── lib/api/
│ └── credentials.ts (API client with PDA-friendly helpers)
└── app/(authenticated)/settings/credentials/
└── page.tsx (main credentials management page)
```
## PDA Language Verification
✅ All dialogs use PDA-friendly language:
- "Remove credential" instead of "Delete"
- "Past target date" instead of "EXPIRED"
- "Approaching target" instead of "URGENT"
- "Consider rotating" instead of "MUST rotate"
- Warning messages use informative tone, not demanding
## Security Features Implemented
✅ Masked values only in list view
✅ Reveal requires explicit user action (with warning)
✅ Auto-hide revealed value after 30 seconds
✅ Copy-to-clipboard for revealed values
✅ Manual hide button for revealed values
✅ Rate limit warning on reveal errors
✅ Password input fields for sensitive values
✅ Security warnings before revealing
## Next Steps for Production
- [ ] Integrate workspace context (remove hardcoded workspace ID)
- [ ] Add settings navigation menu or dropdown
- [ ] Test with real OpenBao backend
- [ ] Add loading states for API calls
- [ ] Add optimistic updates for better UX
- [ ] Add filtering/search for large credential lists
- [ ] Add pagination for credential list
- [ ] Write component tests