git:20260831.e6d9ae7 to git:20260907.51300d4

34 added, 99 removed. Audit A to A.

# Hot Updater Console Design System
## 1. Product Character
The Console is a compact operational workspace, not a marketing dashboard.
It uses warm stone neutrals, restrained orange emphasis, quiet borders, and
dense but readable information layouts. Insights must feel native to the
existing bundle table and detail sheet rather than like a separate product.
The primary operator needs to answer three questions quickly: how many
- installations are active in the selected period, how those installations are
- distributed by bundle, and where a specific installation currently points.
- Supporting context stays subordinate to exact values and actions.
-
- ### Insights dashboard reference
-
- The Insights composition takes its information hierarchy from Expo's public
- EAS Observe > EAS Update dashboard without copying Expo branding or metrics:
-
- - a compact period control precedes the report;
- - one full-width activity card is the primary analytical surface, with a
- period-aware active-installation value above the chart and supporting values
- aligned below it;
- - the overview chart shows one aggregate installation-activity series so the
- selected-bundle inspector remains the place for bundle-specific analysis;
- - the selected-bundle inspector follows the installation activity card rather
- than competing with the primary chart.
-
- Hot Updater keeps its warm-stone surfaces, orange semantic accent, existing
- type scale, and 4 px spacing grid. The reference contributes dashboard
- structure only.
+ installations reported in the selected period, what was reported for a selected
+ bundle, and where a specific installation currently points. Supporting context
+ stays subordinate to exact values and actions.
## 2. Foundations
### Color
- All product UI uses the semantic tokens in `src/styles.css`; component files
do not introduce raw colors.
- `background`, `card`, `muted`, `border`, and their foreground counterparts
create the warm-stone surface hierarchy in both themes.
- - Orange `primary`/`accent` is the single emphasis color. In charts,
- `chart-2` represents the primary Newly applied, reporting-installation, or
- bundle-distribution series.
- - `muted-foreground` or `chart-1` is the neutral secondary-series treatment.
- Labels, values, and tooltips always communicate meaning without color.
+ - Orange `primary`/`accent` is the single emphasis color.
+ - `muted-foreground` is the neutral secondary treatment. Labels and values
+ always communicate meaning without color.
- Destructive color is reserved for genuine errors and destructive actions,
never normal insights status.
### Typography
- Inter Variable is the UI typeface, with the platform stack as the initial
fallback and the existing monospace stack for identifiers.
- Page headings use `text-base` or `text-lg` with semibold weight. Operational
card titles use `text-sm` with medium or semibold weight.
- Body and control text use `text-sm`; dense metadata and table content use
`text-xs`. Exact metrics use `text-2xl` or `text-3xl`, semibold,
`tracking-tight`, and `tabular-nums`.
- Search inputs use at least 16 px text below `lg` to avoid automatic zoom on
iOS. Keep input and adjacent actions at least 44 px tall in that range;
desktop controls retain the Console's compact density.
- Sentence case is mandatory. Uppercase is limited to short metadata labels
already established by the Console.
### Spacing and shape
- The base unit is 4 px. Standard gaps are 8, 12, 16, and 24 px.
- Route padding is 12 px on narrow screens and 24 px from `sm` upward.
- Card headers and contents share a 16 px inset on narrow screens and 24 px
from `sm`; do not mix insets within one surface.
- The shadcn Mira small-radius scale is authoritative. Cards use the existing
`rounded-xl`; controls use `rounded-md`.
- Borders and subtle tonal shifts provide depth. Existing card shadow is the
maximum elevation; insights adds no glow, glass, or decorative shadow.
## 3. Layout Grammar
- The fixed sidebar and route-owned scrolling shell remain unchanged.
- - Insights uses one primary content column at 375 px and 768 px. At 1280 px,
- the installation activity chart remains full width and carries the leading
- value. Reported bundles and the timestamp form one compact footer. A
- searchable bundle selector then introduces the selected-bundle detail.
+ - Insights uses one primary content column at 375 px, 768 px, and 1280 px.
+ Scope controls precede reporting-installation and selected-bundle values.
Installation search remains full width.
- Group with alignment, separators, and whitespace before adding containers.
Do not nest generic KPI cards inside a larger card or repeat equal KPI tiles.
- Insights event history responds to the available card width, not only the
viewport. All Events uses a table from 58 rem; installation history uses a
table from 48 rem. Narrower cards show a vertical event list with the same
time, status, identity, app, and bundle information. Reading an event must
not require horizontal scrolling. The page itself must not overflow at
375 px or 200% zoom.
- Route headers remain compact, sticky, and aligned with the existing sidebar
trigger. Insights title and Overview / Events navigation share one row when
space allows. Navigation and primary mobile actions have 44 px touch targets.
- Use labels, exact values, and controls to explain the interface. Avoid a
title followed by a sentence that repeats it. Keep metric definitions and
- chart calculation details accessible without adding a visible paragraph to
- every section.
+ calculation details accessible without adding a visible paragraph to every
+ section.
## 4. Capability and Data States
- - Bundles is always available.
- - Insights navigation, protected route content, protected queries, and
- per-bundle activity are absent until `supportsInsights` is confirmed true.
- Installation history remains a drill-down route under the single Insights
- navigation state.
- - An unresolved protected route shows only a neutral, layout-stable shell
- loading state. Unsupported routes redirect to Bundles without mounting or
- flashing protected content. Capability discovery errors show a compact
- diagnostic state and a Bundles escape path, with no protected query.
+ - Bundles and Insights navigation are always available. Installation history
+ remains a drill-down route under the Insights Events view.
- Data surfaces define loading, empty, success, and genuine error states.
- Unsupported capability is absence, not an error or empty-state card.
- - Insights language is direct and evidentiary: use Active installations,
- Latest bundle share, Newly applied, Recovered away, Configured rollout, and
- Last known bundle. Daily, Weekly, and Monthly active installations mean
- unique install IDs that sent at least one update status in the selected 24
- hours, 7 days, or 30 days. This is installation activity, not unique user
- accounts. Never imply realtime state, complete fleet coverage, or rollout
- completion.
+ - Insights language is direct and evidentiary: use Reporting installations,
+ Selected bundle installations, Applied reports, Recovered-from reports,
+ Adopted reports, and Last known bundle. Reporting installations are unique
+ install IDs whose latest report falls in the selected 24 hours, 7 days, or 30
+ days. Outcome values count accepted reports. Never imply realtime state,
+ complete fleet coverage, an exact share, success rate, or rollout completion.
## 5. Reusable Primitives
- **Route header:** `SidebarTrigger`, page title, and native view navigation;
sticky with the existing border and translucent card treatment.
- **Operational card:** full shadcn `Card` composition with one clear title
and no nested card grid. Add a description only when a label or direct
action cannot convey necessary information.
- **Metric list:** semantic `dl` with exact tabular values and compact labels;
separators may distinguish adjacent metrics.
- - **Chart:** shadcn `ChartContainer` wrapping Recharts, with
- `accessibilityLayer`, an accessible name, semantic token colors, tooltip, and
- exact text/table equivalent in the DOM.
- - **Rollout row:** bundle identity, reported-in-range count, exact configured
- percentage, and shadcn `Progress`; orange is reserved for the progress
- indicator.
- **History lookup:** shadcn `Field`, `InputGroup`, and `Button`, an explicit
label, Enter submission, trimmed query, and visible focus. The lookup accepts
either a user ID or install ID and opens the existing installation history
drill-down. Matching installations form a collapsed selector below `lg`
and remain alongside the history on wider screens.
- **Feedback:** shadcn `Skeleton` for loading and `Alert` for genuine errors;
- a short state and direct action for empty results, such as No activity /
- View events or No matches / Edit search. Do not reserve a large empty plot
- for zero activity.
+ use a short state and direct action for empty lookup results, such as No
+ matches / Edit search.
Primitive states are default, hover/focus for interactive controls, disabled
- while submitting/loading when relevant, loading, empty, error, and supported
- success. Capability-unavailable primitives do not render.
+ while submitting/loading when relevant, loading, empty, error, and success.
## 6. Insights-Specific Composition
- - **Selected bundle activity:** one full-width operational card below the
- installation activity card. Its header contains the searchable selector so
- the title, control, and card content share one inset and information
- hierarchy instead of forming a detached toolbar. On wide screens the title
- group and selector align to the same top edge; on narrow screens they stack
- in source order. The selected bundle ID appears only in the selector instead
- of being repeated above the metrics. Its metric rail shows Latest bundle
- share (installs whose latest report ends on the selected bundle, divided by
- all reporting installs in the selected period), Newly applied, Recovered
- away, and Configured rollout. The movement summary and chart use the same
- selected period. The chart shows per-bucket distinct movement rather than
- a cumulative total, with a visible series legend and UTC label.
- Metrics use two columns on narrow screens and four on wide screens, with
- compact units rather than a repeated explanatory line under every value.
- - **Installation activity:** Daily, Weekly, or Monthly active installations is
- the leading metric above one full-width aggregate chart. The leading value
- deduplicates install IDs across the whole selected period. Each UTC chart
- bucket separately deduplicates install IDs within that hour or day, so an
- installation may appear in more than one point and the points must not be
- summed to reproduce the period total. Exact values remain available in the
- tooltip and screen-reader table. The title names the selected period; do not
- repeat Active installations, the period, and Activity over time around the
- same number. A populated chart needs only Per hour / Per day and UTC.
- Reported bundles and As of form one compact footer rather than separate
- KPI cards. Bundle IDs do not compete in the overview; the searchable bundle
- detail below provides a human-readable platform, channel, and target-version
- identity.
- - **Configured rollout:** configuration is presented beside the selected
- bundle's latest bundle share, never as reported completion.
+ - **Reporting installations:** the leading card shows the unique latest-state
+ installation count for the selected platform, channel, and period, with its
+ independent measurement time.
+ - **Selected bundle:** when a bundle is selected, show its latest-state
+ installation count and independent Applied reports, Recovered-from reports,
+ and Adopted reports counts. Each outcome links to event history using the
+ same scope and receipt interval. Present the values independently without
+ percentages.
- **All events:** shared Overview / Events navigation makes event history a
primary Insights destination. Native links retain page-navigation semantics.
The installation route without a search or selected installation shows every
recorded event type, newest first, with no reporting-period or bundle filter.
- The title, total count, refresh action, and compact installation lookup sit
- inside the list header. The lookup is not an event filter. Pagination respects
- the existing Insights scan limit. Queries fail above the limit; this is not a
- storage limit, and installation lookup does not bypass it. Show this
- constraint when it causes a query error, not as a permanent banner. Each
- installation links to its history; returning restores the source event page
- and scroll position.
+ The title, refresh action, and compact installation lookup sit inside the list
+ header. The lookup is not an event filter. Event history uses keyset pages and
+ has no total-count claim. Each installation links to its history; returning
+ restores the source event page and scroll position.
Wide table columns follow time, event, user ID / install ID, app, and bundle.
Narrow event rows lead with status and time, then identity, app, and bundle;
this preserves each event's context without hiding columns offscreen. Times
use YYYY/MM/DD HH:mm:ss in the browser's named time zone, with expandable
exact UTC values. User IDs lead; shortened install and bundle IDs reveal and
copy their full values. UNCHANGED is presented as Activity reported, a neutral activity
observation on the current bundle. Applied/adopted events use the semantic
success color; recovery uses warning. Text and icons remain present so color
is never the only distinction.
- **Installation history:** the Events lookup accepts a user ID or install
ID and routes to the installation history drill-down. A user ID may match
multiple installations; below `lg`, a labeled count and disclosure keep
those matches collapsed until needed, then collapse again after selection.
Errors and empty results remain visible. At `lg` and above the matches are
always visible alongside the history. An install ID identifies one history.
Every history event shows the app version reported with that event beside
its bundle transition.
## 7. Motion and Interaction
- - No decorative motion or automatic chart animation is introduced.
- Existing focus, hover, sidebar, and sheet behavior remains authoritative.
- Controls use existing transition utilities only for meaningful state
feedback. Reduced-motion behavior from the shared stack is preserved.
- History lookup is keyboard-operable in source order: input, Find installation,
then the matching-installation disclosure and history controls on the
drill-down. Selecting a match returns focus to the disclosure before hiding
the list. Mobile timestamp disclosure, identifier copy, period, search,
refresh, and pagination actions have targets of at least 44 px.
## 8. Accessibility, Personas, and Accepted Debt
### Personas and constraints
- A release operator scanning under time pressure needs exact values, compact
hierarchy, and stable placement.
- A keyboard or screen-reader user needs semantic headings, `dl` metrics,
- labeled controls, table headers, meaningful link names, and text equivalents
- for every chart.
+ labeled controls, table headers, and meaningful link names.
- A low-vision user at 200% zoom needs wrapping headers, visible primary
actions, and no page-level horizontal overflow.
- A color-vision-deficient user must distinguish series and states by labels,
values, tooltip text, and structure rather than hue alone.
### Accepted debt
- The current card primitive owns its existing single shadow and spacing
defaults; G002 does not redesign shared shadcn primitives.
- Installation history remains on the existing route and is composed from
focused search, matching-installation, and history primitives.