API and Dashboard for IB-Oxford longitudinal questionnaire data.
This project has two components:
- API (
/api) — a read-only FastAPI service that provides suppression-safe access to student questionnaire data - Dashboard (
/dashboard) — a SvelteKit app for authenticated users to view and query data via interactive charts
In development, both are served through an nginx proxy:
- Dashboard →
http://localhost:5173 - API →
http://localhost:5173/api
# Set a strong JWT secret
export IB_OX_SECRET_KEY="your-strong-secret-here"
# Place your data file (CSV or Parquet) in a Docker volume or bind-mount
# The API defaults to /data/data.csv inside the container
# Start everything
docker compose up --build
# Create the first admin user (in a separate terminal)
docker compose exec api ib-ox-api users create --admin adminThe dashboard will be available at http://localhost:5173.
| Variable | Default | Description |
|---|---|---|
IB_OX_DATA_PATH |
data/data.csv |
Path to the CSV or Parquet data file |
IB_OX_DATA_REFRESH_HOURS |
24 |
How often to reload data from disk |
IB_OX_MIN_N |
5 |
Minimum distinct student count for suppression |
IB_OX_SECRET_KEY |
(insecure default) | JWT signing secret — must be set in production |
IB_OX_ALGORITHM |
HS256 |
JWT algorithm |
IB_OX_ACCESS_TOKEN_EXPIRE_MINUTES |
480 |
Token lifetime (8 hours) |
IB_OX_DATABASE_URL |
sqlite:///./auth.db |
SQLAlchemy database URL |
IB_OX_CORS_ORIGINS |
["*"] |
JSON list of allowed CORS origins |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/health |
— | Health check |
POST |
/auth/login |
— | Login (returns JWT) |
GET |
/data/columns |
User | List available column names |
POST |
/query/frequency |
User | Frequency table query |
POST |
/query/means |
User | Means table query |
GET |
/admin/users |
Admin | List users |
POST |
/admin/users |
Admin | Create user |
PUT |
/admin/users/{id} |
Admin | Update user |
DELETE |
/admin/users/{id} |
Admin | Delete user |
GET |
/admin/me |
User | Current user info |
Interactive documentation is available at /docs (Swagger UI) and /redoc.
# Initialise the database
ib-ox-api db init
# List users
ib-ox-api users list
# Create a regular user
ib-ox-api users create alice
# Create an admin user
ib-ox-api users create --admin bob
# Update a user
ib-ox-api users update alice --scope '{"filters": {"school": ["Greenwood"]}}'
# Delete a user
ib-ox-api users delete aliceN is counted as distinct students (uid), not rows. Any frequency or means cell where the contributing student count is less than IB_OX_MIN_N is suppressed (set to empty in the CSV output) and recorded in the suppressions field of the response.
Query columns are restricted to a whitelist to prevent data leakage:
group_by/value_column(frequency):school,yearGroup,class,sex,ethnicity,wave,d_city,d_countryvalue_columns(means):phq9_1–phq9_9,d_age
The SvelteKit dashboard provides:
- Login — JWT-based authentication
- Home — pre-built overview charts
- Query Builder — custom frequency and means queries
- Admin — user CRUD (admin users only)
cd api
pip install -e ".[test]"
# Initialise DB
ib-ox-api db init
# Start development server
uvicorn ib_ox_api.main:app --reload
# Run tests
pytestcd dashboard
npm install
npm run devSee terraform/ for infrastructure definitions (ECS Fargate + ALB + ECR + EFS).
# Deploy version 0.1.0 (base semver must match API version in pyproject.toml)
export IB_OX_SECRET_KEY="your-production-secret"
./deploy.sh 0.1.0
# Or with a pre-release suffix
./deploy.sh 0.1.0-beta1The deploy.sh script:
- Checks required tools (
aws,terraform,docker,curl,jq,python3) - Validates the deploy version against the API version
- Authenticates with AWS SSO
- Creates an S3 bucket for Terraform state + deploy lockfile
- Resolves lockfile conflicts interactively
- Builds and pushes Docker images to ECR (immutable tags — no
latest) - Runs
terraform applyinteractively - Updates the remote lockfile
| Variable | Description |
|---|---|
IB_OX_SECRET_KEY |
JWT secret for production |
AWS_REGION |
AWS region (default: eu-west-2) |
See terraform/variables.tf for all available variables. Key ones:
| Variable | Description |
|---|---|
image_tag |
Docker image tag (set by deploy.sh) |
api_secret_key |
JWT secret (set by deploy.sh from env) |
aws_region |
AWS region |
api_min_n |
Minimum N for suppression (default: 5) |
certificate_arn |
ACM certificate ARN for HTTPS (optional) |
Data must be in the format produced by ib-ox-dummies — a student×wave long format with columns including:
uid— student identifier (used for N counting in suppression)wave— survey wave numberschool,yearGroup,class— school structuresex,ethnicity— demographicsd_age,d_city,d_country— derived/custom fields- Questionnaire items (e.g.
phq9_1–phq9_9)
Generate sample data:
ib_ox_dummies --config examples/default_model.toml --seed 42 --output csv > data/data.csv