ASTAP is a production-oriented pipeline platform that ingests GitHub repositories, freezes immutable snapshots, discovers test targets, and exposes stage-level execution state through a secure API and web console.
- Executive Summary
- Current Product Status
- Core Capabilities
- Application Screenshots
- Architecture
- Data Model
- Pipeline Lifecycle
- Security Model
- Tech Stack
- Quick Start
- Configuration
- API Reference
- Artifacts and Storage
- Operations and Reliability
- Deployment Notes
- Troubleshooting
- Limitations
- Roadmap
- Contributing
- Project Policies
- License
ASTAP is designed around a strict separation of concerns:
- Postgres is the single source of truth for runs, jobs, and targets.
- Redis is transport-only for job delivery.
- Supabase Storage is used for large immutable artifacts.
- Each pipeline stage runs independently in a clean temporary workspace and communicates through persisted state and artifacts.
This model enables predictable recovery, traceable execution, and clear stage boundaries for future expansion into test generation, isolated execution, and AI-driven analysis.
Implemented end-to-end:
ingestdiscover
Defined and visible (not yet executed):
generate_testsexecute_testsanalyze
- Workspace-scoped multi-project model backed by Supabase Postgres + RLS
- Secure auth path using Supabase access tokens validated by API JWKS verification
- Run creation workflow that creates stage jobs and enqueues execution
- Atomic job claim mechanism (
pending -> running) to prevent duplicate processing - Immutable ingest snapshot generation with hash + size metadata
- Python AST-based discovery with idempotent target replacement
- Run timeline and progress visualization in the React UI
- Queue monitoring via RQ Dashboard
client(React/Vite): signup/login, project registration, run launch, run detailsapi(FastAPI): authenticated control plane for projects/runs and status retrievalworker(RQ): async stage executors (ingest,discover)queue(Redis): queue transport for stage jobsrq-dashboard: operator view into queue/job stateSupabase: Postgres, Auth, Storage
- User authenticates with Supabase Auth from the client.
- Client calls API with
Authorization: Bearer <access_token>. - API validates JWT against Supabase JWKS and resolves user workspace.
- API creates run + jobs in Postgres and enqueues ingest.
- Worker performs stage work, persists state in Postgres, writes artifacts to Supabase Storage.
- Client polls run endpoints for near-real-time status updates.
flowchart LR
U[User] --> C[React Client]
C -->|Supabase Auth| SAuth[(Supabase Auth)]
C -->|Bearer JWT| API[FastAPI API]
API --> DB[(Supabase Postgres)]
API --> RQ[(Redis / RQ)]
RQ --> W[Worker]
W --> DB
W --> ST[(Supabase Storage)]
C -->|GET /runs| API
Primary entities:
workspacesprojectsrunsjobstargets
Important invariants:
runsis the lifecycle anchor for pipeline execution.jobsare unique by(run_id, stage).targetsare regenerated idempotently for each discover retry.- Snapshot metadata is stored on
runsand points to immutable storage objects.
Stage sequence:
ingestdiscovergenerate_testsexecute_testsanalyze
- Clone repository
- Checkout requested ref
- Resolve commit SHA (
git rev-parse HEAD) - Produce archive snapshot (
git archive) - Upload snapshot to Supabase Storage
- Persist snapshot metadata to
runs - Mark ingest job succeeded and enqueue discover
- Download and extract immutable snapshot
- Walk Python files and parse with built-in
ast - Detect:
SERVICE_FUNCTIONfor module-level functions and classesAPI_ENDPOINTfor FastAPI-like decorators (get,post,put,delete,patch)
- Replace existing run targets (
DELETE+ freshINSERT) - Upload
discover/targets.json - Mark discover succeeded and mark run succeeded
- Authentication: Supabase email/password in client
- Token transport:
Authorization: Bearer <access_token> - Token verification: server-side JWT validation with Supabase JWKS and issuer/audience checks
- Data isolation: Postgres Row Level Security policies scoped by workspace owner
- Artifact scope: private Supabase Storage bucket (
runs) - API scoping: all run/project reads and writes are constrained to current user workspace
- Backend: FastAPI, SQLAlchemy, Pydantic, PyJWT
- Worker: Python, RQ, Redis
- Frontend: React 18, TypeScript, Vite, Tailwind
- Data plane: Supabase Postgres + Storage + Auth
- Orchestration: Docker Compose
- Docker and Docker Compose
- Supabase project
psqlCLI installed locally
git clone <your-repo-url>
cd ASTAP
cp .env.example .envSet values in .env:
DATABASE_URLREDIS_URLSUPABASE_URLSUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEYSUPABASE_DB_URLSUPABASE_STORAGE_BUCKET(typicallyruns)API_CORS_ORIGIN
./scripts/apply_supabase_schema.shdocker compose up --build- Client:
http://localhost:3000 - API docs:
http://localhost:8000/docs - RQ Dashboard:
http://localhost:9181
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | SQLAlchemy connection string for API/worker |
REDIS_URL |
Yes | RQ Redis URL |
SUPABASE_URL |
Yes | Supabase project base URL |
SUPABASE_ANON_KEY |
Yes | Public key used by frontend auth client |
SUPABASE_SERVICE_ROLE_KEY |
Yes | Service key used for storage operations |
SUPABASE_DB_URL |
Yes | Connection string used by migration scripts |
SUPABASE_STORAGE_BUCKET |
Yes | Artifact bucket name (runs) |
SUPABASE_JWT_AUDIENCE |
No | JWT audience (authenticated by default) |
API_CORS_ORIGIN |
No | Allowed CORS origin for API |
API_PORT |
No | API port override |
CLIENT_PORT |
No | Client port override |
RQ_DASHBOARD_PORT |
No | RQ dashboard port override |
GET /health
POST /projectsGET /projects
POST /projects/{project_id}/runsGET /runsGET /runs/{run_id}
- Creating a run inserts both
ingestanddiscoverjobs. - API enqueues
ingest. - Worker enqueues
discoveronly after successful ingest. - Run progress is computed from stage statuses.
Bucket:
runs(private)
Path convention:
{workspace_id}/{project_id}/{run_id}/snapshot/snapshot.tar.gz{workspace_id}/{project_id}/{run_id}/discover/targets.json
Snapshot metadata stored on run:
snapshot_bucketsnapshot_keysnapshot_sha256snapshot_size_bytesref_resolved
Reliability primitives currently active:
- Atomic job claiming in database
- Stage output persistence in Postgres
- Immutable artifact storage in Supabase
- Idempotent target persistence for discover retries
Monitoring and visibility:
- RQ Dashboard for queue/job state
- FastAPI
/docsfor API behavior verification - Run detail UI with stage-level status and error rendering
Future reliability work:
- Reconciler-based continuation and lock TTL recovery is planned
The repository ships with a local Docker Compose topology:
apiworkerqueuerq-dashboardclient
For production environments:
- Use managed Redis and managed Postgres (Supabase)
- Externalize secrets via a secret manager
- Add centralized logging/metrics and alerting
- Run workers with horizontal scaling by queue/stage
- Introduce CI/CD checks for migrations and API contract tests
- Confirm
psqlis installed. - Validate
SUPABASE_DB_URLin.env. - Ensure migration user has privileges for schemas used (
public,storage,authwhere applicable).
- Confirm frontend and backend target the same
SUPABASE_URL. - Re-authenticate to refresh session token.
- Verify
SUPABASE_JWT_AUDIENCEif customized.
- Check Redis connectivity from
apiandworker. - Confirm worker is running and subscribed to
ingestanddiscoverqueues. - Inspect job failures in RQ dashboard and API run detail.
- Ensure repository snapshot contains valid Python files.
- Review run detail stage error and worker logs for syntax/encoding issues.
- Discovery currently supports Python only.
- Discover skips
tests/and common virtual/build/vendor directories. - Reconciler loop is currently a stub.
- Stages after discover are placeholders in this version.
- Implement reconciler and lock timeout recovery
- Add
generate_testsstage with model-driven test synthesis - Add isolated
execute_testsstage - Add
analyzestage with diagnostics and summaries - Add downloadable artifact management in UI
- Extend discovery to additional languages and frameworks
See CONTRIBUTING.md for full contribution workflow and PR expectations.
This project is licensed under the MIT License.





