diff --git a/.gemini/settings.json b/.gemini/settings.json index dfcb3db2..ea7ec869 100644 --- a/.gemini/settings.json +++ b/.gemini/settings.json @@ -4,11 +4,21 @@ }, "mcpServers": { "laravel-boost": { - "command": "vendor/bin/sail", + "command": "/Users/ahmeddarrazi/Documents/projects/wt-plattform/scripts/platform-sail", "args": [ "artisan", "boost:mcp" ] + }, + "kroki": { + "command": "node", + "args": [ + "/Users/ahmeddarrazi/Documents/projects/kroki-mcp-server/dist/index.js" + ], + "env": { + "KROKI_BASE_URL": "http://development-kroki-ccl69b-553648-194-164-192-109.traefik.me", + "KROKI_TIMEOUT_MS": "10000" + } } } } \ No newline at end of file diff --git a/.github/agents/copilot-instructions.md b/.github/agents/copilot-instructions.md index 8e3f47ae..f477aff7 100644 --- a/.github/agents/copilot-instructions.md +++ b/.github/agents/copilot-instructions.md @@ -272,6 +272,8 @@ ## Active Technologies - PostgreSQL via existing `tenant_reviews`, `tenant_review_sections`, `review_packs`, `evidence_snapshots`, `evidence_snapshot_items`, `stored_reports`, `findings`, `finding_exceptions`, `finding_exception_decisions`, memberships, and `audit_logs`; no new persistence planned (260-governance-service-packaging) - PHP 8.4, Laravel 12 + Filament v5, Livewire v4, Tailwind v4, Pest v4, existing dashboard widgets, `TenantGovernanceAggregateResolver`, `RestoreSafetyResolver`, `BackupHealthDashboardSignal`, `OperationRunLinks`, `RequiredPermissionsLinks`, `TenantRequiredPermissionsViewModelBuilder`, tenant review/evidence/review-pack resources, shared badge rendering, and capability helpers (266-tenant-dashboard-productization-v1) - PostgreSQL via existing tenant-owned findings, exceptions, operation runs, evidence snapshots, review packs, tenant reviews, backup or restore evidence records, memberships, and audit logs; no new persistence planned (266-tenant-dashboard-productization-v1) +- PHP 8.4, Laravel 12 + Filament v5, Livewire v4, Laravel translator, existing `App\Services\Localization\LocaleResolver`, `App\Http\Controllers\LocalizationController`, current `localization.review.*` and locale feedback catalogs, `CustomerReviewWorkspace`, `TenantReviewResource`, `ViewTenantReview`, current review-pack and evidence resource paths, shared RBAC and audit helpers (275-customer-facing-localization-adoption) +- PostgreSQL via existing `users.preferred_locale`, existing workspace localization setting, existing `tenant_reviews`, `review_packs`, `evidence_snapshots`, memberships, and `audit_logs`; translation catalogs in `apps/platform/lang/en` and `apps/platform/lang/de`; no new persistence planned (275-customer-facing-localization-adoption) - PHP 8.4.15 (feat/005-bulk-operations) @@ -306,9 +308,9 @@ ## Code Style PHP 8.4.15: Follow standard conventions ## Recent Changes +- 275-customer-facing-localization-adoption: Added PHP 8.4, Laravel 12 + Filament v5, Livewire v4, Laravel translator, existing `App\Services\Localization\LocaleResolver`, `App\Http\Controllers\LocalizationController`, current `localization.review.*` and locale feedback catalogs, `CustomerReviewWorkspace`, `TenantReviewResource`, `ViewTenantReview`, current review-pack and evidence resource paths, shared RBAC and audit helpers - 266-tenant-dashboard-productization-v1: Added PHP 8.4, Laravel 12 + Filament v5, Livewire v4, Tailwind v4, Pest v4, existing dashboard widgets, `TenantGovernanceAggregateResolver`, `RestoreSafetyResolver`, `BackupHealthDashboardSignal`, `OperationRunLinks`, `RequiredPermissionsLinks`, `TenantRequiredPermissionsViewModelBuilder`, tenant review/evidence/review-pack resources, shared badge rendering, and capability helpers - 260-governance-service-packaging: Added PHP 8.4, Laravel 12 + Filament v5, Livewire v4, Pest v4, existing `TenantReviewComposer`, `TenantReviewSectionFactory`, `ComplianceEvidenceMappingV1`, `ReviewPackService`, `ArtifactTruthPresenter`, capability helpers, localization copy, and shared audit infrastructure -- 259-compliance-evidence-mapping: Added PHP 8.4, Laravel 12 + Filament v5, Livewire v4, Pest v4, existing canonical-control, evidence, tenant-review, RBAC, localization, and audit seams ### Pre-production compatibility check diff --git a/apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php b/apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php index dd987184..352d4a7e 100644 --- a/apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php +++ b/apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php @@ -25,6 +25,7 @@ role: 'owner', workspaceRole: 'manager', ); + $user->forceFill(['preferred_locale' => 'de'])->save(); $tenantWithoutPublished = Tenant::factory()->create([ 'workspace_id' => (int) $tenantPublished->workspace_id, @@ -77,42 +78,45 @@ ]); visit(TenantReviewResource::tenantScopedUrl('view', ['record' => $publishedReview], $tenantPublished)) - ->waitForText('Related context') - ->assertSee('Open customer workspace') + ->waitForText('Verwandter Kontext') + ->assertSee('Kunden-Workspace öffnen') ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() - ->click('Open customer workspace') - ->waitForText('Customer-safe governance package index') - ->assertSee('Clear filters') - ->assertSee('Open review') - ->assertSee('Governance package') + ->click('Kunden-Workspace öffnen') + ->waitForText('Kundensicherer Governance-Paket-Index') + ->assertSee('Filter löschen') + ->assertSee('Review öffnen') + ->assertSee('Governance-Paket') ->assertSee('Status') - ->assertSee('Evidence') - ->assertSee('Review the executive-ready governance package status') - ->assertSee('This workspace summarizes current review evidence for service delivery. It does not replace a formal audit opinion, certification, or legal attestation.') - ->assertSee('Partial') - ->assertSee('Review required') - ->assertSee('Available') - ->assertSee('Review package') + ->assertSee('Nachweise') + ->assertSee('Prüfen Sie für jeden berechtigten Tenant den executive-fähigen Status des Governance-Pakets') + ->assertSee('Dieser Workspace fasst die aktuelle Review- und Nachweislage für die Service-Auslieferung zusammen. Er ersetzt weder ein formales Auditurteil noch eine Zertifizierung oder rechtliche Attestierung.') + ->assertSee('Teilweise') + ->assertSee('Prüfung erforderlich') + ->assertSee('Verfügbar') + ->assertSee('Paket prüfen') + ->assertDontSee('Customer-safe governance package index') + ->assertDontSee('localization.review.customer_safe_review_workspace') ->assertDontSee('Publishable') ->assertDontSee('No mapped controls') ->assertDontSee('Compliance evidence mapping v1') ->assertDontSee('Publish review') ->assertDontSee('Refresh review') - ->click('Clear filters') + ->click('Filter löschen') ->waitForText('Published Tenant') ->assertDontSee('No Published Tenant') ->assertDontSee('No published review available yet') - ->click('Open review') - ->waitForText('Outcome summary') - ->assertSee('Download governance package') - ->assertSee('Governance package') - ->assertSee('Released governance record') - ->assertSee('Review status') - ->assertSee('Primary action') - ->assertSee('Executive entrypoint') - ->assertSee('Structured auditor appendix') - ->assertSee('Assessment basis') + ->click('Review öffnen') + ->waitForText('Ergebniszusammenfassung') + ->assertSee('Governance-Paket herunterladen') + ->assertSee('Governance-Paket') + ->assertSee('Veröffentlichter Governance-Nachweis') + ->assertSee('Review-Status') + ->assertSee('Primäre Aktion') + ->assertSee('Executive-Einstieg') + ->assertSee('Strukturierter Auditor-Anhang') + ->assertSee('Prüfgrundlage') + ->assertDontSee('Released governance record') ->assertDontSee('Control readiness interpretation') ->assertDontSee('Compliance evidence mapping v1') ->assertDontSee('Publish review') diff --git a/apps/platform/tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php b/apps/platform/tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php new file mode 100644 index 00000000..60498187 --- /dev/null +++ b/apps/platform/tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php @@ -0,0 +1,112 @@ +create(['name' => 'Lokalisierter Tenant']); + [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'readonly'); + $user->forceFill(['preferred_locale' => 'de'])->save(); + + $snapshot = seedTenantReviewEvidence($tenant); + + $review = composeTenantReviewForTest($tenant, $user, $snapshot); + $review->forceFill([ + 'status' => TenantReviewStatus::Published->value, + 'published_at' => now(), + 'published_by_user_id' => (int) $user->getKey(), + ])->save(); + + App::setLocale('de'); + + $this->actingAs($user); + setAdminPanelContext(); + session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id); + + Livewire::actingAs($user) + ->test(CustomerReviewWorkspace::class) + ->assertCanSeeTableRecords([$tenant->fresh()]) + ->assertSee('Kundensicherer Governance-Paket-Index') + ->assertSee('Prüfen Sie für jeden berechtigten Tenant den executive-fähigen Status des Governance-Pakets und öffnen Sie bei Bedarf die kundensichere Detailansicht.') + ->assertSee('Jede Zeile ist ein Einstieg in die Detailansicht: Dort sehen Sie Paketstatus, Executive-Einstieg, Nachweise, aktuelle Risiken und den nächsten kundensicheren Schritt.') + ->assertSee('Dieser Workspace fasst die aktuelle Review- und Nachweislage für die Service-Auslieferung zusammen. Er ersetzt weder ein formales Auditurteil noch eine Zertifizierung oder rechtliche Attestierung.') + ->assertSee('Governance-Paket') + ->assertSee('Nachweise') + ->assertSee('Nächster Schritt') + ->assertSee('Review öffnen') + ->assertDontSee('Customer-safe governance package index'); +}); + +it('renders the customer review detail surface in german for the effective locale', function (): void { + Storage::fake('exports'); + + $tenant = Tenant::factory()->create(['name' => 'Lokalisierter Detail-Tenant']); + [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner'); + $user->forceFill(['preferred_locale' => 'de'])->save(); + + $snapshot = seedTenantReviewEvidence($tenant); + + $review = composeTenantReviewForTest($tenant, $user, $snapshot); + $review->forceFill([ + 'status' => TenantReviewStatus::Published->value, + 'published_at' => now(), + 'published_by_user_id' => (int) $user->getKey(), + ])->save(); + + Storage::disk('exports')->put('review-packs/customer-review-localization-test.zip', 'PK-test'); + + $pack = ReviewPack::factory()->ready()->create([ + 'tenant_id' => (int) $tenant->getKey(), + 'workspace_id' => (int) $tenant->workspace_id, + 'tenant_review_id' => (int) $review->getKey(), + 'evidence_snapshot_id' => (int) $snapshot->getKey(), + 'initiated_by_user_id' => (int) $user->getKey(), + 'file_path' => 'review-packs/customer-review-localization-test.zip', + 'file_disk' => 'exports', + ]); + + $review->forceFill(['current_export_review_pack_id' => (int) $pack->getKey()])->save(); + + App::setLocale('de'); + setTenantPanelContext($tenant); + + $this->actingAs($user) + ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) + ->get(TenantReviewResource::tenantScopedUrl('view', ['record' => $review], $tenant).'?'.http_build_query([ + CustomerReviewWorkspace::DETAIL_CONTEXT_QUERY_KEY => 1, + ])) + ->assertOk() + ->assertSee('Veröffentlichter Governance-Nachweis') + ->assertSee('Primäre Aktion') + ->assertSee('Executive-Einstieg') + ->assertSee('Strukturierter Auditor-Anhang') + ->assertDontSee('Released governance record'); + + $component = localizedTenantReviewComponent($user, $review->getKey()); + + $component->assertActionExists( + 'download_current_review_pack', + fn (\Filament\Actions\Action $action): bool => $action->getLabel() === 'Governance-Paket herunterladen', + ); +}); + +function localizedTenantReviewComponent($user, int $reviewId): Testable +{ + return Livewire::withQueryParams([CustomerReviewWorkspace::DETAIL_CONTEXT_QUERY_KEY => 1]) + ->actingAs($user) + ->test(ViewTenantReview::class, ['record' => $reviewId]); +} \ No newline at end of file diff --git a/apps/platform/tests/Feature/Localization/LocalePreferenceFlowTest.php b/apps/platform/tests/Feature/Localization/LocalePreferenceFlowTest.php index 1417cb83..0e18eb0a 100644 --- a/apps/platform/tests/Feature/Localization/LocalePreferenceFlowTest.php +++ b/apps/platform/tests/Feature/Localization/LocalePreferenceFlowTest.php @@ -2,8 +2,10 @@ declare(strict_types=1); +use App\Filament\Pages\Reviews\CustomerReviewWorkspace; use App\Services\Localization\LocaleResolver; use App\Services\Settings\SettingsWriter; +use App\Models\Tenant; use App\Support\Workspaces\WorkspaceContext; it('allows users to save and clear a personal locale preference over workspace default', function (): void { @@ -85,3 +87,16 @@ expect(session(LocaleResolver::SESSION_OVERRIDE_KEY))->toBeNull(); }); + +it('returns to the customer review workspace filter when the locale override changes', function (): void { + $tenant = Tenant::factory()->create(); + [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'readonly'); + + $workspaceUrl = CustomerReviewWorkspace::tenantPrefilterUrl($tenant); + + $this->actingAs($user) + ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) + ->from($workspaceUrl) + ->post(route('localization.override.update'), ['locale' => 'de']) + ->assertRedirect($workspaceUrl); +}); diff --git a/docs/architecture.svg b/docs/architecture.svg new file mode 100644 index 00000000..47bfec1d --- /dev/null +++ b/docs/architecture.svg @@ -0,0 +1 @@ +

TenantPilot Project (wt-plattform)

Microsoft Cloud

Apps

API Calls

SSO/Auth

DevOps & Environment

Laravel Sail (Docker)
Local Dev

Dokploy
Staging & Prod

Gitea
Repo & CI

.specify/
GitHub Spec Kit

apps/platform
(Laravel 12 + Filament v5)

PostgreSQL Database
(JSONB for Snapshots)

Microsoft Graph API
(Intune Policies)

Entra ID / Azure AD
(Auth & RBAC)

apps/website
(Astro)

\ No newline at end of file diff --git a/docs/architecture/tenantpilot-enterprise-architecture.mmd b/docs/architecture/tenantpilot-enterprise-architecture.mmd new file mode 100644 index 00000000..adeca941 --- /dev/null +++ b/docs/architecture/tenantpilot-enterprise-architecture.mmd @@ -0,0 +1,161 @@ +flowchart TB + %% ---------------------------------------------------- + %% 1. USERS & STAKEHOLDERS + %% ---------------------------------------------------- + subgraph Users ["1. Users & Stakeholders"] + SysAdmin(["Platform Superadmin"]) + WsAdmin(["Workspace Admin"]) + TenOp(["Tenant Operator"]) + CustRev(["Customer Reviewer"]) + Auditor(["Auditor / Compliance"]) + ExtSupport(["External Support / PSA"]) + end + + %% ---------------------------------------------------- + %% 2. IDENTITY & ACCESS + %% ---------------------------------------------------- + subgraph Identity_Access ["2. Access & Identity"] + EntraOIDC["Entra OIDC / Tenant Users"] + LocalUsers["Local Platform Users / Break-glass"] + + SysPanel["Platform / System Panel"] + AdminPanel["Admin / Tenant Panel"] + + RBAC["Capability-based RBAC"] + ScopeRes["Workspace / Tenant Scope Resolution"] + end + + %% ---------------------------------------------------- + %% 3. APPLICATION UI + %% ---------------------------------------------------- + subgraph Application_UI ["3. Application UI (Filament)"] + TenDash["Tenant Dashboard"] + OpsHub["Operations Hub"] + InvVersions["Inventory & Policy Versions"] + FindInbox["Findings / Governance Inbox"] + RevWorkspace["Reviews / Customer Workspace"] + EvidReports["Evidence & Reports"] + SuppHandoffUI["Support Handoff"] + end + + %% ---------------------------------------------------- + %% 4. DOMAIN SERVICES + %% ---------------------------------------------------- + subgraph Domain_Services ["4. Domain Services"] + WsSvc["Workspace Service"] + TenSvc["Tenant Service"] + OpRunSvc["OperationRun Service"] + BackRestSvc["Backup / Restore Services"] + DriftSvc["Drift Detection Service"] + BaseCompSvc["Baseline / Compliance Service"] + EvidSnapSvc["Evidence Snapshot Service"] + RevPackSvc["Review Pack Service"] + NotifSvc["Notification Service"] + SuppSvc["Support Handoff Service"] + end + + %% ---------------------------------------------------- + %% 5. EXECUTION & OPERATIONS + %% ---------------------------------------------------- + subgraph Execution_Operations ["5. Execution & Operations"] + Scheduler["Scheduler"] + QueuesJobs["Queues / Jobs"] + OpRunLife["OperationRun Lifecycle"] + ProgStat["Progress / Status / Failure Reason"] + AuditEvt["Audit Events"] + end + + %% ---------------------------------------------------- + %% 6. PROVIDER BOUNDARY + %% ---------------------------------------------------- + subgraph Provider_Boundary ["6. Provider Boundary"] + ProvGateway["Provider Gateway"] + GraphAdapt["Microsoft Graph Adapter"] + IntuneProv["Intune Provider"] + FutProv["Optional future providers"] + + ExtPSA["External PSA / ITSM"] + MailTeams["Email / Teams Notifications"] + end + + %% ---------------------------------------------------- + %% 7. DATA STORE + %% ---------------------------------------------------- + subgraph Data_Store ["7. Data Store (PostgreSQL)"] + dbOrg[("Workspaces & Tenants")] + dbIAM[("Users, Memberships & Capabilities")] + dbOps[("OperationRuns & AuditLogs")] + dbDomain[("Policies, Versions & Findings")] + dbGov[("EvidenceSnapshots & StoredReports")] + dbSupport[("SupportRequests & Notifications")] + end + + %% ---------------------------------------------------- + %% 8. GOVERNANCE & EVIDENCE + %% ---------------------------------------------------- + subgraph Governance_Evidence ["8. Governance & Evidence"] + BaseProf["Baseline Profiles"] + CtrlCat["Control Catalog"] + RiskAcc["Risk Acceptance / Exceptions"] + EvidMap["Evidence Mapping"] + TenRev["Tenant Reviews"] + AudPack["Auditor Packs"] + StoreRep["Stored Reports"] + end + + %% ==================================================== + %% RELATIONSHIPS & EDGES + %% ==================================================== + + %% Users to Identity + SysAdmin & ExtSupport -->|authenticates| LocalUsers + WsAdmin & TenOp & CustRev & Auditor -->|authenticates| EntraOIDC + + LocalUsers -->|accesses| SysPanel + EntraOIDC -->|accesses| AdminPanel + + SysPanel & AdminPanel -->|authorizes| RBAC + RBAC -->|selects scope| ScopeRes + + %% Identity to UI + ScopeRes -->|renders context| TenDash & OpsHub & InvVersions & FindInbox & RevWorkspace & EvidReports & SuppHandoffUI + + %% UI to Domain + TenDash -->|reads state| WsSvc & TenSvc + OpsHub -->|creates run| OpRunSvc + InvVersions -->|fetches state| BackRestSvc + FindInbox -->|reviews| DriftSvc + RevWorkspace -->|publishes review| RevPackSvc + EvidReports -->|views| EvidSnapSvc + SuppHandoffUI -->|escalates| SuppSvc + + %% Domain to Governance + BaseCompSvc -->|manages| BaseProf & CtrlCat + DriftSvc -->|evaluates against| RiskAcc + EvidSnapSvc -->|maps to| EvidMap + RevPackSvc -->|exports report| TenRev & AudPack & StoreRep + + %% Domain to Execution + OpRunSvc -->|dispatches job| QueuesJobs + BackRestSvc & DriftSvc & BaseCompSvc & EvidSnapSvc & RevPackSvc -->|dispatches job| QueuesJobs + Scheduler -->|triggers| QueuesJobs + + QueuesJobs -->|updates| OpRunLife + OpRunLife -->|tracks| ProgStat + OpRunLife -->|emits audit event| AuditEvt + + %% Execution & Domain to Provider + QueuesJobs -->|reads / mutates| ProvGateway + ProvGateway -->|routes to| GraphAdapt & FutProv + GraphAdapt -->|calls| IntuneProv + + NotifSvc & AuditEvt -->|sends notification| MailTeams + SuppSvc -->|creates ticket| ExtPSA + + %% Persistence Layer (Services / Exec to DB) + WsSvc & TenSvc -->|writes| dbOrg + RBAC -->|reads / writes| dbIAM + OpRunLife & AuditEvt -->|records execution truth| dbOps + BackRestSvc & DriftSvc -->|writes| dbDomain + EvidSnapSvc & RevPackSvc -->|writes evidence| dbGov + NotifSvc & SuppSvc -->|writes| dbSupport \ No newline at end of file diff --git a/specs/275-customer-facing-localization-adoption/checklists/requirements.md b/specs/275-customer-facing-localization-adoption/checklists/requirements.md new file mode 100644 index 00000000..91761735 --- /dev/null +++ b/specs/275-customer-facing-localization-adoption/checklists/requirements.md @@ -0,0 +1,54 @@ +# Specification Quality Checklist: Customer-Facing Localization Adoption v1 + +**Purpose**: Validate specification completeness, boundedness, and readiness before implementation +**Created**: 2026-05-04 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] The package stays on one bounded customer-facing localization adoption pass over existing localization and customer-review foundations instead of inventing a new locale system, panel, or auth plane. +- [x] The spec remains product- and behavior-oriented rather than reading like a low-level implementation diff. +- [x] The package explicitly names the repo-real anchors it builds on: `LocaleResolver`, `LocalizationController`, the existing EN/DE catalogs, `CustomerReviewWorkspace`, `TenantReviewResource`, `ViewTenantReview`, and the current review-pack and evidence paths. +- [x] Mandatory repo sections for scope, RBAC, shared-pattern reuse, testing, proportionality, and candidate rationale are completed. + +## Requirement Completeness + +- [x] No `[NEEDS CLARIFICATION]` markers remain. +- [x] Requirements are testable and bounded to existing customer review workspace and released-review detail adoption, glossary completion, localized access messaging, and machine-artifact invariance. +- [x] The package makes English fallback and no-raw-key behavior explicit. +- [x] The package forbids website localization, export or audit localization, new locale infrastructure, and panel or auth-plane expansion. +- [x] Canonical proof commands match across `spec.md`, `plan.md`, `quickstart.md`, and `tasks.md`. + +## Candidate Selection Gate + +- [x] The selected candidate exists in `docs/product/spec-candidates.md`, `docs/product/roadmap.md`, and `docs/product/implementation-ledger.md` as `Customer-Facing Localization Adoption v1`. +- [x] Related anchor specs were checked for completion or close-out signals and treated as context only: Specs 252 and 258 are completed context, and Spec 260 is related context only. +- [x] The chosen slice is smaller and more bounded than deferred alternatives such as Enterprise Access Boundary & Support Access Governance v1, Stored Reports Surface v1, Workspace & Tenant Closure Lifecycle v1, or a broader operator-wide localization program. +- [x] The selected slice explicitly closes the remaining customer-facing localization productization gap without reopening the completed localization foundation. + +## Feature Readiness + +- [x] The package keeps Filament on Livewire v4, provider registration unchanged in `apps/platform/bootstrap/providers.php`, global search unchanged, and assets unchanged. +- [x] The package keeps the current admin-plane workspace page and tenant-scoped released-review detail as the only in-scope surfaces. +- [x] The package keeps review-pack downloads, evidence proof paths, audit rows, JSON payloads, and other machine artifacts unlocalized. +- [x] The package explicitly defers broader operator-wide localization, website localization, localized artifact contents, and new locale infrastructure. + +## Test Governance + +- [x] Planned proof stays bounded to focused `Feature` coverage plus one existing `Browser` smoke. +- [x] No new heavy-governance family or new browser family is introduced by default. +- [x] Fixture growth remains bounded to existing workspace membership, tenant entitlement, released review, current review-pack, and locale helper families. +- [x] The review outcome, workflow outcome, and test-governance outcome are carried into `plan.md` and `tasks.md`. + +## Notes + +- Reviewed against `.specify/memory/constitution.md`, `docs/product/spec-candidates.md`, `docs/product/roadmap.md`, `docs/product/implementation-ledger.md`, `specs/252-platform-localization-v1/spec.md`, `specs/258-customer-review-productization/spec.md`, `specs/260-governance-service-packaging/spec.md`, and the active 275 prep artifacts on 2026-05-04. +- No application implementation was performed while preparing this package. + +## Review Outcome + +- **Outcome class**: `acceptable-special-case` +- **Workflow outcome**: `keep` +- **Test-governance outcome**: `keep` +- **Reason**: The package promotes the remaining customer-facing localization productization gap as one bounded follow-through over repo-real localization and review foundations. It keeps the current locale chain, current customer-safe review surfaces, and current artifact truth, and it explicitly blocks website localization, export or audit localization, and new locale infrastructure. +- **Workflow result**: Ready for implementation. \ No newline at end of file diff --git a/specs/275-customer-facing-localization-adoption/contracts/customer-facing-localization-adoption.openapi.yaml b/specs/275-customer-facing-localization-adoption/contracts/customer-facing-localization-adoption.openapi.yaml new file mode 100644 index 00000000..a5c66041 --- /dev/null +++ b/specs/275-customer-facing-localization-adoption/contracts/customer-facing-localization-adoption.openapi.yaml @@ -0,0 +1,471 @@ +openapi: 3.1.0 +info: + title: TenantPilot Customer-Facing Localization Adoption v1 (Conceptual) + version: 0.1.0 + summary: Conceptual contract for localized customer-review surface adoption over existing locale and review foundations. + description: | + These paths document the existing locale endpoints and current customer-review + surfaces reused by the implementation. The schemas describe the expected + localized view behavior and invariance boundaries for planning purposes only; + they do not introduce a new public API or a new artifact family. +servers: + - url: / +paths: + /localization/context: + get: + summary: Resolve the effective locale for the current request. + operationId: resolveLocalizationContext + description: | + Reuses the existing locale precedence chain over explicit override, + user preference, workspace default, and system default. + responses: + '200': + description: Effective locale context for the current request. + content: + application/json: + schema: + $ref: '#/components/schemas/ResolvedLocaleContext' + + /localization/override: + post: + summary: Set the explicit temporary locale override. + operationId: updateExplicitLocaleOverride + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LocaleOverrideUpdate' + responses: + '200': + description: Locale feedback result after the override becomes effective. + content: + application/json: + schema: + $ref: '#/components/schemas/LocaleFeedbackResult' + '400': + description: Unsupported locale input was rejected. + delete: + summary: Clear the explicit temporary locale override. + operationId: clearExplicitLocaleOverride + responses: + '200': + description: Locale feedback result after the override is cleared. + content: + application/json: + schema: + $ref: '#/components/schemas/LocaleFeedbackResult' + + /users/me/locale-preference: + post: + summary: Persist the authenticated user's locale preference. + operationId: updateUserLocalePreference + description: | + Reuses the existing personal preference path for the workspace-bound user. + The slice does not add a second preference store or a new auth plane. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UserLocalePreferenceUpdate' + responses: + '200': + description: Locale feedback result after saving or clearing the preference. + content: + application/json: + schema: + $ref: '#/components/schemas/LocaleFeedbackResult' + '400': + description: Unsupported locale input was rejected. + '404': + description: The preference path is unavailable outside the current authenticated workspace-user context. + + /admin/reviews/workspace: + get: + summary: View the localized customer review workspace. + operationId: viewLocalizedCustomerReviewWorkspace + description: | + Existing admin-plane workspace page reused as the primary decision + surface for the customer-safe review flow. The route remains read-only + and keeps the current tenant filter and row-action behavior. + parameters: + - in: query + name: tenant + required: false + schema: + type: string + description: Optional existing tenant prefilter using tenant id or external id. + responses: + '200': + description: Localized workspace page rendered. + content: + text/html: + schema: + type: string + application/json: + schema: + $ref: '#/components/schemas/LocalizedCustomerReviewWorkspaceModel' + '404': + description: Not found for non-members, actors without entitled tenants, or explicit out-of-scope tenant targeting. + + /admin/t/{tenant}/reviews/{review}: + get: + summary: View the localized released-review detail from the customer workspace. + operationId: viewLocalizedCustomerReviewDetail + description: | + Existing tenant-scoped review detail route reused as the secondary + context surface. The existing `customer_workspace=1` query flag keeps the + surface read-only and customer-safe. + parameters: + - in: path + name: tenant + required: true + schema: + type: integer + - in: path + name: review + required: true + schema: + type: integer + - in: query + name: customer_workspace + required: false + schema: + type: boolean + description: Existing query-context flag for customer-workspace mode. + responses: + '200': + description: Localized released-review detail rendered. + content: + text/html: + schema: + type: string + application/json: + schema: + $ref: '#/components/schemas/LocalizedCustomerReviewDetailModel' + '403': + description: Forbidden for an in-scope actor missing the record-level review permission. + '404': + description: Not found for tenant mismatches, non-members, or out-of-scope review targets. + + /admin/review-packs/{reviewPack}/download: + get: + summary: Download the current governance-package artifact. + operationId: downloadCurrentGovernancePackage + description: | + Reuses the existing signed review-pack download path. Localization may + change the surrounding UI labels and reasons, but the artifact bytes and + machine-readable payload remain unchanged. + parameters: + - in: path + name: reviewPack + required: true + schema: + type: integer + responses: + '200': + description: Current review-pack artifact streamed unchanged. + content: + application/zip: + schema: + type: string + format: binary + '403': + description: Forbidden because of invalid signature or inaccessible pack download permission. + '404': + description: Review pack not found, unavailable for the current review flow, expired, or outside the accessible tenant scope. Supporting UI reasons such as missing or not-ready remain derived under the existing unavailable state. + + /admin/t/{tenant}/evidence/{evidenceSnapshot}: + get: + summary: Open supporting proof from the localized customer review flow. + operationId: viewLocalizedCustomerReviewProof + description: | + Reuses the existing evidence detail route only after explicit drilldown. + The supporting proof path stays secondary and capability-gated. + parameters: + - in: path + name: tenant + required: true + schema: + type: integer + - in: path + name: evidenceSnapshot + required: true + schema: + type: integer + responses: + '200': + description: Evidence proof detail rendered. + content: + text/html: + schema: + type: string + '403': + description: Forbidden for an in-scope actor missing the evidence capability. + '404': + description: Not found for non-members, mismatched tenant scope, or unavailable proof targets. + +components: + schemas: + SupportedLocale: + type: string + enum: + - en + - de + LocaleSource: + type: string + enum: + - explicit_override + - user_preference + - workspace_default + - system_default + ResolvedLocaleContext: + type: object + required: + - locale + - source + - fallback_locale + - machine_artifacts_invariant + properties: + locale: + $ref: '#/components/schemas/SupportedLocale' + source: + $ref: '#/components/schemas/LocaleSource' + fallback_locale: + type: string + const: en + user_preference_locale: + anyOf: + - $ref: '#/components/schemas/SupportedLocale' + - type: 'null' + workspace_default_locale: + anyOf: + - $ref: '#/components/schemas/SupportedLocale' + - type: 'null' + machine_artifacts_invariant: + type: boolean + const: true + LocaleOverrideUpdate: + type: object + required: + - locale + properties: + locale: + $ref: '#/components/schemas/SupportedLocale' + UserLocalePreferenceUpdate: + type: object + required: + - preferred_locale + properties: + preferred_locale: + anyOf: + - $ref: '#/components/schemas/SupportedLocale' + - type: 'null' + description: Null clears the personal preference and returns the user to inherited behavior. + LocaleFeedbackResult: + type: object + required: + - resolved_locale + - status_message + - machine_artifacts_invariant + properties: + resolved_locale: + $ref: '#/components/schemas/SupportedLocale' + source: + $ref: '#/components/schemas/LocaleSource' + status_message: + type: string + machine_artifacts_invariant: + type: boolean + const: true + LocalizedAccessMessage: + type: object + required: + - state + - label + properties: + state: + type: string + enum: + - available + - partial + - unavailable + - blocked + - expired + label: + type: string + description: + type: string + nullable: true + translation_key: + type: string + nullable: true + CustomerFacingGlossaryBoundary: + type: object + required: + - in_scope_terms + - out_of_scope_artifacts + - fallback_locale + properties: + in_scope_terms: + type: array + items: + type: string + example: + - customer review + - governance package + - current review pack + - proof access + - next step + - review status + - evidence + - accepted risk + out_of_scope_artifacts: + type: array + items: + type: string + example: + - exported review-pack file contents + - raw JSON payloads + - audit action ids and metadata + fallback_locale: + type: string + const: en + LocalizedCustomerReviewWorkspaceEntry: + type: object + required: + - tenant_id + - tenant_name + - governance_package + - proof_access + - primary_action_label + properties: + tenant_id: + type: integer + tenant_name: + type: string + latest_published_review_id: + type: integer + nullable: true + review_status_label: + type: string + nullable: true + accepted_risk_summary: + type: string + nullable: true + governance_package: + $ref: '#/components/schemas/LocalizedAccessMessage' + proof_access: + $ref: '#/components/schemas/LocalizedAccessMessage' + next_step_label: + type: string + nullable: true + primary_action_label: + type: string + primary_action_url: + type: string + nullable: true + glossary_terms_rendered: + type: array + items: + type: string + LocalizedCustomerReviewWorkspaceModel: + type: object + required: + - workspace_id + - resolved_locale + - glossary_scope + - heading_copy + - intro_copy + - disclosure_copy + - entries + - empty_state_copy + - untranslated_keys_detected + - machine_artifacts_invariant + - glossary_boundary + properties: + workspace_id: + type: integer + tenant_filter_id: + type: integer + nullable: true + resolved_locale: + $ref: '#/components/schemas/SupportedLocale' + glossary_scope: + type: string + const: customer_review + heading_copy: + type: string + intro_copy: + type: string + disclosure_copy: + type: string + entries: + type: array + items: + $ref: '#/components/schemas/LocalizedCustomerReviewWorkspaceEntry' + empty_state_copy: + type: string + nullable: true + untranslated_keys_detected: + type: boolean + const: false + machine_artifacts_invariant: + type: boolean + const: true + glossary_boundary: + $ref: '#/components/schemas/CustomerFacingGlossaryBoundary' + LocalizedCustomerReviewDetailModel: + type: object + required: + - review_id + - tenant_id + - resolved_locale + - launched_from_customer_workspace + - section_labels + - governance_package + - proof_access + - operator_actions_hidden + - machine_artifacts_invariant + - glossary_boundary + properties: + review_id: + type: integer + tenant_id: + type: integer + resolved_locale: + $ref: '#/components/schemas/SupportedLocale' + launched_from_customer_workspace: + type: boolean + const: true + dominant_action_label: + type: string + nullable: true + section_labels: + type: array + items: + type: string + accepted_risk_summary: + type: string + nullable: true + governance_package: + $ref: '#/components/schemas/LocalizedAccessMessage' + proof_access: + $ref: '#/components/schemas/LocalizedAccessMessage' + helper_copy: + type: array + items: + type: string + glossary_terms_rendered: + type: array + items: + type: string + operator_actions_hidden: + type: boolean + const: true + machine_artifacts_invariant: + type: boolean + const: true + glossary_boundary: + $ref: '#/components/schemas/CustomerFacingGlossaryBoundary' \ No newline at end of file diff --git a/specs/275-customer-facing-localization-adoption/data-model.md b/specs/275-customer-facing-localization-adoption/data-model.md new file mode 100644 index 00000000..53cb18ce --- /dev/null +++ b/specs/275-customer-facing-localization-adoption/data-model.md @@ -0,0 +1,282 @@ +# Data Model — Customer-Facing Localization Adoption v1 + +**Spec**: `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/spec.md` + +No new persisted tables, locale stores, or glossary registries are required for this feature. The slice reuses existing locale truth, current review and artifact truth, and current translation catalogs, then tightens the derived localized view contracts for the customer-facing review flow. + +## Supported Locale Set + +| Value | Meaning | Notes | +|---|---|---| +| `en` | English | Controlled fallback locale for this slice | +| `de` | German | Only additional supported locale in scope | + +## Reused Source Truth + +### Locale Context + +**Purpose**: Resolve the effective locale for the current customer-facing review request. + +**Reused carriers**: +- session override `tenantpilot.locale_override` +- `users.preferred_locale` +- existing workspace setting `localization.default_locale` +- `config('app.fallback_locale')` + +**Relevant fields**: +- `locale` +- `source` +- `fallback_locale` +- `user_preference_locale` +- `workspace_default_locale` +- `machine_artifacts_invariant` + +**Validation rules**: +- the only supported values remain `en` and `de` +- unsupported input falls back through the existing precedence chain until a supported locale is found +- locale changes affect only rendered copy and feedback, not authorization or machine-readable artifacts + +### Workspace / Tenant Entitlement Context + +**Purpose**: Keep the current workspace boundary and entitled tenant set authoritative before any localized workspace row or released-review detail is composed. + +**Reused carriers**: +- existing workspace membership rows +- existing tenant membership and role assignments +- existing capability registry and role-capability map +- current workspace and remembered-tenant session context + +**Validation rules**: +- non-members remain `404` +- only entitled tenants in the active workspace may appear in the localized customer review workspace +- locale changes must not widen tenant or artifact visibility + +### TenantReview + +**Purpose**: Canonical source for the released customer review detail, current package truth, proof pointers, and existing summary copy inputs. + +**Reused carrier**: existing `tenant_reviews` rows via `App\Models\TenantReview` + +**Relevant fields / relationships**: +- `id` +- `workspace_id` +- `tenant_id` +- `status` +- `published_at` +- `summary` +- `evidence_snapshot_id` +- `current_export_review_pack_id` +- `tenant` +- `evidenceSnapshot` +- `currentExportReviewPack` +- `sections` + +**Validation rules**: +- the customer-safe path continues to use the latest published review per entitled tenant only +- localized wording may change, but the underlying review truth and route ownership do not +- the released-review detail remains the only secondary context surface in customer-workspace mode + +### ReviewPack and EvidenceSnapshot + +**Purpose**: Existing supporting artifact truth for package availability, proof availability, and blocked or expired reasons. + +**Reused carriers**: +- existing `review_packs` rows via `App\Models\ReviewPack` +- existing `evidence_snapshots` rows via `App\Models\EvidenceSnapshot` + +**Relevant fields / relationships**: +- `ReviewPack.status` +- `ReviewPack.expires_at` +- `ReviewPack.file_path` +- `EvidenceSnapshot.status` +- `EvidenceSnapshot.completeness_state` +- `EvidenceSnapshot.expires_at` + +**Validation rules**: +- localized package and proof reasons stay derived from existing truth +- signed review-pack download behavior stays unchanged +- secondary proof access remains capability-gated and lower priority than the review summary + +### Translation Catalog Assets + +**Purpose**: Derived presentation assets that hold the approved customer-facing glossary and locale feedback copy. + +**Reused carriers**: +- `apps/platform/lang/en/localization.php` +- `apps/platform/lang/de/localization.php` + +**Relevant key families**: +- `review.*` +- `notifications.*` +- `validation.*` + +**Validation rules**: +- in-scope customer-facing terms must resolve to approved EN or DE copy +- missing in-scope German lines must fall back to English +- raw translation keys must not appear on the default customer-safe path +- provider-specific artifact names stay secondary and already-gated + +### Audit / Machine Artifact Boundary + +**Purpose**: Preserve stable machine truth while customer-facing copy changes. + +**Reused carriers**: +- existing `audit_logs` +- current review-pack files and signed download responses +- raw JSON and other machine-readable artifact payloads already produced by the product + +**Validation rules**: +- audit action IDs and metadata remain untranslated +- review-pack file bytes, hashes, identifiers, timestamps, and raw payloads remain unchanged +- localization changes only the surrounding UI language and feedback text + +## Derived View Contracts + +### LocalizedCustomerReviewWorkspacePageModel + +**Purpose**: Request-time localized page contract for `/admin/reviews/workspace`. + +**Persistence**: none; derived at request or Livewire render time + +**Fields**: +- `workspace_id` +- `tenant_filter_id` (nullable) +- `resolved_locale` +- `heading_copy` +- `intro_copy` +- `disclosure_copy` +- `entries[]` +- `empty_state_copy` (nullable) +- `untranslated_keys_detected = false` +- `machine_artifacts_invariant = true` + +**Validation rules**: +- locale changes must not reset tenant filters or remembered workspace context +- all default-visible copy must resolve from approved EN or DE lines +- the page keeps one dominant row action: `Open review` + +### LocalizedAccessMessage + +**Purpose**: Reused localized access-state message object for governance-package and proof availability on the current customer-safe review flow. + +**Persistence**: none; derived from existing review-pack and evidence truth + +**Fields**: +- `state` +- `label` +- `description` (nullable) +- `translation_key` (nullable) + +**Validation rules**: +- the only allowed states stay inside the existing derived disclosure set: `available`, `partial`, `unavailable`, `blocked`, and `expired` +- any current not-ready wording remains a reason-level description under the existing `unavailable` state instead of becoming a new state family +- the optional `translation_key` is trace-only and must never leak to the rendered customer-safe surface + +### LocalizedCustomerReviewWorkspaceEntry + +**Purpose**: Localized row-level summary for one entitled tenant in the customer review workspace. + +**Persistence**: none; derived from existing tenant, review, pack, and proof truth + +**Fields**: +- `tenant_id` +- `tenant_name` +- `latest_published_review_id` (nullable) +- `review_status_label` +- `accepted_risk_summary` (nullable) +- `governance_package` (`LocalizedAccessMessage`) +- `proof_access` (`LocalizedAccessMessage`) +- `next_step_label` (nullable) +- `primary_action_label` +- `primary_action_url` (nullable) + +**Validation rules**: +- optional package or proof restrictions must not hide the readable review row +- accepted-risk summary copy must use the same approved glossary as the released-review detail +- glossary terms must match the released-review detail surface +- untranslated or mixed-language states are treated as defects, not acceptable partials + +### LocalizedCustomerReviewDetailModel + +**Purpose**: Request-time localized detail contract for `/admin/t/{tenant}/reviews/{review}` when launched from the customer review workspace. + +**Persistence**: none; derived from the existing review record and current `customer_workspace` query flag + +**Fields**: +- `review_id` +- `tenant_id` +- `resolved_locale` +- `launched_from_customer_workspace` +- `dominant_action_label` +- `section_labels[]` +- `accepted_risk_summary` (nullable) +- `governance_package` (`LocalizedAccessMessage`) +- `proof_access` (`LocalizedAccessMessage`) +- `helper_copy[]` +- `operator_actions_hidden = true` +- `machine_artifacts_invariant = true` + +**Validation rules**: +- customer-workspace mode remains read-only +- `Download governance package` remains the single dominant header action when available +- detail section labels and accepted-risk summary must align with the workspace glossary +- localized helper text must not invent new artifact or workflow states + +### LocalizedLocaleFeedbackMessage + +**Purpose**: Existing session-backed feedback contract returned by locale override and personal preference updates. + +**Persistence**: session flash only + +**Fields**: +- `route_name` +- `resolved_locale` +- `status_message` + +**Validation rules**: +- feedback renders in the newly effective locale +- unsupported locale input uses the existing localized validation message path +- no new notification framework is introduced + +### CustomerFacingGlossaryInventory + +**Purpose**: Planning-only inventory of the terms that must stay aligned across workspace, detail, and locale-feedback surfaces. + +**Persistence**: none; maintained as catalog coverage, not a new table or registry + +**Core terms**: +- `customer review` +- `governance package` +- `current review pack` +- `proof access` +- `next step` +- `review status` +- `evidence` +- `accepted risk` +- `customer-safe detail` + +**Validation rules**: +- the same term should not appear with conflicting customer-facing synonyms across workspace and detail +- out-of-scope artifacts such as raw JSON, audit payloads, and export file contents remain outside the glossary inventory + +## Derived Disclosure States + +This slice introduces no new persisted enum or state family. It reuses the current customer-facing labels and reasons as derived presentation only: + +- `available` +- `partial` +- `unavailable` +- `blocked` +- `expired` + +These remain localized labels and helper text over existing review-pack and proof truth. They do not become new stored lifecycle values. + +## Invariance Boundaries + +The following remain unlocalized in v1: + +- review-pack file contents and hashes +- raw JSON and machine-readable payloads +- audit action identifiers and metadata keys or values +- identifiers, slugs, route parameters, and query semantics +- workspace and tenant entitlement outcomes \ No newline at end of file diff --git a/specs/275-customer-facing-localization-adoption/plan.md b/specs/275-customer-facing-localization-adoption/plan.md new file mode 100644 index 00000000..abc4a5b3 --- /dev/null +++ b/specs/275-customer-facing-localization-adoption/plan.md @@ -0,0 +1,276 @@ +# Implementation Plan: Customer-Facing Localization Adoption v1 + +**Branch**: `275-customer-facing-localization-adoption` | **Date**: 2026-05-04 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/spec.md` +**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/spec.md` + +**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts. + +## Summary + +Complete one bounded customer-facing localization adoption pass over the existing customer review flow. The narrow implementation path is to reuse the repo-real locale precedence and update endpoints in `LocaleResolver` and `LocalizationController`, keep the current customer review workspace and released-review detail as the only in-scope read surfaces, fill the remaining EN/DE glossary and helper-copy gaps in the existing `localization.review.*` catalogs, and preserve current review-pack, proof, entitlement, audit, and machine-artifact behavior unchanged. + +This is prep-only work over the foundations from Specs 252, 258, and 260. Filament remains v5 on Livewire v4, provider registration stays unchanged in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/bootstrap/providers.php`, global-search behavior remains unchanged, no destructive action is introduced, and no new panel, website-localization lane, export/audit localization lane, or generic locale/plugin framework is planned. + +## Technical Context + +**Language/Version**: PHP 8.4, Laravel 12 +**Primary Dependencies**: Filament v5, Livewire v4, Laravel translator, existing `App\Services\Localization\LocaleResolver`, `App\Http\Controllers\LocalizationController`, current `localization.review.*` and locale feedback catalogs, `CustomerReviewWorkspace`, `TenantReviewResource`, `ViewTenantReview`, current review-pack and evidence resource paths, shared RBAC and audit helpers +**Storage**: PostgreSQL via existing `users.preferred_locale`, existing workspace localization setting, existing `tenant_reviews`, `review_packs`, `evidence_snapshots`, memberships, and `audit_logs`; translation catalogs in `apps/platform/lang/en` and `apps/platform/lang/de`; no new persistence planned +**Testing**: Pest v4 feature coverage plus one existing browser smoke on the current customer review flow +**Validation Lanes**: confidence, browser +**Target Platform**: Laravel monolith in `apps/platform`, existing admin plane (`/admin`) plus current tenant-scoped review detail reuse (`/admin/t/{tenant}/...`) +**Project Type**: web application +**Performance Goals**: keep locale adoption request-local and DB-only, avoid extra remote calls, reuse current eager-loaded review/pack/evidence relations, and leave review-pack artifact generation and download payloads unchanged +**Constraints**: scope stays on existing EN/DE customer-facing review surfaces only; no new panel/provider/auth plane, no website localization, no export/JSON/audit artifact localization, no generic locale framework, no new global-search behavior, and no new destructive or mutating customer-workspace action +**Scale/Scope**: one locale foundation reuse path, one customer review workspace page, one released-review detail route in customer-workspace mode, existing review-pack and proof availability messaging, two existing EN/DE catalogs, and focused reuse of the current localization, reviews, tenant-review, and browser test families + +## Likely Affected Repo Surfaces + +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Services/Localization/LocaleResolver.php` for the existing locale precedence contract reused by the customer-facing review flow. +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/LocalizationController.php` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/routes/web.php` for the existing context, override, and personal preference endpoints that already format locale feedback. +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php` for localized row labels, empty-state copy, helper text, and glossary consistency on the canonical landing surface. +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php` for the current localized intro and disclosure copy rendered above the workspace table. +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource.php` for localized detail labels, package and proof availability wording, and customer-workspace summary copy already composed from existing review truth. +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php` for the read-only `customer_workspace` detail mode and the existing `Download governance package` dominant action. +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/ReviewPackDownloadController.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/ReviewPackResource.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php` as reuse-only supporting seams for invariant pack and payload behavior and explicit proof-access messaging. +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/en/localization.php` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/de/localization.php` as the canonical glossary assets to complete in place. +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/LocalePreferenceFlowTest.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/LocalizedNotificationFormattingTest.php`, planned `CustomerReviewSurfaceLocalizationTest.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/TenantReview/TenantReviewUiContractTest.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php` as the bounded proving path for locale adoption. + +## Filament v5 / Panel Notes + +- **Livewire v4.0+ compliance**: The slice remains inside existing Filament v5 pages, resources, Blade views, and Livewire-backed request flows. No Livewire v3 behavior or compatibility work is introduced. +- **Provider registration location**: No provider or panel registration change is planned. Existing provider registration remains in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/bootstrap/providers.php`. +- **Global search**: No new globally searchable resource or search behavior is introduced. Existing review-related search posture remains unchanged by this slice. +- **Destructive actions**: No destructive action enters scope. The customer-facing review flow stays read-only, and existing destructive or manage actions remain out of scope in customer-workspace mode. +- **Asset strategy**: No new Filament asset registration or loading strategy is planned. Deployment expectations remain unchanged; if future work ever registers assets elsewhere, the existing `cd apps/platform && php artisan filament:assets` deploy step still applies. + +## Localization / Glossary Fit + +- Reuse the current `localization.review.*` keyspace as the single canonical customer-facing glossary rather than creating a second glossary file, terminology registry, or translation plugin framework. +- Treat the current workspace intro and disclosure, workspace table labels, empty states, released-review detail labels, current governance-package action, package and proof availability reasons, next-step guidance, and locale-feedback notifications as the bounded v1 surface inventory. +- Keep provider-specific artifact or report names secondary and already-gated. They may remain in deeper evidence or artifact contexts, but they must not become default customer-facing glossary terms. +- Keep raw JSON, exported review-pack contents, audit action IDs and metadata, signed download semantics, identifiers, and timestamps invariant. Localization applies to chrome, helper copy, notifications, and access-state wording only. +- Use English as the controlled fallback for missing in-scope German lines, and treat raw translation-key leakage on the customer-safe path as a blocker. + +## RBAC / Isolation Fit + +- Workspace membership remains the first isolation boundary through the existing `WorkspaceContext` and `TenantReviewRegisterService::canAccessWorkspace(...)` path. +- `/admin/reviews/workspace` remains the canonical workspace-scoped landing route; `/admin/t/{tenant}/reviews/{review}` remains the tenant-scoped secondary context route reached through the existing `customer_workspace=1` query flag. +- Locale changes must not alter current denial behavior: non-members and out-of-scope tenant or review targets remain `404`, while in-scope actors missing record-level review access keep existing `403` behavior. +- Optional supporting access remains capability-gated: current review-pack download keeps the existing `REVIEW_PACK_VIEW` path, and evidence proof reuse remains secondary and gated by the current evidence capability model. +- No new customer identity plane, no widened download entitlement, and no new role family are introduced. + +## Data & Invariance Fit + +- Existing `users.preferred_locale` and the existing workspace default-locale setting remain the only persisted locale truth. +- Existing `TenantReview`, `ReviewPack`, and `EvidenceSnapshot` records remain the canonical source of review, package, and proof truth. +- Translation catalogs remain derived presentation assets only; no new persisted glossary inventory, localization projection table, or review-localized artifact copy is created. +- Existing audit rows remain stable machine truth. Locale adoption must not rename action IDs, mutate audit metadata keys or values, or localize stored audit payloads. +- Existing signed review-pack download and evidence detail routes remain the only secondary artifact and proof seams reused by this slice. + +## UI / Surface Guardrail Plan + +- **Guardrail scope**: changed surfaces +- **Native vs custom classification summary**: mixed +- **Shared-family relevance**: locale controls, status messaging, action labels, helper copy, evidence/report viewer chrome, governance-package access labels, and proof-access reasons +- **State layers in scope**: page, detail, URL-query/session +- **Audience modes in scope**: customer/read-only, customer-admin, auditor-read-only, operator-MSP +- **Decision/diagnostic/raw hierarchy plan**: decision-first, diagnostics-second, support-raw-third +- **Raw/support gating plan**: collapsed and capability-gated on reused detail and proof routes only +- **One-primary-action / duplicate-truth control**: the workspace keeps `Open review` as the one dominant row action; released-review detail keeps `Download governance package` as the one dominant header action in customer-workspace mode; localization should not create parallel summary blocks +- **Handling modes by drift class or surface**: review-mandatory +- **Repository-signal treatment**: review-mandatory +- **Special surface test profiles**: standard-native-filament, shared-detail-family +- **Required tests or manual smoke**: functional-core, state-contract, bounded-browser-smoke +- **Exception path and spread control**: none planned; any new locale framework, new customer shell, or localized export or audit artifact becomes exception-required drift +- **Active feature PR close-out entry**: Smoke Coverage + +## Shared Pattern & System Fit + +- **Cross-cutting feature marker**: yes +- **Systems touched**: locale resolution and feedback endpoints, current review localization catalogs, `CustomerReviewWorkspace`, existing workspace Blade intro, `TenantReviewResource`, `ViewTenantReview`, current governance-package download label, proof-access reasons, and localized status and helper copy +- **Shared abstractions reused**: `LocaleResolver`, `LocalizationController`, existing `localization.review.*` and locale notification and validation strings, existing customer-workspace query flag behavior, current review-pack and evidence truth presenters, and current review and detail RBAC paths +- **New abstraction introduced? why?**: none planned +- **Why the existing abstraction was sufficient or insufficient**: the locale foundation, update endpoints, review workspace, and released-review detail are already repo-real and are the correct shared path. What is insufficient today is glossary completion and consistent surface coverage on those existing seams. +- **Bounded deviation / spread control**: none planned. If a future implementation claims the current keyspace or surfaces are insufficient, it must prove that a narrower in-place catalog or surface update cannot solve the current-release gap. + +## OperationRun UX Impact + +- **Touches OperationRun start/completion/link UX?**: no +- **Central contract reused**: `N/A` +- **Delegated UX behaviors**: `N/A` +- **Surface-owned behavior kept local**: localized copy only on existing read surfaces and locale feedback responses +- **Queued DB-notification policy**: `N/A` +- **Terminal notification path**: `N/A` +- **Exception path**: none + +## Provider Boundary & Portability Fit + +- **Shared provider/platform boundary touched?**: yes +- **Provider-owned seams**: raw provider report or artifact names in already-gated evidence or detail contexts only +- **Platform-core seams**: `customer review`, `governance package`, `proof access`, `next step`, `review status`, `evidence`, and locale feedback wording +- **Neutral platform terms / contracts preserved**: `customer review`, `governance package`, `current review pack`, `proof access`, `next step`, `accepted risk`, and `customer-safe detail` +- **Retained provider-specific semantics and why**: provider-specific names may remain only when a deeper artifact or evidence surface already exposes them under existing entitlement. They do not become default-visible glossary terms. +- **Bounded extraction or follow-up path**: none + +## Constitution Check + +*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* + +- Inventory-first / snapshot truth: PASS. The slice localizes presentation over existing review, pack, and evidence truth only. +- Read/write separation: PASS. The only writes are the already-existing locale override and user preference flows; customer-facing review surfaces remain read-only. +- Graph contract path: PASS. No new Graph call or provider contract work is introduced. +- Deterministic capabilities: PASS. Existing workspace, tenant, and capability seams remain authoritative. +- Workspace and tenant isolation: PASS. Locale changes do not relax current `404` workspace or tenant boundaries. +- RBAC-UX plane separation: PASS. Everything stays in the existing admin plane and current tenant-scoped review routes; no new auth plane is added. +- Destructive confirmation standard: PASS by non-use. No destructive action enters scope. +- Global search safety: PASS. No new searchable resource or search behavior is added. +- OperationRun / Ops-UX: PASS by non-use. No run start, lifecycle, or notification semantics change. +- Data minimization and machine invariance: PASS. Exported review-pack contents, raw JSON, audit payloads, IDs, and other machine artifacts remain unchanged. +- Test governance (TEST-GOV-001): PASS. Proof stays in focused feature coverage plus the existing single browser smoke. +- Proportionality / no premature abstraction: PASS. The narrow path is catalog completion and surface adoption on existing seams, not a new locale or glossary framework. +- Persisted truth (PERSIST-001): PASS. No new table, projection, artifact family, or locale store is planned. +- Behavioral state (STATE-001): PASS. Access and availability labels remain derived presentation over current review-pack and evidence truth; no new persisted state family is added. +- UI semantics / shared pattern first / Filament-native UI: PASS. Existing Filament pages, resources, and the current localization keyspace remain the first reuse path. +- Provider boundary (PROV-001): PASS. Default customer-facing vocabulary stays platform-owned and provider-neutral. +- Filament / Laravel planning contract: PASS. Filament remains v5 on Livewire v4, provider registration remains in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/bootstrap/providers.php`, no panel or provider change is planned, no global-search change is planned, and no new assets are expected. + +**Gate evaluation**: PASS. + +- The narrow implementation remains defensible if it reuses the current locale contract and current customer review flow instead of creating a second glossary or shell. +- The gate fails if implementation drifts into website localization, export or audit localization, a new panel, provider, or auth plane, or a generic locale/plugin framework. + +**Post-design re-check**: PASS once `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/research.md`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/data-model.md`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/quickstart.md`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/contracts/customer-facing-localization-adoption.openapi.yaml` are present and the agent-context refresh step is executed. + +## Test Governance Check + +- **Test purpose / classification by changed surface**: Feature for locale preference and override reuse, localized feedback, customer review workspace and detail copy, and glossary consistency; Browser for one existing end-to-end smoke of the customer review flow +- **Affected validation lanes**: confidence, browser +- **Why this lane mix is the narrowest sufficient proof**: the main risk is rendered customer-facing wording and existing access-state continuity on repo-real surfaces, not new backend workflow breadth or a new browser family +- **Narrowest proving command(s)**: + - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Localization/LocalePreferenceFlowTest.php tests/Feature/Localization/LocalizedNotificationFormattingTest.php tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/TenantReview/TenantReviewUiContractTest.php` + - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php` + - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` +- **Fixture / helper / factory / seed / context cost risks**: low to moderate; reuse existing workspace membership, tenant entitlement, published review, current review-pack, and locale helpers instead of creating a new heavy fixture family +- **Expensive defaults or shared helper growth introduced?**: no; any new helper should stay explicit and local to the localization or reviews family +- **Heavy-family additions, promotions, or visibility changes**: none beyond the already-existing single browser smoke +- **Surface-class relief / special coverage rule**: standard-native-filament relief on the workspace page and shared-detail-family coverage on the customer-workspace review detail +- **Closing validation and reviewer handoff**: rerun the exact commands above, verify no raw translation keys appear on the in-scope surfaces, verify workspace and detail copy use the same glossary in EN and DE, verify locale changes do not alter current `404` or `403` behavior, and verify download, audit, and machine artifacts stay unlocalized +- **Budget / baseline / trend follow-up**: none expected beyond contained feature-local assertions +- **Review-stop questions**: lane fit, hidden fixture growth, glossary drift between workspace and detail, accidental machine-artifact localization, and scope creep into website or framework work +- **Escalation path**: `document-in-feature` for contained glossary inventory notes; `reject-or-split` for any drift into new locale infrastructure or broader localization programs +- **Active feature PR close-out entry**: Smoke Coverage +- **Why no dedicated follow-up spec is needed**: this plan is already the bounded adoption follow-through on existing localization and customer-review foundations; broader operator-wide or website localization remains explicitly out of scope +- **Test-governance outcome**: keep + +## Review Checklist Status + +- **Review checklist artifact**: `checklists/requirements.md` +- **Review outcome class**: `acceptable-special-case` +- **Workflow outcome**: `keep` +- **Test-governance outcome**: `keep` +- **Escalation rule**: if implementation widens into website localization, export or audit localization, a new locale framework, or a new panel or auth plane, flip the workflow outcome to `split` or `reject-or-split` before continuing + +## Rollout & Risk Controls + +- Keep the canonical entry surface on the existing customer review workspace and the canonical secondary surface on the existing released-review detail route. +- Inventory the in-scope customer-facing glossary before code changes, then fill EN/DE catalog gaps in place so workspace and detail copy cannot drift independently. +- Treat English fallback and raw-key avoidance as rollout blockers; a missing German string should render approved English, never the raw key. +- Keep current signed review-pack download and evidence detail behavior unchanged. Localize only surrounding labels, tooltips, helper text, and blocked or unavailable reasons. +- Preserve current tenant and workspace filters and customer-workspace launch context when locale changes mid-flow. +- Keep browser validation bounded to the existing smoke harness before considering wider UI rollout or broader localization scope. + +## Project Structure + +### Documentation (this feature) + +```text +specs/275-customer-facing-localization-adoption/ +├── plan.md +├── research.md +├── data-model.md +├── quickstart.md +├── contracts/ +│ └── customer-facing-localization-adoption.openapi.yaml +└── tasks.md # Created later by /speckit.tasks, not by this plan step +``` + +### Source Code (repository root) + +```text +apps/platform/ +├── app/ +│ ├── Filament/ +│ │ ├── Pages/Reviews/ +│ │ │ └── CustomerReviewWorkspace.php +│ │ └── Resources/ +│ │ ├── TenantReviewResource.php +│ │ └── TenantReviewResource/Pages/ViewTenantReview.php +│ ├── Http/ +│ │ └── Controllers/ +│ │ ├── LocalizationController.php +│ │ └── ReviewPackDownloadController.php +│ ├── Services/ +│ │ └── Localization/ +│ │ └── LocaleResolver.php +│ └── Support/ +│ ├── Audit/ +│ └── Auth/ +├── lang/ +│ ├── en/localization.php +│ └── de/localization.php +├── resources/views/filament/pages/reviews/customer-review-workspace.blade.php +├── routes/web.php +└── tests/ + ├── Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php + ├── Feature/Localization/ + ├── Feature/Reviews/ + └── Feature/TenantReview/ +``` + +**Structure Decision**: Laravel monolith. The future implementation stays inside the existing `apps/platform` localization, customer-review, review-pack, and proof surfaces, with no new panel or provider location and no new persistence layer. + +## Complexity Tracking + +| Violation | Why Needed | Simpler Alternative Rejected Because | +|-----------|------------|-------------------------------------| +| None expected at planning time | The plan reuses existing locale, review, and catalog seams instead of introducing new structural machinery | A new glossary framework, locale plugin system, or customer-facing mirror surface would add ownership cost without a new source-of-truth need | + +## Proportionality Review + +- **Current operator problem**: the repo already resolves locale and exposes customer-safe review surfaces, but the customer-facing review flow still contains mixed or incomplete EN or DE wording and uneven glossary coverage across workspace, detail, and access-state messaging. +- **Existing structure is insufficient because**: the current locale foundation and customer-review productization seams exist, but they do not yet guarantee one completed customer-facing glossary and one bounded surface inventory for language adoption. +- **Narrowest correct implementation**: reuse `LocaleResolver`, `LocalizationController`, current `localization.review.*` catalogs, current workspace and detail surfaces, and focused localization and review tests to complete the customer-facing EN or DE adoption pass in place. +- **Ownership cost created**: ongoing maintenance of a bounded EN or DE customer-facing glossary and a small set of feature and browser assertions for those existing surfaces. +- **Alternative intentionally rejected**: a generic locale or plugin framework, website localization program, export or audit artifact localization pass, or second customer-facing shell was rejected because the current release needs adoption on already-real surfaces, not new infrastructure. +- **Release truth**: current-release follow-through on existing localization and customer-review foundations + +## Phase 0 — Research (output: `research.md`) + +See: `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/research.md` + +Goals: +- Confirm the current locale resolution and feedback seams that must be reused rather than replaced. +- Confirm the bounded customer-facing surface inventory and glossary scope for v1. +- Confirm machine-artifact and audit invariance boundaries. +- Confirm the narrowest proving lane that extends current localization and review tests without opening a broader browser or framework scope. + +## Phase 1 — Design & Contracts (output: `data-model.md`, `quickstart.md`, `contracts/`) + +See: +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/data-model.md` +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/quickstart.md` +- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/contracts/customer-facing-localization-adoption.openapi.yaml` + +Design outputs capture: +- the existing locale, review, pack, proof, and glossary truth reused by the slice +- the derived localized workspace and detail view models and invariance rules +- the conceptual contract for locale endpoints and reused customer-review surfaces +- the exact validation commands and smoke focus that should remain canonical for this plan package + +## Proposed Implementation Phases + +1. **Glossary Inventory & Catalog Gap Audit**: enumerate the current in-scope customer-facing keys across workspace, detail, package and proof reasons, and locale feedback; mark any missing or mixed EN and DE lines without widening scope. +2. **Workspace Localization Adoption**: align the customer review workspace intro, headings, table labels, empty states, and next-step copy with the approved glossary while preserving current tenant filter and row-action behavior. +3. **Released-Review Detail Localization Adoption**: align `ViewTenantReview` customer-workspace mode, detail labels, dominant governance-package action label, helper text, and package and proof availability reasons with the same glossary while keeping the surface read-only. +4. **Regression Proof & Rollout Guardrails**: add or expand the bounded feature test for customer-review surface localization, update the existing workspace and detail assertions as needed, and keep the existing browser smoke as the only browser proof for the slice. diff --git a/specs/275-customer-facing-localization-adoption/quickstart.md b/specs/275-customer-facing-localization-adoption/quickstart.md new file mode 100644 index 00000000..2cba95fc --- /dev/null +++ b/specs/275-customer-facing-localization-adoption/quickstart.md @@ -0,0 +1,49 @@ +# Quickstart — Customer-Facing Localization Adoption v1 + +## Preconditions + +- Docker is running and the Sail stack for `apps/platform` is available. +- The feature stays inside the existing Laravel monolith and current admin plane. +- Filament remains v5 on Livewire v4. +- Provider registration remains in `apps/platform/bootstrap/providers.php`; no provider or panel change is part of this work. +- No website localization, export or JSON or audit artifact localization, generic locale framework, global-search change, or asset-strategy change is in scope. +- The customer-facing flow must reuse the existing locale foundation, current customer review workspace, current released-review detail, current review-pack download, and current proof-routing seams. + +## Intended Implementation Order + +1. Review the current localization seams in `LocaleResolver`, `LocalizationController`, and `routes/web.php` so the implementation reuses the repo-real locale chain and feedback endpoints. +2. Inventory the in-scope customer-facing glossary across `CustomerReviewWorkspace`, `customer-review-workspace.blade.php`, `TenantReviewResource`, and `ViewTenantReview`, then mark any missing or mixed EN and DE lines in `lang/en/localization.php` and `lang/de/localization.php`. +3. Tighten the customer review workspace intro, headings, accepted-risk accountability summary, table labels, empty states, and next-step copy so they all resolve from the approved glossary without changing tenant filters or row-action behavior. +4. Tighten the released-review detail in customer-workspace mode so section labels, accepted-risk status, package and proof helper text, availability reasons, and the dominant `Download governance package` action use the same glossary while the surface stays read-only. +5. Reuse existing review-pack and evidence truth for localized partial, blocked, unavailable, and expired reasons instead of adding a new state family or localization-specific presenter. +6. Keep all machine-readable artifacts unchanged: no localized review-pack contents, no localized raw JSON, and no localized audit payloads. +7. Add or expand the bounded feature test for customer-review surface localization and update the existing workspace or detail assertions needed for glossary alignment. +8. Reuse the existing browser smoke as the only browser proof for the slice. + +## Targeted Validation Commands (after implementation) + +```bash +export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Localization/LocalePreferenceFlowTest.php tests/Feature/Localization/LocalizedNotificationFormattingTest.php tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/TenantReview/TenantReviewUiContractTest.php +export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php +export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent +``` + +## Planned Smoke Checklist (after implementation) + +1. Sign in to `/admin` as an entitled customer-safe reader and open `/admin/reviews/workspace`. +2. Verify the workspace intro, disclosure copy, table labels, package and proof states, and `Open review` action render approved English or German copy with no raw translation keys. +3. Change locale through the existing override or personal preference path and confirm the same workspace keeps its current tenant filter and row set. +4. Open a released review through the existing workspace handoff and confirm the detail remains read-only in customer-workspace mode. +5. Verify `Download governance package` remains the one dominant header action and that blocked or unavailable reasons are localized without changing underlying entitlement behavior. +6. Follow an optional proof path and confirm the route remains capability-gated and secondary. +7. Confirm review-pack downloads, audit identifiers, and other machine-readable artifacts stay unchanged while the surrounding UI text is localized. + +## Notes + +- This is a preparation-only artifact package. No application implementation or validation results belong in this planning output yet. +- Filament remains v5 on Livewire v4. +- Provider registration remains unchanged in `apps/platform/bootstrap/providers.php`. +- No new globally searchable resource or global-search behavior is planned. +- No destructive or mutating customer-workspace action is introduced. +- No website localization or localized export, JSON, or audit artifact contents belong in this slice. +- No new Filament assets are expected. If later implementation unexpectedly registers assets, deployment still uses `cd apps/platform && php artisan filament:assets`, but no such change is planned here. \ No newline at end of file diff --git a/specs/275-customer-facing-localization-adoption/research.md b/specs/275-customer-facing-localization-adoption/research.md new file mode 100644 index 00000000..1773d55d --- /dev/null +++ b/specs/275-customer-facing-localization-adoption/research.md @@ -0,0 +1,58 @@ +# Research — Customer-Facing Localization Adoption v1 + +**Date**: 2026-05-04 +**Spec**: `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/spec.md` + +## Decision 1 — Reuse the current locale precedence and update endpoints + +- **Decision**: Reuse `App\Services\Localization\LocaleResolver`, `App\Http\Controllers\LocalizationController`, and the existing `/localization/context`, `/localization/override`, and `/users/me/locale-preference` routes as the only locale-resolution and feedback path for this slice. +- **Rationale**: Repo truth already resolves `explicit override -> user preference -> workspace default -> system default`, and existing tests already cover preference updates, override behavior, and localized feedback formatting. +- **Alternatives considered**: A page-local locale switch or a second localization service was rejected because it would duplicate the repo-real precedence chain and drift immediately from the established foundation. + +## Decision 2 — Keep the v1 surface inventory bounded to the existing customer review flow + +- **Decision**: Limit customer-facing localization adoption to `/admin/reviews/workspace`, `customer-review-workspace.blade.php`, the existing customer-workspace mode of `ViewTenantReview`, current governance-package and proof-access helper text, and locale-feedback messaging that supports this flow. +- **Rationale**: These are the current customer-safe governance surfaces already present in the repo, while the user and spec explicitly exclude website localization, broad operator-wide translation, and localized artifact contents. +- **Alternatives considered**: A wider operator-wide or website-localization pass was rejected because it broadens scope beyond the current productization blocker. + +## Decision 3 — Use the existing `localization.review.*` keyspace as the canonical glossary home + +- **Decision**: Fill and normalize the customer-facing glossary in place under the current `localization.review.*` keys, with supporting reuse of existing locale notification and validation keys. +- **Rationale**: The current EN and DE catalogs already contain substantial customer-review vocabulary, including `customer_safe_review_workspace`, `download_governance_package`, package and proof availability labels, and blocked or expired state wording. +- **Alternatives considered**: A new glossary registry, a second translation domain, or a generic terminology framework was rejected because the repo already has the right catalog boundary for this flow. + +## Decision 4 — Preserve the current read-only customer-workspace drilldown seam + +- **Decision**: Keep `CustomerReviewWorkspace` as the canonical landing surface and `ViewTenantReview` with `customer_workspace=1` as the only secondary context surface. +- **Rationale**: The current detail page already suppresses lifecycle actions in customer-workspace mode, and current tests already assert the single dominant `Download governance package` action on that surface. +- **Alternatives considered**: A new customer-only detail page or customer portal shell was rejected because it would duplicate review truth, routing, and policy or audit behavior. + +## Decision 5 — Reuse current review-pack and evidence truth for localized access-state wording + +- **Decision**: Localize labels and reasons around current package and proof availability without changing `ReviewPack`, `EvidenceSnapshot`, signed download semantics, or current audit behavior. +- **Rationale**: `TenantReviewResource` already computes localized governance-package availability states, and `ViewTenantReview` already exposes the localized `Download governance package` dominant action. The gap is glossary consistency and coverage, not missing artifact truth. +- **Alternatives considered**: Localizing review-pack contents, introducing a second package state family, or creating a new proof viewer was rejected because those would exceed the bounded presentation-only scope. + +## Decision 6 — Keep machine-readable artifacts invariant + +- **Decision**: Exported review-pack contents, raw JSON, audit action IDs and metadata, identifiers, timestamps, and other machine-readable payloads remain untranslated. +- **Rationale**: Existing localization coverage already guards machine-value invariance in audit tests, and the spec explicitly forbids export, JSON, and audit localization. +- **Alternatives considered**: Localized artifacts or localized audit payloads were rejected because they would blur product truth and introduce compatibility risk without current-release need. + +## Decision 7 — Preserve current RBAC and isolation semantics during locale changes + +- **Decision**: Locale adoption changes presentation only; existing workspace and tenant membership checks, capability gates, `404` and `403` behavior, and optional proof or download gating remain unchanged. +- **Rationale**: The workspace already uses `TenantReviewRegisterService` to constrain visible tenants, and the detail route already scopes review access to the current tenant and record. +- **Alternatives considered**: Customer-specific roles, locale-specific authorization branches, or widened artifact access were rejected because they are outside the scope of localization adoption. + +## Decision 8 — Keep global search, provider registration, and asset strategy unchanged + +- **Decision**: Do not change global-search behavior, provider registration, panel topology, or Filament asset strategy. +- **Rationale**: This is a copy and glossary adoption pass on existing surfaces. The repo already keeps provider registration in `apps/platform/bootstrap/providers.php`, and the spec explicitly says global search and asset strategy stay unchanged unless proven otherwise. +- **Alternatives considered**: Search expansion, provider changes, or new asset bundles were rejected because they are unrelated to the current productization need. + +## Decision 9 — Prove adoption with focused feature tests plus the existing browser smoke + +- **Decision**: Add one bounded customer-review surface localization feature test and reuse the current locale preference, localized feedback, workspace page, tenant review UI contract, and customer review workspace smoke tests as the proving lane. +- **Rationale**: The repo already has the localization and review test foundations needed to prove glossary continuity and rendered copy behavior, while the current browser smoke already covers the handoff path that matters most. +- **Alternatives considered**: A broader browser suite or full-product localization regression lane was rejected because it would add governance cost without better proof for this bounded slice. diff --git a/specs/275-customer-facing-localization-adoption/spec.md b/specs/275-customer-facing-localization-adoption/spec.md new file mode 100644 index 00000000..4b99d32b --- /dev/null +++ b/specs/275-customer-facing-localization-adoption/spec.md @@ -0,0 +1,313 @@ +# Feature Specification: Customer-Facing Localization Adoption v1 + +**Feature Branch**: `275-customer-facing-localization-adoption` +**Created**: 2026-05-04 +**Status**: Draft +**Input**: User description: "Customer-Facing Localization Adoption v1 as a prep-only, implementation-ready productization slice over the already repo-real localization and customer-review foundations, focused on customer-facing adoption, glossary completion, and productized surface coverage without reopening the localization foundation or broadening into website, export, or full-product translation work." + +## Spec Candidate Check *(mandatory — SPEC-GATE-001)* + +- **Problem**: TenantPilot already has repo-real locale resolution, customer-safe review surfaces, and EN/DE translation assets, but customer-facing governance consumption still depends on incomplete glossary coverage and inconsistent language across the current review workspace, released review detail, and governance-package or proof access states. +- **Today's failure**: Customer-safe readers in DACH or EU contexts can reach the right review truth, but they still have to infer meaning from mixed English and German wording, uneven surface coverage, and package or proof labels that feel foundation-ready rather than productized. That leaves the product claim ahead of the actual customer-facing experience. +- **User-visible improvement**: An entitled reader can use the existing locale controls and read the current customer-safe review flow in consistent English or German, with one approved glossary for review status, governance package access, proof access, next-step guidance, and related customer-safe helper text. +- **Smallest enterprise-capable version**: Reuse the existing locale foundation and current customer-safe review flow, then complete one bounded adoption pass over the customer review workspace, released review detail, governance-package or proof access states, and locale-related helper or notification copy needed to make that flow consistently customer-facing in EN and DE. +- **Explicit non-goals**: No new locale or plugin system, no website localization, no new panel or auth plane, no localized export review-pack contents, no JSON or audit artifact localization, no broad full-product translation rewrite, no new persistence or abstraction layer, and no reopening of the completed localization foundation or completed customer-review productization work. +- **Permanent complexity imported**: One bounded customer-facing glossary inventory for already-real surfaces, additional EN/DE catalog coverage for those in-scope keys, and focused regression coverage around customer-safe locale adoption. No new models, tables, state families, or platform-wide presentation framework are introduced. +- **Why now**: `docs/product/roadmap.md`, `docs/product/spec-candidates.md`, and `docs/product/implementation-ledger.md` all keep customer-facing localization as an open productization blocker, while the technical foundation and customer-safe review surfaces are already repo-real. The next value is adoption, not more localization infrastructure. +- **Why not local**: One-off copy fixes on a single page would leave package labels, proof access states, download actions, locale feedback, and released-review detail wording inconsistent. The smallest honest solution is one bounded cross-surface adoption pass over the existing customer-safe review flow. +- **Approval class**: Core Enterprise +- **Red flags triggered**: Foundation-sounding localization theme, multiple surfaces, and a shared glossary obligation. Defense: the slice stays on existing EN/DE locale support and existing customer-safe review surfaces, adds no new locale system, and explicitly forbids export or broad operator-UI localization. +- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | **Gesamt: 11/12** +- **Decision**: approve + +## Review Outcome + +- **Outcome class**: acceptable-special-case +- **Workflow outcome**: keep +- **Test-governance outcome**: keep +- **Reason**: The package is a bounded productization pass over already-real localization and customer-review foundations. It keeps the current locale chain, current customer-safe review surfaces, and current artifact truth, while explicitly blocking website localization, export or audit localization, and any new locale framework. +- **Workflow result**: Ready for implementation. + +## Spec Scope Fields *(mandatory)* + +- **Scope**: canonical-view +- **Primary Routes**: + - existing admin-plane customer review workspace at `/admin/reviews/workspace` + - existing tenant-scoped released review detail route at `/admin/t/{tenant}/reviews/{record}` + - existing locale context and override endpoints reused by the current admin plane at `/localization/context` and `/localization/override` + - existing authenticated user locale preference endpoint at `/users/me/locale-preference` +- **Data Ownership**: Existing `preferred_locale` user preference and existing workspace default locale setting remain the only persisted locale truth. Existing tenant-owned review, evidence, and review-pack records remain authoritative for customer-safe review content. Translation catalogs remain derived presentation assets only. No new persisted truth is introduced. +- **RBAC**: + - this remains inside the existing admin plane and current tenant review access paths + - workspace membership remains the first isolation boundary for the customer review workspace + - tenant review visibility, review-pack access, and proof access keep the current capability and entitlement rules + - locale preference updates remain bound to the authenticated user, and any existing workspace-default locale controls remain under the current workspace settings capability model + - no new role family, customer identity plane, or widened download capability is introduced + +For canonical-view specs, the spec MUST define: + +- **Default filter behavior when tenant-context is active**: The current tenant prefilter behavior of the customer review workspace remains unchanged. Language selection changes presentation only and MUST NOT reset or rewrite current tenant or workspace filter context. +- **Explicit entitlement checks preventing cross-tenant leakage**: Locale changes and localized copy MUST NOT reveal inaccessible tenants, reviews, review packs, or proof links. Non-members or out-of-scope tenant targets remain `404`, and member actors missing a capability keep the existing `403` behavior on gated download or proof actions. + +## Cross-Cutting / Shared Pattern Reuse *(mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write `N/A - no shared interaction family touched`)* + +- **Cross-cutting feature?**: yes +- **Interaction class(es)**: locale controls, status messaging, evidence or report viewers, governance-package access labels, proof-access labels, helper copy, and locale-related notifications +- **Systems touched**: current locale resolution and preference flow, existing `localization.review.*` catalogs, current customer review workspace page, current released review detail surface, and existing review-pack access or proof-access messaging +- **Existing pattern(s) to extend**: the locale foundation from Spec 252, the customer review productization contract from Spec 258, and the governance-package delivery wording introduced as related context in Spec 260 +- **Shared contract / presenter / builder / renderer to reuse**: existing locale resolution and preference flow, existing `localization.review.*` keyspace, current `CustomerReviewWorkspace` page, current `TenantReview` detail surface, and the current governance-package download action on the released review detail +- **Why the existing shared path is sufficient or insufficient**: The resolver, preference flow, and customer-safe review surfaces already exist and are the correct reuse path. What remains insufficient is glossary completion and consistent customer-facing copy coverage across those already-real surfaces. +- **Allowed deviation and why**: none. This slice must not introduce page-local translation behavior, new locale sources, or a second customer-facing glossary. +- **Consistency impact**: Terms such as `review`, `customer review`, `governance package`, `current review pack`, `proof access`, `next step`, and customer-safe availability states must stay aligned across workspace list, released review detail, localized notifications, and helper copy. +- **Review focus**: Reviewers must block any new locale infrastructure, export-localization attempt, page-local synonym drift, or provider-specific wording entering the default customer-facing glossary. + +## OperationRun UX Impact *(mandatory when the feature creates, queues, deduplicates, resumes, blocks, completes, or deep-links to an `OperationRun`; otherwise write `N/A - no OperationRun start or link semantics touched`)* + +N/A - no `OperationRun` start, completion, dedupe, or deep-link semantics are changed by this slice. + +## Provider Boundary / Platform Core Check *(mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write `N/A - no shared provider/platform boundary touched`)* + +- **Shared provider/platform boundary touched?**: yes +- **Boundary classification**: platform-core +- **Seams affected**: customer-facing glossary terms, governance-package labels, proof-access labels, helper text, and availability-state wording +- **Neutral platform terms preserved or introduced**: customer review, governance package, current review pack, proof access, next step, review status, and customer-safe detail +- **Provider-specific semantics retained and why**: Any provider-specific report or artifact names may remain only in already-gated secondary evidence or artifact context where the underlying record is provider-owned. They are not promoted into the default customer-facing glossary. +- **Why this does not deepen provider coupling accidentally**: The slice reuses platform-owned localization keys and current customer-safe review vocabulary rather than translating raw provider payload labels into the default visible path. +- **Follow-up path**: none + +## UI / Surface Guardrail Impact *(mandatory when operator-facing surfaces are changed; otherwise write `N/A`)* + +| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note | +|---|---|---|---|---|---|---| +| Customer Review Workspace page | yes | Native Filament page plus existing customer-review primitives | status messaging, action labels, localized glossary, package and proof availability | page, filter, disclosure | no | Existing page remains the primary customer-safe index; no new page type is introduced | +| Released Customer Review detail | yes | Native Filament resource detail plus existing review and artifact primitives | detail labels, helper text, governance-package access, proof-access states | detail, disclosure, access-state messaging | no | Existing detail remains the secondary context surface; no new report viewer or package registry is introduced | + +## 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 | +|---|---|---|---|---|---|---|---| +| Customer Review Workspace page | Primary Decision Surface | Reader decides which entitled tenant review to open and whether the current review appears ready for customer-safe follow-up | localized review state, governance-package availability, proof status, and next-step wording | released review detail, proof context, and gated artifact detail only after explicit open | Primary because it is the current customer-safe landing surface and should answer the first cross-tenant review question in the chosen language | Follows current review-consumption workflow instead of inventing a new localization dashboard | Removes manual interpretation of mixed-language labels before review drilldown | +| Released Customer Review detail | Secondary Context Surface | Reader validates why the review says what it says and whether the current governance package or proof can be opened or downloaded | localized narrative labels, current governance-package action, localized access-state reasons, and customer-safe helper text | deeper proof context, gated artifact detail, and any provider-owned secondary references only after explicit drilldown | Secondary because it deepens one selected review rather than replacing the workspace entry surface | Keeps customer-facing localization inside the existing review detail route | Prevents repeating the same summary in multiple languages across parallel detail widgets | + +## Audience-Aware Disclosure *(mandatory when operator-facing surfaces are changed)* + +| 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 | +|---|---|---|---|---|---|---|---| +| Customer Review Workspace page | customer-read-only, customer-admin, auditor-read-only, operator-MSP | localized customer-safe review state, governance-package availability, proof availability, and next-step summary | deeper lineage, freshness, and secondary governance detail only after opening the review | raw payloads, provider IDs, and unrestricted support detail stay hidden or gated | `Open review` | raw or support detail, deeper diagnostics, and any out-of-scope operator controls remain hidden | The workspace states one localized summary per tenant row; the detail view owns deeper explanation | +| Released Customer Review detail | customer-read-only, customer-admin, auditor-read-only, operator-MSP | localized section labels, governance-package action, localized package or proof availability reasons, and customer-safe helper text | release history, evidence freshness, and secondary context stay lower priority | raw evidence payloads, provider-debug detail, and unrestricted support detail remain hidden or gated | `Download governance package` | support-only or raw artifact context remains secondary and capability-gated | Detail adds explanation and access-state wording without duplicating the same overview cards as peer truth | + +## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)* + +| 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 | +|---|---|---|---|---|---|---|---|---|---|---|---|---|---| +| Customer Review Workspace page | List / Table / Read-only workspace report | Read-only registry report | Open the released review for one entitled tenant | dedicated `Open review` link column | forbidden | contextual `Back to governance inbox` and `Clear filters` remain neutral header actions only | none | `/admin/reviews/workspace` | `/admin/t/{tenant}/reviews/{record}` | workspace context, tenant filter, review state, governance-package availability | Customer review | localized review state, governance-package state, proof state, and next step | Existing inspect affordance stays a primary link column rather than row click | +| Released Customer Review detail | Detail / Report / Evidence | Read-only detail report | Download the current governance package or inspect localized proof-access status | detail header action plus in-body secondary proof context | forbidden | proof and supporting artifact links remain secondary in-body actions | no new destructive action enters customer-workspace mode; existing destructive manage actions stay out of scope | `/admin/reviews/workspace` | `/admin/t/{tenant}/reviews/{record}` | workspace, tenant, released-review context, package or proof state | Customer review | localized customer-safe labels and access-state explanations for the current released review | Existing customer-workspace mode keeps one dominant header action and no new action family | + +## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)* + +| 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 | +|---|---|---|---|---|---|---|---|---|---|---| +| Customer Review Workspace page | Customer-safe reader or MSP operator preparing customer consumption | Decide which entitled review to open in the chosen language | Read-only workspace review overview | Which current review matters for this tenant, and is the customer-safe package or proof ready? | localized review state, governance-package availability, proof status, and next-step guidance | deeper lineage, freshness, and supporting detail after drilldown only | review state, package availability, proof availability | none | Open review | none | +| Released Customer Review detail | Customer-safe reader or MSP operator continuing the same review | Understand the current governance record and whether the current package or proof can be safely consumed | Read-only detail report | What does this review say in my chosen language, and what customer-safe artifact can I use now? | localized section labels, helper text, governance-package action label, and localized access-state reasons | deeper proof context, release history, and gated secondary artifact detail | review state, package availability, proof-access state | none | Download governance package | none | + +## Proportionality Review *(mandatory when structural complexity is introduced)* + +- **New source of truth?**: no +- **New persisted entity/table/artifact?**: no +- **New abstraction?**: no +- **New enum/state/reason family?**: no +- **New cross-domain UI framework/taxonomy?**: no +- **Current operator problem**: The current locale foundation exists, but customer-facing review consumption still presents incomplete or inconsistent translated terminology across the already-real customer-safe review flow. +- **Existing structure is insufficient because**: The repo already has the right resolver and review surfaces, but those existing surfaces do not yet share one completed customer-facing glossary or one bounded surface inventory for locale adoption. +- **Narrowest correct implementation**: Keep the current locale foundation, keep the current review and package flow, and complete a bounded EN/DE glossary and copy pass only on the customer-facing review surfaces that already exist. +- **Ownership cost**: Ongoing maintenance of the in-scope glossary keys and focused regression coverage for those surfaces only. +- **Alternative intentionally rejected**: A full product-wide translation rewrite, localized export program, or second locale framework was rejected because the current release only needs customer-facing adoption on already-real review surfaces. +- **Release truth**: current-release productization blocker, not future-release preparation + +### Compatibility posture + +This feature assumes a pre-production environment. + +Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec. + +Canonical reuse of the current locale foundation and customer-safe review flow is preferred over introducing any new compatibility layer. + +## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)* + +- **Test purpose / classification**: Feature, Browser +- **Validation lane(s)**: confidence, browser +- **Why this classification and these lanes are sufficient**: Focused feature coverage is the narrowest sufficient proof for locale preference or override reuse, localized customer-safe review surfaces, access-state wording, glossary consistency, and unchanged artifact truth. One bounded browser smoke remains justified because this slice is primarily about rendered customer-facing copy and dominant-action clarity on existing review surfaces. +- **New or expanded test families**: expand the existing localization feature family plus the current customer review workspace and tenant review UI contract tests; keep exactly one bounded browser smoke around the customer review workspace flow +- **Fixture / helper cost impact**: low to moderate. Reuse existing workspace membership, tenant entitlement, customer review workspace, released review, review-pack, and localization helpers instead of introducing a new heavy fixture family. +- **Heavy-family visibility / justification**: exactly one browser smoke stays explicit because this slice changes rendered customer-facing wording and access-state clarity, not backend workflow breadth. +- **Special surface test profile**: shared-detail-family +- **Standard-native relief or required special coverage**: ordinary Filament feature coverage is sufficient for route, entitlement, and localized label assertions. The bounded browser smoke is the only required rendered proof of customer-safe locale adoption. +- **Reviewer handoff**: Reviewers must confirm that localized copy appears only on in-scope customer-safe surfaces, no raw translation keys leak, no export or audit artifact content changes, tenant or workspace scope remains intact, and glossary terms stay aligned between workspace and detail surfaces. +- **Budget / baseline / trend impact**: low feature-local increase only +- **Escalation needed**: none +- **Active feature PR close-out entry**: Smoke Coverage +- **Planned validation commands**: + - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Localization/LocalePreferenceFlowTest.php tests/Feature/Localization/LocalizedNotificationFormattingTest.php tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/TenantReview/TenantReviewUiContractTest.php` + - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php` + - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` + +## Scope Boundaries + +### In Scope + +- bounded customer-facing EN/DE glossary completion for the existing customer review workspace and released review detail +- localized governance-package, current review-pack, and proof-access labels, tooltips, helper text, and access-state reasons on those existing customer-safe surfaces +- locale-related helper or notification copy needed to switch into or remain in the chosen language on the in-scope flow +- explicit verification that customer-facing locale adoption changes surface chrome and messaging only, not underlying review-pack, JSON, audit, or other machine-readable artifacts +- consistent use of the approved customer-safe glossary across workspace list, released review detail, and current governance-package action labels + +### Non-Goals + +- any new locale resolver, plugin framework, or supported-locale expansion beyond the existing EN/DE foundation +- website localization or public documentation translation +- a broad operator-wide translation rewrite outside the existing customer-safe review and package surfaces +- localized export review-pack contents, JSON payloads, audit records, or other machine-readable artifacts +- a new panel, auth plane, customer portal, or new package domain +- reopening Spec 252 localization foundation work or re-normalizing completed Spec 258 artifacts + +## Candidate Selection Rationale + +- **Selected candidate**: Customer-Facing Localization Adoption v1 +- **Source locations**: + - `docs/product/spec-candidates.md` manual-promotion backlog priority 4 + - `docs/product/roadmap.md` customer-facing localization remains a `Next` and manual-promotion productization lane + - `docs/product/implementation-ledger.md` explicit blocker: customer-facing localization adoption is incomplete +- **Why selected**: The active auto-prep queue is intentionally empty, this candidate remains unspecced, and it is the next repo-grounded customer-facing localization follow-through that builds directly on already-real foundations rather than requiring new infrastructure. +- **Why this is the smallest viable implementation slice**: The repo already has locale resolution, language catalogs, customer-safe review workspace, released review detail, and governance-package access messaging. The missing piece is one productized adoption pass over glossary completion and customer-safe surface coverage, not a new localization foundation. +- **Why close alternatives are deferred**: + - `Enterprise Access Boundary & Support Access Governance v1` remains a separate access-governance lane with different trust and audit seams. + - `Stored Reports Surface v1` remains a retained-artifact product surface lane and is not required to make the current customer-safe review flow readable in EN/DE. + - `Workspace & Tenant Closure Lifecycle v1` remains a lifecycle-runtime lane and does not tighten the current customer-facing review or locale contract. + - `First Governed AI Runtime Consumer v1` remains a governed-AI follow-through lane and is not a prerequisite for customer-safe locale adoption. + +## Completed-Spec Guardrail Result + +- **Spec 252 - Platform Localization v1**: completed context only. It already contains review outcome and implementation close-out evidence, so this spec reuses it as foundation context and does not reopen or normalize it. +- **Spec 258 - Customer Review Workspace Productization v1**: completed context only. It already contains implementation close-out evidence and remains the customer-safe review surface foundation for this adoption slice. +- **Spec 260 - Governance-as-a-Service Packaging v1**: related context only. It remains a terminology and package-surface anchor for current governance-package wording, but this spec does not refresh or broaden that package domain. + +## Dependencies + +- existing locale resolution and preference flow already present in the repo +- existing EN/DE `localization.review.*` catalogs and current review-related translation keys +- existing `CustomerReviewWorkspace` page and tenant review detail surface +- existing current governance-package download action and proof-access messaging on the released review detail +- existing customer-safe review RBAC, workspace or tenant isolation, and review-pack entitlement behavior + +## Assumptions + +- The supported locale set remains exactly English and German for this slice. +- Existing locale preference, override, and workspace-default behavior remain the canonical resolution path and are reused rather than redesigned. +- The current `Download governance package` action continues to resolve to the existing current export review pack and remains a customer-safe surface label only. +- Customer-facing localization in v1 applies to surface chrome, helper text, notifications, and access-state wording, not to the underlying downloadable artifact contents or audit payloads. +- Product copy review can approve the bounded customer-facing glossary without creating a new terminology-governance framework. + +## Risks + +- Glossary drift can reappear if workspace and released-review detail copy are translated independently. +- Partial German coverage can leave mixed-language surfaces if the bounded inventory is not enforced explicitly. +- Scope pressure can try to turn this adoption slice into a broad operator-wide rewrite or an export-localization program. +- Provider-owned artifact names could leak into default-visible customer-facing copy if the glossary is not kept platform-first. + +## Follow-Up Candidates Explicitly Kept Out of Scope + +- Enterprise Access Boundary & Support Access Governance v1 +- Stored Reports Surface v1 +- Workspace & Tenant Closure Lifecycle v1 +- First Governed AI Runtime Consumer v1 +- broad operator-wide localization beyond the current customer-safe review flow +- website localization and localized export, JSON, audit, or stored-artifact contents + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - Read the customer review workspace in the chosen language (Priority: P1) + +As an entitled customer-safe reader, I want the current customer review workspace to honor the existing locale choice so I can understand which tenant review to open without translating mixed-language labels myself. + +**Why this priority**: This is the first customer-facing surface in the current governance consumption flow, and it is where the productization gap is most visible. + +**Independent Test**: Set or inherit a supported locale, open the customer review workspace, and verify that the in-scope headings, accepted-risk accountability summary, package or proof states, next-step wording, and `Open review` action use the approved glossary with no raw translation keys. + +**Acceptance Scenarios**: + +1. **Given** an entitled reader resolves to German through the existing locale foundation, **When** they open the customer review workspace, **Then** the workspace heading, accepted-risk accountability summary, governance-package state, proof state, next-step wording, and `Open review` label render in approved German copy. +2. **Given** the same reader switches back to English using the existing locale controls, **When** they reopen the customer review workspace, **Then** the same in-scope terms, including accepted-risk accountability copy and any partial package or proof state, render in approved English copy and the current tenant or workspace filtering remains unchanged. + +--- + +### User Story 2 - Consume released review detail with one consistent customer-safe glossary (Priority: P1) + +As an entitled customer-safe reader, I want the released review detail to use the same approved customer-facing terminology as the workspace so I can trust the current governance package, accepted-risk status, and proof-access messaging. + +**Why this priority**: The product claim fails if the workspace is localized but the released review detail falls back to inconsistent English, mixed synonyms, or unclear package or proof wording. + +**Independent Test**: Open a released review from the customer review workspace in both supported locales and verify that the section labels, accepted-risk status, helper copy, governance-package action, and package or proof access-state reasons use the same glossary as the workspace. + +**Acceptance Scenarios**: + +1. **Given** a released review has a downloadable current governance package, **When** the reader opens the detail in German, **Then** the detail labels, accepted-risk status, and the dominant package action render in approved German while the underlying downloadable artifact remains unchanged. +2. **Given** a released review is missing, partial, blocked, or expired for package or proof access, **When** the reader opens the detail in either supported locale, **Then** the access-state reason appears in the selected language without changing the underlying authorization outcome. + +--- + +### User Story 3 - Receive truthful localized access-state and locale-feedback messaging (Priority: P2) + +As a reader or operator using the customer-safe review flow, I want locale-related helper or notification copy and customer-safe access-state messages to stay localized so the product does not fall back to raw keys or generic English during common follow-up steps. + +**Why this priority**: Trust breaks quickly when the visible review surface is localized but common helper or access-state messages are not. + +**Independent Test**: Trigger locale preference or override feedback and package or proof unavailable states on the in-scope customer-safe flow, then verify that the messages are localized while the same authorization and artifact rules still apply. + +**Acceptance Scenarios**: + +1. **Given** a reader clears or changes their current locale using the existing flow, **When** the action completes, **Then** the resulting helper or notification copy appears in the selected supported language. +2. **Given** a reader can view the released review but not download the current review pack, **When** they inspect the package action state, **Then** the reason is localized and the action remains correctly unavailable. + +### Edge Cases + +- What happens when a German translation is missing for an in-scope key? The surface MUST fall back to approved English copy and MUST NOT show a raw translation key. +- What happens when the reader can open the released review but not the current review pack or proof? The review remains readable, while the blocked or unavailable reason stays localized and truthful. +- What happens when the reader changes locale mid-flow? The next rendered customer-safe surface updates its localized copy while preserving the same tenant, workspace, and review context. +- What happens when the downloadable review pack or proof artifact is expired? The localized access-state wording changes, but the underlying artifact and machine-readable content remain unchanged. + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: System MUST reuse the existing EN/DE locale foundation so the current customer review workspace and released review detail honor the reader's resolved locale without adding a new locale source or locale-management surface. +- **FR-002**: System MUST localize the in-scope customer-facing review surfaces with one approved glossary covering workspace headings, section labels, accepted-risk summaries or status, review status, governance-package wording, proof-access wording, next-step guidance, and related helper copy. +- **FR-003**: System MUST keep the same canonical customer-facing terms across the customer review workspace, released review detail, dominant package action, tooltips, helper text, empty states, and locale-related notifications for this slice. +- **FR-004**: System MUST provide localized and truthful package or proof availability messaging for the current customer-safe review flow, including partial or unavailable states, unavailable reasons such as missing or not-ready where applicable, plus blocked and expired states where they already exist in repo truth. +- **FR-005**: System MUST preserve the current workspace, tenant, and capability enforcement semantics on all in-scope localized surfaces, including existing `404` and `403` behavior. +- **FR-006**: System MUST keep exported review-pack files, raw JSON, audit records, identifiers, timestamps, and other machine-readable artifacts unchanged and unlocalized. +- **FR-007**: System MUST use existing locale-related helper or notification messaging for preference and override feedback rather than introducing a new panel, auth plane, or notification framework. +- **FR-008**: System MUST define and validate a bounded v1 surface inventory for customer-facing locale adoption and MUST leave broader operator-wide localization as follow-up work. +- **FR-009**: System MUST fail safely to approved English copy for missing in-scope translations and MUST NOT render raw translation keys on the default customer-safe path. +- **FR-010**: System MUST keep provider-specific artifact or report wording out of the default customer-facing glossary unless the existing underlying record is intentionally opened through a secondary, already-gated context. + +## 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 | +|---|---|---|---|---|---|---|---|---|---|---| +| Customer Review Workspace | `app/Filament/Pages/Reviews/CustomerReviewWorkspace.php` | `Back to governance inbox` when launched contextually, `Clear filters` | dedicated `Open review` link column | none | none | `Clear filters` only when filters are active | `N/A` | `N/A` | yes | Action-surface contract stays satisfied through one primary inspect affordance and one neutral filter-reset action; this slice only localizes copy and glossary use | +| Released Customer Review detail in customer-workspace mode | `app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php` | `Download governance package` remains the dominant header action in customer-workspace mode | `N/A` | none | none | `N/A` | `Download governance package` | `N/A` | yes | Existing destructive manage actions stay outside the customer-workspace-mode scope for this localization slice; no new actions are introduced | + +### Key Entities *(include if feature involves data)* + +- **Locale Context**: The existing resolved locale and source used to render customer-safe review surfaces, derived from already-real user, workspace, session, and system settings. +- **Customer-Facing Review Glossary Inventory**: The approved EN/DE term set for current customer-safe review surfaces, including review status, governance-package wording, proof-access wording, and next-step guidance. +- **Customer-Safe Artifact Access State**: The existing derived package or proof state shown to a reader on the customer-safe review flow, expressed through localized customer-facing wording without creating a new state family. + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: In acceptance review, 100% of default-visible labels and helper text on the in-scope customer-facing review surfaces render approved English or German copy with zero raw translation keys. +- **SC-002**: An entitled reader can switch to or inherit either supported locale and identify the current review status, next step, and governance-package or proof availability for one tenant review in under 2 minutes. +- **SC-003**: In 100% of sampled acceptance flows, changing locale updates only in-scope surface chrome, helper copy, and feedback messaging while leaving exported review-pack contents, audit payloads, and other machine-readable artifacts unchanged. +- **SC-004**: Product review confirms that the approved customer-facing glossary stays consistent across the customer review workspace, released review detail, and current governance-package action in both supported locales. diff --git a/specs/275-customer-facing-localization-adoption/tasks.md b/specs/275-customer-facing-localization-adoption/tasks.md new file mode 100644 index 00000000..fd56029e --- /dev/null +++ b/specs/275-customer-facing-localization-adoption/tasks.md @@ -0,0 +1,206 @@ +--- +description: "Task list for Customer-Facing Localization Adoption v1" +--- + +# Tasks: Customer-Facing Localization Adoption v1 + +**Input**: Design documents from `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/` +**Prerequisites**: `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/plan.md` (required), `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/spec.md` (required), `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/checklists/requirements.md` (required), `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/research.md`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/data-model.md`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/contracts/customer-facing-localization-adoption.openapi.yaml`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/quickstart.md` + +**Review Artifact**: `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/checklists/requirements.md` is the outcome-of-record for the review outcome class, workflow outcome, and test-governance outcome. If implementation widens into website localization, export or audit localization, a new locale framework, or a new panel or auth plane, update that artifact before continuing. + +**Tests**: Required (Pest) for runtime behavior changes. Keep proof in the existing `confidence` lane plus one bounded `browser` smoke only because this slice changes rendered customer-facing copy, glossary consistency, locale feedback, and dominant-action clarity on existing review surfaces. +**Operations**: No new `OperationRun`, queue, remote call, publication flow, or background processing is introduced. Audit and machine-readable truth remain on the current shared paths only. +**RBAC**: Workspace membership remains the first `404` boundary; tenant or review scope mismatches remain `404`; in-scope actors missing an optional secondary capability keep inherited `403` or explicit unavailable-state behavior. Reuse `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Support/Auth/Capabilities.php` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Services/Auth/RoleCapabilityMap.php`; do not introduce raw capability strings or role-name checks. +**Shared Pattern Reuse**: Reuse `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Services/Localization/LocaleResolver.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/LocalizationController.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/ReviewPackDownloadController.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/ReviewPackResource.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php`, and the existing `localization.review.*` catalogs in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/en/localization.php` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/de/localization.php`. Do not add a new locale framework, panel, provider, auth plane, or customer-facing shell. +**Filament / Panel Guardrails**: Filament remains v5 on Livewire v4. Provider registration remains unchanged in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/bootstrap/providers.php`. No new globally searchable resource, no new panel, no destructive action, and no asset-strategy change are allowed in this slice. +**Organization**: Tasks are grouped by user story so glossary completion, workspace adoption, released-review detail adoption, and localized feedback or invariance protection remain independently testable after shared seams are settled. +**Review Outcome**: `acceptable-special-case` +**Workflow Outcome**: `keep` +**Test-governance Outcome**: `keep` + +## Test Governance Checklist + +- [x] Lane assignment is named and is the narrowest sufficient proof for the changed behavior. +- [x] New or changed tests stay in the smallest honest family, and any browser addition remains explicit and bounded. +- [x] Shared helpers, fixtures, memberships, released reviews, review packs, and locale defaults stay cheap by default. +- [x] Planned validation commands cover the change without pulling in unrelated lane cost. +- [x] Surface test profile stays explicit: `standard-native-filament` for the workspace page and `shared-detail-family` for the customer-workspace review detail. +- [x] Any material budget, baseline, trend, or escalation note is recorded in the active feature package or PR close-out. + +## Phase 1: Setup (Shared Context) + +**Purpose**: Lock the bounded productization slice, glossary scope, and proving lanes before runtime edits begin. + +- [x] T001 Review the bounded slice, explicit non-goals, completed-spec guardrails, and repo-fit outcome in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/spec.md`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/plan.md`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/checklists/requirements.md` +- [x] T002 [P] Review locale-precedence reuse, glossary boundary, customer-workspace route reuse, and machine-artifact invariance in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/research.md`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/data-model.md`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/contracts/customer-facing-localization-adoption.openapi.yaml` +- [x] T003 [P] Confirm the focused Sail/Pest validation commands, existing localization or review test families, and one bounded browser smoke in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/quickstart.md`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Reviews/`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/TenantReview/`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Browser/Reviews/` + +--- + +## Phase 2: Foundational (Blocking Prerequisites) + +**Purpose**: Settle the shared glossary inventory, fallback and invariance guardrails, and reuse seams that every user story depends on. + +**Critical**: No user-story work should begin until this phase is complete. + +- [x] T004 [P] Inventory and map the canonical `localization.review.*` glossary coverage across `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/en/localization.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/de/localization.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/LocalizationController.php` so later story work reuses one approved customer-facing glossary only +- [x] T005 [P] Add or extend shared guard coverage for English fallback, no raw translation-key leakage, localized locale-feedback reuse, and unchanged machine-artifact truth in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/LocalePreferenceFlowTest.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/LocalizedNotificationFormattingTest.php` +- [x] T006 Reuse or minimally tighten the existing locale-resolution and customer-workspace seams in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Services/Localization/LocaleResolver.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/LocalizationController.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/routes/web.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/ReviewPackDownloadController.php` so story work stays on one locale source, one read-only detail route, and unchanged artifact/download behavior + +**Checkpoint**: Shared glossary ownership, fallback safety, and invariance boundaries are fixed before workspace or detail adoption begins. + +--- + +## Phase 3: User Story 1 - Read the customer review workspace in the chosen language (Priority: P1) + +**Goal**: Let an entitled customer-safe reader use the existing locale choice on `/admin/reviews/workspace` without mixed-language labels or broken tenant context. + +**Independent Test**: Resolve English or German through the existing locale foundation, open `/admin/reviews/workspace`, and verify the heading, intro, disclosure copy, package and proof states, next-step wording, empty state, and `Open review` label render with the approved glossary while the current tenant filter stays intact. + +### Tests for User Story 1 + +- [x] T007 [P] [US1] Extend `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php` for EN or DE workspace headings, intro or disclosure copy, accepted-risk accountability summary, package or proof labels including partial states, next-step wording, empty-state copy, `Open review`, and locale-switch filter continuity + +### Implementation for User Story 1 + +- [x] T008 [US1] Complete the workspace glossary entries and missing EN or DE copy in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/en/localization.php` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/de/localization.php` for workspace headings, intro or disclosure copy, accepted-risk accountability summaries, package or proof states including partial, next-step guidance, empty states, and `Open review` +- [x] T009 [US1] Apply the canonical glossary to `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php` so the existing workspace page renders localized customer-facing copy, accepted-risk accountability summary, and existing package or proof states without adding a new action family or row behavior +- [x] T010 [US1] Preserve tenant and workspace filter continuity during locale changes by tightening `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/LocalizationController.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/routes/web.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php` without introducing page-local locale logic + +**Checkpoint**: User Story 1 is independently functional when the workspace is readable in English or German with unchanged filter and row-action behavior. + +--- + +## Phase 4: User Story 2 - Consume released review detail with one consistent customer-safe glossary (Priority: P1) + +**Goal**: Let the same reader open the released review detail from the workspace and see the same customer-facing terminology on package and proof states. + +**Independent Test**: Open a released review from `/admin/reviews/workspace` in both supported locales and verify the section labels, helper copy, dominant `Download governance package` action, and localized package or proof access reasons match the workspace glossary while the detail stays read-only in customer-workspace mode. + +### Tests for User Story 2 + +- [x] T011 [P] [US2] Extend `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/TenantReview/TenantReviewUiContractTest.php` for customer-workspace detail section labels, accepted-risk status, helper copy, localized package or proof reasons including partial states, dominant `Download governance package` wording, and glossary continuity with the workspace surface +- [x] T012 [P] [US2] Extend `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php` for the bounded workspace-to-detail handoff, localized dominant action, secondary proof-path visibility, and the absence of raw translation keys while keeping browser proof inside the existing smoke family only + +### Implementation for User Story 2 + +- [x] T013 [US2] Complete the released-review detail glossary entries and missing EN or DE copy in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/en/localization.php` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/de/localization.php` for section labels, accepted-risk status wording, helper text, governance-package wording, proof-access wording, and localized partial or unavailable or blocked or expired reasons +- [x] T014 [US2] Apply the shared glossary to `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource.php` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php` so the existing customer-workspace detail flow stays read-only, explanatory, and centered on one dominant `Download governance package` action +- [x] T015 [US2] Reuse current package and proof truth in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/ReviewPackDownloadController.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/ReviewPackResource.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php` so localized labels and reasons, including partial package or proof states, stay truthful without changing signed downloads, proof gating, or customer-workspace read-only mode + +**Checkpoint**: User Story 2 is independently functional when the released-review detail uses the same glossary as the workspace and keeps the one-action customer-workspace contract. + +--- + +## Phase 5: User Story 3 - Receive truthful localized access-state and locale-feedback messaging (Priority: P2) + +**Goal**: Keep locale feedback, blocked or unavailable messaging, and fallback behavior localized without changing authorization or machine-readable artifact truth. + +**Independent Test**: Trigger locale preference or override feedback and in-scope unavailable, blocked, or expired package or proof states, then verify the messages render in the effective locale with English fallback only and with unchanged `404` or `403`, download, and machine-artifact behavior. + +### Tests for User Story 3 + +- [x] T016 [P] [US3] Extend `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/LocalePreferenceFlowTest.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/LocalizedNotificationFormattingTest.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php` for localized override or preference feedback, localized partial or unavailable or blocked or expired messaging, controlled English fallback, no raw-key leakage, and unchanged artifact-truth assertions on the in-scope customer-safe flow + +### Implementation for User Story 3 + +- [x] T017 [US3] Finalize locale-feedback copy and supported fallback behavior in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/LocalizationController.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Services/Localization/LocaleResolver.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/en/localization.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/de/localization.php` so override or preference responses render in the effective locale without a new notification or locale framework +- [x] T018 [US3] Keep package or proof availability messaging, including partial or unavailable or blocked or expired states, `404` or `403` semantics, and machine-readable artifact invariance unchanged while localized reasons render in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/ReviewPackDownloadController.php` without localizing review-pack bytes, raw JSON, audit payloads, or identifiers + +**Checkpoint**: User Story 3 is independently functional when feedback and access-state messaging stay localized and truthful without altering artifact or authorization truth. + +--- + +## Phase 6: Polish & Cross-Cutting Validation + +**Purpose**: Run the canonical proof commands, format touched files, and keep any discovered spillover explicit instead of absorbing it into this slice. + +- [x] T019 Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Localization/LocalePreferenceFlowTest.php tests/Feature/Localization/LocalizedNotificationFormattingTest.php tests/Feature/Localization/CustomerReviewSurfaceLocalizationTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/TenantReview/TenantReviewUiContractTest.php` exactly as recorded in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/plan.md` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/quickstart.md` +- [x] T020 Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php` exactly as recorded in `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/plan.md` and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/quickstart.md` +- [x] T021 Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` for all touched platform files +- [x] T022 Review `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Services/Localization/LocaleResolver.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Http/Controllers/LocalizationController.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/en/localization.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/lang/de/localization.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/plan.md`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/quickstart.md`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/275-customer-facing-localization-adoption/checklists/requirements.md` to confirm no website localization, no export or JSON or audit-artifact localization, no new panel or provider or auth plane, no locale framework, and explicit `follow-up-spec` recording for any spillover discovered during implementation + +--- + +## Dependencies & Execution Order + +### Phase Dependencies + +- **Phase 1 (Setup)**: no dependencies; start immediately. +- **Phase 2 (Foundational)**: depends on Phase 1 and blocks all user stories until glossary inventory, fallback safety, and reuse seams are settled. +- **Phase 3 (US1)**: depends on Phase 2 and delivers the first customer-facing localization increment on the workspace landing surface. +- **Phase 4 (US2)**: depends on Phase 2 and should follow US1 because it deepens the same workspace-led review flow on shared files and copy. +- **Phase 5 (US3)**: depends on Phase 2 and is safest after US1 and US2 because feedback, fallback, and invariance hardening rely on the final glossary contract. +- **Phase 6 (Polish)**: depends on all implemented stories. + +### User Story Dependencies + +- **US1 (P1)**: first independently testable increment once the glossary inventory and fallback guardrails exist. +- **US2 (P1)**: independently testable after Phase 2, but should merge after US1 because the workspace and detail must share one glossary and one dominant-action contract. +- **US3 (P2)**: independently testable after Phase 2, but should merge after US1 and US2 because it hardens the localized feedback and invariance behavior of the same flow. + +### Within Each User Story + +- Write the listed Pest coverage first and make it fail for the intended gap before runtime implementation. +- Reuse the existing locale, review, package, and proof seams before adding any new helper or translation mapping. +- Re-run the narrowest relevant validation command after each story checkpoint before moving to the next story. + +--- + +## Parallel Execution Examples + +### Phase 1 + +- T002 and T003 can run in parallel after T001 confirms the bounded slice. + +### Phase 2 + +- T004 and T005 can run in parallel while T006 settles the shared reuse seam. + +### User Story 1 + +- T007 can run in parallel with any last Phase 2 cleanup. +- After the missing glossary terms are identified, T008 and T010 can proceed in parallel before T009 finalizes the workspace copy wiring. + +### User Story 2 + +- T011 and T012 can run in parallel because they cover feature and browser proof separately. +- After the missing glossary terms are identified, T013 and T015 can proceed in parallel before T014 finalizes the shared detail surface wording. + +### User Story 3 + +- T016 can run in parallel with late US2 verification. +- T017 and T018 can proceed in parallel once the feedback and invariance gaps are proven. + +--- + +## Implementation Strategy + +### Suggested MVP Scope + +- MVP = **Phase 2 + US1 + US2**. The package becomes product-meaningful once the existing workspace and released-review detail both render one customer-facing EN or DE glossary on the current review flow. + +### Incremental Delivery + +1. Complete Phase 1 and Phase 2. +2. Deliver US1 and validate the localized workspace surface. +3. Deliver US2 and validate the localized released-review detail plus the bounded browser smoke. +4. Deliver US3 and validate localized feedback, fallback safety, and invariance protection. +5. Finish with Phase 6 validation, formatting, and explicit spillover review. + +### Team Strategy + +1. Settle the glossary inventory and fallback guardrails before changing multiple shared surfaces. +2. Parallelize test authoring inside each story before converging on the shared localization files. +3. Serialize merges around `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php`, and `/Users/ahmeddarrazi/Documents/projects/wt-plattform/apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php` because they are the main conflict hotspots for this slice. + +--- + +## Explicit Follow-Ups / Out of Scope + +- Broader operator-wide localization outside the existing customer-review workspace, released-review detail, and locale-feedback surfaces remains a separate follow-up spec. +- Website localization remains out of scope and must not be folded into this task list. +- Localized export review-pack contents, raw JSON, audit payloads, or other machine-readable artifacts remain out of scope and must not be folded into this task list. +- Any new locale or plugin framework, new panel, provider-registration change, new auth plane, or customer portal shell remains out of scope and must be split into a separate follow-up spec if later required. +- Any spillover discovered during implementation that cannot be contained to the in-scope customer-facing review flow must resolve as explicit `follow-up-spec`, not as an implicit expansion of this feature. \ No newline at end of file