The workspace was using /api/projects/... but the API routes are mounted
at /projects without the /api prefix. Switched from raw fetch() to the
apiClient which already has the correct baseURL configured.
Also fixed TypeScript types and removed unused variables.
Using 'git log --all <branch>' creates ambiguous behavior. Now:
- Without branch: uses --all to show all commits from all refs
- With branch: shows only commits from that specific branch
This ensures consistent commit counts between git CLI and API.
The backend defaults to returning only 100 commits. Update frontend
to explicitly request up to 10000 commits to show full history for
most repositories.
Backend was sending Unix timestamps as strings (e.g. '1716112800')
which JavaScript Date couldn't parse. Now sends proper ISO 8601
format dates that work with new Date() in the browser.
Backend was returning fields like 'author', 'email', 'date' but frontend
expected 'author_name', 'author_email', 'author_date'. Also 'branches' and
'tags' were separate but frontend expects unified 'refs' array.
- Update _commit_to_dict to return frontend-compatible field names
- Add graph_symbol and graph_depth for commit graph display
- Update get_commit_detail to return matching field names
- Include diff as top-level field for detail view
The git log --graph output uses | characters in the ASCII art,
which conflicts with using | as a format separator. Switch to
NULL bytes (\x00) which won't appear in commit data.
Also removed --graph flag since we build graph data from
parent relationships instead.
- Add git_history.py utility for extracting commit history and details
- Add API endpoints for repository history and commit details
- Integrate with existing git_repositories router
This completes the backend for git history visualization.
- Add API client functions for commit history and detail endpoints
- Create GitHistoryPage with commit list, graph visualization, and detail panel
- Add branch selector for viewing different branches
- Integrate history view into repository list with History button
- Add comprehensive CSS styles for history page layout
Quality gates: typecheck ✓, lint ✓, build ✓
Tool types and git repositories response models declared created_at/
updated_at as str but ORM returns datetime objects. Change to datetime
type so Pydantic serializes correctly to ISO format strings.
- Create missing /dashboard/summary endpoint that frontend expects
- Fix SSH key Fernet key generation to use proper base64 encoding
(was using raw session secret slice which failed validation)
FastAPI uses parameter name as cookie name by default.
get_current_user_id was looking for 'session_cookie' but we set
the cookie as 'session'. Add alias='session' to match.
In production, the session cookie needs to be shared across
subdomains (e.g., api.example.com and app.example.com).
- Add cookie_domain property to config (extracts parent domain)
- Set SameSite=None for cross-origin requests in production
- Update auth callback and logout to use cookie domain
- This fixes the login loop where session cookie wasn't sent
Add CORSMiddleware configured to:
- Allow the frontend origin (web_base_url)
- Allow credentials (cookies)
- Allow all methods and headers
This fixes cross-origin requests between frontend and API
when they're on different subdomains.
- /auth/callback now redirects to frontend URL with session cookie
- /auth/login stores 'next' path in cookie for post-login redirect
- User is redirected to their original destination after authentication
Add if_not_exists=True to CREATE TABLE operations in migrations
0003 and 0004. This prevents DuplicateTableError when migrations
are re-run on databases where tables were partially created.
SQLAlchemy 2.0 async engines conflict with alembic's sync context manager.
Instead of trying to bridge async/sync, use subprocess to run
'alembic upgrade head' directly. This is simpler and more reliable.
- Remove psycopg2-binary dependency (no longer needed)
- Simplify init_database to use subprocess.run()
- Remove all sync engine code
SQLAlchemy 2.0 async engines don't support the sync context manager
protocol needed by alembic. Create a separate sync engine (using
psycopg2) for migration operations while keeping async engine for
application queries.
- Add psycopg2-binary dependency
- Rename async connection variable to avoid mypy confusion
- Use sync engine for MigrationContext and alembic commands
- Exit with error code 1 if init_database() returns False
- Update health check to verify database connectivity
- Prevents confusing 'table does not exist' errors later
Add migration version check before running alembic upgrade to prevent
multiple uvicorn workers from running migrations simultaneously.
- Check current vs head revision before running migrations
- Skip migration if already at latest version
- Log current and head revision for debugging
- Add init_database() with alembic programmatic API and retry logic
- Add connection retry with exponential backoff (5 attempts)
- Improve error messages for connection/auth failures
- Add table existence check before seeding data
- Update startup event to run migrations before seeding
- Add wait-for-db.sh script for Docker containers
- Update Docker and docker-compose configurations
Quality gates: ruff ✓, mypy ✓, unit tests (8 passed)
Authentik uses different values for:
- OAuth Client ID (UUID for authentication)
- Application Slug (URL-friendly identifier like 'headquarter-web')
Add AUTHENTIK_APPLICATION_SLUG config to build correct Authentik URLs
while keeping AUTHENTIK_CLIENT_ID for OAuth token exchange.
- Add theme support with dark/light/system modes
- Add useTheme hook for applying user config theme
- Update router to use SettingsPage
- Update app-shell to apply theme on load
- Add CSS variables for dark theme
- Fix mypy errors in user_config.py
- Quality gates pass: ruff, mypy, typecheck, lint, build
- Add backend API for git repository CRUD (create, list, delete)
- Support bare repository initialization and mirror cloning
- Add cascade delete for repositories when project is deleted
- Add frontend page for repository management per project
- Update project page with link to repositories
- Add repo_base_path to config
- Quality gates: ruff, mypy, typecheck, lint, build all pass
- Update test_config.py: account for conftest.py DATABASE_URL override
- Update test_migration_metadata.py: correct alembic path resolution
(alembic/ is at project root, not under src/)
Task 2.5: Remove duplicate fixtures from integration tests
- test_auth_api.py, test_auth_services.py, test_models.py
- test_projects_api.py, test_seed.py, test_users_api.py
- Fix npytest typos in all test files
Task 3.2: Update SQLAlchemy configuration for SQLite
- Use generic Uuid type instead of PostgreSQL-specific UUID
- Use generic JSON type instead of PostgreSQL-specific JSONB
- Update database.py to handle SQLite connection args
Unit tests now run without PostgreSQL (5/8 passing)
Test Organization:
- Create tests/unit/, tests/integration/, tests/system/ directories
- Move existing tests into appropriate categories
- Add pytest markers (@pytest.mark.unit, @pytest.mark.integration)
Shared Fixtures:
- Create conftest.py with SQLite engine (for unit tests)
- Add PostgreSQL session fixture with transaction rollback
- Add TestClient fixture for API tests
Configuration:
- Update pyproject.toml with asyncio_mode=auto
- Add test markers and default addopts
- Add aiosqlite dependency for SQLite support
E2E Testing:
- Initialize Playwright in e2e/ directory
- Add playwright.config.ts
- Create login flow E2E test
Build:
- Add test-unit, test-integration, test-system, test-e2e to Makefile
- Update test target to run all categories
- Add testing documentation to README
Note: Some tests have import issues due to missing python-jose
package in dev environment. This needs to be addressed separately.
Vite reads env vars at build time, not runtime. The previous setup
only set them in docker-compose 'environment' which is only available
at container runtime. Now they are passed as build args so Vite can
embed the correct API URL during the build process.
- Add build args to web service in both compose files
- Update Dockerfile to accept ARGs and set ENV for Vite
- Fixes login redirect always going to localhost:8000
In Traefik deployment, API and web are on different domains.
Frontend was using relative paths (/auth/login) which resolved
to the web domain instead of the API domain.
- Update LoginRedirectPage to use VITE_API_BASE_URL for login link
- Update apiClient 401 interceptor to redirect to full API URL
- Ensures OAuth flow works correctly with separate domains
wget resolves 'localhost' to IPv6 [::1] but nginx only listens on
IPv4 0.0.0.0:80, causing connection refused. Using 127.0.0.1 ensures
IPv4 connection and healthy container status.
- Create /run directory explicitly for nginx.pid
- Set proper ownership and permissions for non-root user
- Fixes 'open() /run/nginx.pid failed (13: Permission denied)' error
The package-lock.json was missing some esbuild optional dependencies
for other platforms. Using npm install instead of npm ci allows the
docker build to proceed without requiring all platform-specific packages
in the lock file.
- Add docker-compose.yml with postgres, redis, api, and web services
- Add multi-stage Dockerfile for API (Python 3.11)
- Add multi-stage Dockerfile for web (Node.js 20 + nginx)
- Add Makefile with common development commands
- Add .env.example with all required environment variables
- Add placeholder pyproject.toml and package.json for builds
- Configure health checks for all services
- Setup persistent volumes for postgres, redis, and repos
- Run services as non-root users