Everything you need to run your first rehearsal, gate a GitLab pipeline on it, and run FutureFault yourself.
ledgerly-mr-42 merge request.Want to look around first? Explore the public demo as a guest, no account needed.
| Concept | What it means |
|---|---|
| Rehearsal | An eleven-step run for one change: intake, impact, hypotheses, experiments, evidence, remediation, verification, packaging, staging, validation, governance. |
| Hypothesis | A falsifiable failure claim that cites the lines that triggered it, with ordinal severity and likelihood (never a probability). |
| Scenario | An approved, sandboxed experiment registered by ID. Hypotheses without an approved scenario are recorded as not tested. |
| Verification | Re-running the original experiment, new regression tests, the full suite and a security rescan in a fresh copy of the patched tree. |
| Policy | Twelve deterministic rules in a profile (development or release). Each decision stores the profile’s SHA-256 digest. |
| Evidence bundle | A self-validating JSON export of every record, edge and digest behind a decision. |
Store a workspace API key as a masked CI/CD variable named FUTUREFAULT_API_KEY, then start rehearsals from any job:
rehearse:
stage: test
image: curlimages/curl:8.10.1
rules:
- if: $CI_MERGE_REQUEST_IID
script:
- >
curl --fail-with-body -sS -X POST "$FUTUREFAULT_URL/api/runs"
-H "Authorization: Bearer $FUTUREFAULT_API_KEY"
-H "Content-Type: application/json"
-d "{\"change_set_id\":\"ledgerly-mr-42\",\"remediation\":\"catalog\",
\"source\":{\"provider\":\"gitlab\",\"sha\":\"$CI_COMMIT_SHA\",\"number\":$CI_MERGE_REQUEST_IID}}"With source set and the GitLab integration connected, the rehearsal reports back on its own: a futurefault/release commit status (running, then success or failed) and a comment on the merge request with the decision and a link to the evidence. Use "provider":"github" with a pull request number for GitHub.
To make the pipeline itself the gate, run the CLI in the job. It exits non-zero unless the policy allows promotion, and writes the evidence bundle as an artifact:
rehearse:release:
image: python:3.12-slim
script:
- pip install -e services/api
- python -m futurefault rehearse --change-set ledgerly-mr-42 --profile release
--trigger gitlab-ci --ci-status success --bundle-out evidence.json
artifacts:
paths: [evidence.json]The repository ships a five-agent custom flow in .gitlab/duo/flows/futurefault-release-rehearsal.yml: impact analyst → hypothesis generator → experiment coordinator → remediation agent → governance reporter.
.gitlab/duo/agent-config.yml to the default branch.Agents write hypotheses as validated data, run only the bounded CLI, open remediation merge requests, and post the policy decision verbatim. The remediation MR’s own pipeline re-verifies the fix; an agent’s claim is never used as evidence.
The full, searchable API reference has code samples and an in-browser console (raw schema: /api/openapi.json). Authenticate with a session cookie (browser) or Authorization: Bearer ff_… (workspace API key). Common endpoints:
| Method | Path | Purpose |
|---|---|---|
| POST | /api/runs | Start a rehearsal |
| GET | /api/runs/{id} | Run state and steps |
| POST | /api/runs/{id}/rerun | Repeat with the same configuration |
| GET | /api/runs/{id}/bundle | Download the evidence bundle |
| GET | /api/overview | Workspace dashboard data |
| GET | /api/workspace/usage | Plan limits and current usage |
FutureFault is one container: API, web app and rehearsal worker.
docker build -f deploy/docker/Dockerfile -t futurefault .
docker run -p 8080:8080 -v futurefault-data:/data futurefaultRender + Supabase is the quickest hosted setup: Render runs the container from render.yaml, Supabase Postgres keeps every record and a private Supabase Storage bucket keeps artifacts, so restarts lose nothing that is finished. Create a Blueprint from the repository and paste three values from Supabase. The step-by-step guide is docs/deploy-render-supabase.md.
| Variable | Purpose |
|---|---|
FF_DATA_DIR | Local working files, and the SQLite database when no Postgres URL is set |
FF_DATABASE_URL | Postgres (for example Supabase) instead of SQLite. Tables live in the private FF_DATABASE_SCHEMA (default futurefault), never public |
FF_SUPABASE_URL, FF_SUPABASE_SERVICE_KEY | Keep artifacts in a private Supabase Storage bucket, restored and digest-checked on read |
FF_PUBLIC_URL | Base URL for links in emails and the OAuth callback |
FF_COOKIE_SECURE | Set to 1 behind HTTPS |
FF_SECRET_KEY | 32-byte base64 key that encrypts integration credentials (AES-256-GCM). Required in production |
FF_RESEND_API_KEY or FF_SMTP_HOST, FF_SMTP_USER, FF_SMTP_PASSWORD; FF_MAIL_FROM | Email delivery for invites, password resets and run alerts |
FF_STRIPE_SECRET_KEY, FF_STRIPE_WEBHOOK_SECRET, FF_STRIPE_PRICE_TEAM | Self-serve upgrades with Stripe Checkout and the customer portal (webhook at /api/billing/webhook) |
FF_OIDC_ISSUER, FF_OIDC_CLIENT_ID, FF_OIDC_CLIENT_SECRET, FF_OIDC_NAME, FF_OIDC_ALLOWED_DOMAINS | Single sign-on with any OpenID Connect provider (PKCE, verified emails only) |
FF_SENTRY_DSN | Error reporting to Sentry, without personal data |
FF_ALLOW_PRIVATE_INTEGRATIONS | Let integrations reach self-managed GitLab or Jira on a private network |
FF_GITLAB_OAUTH_CLIENT_ID, FF_GITLAB_OAUTH_CLIENT_SECRET | Enable Sign in with GitLab |
FF_API_TOKEN | Operator token for metrics and cross-workspace automation |
FF_ALLOW_SIGNUP, FF_ALLOW_GUEST | Control self-service sign-up and guest access |