---
title: "Reporting & Analytics"
slug: reporting-analytics
section: Governance & Operations
status: stable
description: "Unified analytics architecture spanning all six reporting domains — pipeline health, partner performance, placement fill rates, financial reconciliation, compliance audits, and seasonal comparisons"
last-updated: 2026-10-07
---

# Reporting & Analytics

Unified analytics architecture spanning all six reporting domains — pipeline health, partner performance, placement fill rates, financial reconciliation, compliance audits, and seasonal comparisons

> **Architectural Overview, Not Implementation**
>
> This page defines where the analytics layer sits, how data flows into it, what each audience sees, and how KPIs are computed. It does not prescribe a specific BI tool or vendor implementation.

> **Related Pages**
>
> Domain-specific reporting details remain on their respective pages: Queue-Powered Reporting, Automation Reporting Exports, Partner Monitored Metrics, Finance Reconciliation. This page provides the cross-cutting architectural view.

## Architecture Overview

### Analytics Layer Position

The analytics layer sits above the operational data stores (Globus, NetSuite, Queue System) and below the presentation tier (dashboards, exports, scheduled reports). It is a read-only consumer of operational events and state — it never writes back to source systems.

Presentation Tier

Executive Dashboard / Ops Dashboard / Compliance Dashboard / Finance Dashboard / Partner Dashboard
Analytics Layer

KPI Engine / Aggregation Service / Cache / Export Engine / Scheduler
Operational Data Sources

Globus Core / Queue System / NetSuite / SEVIS Gateway / Partner Portal / Matching Engine
### Design Principles

Read-only — the analytics layer never writes to operational data stores / RBAC-scoped — every query is filtered by the requesting user's scope before execution / Cache-first — pre-computed aggregations serve dashboards; cache invalidates within 5 minutes of data changes / Cross-layer — reports can span applicants, placements, compliance, finance, and queues in a single query / Export-aware — any view can be exported in CSV, Excel, or PDF with current filters preserved / Audit-logged — every report generation, export, and scheduled delivery is recorded
## Data Flow

Operational data reaches the analytics layer through three distinct mechanisms, each optimized for its use case:

### Real-Time Counters

Event-driven counters updated on every state change via the Event Outbox. Used for metrics that need immediate visibility.

| Counter | Trigger Event | Dashboard |
| --- | --- | --- |
| Queue depth per queue | queue_membership.created / resolved | |
| Active participants | Not event-driven: computed at read time as every application whose status is not terminal (`withdrawn`, `rejected`, `lapsed`, `cancelled`, `completed`) | |
| Exception count | compliance_hold.created | |
| Open positions | job_order.capacity_changed | |
| SLA breach count | sla.breached event | |

### Scheduled Aggregations

Background jobs that compute aggregate metrics at fixed intervals. Used for metrics that are expensive to calculate or where slight staleness is acceptable.

### On-Demand Queries

Ad-hoc queries executed when a user requests a specific drill-down or custom report. Results are not cached by default but can be saved as a report template.

`POST /api/aggregate` is a counts-only, privacy-preserving aggregation API over a fixed allow-list of entities, dimensions and filters. It authenticates with an `X-API-Key` carrying the `aggregate:read` scope (401 without a valid key, 403 without the scope). The body takes `entity`, `groupBy`, `filters`, `metric` and `minGroupSize`, and small groups are suppressed. Errors use `error.code` with lowercase codes: `unknown_entity`, `dimension_not_allowed`, `filter_not_allowed`, `groupby_required` and `invalid_request` (400), `metric_unsupported` (422), `rate_limited` (429, with a `Retry-After` header and `retryAfterSeconds`) and `internal_error` (500). The limiter is a fixed window per API key id (client IP if absent): `AGGREGATE_RATE_LIMIT` requests (default 120) per `AGGREGATE_RATE_WINDOW_MS` (default 60000). Both are optional, read on every call so they can change without a restart, and a limit that is not a positive number switches the limiter off.

Custom date range filtering on any dashboard / Drill-down from KPI card to underlying record list / Cross-filter by program + season + partner + host / Ad-hoc data exports for compliance audits / Saved report templates with stored filter configurations

Counts-only aggregate API: `POST /api/aggregate` needs an API key with the `aggregate:read` scope (401 without a valid key, 403 without the scope). Body: `entity` (`applicants`, `hosts` or `placements`), `groupBy`, optional `filters`, `metric` (only `count`) and `minGroupSize`. Buckets below max(`minGroupSize`, 5) are suppressed. Errors use lowercase codes: `unknown_entity`, `dimension_not_allowed`, `filter_not_allowed`, `groupby_required` and `invalid_request` (400), `metric_unsupported` (422), `rate_limited` (429 with `Retry-After`) and `internal_error` (500). The in-memory limit is per API key (client IP as fallback): `AGGREGATE_RATE_LIMIT` requests (default 120; zero or negative disables) per `AGGREGATE_RATE_WINDOW_MS` (default 60000), read on each call.
## Dashboard Specifications

Five audience-specific dashboards, each designed for distinct decision-making contexts. All dashboards respect RBAC scoping — users only see data within their authorized scope.

### Executive Dashboard

Brand-scoped KPIs for C-suite leadership. Auto-refreshes every 60 seconds. Clicking any KPI card navigates to the detailed drill-down view.

Four leadership panels sit alongside the KPI strip, giving leadership real-time portfolio health without drilling into program-level queues (Aug 11 2026 release capsule).

Every figure on the page, including the health banner, is read from a single executive-KPI payload captured at one moment, so the banner, tiles and cards can never show numbers from different fetches. If that payload cannot be loaded the page says so explicitly (see the banner below and the "Data unavailable" badge that replaces "Live Data") rather than rendering zeros or an all-clear.

#### Portfolio Health Banner

A RAG-banded status strip sits above the KPI strip. It shows the overall portfolio status — "Portfolio healthy" (green), "Portfolio status: Watch" (amber) or "Portfolio status: Action needed" (red) — alongside four headline numbers: programs in scope (every program that is not inactive), active participants, Operational Readiness % (shown as "ready"), and the blocked count (the Blocked segment of the Operational Readiness Breakdown). The banner also surfaces a single "Next concern" line, chosen from every amber or red figure on the page (fill rate, Operational Readiness, open compliance cases, SEVIS batch failures, check-in timeliness, each compliance gate, each review-type SLA attainment) by a deterministic tie-break order — worst RAG band (red before amber) → higher stuck-item (blocked) count → older breach age (only open compliance cases carry one) → stable on-page order — with a "Review" drill-through link and a "+N more figures outside target" note. Every figure is banded through the same shared RAG thresholds as its own tile, so the banner cannot disagree with the tiles. When the portfolio is healthy the banner is quiet: it reads "Every tracked figure is inside its target band." with no concern line. If the underlying figures cannot be loaded the banner shows "Portfolio status unavailable — figures could not be loaded" with a Retry button instead of a status word. The print snapshot header repeats the banner's status and concern lines verbatim.

#### Portfolio by Brand — Scorecards

Each brand in the executive view renders as a uniform mini scorecard row showing its program and season counts, applicant count, readiness % (the On Track share, using the same definition as the Operational Readiness Breakdown), compliance % (the headline Operational Readiness predicate) and, where set, total capacity. All of these count active participants only. Per-season ready / blocked counts are not on the brand rows; they appear on the Pre-Season Readiness season cards. The Operational Readiness Breakdown card uses the vocabulary On Track / Needs Attention / Blocked (plus an "Other Status" row when a participant holds a status outside those three, so the segments always add up to the total); each segment drills through to the applicants list filtered to that state.

#### Top Recruiting Partners Table

A brand-scoped table of the top recruiting partners, pre-ordered by the server by in-scope applicant volume (name as tie-break), with columns Partner, Applicants, Ready % and Blocked % and a drill-through from each partner name to its partner detail page. Ready % mirrors the headline Operational Readiness predicate and Blocked % the Breakdown card's Blocked segment, computed over the same active-participant population. Partners with zero in-scope applicants are excluded. The caption reads "Top N of M partners by in-scope applicant volume" when more partners exist than are shown.

#### Review SLA Attainment Tiles

Per-review-type trailing-30-day SLA attainment (percentage of timers resolved within SLA in the window) is shown alongside a count of currently-open breaching timers and the number of queues they sit in. Review types with no activity are omitted rather than shown as zero tiles. Tile colour is RAG-banded against configured thresholds. Clicking a tile opens the Queue Workbench scoped to that review type's queues (/queues?reviewType=...). Shares the same open-timer definition as the Ops SLA Monitor, so the breaching counts agree with its Overdue rows.

#### Gate Readiness, Lenses, Focus and Export Controls

Beneath the KPI strip, a Compliance Gate Readiness strip shows one tile per gate family that applies to a program in scope (ready / blocked / waiting counts and a RAG badge; data comes from the compliance rules engine's persisted per-application gate projection). This is a different source from the Operational Readiness tile, which reads the applicant operational-status column, and the two are labelled separately because they may disagree. Each tile drills through to the surface that owns working that gate's blockers.

The page header carries these controls:

- View lens — Executive (default, every card), Operations, Finance, Compliance or SEVIS. Lenses only show, hide, reorder and default-collapse cards; they never change what is fetched, how data is scoped or what exports contain. A ?lens= URL parameter wins over the saved per-user preference.
- Brand focus — pin one or more brands; saved per user and can only narrow the caller's scope.
- Comparison period — "vs. last month" or "vs. last season" for the KPI delta chips.
- Shared Program and Season selectors narrow the tiles, drill-throughs and exports; a badge indicates when a filter is active.
- Print snapshot, and an export menu offering the formats advertised by the report catalogue for this report (CSV, Excel and PDF). Downloads carry the brand focus, comparison period and Program/Season scope currently selected.

A Portfolio Readiness Index tile is built but dark behind a SHOW_PRI_TILE switch (currently off); the server still records its score history. `executive_kpi_snapshots` holds one row per UTC day and brand (unique on `snapshot_date` and `brand_id`; the scheduler upserts) with raw numerators and denominators rather than percentages, so scoped trends can be summed across brands and recomputed: active participants, fill rate, compliance, revenue due/paid/outstanding, open compliance cases and oldest breach age, failed SEVIS batches, regulatory check-ins on time vs due, gate and SLA counts, and the PRI score with `pri_weight_version` and `pri_components`. `executive_pri_weight_sets` stores the PRI weights as versioned sets (`version` unique, `status` draft, published or retired, `effective_date`, `weights`, `params`); the highest published version is active and changing weights creates a new version, so historical scores stay reproducible.

### Operations Dashboard

Pipeline visibility, queue health, and processing time analytics for program managers and operations staff. Filterable by program, season, and date range.

### Compliance Dashboard

SEVIS submission health, document turnaround, and site visit compliance tracking for compliance officers. Audit-ready export capabilities built in.

`GET /api/reports/compliance` backs this dashboard and its exports (`compliance.view`, scoped to the caller's brand, program and season). Query: `programId`, `seasonId`, `brandId`, `from`, `to` (default window is the trailing 90 days; `from` after `to` returns 400 `VALIDATION_ERROR`). With no export format it returns the JSON report. An export format streams CSV or Excel rows for one `domain` (`sevis`, the default, `site_visits` or `documents`; anything else is 400 `VALIDATION_ERROR`), while PDF is the formal document covering all three domains. Site-visit and document exports are participant-level and are captured as bulk PII disclosures in the report-run record.

### Finance Dashboard

Revenue tracking, reconciliation status, and aging analysis. Data sourced from both Globus charge events and NetSuite sync. Staleness indicators on all cached values.

### Partner Management Dashboard

Performance scorecards for all active partners showing the 7 monitored metrics, trending over time, probation/suspension tracking, and cross-partner comparison within a program.

The sponsor-side Host Management screen renders a program-type-scoped subset of these metrics as tiles — e.g. a Camp host’s Performance section surfaces only Conversion Rate (Hired vs Not Hired), Avg Processing Days (Reserved-to-Hire), Reservation Expiry Rate, and Hired-to-DS-2019 Completion Rate. See Partner Organizations &rarr; Performance Tiles — Program-Type Scoping .

## Data Source Mapping

How operational data from each source system feeds into the reporting layer:

| Source System | Data Feeds | Delivery | Destination |
| --- | --- | --- | --- |
| source | feeds | | destination |

_(row above is a template, repeated for each data row)_

## KPI Catalog

Complete catalog of metrics across all six reporting domains. Each metric defines its data source, calculation method, target dashboard, and refresh frequency.

### Pipeline Health

| Metric | Source | Calculation | Dashboard | Refresh |
| --- | --- | --- | --- | --- |
| metric | source | calculation | dashboard | |

_(row above is a template, repeated for each data row)_

### Partner Performance

| Metric | Source | Calculation | Dashboard | Refresh |
| --- | --- | --- | --- | --- |
| metric | source | calculation | dashboard | |

_(row above is a template, repeated for each data row)_

### Placement Fill Rates

| Metric | Source | Calculation | Dashboard | Refresh |
| --- | --- | --- | --- | --- |
| metric | source | calculation | dashboard | |

_(row above is a template, repeated for each data row)_

### Financial Reconciliation

| Metric | Source | Calculation | Dashboard | Refresh |
| --- | --- | --- | --- | --- |
| metric | source | calculation | dashboard | |

_(row above is a template, repeated for each data row)_

### Compliance & Audit

| Metric | Source | Calculation | Dashboard | Refresh |
| --- | --- | --- | --- | --- |
| metric | source | calculation | dashboard | |

_(row above is a template, repeated for each data row)_

### Seasonal Comparison

| Metric | Source | Calculation | Dashboard | Refresh |
| --- | --- | --- | --- | --- |
| metric | source | calculation | dashboard | |

_(row above is a template, repeated for each data row)_

## Seasonal Analytics

Seasonal comparison analytics enable year-over-year and season-over-season analysis of all major KPIs. The model handles the inherent complexity of comparing seasons that span different date ranges across years.

### Time Dimensions

Every metric is indexed by three time dimensions that enable flexible comparison:

### Cohort Definitions

Cohorts are defined as "the same program across different seasons." This enables apples-to-apples comparison even when program structures evolve.

Cohort Matching Rules

prior season
### Year-over-Year Methodology

YoY comparisons use a standardized methodology across all KPIs:

Absolute delta: Current value − Prior year value (e.g., +42 applicants) / Percentage change: (Current − Prior) / Prior × 100 (e.g., +12.5%) / Trend direction: Up/Down/Flat indicator with color coding (green = improvement, red = decline, gray = flat within ±2%) / Rolling comparison: 30/60/90-day rolling windows for smoother trend lines / Benchmark tracking: User-defined targets per KPI per program for comparison against actuals / Statistical significance: Changes below a minimum sample size threshold are flagged as 'insufficient data'
## RBAC & Scoping

Every report query is filtered by the requesting user's RBAC scope before execution. This ensures data isolation without requiring separate report definitions per role. See RBAC & Governance for the full scope model.

### Brand Isolation

### Partner-Scoped Views

Partner portal users see only their own organization's data. Partner admins see data for all users within their partner organization. Sponsor staff see cross-partner views within their program scope.

### Program Filtering

All dashboards and reports support program-level filtering as a first-class filter dimension. This filter is applied on top of RBAC scope — users can narrow their view but never expand beyond their authorized scope.

## Export & Delivery

### Export Formats

Any report or dashboard view can be exported. Exports respect current filters, column selection, sort order, and the user's RBAC scope.

### Scheduled Delivery

Staff can schedule reports for automatic generation and email delivery on a recurring basis.

Schedule Configuration

### Async Generation

Interactive report downloads (CSV, Excel and PDF) are capped at 5,000 rows (REPORT_EXPORT_ROW_LIMIT); rows beyond the cap are truncated, with a truncation note giving rows shown and total, rather than processed asynchronously.

Each catalogue-report export is recorded as a `report_runs` row so a figure handed to a regulator can be reproduced later, because reports are recomputed live every time they are opened. The row keeps the `report_key` and `report_name` (captured at run time), `actor_user_id` (no foreign key, so attribution survives user deletion), `export_mode` (`interactive`, the capped download, or `audit`, the complete record), `format`, the applied `filters`, a point-in-time copy of the caller's row-level `scope`, `generated_at`, `row_count`, `total_row_count`, `truncated`, `contains_pii`, `storage_state` (`pending`, `stored`, `unavailable` or `purged`; only `stored` is re-downloadable), the internal `storage_path` (never returned to a client), `file_name`, `content_type` and `file_size`.

## Cross-References

Reporting capabilities are documented in detail on their respective domain pages. This page provides the unified architectural view; the following pages contain domain-specific implementation details:

> **Domain Pages Remain Unchanged**
>
> The domain-specific reporting sections on other pages are not being removed or replaced. They provide detailed, contextual documentation for each domain. This page provides the cross-cutting architectural overview that ties them together.
