Skip to content

Monitoring

Monitoring illustration

The SCF Controls Platform includes a built-in monitoring dashboard that helps you understand system health, track usage, and monitor compliance progress. This guide covers accessing and interpreting the monitoring features.

GET /api/database/stats responds with:

SectionInformation
Version InformationPlatform version, API version, catalog version
Health StatusOverall system health (Healthy/Unhealthy)
Database TablesRecord counts for all tables
Control StatisticsSelected, implemented, at-risk counts
User & Task StatisticsActive users, pending/completed/overdue tasks
By Implementation StatusControls grouped by status
By Maturity LevelControls grouped by maturity
Tasks By Status/TypeTask breakdown
Recent ActivityLast update timestamps
MetricWhat It Tells You
Health StatusOverall system health
At Risk ControlsControls needing attention
Overdue TasksTasks past their due date
Pending TasksWork queue size
Active UsersCurrent user engagement
Total RecordsDatabase size over time

The dashboard shows version details useful for support:

Platform: v1.0.0 (API v1.0)
Catalog: SCF 2025.4 (1,451 controls, 300+ evidence requirements)

StatusMeaningAction
HealthyAll systems operating normallyNone needed
UnhealthyThere’s a problem with the platformContact support
  • Daily — Quick glance to ensure systems are running
  • Before critical work — Verify health before bulk operations
  • When issues occur — First step in troubleshooting

Separate from /api/database/stats above, the backend serves an unauthenticated GET /health. It is what the container healthcheck and any load balancer in front of the platform poll, so it takes no credentials and answers in a few milliseconds.

Terminal window
curl -s http://localhost:8000/health | jq
{
"status": "healthy",
"service": "cg-scf-backend",
"version": "1.0.0",
"components": {
"redis": { "status": "healthy", "redis_version": "7.4.6", "connected_clients": "unknown" },
"evidence_storage": { "status": "ok", "source": "bundled", "provider": "minio" }
}
}

It reports the platform-wide effective storage — the store an organisation with no configuration of its own falls back to. It says nothing about any individual organisation’s store, which is per-organisation state and not a property of this process.

statussourceWhat it meansDoes it degrade /health?
okbundledThe object store this installer provisioned into the stackNo
okplatformA platform-wide store an operator configured in the appNo
oklegacy_envNo platform configuration row; the process environment is in forceNo
unconfigurednoneThis installation has no platform store at all. Organisations that have configured their own are unaffected and still workNo — see below
errornoneThe configuration could not be resolved, an undecryptable secret being the case that actually happens. An error field carries the exception class nameYes, the overall status becomes degraded

Two deliberate omissions. No bucket, endpoint or credential appears in the response: the endpoint is unauthenticated and reachable by anyone who can reach the port, and a bucket name is an asset inventory. Which kind of store, and whether it resolves, is all this can safely say.

It never dials the store. A round trip per poll would turn a healthcheck into a traffic generator against a customer’s object store — Docker polls this every 30 seconds for the life of the container — and one network blip would flap container health and restart a healthy backend. The answer comes from the resolver’s own cached snapshot. For a real reachability answer, use the administrator-triggered connection test (POST .../evidence-storage/test, see Quick Reference), which dials the store and has somebody to report the failure to.

unconfigured does not degrade the service, and this is the point of it. An installation made with --no-minio is in that state by design and is perfectly healthy; so is one whose organisations have each brought their own store. Marking it degraded would take a working platform out of load balancer rotation for a condition only an administrator can resolve.


The dashboard shows record counts for each table:

TableDescription
OrganisationsNumber of organisations configured
Scoped ControlsControls in scope for compliance
Evidence TrackingEvidence items being tracked
UsersRegistered user accounts
Organisation MembersUser-organisation associations
AssignmentsControl/evidence assignments
CommentsDiscussion comments
Evidence TasksEvidence collection tasks
NotificationsSystem notifications
Total RecordsSum across all tables
  • Growing steadily — Normal as you add more data
  • Sudden increase — May indicate bulk import
  • Sudden decrease — Check if backup was restored
  • Very high counts — May need data cleanup

The dashboard shows controls by implementation status:

StatusWhat to Monitor
ImplementedShould grow over time
In ProgressTrack to ensure progress
At RiskInvestigate and resolve
Not StartedPlan implementation work

Track control maturity levels:

LevelHealthy Distribution
InitialShould decrease over time
DevelopingCommon for newer controls
DefinedTarget for most controls
ManagedIndicates mature programme
OptimisedBest-in-class controls

MetricWhat It Means
Pending TasksWork waiting to be started
In ProgressActive work items
CompletedFinished tasks
OverdueTasks past due date
  • Overdue: 0-5% — Keep overdue tasks minimal
  • Pending: < 50% — Most tasks should be in progress or completed
  • Completed: Growing — Shows progress over time

Track user engagement:

MetricMeaning
Total UsersAll registered users
Active UsersUsers who have logged in recently
  • High activity — Good engagement with the platform
  • Low activity — May need training or outreach
  • Sudden changes — Investigate cause

Window assessments run on the evidence_window Celery queue: on upload and webhook ingest (after a debounce, WINDOW_ASSESSMENT_INGEST_DEBOUNCE_SECONDS), from the nightly sweep at 04:00 UTC, and on request. Three checks tell you the pipeline is alive without reading worker logs:

Terminal window
# Verdicts waiting for a human, worst first (window tier is the primary surface)
curl -sS -H "X-API-Key: $API_KEY" \
"http://localhost:8000/api/organizations/$ORG_ID/evidence/assessment/review-queue?tier=window" | jq '.total'
# Window status counts — a growing "processing" or "error" count means the worker is not draining the queue
curl -sS -H "X-API-Key: $API_KEY" \
"http://localhost:8000/api/organizations/$ORG_ID/evidence/window-assessments/summary" | jq
# The flags the backend is actually running with (compare with the frontend's console warning, if any)
curl -sS http://localhost:8000/api/features

Every confirm or override appends a row to evidence_window_assessment_versions (append-only, enforced by a database trigger), so GET …/window-assessments/{id}/versions is the audit trail for a verdict. Both version tables are covered by scripts/backup.sh.

  • Call GET /api/database/stats and verify "status": "healthy"
  • Check at-risk and overdue counts
  • Review any unexpected changes in record counts
  • Review implementation progress trends
  • Check task completion rates
  • Review user activity levels
  • Verify backup is recent
  • Review maturity level distribution
  • Analyse control implementation velocity
  • Check data growth trends
  • Review and archive old data if needed

Normal performance expectations:

ActionExpected Time
Page load< 2 seconds
Search results< 1 second
Save operations< 2 seconds
Backup download5-30 seconds depending on data size
  1. Check your internet connection
  2. Clear browser cache — Hard refresh with Ctrl+Shift+R
  3. Try a different browser — To rule out browser issues
  4. Check platform health — May be a temporary issue
  5. Contact support — If issues persist

The platform provides visual indicators for:

ConditionIndicator
At-risk controlsBadge count in dashboard
Overdue tasksBadge count in tasks section
Sync issuesStatus indicator in header
  • Check dashboard daily — Review key metrics
  • Enable email notifications — Get alerts for assignments and due dates
  • Set calendar reminders — Schedule regular review sessions

  1. Hard refresh the page (Ctrl+Shift+R)
  2. Check your internet connection
  3. Try signing out and back in
  4. Contact support if issue persists
  1. Click refresh to get latest data
  2. Check if filters are affecting the view
  3. Verify you’re looking at the correct organisation
  4. Contact support if numbers seem incorrect
  1. Note any error messages displayed
  2. Try refreshing the page
  3. Check if other features are working
  4. Contact support with details of the issue