docs/outpost-template-ui-review.md
Rama main · réplica de lectura del repositorio original.
# Outpost template UI review — 2026-10-05
Independent reviewer: `/root/outpost_ui_review`. The covered self-hosted dashboard UI is approved after source review, successful rendered checks and screenshot inspection. This record does not approve a release or claim Outpost runtime acceptance.
## Source and evidence
- PR head: `2cb30a8c035a3c9483b2233374ca7367ff28fce7`.
- CI checkout: `de671fa7e9b3213fabe7af81cb403dce40da739c`, the GitHub PR merge ref. Its tree `7b9ea499b2da61c183a78a3ad160a8ef8b6d3082` exactly matches the PR head.
- Catalog: `5cbe8a06b4bf5aab8aced29cc64ac0bcc4316d25`. The later rebased catalog `c7c4ef4` has the same tree, `471b70e45689549be07cbb701999c447131f885f`.
- Successful GitHub-hosted capture: [run 37257938288](https://github.com/hakopod/hakopod/actions/runs/37257938288), artifact `11323307183`, `outpost-ui-review` (7,491,042 bytes).
- Results JSON SHA-256: `b47f95b00e6584fe5fc3380f3f7513fe200585d296fef144112ade0a7207ada2`.
The fixture loads the real shared dashboard shell, catalog, configuration and secret-review components. Catalog metadata and all eight dependency plans are generated by Go. Identity, project, secret metadata and intentional request failures are explicitly synthetic. Secret PUT bodies are redacted before retention. The fixture never reports successful deployment or contacts an external provider.
## Rendered coverage
The matrix used Chromium in dark and Paper themes at 1440, 390 and 320 pixels. It retained 52 screenshots and recorded zero page errors or assertion failures. Each route waited for its expected loaded body, fonts and completed animations; unexpected loading, empty, error and route-boundary states were rejected outside their intentional cases.
| State | Coverage |
| --- | --- |
| Filtered catalog | Both themes, all three widths; decoded Outpost logo and one result |
| Outpost inspector | Keyboard open, Escape and return to the originating card at every width; screenshots at 1440 and 320 |
| Bundled configuration | Both themes, all widths; external Redis fields absent |
| Bundled review | Exact six selected secrets checked at all widths; screenshots at 1440 and 390 |
| Existing PostgreSQL with bundled Redis/RabbitMQ | Exact selected secret list and request values, both themes at 390 |
| All external configuration and review | Both themes, all widths; conditional Redis settings, exact selected secret list and actual plan-request values |
| Failed review | Draft preservation checked at every width; visible failure captured at 320 in both themes |
| Provider secret editor failure | Masked input and preserved value, no generated external-URL action; screenshots at 390 and 320 in both themes |
| Denied, empty and catalog failure/retry | Dark 1440 and Paper 390; denied deployment controls absent and retry returns loaded catalog cards |
Fourteen plan requests were checked across bundled, mixed and all-external selections. The reviews retain the stable API/JWT/encryption/Redis secrets while swapping bundled database/broker passwords for external URLs as selected. Deployment remains disabled with missing secrets.
Geometry checks verify the shared 24px/16px page inset, full-width heading dividers, balanced heading padding, a single h1, label/control alignment, input and action bounds, inspector bounds and absent decorative self-hosted brackets. The inspector, popup and help controls remain within the viewport. Actions remain at least 32px tall, and narrow controls reflow without clipping their labels.
Normal Shift+Tab from the application-name input focuses the section help and reveals its tooltip at all six theme/width combinations. Escape dismisses it. Direct mobile taps on help open and close it at 390 and 320 in both themes; these checks use no programmatic help focus or repositioning. The Redis choice is changed using ArrowDown, End and Enter after the relevant option receives focus. Inactive external Redis drafts survive a mode round trip. Review and secret-save failures retain typed values.
## Independent visual inspection
The reviewer inspected the catalog, inspector, bundled and external forms, review notes, selected secret lists, masked secret editor, failure notices, permission state and empty/retry states. All 52 screenshots were represented in contact sheets, with additional native-size crops of the external Redis settings, selected secret lists and mobile secret editors. Full-resolution screenshot content was reused to make these inspection aids; no browser or application test ran locally.
The inspected typography, dark/Paper contrast, conditional-field hierarchy, secret descriptions, focus outlines and narrow action wrapping remain readable. Mobile secret actions stack within their rows and the inspector footer stays reachable. No actionable Outpost UI finding remains.
Long full-page captures were taken at several scroll positions. They can include the fixed, off-viewport skip link inside the expanded screenshot canvas; the source positions its unfocused element above the actual viewport. This artifact is not evidence that the link was focused or overlaid on the active viewport. The normal help-focus and touch results above come from interaction assertions and their corresponding rendered captures.
## Capture corrections and limits
Initial runs were not used as final approval: `37256884490` sent keyboard selection before Radix focus settled; `37257210901` jumped help focus while the form was scrolling; `37257658364` and `37257786489` asserted inspector focus return before asynchronous restoration. The final harness waits for actual focused options and originating-card restoration, and uses ordinary keyboard/touch traversal for help. No product component was changed to make those checks pass.
This pass covers the self-hosted edition and three representative dependency combinations. It does not newly verify Cloud edition gates, every one of the eight dependency combinations in the browser, expanded canonical TOML interaction, every diff row, successful secret persistence, deployment, server-side authorization, startup, delivery, databases, external providers, backups or recovery. The full canonical drawer stayed closed; Go/runtime validation is separate. Physical devices, assistive technology, other browser engines and a broad animation audit were not covered. Subsequent nonvisual validation changes require their own tests, and any user-visible catalog change needs a content comparison before publication.
## Migration content supplement — 2026-10-05
Independent reviewer: `/root/outpost_content_review`. The changed migration
configuration is approved for the covered dashboard presentation after source
comparison, GitHub-hosted capture and inspection of all 32 resulting screenshots.
This extends the preceding review only to the migration diff and selected
canonical TOML passages; it does not add runtime acceptance.
The capture source is `6e212b0cdd7e4db5733ec9da047310b219d112c8`, with catalog
`d6467a12881798a379ba6a71e8951fd88ed38049`. Product source remains equivalent to
`708e0b1e75b5e69513a856322786519ddc4bc812`; the two later commits only add and
adjust review tooling. Compared with catalog `5cbe8a0`/`c7c4ef4`, the catalog's
JSON, logos, form labels and secret descriptions are unchanged. Only Outpost's
README and native TOML changed. The source comparison covers the bounded
migration-plan loop, one migration apply, required broker/encryption configuration
and bundled PostgreSQL's TLS override. The planner removes that override for an
external database. Private-hostname validation changes have separate tests and
do not change displayed field copy.
[Capture run 37260525089](https://github.com/hakopod/hakopod/actions/runs/37260525089)
passed eight cases: Paper and dark themes at 1440 and 320 pixels, each with bundled
or external PostgreSQL while Redis and RabbitMQ stay bundled. Its 40 observations
comprise 32 screenshots with measured bounds and eight interaction/content
records. There were no page errors or assertion failures. All documents match
their viewport width. The inspected command, argument row and complete 300-pixel
canonical pane stay within the viewport and above the review footer.
The harness follows the real diff pagination to `migrate.command` and
`migrate.args`, checking their complete displayed values against the Go plan.
It opens the native canonical disclosure and verifies its full text equals the
same plan's TOML. Desktop pagination/disclosure activation uses Enter after
programmatic initial focus; mobile uses emulated touch. Tab enters the code pane
from a programmatically focused disclosure. Its visible focus outline measures
2 pixels. ArrowRight moves the pane horizontally by 33–36 pixels without moving
the document. Positioning the command and environment passages for screenshots
is programmatic and is not counted as keyboard or touch traversal.
Every theme/width/dependency case was inspected at screenshot resolution. The
long migration argument wraps within the diff row, including the retry loop and
single apply command. Redacted environment/secret summaries remain distinct from
the visible command and binding references. The canonical pane keeps its native
bounded scrolling, legible contrast and complete focus outline. The environment
captures retain 4–7 pixels of horizontal scroll after the key check, so the first
character can be partly outside the pane; the exact-text assertion and earlier
zero-offset command captures distinguish scrolling from lost content. These are
selected passages, not a visual reading of every canonical line. No actionable
source or visual finding remained within this supplement.
The first supplemental run, `37260259690`, passed its assertions but left the lower
canonical pane behind the existing sticky footer in some screenshots. It is
retained as capture-framing evidence, not final visual approval. The final harness
centers each target, verifies full vertical bounds and waits for substantial
horizontal key movement. No product component changed for that correction.
Final evidence is artifact `11324685878`, `outpost-ui-review`, 1,223,121 bytes.
Its archive SHA-256 is
`f47b1221eb668d8e1670ab9805df1520cc0dc4ed585949418a4763db88e16d08`;
the results JSON SHA-256 is
`4555eb3f556a3952d675da5398e2a2b2b11abe86fd015f213f77d8987e81ddae`.
Both were independently verified. Captures, browser execution and fixture builds
ran on GitHub-hosted CI. Local work only read source, edited review tooling and
inspected the downloaded evidence.
This supplement does not re-review the broader forms, Cloud edition gates,
every provider combination, full keyboard traversal, physical devices, assistive
technology, other browser engines or no-JavaScript behavior. It does not execute
migrations or prove deployment, provider TLS, delivery, persistence, backup or
recovery. Those remain separate checks. The preceding full review remains the
evidence for unchanged route presentation and interactions.
## Standing checklist
The copied checklist is the reusable review gate. The coverage above records the result; unrelated dashboard routes and unexecuted states are not represented as newly tested.
### Layout and hierarchy
- [ ] The shared page container supplies 24px horizontal padding at 640px and above, 16px below. Nested pages fill its content box without duplicate insets, centered margins or width caps. Headings, summaries and lists align. Settings fill the area beside their navigation; embedded auth does not double its parent's inset.
- [ ] Page-heading and page-level tab-row bottom dividers reach both viewport edges. Full-width row backgrounds and borders do not shift their labels outside the content inset or cause document overflow. Internal card/inspector dividers stay within their component.
- [ ] Shared layout/spacing uses Tailwind utilities in JSX or `@apply` within semantic CSS classes. Responsive rules use the shared breakpoint; raw CSS remains for component-specific behavior. There are no competing page padding overrides.
- [ ] Side-by-side settings share heading, control and help rows. Measure matching labels and control top/bottom edges on the Y axis, including wrapped help and validation states. Do not pair a control with an internal heading against a sibling with an external label. Check alignment visually as well as checking overflow; use shared grid tracks where content can wrap.
- [ ] Page and form-section headings have no decorative icon or visible description. One title carries the context; necessary actions remain aligned. Status and data needed for decisions stay visible; explanatory prose moves to help.
- [ ] Help is short, named, keyboard reachable and available on touch. Focus/hover or activation reveals it; Escape dismisses it; it stays inside the viewport. It is not the sole home for essential warnings or field instructions.
- [ ] Pages have one h1, sensible subordinate heading order and no duplicate headings or breadcrumbs. Nested back navigation uses the global header.
- [ ] Projects is the default home regardless of saved scope. Application lists are URL-scoped to a valid project and environment; invalid or unavailable scopes never fall back silently or display another project’s cached data.
- [ ] Page-heading vertical padding is balanced above and below at every responsive layout.
- [ ] Active main navigation, tabs and Settings/preferences sections use the shared theme-aware red for text and icons, with no selected underline, border or background fill. Hover/focus preserve the selected color and visible keyboard focus; ordinary row dividers remain visible.
- [ ] The active section remains visible inside scrollable navigation after deep links, selection changes, font loading and resizing, without scrolling the document.
- [ ] Desktop navigation is one compact row. Mobile reflow and long names do not cause document overflow or clipped actions.
- [ ] Summaries are inline and compact. Catalog lists have no outer panel border. Cards keep restrained surfaces, readable spacing and meaningful hover/focus states.
- [ ] Application/service grids use at most four normal desktop columns and five wide columns. Sparse grids retain card widths.
- [ ] Action links use shared Button with asChild. Sibling actions have equal height and vertical alignment; labels remain readable and targets usable.
- [ ] Application endpoint text and external-link icon stay on one line; long labels truncate without hiding the destination from assistive technology. Alarm links have visible separation from the preceding content.
### Components and interaction
- [ ] Consume Hatch through public exports. Use shared tokens for color, spacing, state and typography; check dark and Paper themes.
- [ ] All selects use SelectField, including disabled/empty options and accessible labels. Do not add native selects or a competing wrapper.
- [ ] Keyboard focus is visible. Cards preserve native links and independent menu/copy actions. Disabled/loading controls cannot double-submit.
- [ ] Forms with more than four inputs use nested pages. Labels, contextual instructions and validation stay associated with inputs. Textareas can expand where useful.
- [ ] Consequential actions show a review/confirmation, and failed requests preserve entered values. Permission failures are clear.
- [ ] Before screenshots, wait for the route’s expected body or control, lazy imports, query completion and fonts. Reject unexpected loading placeholders, rendered error boundaries and fixture schema errors. A page title or clean console alone is not evidence that the page loaded.
- [ ] Empty, loading, denied, failure and stale-data states remain usable without artificial success. Long IDs, URLs, values and translated-length text wrap or scroll within their component.
### Data, safety and cost
- [ ] Display actual backend observations; separate desired, observed, pending and stale state. Never fabricate metrics, logs or deployment success.
- [ ] Secrets are write-only, roles are enforced by Go, and mutation controls respect access. Review shared-secret impact before replacement.
- [ ] Polling, streaming, caches and buffers are bounded and inactive work stops. Do not add dependencies or runtime services for cosmetic changes.
- [ ] Product copy is concise plain English with no emojis. Avoid repeated context and implementation jargon in routine flows.