TenantAtlas/specs/387-review-publication-resolution-decision-ux-v1/spec.md
ahmido aca0b10658 feat: add review publication resolution ux spec and tests (#458)
Automated PR created by Codex via Gitea API.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #458
2026-06-19 08:49:26 +00:00

37 KiB

Feature Specification: Spec 387 - Review Publication Resolution Decision UX v1

Feature Branch: 387-review-publication-resolution-decision-ux-v1 Created: 2026-06-18 Status: Draft / Ready for implementation planning Input: User-provided draft candidate "Spec 387 - Review Publication Resolution Decision UX v1" from /Users/ahmeddarrazi/.codex/attachments/68c5630e-4d21-42fa-bba6-e49ee38ab08a/pasted-text.txt.

Repo-Truth Adjustment

The supplied draft describes a broad UX/productization pass after Spec 386. Current repo truth shows that Spec 386 already implemented much of the decision-first target:

  • ResolveReviewPublication already renders "Review can't be published yet".
  • The page already shows "Publication preparation".
  • Technical proof is already placed under "Technical proof and operation history".
  • Existing Spec 386 Feature and Browser tests assert decision-first copy, "Update required reports", hidden "Report-backed evidence", and confirmation behavior.
  • UI-101 already registers the route as a browser-verified strategic surface with decision-first direction.

This Spec 387 package therefore narrows the user draft to residual hardening only:

  • finish remaining operator-facing terminology mismatches such as "Generate review pack" versus "Prepare export" and "Return to publication" versus "Return to review";
  • tighten modal heading, body, and submit labels so each mutating step names the actual action and states that it will not publish the review;
  • add explicit readonly/capability-denied inspection copy instead of relying only on a disabled action tooltip;
  • verify state-specific copy for waiting, failed, ready-to-continue, ready-for-publication, and no-blocker states;
  • verify technical proof remains collapsed by default and does not compete with the next safe action;
  • update or confirm UI audit coverage and screenshot evidence for this narrower hardening pass.

Spec 387 must not duplicate the Spec 386 workflow, data model, persistence, services, actions, route, navigation, or global search behavior.

Candidate Selection Gate

  • Selected candidate: Spec 387 - Review Publication Resolution Decision UX v1.
  • Source: Direct user-provided candidate attachment.
  • Why selected: The user explicitly supplied a ready Spec 387 draft, and repo inspection found residual copy/state/confirmation/readonly hardening gaps that are smaller than the original draft but still visible to operators.
  • Roadmap relationship: Supports the roadmap's current productization and moat priority around customer-safe review consumption and decision-first governance workflows. This is a manual user-provided candidate; it does not reopen the active auto-prep queue, which currently says there is no safe automatic next-best target.
  • Close alternatives deferred:
    • Active auto-prep queue candidates remain closed or manual-promotion only in docs/product/spec-candidates.md.
    • Management Report PDF staging/runtime validation remains tied to Specs 378-380.
    • Governance artifact lifecycle/retention runtime remains manual-promotion backlog.
    • Governance Inbox resolution intake and generic resolution adapters remain follow-up candidates, not hidden scope.
    • Spec 386 must not be rewritten or converted back into preparation state.
  • Completed-spec guardrail result:
    • specs/386-review-publication-resolution-workflow-v1/ is completed implementation context with route, UI, tests, screenshots, and UI audit registry evidence; it is not modified by this preparation.
    • Related Specs 350, 351, 385, and UI-101 are dependency/context only.
    • No existing specs/387-* package or *387* branch was found before Spec Kit creation.
  • Smallest viable implementation slice: A focused UX/copy hardening pass over the existing Review Publication Resolution page and Review Detail blocked CTA, preserving all Spec 386 runtime behavior.
  • Gate result: PASS, with scope reduction. The original draft is too broad relative to current repo truth; this narrowed slice is not already fully covered.

Spec Candidate Check (mandatory - SPEC-GATE-001)

  • Problem: The functional Review Publication Resolution page is already decision-first in structure, but a few remaining labels, modal affordances, disabled-action states, and state-specific messages can still expose internal workflow wording or leave the operator inferring the safest next step.
  • Today's failure: Operators may still see "Generate review pack", "Return to publication", a generic confirmation submit label, or a disabled action without an explicit page-level permission explanation, even though the product intent is "prepare export", "return to review", and "this will not publish".
  • User-visible improvement: The existing page becomes more immediately understandable: one next safe action, action-specific confirmation, no publish ambiguity, clear readonly inspection state, and technical proof available without dominating the first decision.
  • Smallest enterprise-capable version: Adjust labels/copy/state handling on the existing page, add or update focused Feature/Filament/Browser tests, and refresh screenshot/UI coverage notes only where the rendered UI changes.
  • Explicit non-goals: No new resolution data model, migrations, workflow engine, adapter framework, top-level navigation, global-search resource, auto-publish path, provider/evidence/review-pack service changes, customer-facing resolution flow, or new OperationRun lifecycle behavior.
  • Permanent complexity imported: Focused copy mappings, tests, screenshots, and possibly a page-local extraction only if it replaces duplicated mapping. No new durable source of truth, no new enum/status family, no generic presenter/framework, and no new queue or storage behavior.
  • Why now: Spec 386 just introduced the workflow, so this is the right time to remove residual implementation-first wording before the surface becomes a repeated operator workflow.
  • Why not local: This is local to the existing resolution page and should stay local; the spec exists because the change is user-facing and must carry UI, RBAC, audit, and browser-smoke expectations without reopening Spec 386.
  • Approval class: Workflow Compression.
  • Red flags triggered: UI polish over a recently completed workflow. Defense: the scope is explicitly narrowed, no new architecture is approved, and implementation must prefer direct local mapping over a new framework.
  • Score: Nutzen: 2 | Dringlichkeit: 1 | Scope: 2 | Komplexitaet: 2 | Produktnaehe: 2 | Wiederverwendung: 1 | Gesamt: 10/12
  • Decision: approve as a narrowed residual UX hardening slice.

Problem Statement

Spec 386 gave TenantPilot a resumable Review Publication Resolution workflow for blocked Environment Reviews. Current code already presents the main decision-first structure, but residual copy and state handling can still make the surface feel partly implementation-led.

The operator should be able to answer within five seconds:

  1. Can I publish? No, not yet.
  2. Why not? Required preparation inputs are missing, stale, running, or failed.
  3. What should I do now? Take the one next safe action.
  4. Will this publish automatically? No.
  5. Where is proof? In collapsed technical proof and operation history.

Business / Product Value

  • Reduces operator hesitation during blocked review publication.
  • Preserves the trust boundary that preparation actions never publish automatically.
  • Keeps customer-safe review output separate from internal remediation mechanics.
  • Makes support/proof details available without turning the page into a workflow-engine debug surface.

Primary Users / Operators

  • MSP or workspace operator preparing an Environment Review for publication.
  • Workspace manager reviewing blocked publication state and next action.
  • Readonly or support user inspecting an existing resolution case without execution rights.
  • Customer-facing review consumers indirectly protected by the non-leakage boundary.

Spec Scope Fields (mandatory)

  • Scope: workspace-owned / managed-environment-scoped Review Publication Resolution UI over existing Spec 386 persistence and services.
  • Primary Routes:
    • /admin/workspaces/{workspace}/environments/{environment}/environment-reviews/{record}
    • /admin/workspaces/{workspace}/environments/{environment}/environment-reviews/{record}/resolve-publication
    • Customer Review Workspace only for leakage regression checks; no new customer resolution UI.
  • Data Ownership:
    • ReviewPublicationResolutionCase and ReviewPublicationResolutionStep remain Spec 386 workflow state.
    • OperationRun remains execution/proof truth.
    • Evidence Snapshot, Environment Review, Review Pack, and Stored Report remain artifact/review truth.
    • Spec 387 adds no persisted truth.
  • RBAC: Existing policies, capabilities, ReviewPublicationResolutionStepAuthorizer, UiEnforcement, workspace membership, and managed-environment entitlement remain authoritative. Non-member/not-entitled access remains deny-as-not-found; entitled members without execution capability may inspect only when current policies allow it.

For canonical-view specs:

  • Default filter behavior when tenant-context is active: N/A. This spec does not add canonical-view filtering or revive retired /admin/t routes.
  • Explicit entitlement checks preventing cross-tenant leakage: Existing EnvironmentReviewResource scoped record resolution and case policy checks remain mandatory; customer workspace leakage tests must continue to prove no internal resolution detail is exposed.

UI Surface Impact (mandatory - UI-COV-001)

Does this spec add, remove, rename, or materially change any reachable UI surface?

  • No UI surface impact
  • Existing page changed
  • New page/route added
  • Navigation changed
  • Filament panel/provider surface changed
  • New modal/drawer/wizard/action added
  • New table/form/state added
  • Customer-facing surface changed
  • Dangerous action changed
  • Status/evidence/review presentation changed
  • Workspace/environment context presentation changed

Clarification: no new modal/action class is approved. Existing Filament action modal copy and existing page action states are changed. Customer-facing scope is negative leakage/regression coverage only unless implementation proves existing copy leaks or overclaims and updates this spec before changing customer-visible UI.

UI/Productization Coverage (mandatory when UI Surface Impact is not "No UI surface impact")

  • Route/page/surface:
    • Review Publication Resolution page (ResolveReviewPublication)
    • Environment Review detail blocked publication CTA
    • Customer Review Workspace leakage boundary checks only
  • Current or new page archetype: existing UI-101 Reviews strategic workflow surface; existing UI-040 Environment Review detail; existing UI-006 Customer Review Workspace for no-leakage boundary only.
  • Design depth: Strategic Surface for UI-101; Domain Pattern Surface for CTA copy on UI-040; customer-safe regression only for UI-006.
  • Repo-truth level: repo-verified and browser-verified through Spec 386.
  • Existing pattern reused: UI-101 page report, Spec 386 page/action implementation, native Filament sections/badges/actions/modals, existing UiEnforcement, existing OperationRun link helpers.
  • New pattern required: none. Direct local mapping is preferred. A new generic presenter or framework is not approved.
  • Screenshot required: yes for changed states where feasible, under specs/387-review-publication-resolution-decision-ux-v1/artifacts/screenshots/.
  • Page audit required: update UI-101 only if rendered structure/copy materially changes; otherwise record a no-new-route coverage note in the implementation close-out.
  • Customer-safe review required: yes, negative leakage check only; no customer-facing resolution UI is planned.
  • Dangerous-action review required: yes for existing high-impact/mutating step action and existing cancel action. Step execution keeps ->action(...), ->requiresConfirmation(), server authorization, audit, and notifications from Spec 386.
  • Coverage files updated or explicitly not needed:
    • docs/ui-ux-enterprise-audit/route-inventory.md
    • docs/ui-ux-enterprise-audit/design-coverage-matrix.md
    • docs/ui-ux-enterprise-audit/page-reports/...
    • docs/ui-ux-enterprise-audit/strategic-surfaces.md
    • docs/ui-ux-enterprise-audit/grouped-follow-up-candidates.md
    • docs/ui-ux-enterprise-audit/unresolved-pages.md
    • N/A - no reachable UI surface impact
  • No-impact rationale when applicable: N/A.

Cross-Cutting / Shared Pattern Reuse (mandatory)

  • Cross-cutting feature?: yes, but limited to one existing workflow surface.
  • Interaction class(es): status messaging, action labels, header actions, confirmation modal copy, OperationRun links, proof disclosure, customer-safe review boundary.
  • Systems touched:
    • ResolveReviewPublication
    • ViewEnvironmentReview
    • ReviewPublicationResolutionStepAuthorizer
    • OperationUxPresenter / OperationRunLinks only as existing link/copy context
    • Customer Review Workspace leakage tests only
  • Existing pattern(s) to extend: existing Spec 386 page methods, native Filament Actions, UiEnforcement, Filament badges/sections, existing OperationRun UX link helpers.
  • Shared contract / presenter / builder / renderer to reuse: existing page-local mapping and shared OperationRun helpers. Do not introduce a cross-domain presenter.
  • Why the existing shared path is sufficient or insufficient: The existing path is sufficient for runtime behavior. It is insufficient only in a few labels and state messages.
  • Allowed deviation and why: page-local extraction is allowed only if it replaces duplicated mapping and stays review-publication-specific.
  • Consistency impact: Button labels, modal headings, modal submit labels, run titles/notifications where touched, tests, and audit-facing copy must keep the same domain vocabulary.
  • Review focus: no new workflow engine, no action-start bypass, no local OperationRun UX composition, no internal terms in the default operator layer.

OperationRun UX Impact (mandatory)

  • Touches OperationRun start/completion/link UX?: yes, copy and link presentation only. No new OperationRun start/completion semantics.
  • Shared OperationRun UX contract/layer reused: existing OperationUxPresenter, OperationRunLinks, and Spec 386 operation-link behavior.
  • Delegated start/completion UX behaviors: queued toast/link/event/dedupe/terminal notification behavior remains unchanged and service-owned.
  • Local surface-owned behavior that remains: action label, modal copy, "Open operation" secondary link, and proof disclosure ordering.
  • Queued DB-notification policy: unchanged; no new queued DB notification.
  • Terminal notification path: unchanged.
  • Exception required?: none.

Provider Boundary / Platform Core Check (mandatory)

  • Shared provider/platform boundary touched?: no new shared seam. Existing provider/evidence/report/review/export steps remain source-owned.
  • Boundary classification: platform-core UI vocabulary over a review workflow; provider-owned details stay behind existing proof/diagnostics.
  • Seams affected: visible labels for existing step keys and proof links only.
  • Neutral platform terms preserved or introduced: publication preparation, required reports, collect evidence, refresh review, prepare export, return to review, technical proof, operation.
  • Provider-specific semantics retained and why: "Entra admin roles" and "Permission posture" may remain as report requirement labels because they are current report names visible to operators.
  • Why this does not deepen provider coupling accidentally: no Graph/provider code is changed; provider-specific proof remains diagnostic and existing.
  • Follow-up path: Resolution Proof & Currentness Contract, Governance Inbox Resolution Intake, and Restore Readiness Resolution Adapter remain follow-up candidates only.

UI / Surface Guardrail Impact (mandatory)

Surface / Change Operator-facing surface change? Native vs Custom Shared-Family Relevance State Layers Touched Exception Needed? Low-Impact / N/A Note
Review Publication Resolution page copy/state hardening yes Native Filament page + existing Blade composition action labels, status messaging, proof disclosure page, detail no existing route only
Step confirmation modal copy yes Filament Action modal confirmation/dangerous-action safety action modal no existing action only
Environment Review blocked CTA copy yes existing Filament resource page/action review publication action link detail no copy/summary only
Customer Review Workspace leakage regression no material customer feature change existing page customer-safe boundary page no negative test/smoke only

Decision-First Surface Role (mandatory when operator-facing surfaces are changed)

Surface Decision Role Human-in-the-loop Moment Immediately Visible for First Decision On-Demand Detail / Evidence Why This Is Primary or Why Not Workflow Alignment Attention-load Reduction
Review Publication Resolution page Primary Decision Surface Operator decides and executes the next safe preparation step blocked/ready state, missing requirement summary, one primary action, no-auto-publish copy operation links, proof artifacts, technical step keys if needed Primary because it owns the blocked-publication fix flow review publication preparation removes internal workflow wording from the first decision
Environment Review detail blocked CTA Primary Decision entry point Operator decides whether to resolve blockers before publication publication blocked explanation and one CTA review sections/evidence/proof Primary entry point only, not the whole workflow review lifecycle avoids promoting refresh/publish while blocked
Customer Review Workspace Customer-safe context Customer/output reader sees no internal resolution mechanics customer-safe unavailable/preparing state where applicable none from resolution case Not a resolution surface customer review consumption avoids leakage and action confusion

Audience-Aware Disclosure (mandatory when detail/status surfaces change)

Surface Audience Modes In Scope Decision-First Default-Visible Content Operator Diagnostics Support / Raw Evidence One Dominant Next Action Hidden / Gated By Default Duplicate-Truth Prevention
Review Publication Resolution page operator-MSP, manager, readonly inspector, support-platform can/cannot publish, why, next action, no-auto-publish proof links, operation status, evaluated time, safe reason code raw provider/report/evidence payloads remain hidden current step action, or open operation/return to review by state proof/history collapsed; raw data absent blocker stated once; checklist and proof add context only
Environment Review detail operator-MSP, manager, readonly inspector publication blocked explanation and CTA evidence/review sections raw details in existing deeper surfaces resolve publication blockers while blocked case internals hidden detail points to workflow instead of duplicating it
Customer Review Workspace customer/read-only, operator-MSP customer-safe review availability only none from internal resolution internal resolution proof absent none introduced all internal resolution mechanics hidden no duplicate or leaked blocker mechanics

UI/UX Surface Classification (mandatory when operator-facing surfaces change)

Surface Action Surface Class Surface Type Likely Next Operator Action Primary Inspect/Open Model Row Click Secondary Actions Placement Destructive Actions Placement Canonical Collection Route Canonical Detail Route Scope Signals Canonical Noun Critical Truth Visible by Default Exception Type / Justification
Review Publication Resolution Workflow / Primary Decision Subject-driven workflow detail run current preparation step, open operation, or return to review direct page route from review N/A related links and proof disclosure cancel in More with confirmation none existing resolve-publication route workspace + environment + review Publication preparation can publish, blocker, next step, no-auto-publish no collection/global search by design
Environment Review detail Detail / Review Context Existing review detail resolve blockers or continue existing lifecycle existing detail page existing behavior only secondary evidence/proof links existing destructive actions remain separated existing review collection existing review detail route workspace + environment Environment review publication blocked state none

Operator Surface Contract (mandatory when operator-facing surfaces change)

Surface Primary Persona Decision / Operator Action Supported Surface Type Primary Operator Question Default-visible Information Diagnostics-only Information Status Dimensions Used Mutation Scope Primary Actions Dangerous Actions
Review Publication Resolution page MSP/workspace operator Resolve the current publication blocker without publishing workflow detail Why is publication blocked and what is the next safe action? blocker summary, required reports, next safe action, checklist, no-auto-publish note proof links, operation history, technical step keys preparation readiness, operation execution state, artifact proof state TenantPilot artifact/workflow work only; provider work only through existing source-owned actions update required reports, collect evidence, refresh review, prepare export, return to review cancel resolution; step execution is high-impact and confirmation-gated
Environment Review detail CTA MSP/workspace operator Enter resolution flow when publication is blocked review detail Can I publish, and if not where do I resolve blockers? blocked explanation and resolve CTA review/evidence details review lifecycle/readiness existing review lifecycle only resolve publication blockers existing publish/archive actions remain separate

Proportionality Review (mandatory when structural complexity is introduced)

  • New source of truth?: no.
  • New persisted entity/table/artifact?: no.
  • New abstraction?: no by default. A page-local helper extraction is allowed only if it replaces duplicated mapping and stays bounded to ResolveReviewPublication.
  • New enum/state/reason family?: no.
  • New cross-domain UI framework/taxonomy?: no.
  • Current operator problem: residual internal wording and generic modal affordances can slow or confuse the publication preparation decision.
  • Existing structure is insufficient because: the existing page has the right architecture and most decision-first copy, but several labels and state messages still need alignment.
  • Narrowest correct implementation: update existing local mappings, Blade copy, Filament action modal labels, and tests.
  • Ownership cost: focused test/screenshot maintenance only.
  • Alternative intentionally rejected: a new ReviewPublicationResolutionDecisionPresenter or generic resolution UI framework is rejected unless implementation proves the existing page methods are unsafe to maintain.
  • Release truth: current-release UX hardening over an already implemented workflow.

Compatibility posture

This feature assumes a pre-production environment. Backward compatibility shims, legacy aliases, and migration compatibility code are out of scope.

Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)

  • Test purpose / classification: Feature + Filament/Livewire + Browser.
  • Validation lane(s): confidence + browser; fast-feedback for focused feature tests.
  • Why this classification and these lanes are sufficient: The risk is visible UI and action confirmation behavior on an existing Filament page, plus customer non-leakage. No schema or Graph behavior changes are approved.
  • New or expanded test families: add/update focused Spec 387 tests near existing Spec 386 Environment Review and Browser tests.
  • Fixture / helper cost impact: reuse existing Spec 386 factories/helpers/fixtures; no new expensive global setup.
  • Heavy-family visibility / justification: browser coverage is explicit because the feature is layout/copy/disclosure-sensitive.
  • Special surface test profile: workflow-detail surface / standard-native-filament with browser smoke.
  • Standard-native relief or required special coverage: ordinary Filament/Livewire action tests plus browser smoke for first-screen order, modal copy, collapsed disclosure, mobile, and customer non-leakage.
  • Reviewer handoff: verify no new workflow mechanics, no enabled action for unauthorized execution, no internal terms in default UI, and no publish action on the resolution page.
  • Budget / baseline / trend impact: low; one focused browser smoke may add explicit browser lane runtime.
  • Escalation needed: document-in-feature if screenshots for some states cannot be produced with current fixtures.
  • Active feature PR close-out entry: Smoke Coverage / UX Hardening / No New Workflow Mechanics.
  • Planned validation commands:
    • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/EnvironmentReview/Spec387ReviewPublicationResolutionDecisionUxTest.php
    • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/EnvironmentReview/Spec386ReviewPublicationResolutionWorkflowTest.php
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec387ReviewPublicationResolutionDecisionUxTest.php
    • cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
    • git diff --check

User Scenarios & Testing (mandatory)

User Story 1 - Understand the Blocked Publication Decision (Priority: P1)

As an operator opening a blocked review's publication preparation page, I need the first visible area to explain why the review cannot be published, which requirements are missing, and the one next safe action.

Why this priority: This is the core 5-second decision the page exists to support.

Independent Test: Open a blocked Environment Review resolution page and verify the first heading/card uses decision-first copy, required report labels, one primary next action, and no prominent internal case/step/proof terms.

Acceptance Scenarios:

  1. Given a blocked review with missing required reports, When an authorized operator opens the resolution page, Then the page shows "Review can't be published yet", the missing required reports, "Update required reports", and visible no-auto-publish copy before technical proof.
  2. Given the same page, When the operator scans the preparation checklist, Then the checklist uses operator labels such as "Update required reports", "Collect evidence", "Refresh review", "Prepare export", and "Return to review".

User Story 2 - Execute the Next Step With Clear Confirmation (Priority: P1)

As an authorized operator, I need the confirmation modal to name the exact preparation action, use a matching confirm button, and clearly state that the action will not publish the review.

Why this priority: Step actions can queue work or touch provider/evidence/report services; the safety boundary must be explicit.

Independent Test: Mount the Filament page, open each reachable step action confirmation, and verify title, body, submit label, ->requiresConfirmation(), and server authorization remain intact.

Acceptance Scenarios:

  1. Given the current step is required reports, When the operator starts the action, Then the modal heading is "Update required reports?", the confirm button is "Update required reports", and the body says the review will not be published.
  2. Given the current step is prepare export, When the operator starts the action, Then the visible copy uses "Prepare export" instead of "Generate review pack" by default.

User Story 3 - Inspect Without Execution Rights (Priority: P2)

As a readonly user who is allowed to inspect an existing case, I need a clear explanation that I can inspect the preparation flow but cannot run the next action.

Why this priority: Disabled actions without page-level explanation can look broken or like a permission leak.

Independent Test: Open an existing resolution case as a readonly actor and verify the primary action is disabled or absent, execution remains denied server-side, and an explicit page-level permission message appears.

Acceptance Scenarios:

  1. Given a readonly actor with view access but no step execution capability, When the actor opens the resolution page, Then the page shows "You can inspect this preparation flow, but you do not have permission to run the next action." or equivalent.
  2. Given the same actor attempts direct execution, When the action handler runs, Then the server denies execution and no operation/report/evidence/review-pack job is dispatched.

User Story 4 - Keep Proof Secondary and Customer Surfaces Clean (Priority: P2)

As an operator or customer-safe reviewer, I need proof available for inspection without exposing internal resolution mechanics on the default page or customer workspace.

Why this priority: The workflow should feel like guided governance, not a visible workflow engine or support console.

Independent Test: Browser smoke verifies technical proof is collapsed by default on the resolution page and customer workspace does not show resolution case, step, OperationRun, proof, or internal blocker terms.

Acceptance Scenarios:

  1. Given an operator opens the resolution page, When the page first renders, Then "Technical proof and operation history" is collapsed by default and below the decision content.
  2. Given a customer-facing review workspace, When a review is being prepared internally, Then no resolution case, step key, OperationRun link, proof link, or internal blocker reason code is visible.

Edge Cases

  • The linked operation is running: show operation-in-progress copy and do not expose another start/retry action while the operation is active.
  • The linked operation failed: show safe failed-operation copy, safe reason only, and a retry action only if existing Spec 386 rules allow it.
  • No blockers remain: do not create or emphasize a workflow; return the operator to the normal review publication path.
  • Ready for publication: keep publish on the Environment Review detail page; never publish from the resolution page.
  • Missing fixtures for a browser state: document the unavailable state in the screenshot index rather than widening product code.

Requirements (mandatory)

Functional Requirements

  • FR-387-001: The resolution page MUST keep decision-first heading and summary copy as the first default-visible content.
  • FR-387-002: The visible checklist and secondary return navigation/action label MUST use operator labels: Check readiness, Update required reports, Collect evidence, Refresh review, Prepare export, and Return to review.
  • FR-387-003: Default operator-facing UI MUST NOT prominently show "Resolution Case", "Case Status", "Current step", "Resolution steps", "Report-backed evidence", "OperationRun", "Artifact proof", or raw step keys.
  • FR-387-004: Technical proof and operation history MUST remain collapsed by default and below decision/next-action content.
  • FR-387-005: Every mutating/high-impact step action MUST continue to execute through Action::make(...)->action(...), keep ->requiresConfirmation(), and use existing server-side authorization.
  • FR-387-006: Step confirmation copy MUST include action-specific heading/body/submit labels and MUST state that the action will not publish the review, except the return-to-review step which must state that publishing remains separate. Each reachable current-step state MUST be covered by a test assertion or a named fixture-unavailable note.
  • FR-387-007: The resolution page MUST NOT show a Publish action.
  • FR-387-008: The Environment Review detail blocked state MUST keep Resolve publication blockers as the primary blocked-publication CTA and MUST NOT promote refresh or publish while blockers remain.
  • FR-387-009: Readonly/capability-denied inspectors MUST see an explicit page-level permission message and no enabled executable primary action.
  • FR-387-010: Customer-facing surfaces MUST NOT expose resolution case details, step keys, proof links, operation links, or internal blocker reason codes.
  • FR-387-011: No new route, navigation item, global-search resource, model, migration, queue family, provider adapter, workflow engine, or auto-publish path may be added.
  • FR-387-012: Existing Spec 386 audit, RBAC, source-owned action, failure redaction, and no-auto-publish guarantees MUST remain intact.
  • FR-387-013: New or changed visible UI copy MUST use existing localization files/keys where practical; any bounded operator-only localization debt MUST be recorded in the implementation close-out.

UI Action Matrix (mandatory when Filament is changed)

Surface Location Header Actions Inspect Affordance (List/Table) Row Actions (max 2 visible) Bulk Actions (grouped) Empty-State CTA(s) View Header Actions Create/Edit Save+Cancel Audit log? Notes / Exemptions
Review Publication Resolution page ResolveReviewPublication one current-step action when executable, Return to review/secondary nav, More with Cancel resolution N/A N/A N/A N/A current-step action confirmation required; cancel confirmation required N/A Spec 386 audit remains required for mutating steps/cancel No publish action; no global search; no top-level nav
Environment Review detail ViewEnvironmentReview / EnvironmentReviewResource existing lifecycle actions plus blocked CTA existing detail route N/A N/A existing Resolve publication blockers primary while blocked N/A existing audit rules remain Refresh/publish must not compete while blockers remain

Key Entities (include if feature involves data)

  • ReviewPublicationResolutionCase: Existing Spec 386 workflow-state record; no schema or lifecycle expansion in Spec 387.
  • ReviewPublicationResolutionStep: Existing Spec 386 step record; no new step keys or statuses in Spec 387.
  • OperationRun: Existing execution proof; no new start/completion semantics in Spec 387.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-387-001: Browser smoke shows the first visible resolution page content answers blocked state, reason, next action, and no-auto-publish before proof/history.
  • SC-387-002: Focused tests prove internal terms are absent from default operator UI and proof remains collapsed by default.
  • SC-387-003: Focused tests prove each current-step confirmation keeps ->requiresConfirmation() and action-specific no-auto-publish copy.
  • SC-387-004: Focused tests prove readonly inspectors cannot execute the current step and see explicit permission copy.
  • SC-387-005: Customer workspace regression proves no internal resolution mechanics leak.
  • SC-387-006: No migrations, model changes, route additions, global-search resource, top-level navigation, or auto-publish behavior appear in the diff.

Out of Scope

  • New resolution persistence or status families.
  • Generic resolution/workflow adapter frameworks.
  • Provider/evidence/review-pack service behavior changes except label wiring to existing actions.
  • Governance Inbox intake.
  • Restore readiness adapters.
  • Customer-facing resolution workflows.
  • PDF/report runtime validation.
  • Broad UI redesign beyond the existing resolution page and CTA copy.

Assumptions

  • Spec 386 is the source of runtime workflow truth and remains implemented.
  • The current branch contains the latest Spec 386 code and tests.
  • The user-provided draft is treated as manual promotion and is narrowed against repo truth.
  • Any implementation that discovers a real runtime bug must update this spec/plan before expanding beyond UX hardening.

Open Questions

None blocking. Implementation may choose whether small mapping cleanup stays as page-local methods or a page-owned helper; a generic/shared presenter is not approved without a spec update.

Follow-up Spec Candidates

  • Resolution Proof & Currentness Contract v1.
  • Governance Inbox Resolution Intake v1.
  • Restore Readiness Resolution Adapter v1.
  • Provider/readiness-specific wording improvements if browser/user evidence shows continued friction.