TenantAtlas/specs/386-review-publication-resolution-workflow-v1/plan.md
ahmido ba7622a158 feat: implement ReviewPublicationResolutionWorkflow (Spec 386) (#457)
## Summary\n- Implements the ReviewPublicationResolutionWorkflow for Spec 386.\n- Adds resolution case/step persistence, policies, services, audit action IDs, and Filament integration.\n- Updates specs, UI/UX documentation, screenshots, and Pest coverage.\n\n## Tests\n- Not run during this handoff; branch was already clean and pushed.\n\n## Target\n- Base: platform-dev\n- Head/topic: 386-review-publication-resolution-workflow-v1

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #457
2026-06-18 21:06:20 +00:00

359 lines
24 KiB
Markdown

# Implementation Plan: Spec 386 - Review Publication Resolution Workflow v1
**Branch**: `386-review-publication-resolution-workflow-v1` | **Date**: 2026-06-18 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/386-review-publication-resolution-workflow-v1/spec.md`
## Summary
Create a bounded, review-publication-specific resolution workflow for blocked Environment Reviews. The implementation should add narrow case/step persistence, derive a step plan from existing review/evidence/report/review-pack readiness, execute only source-owned domain actions, link OperationRun and artifact proof, support pause/resume/currentness, audit lifecycle events, and keep customer-facing surfaces free of internal resolution details.
The plan explicitly excludes a generic workflow engine, top-level navigation, global search, CRUD resource exposure, auto-publish behavior, cross-domain adapters, customer self-resolution, and generic proof/currentness infrastructure.
## Technical Context
**Language/Version**: PHP 8.4.15
**Primary Dependencies**: Laravel 12.52.0, Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, PostgreSQL via Sail/Dokploy
**Storage**: New review-publication-specific case/step tables plus existing `EnvironmentReview`, `EvidenceSnapshot`, `StoredReport`, `ReviewPack`, and `OperationRun` truth.
**Testing**: Pest Unit, Feature, Filament/Livewire Feature, PostgreSQL migration/constraint lane, and one bounded Browser smoke.
**Validation Lanes**: fast-feedback, confidence, pgsql, browser.
**Target Platform**: Laravel monolith in `apps/platform`, Sail locally, Dokploy for staging/production.
**Project Type**: Laravel/Filament web application inside `apps/platform`.
**Performance Goals**: Resolution page renders from DB-local readiness and proof references; no Graph/provider calls during render; planner evaluation remains bounded to one review and its known evidence/report/pack/run references.
**Constraints**: no generic workflow registry; no raw provider/report/evidence payloads in case metadata; no direct `OperationRun.status`/`outcome` transitions outside existing services; no new panel provider or assets by default; no auto-publish.
**Scale/Scope**: one blocked Environment Review at a time, one active current resolution case per subject/action/currentness, ordered sequential steps for review publication only.
## Existing Repository Surfaces Likely Affected
```text
apps/platform/database/migrations/
apps/platform/app/Models/
apps/platform/app/Policies/
apps/platform/app/Services/EnvironmentReviews/
apps/platform/app/Services/Evidence/
apps/platform/app/Services/ReviewPacks/
apps/platform/app/Services/OperationRunService.php
apps/platform/app/Support/ResolutionGuidance/
apps/platform/app/Support/ReviewPacks/ReviewPackOutputResolutionGuidance.php
apps/platform/app/Support/ReviewPacks/ReviewPackOutputReadiness.php
apps/platform/app/Support/OpsUx/OperationUxPresenter.php
apps/platform/app/Support/OperationRunLinks.php
apps/platform/app/Support/Rbac/UiEnforcement.php
apps/platform/app/Support/Rbac/WorkspaceUiEnforcement.php
apps/platform/app/Filament/Resources/EnvironmentReviewResource.php
apps/platform/app/Filament/Resources/EnvironmentReviewResource/Pages/ViewEnvironmentReview.php
apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php
apps/platform/resources/views/filament/infolists/entries/environment-review-summary.blade.php
apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php
apps/platform/tests/Unit/
apps/platform/tests/Feature/
apps/platform/tests/Browser/
docs/ui-ux-enterprise-audit/route-inventory.md
docs/ui-ux-enterprise-audit/design-coverage-matrix.md
docs/ui-ux-enterprise-audit/page-reports/
```
Likely new implementation paths, subject to repo verification:
```text
apps/platform/app/Models/ReviewPublicationResolutionCase.php
apps/platform/app/Models/ReviewPublicationResolutionStep.php
apps/platform/app/Policies/ReviewPublicationResolutionCasePolicy.php
apps/platform/app/Support/ReviewPublicationResolution/
apps/platform/app/Filament/Resources/EnvironmentReviewResource/Pages/ResolveReviewPublication.php
```
If implementation proves an existing resource/page naming convention is better, use the repo convention and keep the subject-driven/no-top-level-nav boundary.
## Data and Migration Plan
Prefer review-specific table names:
```text
review_publication_resolution_cases
review_publication_resolution_steps
```
Case fields should include:
- `id`
- `workspace_id` required
- `managed_environment_id` or the repo-current environment FK required for review publication
- `environment_review_id` required or a subject reference constrained to Environment Review only
- `action_key` required and fixed to `review.publication` for v1
- `status`
- `current_step_key`
- `readiness_fingerprint`
- `last_evaluated_at`
- `created_by`
- `assigned_to`
- `started_at`, `completed_at`, `cancelled_at`, `superseded_at`
- `summary` JSONB for safe derived summary
- `metadata` JSONB for safe workflow metadata only
- timestamps
Step fields should include:
- `id`
- case FK
- `position`
- `step_key`
- `status`
- `primary_action_key`
- `operation_run_id` nullable
- `proof_type`, `proof_id`, `proof_status` nullable
- lifecycle timestamps
- `summary` JSONB for safe step summary
- `metadata` JSONB for safe workflow metadata only
- timestamps
Indexes/constraints:
- PostgreSQL-enforced unique active/current case constraint for one active case per workspace/environment/review/action/currentness, backed by transactional service locking/idempotency for double-click and concurrent Livewire requests.
- unique `case_id` + `step_key`.
- indexes for workspace/environment/action/status/current step/operation run/proof reference.
- PostgreSQL JSONB lane validation for JSONB/default/index behavior.
Do not use polymorphic subject persistence unless implementation updates this spec/plan/tasks first. A generic `action_resolution_*` schema requires a proportionality update before coding.
No persisted `reason_code` column or reason-code enum is approved in v1. Step reasons remain evaluator/planner-derived and may appear only as safe summary text unless the spec/plan/tasks are updated with `STATE-001` consequences and tests.
## UI / Surface Guardrail Plan
- **Guardrail scope**: existing Environment Review blocked-state change, new subject-driven resolution workflow page/action, high-impact step actions, OperationRun/artifact proof links, and customer-safe non-leakage.
- **Affected routes/pages/actions/states/navigation/panel/provider surfaces**:
- Environment Review detail
- new Review Publication Resolution page or page action route
- Customer Review Workspace non-leakage/preparation wording
- existing OperationRun/evidence/report/pack proof destinations
- **No-impact class, if applicable**: N/A.
- **Native vs custom classification summary**: use native Filament Resource/Page actions and shared primitives first. Custom Blade only where existing review summary/customer workspace views already use it.
- **Shared-family relevance**: next-action guidance, review readiness, OperationRun proof links, evidence/report viewers, audit/status messaging, customer-safe disclosure.
- **State layers in scope**: persisted case, persisted steps, page current step, detail action state, URL route parameters, proof links.
- **Audience modes in scope**: operator-MSP, workspace manager, support-platform, customer-safe viewer.
- **Decision/diagnostic/raw hierarchy plan**: decision-first blocked reason, missing requirements, next safe action, and no-auto-publish note by default; proof and diagnostics secondary/collapsed; raw/support detail never customer default.
- **Raw/support gating plan**: raw provider payloads, raw report content, full evidence JSON, internal reason families, and OperationRun context stay behind existing gated diagnostics or are not exposed.
- **One-primary-action / duplicate-truth control**: one primary CTA on blocked review and one primary action for the current step. Completed/secondary proof links are demoted into technical disclosure.
- **Handling modes by drift class or surface**: new strategic workflow surface is `review-mandatory`; high-impact actions are `exception-required` only if deviating from existing confirmation/audit patterns.
- **Repository-signal treatment**: UI-COV-001 applies because a new reachable route/action surface is planned.
- **Special surface test profiles**: workflow detail surface, shared-detail-family, and browser smoke.
- **Required tests or manual smoke**: Unit, Feature, Filament/Livewire, PostgreSQL, and Browser smoke.
- **Exception path and spread control**: no generic workflow exception approved.
- **Active feature PR close-out entry**: Review Publication Resolution Workflow.
- **UI/Productization coverage decision**: update route inventory, design coverage matrix, and page reports for the new workflow surface and affected review/customer surfaces.
- **Coverage artifacts to update**:
- `docs/ui-ux-enterprise-audit/route-inventory.md`
- `docs/ui-ux-enterprise-audit/design-coverage-matrix.md`
- relevant `docs/ui-ux-enterprise-audit/page-reports/...`
- **No-impact rationale**: N/A.
- **Navigation / Filament provider-panel handling**: no top-level navigation and no panel provider changes. Laravel 12 panel providers remain in `apps/platform/bootstrap/providers.php`.
- **Screenshot or page-report need**: yes for the new workflow and blocked/recovery/customer-safe states.
## Shared Pattern & System Fit
- **Cross-cutting feature marker**: yes.
- **Systems touched**: Review readiness, evidence/report/pack readiness, OperationRun proof, Filament action UX, audit logging, RBAC UI enforcement, customer-safe disclosure.
- **Shared abstractions reused**: `ReviewPackOutputResolutionGuidance`, `ReviewPackOutputReadiness`, `ResolutionGuidance` DTOs where useful, `OperationRunLinks`, `OperationUxPresenter`, `BadgeCatalog`, `UiEnforcement`, `WorkspaceUiEnforcement`, existing review/evidence/pack services.
- **New abstraction introduced? why?**: yes, a review-publication-specific evaluator/planner/case/action/proof service family. It exists because the workflow must persist/resume state and proof over time.
- **Why the existing abstraction was sufficient or insufficient**: existing derived guidance can explain and select actions but cannot persist case lifecycle, steps, proof references, currentness, or audit lifecycle.
- **Bounded deviation / spread control**: no registry, no generic adapters, no cross-domain workflows. Namespace/service names should include `ReviewPublication` to preserve scope.
## OperationRun UX Impact
- **Touches OperationRun start/completion/link UX?**: yes.
- **Central contract reused**: existing OperationRun service/job creation and link/presenter helpers.
- **Delegated UX behaviors**: queued toast, run link, artifact link, run-enqueued browser event, dedupe/already-running messaging, blocked/failed-to-start messaging, tenant/workspace-safe URL resolution, and terminal notifications stay in shared/source-owned paths.
- **Surface-owned behavior kept local**: internal case status/current step selection, operator-facing next-action explanation, collapsed proof reference display, "Open operation", "Retry", and "Return to review" placement.
- **Queued DB-notification policy**: unchanged unless spec is updated.
- **Terminal notification path**: unchanged central lifecycle mechanism.
- **Exception path**: none approved.
Implementation must never mark `OperationRun.status` or `OperationRun.outcome` directly from the resolution page. It should link runs and re-evaluate domain truth.
## Provider Boundary & Portability Fit
- **Shared provider/platform boundary touched?**: yes, indirectly.
- **Provider-owned seams**: raw provider IDs, raw Graph payloads, provider permission details, and provider-specific report internals.
- **Platform-core seams**: review publication, evidence basis, report requirement, operation proof, artifact proof, readiness currentness, customer-ready boundary.
- **Neutral platform terms / contracts preserved**: review publication, resolution case, resolution step, publication blocker, proof reference, evidence basis, report requirement, artifact proof.
- **Retained provider-specific semantics and why**: only inside existing proof/diagnostics where needed; never as primary customer or operator workflow vocabulary.
- **Bounded extraction or follow-up path**: follow-up-spec for provider onboarding adapter or generic proof/currentness.
## Constitution Check
- Inventory-first: readiness derives from last-observed evidence/review/report/pack truth; no provider calls during render.
- Read/write separation: publication is not automatic. Step actions that create/refresh TenantPilot artifacts or queue operations use existing services, explicit operator intent, authorization, audit, and tests.
- Graph contract path: no direct Graph calls. Any existing evidence/report generation must continue through approved services/jobs and `GraphClientInterface`.
- Deterministic capabilities: step action availability must derive from existing capabilities/policies and be testable.
- RBAC-UX: `/admin` and `/system` remain separated; non-members 404; entitled users missing capability get safe denial/disabled state; customer users cannot access case internals.
- Workspace isolation: cases and proof links are workspace scoped.
- Tenant/environment isolation: review publication cases are environment scoped; no cross-environment proof leakage.
- Global search: no global-search resource for cases in v1.
- Destructive/high-impact actions: high-impact queued/artifact actions, retry that queues/regenerates work, case cancellation, and operator-triggered supersede/restart use `->action(...)`, authorization, confirmation, audit, notification, and tests. URL-only actions are navigation only. The initial `Resolve publication blockers` CTA creates/resumes an internal TenantPilot case and does not require confirmation, but must communicate scope and audit create/resume.
- Run observability: long-running/queued step actions create or reuse `OperationRun` through existing paths and link the run to the step.
- OperationRun start UX: shared start/link/presenter paths are reused; no local queued-toast/run-link composition.
- Ops-UX lifecycle: no direct OperationRun lifecycle transitions outside service-owned paths.
- Ops-UX summary counts: no new summary count keys unless `OperationSummaryKeys::all()` and tests are updated.
- Data minimization: case and step metadata contain safe identifiers/summaries only.
- Test governance: Unit, Feature, Filament/Livewire, PostgreSQL, and Browser lanes are explicit.
- Proportionality: new persistence is justified by pause/resume, audit, currentness, and proof-linked workflow needs.
- No premature abstraction: namespace and persistence remain review-publication-specific.
- Persisted truth: new tables store workflow state, not readiness or artifact truth.
- Behavioral state: case/step statuses affect routing/actionability/audit/lifecycle; v1 does not persist `skipped`, `not_applicable`, or a separate reason-code family for steps.
- UI semantics: use existing badges/disclosure/action-group patterns, no local color/status framework. Default page copy stays operator-facing; technical proof and implementation terms remain behind explicit disclosure.
- Shared pattern first: existing guidance/proof/action helpers are reused before local composition.
- Provider boundary: platform-core workflow vocabulary stays provider-neutral.
- V1 explicitness / few layers: direct review-specific services, no registry.
- UI/Productization coverage: new reachable workflow surface must update UI coverage artifacts.
Gate result for preparation: PASS.
## Test Governance Check
- **Test purpose / classification by changed surface**:
- Unit: evaluator, planner, fingerprint, proof resolver.
- Feature: migrations/models, case service, step actions, audit, RBAC, scope, customer boundary.
- Filament/Livewire Feature: CTA, resolution page, action enabled/disabled/executed states.
- PostgreSQL: JSONB/index/unique/constraint behavior.
- Browser: critical workflow smoke and non-leakage.
- **Affected validation lanes**: fast-feedback, confidence, pgsql, browser.
- **Why this lane mix is the narrowest sufficient proof**: the feature adds stateful workflow persistence and a new operator workflow page; SQLite-only tests cannot prove all PostgreSQL constraints and feature tests cannot prove full browser workflow presentation.
- **Narrowest proving command(s)**:
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/ReviewPublicationResolution`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPublicationResolution tests/Feature/EnvironmentReview tests/Feature/ReviewPack`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/Spec386ReviewPublicationResolutionUiTest.php`
- `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest -c phpunit.pgsql.xml --filter Spec386`
- `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec386ReviewPublicationResolutionWorkflowTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `git diff --check`
- **Fixture / helper / factory / seed / context cost risks**: review/evidence/report/pack/operation fixtures can grow expensive. Keep new fixtures local and explicit unless existing helpers already provide cheap setup.
- **Expensive defaults or shared helper growth introduced?**: none planned.
- **Heavy-family additions, promotions, or visibility changes**: none planned.
- **Surface-class relief / special coverage rule**: no standard-native relief for the new workflow page; it needs explicit page/action/browser coverage.
- **Closing validation and reviewer handoff**: verify no generic workflow spread, no stale proof, no customer leakage, correct audit/RBAC, and updated UI coverage artifacts.
- **Budget / baseline / trend follow-up**: document-in-feature if pgsql/browser runtime or fixture cost materially grows.
- **Review-stop questions**: duplicate truth, generic naming, proof currentness, unauthorized action execution, raw detail leakage, OperationRun lifecycle misuse, no-Graph-during-render.
- **Escalation path**: document-in-feature for bounded implementation choices; follow-up-spec for structural proof/currentness or additional adapters.
- **Active feature PR close-out entry**: Review Publication Resolution Workflow.
- **Why no dedicated follow-up spec is needed**: Spec 386 itself is the bounded review-publication workflow. Generic proof/currentness and other adapters are listed as future specs.
## Project Structure
### Documentation (this feature)
```text
specs/386-review-publication-resolution-workflow-v1/
├── checklists/
│ └── requirements.md
├── plan.md
├── spec.md
└── tasks.md
```
### Source Code (repository root)
```text
apps/platform/
├── app/
│ ├── Models/
│ │ ├── ReviewPublicationResolutionCase.php
│ │ └── ReviewPublicationResolutionStep.php
│ ├── Policies/
│ │ └── ReviewPublicationResolutionCasePolicy.php
│ ├── Support/
│ │ └── ReviewPublicationResolution/
│ │ ├── ReviewPublicationReadinessEvaluator.php
│ │ ├── ReviewPublicationResolutionPlanner.php
│ │ ├── ReviewPublicationResolutionCaseService.php
│ │ ├── ReviewPublicationResolutionActionService.php
│ │ ├── ReviewPublicationResolutionProofResolver.php
│ │ └── DTOs and enums/value objects as needed
│ ├── Services/
│ │ ├── EnvironmentReviews/
│ │ ├── Evidence/
│ │ └── ReviewPacks/
│ └── Filament/
│ └── Resources/
│ └── EnvironmentReviewResource/
│ └── Pages/
│ └── ResolveReviewPublication.php
├── database/
│ └── migrations/
├── resources/views/
└── tests/
├── Unit/ReviewPublicationResolution/
├── Feature/ReviewPublicationResolution/
├── Feature/Filament/
└── Browser/
```
**Structure Decision**: Laravel monolith under `apps/platform`; review-publication-specific support namespace; subject-driven Filament page/action under Environment Review; no top-level resource/navigation.
## Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
| New persisted case/step tables | Operator workflow must survive navigation, queued operation completion, permission fixes, audit review, and currentness changes | Derived cards cannot preserve pause/resume, proof linkage, lifecycle audit, or current step over time |
| New case/step statuses | Status changes drive next action, wait state, failure handling, completion, cancellation, and supersession | Presentation-only labels would not support resume, audit, or safe action routing |
| New review-specific service family | Evaluation, planning, persistence, action execution, and proof/currentness must remain thin and testable | Putting this behavior in Filament closures would bury business logic and make RBAC/audit hard to verify |
## Implementation Phases
1. Confirm current review/evidence/report/pack/OperationRun services, capabilities, audit helpers, and UI patterns.
2. Add migration/model/policy tests first, including isolation and pgsql-specific constraints.
3. Add review-publication-specific models, migrations, enums/value objects, and policy.
4. Implement readiness evaluator, planner, fingerprinting, case service, action service, and proof resolver.
5. Integrate Environment Review blocked-state CTA and subject-driven resolution page/action.
6. Wire step actions through existing services/jobs and link OperationRun/artifact proof.
7. Add audit events and customer-boundary safeguards.
8. Update UI coverage artifacts.
9. Run focused Unit/Feature/Filament/PostgreSQL/Browser/Pint/diff validation.
10. Record implementation close-out with Filament v5 output contract and deployment impact.
## Data Truth Separation
- **Execution truth**: `OperationRun`.
- **Artifact truth**: `EvidenceSnapshot`, `StoredReport`, `EnvironmentReview`, `ReviewPack`.
- **Backup/snapshot truth**: unchanged and out of scope.
- **Recovery/evidence truth**: existing evidence/report/review/pack services.
- **Operator next action**: Review Publication Resolution Case current step and planner output.
The case may store a pointer to proof but must re-evaluate current truth before completing steps or the case.
## Rollout and Deployment Considerations
- Migrations are required and must be safe on PostgreSQL.
- Queue workers are already involved through existing evidence/report/review/pack operations; no new queue name is planned.
- No new environment variables are planned.
- No new scheduler entry is planned.
- No new storage volume is planned.
- No Filament asset registration is planned. If assets are added later, include `cd apps/platform && php artisan filament:assets` in deploy.
- Staging validation must include migration, focused tests, and browser smoke before production promotion.
## Filament v5 Output Contract For Implementation Close-Out
The implementation close-out must explicitly state:
1. Livewire v4.0+ compliance is preserved; current repo uses Livewire 4.1.4.
2. Filament panel provider registration remains in `apps/platform/bootstrap/providers.php`; no provider registration change unless explicitly made.
3. No globally searchable Resolution Case resource is added. If any Resource is added unexpectedly, global search is disabled or a safe View/Edit page exists.
4. Destructive/high-impact actions: list all new case/step actions and explain confirmation, authorization, audit, and notification behavior.
5. Asset strategy: no assets by default; if assets are registered, deploy includes `php artisan filament:assets`.
6. Tests added/updated: Unit, Feature, Filament/Livewire, PostgreSQL, Browser.
7. Deployment impact: migrations, queues, scheduler, env vars, storage, Dokploy/staging notes.
## Spec Readiness Gate
Preparation readiness is expected to pass after `spec.md`, `plan.md`, `tasks.md`, and `checklists/requirements.md` are present and consistent.
Implementation must stop and update artifacts first if it needs any of:
- generic `action_resolution_*` persistence;
- generic workflow registry/adapter;
- top-level navigation;
- global-searchable case resource;
- customer self-resolution;
- auto-publish behavior;
- new Graph/provider call path;
- new OperationRun type outside existing services;
- new public state/status family beyond the case/step statuses listed in the spec.