Developer Quick Start¶
For evaluating Provisa without building from source, see the Quick Start — download the macOS, Windows, or Linux installer and run provisa start. (REQ-223, REQ-224, REQ-227)
This guide is for running Provisa from the repository — active development, debugging, or contributing.
Prerequisites¶
- Docker Desktop (running)
- Python 3.12+
- Node.js 20+
- Git
1. Clone and set up¶
setup.sh creates .venv/, installs all Python dependencies via pip install -e ".[dev]", and configures git hooks to .githooks/. [tool-verified: setup.sh lines 5–9]
2. Start everything¶
When it finishes starting up you'll see:
What it starts: [tool-verified: start-ui.sh]
- Docker Compose core services (
docker-compose.core.yml) — PostgreSQL, PgBouncer, Trino, Redis (REQ-055) - Docker Compose dev overlay (
docker-compose.dev.yml) — MinIO, Kafka, MongoDB, Elasticsearch, Neo4j, Fuseki, Debezium, Schema Registry (REQ-055) - Backend API on port 8001 (hot-reload on changes to
provisa/andconfig/) (REQ-618) - Vite UI dev server on port 3000 (HMR)
- OpenTelemetry tracing and Grafana at
http://localhost:3100. The observability stack is an opt-in docker-composeobservabilityprofile (OTel Collector, Prometheus, Tempo, Grafana), not on by default at the platform level;start-ui.shenables it as a dev-script convenience unless you pass--no-observability. (REQ-302, REQ-303, REQ-330)
Ctrl+C stops everything — backend, UI, and all Docker services — and reverts any config patches. (REQ-619)
Ctrl+R restarts only the backend (useful after a config change that hot-reload misses). (REQ-619)
Options¶
--no-observability — Disables distributed tracing. By default, start-ui.sh downloads the OpenTelemetry Java agent if not already present, patches Trino's jvm.config to load it, and starts the OTel collector, Prometheus, Tempo, and Grafana. Pass --no-observability to skip all of that. The jvm.config patch is reverted on Ctrl+C. [tool-verified: start-ui.sh lines 15, 67–82] (REQ-330)
--seed-data — Seeds Kafka with demo data after Docker services are healthy. Not run by default. [tool-verified: start-ui.sh lines 14, 173–178]
--keep-docker — Leaves Docker Compose services running after Ctrl+C instead of calling docker compose down. [tool-verified: start-ui.sh lines 16, 301–306] (REQ-619)
--reset-volumes — Wipes all Docker volumes and restarts with a clean state. Useful for Docker crash recovery. [tool-verified: start-ui.sh line 19] (REQ-170)
--demo — Starts additional demo data sources (PostgreSQL pet-store schema, OpenAPI petstore mock, SQLite, and a GraphQL remote). Seeds petstore users and orders automatically. [tool-verified: start-ui.sh lines 17, 55–171]
--source=<name> (start-ui-install.sh only, repeatable) — Provisions an optional data source alongside --demo. Each name maps to demo/sources/<name>/. The start calls demo/sources/provision.py up, which starts the source's compose.yml as its own Docker Compose project (provisa-demo-<name>), waits for its health check, and runs prime.py when the source has one to seed data. The start then writes a wrapper config at ${PROVISA_HOME:-~/.provisa}/demo/provisa-with-sources.yaml that includes the base config plus each source's fragment.yaml, and boots from it. [tool-verified: start-ui-install.sh (search SOURCES), demo/sources/provision.py] (REQ-1669)
The same provision.py is what the UI end-to-end suite calls to stand up these sources (under the provisa-e2e-<name> project prefix on its own ports), so the seed data a demo shows and the rows the suite asserts on are defined once. [tool-verified: provisa-ui/e2e/demo-source-containers.ts] (REQ-1671)
Under a Docker start (no --demo/--native) the coordinator is a container, so each source is joined to the core stack's network and registered at <name>:<container port>; under a native start it is registered at localhost:<published port>. A source whose demo/sources/<name>/engine file names an engine the start does not run is refused.
Shipped sources:
| Name | Port(s) | Notes |
|---|---|---|
neo4j |
HTTP 27474, Bolt 27687 | Two Cypher tables (adopter, adopter_referral); graph seeded by seed.cypher; tables registered from the fragment |
mongodb |
27117 | Source registered; product_reviews collection seeded by db/mongo-init.js; register tables by hand through Register Table |
redis |
26379 | Source registered; support_agent:* and agent_status:* hashes seeded by prime.py; each prefix registers as a table through Register Table (REQ-1675) |
cassandra |
29042 | Source registered; shelter_ops.intake_events seeded by prime.py (needs the cassandra extra); the keyspace registers as a schema through Register Table (REQ-1676) |
sparql |
23030 | Apache Jena Fuseki; source and one query-backed table (volunteer) registered from the fragment, graph seeded by prime.py; more tables through Register Table (query + Preview) (REQ-1683) |
prometheus |
29090 | Source registered; the server scrapes itself, so up and the prometheus_* metrics register as tables through Register Table (REQ-1689) |
elasticsearch |
29200 | Source and index mapping registered; support_tickets index seeded by prime.py; read over HTTP by the native engine (REQ-1672), through the connector on Trino |
splunk |
mgmt 8089, HEC 8088 | Source registered with token auth and disable_ssl_validation (the container's certificate is self-signed); an index, seven shelter-alert events and the shelter_alerts Data Model seeded by prime.py, which also mints the API token the fragment reads as PROVISA_DEMO_SPLUNK_TOKEN. Data Models register as tables through Register Table — on Trino through the splunk catalog, on every other engine through the bundled Calcite pgwire server the engine attaches (REQ-1694) |
chinook |
25433 | Postgres holding the snake_case Chinook subset Hasura's metadata sample tracks, seeded by prime.py from tests/fixtures/hasura_v2_t1_seed.sql; source registered from the fragment, and the source a Hasura v2 import of tests/fixtures/hasura_v2_t1_metadata.json lands on (REQ-1687) |
--idp=basic|firebase — Enables an identity provider for auth. Without this flag, the backend runs with no auth provider and all requests are treated as admin. [tool-verified: start-ui.sh line 18; provisa/auth/wiring.py lines 57–60; provisa/auth/middleware.py lines 57–68] (REQ-120, REQ-124)
3. Connect a data source¶
Provisa reads configuration from config/. Add a source file — for example config/sources/my-db.yaml:
sources:
- id: my-pg
type: postgresql
host: localhost
port: 5432
database: mydb
username: myuser
password: ${MY_DB_PASSWORD}
tables:
- id: orders
publish: true
columns:
- name: id
- name: amount
- name: region
- name: customer_id
Set the env var and the backend will pick it up on next reload:
See docs/configuration.md for the full YAML reference and all supported source types.
4. Run your first query¶
# GraphQL
curl -s -X POST http://localhost:8001/data/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ orders { id amount region } }"}' | jq
# SQL — use the /data/sql endpoint
curl -s -X POST http://localhost:8001/data/sql \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT id, amount, region FROM orders LIMIT 5"}' | jq
No auth is required when no auth section is present in config/provisa.yaml (the default in dev). The role defaults to admin. [tool-verified: provisa/auth/wiring.py lines 57–60; provisa/auth/middleware.py lines 56–68] (REQ-120, REQ-267)
5. Open the UI¶
Open http://localhost:3000 in a browser.
The nav bar has four top-level menus: [tool-verified: provisa-ui/src/components/NavBar.tsx lines 39–80]
- Explore — Schema Explorer (
/schema), GraphQL editor (/query), Cypher editor (/graph), SQL editor (/sql) - Model — Views and Commands
- Security — Row-level security and column masking policies (REQ-038, REQ-041)
- Admin — Overview, domains, cache, scheduled tasks, system health, observability, users, orgs, roles
The admin GraphQL API is at http://localhost:8001/admin/graphql. [tool-verified: provisa/api/app.py line 3389] (REQ-620)
Troubleshooting¶
Backend won't start — check .logs/server.log. Most common cause is a missing env var or a port conflict on 8001. [tool-verified: start-ui.sh line 202] (REQ-618)
Docker services not healthy — run docker compose -f docker-compose.core.yml -f docker-compose.dev.yml ps to see which service is stuck. The federation engine takes ~30 seconds on first start. (REQ-055)
Port conflict on 3000 or 8001 — start-ui.sh kills stale processes on those ports before starting. If something else owns the port, stop it manually first. [tool-verified: start-ui.sh lines 197–199] (REQ-619)
Fresh start — stop the script, then run ./start-ui.sh --reset-volumes to wipe all volumes and restart. [tool-verified: start-ui.sh line 19] (REQ-170)
Next steps¶
| Goal | Doc |
|---|---|
| Full YAML configuration reference | configuration.md |
| Row-level security, column masking, auth | security.md |
| All supported source types | sources.md |
| Real-time subscriptions | subscriptions.md |
| JDBC, BI tools, Arrow Flight, Apollo Federation | integrations.md |
| Python client | python-client.md |
| Production deployment | deployment.md |