# Frontend Authoring — Improvement & Growth Plan

> Package: capell-app/frontend-authoring · Kind: package · Tier: free · Product group: Capell Foundation · Bundle: foundation · Status: Draft

## Completed Improvement Slices

- **2026-06-04:** Defined the advertised `frontend-authoring.edit` Gate as a package-owned deny-by-default ability that host apps can override, while preserving existing `editContent` / `update` pageable policy fallbacks. Focused coverage proves the ability is registered, denies by default, can be overridden, and does not suppress fallback authorization.
- **2026-06-04:** Guarded the optional Publishing Studio approval workspace branch behind the package install state and removed the catch-all fallback that converted approval failures into `in_review` saves. Focused coverage proves unavailable Publishing Studio returns a 409 without creating a workspace, installed approval still creates an in-review workspace, and approval submission failures now surface.

## 1. Snapshot

Frontend Authoring is the foundation in-page editing bridge: it adds an admin-only beacon (`POST /beacon`, `BeaconController`) that, after a public page has loaded, returns a bootstrap script decorating registered regions (page title, meta description, page content) with edit controls, plus a signed iframe editor route (`GET authoring/regions/{payload}`, `EditRegionController` → `EditRegionField` Livewire) that saves a single Filament field through `UpdateEditableRegionAction` and clears affected HTML caches. Gating is layered and genuinely defensive: the beacon short-circuits to a bare CSRF token for anonymous users, non-admins, cross-origin requests, and posted-URL/origin mismatches before any DB work (`src/Http/Controllers/BeaconController.php`); the editor route is `auth`+`signed`, payloads are HMAC-signed (`EditableRegionSigner`) and re-validated against the live manifest on every load and save (`ValidateEditableRegionPayloadAction`). Surfaces: `frontend`, `console`. Deps: `capell-app/admin`, `capell-app/core`, `capell-app/frontend`, `capell-app/html-cache`, `spatie/laravel-package-tools`. Capabilities: `authoring-surface`, `preview-only`, `beacon`, `cache-blocking`; manifest declares it non-cacheable (`cacheSafety.cacheable: false`) with a 20ms frontend render budget. Marketplace summary now leads with the live-site editing outcome while emphasizing visitor/cache safety, and Composer description is aligned. Screenshots: `marketplace.screenshots[]` now declares the extension card plus real desktop and mobile authoring captures from runner-backed `docs/screenshots/`; `docs/screenshots.json` still defines the wider browser/config proof contract for the screenshot runner.

## 2. Improvements (existing functionality)

- **Make the health check actually check something** — `FrontendAuthoringHealthCheck` only implements `compatibleCapellApiVersion(): '^4.0'`; the manifest advertises it as `severity: critical` with label "surfaces, providers, and install health are discoverable by Diagnostics." It verifies none of that. Add real probes: beacon route registered, `EditableRegionRegistry`/`EditorSurfaceRegistry`/`EditableRegionSigner` resolvable, `capell-frontend-authoring.enabled` readable, `app.key` present (signer depends on it). `src/Health/FrontendAuthoringHealthCheck.php` — S.
- **Shipped 2026-06-04: Define the `frontend-authoring.edit` Gate.** `FrontendAuthoringServiceProvider` now registers the advertised ability as deny-by-default when the host has not defined it. Host apps can override it with `Gate::define()` / `Gate::before()`, and `AuthorizeEditableRegionAction` still falls back to pageable `editContent` / `update` policies when the package ability denies. `src/Providers/FrontendAuthoringServiceProvider.php`, `tests/Feature/AuthorizeEditableRegionActionTest.php` — S/M.
- **Done/Shipped: beacon admin-manifest assembly now lives in an Action.** `BeaconController` delegates to `BuildBeaconResponseAction`, which owns anonymous/non-origin short-circuits, site/page resolution, admin user response shape, banner context, editable-region manifest assembly, and bootstrap script rendering. This keeps public no-leak behavior intact while moving domain response assembly out of the controller. `src/Actions/BuildBeaconResponseAction.php`, `src/Http/Controllers/BeaconController.php` — M.
- **Done/Shipped: editable-region field/type/surface/status logic is enum-backed.** `EditableRegionInputType`, `EditableRegionSurface`, `EditableRegionSaveStatus`, and `EditableRegionField` now back internal comparisons while `EditableRegionPayloadData::toArray()` and `EditableRegionData::toArray()` keep the same string values for signed editor URLs and beacon manifests. Custom meta paths such as `meta.summary` remain preserved while being classified as meta fields. `src/Enums/`, `src/Data/EditableRegionPayloadData.php`, `src/Livewire/EditRegionField.php`, `src/Actions/UpdateEditableRegionAction.php` — M.
- **Shipped 2026-06-04: Harden `UpdateEditableRegionAction` approval branch against duck-typing.** The approval workspace branch now aborts with 409 unless `capell-app/publishing-studio` is installed, and `submitForApproval()` failures bubble instead of being caught and forced into `in_review`. `src/Actions/UpdateEditableRegionAction.php`, `tests/Feature/EditableRegionEditingTest.php` — M.
- **Cache `BuildAuthoringBannerContextAction` table check** — it calls `Schema::hasTable(...)` on every admin beacon hit before querying `cached_model_urls`. Since html-cache is a hard dependency the table is always present; drop the probe or memoise it to respect the 20ms budget. `src/Actions/BuildAuthoringBannerContextAction.php` — S.
- **Closed 2026-06-05: Refresh the CHANGELOG.** The changelog now records real health probes, signed-payload editor flow, beacon origin hardening, optional approval-workspace save flow, marketplace/composer copy sharpening, promoted desktop/mobile screenshots, signer tamper coverage, and orphan screenshot cleanup. `CHANGELOG.md` — S.

## 3. Missing Features (gaps)

Tie-back to `capabilities: [authoring-surface, preview-only, beacon, cache-blocking]`.

- **Done/Shipped: Click-to-edit beyond text fields has a second built-in surface.** Frontend Authoring now ships a registered `media` editor surface beside `field`, and package-supplied editable-region extenders can emit `EditableRegionSurface::Media` regions with target/context metadata that round-trip through the manifest and signed edit controller. The first built-in media shell still uses the shared value editor, so richer asset-picker UX remains future Pro depth. `src/Enums/EditableRegionSurface.php`, `src/Support/EditorSurfaces/MediaEditorSurface.php`, `src/Providers/FrontendAuthoringServiceProvider.php`, `tests/Unit/Actions/BuildEditableRegionManifestActionTest.php`, `tests/Feature/EditableRegionEditingTest.php` — L.
- **Section reorder / block management on the frontend (differentiator).** `capabilities` implies an authoring surface but there is no drag-reorder or add/remove-block affordance; editing is strictly per-field, per-region. This is the single biggest differentiator vs table-stakes "edit text in place." — L.
- **Draft/preview from the frontend is half-built (table-stakes).** `preview-only` is advertised and `UpdateEditableRegionAction` has an approval-workspace path returning a `redirect_url`, but it is opt-in (`workflow.require_approval`, default false), entirely dependent on publishing-studio internals, and has no first-class "edit as draft / preview / publish" toggle in the editor UI. Promote this to a visible, supported control. — M/L.
- **Done/Shipped: role-aware region controls are available to extenders.** `EditableRegionPayloadData` now accepts a `permissions` list, `AuthorizeEditableRegionAction` requires those Gate abilities before coarse `frontend-authoring.edit` / pageable policy checks pass, and `BuildEditableRegionManifestAction` filters denied regions before returning the admin-only manifest. The manifest now declares `frontend-authoring.edit`, while package extenders can supply their own per-region abilities. `src/Data/EditableRegionPayloadData.php`, `src/Actions/AuthorizeEditableRegionAction.php`, `src/Actions/BuildEditableRegionManifestAction.php`, `tests/Feature/AuthorizeEditableRegionActionTest.php`, `tests/Unit/Actions/BuildEditableRegionManifestActionTest.php` — M.
- **No edit toolbar persistence / discoverability surface.** The bootstrap script injects a banner + per-region controls, but there is no documented public JS API or `CapellFrontendAuthoring` global for themes to hook (the anonymous browser-test asserts _no_ such global, which is correct — but admins get none either). A namespaced admin-only API would let themes register custom regions client-side. — M.
- **Done/Shipped: locale coverage extends beyond English.** Frontend Authoring now bundles `resources/lang/es/authoring.php`, mirroring the banner, editor, health, enum-label, and surface strings from English. `LocaleCoverageTest` asserts Spanish and English key parity so future authoring strings cannot drift silently. `resources/lang/es/authoring.php`, `tests/Unit/LocaleCoverageTest.php` — S.

## 4. Issues / Risks

**Public-output safety (the #1 rule) — currently strong, keep it that way.**

- Anonymous/non-admin no-leak coverage **exists and is solid**: `tests/Feature/BeaconControllerTest.php` covers guest (`returns only csrf token for guest`), authenticated non-admin (`does not return authoring scripts or metadata for non-admin authenticated user`), admin-without-permission, cross-origin admin (`does not return authoring scripts for cross-origin admin beacons`), posted-URL/origin mismatch, and **cached-HTML leakage** (`page data does not render authoring metadata into cached html`, line 383). `tests/Unit/ManifestRequirementsTest.php:54` enforces a declared browser test `anonymous-users-receive-no-authoring-surface`, and `docs/screenshots.json` codifies the assertions ("no `CapellFrontendAuthoring` global, no `capell-authoring` DOM, no `edit_url`/`recordKey`/`model`/field path/selector/label/signed URL"). This is the model other packages should copy.
- **html-cache interaction is correct by construction**: editor HTML is injected client-side by the beacon _after_ load, never rendered into Blade, so cached pages stay clean. The manifest correctly sets `cacheSafety.cacheable: false`. The risk is regression — any future change that moves a region marker, selector, or signed URL into server-rendered Blade (`resources/views/components/page-data.blade.php` is the only public-injected view and it emits only the generic beacon fetch, no authoring data) would break this. Keep the line-383 cached-HTML test and the arch/browser contract as guardrails.

**Bugs / tech debt.**

- **Stub health check** misrepresents `severity: critical` coverage (see §2). `src/Health/FrontendAuthoringHealthCheck.php` — risk: Diagnostics reports green while the surface is broken.
- **Undefined `frontend-authoring.edit` ability** (see §2/§3) — advertised gate is inert in production; real gating silently delegates to pageable policies. `src/Actions/AuthorizeEditableRegionAction.php:24`.
- **Shipped 2026-06-04: approval path now respects optional publishing-studio availability.** `UpdateEditableRegionAction` checks `CapellCore::isPackageInstalled('capell-app/publishing-studio')` before creating an approval workspace and surfaces submission failures instead of masking them. `src/Actions/UpdateEditableRegionAction.php`.
- **Closed 2026-06-05: Orphan duplicate asset cleanup.** The nested stray `packages/frontend-authoring/...` screenshot copy is gone; committed documentation image assets still live under `docs/images/screenshots/`, while marketplace and runner contract captures now use the release-gate-friendly `docs/screenshots/` location.
- **`PassThroughActivityMiddleware` is a literal no-op** aliased only when `frontend.activity` is unregistered. Fine as a fallback shim, but undocumented; a reader can't tell it's intentional. Add a class docblock. `src/Http/Middleware/PassThroughActivityMiddleware.php`.

**Test gaps.**

- No direct unit test for `EditableRegionSigner` tamper/format edge cases at the `decode()` boundary (malformed base64, missing keys, truncated signature) — these `abort(403)` paths are only hit indirectly via `EditableRegionEditingTest` ("encodes signed region payloads and rejects tampered payloads"). Add a focused signer unit test.
- **Done/Shipped: content HTML policy is explicit and covered.** Frontend Authoring keeps `content` HTML as `trusted_admin_raw`: signed editor routes are admin-only, and the package stores admin-authored content exactly as submitted so Capell's normal rendering/theme layer remains the owner of output policy. A focused test covers script-bearing HTML round-tripping unchanged under that policy. `config/capell-frontend-authoring.php`, `src/Actions/UpdateEditableRegionAction.php`, `tests/Feature/EditableRegionEditingTest.php`.
- No assertion that the beacon stays within the **`frontendRenderBudgetMs: 20`** budget; the budget is declared in `capell.json` but unverified.

**Performance budgets (cited).** `performance.frontendRenderBudgetMs: 20`, `adminQueryBudget: 0`. The anonymous beacon path is O(1) (returns before any query) — good. The admin path runs several queries (`LoadSiteDomainFromUrlAction`, `PageUrl` lookup with eager loads, registry translation load, `cached_model_urls` lookup, `Schema::hasTable`); `adminQueryBudget: 0` is therefore aspirational/irrelevant for the admin branch but should be documented as "anonymous only."

**i18n.** English-only (see §3). `variesBy: ["site","locale"]` declared but no non-en bundle.

## 5. Marketplace & Positioning

This is a **foundation/bundled** package (`tier: free`, `bundle: foundation`, `proposedLicense: free`, `requestedCertification: first-party`) — it is plumbing that the frontend stack depends on, not a standalone purchase.

- **Closed 2026-06-05 — manifest `summary` and composer `description`.** Manifest and Composer copy now lead with live-site editing for admins, then the public/cache safety guarantee. This is outcome-led and avoids the previous plumbing-first "beacon/manifest/routes" phrasing.
- **Screenshot/media status.** `marketplace.screenshots[]` now lists the card plus real desktop and mobile authoring captures from `docs/screenshots/`. `docs/screenshots.json` tracks the broader three product captures plus two config-proof captures; the before/after "authoring enabled vs disabled / no leak" proof images remain strong trust assets for future gallery expansion.
- **free/bundle vs premium.** Frontend inline editing is the strongest _visible_ differentiator in the whole catalogue and a classic paid-pro hook. The current split is defensible: keep the **core single-field text/meta/content editor free** (it's foundation, other packages assume the beacon exists), but a **"Frontend Authoring Pro"** could layer the high-value capabilities from §3 — media/block surfaces, frontend section reorder, draft→preview→publish UI, granular per-role region permissions — as a premium tier. The beacon + signer + registry already provide the extension seams (`EditorSurfaceRegistry`, `capell-frontend-authoring:editable-regions` tag) to do this without forking.
- **Platform-pitch contribution.** This package _is_ the "edit your site like Webflow/Framer, but it's just Laravel + Filament" headline. It demonstrably proves the platform's hardest promise — WYSIWYG-style editing **with** aggressive HTML caching and zero public leakage. Lead marketing with it; back the claim with the existing no-leak browser test as evidence.
- **Keywords/tags (8–12):** `inline editing`, `in-page editing`, `frontend authoring`, `live editing`, `WYSIWYG`, `click to edit`, `Filament`, `Livewire`, `html cache safe`, `signed urls`, `cms editing`, `content editing`.

## 6. Prioritized Roadmap

| Item                                                                                                                                                                                | Bucket | Effort   | Impact | Section ref                                                                                                                           |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| Shipped 2026-06-04: implement real probes in `FrontendAuthoringHealthCheck`; evidence: route, service-binding, config, app-key probes plus healthy/broken `critical` manifest tests | Done   | S        | High   | §2, §4                                                                                                                                |
| Shipped 2026-06-04: define/deny-by-default the `frontend-authoring.edit` ability                                                                                                    | Done   | S/M      | High   | §2, §3, §4                                                                                                                            |
| Shipped 2026-06-04: guard publishing-studio approval branch behind `isPackageInstalled` + stop swallowing errors                                                                    | Done   | M        | High   | §2, §4                                                                                                                                |
| Done/Shipped: Promote real desktop+mobile captures into `marketplace.screenshots[]`; delete orphan nested asset                                                                     | Done   | S        | Med    | §4, §5                                                                                                                                |
| Done/Shipped: Sharpen composer `description` + marketplace `summary` to outcome-led copy                                                                                            | Done   | S        | Med    | §5                                                                                                                                    |
| Shipped 2026-06-04: add `EditableRegionSigner` tamper/format unit test + beacon render-budget assertion                                                                             | Done   | S        | Med    | §4                                                                                                                                    |
| Done/Shipped: Refresh CHANGELOG with signer/beacon-origin/approval history                                                                                                          | Done   | S        | Low    | §2                                                                                                                                    |
| Done/Shipped: Extract beacon admin-manifest assembly into a `BuildBeaconResponse` Action                                                                                            | Done   | M        | Med    | §2 — `BeaconController` now delegates response assembly to `BuildBeaconResponseAction`.                                               |
| Done/Shipped: Replace field/type/surface/status string literals with backed enums (`HasLabels`)                                                                                     | Done   | M        | Med    | §2 — typed enums now back editor input type, surface, save status, and field-kind comparisons without changing public payload values. |
| Done/Shipped: Decide + test HTML sanitization policy for the `content` region                                                                                                       | Done   | S/M      | Med    | §4 — admin-authored content HTML is explicitly `trusted_admin_raw` and covered by focused round-trip coverage.                        |
| Done/Shipped: add a second built-in editor surface (image/media) to exercise the contract                                                                                           | Done   | L        | High   | §3 — registered `media` surface plus manifest/controller coverage for package-supplied media regions.                                 |
| Done/Shipped: Add granular per-region/per-role permissions, filtered in the manifest builder                                                                                        | Done   | M        | High   | §3 — optional region `permissions` are enforced by `AuthorizeEditableRegionAction` before manifest inclusion or editor validation.    |
| Done/Shipped: Translate `authoring.php` into the supported locale set (`variesBy: locale`)                                                                                          | Done   | S/locale | Med    | §3, §4 — bundled Spanish locale plus key-parity coverage against English.                                                             |
| First-class draft→preview→publish toggle in the editor UI                                                                                                                           | Later  | M/L      | High   | §3                                                                                                                                    |
| Frontend section reorder / block add-remove ("Pro" differentiator)                                                                                                                  | Later  | L        | High   | §3, §5                                                                                                                                |
| Namespaced admin-only client API so themes can register regions in JS                                                                                                               | Later  | M        | Med    | §3                                                                                                                                    |