A self-hosted App Store for Open Source Software — discover, analyze, and launch OSS projects locally.
Inspired by Apify Store, HuggingFace Hub, Docker Hub, and GitHub Trending, combined into a single production-grade desktop application.
| Layer | Technology |
|---|---|
| Frontend | Next.js 15, TypeScript, Tailwind CSS, shadcn/ui, TanStack Query |
| Backend | FastAPI (Python 3.11) |
| Database | PostgreSQL 16 |
| Search | Meilisearch |
| Vector DB | Qdrant |
| Queue | Celery + Redis |
| AI | OpenAI-compatible API (Ollama / LM Studio) |
# 1. Clone and setup
git clone https://github.com/stag175/OpenForge
cd OpenForge
make setup # copies .env.example → .env
# 2. (Optional) Add your GitHub token for higher rate limits
# Edit .env: GITHUB_TOKEN=ghp_...
# 3. Start everything
make dev
# 4. Run database migrations + seed data
make migrate
make seed
# 5. Open the app
open http://localhost:3000Services:
- Frontend: http://localhost:3000
- Backend API: http://localhost:8000
- API Docs: http://localhost:8000/docs
- Meilisearch: http://localhost:7700
- Browse 25+ categories: AI/ML, LLM, RAG, Agents, Scraping, DevOps, Finance, etc.
- Trending repositories from GitHub
- Instant full-text search via Meilisearch
- Semantic search via Qdrant named vectors for catalog, README, runtime, and trust domains
- AI-powered natural language search
- README rendering
- Health/Activity/Popularity scores (0–100)
- AI-generated summary, use cases, pros & cons
- Auto-detected install commands
- Related repositories via vector similarity
- Import any GitHub repository by
owner/name - Direct GitHub imports capture latest release and changelog evidence when upstream metadata is available
- Direct GitHub imports refresh issue totals and contributor counts for stronger issue-health and community scoring, and sample issue response, resolution, stale-open, release-cadence, and discussion evidence when upstream metadata is available
- Import GitHub trending (daily/weekly/monthly)
- GitHub search query import
- Awesome List import (parse GitHub links from any README URL)
- Background Celery workers process everything asynchronously
- Create named collections to organize repositories
- Create smart boards from saved searches and refresh their materialized repository list
- Pin collections for quick access
- Keep boards private or share them with the local tenant for read-only collaboration
- Group boards, actors, schedules, and review streams under one collaboration context
- Keep workspaces private, share them with the local tenant, or grant named principals/groups viewer/editor access
- Let workspace owners manage grants while editors can update workspace context and link tenant-visible resources
- Link caller-visible boards, actors, schedules, and review notes from their native surfaces while preserving hidden private-resource boundaries for tenant readers and granted collaborators
- Export caller-visible workspace collaboration summaries as markdown plus structured JSON
- Live system health and capability checks for Postgres, Redis, Meilisearch, Qdrant, AI, GitHub, Docker, Dagger, and Temporal
- Operator preferences for tenant/principal-scoped saved controls, including Settings replay filters
- Unified search across text, semantic named-vector, and AI-assisted modes with reciprocal-rank fusion telemetry, facets, match explanations, dependency-centrality evidence, package metadata freshness, and quality-aware ranking
- Browse marketplace facets for code language, source, maintainer/owner, license, support model, commercial model, OpenSSF Scorecard evidence, release/changelog/cadence evidence, install method, OpenForge quality score, launch readiness, generated example coverage, runnable sample-input evidence, last-updated freshness, issue health, actor runtime/resource declarations, local resource estimates, measured actor-run telemetry, actor build trust and signed-image evidence, shared review evidence, package metadata provider coverage, package vulnerability state, local trust status, package attestation evidence, and catalog state
- Repository listing cards with release/changelog/cadence, issue response-time, issue resolution/stale-open, discussion, and shared review evidence, and dossiers with score breakdowns, OpenForge Quality scores/factors, support/commercial model evidence, OpenSSF Scorecard evidence, package/dependency/advisory/download reach, package centrality, external package metadata freshness, package attestation evidence, actor build scan/provenance/signed-image evidence, actor runtime/resource declarations, runnable sample-input previews, local resource estimate tiers, measured actor-run status/duration evidence, repository detail release-cadence, issue-response/resolution/stale-open, discussion, and run-history trends, trust signals, suggested next actions, and launch readiness
- Sandboxed launch plans that generate review-only steps, risks, confirmations, and logs without silently executing third-party code
- Collection actions from repository detail pages for faster curation
- Workspace overview and detail pages for tenant-shared collaboration contexts across boards, actors, schedules, and review streams
OpenForge uses any OpenAI-compatible API for repository analysis and embeddings.
Ollama (default):
ollama pull llama3.2
ollama pull nomic-embed-textLM Studio: set OPENAI_API_BASE=http://localhost:1234/v1 in .env
┌─────────────┐ ┌──────────────┐ ┌────────────────┐
│ Next.js │───▶│ FastAPI │───▶│ PostgreSQL │
│ Frontend │ │ Backend │ │ (main DB) │
│ :3000 │ │ :8000 │ └────────────────┘
└─────────────┘ │ │ ┌────────────────┐
│ │───▶│ Meilisearch │
│ │ │ (text search) │
│ │ └────────────────┘
│ │ ┌────────────────┐
│ │───▶│ Qdrant │
│ │ │ (vectors) │
└──────┬───────┘ └────────────────┘
│ ┌────────────────┐
└───────────▶│ Celery+Redis │
│ (background) │
└────────────────┘
make logs-backend # tail backend + worker logs
make shell-backend # bash into backend container
make shell-db # psql session
make test # run pytest
make lint # ruff + eslintFrontend linting uses the standalone ESLint CLI through npm run lint with flat eslint.config.mjs, preserving the Next.js core web vitals and TypeScript rules without the deprecated next lint wrapper.
For non-Docker backend work, install from the project manifest:
cd backend
python -m pip install -e ".[dev]"
python -m uvicorn app.main:app --host 127.0.0.1 --port 8000Backend dependency gates are lockfile-aware and can run as a local release check:
cd backend
uv run python scripts/verify_backend_dependency_audit.py --compact
# or from the repo root on systems with Make installed:
make backend-auditThe backend package also installs the openforge CLI for local API operations:
openforge --help
openforge status
openforge search repositories "llm workflow" --limit 5
openforge repo dossier <repository-id>
openforge repo enrich-packages <repository-id> --osv
openforge repo enrich-packages <repository-id> --metadata --metadata-source deps.dev --metadata-source ecosyste.ms --metadata-source npm_registry
openforge repo refresh-package-metadata --dry-run
openforge repo refresh-package-metadata --confirm-external-metadata-refresh --metadata-source deps.dev
openforge repo refresh-scorecards --dry-run
openforge repo refresh-scorecards --confirm-scorecard-refresh
openforge repo refresh-github-evidence --dry-run
openforge repo refresh-github-evidence --confirm-github-evidence-refresh --history-page-limit 3 --skip-discussions
openforge actors run-task <actor-id> --task-id <task-id>
openforge actors monitoring <actor-id>
openforge actors execute-run <run-id> --confirm-sandbox-execution
openforge schedules trigger <schedule-id> --confirm-review-only
openforge webhooks send-delivery <delivery-id> --confirm-outbound-delivery --expected-target-url https://example.com/hook --max-attempts 3 --retry-after-seconds 300 --operator-id local-operator --confirmation outbound_delivery_confirmed
openforge webhooks verify-delivery <delivery-id> --operator-id local-operatorCLI profiles let operators switch API origins without repeating flags:
openforge profiles set local --api-url http://localhost:8000 --activate
openforge profiles set staging --api-url https://openforge.example.com/api/v1 --token <token>
openforge profiles list
openforge --profile staging status
openforge completion powershellProfile commands never print stored token values. OPENFORGE_PROFILE, OPENFORGE_API_URL, and OPENFORGE_API_TOKEN override saved profile values, while explicit --profile, --api-url, and --token flags take highest precedence. Use OPENFORGE_CLI_CONFIG_PATH to choose a custom profile file for portable or test installs.
Local CLI distribution artifacts can be built without publishing to a package index:
make cli-dist
# or
cd backend && uv run python scripts/build_cli_distribution.py
# Signed internal/stable channels require an Ed25519 private key and explicit key id:
uv run python scripts/build_cli_distribution.py --release-channel stable --signing-key path/to/release-ed25519.pem --signing-key-id openforge-stable-ed25519-v1
# Verify hashes, channel, detached signature, and trusted signing identity before installing:
uv run python scripts/verify_cli_distribution.py dist/openforge-cli-0.1.0.zip --require-signature --expected-release-channel stable --trusted-key-id openforge-stable-ed25519-v1 --trusted-public-key-sha256 <fingerprint>The builder writes backend/dist/openforge-cli-<version>.zip with the backend wheel/sdist, Bash/Zsh/PowerShell completion scripts, Windows and POSIX installer scripts, read-only MCP examples, a package manifest.json, package SHA256SUMS, and a openforge-cli-<version>.zip.sha256 sidecar. Builds use the local release channel by default and remain unsigned for developer artifacts. The internal and stable channels require --signing-key plus a long-lived --signing-key-id; signed bundles include a detached Ed25519 manifest.json.sig and record the key id plus public-key fingerprint in the manifest. The verifier checks the archive sidecar, package checksums, manifest file ledger, release channel, optional detached signature, and optional trusted key id/fingerprint pins before install.
The v1 API includes the original repository, category, collection, ingestion, search, and stats routes plus:
| Endpoint | Purpose |
|---|---|
GET /api/v1/system/health |
Service reachability and configuration status |
GET /api/v1/system/capabilities |
Feature availability and workflow contract readiness derived from live services |
GET /api/v1/system/auth |
Sanitized local API auth status for optional read/write/admin role tokens |
GET /api/v1/system/operator-preferences |
List owned and tenant-shared operator preferences, optionally scoped by namespace and key |
PUT /api/v1/system/operator-preferences/{namespace}/{key} |
Save or update the caller-owned operator preference with private or tenant visibility |
DELETE /api/v1/system/operator-preferences/{id} |
Delete a caller-owned operator preference |
GET /api/v1/system/identity/tenants |
List the built-in local tenant plus managed identity tenants with principal and group counts |
POST /api/v1/system/identity/tenants |
Create a managed identity tenant; requires admin auth when local API auth is enabled |
PATCH /api/v1/system/identity/tenants/{tenant_id} |
Update managed identity tenant name, mode, status, description, or metadata |
DELETE /api/v1/system/identity/tenants/{tenant_id} |
Delete a managed identity tenant and its principals |
GET /api/v1/system/identity/users?tenant_id= |
List managed identity principals, optionally scoped to one tenant |
POST /api/v1/system/identity/users |
Create a managed identity principal for an existing tenant |
POST /api/v1/system/identity/users/scim-provision |
Apply one live SCIM User push or PATCH event by upserting, patching, or disabling a provider-managed principal without touching manual users |
GET /api/v1/system/identity/scim/v2/{ServiceProviderConfig,ResourceTypes,Schemas,Users,Groups} |
Expose SCIM v2 discovery metadata plus paged/filterable managed-tenant User and Group resources |
PATCH /api/v1/system/identity/users/{id} |
Update a managed principal role, status, profile metadata, or tenant assignment |
DELETE /api/v1/system/identity/users/{id} |
Delete a managed identity principal |
GET /api/v1/system/identity/groups?tenant_id= |
List local or managed tenant identity groups with member counts |
POST /api/v1/system/identity/groups |
Create a local or managed tenant identity group |
POST /api/v1/system/identity/groups/sync |
Upsert local or managed tenant groups from an external directory manifest; scheduled SCIM sources feed the same safe sync engine |
POST /api/v1/system/identity/groups/scim-provision |
Apply one live SCIM group push event by upserting or archiving a provider-managed group without touching manual groups |
PATCH /api/v1/system/identity/groups/{id} |
Update an identity group name, status, tenant, key, description, or metadata |
DELETE /api/v1/system/identity/groups/{id} |
Delete an identity group and its memberships |
GET /api/v1/system/identity/groups/{id}/members |
List group members by principal id |
POST /api/v1/system/identity/groups/{id}/members |
Add a principal to an identity group |
PATCH /api/v1/system/identity/group-members/{id} |
Update group member principal id, role, display name, identity kind, or metadata |
DELETE /api/v1/system/identity/group-members/{id} |
Remove a principal from an identity group |
GET /api/v1/system/settings/env-export |
Generate a non-secret dotenv export from the saved local settings profile |
POST /api/v1/system/settings/validate-service |
Validate and probe one draft local settings provider |
PATCH /api/v1/system/settings/secrets |
Write-only local GitHub/OpenAI/API role secret update and clear flow |
POST /api/v1/search/query |
Unified text, semantic, and AI search with explainable dependency and package metadata-aware ranking |
GET /api/v1/artifacts/{id} |
Shared parent detail for repository, actor, package, and actor image/build records |
GET /api/v1/repositories/{id}/dossier |
Repository score, trust, provenance, and launch-readiness dossier |
GET /api/v1/repositories/{id}/dossier/export |
Copy-ready dossier summary with markdown, counts, and the structured source dossier |
PATCH /api/v1/repositories/{id} |
Update local repository metadata such as the checkout clone_path used for package and actor manifest discovery |
GET /api/v1/repositories/{id}/review-notes |
List caller-owned and tenant-shared repository review notes |
GET /api/v1/repositories/{id}/audit-events |
List caller-visible repository audit events, including review-note create, update, and delete history |
POST /api/v1/repositories/{id}/review-notes |
Create a caller-owned repository review note with status, rating, visibility, and metadata |
PATCH /api/v1/review-notes/{id} |
Update a caller-owned repository review note |
DELETE /api/v1/review-notes/{id} |
Delete a caller-owned repository review note |
GET /api/v1/workspaces |
List caller-owned, tenant-shared, and explicitly granted collaboration workspaces with visible linked-resource counts and caller role metadata |
POST /api/v1/workspaces |
Create a caller-owned private or tenant-shared workspace |
GET /api/v1/workspaces/{id} |
Retrieve a workspace with caller role, permissions, grants visible to the caller, and caller-visible board, actor, schedule, and review-note links |
GET /api/v1/workspaces/{id}/export |
Export a caller-visible workspace collaboration summary with markdown, linked resources, counts, and recent audit events |
GET /api/v1/workspaces/{id}/audit-events |
List caller-visible workspace audit events for workspace and linked-resource mutations |
GET /api/v1/workspaces/{id}/permissions |
List owner-managed viewer/editor permission grants for a workspace |
POST /api/v1/workspaces/{id}/permissions |
Create or upsert a viewer/editor permission grant for a tenant principal or group |
PATCH /api/v1/workspaces/{id}/permissions/{grant_id} |
Update a workspace permission grant role, identity kind, or metadata |
DELETE /api/v1/workspaces/{id}/permissions/{grant_id} |
Revoke a workspace permission grant |
POST /api/v1/workspaces/{id}/collections |
Link a caller-visible board into a workspace as owner/editor, limited to tenant-visible or public boards for non-owner editors |
POST /api/v1/workspaces/{id}/actors |
Link an actor into a workspace as owner/editor |
POST /api/v1/workspaces/{id}/schedules |
Link an actor schedule into a workspace as owner/editor |
POST /api/v1/workspaces/{id}/review-notes |
Link a caller-visible review note into a workspace as owner/editor, limited to tenant-visible review streams for non-owner editors |
GET /api/v1/repositories/{id}/packages |
List linked PURL package identities and repository-package evidence |
POST /api/v1/repositories/{id}/packages/infer |
Infer and persist local package identities from source and install metadata |
GET /api/v1/repositories/{id}/package-intelligence |
List package dependency edges, catalog centrality, external package metadata status and facets, local advisory review records, and explicit external advisory findings |
POST /api/v1/repositories/{id}/packages/enrich |
Extract local dependency evidence, with optional operator-requested deps.dev/ecosyste.ms/npm registry metadata and OSV advisory enrichment |
POST /api/v1/repositories/packages/metadata-refresh |
Dry-run or confirm refreshes for stale or failed operator-requested package metadata checks |
POST /api/v1/repositories/scorecards/refresh |
Dry-run or confirm refreshes for stale or failed OpenSSF Scorecard evidence |
POST /api/v1/repositories/github-evidence/refresh |
Dry-run or confirm refreshes for stale GitHub release, issue, contributor, and optional discussion evidence, with opt-in multi-page history depth |
POST /api/v1/repositories/{id}/refresh |
Queue a source refresh for a repository |
POST /api/v1/repositories/compare |
Compare up to four repository dossiers |
POST /api/v1/actors/import |
Import an actor from an explicit manifest payload |
POST /api/v1/actors/import/from-repository |
Detect openforge.actor.json or .actor/actor.json from a repository clone path and import the actor manifest |
GET /api/v1/ingestion/jobs/{id}/events |
Step-level synthesized ingestion events |
GET /api/v1/ingestion/jobs/{id}/events/page?cursor= |
Page through ingestion lifecycle events with an opaque cursor |
GET /api/v1/ingestion/jobs/{id}/logs/page?cursor= |
Page through ingestion log chunks with an opaque cursor |
GET /api/v1/ingestion/jobs/{id}/repository-results |
List per-repository ingestion outcomes for a job |
GET /api/v1/ingestion/jobs/{id}/repository-results/page?cursor= |
Page through per-repository ingestion outcomes with an opaque cursor |
POST /api/v1/ingestion/repository-results/{id}/retry |
Requeue a per-repository ingestion result as a fresh single-repository job |
PATCH /api/v1/ingestion/repository-results/{id}/disposition |
Mark, clear, ignore, archive, or accept a per-repository ingestion result for operator triage |
POST /api/v1/ingestion/jobs/{id}/cancel |
Cancel a queued or running ingestion job; running jobs request Celery termination with cooperative checkpoints as fallback |
POST /api/v1/ingestion/jobs/{id}/retry |
Replay a completed, failed, or canceled ingestion job as a fresh queued job |
POST /api/v1/ingestion/jobs/{id}/clone |
Duplicate any replayable ingestion job as a fresh queued job |
GET /api/v1/actors/{id}/tasks |
List saved actor task configurations |
GET /api/v1/actor-tasks/{id} |
Retrieve one saved actor task configuration |
GET /api/v1/actor-tasks/{id}/snippets |
Generate API, CLI, Docker, and Compose snippets for a saved task |
GET /api/v1/integrations/agent/manifest |
List read-only local agent integration tools for search, actors, storage, and logs |
GET /api/v1/actors/{id}/integrations/agent/manifest |
List actor-scoped agent integration tools with actor examples |
POST /api/v1/integrations/agent/invoke |
Invoke a read-only local agent integration tool with constrained JSON input |
GET /api/v1/search/evaluations/package-metadata-facets |
Summarize package metadata search-evaluation benchmark coverage by provider feed, repository archetype, expected facets, and advisory signals |
GET /api/v1/search/evaluations/package-metadata-facets/runs |
List persisted package metadata benchmark run history with relevance scores, case results, and operator-ready summary text |
POST /api/v1/search/evaluations/package-metadata-facets/runs |
Record a durable package metadata benchmark run from the governed fixture and measured relevance judgments |
GET /api/v1/search/evaluations/package-metadata-facets/replay-runs |
List persisted package metadata replay runs with observed repository ranks, misses, exact metadata facet matches/misses, advisory evidence, and operator-ready summary text |
POST /api/v1/search/evaluations/package-metadata-facets/replay-fixture |
Seed or refresh evaluation-scoped package metadata replay repositories plus package identity, dependency, and advisory evidence so runtime smoke can prove executable ranking assertions |
POST /api/v1/search/evaluations/package-metadata-facets/replay-runs |
Replay the governed package metadata benchmark through current unified search ranking and persist observed rank, exact metadata facet, and advisory evidence |
POST /api/v1/actors/{id}/tasks |
Save a reusable actor task after schema validation |
PATCH /api/v1/actor-tasks/{id} |
Update saved task metadata, input, run options, or actor version |
DELETE /api/v1/actor-tasks/{id} |
Delete a saved task, with force=true for dependent schedules |
POST /api/v1/actors/{id}/runs |
Create a review-only actor run |
GET /api/v1/actors/{id}/runs?actor_task_id=&status= |
List actor run history, optionally filtered by saved task or run status |
GET /api/v1/actors/{id}/runs/page?cursor=&actor_task_id=&status= |
Page through actor run history with an opaque cursor |
GET /api/v1/actors/{id}/monitoring |
Summarize actor run health, build gate state, schedules, webhooks, queue pressure, and storage volume |
GET /api/v1/actors/{id}/audit-events |
List caller-visible actor collaboration audit events for task, schedule, webhook, delivery, and saved-view actions |
GET /api/v1/actors/{id}/run-saved-views |
List owned and tenant-shared actor run saved views |
POST /api/v1/actors/{id}/run-saved-views |
Save or update an owned actor run saved view with private or tenant visibility |
PATCH /api/v1/actor-run-saved-views/{id} |
Update an owned actor run saved view |
DELETE /api/v1/actor-run-saved-views/{id} |
Delete an owned actor run saved view |
GET /api/v1/actor-runs/{id}/logs/page?cursor= |
Page through actor run log chunks with an opaque cursor |
POST /api/v1/actor-runs/{id}/start |
Mark a review actor run as running and record lifecycle evidence |
POST /api/v1/actor-runs/{id}/execute |
Queue a promotion-ready run for explicit sandboxed Celery worker execution |
POST /api/v1/actor-runs/{id}/complete |
Mark a review actor run as completed and record lifecycle evidence |
POST /api/v1/actor-runs/{id}/fail |
Mark a review actor run as failed and record lifecycle evidence |
POST /api/v1/actor-runs/{id}/cancel |
Cancel a review actor run before it reaches a terminal state |
POST /api/v1/actor-runs/{id}/retry |
Recreate a terminal actor run as a fresh review run with source lineage |
POST /api/v1/actor-runs/{id}/clone |
Clone any actor run into a fresh review run with source lineage |
POST /api/v1/actor-runs/{id}/tasks |
Duplicate a review run input and resources into a saved task |
GET /api/v1/actor-runs/{id}/datasets |
List dataset handles produced by a review run |
POST /api/v1/datasets/{id}/items |
Append a confirmed review-only dataset row |
GET /api/v1/datasets/{id}/items/page?cursor= |
Page through dataset rows with an opaque cursor |
GET /api/v1/datasets/{id}/export |
Export bounded dataset rows as JSONL |
GET /api/v1/actor-runs/{id}/key-value-stores |
List key-value store handles produced by a review run |
PUT /api/v1/key-value-stores/{id}/records/{key} |
Upsert a confirmed review-only key-value record |
DELETE /api/v1/key-value-stores/{id}/records/{key} |
Delete a confirmed review-only key-value record |
GET /api/v1/key-value-stores/{id}/records/page?cursor= |
Page through key-value records with an opaque cursor |
GET /api/v1/key-value-stores/{id}/records/export |
Export bounded key-value records as JSON |
GET /api/v1/actor-runs/{id}/request-queues |
List request queue handles produced by a review run |
POST /api/v1/request-queues/{id}/items |
Add a confirmed review-only request queue item |
PATCH /api/v1/request-queue-items/{id} |
Update a confirmed review-only request queue item |
DELETE /api/v1/request-queue-items/{id} |
Delete a confirmed review-only request queue item |
GET /api/v1/request-queues/{id}/items/page?cursor=&status= |
Page through request queue items with an optional status filter |
GET /api/v1/request-queues/{id}/items/export?status= |
Export bounded request queue items as JSON |
GET /api/v1/actors/{id}/schedules |
List paused or active task schedules for an actor |
GET /api/v1/actor-schedules/{id} |
Retrieve one saved actor schedule |
GET /api/v1/actor-schedules/{id}/snippets |
Generate API, CLI, Docker, and Compose snippets for a saved schedule |
GET /api/v1/actor-schedules/{id}/dispatches |
List claimed schedule dispatch slots and run links |
POST /api/v1/actors/{id}/schedules |
Save a confirmed review-only schedule for an actor task |
PATCH /api/v1/actor-schedules/{id} |
Update schedule timing, status, task, or overrides |
POST /api/v1/actor-schedules/{id}/trigger |
Manually trigger a scheduled review run after confirmation |
POST /api/v1/actor-schedules/dispatch-due |
Dispatch due active schedules idempotently into review-only runs |
GET /api/v1/actors/{id}/webhooks |
List actor webhook subscriptions |
POST /api/v1/actors/{id}/webhooks |
Save a review-only webhook subscription for run events |
GET /api/v1/actor-webhooks/{id} |
Retrieve one actor webhook subscription |
PATCH /api/v1/actor-webhooks/{id} |
Update webhook target, events, status, or signing secret |
DELETE /api/v1/actor-webhooks/{id} |
Delete an actor webhook subscription |
GET /api/v1/actor-webhooks/{id}/deliveries?status= |
List captured webhook delivery records, optionally filtered by status such as failed, rate_limited, or dead_lettered |
POST /api/v1/actor-webhooks/{id}/replay |
Replay a captured run event into an idempotent webhook delivery record |
POST /api/v1/actor-webhook-deliveries/{id}/send |
Send a captured webhook delivery after explicit outbound confirmation, with sanitized auth profile headers, rate-limit checks, retry scheduling, dead-letter exhaustion metadata, and operator audit policy binding |
POST /api/v1/actor-webhook-deliveries/{id}/verify-signature |
Verify a captured delivery HMAC signature against the stored webhook secret and payload, recording bounded operator audit history |
POST /api/v1/policy/evaluate |
Preview local allow, warn, or deny policy decisions for actor launch intent |
GET /api/v1/actors/{id}/builds |
Review-ready actor build records with scan and provenance state |
GET /api/v1/actor-builds/{id} |
Retrieve one actor build lifecycle record |
POST /api/v1/actor-builds/{id}/scan-review |
Record static scan and policy findings; with run_local_tools=true, execute available local Syft, OSV-Scanner, Grype, Gitleaks, OPA, or explicit Dagger validation tools and persist bounded evidence |
POST /api/v1/actor-builds/{id}/scan-review/queue |
Queue scan-review through the Celery actor worker and persist queue/running/completed metadata on the build record |
GET /api/v1/actor-builds/{id}/findings |
List SBOM, vulnerability, secret, policy, and provenance findings for a build |
GET /api/v1/actor-builds/{id}/logs |
List scan-review log chunks for a build |
GET /api/v1/actor-builds/{id}/logs/page?cursor= |
Page through scan-review log chunks with an opaque cursor |
GET /api/v1/actor-builds/{id}/artifacts |
List scan-review summary and input artifacts for a build |
GET /api/v1/actor-builds/{id}/artifacts/page?cursor= |
Page through scan-review artifacts with an opaque cursor |
GET /api/v1/actor-build-artifacts/{id} |
Retrieve one build scan artifact record |
GET /api/v1/actor-build-artifacts/{id}/download |
Download one build scan artifact payload as JSON |
PATCH /api/v1/actor-build-findings/{id} |
Accept, suppress, or reopen a build finding with an audit note |
POST /api/v1/launch-plans |
Create a sandbox-first launch review plan |
POST /api/v1/launch-plans/{id}/validate |
Validate launch plan warnings and confirmations |
POST /api/v1/launch-sessions |
Create a review session after sandbox confirmation |
GET /api/v1/launch-sessions/{id}/logs |
Retrieve review-session logs |
GET /api/v1/launch-sessions/{id}/events |
Retrieve review-session lifecycle events and warning timeline |
GET /api/v1/launch-sessions/{id}/artifacts |
Retrieve review-session evidence artifacts, including the launch plan snapshot |
GET /api/v1/launch-session-artifacts/{id} |
Retrieve one review-session evidence artifact record |
GET /api/v1/launch-session-artifacts/{id}/download |
Download one review-session evidence artifact payload as JSON |
POST /api/v1/system/workflows/{contract_id}/dispatch |
Dry-run or explicitly confirmed Temporal dispatch for a selected workflow contract, returning fallback runner guidance when Temporal dispatch is disabled or unavailable |
- Docker is the recommended runtime for the full stack. If Docker Desktop is not running, the frontend can still build, but backend service checks will report attention states.
- The backend now creates the SQLAlchemy engine lazily, so unit tests and app imports do not require
asyncpguntil database access is actually used. - The API boots in degraded mode when optional local dependencies or services are missing.
/api/v1/system/healthand/api/v1/system/capabilitiesreport missing Python packages, stopped services, unavailable Docker/Dagger tooling, Temporal readiness, and workflow-contract fallback state instead of hiding the issue. - Dagger validation readiness is passive until the
daggerCLI is onPATHand Docker is reachable. Temporal workflow readiness is passive untilOPENFORGE_TEMPORAL_ADDRESSorTEMPORAL_ADDRESSpoints at a reachable Temporal server and the backend has thetemporalioPython package installed. - Workflow contract dispatch defaults to safe dry runs. Confirmed Temporal starts require
dry_run=false,confirm_temporal_dispatch=true, Temporal readiness, andOPENFORGE_TEMPORAL_DISPATCH_ENABLED=true; setOPENFORGE_TEMPORAL_TASK_QUEUEto override the defaultopenforge-workflowsqueue. When those requirements are not met, the dispatch endpoint returns the contract's Celery/local fallback runner and entrypoints instead of altering existing fallback behavior. - The optional Temporal worker is installed with
uv sync --extra temporaland can be started withuv run openforge-temporal-worker --address localhost:7233 --task-queue openforge-workflows. It registers the same six workflow types reported by/api/v1/system/capabilities: ingestion/enrichment/indexing, package metadata refresh, identity directory sync, actor build validation, actor schedule dispatch, and sandbox launch validation. Actor build validation runs as staged Temporal work: static scan review first, then an optional local scanner or Dagger validation stage when requested. - Local settings support full-profile validation and per-provider draft checks for database, Redis, Celery broker/result backend, Celery worker heartbeat, Meilisearch, Qdrant, Docker, Dagger, Temporal, Apify, sandbox policy, optional local scanner binaries, OpenAI-compatible AI, CORS, and repository workspace settings.
- Saved non-secret local settings are loaded into backend runtime configuration on restart, so persisted CORS origins, service URLs, explicit Celery broker/result backend URLs, and sandbox policy profiles no longer require hand-copying into
.env. Local settings can still generate a copy-ready.env.openforgeexport; write-only GitHub/OpenAI/API role secrets are represented as blank placeholders so saved secret values are never returned by the API. - Local settings can manage GitHub tokens, Apify tokens, OpenAI-compatible API keys, and optional local API read/write/admin role tokens through write-only secret updates. Saved secrets live in a separate local secrets file, are never returned by the API, and environment variables take precedence. Use
OPENFORGE_LOCAL_SECRETS_PATHto choose a custom secrets file for portable or test profiles. SetOPENFORGE_LOCAL_SECRETS_KEYto store that local profile as an encrypted Fernet/PBKDF2 envelope instead of plaintext JSON; setOPENFORGE_LOCAL_SECRETS_KEYRING_SERVICEplus optionalOPENFORGE_LOCAL_SECRETS_KEYRING_USERto read the encryption passphrase from an installed Pythonkeyringbackend instead. The direct environment key takes precedence over keyring lookup. - Local API auth is disabled until at least one
OPENFORGE_API_READ_TOKEN,OPENFORGE_API_WRITE_TOKEN, orOPENFORGE_API_ADMIN_TOKENis configured through the environment or local secrets profile, or until external OIDC JWT verification is ready withOPENFORGE_OIDC_ISSUER_URL,OPENFORGE_OIDC_CLIENT_ID, optionalOPENFORGE_OIDC_AUDIENCE, and trusted JWKS material fromOPENFORGE_OIDC_JWKS_JSON,OPENFORGE_OIDC_JWKS_FILE, cachedOPENFORGE_OIDC_JWKS_URL, or OIDC discovery throughOPENFORGE_OIDC_DISCOVERY_URL/OPENFORGE_OIDC_DISCOVERY_ENABLED=true. API clients can sendAuthorization: Bearer <token>orX-OpenForge-Api-Token; local read tokens can call read routes and read-only probes, write tokens also cover mutations, and admin tokens are required for local settings/profile writes plus identity tenant/user/group mutations, directory group sync, and SCIM provisioning. OIDC bearer JWTs are verified locally against the configured issuer, audience/client id, allowed algorithms, and trusted JWKS; URL/discovery refreshes are HTTPS-only by default, allow localhost HTTP for development, useOPENFORGE_OIDC_JWKS_TIMEOUT_SECONDS, and cache results withOPENFORGE_OIDC_JWKS_CACHE_SECONDS. Roles map fromOPENFORGE_OIDC_ROLE_CLAIM(defaultopenforge_role),role,roles,scope, orOPENFORGE_OIDC_DEFAULT_ROLE, and tenant ids map fromOPENFORGE_OIDC_TENANT_CLAIM(defaultopenforge_tenant). Matched tokens become sanitized local principals such aslocal-api-read,local-api-write,local-api-admin, or hashedexternal-oidc-*principals;/api/v1/system/authreports configured principals, the tenant catalog, identity-provider readiness, and session policy without returning token values or OIDC setting values, and authenticated responses includeX-OpenForge-Auth-PrincipalplusX-OpenForge-Auth-Tenant. Tenant-shared collection boards are readable across principals in the same tenant, while board edits and repository membership changes remain owner-only. The CLI supports bearer tokens through--token,OPENFORGE_API_TOKEN, and saved CLI profiles. The Settings page includes a browser-only API Access token profile, tenant/provider/session readiness, write-only API role-token controls, and an Identity Admin panel for managed tenant/principal CRUD, local or managed identity groups, and external directory group sync; saving a local API Admin Token also stores it for the current browser so the frontend remains authenticated after auth turns on. - Scheduled SCIM identity directory sync is disabled unless
SCIM_DIRECTORY_SYNC_ENABLED=true. ConfigureSCIM_DIRECTORY_SYNC_SOURCES_JSONas a JSON array, or{ "sources": [...] }, with entries such astenant_id,provider,source_ref,base_url, optionalgroups_path,sync_mode,prune_missing_members,archive_missing_groups,page_size,group_limit,member_limit, and eitherbearer_token_envor a directbearer_token; preferbearer_token_envso tokens stay out of settings payloads. Celery beat runssync-scim-directory-groupsdaily, and the optional Temporalidentity-directory-syncworkflow can run the same configured sources or an explicitinput.sourcesarray. - Live SCIM group push events can call
POST /api/v1/system/identity/groups/scim-provisionwith admin auth, a tenant/provider/source reference, anupsert,archive, ordeleteaction, and either a SCIM Group resource or group id. Upserts reuse the same directory sync metadata and member pruning rules; archive/delete events only affect groups already marked as managed by the same provider/source. - Live SCIM User push and PATCH events can call
POST /api/v1/system/identity/users/scim-provisionwith admin auth, an existing managed tenant, provider/source reference,upsert,patch,deactivate, ordeleteaction, a SCIM User resource or user id, optional PATCH operations, event id/type, and bounded event metadata. Deactivate/delete events only affect users already marked as managed by the same provider/source, so manual principals and the built-in local tenant are left alone. - SCIM protocol reads are available under
GET /api/v1/system/identity/scim/v2/.ServiceProviderConfig,ResourceTypes, andSchemasdescribe OpenForge's User/Group support;UsersandGroupsrequire an existing managedtenant_id, supportstartIndex/countpaging, and accept simple SCIMeq/cofilters joined byandover identifiers, display names, user names, emails, roles, active status, meta resource type, and group members. - Actor imports can now discover local manifests from a repository clone path. Set
Repository.clone_pathto an available checkout withPATCH /api/v1/repositories/{id}or the repository Setup tab, then callPOST /api/v1/actors/import/from-repositoryor use the Actor setup cockpit's manifest import action; OpenForge prefersopenforge.actor.json, falls back to.actor/actor.json, resolves relative JSON schema file references inside the clone, and still routes the result through review-only actor build evidence. - Launch planning is intentionally review-only. Actor execution is explicit and worker-backed:
POST /api/v1/actor-runs/{id}/executerequires sandbox confirmation, allow-level policy evaluation, passed build evidence, and a pinned Docker image before Celery queues the sandbox worker.SANDBOX_POLICY_PROFILEdefaults tostrict_local, can be persisted through Settings, and applies local policy defaults before actor/request policy overrides;reviewed_networkadds a network-egress confirmation requirement by default, whilecustomdelegates guardrails to the actor manifest or API request. - Build scan review is static by default.
/api/v1/system/health,/api/v1/system/capabilities, and Settings draft validation report optional Syft, OSV-Scanner, Grype, Gitleaks, and OPA binary availability as thescannerprovider without executing those tools. Local scanner binaries only run when an operator submitsrun_local_tools=true; OpenForge resolves known scanner executables, bounds timeout/output, and records skipped tool evidence when a source path or binary is unavailable. The default local scanner bundle is Syft, OSV-Scanner, Grype, Gitleaks, and OPA; Dagger validation is a separate operator-selected tool viascanner_tools=["dagger"], requires a Dagger module marker such asdagger.jsonor.dagger, and recordsdaggerValidationevidence in the scan manifest. Operators can call/actor-builds/{id}/scan-review/queueto dispatch the same review through the Celery actor worker; the build metadata records queued, running, completed, or failed worker state without requiring a schema migration. - The CLI distribution includes
examples/mcp/with a dependency-light stdio bridge, MCP server config skeleton, OpenForge agent manifest, and MCP-shaped read-only tool catalog generated from the current local agent tool descriptors. - GitHub evidence refreshes are dry-run/confirm gated. The manual API and CLI refresh path reuses the bounded GitHub release, issue, contributor, changelog, and optional authenticated Discussions collectors for existing GitHub repositories whose evidence is missing or stale; operators can opt into deeper release and issue history scans with
history_page_limit/--history-page-limit, while broad search and trending imports still avoid surprise provider calls. - Smart collection scheduled refresh is disabled by default. Set
SMART_COLLECTION_REFRESH_ENABLED=truefor the Celery beatrefresh-smart-collectionstask to rematerialize saved-search-backed smart boards daily in bounded batches; useSMART_COLLECTION_REFRESH_LIMITto cap each run. Manual smart-board refresh remains available through/api/v1/collections/{id}/smart-refresh. - Package intelligence remains local-only by default. Include
include_external_metadata=trueto query deps.dev, ecosyste.ms, npm registry, and PyPI registry metadata for freshness history, provider-failure telemetry, and registry-specific facets; fresh matched metadata also contributes to OpenForge Quality ranking and unified search explanations. Includeinclude_external_advisories=trueto query OSV for exact versioned PURLs. Scheduled package metadata refresh is disabled unlessPACKAGE_METADATA_REFRESH_ENABLED=true; manual refreshes require explicit API/CLI confirmation unless they are dry runs. The seed metadata-facet benchmark lives atbackend/app/evaluation/package_metadata_facets_benchmark.json,/api/v1/search/evaluations/package-metadata-facetsreports its provider-feed, repository-archetype, facet, and advisory-signal coverage,/api/v1/search/evaluations/package-metadata-facets/runspersists measured relevance run history,/api/v1/search/evaluations/package-metadata-facets/replay-fixtureidempotently seedsopenforge-evalrepositories plus package identities, dependencies, and advisory evidence for runtime replay smoke, and/api/v1/search/evaluations/package-metadata-facets/replay-runsexecutes current unified search ranking against those cases while recording observed rank, exact matched and missing metadata facets, advisory signals, and ranking explanation details. Replay cases only pass when both rank and exact expected evidence assertions pass. - Webhook delivery records are captured locally first. Outbound HTTP delivery only occurs through the explicit delivery send API or CLI confirmation, with target URL checks, sanitized bearer/header auth profiles sourced from the write-only webhook secret, fixed-window rate-limit profiles, attempt history, retry schedule metadata, and dead-letter exhaustion persisted. Send and signature-verification operations record bounded operator audit context, local policy binding, and signature verification history; API callers can pass
operator_contextor theX-OpenForge-Operator/X-OpenForge-Policy-Decision-Idheaders, while raw credential fields are rejected and authorization values are stored only as fingerprints. When local API auth is enabled, matched token principals are also persisted in webhook audit and policy binding metadata as principal id, tenant id, role, source, and token fingerprint. Captured HMAC signatures can be verified through the API, CLI, and actor cockpit without exposing the secret token.