Internal recruitment workflow automation tool for Provectus. Connects Lever (ATS), Barley (interview recordings/transcripts), and Claude AI (via Amazon Bedrock) to automate candidate evaluation. Recruiters upload CVs and transcripts through a web UI; AWS Step Functions + Lambda orchestrate AI analysis and store results directly in the database.
React SPA (S3+CF) β FastAPI (ECS Fargate) β EventBridge β Step Functions β Lambdas
β β
RDS Postgres Bedrock (Claude)
S3 (files)
| Layer | Technology |
|---|---|
| Frontend | React 19, TypeScript, Vite, TanStack Router, Tailwind v4, shadcn/ui |
| Backend | Python 3.12+, FastAPI (async), SQLModel, asyncpg, Alembic |
| Evaluation | AWS Step Functions + Lambda (5 evaluator functions) |
| AI | Claude via Amazon Bedrock |
| Auth | AWS Cognito (Google OAuth federation) + JWT |
| Infra | AWS β ECS Fargate, RDS PostgreSQL, S3, CloudFront, EventBridge |
See context/product/architecture.md for full architecture details.
- Python 3.12+
- uv (Python package manager)
- Bun (JS runtime & package manager)
- Docker & Docker Compose
- PostgreSQL 16 (provided via Docker Compose)
Using Claude Code? Run
/setupfor a guided walkthrough with verification at each step.
git clone <repo-url> && cd recruitment-framework-workflow
cp app/backend/.env.example app/backend/.envDefaults in .env.example work for local Docker Compose. Cognito vars are only used in production and can be left commented out β local auth uses dev-login.
docker compose up -d # Postgres, MinIO, backend, evaluatorThe backend container auto-runs alembic upgrade head on start via its entrypoint.
docker compose --profile seed run --rm seedLoads 4 teams, 6 users, 10 positions, 25 candidates across all pipeline stages. Safe to re-run β script truncates first.
cd app/frontend && bun install && bun run devOpen http://localhost:5173, click Dev Login, enter any @provectus.com email. You should see the dashboard with seeded positions and candidates.
Backend: http://localhost:8000 (docs at /docs) | Frontend: http://localhost:5173 | MinIO Console: http://localhost:9101 (minioadmin / minioadmin)
If you prefer to run the backend or frontend outside Docker:
Database + MinIO only:
docker compose up db minio minio-init -d # Postgres on :5437, MinIO on :9100Backend (app/backend/):
uv sync # Install dependencies
uv run alembic upgrade head # Apply migrations
uv run python -m scripts.seed # (Optional) seed dev data
uv run fastapi dev # Dev server at :8000Frontend (app/frontend/):
bun install # Install dependencies
bun run dev # Dev server at :5173 (proxies /api β :8000)Note: Docker Compose sets
DEBUG=true, which skips Cognito and enablesPOST /api/auth/dev-loginfor local development.S3_PRESIGN_ENDPOINT_URL(http://localhost:9100) is separate fromS3_ENDPOINT_URLβ presigned URLs must resolve from the browser, not from inside the container.Apple Silicon: if you hit platform errors, prepend
DOCKER_DEFAULT_PLATFORM=linux/amd64todocker compose up.
app/
backend/ # FastAPI API server
app/
main.py # Entrypoint, lifespan, router registration
config.py # pydantic-settings (reads .env)
database.py # Async SQLAlchemy engine + session factory
models/ # SQLModel data models
routers/ # API route modules
services/ # Business logic
schemas/ # Pydantic request/response schemas
dependencies/ # FastAPI dependency injection
migrations/ # Alembic (async)
tests/ # pytest-asyncio + aiosqlite
frontend/ # React SPA
src/
routes/ # TanStack file-based routes
features/ # Domain hooks (features/{domain}/hooks/)
widgets/ # Composite UI components
shared/ # API client, UI components, utilities
lambdas/ # Evaluation pipeline
cv_analysis/ # CV parsing and requirements matching
screening_eval/ # Screening interview evaluation
technical_eval/ # Technical interview evaluation
recommendation/ # Hire/no-hire recommendation
feedback_gen/ # Candidate feedback generation
shared/ # Common utilities (Bedrock, DB, S3)
local_orchestrator.py # Local Step Functions simulator
context/
product/ # Product definition, architecture, roadmap
spec/ # Feature specs (per feature)
infra/ # Terraform IaC (AWS)
docker-compose.yml # Postgres, MinIO, backend, evaluator (dev)
uv run fastapi dev # Dev server (hot reload)
uv run pytest # Run tests
uv run ruff check . && uv run ruff format . # Lint + format
uv run alembic upgrade head # Apply migrations
uv run alembic revision --autogenerate -m "description" # New migrationbun run dev # Dev server (HMR)
bun run build # Type-check + production build
bun run lint # ESLint
bun run generate:api # Regenerate API client from openapi.json
bunx shadcn@latest add <component> # Add shadcn/ui componentRe-export after changing backend routes (CI openapi-check will fail otherwise):
cd app/backend && uv run python scripts/export_openapi.py
cd app/frontend && bun run generate:apiAll backend config is managed via environment variables loaded through pydantic-settings. Copy .env.example and fill in real values:
| Variable | Description |
|---|---|
DATABASE_URL |
Async Postgres connection string (or use DB_HOST/DB_PORT/DB_NAME/DB_USERNAME/DB_PASSWORD) |
JWT_SECRET_KEY |
Secret for signing JWT tokens |
COGNITO_USER_POOL_ID |
AWS Cognito user pool ID |
COGNITO_CLIENT_ID |
Cognito app client ID |
COGNITO_CLIENT_SECRET |
Cognito app client secret |
COGNITO_DOMAIN |
Cognito domain for OAuth flow |
COGNITO_REDIRECT_URI |
OAuth callback URL |
S3_BUCKET_NAME |
S3 bucket for file storage |
S3_ENDPOINT_URL |
S3 endpoint (MinIO for local dev) |
S3_PRESIGN_ENDPOINT_URL |
Browser-facing S3 endpoint for presigned URLs |
ALLOWED_EMAIL_DOMAIN |
Restrict login to this email domain (default: provectus.com) |
DEBUG |
Enable dev-login and skip Cognito (default: false) |
See app/backend/.env.example for the full list.
| Phase | Focus | Status |
|---|---|---|
| 0 | AWS infra, CI/CD, evaluation pipeline architecture | Done |
| 1 | Auth, candidate/position management, CV upload, transcript upload, Barley integration | In progress |
| 2 | Screening summaries, technical evaluation, recommendation engine | Done |
| 3 | Candidate feedback generation | In progress |
| Future | Lever integration (read + write), AI candidate analyst chat | Planned |
See context/product/roadmap.md for details.
CI runs on PRs to main with path-scoped triggers. Deploy workflows use OIDC β no static AWS keys.
| Workflow | Trigger paths | Checks |
|---|---|---|
| CI Backend | app/backend/** |
ruff, mypy, bandit, pytest, openapi-check |
| CI Frontend | app/frontend/** |
eslint, build (includes type-check) |
| CI Lambdas | app/lambdas/** |
ruff, pytest |
| CI Infrastructure | infra/** |
terraform fmt/validate, version pin enforcement, tflint |
| Deploy Backend | app/backend/** (push to main) |
Build β ECR β ECS migration task β ECS deploy |
| Deploy Frontend | app/frontend/** (push to main) |
Build β S3 sync β CloudFront invalidation |
| Deploy Lambdas | app/lambdas/** (push to main) |
Package β publish shared layer β update function code |
context/product/product-definition.mdβ full product definitioncontext/product/architecture.mdβ system architecturecontext/product/roadmap.mdβ product roadmapapp/frontend/README.mdβ frontend-specific docsCLAUDE.mdβ guidance for Claude Code