← Design · c128
data-inventory.md
c128 data inventory: what qdash shows today, and how time works on it
Contents
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.tsowns?period=and shows it as thewhen:pill. The values, fromfilter-keys.tsPERIOD_OPTIONS, areall · 24h · 7d · 30d, and the default is7d. - Presets only. There is no from–to or custom range in the UI. On the backend,
web.rsperiod_spanmaps 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 use Pages Follow the pill findings, dlp, endpoints, users and teams, every inventory listing, activity, cost, home /Always all-time posture, compliance, policies, alerts, identity, integrations, every detail page except users and teams Fixed windows that ignore the pill /api/trends(90 days, daily),/api/statscost 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.tstimeFrameToStart(tf, previous), the only prior-period helper. - History:
DataHistoryGraphdraws daily history and hatches gaps where days are missing. - Deltas:
DataMachineandDataMetricTrendtake a baredeltawith no basis label. - Not in the layer: a date range picker, a calendar, print styles, a CSV or PDF helper, an export component.
- Presets:
Exports that exist
| Export | Where | Window |
|---|---|---|
Findings JSON / CSV (lib/download.ts) | /compliance, /integrations | all time, built in the browser |
Evidence packet JSON qdash.security_packet.v1 (/api/security-packet) | /policies | current state, takes no period |
| Server-side evidence pack | /compliance | staged, 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:
| Basis | Meaning | Examples |
|---|---|---|
| In window (flow) | summed or counted over the window | findings opened and resolved, sessions, spend, DLP touches, new installs (first_seen in the window) |
| Over window (trend) | the window's days as a series | posture score, coverage %, findings per day, spend per day |
| As of (state) | read at the window's end | endpoint 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
| Section | Source | Basis | Status |
|---|---|---|---|
| Posture score, start → end, delta | /api/trends posture series | over window | live, limited to 90 days |
| What lowers the score (factors) | lib/posture-rollups.ts over /api/agents | as of (now) | live |
| Critical and at-risk harnesses (score < 80) | /api/agents security_score, worst_* | as of (now), worst ever | live |
| 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 window | live; windows are presets only |
| Findings per day | /api/trends findings series | over window | live |
| Data protection: sensitive paths, secrets and PII in content | /api/dlp?period= | in window | live |
| Would-fire alerts by severity | alerts/alerts.ts (all-time sources) | none yet | needs a window |
| Credential risk | /api/inventory?period=all | as of | all-time only |
| Policies in force, mode changes in window | /api/controls; policy history is lab-only (c118 publishing) | as of + in window | qdash policies are staged |
| Framework evidence, counts by state (c123: no %) | compliance/frameworks.ts (localStorage, staged) | as of | staged; owned by c123 |
| Egress decisions | /api/egress-decisions, trends egress series | in window and over window | live |
IT · Inventory: sources
| Section | Source | Basis | Status |
|---|---|---|---|
| Endpoints by OS | /api/endpoints?period= os (often null) | as of | live; OS is patchy |
| People and teams | team/people.ts, /api/teams | as 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/accounts | in window | live |
| MCP servers, skills, tools | /api/mcp-servers, /api/skills, /api/tools | as of + in window | live (tool success rate is staged) |
| Workspaces | /api/workspaces | in window | live |
New in window (anything whose first_seen falls in it) | first_seen on installs, endpoints, skills | in window | derivable now |
| Spend by harness, user, team, provider | /api/costs?period= | in window + over window | live |
IT · Deployment status: sources
| Section | Source | Basis | Status |
|---|---|---|---|
| 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 endpointsBand | as of | live |
| Shadow installs (installed but unmonitored), binary-confirmed | /api/installations instrumented, fp_confirmed | as of | live |
| Users not covered | team/people.ts coverage | as of | live |
| Stale endpoints (not active in N days) | last_active | as of | derivable; there is no heartbeat, so this means "last active", not "last seen" |
| Harness version spread | Installation.version, Agent.version | as of | live |
| Sensor (qcontrol) version per endpoint | none | — | missing |
| Sensor health / heartbeat | none; 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)
from/toon windowed endpoints.period_spanneeds to accept a range, not only 24h/7d/30d.- History longer than 90 days in
/api/trends. Quarterly reports and a SOC 2 Type II observation period need 3–12 months. - A daily snapshot store for state: inventory counts, coverage and versions on date X.
- Sensor version, heartbeat and health per endpoint. Also show
Stats.coveragesomewhere. - One window for every page. Posture, compliance and alerts are all-time today, so a report and the page it links to can disagree.