docs(openspec): add OpenSpec changes for FN-005, FN-006, FN-008, FN-009, FN-010
- Add frontend-foundation change (FN-005) with 46 tasks - Add deployment-config change (FN-006) with 27 tasks - Add runfusion-poc/opencode-poc change (FN-008) with 25 tasks - Add config-secrets change (FN-009) with 31 tasks - Add codeserver-spawn change (FN-010) with 38 tasks - Include project specsheet and configuration - Archive completed deployment-config change
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-14
|
||||
@@ -0,0 +1,75 @@
|
||||
## Context
|
||||
|
||||
The frontend is currently a static scaffold (FN-002) with no routing, auth, or API integration. The backend has complete domain models, CRUD routers, and auth dependencies (FN-004, FN-011). This design bridges the gap by establishing the frontend architecture needed for all user-facing features.
|
||||
|
||||
Current frontend state:
|
||||
- Single App.tsx with static HTML
|
||||
- No routing, state management, or API client
|
||||
- No auth integration
|
||||
- Tests only verify static rendering
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Deliver a functional auth flow (login/logout via Authentik OIDC)
|
||||
- Provide a responsive dashboard shell with navigation
|
||||
- Enable project CRUD operations from the UI
|
||||
- Establish typed API client patterns
|
||||
- Set up environment-based configuration
|
||||
|
||||
**Non-Goals:**
|
||||
- Full tool spawn UI (deferred to FN-010/FN-008)
|
||||
- Config/secrets management UI (deferred to FN-009)
|
||||
- Repository connection UI (deferred to future task)
|
||||
- Real-time updates or WebSockets
|
||||
- Mobile-optimized responsive design (basic responsiveness only)
|
||||
|
||||
## Decisions
|
||||
|
||||
**1. React Router v7 for routing**
|
||||
- Rationale: Industry standard, integrates well with React 19, supports nested routes and loaders
|
||||
- Alternative: TanStack Router - more type-safe but steeper learning curve, overkill for MVP
|
||||
|
||||
**2. TanStack Query (React Query) for server state**
|
||||
- Rationale: Standard for API caching, background refetching, and optimistic updates
|
||||
- Alternative: SWR - similar but TanStack Query has better TypeScript support and devtools
|
||||
|
||||
**3. Zustand for client state**
|
||||
- Rationale: Lightweight, TypeScript-friendly, minimal boilerplate vs Redux
|
||||
- Alternative: Context API - sufficient for auth but Zustand scales better for future features
|
||||
|
||||
**4. HTTP client: fetch API with thin wrapper**
|
||||
- Rationale: No extra dependency needed, native fetch is sufficient
|
||||
- Alternative: Axios - adds bundle size, fetch handles our use cases
|
||||
|
||||
**5. Auth: OIDC Authorization Code flow with PKCE**
|
||||
- Rationale: Secure, recommended by OAuth 2.1, Authentik supports it
|
||||
- Implementation: redirect to Authentik authorize endpoint, callback handles code exchange
|
||||
|
||||
**6. Component library: Headless UI + Tailwind CSS**
|
||||
- Rationale: Unstyled primitives give full control, Tailwind is already in Vite scaffold
|
||||
- Alternative: Material UI - opinionated, harder to customize
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
**[Risk] Auth token storage in browser**
|
||||
→ Mitigation: Use httpOnly cookies (set by backend callback) or secure storage. Never localStorage. Implement CSRF protection.
|
||||
|
||||
**[Risk] OIDC library bundle size**
|
||||
→ Mitigation: Use lightweight oauth4webapi or implement PKCE manually (~2KB vs 50KB+ for oidc-client-ts)
|
||||
|
||||
**[Risk] CORS complexity between web and API**
|
||||
→ Mitigation: Configure CORS in FastAPI to allow web origin. Use same-origin deployment in production (Traefik routes both).
|
||||
|
||||
**[Risk] Test complexity with auth flows**
|
||||
→ Mitigation: Mock auth context in tests, test components in isolation. E2E tests deferred post-MVP.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
No migration needed - this is additive to the scaffold.
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. Should we use a pre-built OIDC client library or implement PKCE manually?
|
||||
2. Do we need refresh token rotation or are short-lived access tokens sufficient?
|
||||
3. Should the API client auto-retry on 401 or redirect immediately?
|
||||
@@ -0,0 +1,32 @@
|
||||
## Why
|
||||
|
||||
The backend API is fully scaffolded with domain models, routers, and authentication dependencies, but the frontend remains a static scaffold page (FN-002). Users cannot sign in, view projects, or interact with any backend functionality. This change delivers the foundational frontend architecture needed to unlock all user-facing MVP features.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Authentik OIDC integration**: Auth provider with login/logout flow, token management, and automatic user provisioning
|
||||
- **Dashboard shell**: Responsive layout with header, navigation sidebar, and main content area
|
||||
- **Navigation routes**: Dashboard, Projects, Repositories, Tools, Settings pages with React Router
|
||||
- **Typed API client**: Generated or hand-written client for all `/api/v1/*` endpoints
|
||||
- **Project list UI**: Display user's projects with create/edit capabilities
|
||||
- **Environment config layer**: Vite env var integration for API URL, auth endpoints
|
||||
- **Auth-guarded routes**: Redirect unauthenticated users to login
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `auth-oidc`: Authentik OIDC authentication flow, token storage, session management
|
||||
- `dashboard-shell`: Responsive layout with navigation, header, and content area
|
||||
- `project-management-ui`: Project list, create, edit, delete views
|
||||
- `api-client`: Typed HTTP client for backend API consumption
|
||||
- `route-guards`: Authentication-based route protection and redirects
|
||||
|
||||
### Modified Capabilities
|
||||
- None (this is purely additive to the existing scaffold)
|
||||
|
||||
## Impact
|
||||
|
||||
- **apps/web/src/**: All new frontend code
|
||||
- **apps/web/package.json**: New dependencies (react-router-dom, @tanstack/react-query, etc.)
|
||||
- **apps/api/app/auth/dependencies.py**: CORS and auth flow alignment
|
||||
- **docs/development.md**: Updated frontend development instructions
|
||||
@@ -0,0 +1,28 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: API client handles all backend endpoints
|
||||
The system SHALL provide a typed HTTP client for all backend API endpoints.
|
||||
|
||||
#### Scenario: GET request
|
||||
- **WHEN** the client calls api.get('/projects')
|
||||
- **THEN** it sends a GET request to /api/v1/projects
|
||||
- **AND** returns typed Project[] data
|
||||
- **AND** includes the Authorization header with the current access token
|
||||
|
||||
#### Scenario: POST request
|
||||
- **WHEN** the client calls api.post('/projects', data)
|
||||
- **THEN** it sends a POST request with JSON body
|
||||
- **AND** returns typed Project data
|
||||
|
||||
#### Scenario: Error handling
|
||||
- **WHEN** a request returns 4xx or 5xx
|
||||
- **THEN** the client throws an ApiError with status code and message
|
||||
- **AND** the error can be caught and displayed to the user
|
||||
|
||||
### Requirement: API client supports request/response types
|
||||
The system SHALL use TypeScript interfaces matching the backend Pydantic schemas.
|
||||
|
||||
#### Scenario: Type safety
|
||||
- **WHEN** a developer uses the API client
|
||||
- **THEN** request and response types are checked at compile time
|
||||
- **AND** mismatches produce TypeScript errors
|
||||
@@ -0,0 +1,36 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: User can authenticate via Authentik OIDC
|
||||
The system SHALL provide an authentication flow using Authentik as the OIDC provider.
|
||||
|
||||
#### Scenario: Successful login
|
||||
- **WHEN** an unauthenticated user clicks "Sign In"
|
||||
- **THEN** the system redirects to Authentik's authorization endpoint with PKCE parameters
|
||||
- **AND** after successful authentication, Authentik redirects back with an authorization code
|
||||
- **AND** the system exchanges the code for tokens
|
||||
- **AND** the user is redirected to the dashboard
|
||||
|
||||
#### Scenario: Automatic user provisioning
|
||||
- **WHEN** a user authenticates for the first time
|
||||
- **THEN** the backend creates a User record automatically
|
||||
- **AND** the user can access their projects immediately
|
||||
|
||||
#### Scenario: Logout
|
||||
- **WHEN** an authenticated user clicks "Sign Out"
|
||||
- **THEN** the system clears all session data
|
||||
- **AND** redirects to Authentik's end_session_endpoint
|
||||
- **AND** the user is redirected back to the login page
|
||||
|
||||
### Requirement: Auth state is managed globally
|
||||
The system SHALL maintain authentication state accessible throughout the application.
|
||||
|
||||
#### Scenario: Auth context available
|
||||
- **WHEN** the application loads
|
||||
- **THEN** an auth context provider wraps the component tree
|
||||
- **AND** child components can read the current auth state (loading, authenticated, unauthenticated, error)
|
||||
|
||||
#### Scenario: Token refresh
|
||||
- **WHEN** an API request returns 401 due to expired token
|
||||
- **THEN** the system attempts token refresh
|
||||
- **AND** retries the original request with the new token
|
||||
- **AND** if refresh fails, redirects to login
|
||||
@@ -0,0 +1,28 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Dashboard provides responsive layout
|
||||
The system SHALL provide a consistent layout with header, navigation, and content area.
|
||||
|
||||
#### Scenario: Layout structure
|
||||
- **WHEN** the user views any authenticated page
|
||||
- **THEN** a header displays the application name and user avatar
|
||||
- **AND** a sidebar shows navigation links (Dashboard, Projects, Repositories, Tools, Settings)
|
||||
- **AND** the main content area renders the current route's component
|
||||
|
||||
#### Scenario: Collapsible sidebar
|
||||
- **WHEN** the user is on a mobile device
|
||||
- **THEN** the sidebar is initially collapsed
|
||||
- **AND** a hamburger menu toggles the sidebar visibility
|
||||
|
||||
### Requirement: Navigation reflects auth state
|
||||
The system SHALL show/hide navigation items based on authentication status.
|
||||
|
||||
#### Scenario: Authenticated navigation
|
||||
- **WHEN** the user is authenticated
|
||||
- **THEN** all navigation links are visible
|
||||
- **AND** "Sign Out" is available in the user menu
|
||||
|
||||
#### Scenario: Unauthenticated navigation
|
||||
- **WHEN** the user is not authenticated
|
||||
- **THEN** only "Sign In" is shown
|
||||
- **AND** accessing protected routes redirects to login
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: User can view their projects
|
||||
The system SHALL display a list of projects belonging to the authenticated user.
|
||||
|
||||
#### Scenario: Project list page
|
||||
- **WHEN** the user navigates to /projects
|
||||
- **THEN** the system fetches projects from /api/v1/projects
|
||||
- **AND** displays each project with name, description, and created date
|
||||
- **AND** shows an empty state when no projects exist
|
||||
|
||||
#### Scenario: Project detail
|
||||
- **WHEN** the user clicks on a project
|
||||
- **THEN** the system navigates to /projects/:id
|
||||
- **AND** displays project details including repositories and tool instances
|
||||
|
||||
### Requirement: User can create a project
|
||||
The system SHALL allow authenticated users to create new projects.
|
||||
|
||||
#### Scenario: Create project form
|
||||
- **WHEN** the user clicks "New Project"
|
||||
- **THEN** a form appears with name and description fields
|
||||
- **AND** the name field validates for non-empty and URL-friendly slug generation
|
||||
- **AND** submitting the form POSTs to /api/v1/projects
|
||||
- **AND** on success, the user is redirected to the new project
|
||||
|
||||
### Requirement: User can edit and delete projects
|
||||
The system SHALL allow project owners to modify or remove their projects.
|
||||
|
||||
#### Scenario: Edit project
|
||||
- **WHEN** the user clicks "Edit" on a project
|
||||
- **THEN** a pre-filled form appears
|
||||
- **AND** submitting updates the project via PUT /api/v1/projects/:id
|
||||
|
||||
#### Scenario: Delete project
|
||||
- **WHEN** the user clicks "Delete" on a project
|
||||
- **THEN** a confirmation dialog appears
|
||||
- **AND** confirming sends DELETE /api/v1/projects/:id
|
||||
- **AND** the project is removed from the list
|
||||
@@ -0,0 +1,24 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Protected routes require authentication
|
||||
The system SHALL prevent unauthenticated users from accessing protected pages.
|
||||
|
||||
#### Scenario: Unauthenticated access attempt
|
||||
- **WHEN** an unauthenticated user navigates to /projects
|
||||
- **THEN** the system redirects to /login
|
||||
- **AND** stores the intended destination for post-login redirect
|
||||
|
||||
#### Scenario: Authenticated access
|
||||
- **WHEN** an authenticated user navigates to /projects
|
||||
- **THEN** the route renders normally
|
||||
|
||||
### Requirement: Public routes are accessible
|
||||
The system SHALL allow unauthenticated access to public pages.
|
||||
|
||||
#### Scenario: Login page
|
||||
- **WHEN** an unauthenticated user navigates to /login
|
||||
- **THEN** the login page renders without redirect
|
||||
|
||||
#### Scenario: Health/status pages
|
||||
- **WHEN** any user navigates to /health
|
||||
- **THEN** the page renders without authentication
|
||||
@@ -0,0 +1,72 @@
|
||||
## 1. Setup & Dependencies
|
||||
|
||||
- [x] 1.1 Install frontend dependencies: react-router-dom, @tanstack/react-query, zustand, @headlessui/react
|
||||
- [x] 1.2 Set up Tailwind CSS configuration (tailwind.config.js, postcss.config.js)
|
||||
- [x] 1.3 Create environment type definitions in apps/web/src/env.d.ts
|
||||
- [x] 1.4 Add Vite environment variables to .env.example (VITE_API_URL, VITE_OIDC_ISSUER, etc.)
|
||||
|
||||
## 2. API Client & Types
|
||||
|
||||
- [x] 2.1 Create apps/web/src/api/client.ts with typed fetch wrapper and auth header injection
|
||||
- [x] 2.2 Generate or create TypeScript interfaces matching backend schemas (Project, User, etc.)
|
||||
- [x] 2.3 Implement error handling with ApiError class
|
||||
- [x] 2.4 Add request/response logging in debug mode
|
||||
|
||||
## 3. Authentication
|
||||
|
||||
- [x] 3.1 Create apps/web/src/auth/oidc.ts with PKCE code generation and token exchange
|
||||
- [x] 3.2 Implement auth store (Zustand) with state: loading, authenticated, unauthenticated, error
|
||||
- [x] 3.3 Create AuthProvider component wrapping the app
|
||||
- [x] 3.4 Implement login redirect to Authentik authorize endpoint
|
||||
- [x] 3.5 Implement callback handler (/callback route) for code exchange
|
||||
- [x] 3.6 Implement logout with end_session_endpoint redirect
|
||||
- [x] 3.7 Add token refresh logic for expired access tokens
|
||||
|
||||
## 4. Routing & Layout
|
||||
|
||||
- [x] 4.1 Set up React Router with route definitions in apps/web/src/router.tsx
|
||||
- [x] 4.2 Create DashboardLayout component with header, sidebar, and outlet
|
||||
- [x] 4.3 Implement RouteGuard component for protected routes
|
||||
- [x] 4.4 Add public routes: /login, /callback
|
||||
- [x] 4.5 Add protected routes: /, /projects, /projects/:id, /tools, /settings
|
||||
|
||||
## 5. Dashboard Shell
|
||||
|
||||
- [x] 5.1 Create Header component with app name and user avatar dropdown
|
||||
- [x] 5.2 Create Sidebar component with navigation links
|
||||
- [x] 5.3 Implement mobile-responsive sidebar toggle
|
||||
- [x] 5.4 Add active route highlighting in sidebar
|
||||
- [x] 5.5 Create Dashboard home page with welcome content
|
||||
|
||||
## 6. Project Management UI
|
||||
|
||||
- [x] 6.1 Create ProjectList page fetching from /api/v1/projects
|
||||
- [x] 6.2 Implement ProjectCard component for list view
|
||||
- [x] 6.3 Add empty state when no projects exist
|
||||
- [x] 6.4 Create ProjectDetail page at /projects/:id
|
||||
- [x] 6.5 Implement NewProject form with validation (name, description)
|
||||
- [x] 6.6 Implement EditProject form with pre-filled data
|
||||
- [x] 6.7 Add delete confirmation dialog for projects
|
||||
- [x] 6.8 Wire up TanStack Query mutations for create/update/delete
|
||||
|
||||
## 7. Placeholder Pages
|
||||
|
||||
- [x] 7.1 Create Tools page placeholder
|
||||
- [x] 7.2 Create Settings page placeholder
|
||||
- [x] 7.3 Create Repositories page placeholder
|
||||
|
||||
## 8. Testing & Verification
|
||||
|
||||
- [x] 8.1 Write unit tests for auth store
|
||||
- [x] 8.2 Write unit tests for API client error handling
|
||||
- [x] 8.3 Write tests for RouteGuard component
|
||||
- [x] 8.4 Update App.test.tsx to test routing
|
||||
- [x] 8.5 Run `pnpm test` and fix any failures
|
||||
- [x] 8.6 Run `pnpm lint` and fix any issues
|
||||
- [x] 8.7 Run `pnpm typecheck` and fix any errors
|
||||
|
||||
## 9. Documentation
|
||||
|
||||
- [x] 9.1 Update docs/development.md with frontend auth setup instructions
|
||||
- [x] 9.2 Update README.md with new environment variables
|
||||
- [x] 9.3 Add frontend architecture notes to docs/architecture.md
|
||||
Reference in New Issue
Block a user