LTI Dev FRAPI Runtime

This note describes how to deploy and use the LTI dev FRAPI health integration.

Runtime Configuration

lti-dev and lti-dev-cron must carry these non-secret runtime values. Configure them through the runtime-config path after explicit approval; the normal Deploy LTI dev workflow does not manage FRAPI runtime configuration. The service and cron job must also be attached to the Cloud SQL instance named in FRAPI_DB_HOST; an env var alone is not enough for /cloudsql/... sockets.

Name Value
FRAPI_BASE_URL https://frapi.citizengo.org
FRAPI_HEALTH_URL Optional; leave unset unless the health endpoint moves
FRAPI_DB_HOST Optional direct Cloud SQL socket, e.g. /cloudsql/lucid-sol-192917:europe-west1:cgo-sql-1
FRAPI_DB_PORT 3306
FRAPI_DB_NAME Default schema, currently frapi_test; report queries may explicitly read frapi_cgo
FRAPI_DB_USER Scoped read-only LTI database user
FRAPI_DB_PASSWORD Secret Manager binding for the scoped read-only user
FRAPI_DB_CONNECT_TIMEOUT Connection and short-query timeout in seconds; default 10
FRAPI_DB_READ_TIMEOUT Month-scale report read timeout in seconds; default 60

When FRAPI_HEALTH_URL is empty, LTI derives the probe URL as https://frapi.citizengo.org/v1/health/.

When all FRAPI_DB_* values are configured, LTI payment gateway reports and donation verification use direct MySQL access. If any required direct database value is missing, LTI falls back to the existing SSH_* FRAPI settings. Keep the SSH fallback until direct reads are fully exercised across the remaining legacy flows.

The longer FRAPI_DB_READ_TIMEOUT is selected only by month-scale payment gateway and rejection reports. Express donation verification and other short reads keep the 10-second connection timeout as their read safety bound. Writes also retain the short connection-timeout budget. Direct SQL NULL values are returned as the literal string NULL, matching the legacy mysql -B transport and preventing nullable stages from being folded into the empty-string PayPal rejection bucket.

For lti-dev, the direct database user should be read-only: SELECT on frapi_test.* and frapi_cgo.*, with no cloudsqlsuperuser role and no write grants.

Deploy To LTI Dev

Use the Deploy LTI dev GitHub Actions workflow:

  1. Open GitHub Actions for CitizenGO-Org/soft-live_testing_interface.
  2. Choose Deploy LTI dev.
  3. Run the workflow with:
  4. deploy_branch: the branch to deploy.
  5. Wait for the workflow to finish.

The workflow deploys a no-traffic candidate revision, checks /system_health, verifies lti-dev-cron report routing, promotes the candidate revision to 100% traffic, and then updates the lti-dev-cron image. Routine deploys do not run FRAPI, Salesforce, or Agent API gates and do not mutate cron runtime environment variables.

Use The FRAPI Health Endpoint

The deployed endpoint is:

/system_health/frapi

On Cloud Run, the endpoint requires the configured health-check identity. To check it manually, mint the identity token as that service account or impersonate that service account from an authenticated Google Cloud CLI session:

SERVICE_URL="$(gcloud run services describe lti-dev \
  --project lucid-sol-192917 \
  --region europe-west1 \
  --format='value(status.url)')"

HEALTH_CHECK_IDENTITY_EMAIL="$(gcloud run services describe lti-dev \
  --project lucid-sol-192917 \
  --region europe-west1 \
  --format=json \
  | jq -r '.spec.template.spec.containers[0].env[]? | select(.name == "HEALTH_CHECK_IDENTITY_EMAIL") | .value // empty')"

TOKEN="$(gcloud auth print-identity-token \
  --audiences="${SERVICE_URL}" \
  --impersonate-service-account="${HEALTH_CHECK_IDENTITY_EMAIL}")"

curl --fail --show-error --silent \
  --header "Authorization: Bearer ${TOKEN}" \
  "${SERVICE_URL}/system_health/frapi"

A healthy response has this shape:

{
  "ok": true,
  "health_url": "https://frapi.citizengo.org/v1/health/",
  "cgo_db_status": "healthy",
  "frapi_db_status": "healthy",
  "php_version": "8.3.31",
  "timestamp": "2026-07-02T00:35:17+00:00"
}

If FRAPI is unreachable or reports an unhealthy database status, LTI returns 503 with only a sanitized error type.

Local Use

For local development, set one of the FRAPI HTTP settings in the active local settings module. If that module reads environment variables, export the base URL before starting Django:

export FRAPI_BASE_URL=https://frapi.citizengo.org
python manage.py runserver

Then open:

http://127.0.0.1:8000/system_health/frapi

Local debug access does not require the Cloud Run identity token.