Ctrl K
ComunidadGuías…

docs/xem-ui-review.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Xem template UI review

Reviewed on 4 October 2026 against [the Hatch dashboard checklist](ui-ux-checklist.md).

## Current status

The real catalog entry and all eight Go-generated deployment plans passed 20 grouped browser checks and eight supplemental viewport cases. The final shared secret-editor review then passed 12 template/theme/width contexts and produced 18 screenshots on an isolated VM. Independent screenshot inspection found no remaining visual issue in the covered states. Earlier application browser acceptance passed against the corrected ARM64 images with external storage in the disposable development cluster; the final bundled-MinIO browser pass remains unverified. This document does not claim production deployment or full runtime acceptance.

The ignored fixture renders the actual dashboard shell, catalog route, template form and shared components using the real Xem catalog fields and plans generated by `spec.PlanTemplate`. The final fixture has `preview: false`; it replaced the earlier visibly marked development preview. Identity, project and request-failure data are artificial; no live account, cluster, application, secret or deployment is changed by the dashboard review. Image availability and release publication are tracked separately.

## Completed coverage

- Dark and Paper at 1440px and 390px: catalog, inspector, all eight independently bundled/external PostgreSQL, Redis and storage combinations, optional empty Redis username, retained hidden connection drafts and keyboard/touch selection.
- The default MinIO form needs no provider bucket, endpoint or region. Existing S3 reveals those fields; required bucket and endpoint fields keep Review disabled until complete. Database, Redis and S3 draft values survive toggling to bundled mode and back, checked before any fields are refilled.
- Additional 320px and 1920px default and fully external form bounds: shared insets, readable controls, one heading, no decorative brackets or document overflow.
- Reviewed secret rows match the actual Go-generated plan references: bundled storage requires `storage-user` and `storage-password`, while external storage requires the two provider-issued keys. Bundled values generate with the required formats; provider keys have no Generate action. Deployment stays disabled until required secrets are saved.
- The long form uses the existing focus-reveal behavior so tabbed controls remain visible above the action footer. Redis TLS selection stays within the mobile viewport and supports touch.
- Shared conditional-field regression tests cover all four database/Redis combinations; the eight-plan browser review checks omission of all inactive database, Redis and storage connection values from submitted configuration.
- Critical screenshot review caught touching secret-editor actions and help wrapping around Copy on mobile. The shared editor now uses wrapping flex rows with an 8px gap and a separate help row. Final VM screenshots confirmed clean wrapping at 320px, readable help, visible keyboard focus and no overlapping or clipped controls.

## RSA credential generation

The write-only secret editor generates a 2048-bit RSA key with Web Crypto, exports PKCS8 PEM, and Base64-encodes that PEM. Copy remains available before Save. The RSA input accepts up to 8192 characters so existing 4096-bit PEM keys wrapped in Base64 are not truncated; other one-line secret formats keep their existing 4096-character bound.

Generation disables repeat clicks and saving, and is bounded to ten seconds. Failure and timeout preserve the existing draft. A crypto result arriving after timeout cannot overwrite it. The error offers retry or a supplied key without displaying internal errors or key material.

A Node test decodes the generated value with `createPrivateKey` and checks RSA, 2048 bits and PKCS8. A browser component fixture verified generation, duplicate-click prevention, failure, timeout, late-result handling and importing a valid 4096-bit key at both 1440px and 390px in both themes. Generated and imported private keys were not logged or displayed in screenshots.

## Validation and evidence

- Shared UI suite: 214 tests passed, including generated credential formats, RSA decoding, bounded RSA field length and independent PostgreSQL/Redis conditions.
- Typecheck passed after async RSA generation was added; final task validation is recorded separately.
- Actual Go-generated plans: 20 grouped checks passed, covering all eight combinations in each main theme/width case, retained configuration and secret drafts, generated credential formats and edge-width forms. Results and screenshots are in ignored `work/xem-ui-review/`; `results.json` records `preview: false`.
- Eight supplemental theme/width cases cover viewport screenshots of the catalog, default form, storage menu and external endpoint focus. The menu fits at 320px and the focused endpoint remains above the sticky footer. The actual candidate has no `jobs` workload requirement.
- RSA browser component checks: `work/mathesar-ui-review/rsa-browser-results.json` and `rsa-browser.mjs`; all four theme/width cases passed.
- Three focused secret-editor unit tests passed after the spacing correction. Final VM browser coverage passed all 12 Mathesar/Xem contexts in Dark and Paper at 1440px, 390px and 320px, including 18 editor captures. Real Tab navigation verified the focus outline and footer clearance; touch activation, wrapping gaps and failed-save draft retention passed.
- The independent reviewer inspected representative Mathesar, Xem RSA and storage-user screenshots. The coordinating agent separately inspected four full-resolution captures and confirmed the final layout. Evidence is in ignored `work/xem-ui-review/remote-final/`, including `secret-layout-results.json`, `mathesar-light-390-secret-key-layout-final.png`, `xem-light-320-encryption-private-key-layout-final.png`, `xem-dark-1440-storage-user-layout-final.png` and `xem-dark-390-encryption-private-key-layout-final.png`.
- Final dependencies, fixture builds and browser execution stayed in an isolated VM scratch directory with a two-CPU and 2 GiB memory cap. No local build, test or browser runtime was used for that pass. Fixture and browser processes stopped afterward. The prepared bundled-runtime proxy was never started, and its temporary TLS material was removed.

## Real application browser acceptance

The independent reviewer used the actual paired ARM64 images on the named development cluster after the backend seed-directory permissions were corrected for its non-root user. An isolated Chromium context reached `https://xem.example.test` through a temporary loopback TLS proxy and per-process host mapping. No system DNS or trust-store setting changed.

- The native login form authenticated the generated development administrator and returned to the application. The browser stored `__Secure-authjs.session-token` with Secure, HttpOnly and SameSite=Lax.
- The native Forms page loaded successfully. Its `/api/v1/marketing/forms` and `/api/v1/marketing/options` requests returned 200 from the installation's HTTPS origin. A request interceptor recorded zero requests to `api.xem.email`.
- Using that browser session, `/api/v1/users/me` returned the fixture administrator. A real multipart text-file upload returned 200 and a stored file identity; the subsequent file lookup returned 200 and an application-signed URL. Credentials, tokens and signed URL queries were never recorded in evidence.
- Desktop login and Forms screenshots and the mobile Forms screenshot were inspected. They show the loaded, authenticated empty workspace, with no error boundary or browser exception. Aborted Next.js navigation prefetches occurred during route changes; no application API request failed.
- The browser context and TLS proxy were stopped and the runtime reviewer was signalled to continue fixture acceptance and cleanup.

Evidence is in ignored `work/xem-runtime-browser/results.json`, `journey.mjs`, `login.png`, `forms-desktop.png` and `authenticated-mobile.png`. The upload was an authenticated browser API check, not a contact-import UI test. This earlier pass used external storage and did not download the returned signed object in the browser. It does not verify the final bundled MinIO route, public DNS/TLS, provider storage CORS, real email delivery, AI features, or arbitrary external dependencies. The new bundled-storage browser pass was cancelled when the user stopped local validation; separate cluster acceptance records its own completed checks and limitations.

## Verification limits

The dashboard fixture cannot establish public patched-image availability, backend authorization, database or Redis connectivity and TLS negotiation, object-storage permissions, administrator bootstrap, delivery-provider setup, media access, migrations, restart behavior or backups. Successful deployment is not simulated. The earlier real application browser pass establishes only the scoped behavior above. Cloud edition behavior and unrelated route families were not newly reviewed.

## Standing checklist

The checklist below is copied from the shared repository-wide gate. Its unchecked boxes are reusable checklist items, not a claim that unrelated routes were tested. Completed coverage and limitations are recorded above.

### 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.