Skip to content

design

Part of the standalone star-trek product (see ../../DESIGN.md for why this isn’t an Atlas flow). Sibling to the Field Marshal persona (flows/field-marshal/), which creates the areas and agents this flow supervises.

Live interactive prototype: ./index.html

Every shell primitive — the #scr-login split sign-in (identical byte-for-byte apart from the prefilled email), sidebar/topbar, .tbl/.pstat/.dlg/.badge/.fld/toast, the Vehicle Gallery card view — is copied byte-for-byte from flows/field-marshal/index.html, not re-derived. Only the login copy (“Sign in to your Grand Admiral workspace”) and the signed-in user (Gloria Amune, this initiative’s actual PRD owner) differ. This flow drops the Leaflet map dependency and the address-autocomplete popover entirely: the Grand Admiral never places a pin or types an address, so neither has anything to attach to here.

There is no splash/landing screen in front of login — PATTERNS.md:287 bans a splash on web outright, with no product-scope carve-out. The flow boots straight to #scr-login, never .hide by default.

Page Role
Dashboard .pstat KPIs (awaiting approval / Field Marshals / Agents / Blocked) + a cross-Field-Marshal “Awaiting your approval” table — every pending area, unrouted, regardless of who submitted it
Areas Every area across every Field Marshal, filterable by status. Row click → Area approval detail
Area approval detail .pg-back + .pstat-row + .pseg (Spot-check / Notes) — a rich record, so a details page, never a drawer
Field Marshals Table + New Field Marshal dialog. Row click → Field Marshal detail (their areas + agents), block/unblock
Agents Cross-Field-Marshal table with a Field Marshal column + within-radius fraction. Row click → Agent detail, block/unblock
Ledger Full payment ledger across every Field Marshal, with a Field Marshal filter added alongside Agent/Area/Status

Area approval is a sample, not an image-level approve/reject

Section titled “Area approval is a sample, not an image-level approve/reject”

Every image in the Spot-check tab has already been approved by the Field Marshal — this flow samples the already-approved set (plate + geolocation match) to decide on the area as a whole, so there’s no per-image approve/reject here (re-litigating individual images at this tier would duplicate work already done). What the Grand Admiral does per image is Verify it in the “View capture” dialog — a lightweight “I looked at this one” action, not a decision — which flips its row’s Reviewed badge (reviewedBadgeHTML) and increments the Sample checked KPI (renderSampleChecked) against the approved total, so the card visibly fills in as the spot-check progresses instead of showing a static pre-computed number. Deciding the area itself is still just Approve area (confirm dialog, locks pay to Finalized) and Reject area (required reason, sends the whole area back to the Field Marshal for further cleanup — the Field Marshal’s cleanup queue picks up exactly where it left off, per PRD §7.1 step 6); verifying captures isn’t a prerequisite for either, same as the plate-read tag never blocking the Field Marshal’s own approve/reject.

Blocking a Field Marshal opens a toolkit, not one fixed outcome

Section titled “Blocking a Field Marshal opens a toolkit, not one fixed outcome”

Confirming Block Field Marshal immediately chains into #dlg-toolkit: a list of every one of their still-open areas, each with its own “Reassign to another Field Marshal” or “Close & free agent” action, plus a list of their active Agents, each with its own reason field + “Block agent” action. Nothing here is forced — the PRD doesn’t specify one fixed cascade, so the dialog is a menu the admin works through at their own pace (its only footer action is “Done”). Blocking an Agent directly (from the Agents page, no Field Marshal in the loop) never closes their in-progress area — it stays open for a new Agent, and the blocked Agent’s own already-approved images remain valid for their own pay, matching the same rule already established on the Field Marshal side.

Block/unblock always requires a reason, and it’s logged

Section titled “Block/unblock always requires a reason, and it’s logged”

Every block or unblock — Field Marshal or Agent, whether from their detail page or the toolkit’s inline agent row — requires a non-empty reason before the action goes through; the same dialogs (dlg-block-marshal/dlg-block-agent) serve both directions, swapping title/copy/button class (btn-danger-out to block, btn-pri to unblock) rather than forking into four dialogs. That reason becomes the email copy sent to the affected person (Agent blocks additionally notify their Field Marshal), and it’s appended to the entity’s blockLog array ({action, by, dateISO, reason}, rendered oldest-last via activityLogHTML). A currently-blocked Field Marshal or Agent shows their latest block reason in its own “Blocked reason” card; the full history lives in a separate “Activity log” card underneath, so “why are they blocked right now” and “what happened over time” aren’t the same read.

Ledger adds a Field Marshal filter, everything else matches Field Marshal’s

Section titled “Ledger adds a Field Marshal filter, everything else matches Field Marshal’s”

Same collapsed-filter-dialog pattern, same Provisional/Finalized status model, same row-click → read-only ledger-entry .dlg (openLedgerDetail, copied from Field Marshal and given an added Field Marshal row) — because a table row with no onclick reads as non-interactive when every other row-click pattern in this product opens something, this flow keeps that click-through even though the underlying entry is read-only from here.

Shell reproduced from products/star-trek/flows/field-marshal/index.html, which itself reproduces products/atlas/flows/starter-template/index.html — see that flow’s own design.md for the shell provenance. Lint-clean via node site/scripts/lint-canon.mjs; all 5 top-level views pass flow-probe.js at the canonical 1440px width.