← Design · c128

data-inventory.md

c128 data inventory: what qdash shows today, and how time works on it

As of: 2026-11-03. Taken from qcontrol/crates/qdash/ui on feat/new-pages, the layer and the design site. Purpose: reports put together what the dashboard already shows, so this file maps each candidate report section to its source, its time basis and the gaps.

How time works in qdash today

  • One global window. composables/shell/useGlobalFilter.ts owns ?period= and shows it as the when: pill. The values, from filter-keys.ts PERIOD_OPTIONS, are all · 24h · 7d · 30d, and the default is 7d.
  • Presets only. There is no from–to or custom range in the UI. On the backend, web.rs period_span maps only 24h, 7d and 30d, and treats anything else as all time.
  • Windows are cut back from fleet_anchor, the newest observed timestamp, not from the wall clock.
  • Not every page uses the window:
    Window usePages
    Follow the pillfindings, dlp, endpoints, users and teams, every inventory listing, activity, cost, home /
    Always all-timeposture, compliance, policies, alerts, identity, integrations, every detail page except users and teams
    Fixed windows that ignore the pill/api/trends (90 days, daily), /api/stats cost and tokens (24h), the people pages' intensity feed (30d)

    So by default Compliance (all-time) and Findings (7d) already show different counts.
  • History sources. Only two exist:
    • /api/trends: a 90-day daily series of posture, spend, egress, findings and coverage {discovered, monitored, pct}.
    • /api/costs: a daily spend series across the window.

    Everything else is either a total for the window or the current state. There is no snapshot store, so nothing can say what the inventory looked like on date X.
  • Layer.
    • Presets: Filter (timeframe* props), UxTabGroup, UxSelectInline.
    • Time helpers: utils/time.ts timeFrameToStart(tf, previous), the only prior-period helper.
    • History: DataHistoryGraph draws daily history and hatches gaps where days are missing.
    • Deltas: DataMachine and DataMetricTrend take a bare delta with no basis label.
    • Not in the layer: a date range picker, a calendar, print styles, a CSV or PDF helper, an export component.

Exports that exist

ExportWhereWindow
Findings JSON / CSV (lib/download.ts)/compliance, /integrationsall time, built in the browser
Evidence packet JSON qdash.security_packet.v1 (/api/security-packet)/policiescurrent state, takes no period
Server-side evidence pack/compliancestaged, button disabled
PDF / print—none

c123 is merging the two evidence exports (X4), and c126 is moving the packet off Policies. Reports is a natural home for both.

Rule for each section's time basis

Every report section has one of three time bases, and the report labels it:

BasisMeaningExamples
In window (flow)summed or counted over the windowfindings opened and resolved, sessions, spend, DLP touches, new installs (first_seen in the window)
Over window (trend)the window's days as a seriesposture score, coverage %, findings per day, spend per day
As of (state)read at the window's endendpoint count, monitored vs shadow, versions, models in use

Today "as of" can only mean now. If a window ends in the past, a state section either falls back to a trend series that holds that day (posture, coverage) or says plainly that it shows current state (c108 honest states). Snapshots would close this gap (plan, Phase 6).

Security · Posture: sources

SectionSourceBasisStatus
Posture score, start → end, delta/api/trends posture seriesover windowlive, limited to 90 days
What lowers the score (factors)lib/posture-rollups.ts over /api/agentsas of (now)live
Critical and at-risk harnesses (score < 80)/api/agents security_score, worst_*as of (now), worst everlive
Findings by severity: opened, resolved, still open, past SLA/api/security?period=, lib/findings-rollups.ts, findings-sla.ts (first_seen, last_seen, workflow)in windowlive; windows are presets only
Findings per day/api/trends findings seriesover windowlive
Data protection: sensitive paths, secrets and PII in content/api/dlp?period=in windowlive
Would-fire alerts by severityalerts/alerts.ts (all-time sources)none yetneeds a window
Credential risk/api/inventory?period=allas ofall-time only
Policies in force, mode changes in window/api/controls; policy history is lab-only (c118 publishing)as of + in windowqdash policies are staged
Framework evidence, counts by state (c123: no %)compliance/frameworks.ts (localStorage, staged)as ofstaged; owned by c123
Egress decisions/api/egress-decisions, trends egress seriesin window and over windowlive

IT · Inventory: sources

SectionSourceBasisStatus
Endpoints by OS/api/endpoints?period= os (often null)as oflive; OS is patchy
People and teamsteam/people.ts, /api/teamsas of + in window (active)live
Harnesses: installs, endpoints, providers/api/harnesses?period=as of (installs) + in window (activity)live
Models, providers and accounts (personal vs enterprise)/api/models, /api/providers, /api/accountsin windowlive
MCP servers, skills, tools/api/mcp-servers, /api/skills, /api/toolsas of + in windowlive (tool success rate is staged)
Workspaces/api/workspacesin windowlive
New in window (anything whose first_seen falls in it)first_seen on installs, endpoints, skillsin windowderivable now
Spend by harness, user, team, provider/api/costs?period=in window + over windowlive

IT · Deployment status: sources

SectionSourceBasisStatus
Coverage: discovered vs monitored, %/api/trends.coverage[]over window (90 days)live, but only Campaigns reads it
Endpoints by monitoring state (fully, partial, unmonitored)lib/actor-bands.ts endpointsBandas oflive
Shadow installs (installed but unmonitored), binary-confirmed/api/installations instrumented, fp_confirmedas oflive
Users not coveredteam/people.ts coverageas oflive
Stale endpoints (not active in N days)last_activeas ofderivable; there is no heartbeat, so this means "last active", not "last seen"
Harness version spreadInstallation.version, Agent.versionas oflive
Sensor (qcontrol) version per endpointnone—missing
Sensor health / heartbeatnone; Stats.coverage {injection_failures, adapter_errors, uninspectable_conns} exists but nothing shows it—missing / undisplayed
Deployment denominator (identity or MDM roster)none (sensor-coverage-gap wants it)—missing

Gaps to bring to Tyler (backend)

  1. from / to on windowed endpoints. period_span needs to accept a range, not only 24h/7d/30d.
  2. History longer than 90 days in /api/trends. Quarterly reports and a SOC 2 Type II observation period need 3–12 months.
  3. A daily snapshot store for state: inventory counts, coverage and versions on date X.
  4. Sensor version, heartbeat and health per endpoint. Also show Stats.coverage somewhere.
  5. One window for every page. Posture, compliance and alerts are all-time today, so a report and the page it links to can disagree.

Qpoint Brand Style Guide