FedRAMP Compliance Tracker — from install to a live control scorecard¶
Install app-fedramp-tracker, get a 13-family NIST 800-53 Rev 5 scorecard with worst-child rollup and FedRAMP-aligned status rules, plus an 8-tile ADX compliance dashboard over your Sentinel-backed cyber medallion. ~20 minutes.
What you end up with
Two workspace items: NIST 800-53 Control Families — FedRAMP Moderate (scorecard) and Compliance Events Dashboard (KQL dashboard). The scorecard is fully live on Loom's own goal store — check-ins, history, rollups, status colouring — with no Power BI or Fabric required.
Prerequisites¶
| You need | Why | If it is missing |
|---|---|---|
| A Loom workspace | Apps install into a workspace | Tutorial 01 — First workspace |
LOOM_KUSTO_CLUSTER_URI set | The dashboard tiles need a queryable ADX data source | The dashboard installs with a remediation gate naming the variable |
A cyber medallion in ADX (bronze.stg_sentinel_alerts, silver.fct_security_alerts, silver.dim_mitre_techniques, gold.rpt_compliance_posture) | The eight tiles query these tables by name | The app now creates them — see below |
This app creates the cyber tables (changed 2026-09, #3537)
The bundle ships a Compliance Events kql-database item alongside the dashboard. Installing the app provisions the ADX database and all four medallion tables, seeded with sample rows, so the dashboard renders on a fresh install instead of returning a Kusto "table not found" per tile. Re-ingest from your own Sentinel workspace (or repoint the tables at the Cybersecurity (MITRE ATT&CK) example medallion in examples/cybersecurity/domains/{bronze,silver,gold}) to make it live.
The dashboard's database is resolved from the kql-database item this same install provisions — the deterministic safeAdxDatabaseName(displayName) mapping kql-db.ts creates the ARM database with — then from content.database on the bundle. It no longer falls back to LOOM_KUSTO_DEFAULT_DB or to a slug of the dashboard's own name: both bound the tiles to a database that does not hold their tables, and reported created while doing it. A dashboard that can resolve neither now returns an honest remediation naming what to add.
ADX has no schemas, so a dotted name is a single table name and the tile KQL brackets it — ['bronze.stg_sentinel_alerts']. An unbracketed bronze.stg_sentinel_alerts does not parse as a table reference.
1. Install the app¶
- Left nav → Apps → FedRAMP Compliance Tracker (
/apps/app-fedramp-tracker). - Install into workspace → pick the workspace, optionally a folder (e.g.
Compliance). - Leave Deploy artifacts to live Azure services On and Compute on Shared.
- Install. The route returns
202 { jobId }; the dialog polls/api/apps/install-jobs/<jobId>and renders the per-item provisioning report.
2. What gets provisioned¶
| Item | Provisioner | Real backend | Notes |
|---|---|---|---|
NIST 800-53 Control Families — FedRAMP Moderate (scorecard) | none — Cosmos-only | Loom's own goal store | The scorecard editor is fully functional against it (goals, check-ins, history, rollups) |
Compliance Events Dashboard (kql-dashboard) | kqlDashboardProvisioner | Confirms the ADX data source (LOOM_KUSTO_CLUSTER_URI + database); the tiles run live KQL via /api/items/kql-dashboard/<id>?run=1 | Azure-native by default; a Fabric Real-Time Dashboard is opt-in only (LOOM_DASHBOARD_BACKEND=fabric and a bound workspace) |
The dashboard row in the install report reads Loom-native KQL dashboard ready: 8/8 tile(s) bound to ADX <cluster> / <db> when it succeeds.
3. Seeded data — read this carefully¶
The scorecard installs with sample mid-ATO maturity values, clearly labelled as such in the app intro and in every goal description:
| Family | Sample % controls implemented | Family | Sample |
|---|---|---|---|
| AC — Access Control | 92 | RA — Risk Assessment | 79 |
| AU — Audit and Accountability | 88 | SA — System & Services Acquisition | 82 |
| AT — Awareness and Training | 95 | SC — System & Comms Protection | 87 |
| CM — Configuration Management | 84 | SI — System & Information Integrity | 89 |
| CP — Contingency Planning | 81 | SR — Supply Chain Risk Management | 78 |
| IA — Identification & Authentication | 90 | MP — Media Protection | 93 |
| IR — Incident Response | 86 |
Replace these with live evidence (your CMDB + Sentinel workspace + the gold.rpt_compliance_posture table) before anyone treats the number as an ATO artifact. Step 4 shows how.
The rollup semantic¶
NIST 800-53 Overall Compliance is the parent of all thirteen families, with rollupMethod: 'min' — worst-child aggregation. The parent reflects the weakest family, which is the standard compliance-scorecard semantic (you are not compliant on average; you are compliant at your weakest control family). Status rules, applied at both parent and family level:
>= 90→ On track>= 75→ At risk- otherwise → Behind
With the seeded values the parent lands on the SR family (78) → At risk.
The default baseline is FedRAMP Moderate. Flip to High by setting LOOM_FEDRAMP_BASELINE=high.
4. First meaningful task — record a real check-in and watch the rollup move¶
- Open
NIST 800-53 Control Families — FedRAMP Moderate. The left tree lists scorecards; the main pane shows the goal hierarchy with current / target / status / owner / due. - Select the SR — Supply Chain Risk Management goal (the weakest child, 78).
- Ribbon → Goal group → Check in. Record the real value from your evidence source, a status, and a note. Check-ins are versioned — History on the same ribbon group shows the full trail, which is the audit artifact an assessor asks for.
- Save, then look at NIST 800-53 Overall Compliance. Because the parent rolls up with Min (Worst child), the overall number tracks whichever family is now lowest — not the one you just edited, unless it is still the worst.
- Ribbon → Rollup group → Configure rollups to inspect or change the aggregation and the status-rule ladder per goal (operator, threshold, value vs % of target, resulting status, and the "otherwise" fallback).
- Optional, if you run a Power BI / AAS semantic model: Bind metric connects a goal's value to a live DAX measure so check-ins stop being manual. This requires the Power BI backend enabled in Admin → Runtime configuration and a selected workspace — it is an opt-in leg, not the default path.
Then read the dashboard¶
Open Compliance Events Dashboard. Eight tiles, all real KQL:
- Total alerts (last 24h) — card,
dcount(alert_id)overbronze.stg_sentinel_alerts. - Open high/critical incidents — card,
severity_level >= 3and status inNew / InProgress / Investigating. - Mean time to detect (minutes) — card,
datetime_diffbetweenprocessed_atandtime_generated. - Alerts by MITRE technique (top 15, 30d) — bar, joined to
silver.dim_mitre_techniques. - Alert trend — daily (30d, severity stacked) — timechart.
- Top 10 risk users (30d) — table,
mv-expandoveraccount_entities. - Compliance posture by NIST control family (30d) — pie over
gold.rpt_compliance_posture. - Top 10 remediation priorities (30d) — table, ordered by
remediation_priority.
5. Verify it worked¶
- Install dialog: the dashboard row is
createdand names the resolved cluster + database. - Scorecard editor: 14 goals render (1 parent + 13 families) with statuses that match the ladder above; a check-in you record appears in History.
- Dashboard: tiles 1–3 return numeric cards. If they return a Kusto "table not found", the cyber medallion is missing — that is the documented caveat, not a broken app.
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
Dashboard row = remediation, "No ADX cluster configured" | LOOM_KUSTO_CLUSTER_URI unset | Set it to the cluster URI (e.g. https://<adx>.<region>.kusto.<suffix>), then Retry the row |
| Every tile errors "could not resolve table" | The cyber medallion tables are not in the resolved database | Build them from examples/cybersecurity/domains/** into LOOM_KUSTO_DEFAULT_DB, or edit the tile KQL to point at your own table names |
| Tiles 7–8 error but 1–6 work | gold.rpt_compliance_posture is missing | It is the gold-layer report table; create it from examples/cybersecurity/domains/gold/rpt_compliance_posture.sql |
| Scorecard shows "No scorecards yet" | You are looking at the Power BI-backed list with no workspace selected | The Loom-native goals load without a Power BI workspace; refresh the editor. Power BI is opt-in |
| Parent number does not change after a check-in | Worst-child rollup — another family is now the minimum | Working as designed; check the family list for the new minimum |
Cleanup¶
Delete both items from the workspace tree, or delete the workspace. Nothing external is created by this app — the ADX tables it reads were not created by it and are not removed with it.
What's next¶
- Cybersecurity (MITRE ATT&CK) example — build the medallion the dashboard reads.
- Data Steward Console — the governance sign-off half of the same compliance story.
- Workspace Monitoring — platform telemetry for the AU (audit) family evidence.