RFDs/0008

Product experience

State
committed
Authors
Darwin D Wu
Discussion
renga-dcim/renga#72
Labels
rengaproductdesignuiux
Implemented
100%Checklist

Goal

Give Renga one coherent product experience that facilities staff and infrastructure operators share, with the speed and polish of a modern keyboard-first tool. The experience must make Renga’s distinctive model (observed versus desired state, provenance, freshness, and findings) easy to read and act on, and it must give later capabilities such as osquery and virtualization defined places to plug in instead of new top-level pages.

This RFD owns information architecture, shared interaction patterns, the Inbox and triage workflows, visual design tokens, and the user-facing extension points. Domain behavior stays in RFDs 1 through 7; where this RFD needs new domain state, it says so and the owning domain implements it.

Problem

The current web UI was built feature by feature and mirrors the data model:

  • the sidebar has eleven destinations, roughly one per table or RFD;

  • findings live on three separate pages (component, topology, and placement), and placement findings are not reachable from the sidebar;

  • most screens place always-open create forms above the data they create;

  • three visual languages coexist: a dense operator table on Resources, spacious card dashboards elsewhere, and stock generated authentication and settings pages;

  • LiveViews hand-roll their markup, with duplicated private helpers and daisyUI classes mixed with hard-coded Tailwind colors; and

  • status is shown differently on every screen, and observed versus expected values sit in separate cards that the reader must compare.

Each new domain has added pages. Without a shared structure, osquery and virtualization would add more.

Audience

Facilities staff (placement, assets, warranty, replacements) and operators (freshness, agents, drift, network) use the same objects, lists, and Inbox. Neither group gets a separate application or vocabulary. Saved views are the only role-specific surface. Both groups' actions appear in the same activity history so each can see what the other changed and why.

The interface is designed for frequent, keyboard-driven use and must remain readable for occasional visitors. Copy names things the way people recognize them ("Expected" and "Observed", not "canonical projection").

Principles

  1. Organize around the operator’s questions, not the data model.

  2. One object, one page; domains contribute tabs rather than pages.

  3. One list grammar for every collection.

  4. Observed versus desired is a visual language on each value, not a section.

  5. Lifecycle, freshness, agent connectivity, and drift are always shown as separate signals in one fixed strip.

  6. Creating and editing are actions (keyboard, command menu, side panels), not page sections.

  7. The system opens and closes findings; people add judgment to them.

  8. Edits never overwrite observed evidence; the UI says which layer an edit changes.

  9. Changes with a wide blast radius show their impact before they happen.

  10. Status colors carry one meaning everywhere and never depend on user theme.

Information architecture

The top level has six areas that do not grow per feature:

Question Area Contents

What needs me?

Inbox

Findings from every domain, member requests, and triage, in one queue

What exists?

Inventory

Every resource kind in one list with saved views

Where is it?

Places

Sites, nested locations, racks, and rack elevations

How is it connected?

Network

Topology, VLANs, prefixes, and cables as tabs of one area

What changed?

Activity

Organization-wide change feed; each object also has its own history

What can exist?

Catalog

Manufacturers, hardware types, and module types

"Who reported this?" has no page. Provenance is available on every value (see Values, provenance, and drift).

The sidebar holds the six areas, pinned saved views, and sites. The mobile menu and the command menu are generated from the same navigation definition so they cannot diverge. Organization and personal settings live under one Settings area.

Existing routes are kept as redirects to their new homes during migration.

Shared patterns

Lists

Every collection uses one list component with filtering, grouping, sorting, column choice, pagination, and keyboard navigation (J/K to move, Enter to open, X to select, F to filter, C to create). Filters, grouping, and selection live in the URL so any view can be shared. A saved view is a named filter, grouping, and column set; members may save personal views and pin organization views. Bulk actions appear in a floating bar when rows are selected.

Object pages

Every resource kind opens into the same layout: title, status strip, editable properties panel, related objects, and history. Domains contribute tabs, for example Hardware, Network, Placement, Ports, Virtual machines, or Software. A tab may declare a capability requirement (such as an agent capability) and is hidden or explained when the requirement is not met.

Values, provenance, and drift

Any displayed value can reveal its sources: each source’s value, observation time, freshness, and which source won and why. When a desired or expected value differs from the observed value, the drift marker sits on the value itself ("496 GB, expected 512 GB") and links to the related finding. Overrides are offered from the same place.

Status strip

Lifecycle, freshness, agent connectivity, and drift are shown in that order everywhere: list rows, object headers, rack elevations, and topology nodes. Each signal uses shape as well as color so it remains legible in grayscale.

Actions

The command menu (Ctrl/⌘ K) offers navigation and actions for the current object. Unavailable actions state why ("osquery is off on this agent", "Disabled by organization policy"). Creation opens a modal or side panel. Every action is recorded in Activity with its actor.

Live updates

Lists and object pages update over LiveView as reconciliation and other users change data. Pages do not offer a manual refresh control.

Inbox

The Inbox contains three item types, grouped by default as Requests, Triage, Drift, and Health.

Findings are opened and closed only by reconciliation. People add workflow state on top:

  • an assignee;

  • a snooze until a time; and

  • "accept as exception" with a required reason and optional expiry, visible to everyone who views the resource.

A person cannot mark a finding resolved while the system still observes the condition. An expired exception returns the finding to the open queue. This generalizes the existing expected-component exception to all finding types.

Requests are permanent changes a member proposed but may not apply directly (see Editing hardware components). They carry the proposer, reason, the before and after values, and the effect of approval. When the same request is open on several resources, the request suggests changing the shared definition instead.

The domain implication is one organization-scoped workflow record keyed by finding identity (assignee, snooze, exception, and history) that every finding-producing domain uses, plus a request record with approval state.

Triage

Triage is a computed view, not a flag. A resource is in triage while it lacks facts a person usually supplies: a placement, a hardware type, an owner, or a resolution of a suspected duplicate identity. It leaves triage automatically when those facts arrive, whether from a person, a rule, or a collector.

Triage never gates inventory. Untriaged resources appear in every list and count. Virtual machines and other short-lived resources never enter triage; they inherit their placement from their host.

To handle onboarding bursts, triage groups items by pattern and suggests rules such as "hosts reporting from 10.20.0.0/16 belong to Ashburn DC1, Data Hall A". The first release has a small fixed set of rule types, each turning one strong signal into one fact:

Rule type Condition Sets

Network location

Reporting subnet or intake key

Site and location

Top-of-rack switch

The resource’s LLDP neighbor is a switch placed in a rack

That rack, without a rack unit

Ownership

Hostname pattern or a label reported by the collector

Owner team

Hardware type needs no rule: RFD 6 catalog matching assigns it from reported manufacturer and model, and an ambiguous match becomes a finding.

Every rule:

  • shows a preview of the existing resources it matches and the facts it would set before it is saved;

  • applies to existing and future discoveries, with each value it sets carrying the rule as its provenance and each application recorded in Activity; and

  • never overwrites a fact a person set and never chooses a rack unit.

New rule types are added individually when a recurring case needs one, rather than through a general rule builder.

Places

Places presents site, location, and rack hierarchy and ends in a rack elevation. The elevation draws empty units as faint rows, devices as single blocks spanning their height, front and rear side by side, and full-depth devices on the rear face. A device observed in a rack (for example through LLDP from the rack’s switch) but planned elsewhere is drawn as a dashed block with a one-step resolution. Unplaced resources in the location can be dragged onto free units.

Network

Topology

The topology view keeps RFD 7's three layers visible: the cable plan, LLDP/CDP evidence, and the confirmed cable record. Each link’s line style encodes their agreement: confirmed and agreeing, evidence without a record, planned but not seen, and plan and evidence disagreeing. Selecting a link shows all three layers side by side with actions that never change the cable record without an explicit operator assertion. Unresolved neighbors are listed with the map.

Switch ports

Switch object pages have a Ports tab with a front-panel view colored by port state and a port table showing link speed, LLDP neighbor, cable, mode, and untagged and tagged VLANs. A port with VLAN drift expands in place to show desired and observed membership.

VLANs

The VLAN area lists VLAN groups with an ID-range usage strip, then VLANs with planned and observed member counts. A VLAN’s detail lists interfaces with planned versus observed membership and its linked prefixes.

Prefixes

The prefix view changes with the size of the space:

Selection Visualization "Used" means

IPv4 prefix with at most 1,024 addresses

Per-address map

Host utilization percentage

Any container, IPv4 or IPv6

Child-prefix space map; each cell is the next planning level and opens it

Children allocated, such as "5 of 256 /56s"

IPv6 /64 or larger IPv4 leaf

Address table

Address counts, never a percentage

IPv6 presentation additionally:

  • dims the shared prefix so interface identifiers stand out;

  • shows how each address was assigned (static, SLAAC, or DHCPv6);

  • hides temporary privacy addresses by default;

  • treats observed-only addresses as normal rather than as findings, with an explicit "adopt" action when an address needs managed state; and

  • shows dual-stack coverage for the VLAN the prefix serves.

An address-family switch (IPv4, IPv6, both) and a routing-table switch (global or a VRF) apply to the whole view.

The "both" view shows each family’s own tree side by side; it never merges families into one row, because containment hierarchies differ between families. A prefix linked to a VLAN that also carries the other family shows a link to its counterpart, and selecting either highlights both. A VLAN-linked prefix whose VLAN lacks the other family is marked as single-stack. The VLAN, not the prefix tree, is where both families are shown together, with dual-stack host coverage and the hosts missing a family. Pairing derives from the existing optional prefix-to-VLAN relationship and needs no new model. An optional organization addressing plan (for example /48 site, /56 hall, /64 VLAN) drives next-free allocation.

Editing hardware components

On a resource

The Hardware tab compares expected and observed components slot by slot, with runs of matching slots collapsed. Each row has one of four states: match, missing, not expected, or local change. Editing a component asks what happened rather than presenting raw fields:

Choice Effect Who

It is out temporarily

Accepts the gap until a date; the expectation stays

Any member

A replacement was installed

Records the part as confirmed; the finding closes when a collector reports it

Any member

This resource should expect something else

Changes the expectation for this resource only; the catalog is unchanged

Owner or admin; members create a request

In the catalog

Editing a hardware or module type creates a draft revision that saves automatically. Templates are edited in groups using name patterns such as DIMM {A,B}{1..16}, attributes are key/value rows instead of raw JSON, and each template explains how collector reports are matched to it. Before publishing, the draft lists its changes and the impact on resources pinned to earlier revisions.

Publishing never moves existing resources. New resources use the latest revision. Existing resources move individually from their Hardware tab or in bulk from the type’s "Used by" list. Bulk moves use the standard list with a preview of findings opened and closed, and a shortcut to select resources whose observed hardware already fits the new revision. An optional per-type setting moves a resource automatically once it fits, which can only close findings and never opens them.

Visual design

The UI moves to plain Tailwind with design tokens defined as CSS custom properties, and stops using daisyUI. Shared components are built against those tokens.

Each person chooses a theme (light, dark, or match system) and one of five accents: Copper, Petrol, Cobalt, Iris, or Monochrome. Copper is the organization default, and owners may change the default for new members. Each person also chooses a density: comfortable (the default) or compact. Density is expressed only through tokens (row height, padding, table text size, and rack-unit height) consumed by shared components; no screen handles density on its own. On touch devices, tap targets stay at least 44px at either density. Preferences are stored per user so they follow the person across devices.

Status colors are fixed and independent of accent and theme: green for healthy, yellow-ochre for warnings and drift, red for failures, and a neutral for unknown. Warnings use ochre rather than amber so they never resemble the Copper accent. Every status also has a distinct shape.

The page title drops the generator’s " · Phoenix Framework" suffix.

Phone and tablet

Phones are used in two situations: an operator on call acting on one problem, and facilities staff at a rack finding a device and recording physical work. A short list of tasks is designed and tested to be fully usable at phone width (390px); every other screen remains readable, with wide tables scrolling horizontally and edits linking to the desktop view.

Situation Phone-complete task

On call

Inbox: read a finding, assign it, snooze it, or accept it as an exception

On call

Object page: read all tabs and change lifecycle

Both

Search and the command menu

On the floor

Find a device by name, serial number, or asset tag

On the floor

Rack elevation, one face at a time, scrolling vertically

On the floor

Place a device in a rack by choosing a unit from a list instead of dragging

On the floor

Hardware tab: record "out temporarily" or "replacement installed"

On the floor

Triage: place or assign one item at a time

Topology, switch ports, VLANs, prefixes, catalog editing, bulk moves, and settings other than appearance are readable but not editable on a phone. Tablets use the desktop layout with the touch rule from Visual design. The list grows when a recurring phone task appears; additions are amendments to this RFD.

Scanning an asset tag or serial-number barcode with the device camera to open a resource is a natural follow-up for on-floor work. It needs camera permissions and label conventions and is left to a later RFD.

Extension points

Later capabilities plug into the shared patterns rather than adding top-level areas:

Extension point osquery Virtualization

Resource kinds

None required

Virtual machine and hypervisor kinds related by "runs on"

Object tabs

Software, users, and processes

Virtual machines on a host; host on a virtual machine

Sources and provenance

osquery as another evidence source

libvirt and other providers as evidence sources

Findings and Inbox

Policy or compliance findings

Drift, orphaned disks, and placement conflicts

Actions

"Run query", gated by capability and policy

Lifecycle operations, gated by capability and policy

Collector capabilities

Shown on the collector and the resource

Shown on the collector and the resource

Every future RFD that adds user-facing behavior states which extension points it uses. A proposal that needs a new top-level area must explain why none of these points fit.

Security and authorization

Presentation never replaces context-level authorization. Inbox workflow changes, exceptions, requests, approvals, triage rules, revision moves, and appearance defaults are authorized in their contexts and recorded in Activity. Requests exist because a member lacks permission; approving one applies the change as the approver with the requester recorded. Saved views and preferences are scoped to the organization or user that owns them, and a shared view never reveals data its viewer cannot otherwise read.

Actions that later control hosts (queries, terminal access, virtual machine operations) continue to follow RFD 1's control-plane rules; the command menu only surfaces them.

Alternatives considered

  • Polish the existing pages. Cheaper, but keeps the per-domain structure that makes every new capability add navigation.

  • A manual triage flag. Simpler to explain, but adds a status to read, does not leave the queue on its own, and floods during onboarding.

  • A general triage rule builder. Covers every case, but broad rules can write wrong data at scale, are hard to preview and explain, and turn Renga into a rules engine.

  • Letting people resolve findings. Familiar from issue trackers, but lets the Inbox disagree with observed reality.

  • Moving all resources on catalog publish. Keeps the fleet uniform but can open hundreds of findings at once.

  • One density, or density per saved view. A single density compromises for both operators and on-floor tablet use; per-view density makes shared views look different to each viewer and adds settings to every view.

  • Full phone parity, or no phone guarantees. Parity is expensive for screens that do not fit 390px, such as topology and switch front panels; no guarantees leave on-call and on-floor work stuck until someone reaches a desk.

  • A single fixed palette. Simpler, but the team preferred personal choice; fixed status colors keep the meaning shared.

  • One address visualization for all prefixes. Works for small IPv4 subnets only and is meaningless for IPv6.

  • Pairing IPv4 and IPv6 prefixes on one row. Shows dual-stack at a glance, but the families' containment hierarchies differ, so a paired row has no correct parent, and it only works for VLAN-linked prefixes.

Rollout

  1. Introduce design tokens, remove daisyUI, and build the shared component set: list, object page, properties panel, status strip, side panel, command menu actions, and confirmations.

  2. Replace navigation with the six areas, generated from one definition, and redirect existing routes.

  3. Move Inventory and resource object pages onto the shared list and object page, including provenance and drift on values.

  4. Add finding workflow state and the unified Inbox; retire the three findings pages.

  5. Add computed triage and the first triage rules.

  6. Rebuild Places with the rack elevation.

  7. Rebuild Network: topology, switch ports, VLANs, and scale-aware prefixes.

  8. Add component editing, member requests, catalog draft revisions, and revision moves.

  9. Add appearance preferences and the organization default.

  10. Restyle authentication and settings pages onto the shared components.

Implementation

Progress against this proposal is tracked in the RFD 8 implementation checklist.