# Hotfix10 Visual Fidelity Firewall + Template Thumbnail Upload — Implementation State

Date: 2026-08-24  
Source baseline: `texise-saas-r14.28.20-buildfix49-hotfix10-protected-source-navigation-admin-cloud-complete(1).zip`  
Status: source implementation complete; clean-tree dependency-free certification complete; final single-root source archive produced; dependency-backed workspace/browser gates remain external.

## Objective

Harden Visual mode for arbitrary scientific LaTeX without template-specific rules, and add first-class catalog thumbnail management to `/admin/templates`.

The ICASSP project supplied with this work is a regression fixture only. Production logic contains no `ICASSP`, `spconf`, fixture filename, image-name, or line-number branch.

## Visual fidelity firewall

- Every meaningful body span is projected as an editable Visual node or an immutable Protected LaTeX node; meaningful unclaimed ranges fail closed instead of disappearing.
- Common heading commands are recognized generically: `part`, `chapter`, `section`, `subsection`, `subsubsection`, `paragraph`, and `subparagraph`, including starred forms.
- Simple headings remain editable; unsafe/complex headings retain one immutable source-backed heading proxy.
- Source-only comments and whitespace are preserved outside the top-level ProseMirror document in a source-layout sidecar. This prevents `% -----` comments from appearing as horizontal bars while keeping exact source bytes.
- The preamble/document setup is represented by one non-serializing immutable proxy linked to its exact Source range; canonical preamble bytes remain owned by the document shell.
- Bibliography, layout commands, unsupported environments, labels, and other non-editable meaningful LaTeX use protected source-backed proxies.
- Standalone `\includegraphics`, including grouped forms such as `{\includegraphics[...] {...}}`, is recognized even outside a `figure` environment and becomes a protected figure when it cannot be edited safely.
- Complex figures remain atomic/immutable and expose all discovered graphics assets for preview.
- Graphic lookup supports extensionless targets and browser-renderable alternatives. PDF graphics render through PDF.js; the `page=` option is honored where supplied.
- Asset failures have explicit missing/unsupported/render-error states. A failed preview never removes the protected LaTeX component.
- Protected nodes keep canonical `sourceFrom`/`sourceTo` navigation and support pointer plus Enter/Space activation.
- Component-level semantic parsing is fail-closed: an unexpected parser failure protects the canonical document body instead of returning a partial/blank Visual manuscript.
- No-op Source→Visual→Source projection preserves top-level whitespace/comments exactly. Existing source-backed adjacency is retained; newly-created Visual blocks alone receive canonical separators.

## ICASSP regression evidence

A dependency-free runtime semantic check against the supplied `Template.tex` found:

- 14 semantic headings.
- 14 Visual heading projections.
- The complex figure exposes `image1`, `image3`, and `image4` assets.
- The extensionless `image3` graphic is represented as a figure asset and can resolve to its project PDF through the generic asset resolver.

This fixture is not referenced by production implementation code.

## Template thumbnail management

- `/admin/templates` now supports thumbnail upload, replace, and remove in addition to the advanced path field.
- Thumbnail upload accepts PNG, JPEG, or WebP up to 5 MB and validates actual file signatures rather than trusting the browser MIME type/extension.
- Managed uploads use deterministic `thumbnail.png`, `thumbnail.jpg`, or `thumbnail.webp` names and remove stale managed variants when replaced.
- Clearing a managed thumbnail deletes uploader-managed files but does not blindly delete an arbitrary manually-referenced template asset.
- Upload/remove operations synchronize template assets and produce dedicated audit events.
- Public thumbnail delivery reuses `/api/templates/:slug/assets/thumbnail`.
- The supplied A4 WebP is installed once as `/texise-template-default-thumbnail.webp` and is used for catalog cards only when no admin thumbnail is configured.
- Catalog cards deliberately do not substitute Template Preview/PDF assets for a missing thumbnail.
- `/templates` card imagery now uses an A4 portrait `210 / 297` surface with `object-fit: contain` and top-centered positioning.
- Full/Quick Preview behavior remains independent from catalog-thumbnail behavior.

## Modified/new implementation files

- `packages/core/app/src/components/latex-visual-editor.tsx`
- `packages/core/app/src/saas/saas-api.ts`
- `packages/core/app/src/saas/saas-app.tsx`
- `packages/js-lib/latex-visual/src/native-texise-editor.ts`
- `packages/js-lib/latex-visual/src/__tests__/visual-bf4-native.spec.ts`
- `packages/js-lib/project-semantic-index/src/index.ts`
- `packages/js-lib/project-semantic-index/src/__tests__/semantic-index.spec.ts`
- `packages/tooling/browser-entry/public/texise-template-default-thumbnail.webp`
- `packages/tooling/browser-entry/src/index.css`
- `packages/tooling/browser-entry/src/saas.css`
- `packages/tooling/e2e-tests/src/latex-visual-semantic.e2e.ts`
- `packages/tooling/e2e-tests/src/template-thumbnail-hotfix10.e2e.ts`
- `server/saas-router.mjs`
- `server/template-library.mjs`
- `server/template-library.node.test.mjs`
- `scripts/hotfix10-admin-template-management-regression.test.mjs`
- `scripts/hotfix10-complex-latex-editor-regression.test.mjs`
- `scripts/release-runtime-hardening.test.mjs`
- `scripts/repair-buildfix49-source.mjs`

## Verification completed in this source-only environment

- `node --test server/*.node.test.mjs`: **121/121 PASS**.
- `node --test scripts/*.test.mjs`: **280/280 PASS**.
- `node --test scripts/release-runtime-hardening.test.mjs`: **101/101 PASS**.
- `node scripts/repair-buildfix49-source.mjs .`: **PASS**.
- `node scripts/texise-release-audit.mjs`: **362/362 PASS**.
- `node scripts/texise-saas-static-audit.mjs`: **44/44 PASS**.
- Changed TypeScript/TSX files pass TypeScript syntax/transpile parsing with the locally available compiler.
- Modified `.mjs` files pass `node --check`.
- The installed default thumbnail is byte-identical to the supplied WebP (SHA-256 `2a0ce5b2bd7816ab4960f3e2e9b95e0baf1cd693a071a8537888b57d537e5fae`).
- Production hard-code scan for `ICASSP`, `spconf`, and fixture-specific `image3` references is clean in the changed production paths.

## External release gates not run here

The uploaded source archive does not include the monorepo dependency tree, and Corepack cannot download the pinned pnpm package because network package retrieval is unavailable in this execution environment. Therefore the following must still run in a normal release runner before production activation:

- `pnpm run lint:ci` / full workspace typecheck and Biome.
- Vitest dependency-backed workspace suites, including the native ProseMirror tests.
- Production Vite build.
- Playwright browser E2E, including the new Visual-fidelity and template-thumbnail scenarios.
- The normal complete `pnpm run release:quality` certification pipeline.

These are environmental certification limits, not known source failures. All dependency-free gates available in this environment are green.


## Final packaging

- Temporary test-only workspace symlinks and the staging copy of the supplied thumbnail were removed before final certification.
- The deliverable archive contains exactly one top-level `public_html/` source tree.
- The archive is verified with `unzip -t` after creation and accompanied by an external SHA-256 checksum file.

## Follow-up Visual round-trip and catalog interaction hardening (2026-08-24)

After browser validation exposed two remaining Visual-mode failure classes, the implementation was hardened further without adding template-specific production rules:

- Protected LaTeX boxes now display the **complete original protected source** instead of a comment-stripped/truncated excerpt. This applies to complex figures and other unsupported constructs, ensuring an image/PDF preview failure can never leave an empty protected box.
- Complex protected figures now always include a `Complete LaTeX` source panel in addition to any resolved graphic previews, caption/asset metadata, and exact `Open in Source` navigation.
- Document Setup displays the full original pre-`\\begin{document}` source (comments, package setup, definitions, metadata and publisher-specific commands included) while retaining the existing non-serializing source-range mapping.
- Standalone comment-only/whitespace source remains invisible manuscript trivia. Comments embedded inside a protected construct are shown verbatim inside that protected construct's source panel.
- A deliberately narrow plain-prose recovery path prevents ordinary user-authored prose from being swallowed by a generic protected fallback when a semantic boundary is missed. The recovery excludes TeX-special syntax, comments, math/control syntax and multi-paragraph gaps so meaningful unsupported LaTeX remains fail-closed.
- `/templates` cards are now one keyboard-accessible Quick Preview surface; the redundant card-level `Quick Preview` and `View details` actions were removed.
- `Fresh starting points` now follows `All templates`, selects four templates, and uses a four-column desktop grid with two-column tablet and one-column mobile fallbacks.
- Regression coverage was extended for complete protected source, ordinary-prose round trips, card interaction/order, and four-card Fresh layout.

### Follow-up verification

- `node --test server/*.node.test.mjs`: **121/121 PASS**.
- `node --test scripts/*.test.mjs`: **280/280 PASS** (the aggregate R14.28.20 guard was updated from the former 9-test Hotfix10 sub-suite count to the current 11-test count).
- `node scripts/hotfix10-complex-latex-editor-regression.test.mjs`: **11/11 PASS**.
- `node scripts/texise-release-audit.mjs`: **362/362 PASS**.
- `node scripts/texise-saas-static-audit.mjs`: **44/44 PASS**.
- Modified `.mjs` files pass `node --check`.
- All six modified TS/TSX files in this follow-up pass TypeScript parser/syntax validation using the locally installed compiler.
- Production fixture-hardcoding scan remains clean for `ICASSP`, `spconf`, and `image3`.
- ICASSP regression fixture audit confirms **14 structural headings** and the three expected generic graphic references (`image1`, `image3`, `image4`) with PDF assets present. These values are used only for test evidence, never production branching.
- Installed default template thumbnail remains byte-identical to the user-supplied WebP (SHA-256 `2a0ce5b2bd7816ab4960f3e2e9b95e0baf1cd693a071a8537888b57d537e5fae`).

## Post-package lint correction — Template catalog card accessibility

Production `pnpm run lint:ci` on pnpm 11.6.0 identified one Biome accessibility diagnostic in `TemplateCard`: a semantic `<article>` was assigned `role="button"` so the whole card could open Quick Preview. The card container is now a neutral `<div role="button" tabIndex={0}>` with the existing click and Enter/Space handlers preserved. This follows Biome's `lint/a11y/noNoninteractiveElementToInteractiveRole` guidance without disabling or suppressing the rule. A regression assertion now prevents the template-card implementation from returning to an interactive-role `<article>`.

Verification after the correction:
- `node --test scripts/hotfix10-complex-latex-editor-regression.test.mjs`: 11/11 PASS.
- `node scripts/texise-release-audit.mjs`: 362/362 PASS.
- `node --test server/*.node.test.mjs`: 121/121 PASS.
- Full dependency-backed `pnpm run lint:ci` should be rerun on the deployment host; the reported source diagnostic has been removed at its source rather than suppressed.

## Runtime Fix 2 — protected source DOM, multi-paragraph recovery and compact template-card height

A production browser re-test after `lintfix1` showed that source-only nodes could still present as visually empty boxes and that ordinary multi-paragraph Visual text could still be swallowed by a generic Protected LaTeX fallback after Source → Visual. The catalog grid also stretched shorter template cards to the row height.

This follow-up fixes those runtime boundaries generically:

- `latex_raw_block` now has a dedicated ProseMirror NodeView. The NodeView explicitly writes the protected header, source text, figure preview/status, caption/label metadata and footer into the DOM on both creation and node updates. Protected rendering therefore no longer depends solely on schema `toDOM` reconciliation.
- Protected-source selection now rejects whitespace-only display payloads and falls back to canonical `latex`; if both are unexpectedly empty the UI shows an explicit source-unavailable message rather than an empty rectangle. CSS also supplies an `:empty` last-resort label.
- The Document Setup proxy now stores the complete pre-`\\begin{document}` source in both `latex` and `displayLatex` while remaining `serialize:false`, so it cannot duplicate the preamble during serialization but cannot lose the complete source during rendering either.
- Complex figures display `Complete LaTeX` before the image-preview area, so the raw figure/environment source is immediately available even while PDF/image previews are loading or if they fail. Extensionless/PDF asset resolution remains generic.
- Plain raw/gap source recovery now supports multiple TeX-free paragraphs. It splits them into source-backed editable paragraph nodes and preserves exact blank-line separators through the existing sidecar trivia layout. Real TeX syntax/comments/math still fail closed into protected source.
- `/templates` cards now opt out of CSS Grid stretching with `align-self:start;height:fit-content`; both All Templates and Fresh Starting Points grids align items to `start`, so each card finishes at `.texise-template-card-body` instead of gaining blank height to match a taller neighbor.

### Runtime Fix 2 verification

- `node --test scripts/hotfix10-complex-latex-editor-regression.test.mjs`: **11/11 PASS**.
- Full dependency-free script regression suite (run sequentially to avoid harness timeout): **280/280 PASS**.
- `node scripts/texise-release-audit.mjs`: **362/362 PASS**.
- `node scripts/texise-saas-static-audit.mjs`: **44/44 PASS**.
- `node --test server/*.test.mjs`: **121/121 PASS**.
- Modified TS/TSX files have zero parser diagnostics using the locally installed TypeScript 5.8 parser.
- Full dependency-backed `pnpm run lint:ci` / production build / Playwright must still be rerun on the deployment host, which has the workspace dependency tree.
