TenantAtlas/specs/285-workspace-rbac-environment-access/tasks.md
ahmido c7b38606a9 feat: implement spec 285 workspace-first environment access (#344)
Implements platform feature branch `285-workspace-rbac-environment-access`.

Summary:
- switch managed environment authorization to workspace-first role resolution with explicit environment-scope narrowing
- rewire Filament pages, resources, policies, and user tenant access helpers to the shared access-scope resolver
- add Spec 285 coverage across unit, feature, and browser tests plus full spec artifacts

Validation:
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Auth/WorkspaceFirstCapabilityResolverTest.php tests/Unit/Auth/ManagedEnvironmentAccessScopeResolverTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Auth/WorkspaceFirstManagedEnvironmentAccessTest.php tests/Feature/Filament/ManagedEnvironmentAccessScopeManagementTest.php tests/Feature/Filament/WorkspaceMembershipRoleManagementTest.php tests/Feature/Rbac/GovernanceArtifactsWorkspaceFirstAuthorizationTest.php tests/Feature/Rbac/OperationRunWorkspaceFirstAuthorizationTest.php tests/Feature/Rbac/ProviderConnectionWorkspaceFirstPolicyTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Verification/ProviderExecutionReauthorizationTest.php tests/Feature/ProviderConnections/ProviderConnectionHealthCheckStartSurfaceTest.php tests/Feature/Tenants/TenantProviderBackedActionStartTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Audit/TenantMembershipAuditLogTest.php tests/Feature/Filament/TenantMembersTest.php tests/Feature/TenantRBAC/TenantMembershipCrudTest.php tests/Feature/TenantRBAC/TenantSwitcherScopeTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec285WorkspaceRbacEnvironmentAccessSmokeTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`

Target branch: `platform-dev`.

Follow-up integration path after merge:
- `platform-dev` -> `dev`.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #344
2026-05-09 12:40:50 +00:00

24 KiB

description
Task list for Workspace-first RBAC & Environment Access Scoping

Tasks: Workspace-first RBAC & Environment Access Scoping

Input: Design documents from specs/285-workspace-rbac-environment-access/
Prerequisites: specs/285-workspace-rbac-environment-access/spec.md, specs/285-workspace-rbac-environment-access/plan.md, specs/285-workspace-rbac-environment-access/checklists/requirements.md, specs/285-workspace-rbac-environment-access/research.md, specs/285-workspace-rbac-environment-access/data-model.md, specs/285-workspace-rbac-environment-access/quickstart.md, and specs/285-workspace-rbac-environment-access/contracts/workspace-rbac-environment-access.logical.openapi.yaml
Implementation Posture: Runtime implementation completed in this branch.
Tests: REQUIRED (Pest). Keep proof bounded to apps/platform/tests/Unit/Auth/WorkspaceFirstCapabilityResolverTest.php, apps/platform/tests/Unit/Auth/ManagedEnvironmentAccessScopeResolverTest.php, apps/platform/tests/Feature/Auth/WorkspaceFirstManagedEnvironmentAccessTest.php, apps/platform/tests/Feature/Rbac/ProviderConnectionWorkspaceFirstPolicyTest.php, apps/platform/tests/Feature/Rbac/OperationRunWorkspaceFirstAuthorizationTest.php, apps/platform/tests/Feature/Rbac/GovernanceArtifactsWorkspaceFirstAuthorizationTest.php, apps/platform/tests/Feature/Filament/WorkspaceMembershipRoleManagementTest.php, apps/platform/tests/Feature/Filament/ManagedEnvironmentAccessScopeManagementTest.php, and apps/platform/tests/Browser/Spec285WorkspaceRbacEnvironmentAccessSmokeTest.php.
Operations: No new OperationRun family. Reuse apps/platform/app/Support/Operations/OperationRunCapabilityResolver.php, the current OperationRunPolicy, existing run links or monitoring surfaces, and the current OperationRunService lifecycle ownership.
RBAC: Workspace membership is the first 404 boundary, managed-environment scope is the second 404 boundary, and in-scope capability denials remain 403. Provider capability or operability blockers remain downstream of local RBAC and must not be folded into user authorization.
Shared Pattern Reuse: Reuse WorkspaceCapabilityResolver, CapabilityResolver, WorkspaceContext, WorkspaceMembershipManager, TenantMembershipManager or its in-slice successor, OperationRunCapabilityResolver, and the current Filament relation-manager patterns. Do not add a new role family, a second ACL product, a compatibility shim, or adjacent Spec 284, 286, or 287 work.
Filament / Panel Guardrails: Filament remains v5 on Livewire v4. Provider registration remains in apps/platform/bootstrap/providers.php. ProviderConnectionResource remains non-globally-searchable while keeping valid View and Edit pages. Any touched destructive action must continue to use ->action(...), ->requiresConfirmation(), and current server authorization. Asset strategy stays unchanged.
Compatibility Posture: Reject dual-write or fallback reads between workspace and environment role truth, reject per-environment role overrides, reject a second role selector on environment-scope surfaces, and keep Specs 284, 286, and 287 deferred.
External Prerequisites: Specs 280, 281, and 283 must already be merged or otherwise present on the implementation branch before any runtime or test task starts.
Organization: Tasks are grouped by user story so workspace-first core authorization, explicit environment-scope narrowing, and operator-facing membership-surface migration remain independently testable.
Review Outcome: implemented-and-validated
Workflow Outcome: complete
Test-governance Outcome: keep

Test Governance Checklist

  • Lane assignment stays fast-feedback, confidence, and one narrow browser lane.
  • New or changed tests stay in the named unit, feature, and browser files only.
  • Workspace, managed-environment, and access-scope fixtures remain explicit and opt-in; no hidden global defaults or compatibility fixtures are planned.
  • Planned validation commands match spec.md, plan.md, and quickstart.md exactly.
  • standard-native-filament, global-context-shell, and shared authorization expectations stay explicit for touched surfaces.
  • Any attempt to absorb Specs 284, 286, or 287 resolves as split or reject-or-split, not hidden follow-up.

Phase 0: External Gate

Purpose: Confirm the prerequisite cutover slices are present before implementation begins.

  • T000 Confirm Specs 280, 281, and 283 are already merged or otherwise present on the implementation branch before any runtime or test task begins.

Phase 1: Setup (Shared Context)

Purpose: Confirm the exact repo seams, bounded proof files, and deferred-scope posture before runtime edits begin.

  • T001 Review specs/285-workspace-rbac-environment-access/spec.md, plan.md, checklists/requirements.md, research.md, data-model.md, quickstart.md, and contracts/workspace-rbac-environment-access.logical.openapi.yaml together so implementation stays on Spec 285 only.
  • T002 [P] Confirm the current workspace-role seams in apps/platform/app/Models/WorkspaceMembership.php, apps/platform/app/Services/Auth/WorkspaceCapabilityResolver.php, apps/platform/app/Services/Auth/WorkspaceMembershipManager.php, and any supporting workspace-role enums or policies before changing shared authorization logic.
  • T003 [P] Confirm the current managed-environment membership seams in apps/platform/app/Models/ManagedEnvironmentMembership.php, apps/platform/app/Services/Auth/CapabilityResolver.php, apps/platform/app/Services/Auth/TenantMembershipManager.php, and any supporting tenant-role or role-capability mapping files before retargeting environment access.
  • T004 [P] Confirm the current user and workspace-context seams in apps/platform/app/Models/User.php and apps/platform/app/Support/Workspaces/WorkspaceContext.php before retargeting tenant selection, remembered context, and canAccessTenant().
  • T005 [P] Confirm the current policy and run-authorization seams in apps/platform/app/Policies/ProviderConnectionPolicy.php, apps/platform/app/Policies/OperationRunPolicy.php, apps/platform/app/Policies/FindingPolicy.php, apps/platform/app/Policies/EvidenceSnapshotPolicy.php, apps/platform/app/Policies/ReviewPackPolicy.php, apps/platform/app/Policies/TenantReviewPolicy.php, apps/platform/app/Policies/TenantOnboardingSessionPolicy.php, and apps/platform/app/Support/Operations/OperationRunCapabilityResolver.php before changing environment-owned access rules.
  • T006 [P] Confirm the current operator-facing membership and searchable-resource seams in apps/platform/app/Filament/Resources/TenantResource/Pages/ManageTenantMemberships.php, apps/platform/app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php, apps/platform/app/Filament/Resources/Workspaces/RelationManagers/WorkspaceMembershipsRelationManager.php, apps/platform/app/Filament/Resources/TenantResource.php, apps/platform/app/Filament/Resources/Workspaces/WorkspaceResource.php, apps/platform/app/Filament/Resources/ProviderConnectionResource.php, and any touched action helpers so the implementation does not leave duplicate role-editing paths or unsafe searchable results behind.

Phase 2: Foundational (Blocking Prerequisites)

Purpose: Establish the proving suite and the canonical workspace-first access contract that all user stories depend on.

Critical: No user-story work should begin until this phase is complete.

  • T007 [P] Add failing coverage in apps/platform/tests/Unit/Auth/WorkspaceFirstCapabilityResolverTest.php for workspace-role resolution, per-request caching, capability evaluation without role-bearing managed-environment membership fallback, and boundary-safe denied-access diagnostics.
  • T008 [P] Add failing coverage in apps/platform/tests/Unit/Auth/ManagedEnvironmentAccessScopeResolverTest.php for inherited access when no scope rows exist, allowlist narrowing when scope rows exist, invalid scope rows outside the workspace boundary, and scope-row invalidation when workspace membership ends.
  • T009 [P] Add failing coverage in apps/platform/tests/Feature/Auth/WorkspaceFirstManagedEnvironmentAccessTest.php for User::canAccessTenant(), getTenants(), getDefaultTenant(), WorkspaceContext, and representative environment-owned list, run-list, and bulk-authorization preflight behavior using one shared workspace-first access contract without avoidable N+1 membership or scope lookups.
  • T010 [P] Add failing coverage in apps/platform/tests/Feature/Rbac/ProviderConnectionWorkspaceFirstPolicyTest.php, apps/platform/tests/Feature/Rbac/OperationRunWorkspaceFirstAuthorizationTest.php, and apps/platform/tests/Feature/Rbac/GovernanceArtifactsWorkspaceFirstAuthorizationTest.php for 404 versus 403 semantics across provider connections, runs, findings, evidence, review packs, and tenant reviews, including boundary-safe denied-access logging with no raw provider detail.
  • T011 [P] Add failing coverage in apps/platform/tests/Feature/Filament/WorkspaceMembershipRoleManagementTest.php and apps/platform/tests/Feature/Filament/ManagedEnvironmentAccessScopeManagementTest.php for workspace role management staying canonical, last-owner protection remaining workspace-scoped, environment-scope CRUD staying scope-only, and destructive actions preserving confirmation and authorization.
  • T012 [P] Add the narrow browser smoke in apps/platform/tests/Browser/Spec285WorkspaceRbacEnvironmentAccessSmokeTest.php for one workspace owner managing a member role, narrowing that member to one managed environment, and confirming shell access plus one environment-bound drilldown follow the new contract.
  • T013 Introduce the smallest shared workspace-first access contract under apps/platform/app/Services/Auth/ by retargeting WorkspaceCapabilityResolver, CapabilityResolver, and any supporting helper seam so one canonical access decision answers workspace membership, optional environment scope, required capability, search visibility, and boundary-safe denied-access diagnostics without keeping dual role authority.
  • T014 Update apps/platform/app/Models/ManagedEnvironmentMembership.php, apps/platform/app/Services/Auth/TenantMembershipManager.php, and any directly cooperating support or audit seams so managed-environment membership semantics become a narrow access-scope overlay with no role-bearing authority and so scope rows are removed or invalidated when workspace membership ends.

Checkpoint: The proving files exist, the shared access contract is explicit, and no later story needs to invent a second authorization path.


Phase 3: User Story 1 - Workspace membership alone authorizes environment resources (Priority: P1)

Goal: A workspace member with the required role can open environment-owned resources without any second role-bearing managed-environment membership.

Independent Test: Add a user through workspace membership only, open an allowed managed environment in that workspace, and confirm provider connections plus governance artifacts authorize from workspace role plus capability while non-members remain 404.

Tests for User Story 1

  • T015 [P] [US1] Extend apps/platform/tests/Feature/Auth/WorkspaceFirstManagedEnvironmentAccessTest.php after T013-T014 to prove workspace membership alone is sufficient when no explicit environment scope rows exist.
  • T016 [P] [US1] Extend apps/platform/tests/Feature/Rbac/ProviderConnectionWorkspaceFirstPolicyTest.php and apps/platform/tests/Feature/Rbac/GovernanceArtifactsWorkspaceFirstAuthorizationTest.php after T013-T014 to prove provider connections, findings, evidence snapshots, review packs, tenant reviews, onboarding sessions, and any touched searchable-resource destinations all authorize from workspace membership first and keep 404 versus 403 semantics honest.

Implementation for User Story 1

  • T017 [US1] Update apps/platform/app/Models/User.php and apps/platform/app/Support/Workspaces/WorkspaceContext.php so tenant selection, default tenant resolution, remembered tenant context, and canAccessTenant() all consume the shared workspace-first access contract.
  • T018 [US1] Update apps/platform/app/Policies/ProviderConnectionPolicy.php, apps/platform/app/Policies/FindingPolicy.php, apps/platform/app/Policies/EvidenceSnapshotPolicy.php, apps/platform/app/Policies/ReviewPackPolicy.php, apps/platform/app/Policies/TenantReviewPolicy.php, apps/platform/app/Policies/TenantOnboardingSessionPolicy.php, and any directly touched searchable-resource visibility helpers or queries so workspace membership is the only role-bearing authority for environment-owned resources and inaccessible results stay hidden.

Checkpoint: Environment-owned pages and artifacts no longer require a second role-bearing managed-environment membership to authorize.


Phase 4: User Story 2 - Explicit environment scope narrows access without changing roles (Priority: P1)

Goal: Workspace role stays canonical while optional explicit scope rows narrow which managed environments a member may open.

Independent Test: Give a workspace member access to only one managed environment, confirm the allowed environment opens, confirm a sibling environment in the same workspace returns 404, and confirm the same workspace role capabilities apply inside the allowed environment.

Tests for User Story 2

  • T019 [P] [US2] Extend apps/platform/tests/Feature/Auth/WorkspaceFirstManagedEnvironmentAccessTest.php after T013-T014 to prove explicit environment-scope allowlists narrow visibility, stale remembered tenant context is cleared, and missing scope rows default to inheritance across currently selectable managed environments in the workspace.
  • T020 [P] [US2] Extend apps/platform/tests/Feature/Rbac/OperationRunWorkspaceFirstAuthorizationTest.php after T013-T014 to prove workspace-bound runs authorize from workspace membership only while environment-bound runs additionally honor explicit environment scope before capability checks.

Implementation for User Story 2

  • T021 [US2] Update apps/platform/app/Models/User.php, apps/platform/app/Support/Workspaces/WorkspaceContext.php, and any directly touched chooser or tenant-list helpers so explicit environment-scope rows narrow selection visibility and stale out-of-scope remembered environments are cleared.
  • T022 [US2] Update apps/platform/app/Support/Operations/OperationRunCapabilityResolver.php, apps/platform/app/Policies/OperationRunPolicy.php, and any directly touched run-link or monitoring helpers so workspace-bound and environment-bound runs follow the same workspace-first access contract.

Checkpoint: Environment scope acts only as visibility narrowing, and mixed workspace-bound versus environment-bound runs still authorize correctly.


Phase 5: User Story 3 - Membership management surfaces stop editing duplicate role truth (Priority: P2)

Goal: Operators manage workspace roles in one place and managed-environment visibility in another, with no second role selector on the environment surface.

Independent Test: Open workspace membership management and the retargeted managed-environment access-scope surface, confirm roles are edited only at workspace level, confirm environment scope CRUD never exposes a role selector, and confirm destructive actions remain confirmation-protected.

Tests for User Story 3

  • T023 [P] [US3] Extend apps/platform/tests/Feature/Filament/WorkspaceMembershipRoleManagementTest.php after T013-T014 to prove workspace membership remains the sole role editor, last-owner protection stays anchored at workspace scope, and audit logging remains intact.
  • T024 [P] [US3] Extend apps/platform/tests/Feature/Filament/ManagedEnvironmentAccessScopeManagementTest.php after T013-T014 to prove the retargeted managed-environment surface manages visibility scope only, never shows a second role selector, keeps destructive mutations behind ->requiresConfirmation(), and writes audit records for scope add, remove, and clear or narrowing actions.

Implementation for User Story 3

  • T025 [US3] Update apps/platform/app/Services/Auth/WorkspaceMembershipManager.php, apps/platform/app/Filament/Resources/Workspaces/RelationManagers/WorkspaceMembershipsRelationManager.php, and any directly touched workspace-role actions so workspace membership remains the only operator-facing role-editing path.
  • T026 [US3] Retarget apps/platform/app/Filament/Resources/TenantResource/Pages/ManageTenantMemberships.php, apps/platform/app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php, and any directly touched action or label helpers so the surface becomes managed-environment access-scope management with no second role authority.

Checkpoint: The operator-facing UI can no longer recreate dual role truth after the backend cutover.


Phase 6: Polish & Cross-Cutting Validation

Purpose: Run the exact bounded proof set, review the touched auth and Filament seams, and confirm the slice stayed inside Spec 285.

  • T027 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Unit/Auth/WorkspaceFirstCapabilityResolverTest.php tests/Unit/Auth/ManagedEnvironmentAccessScopeResolverTest.php).
  • T028 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Feature/Auth/WorkspaceFirstManagedEnvironmentAccessTest.php tests/Feature/Rbac/ProviderConnectionWorkspaceFirstPolicyTest.php tests/Feature/Rbac/OperationRunWorkspaceFirstAuthorizationTest.php tests/Feature/Rbac/GovernanceArtifactsWorkspaceFirstAuthorizationTest.php tests/Feature/Filament/WorkspaceMembershipRoleManagementTest.php tests/Feature/Filament/ManagedEnvironmentAccessScopeManagementTest.php).
  • T029 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Browser/Spec285WorkspaceRbacEnvironmentAccessSmokeTest.php).
  • T030 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail bin pint --dirty --format agent).
  • T031 [P] Review apps/platform/app/Models/User.php, apps/platform/app/Models/WorkspaceMembership.php, apps/platform/app/Models/ManagedEnvironmentMembership.php, apps/platform/app/Services/Auth/WorkspaceCapabilityResolver.php, apps/platform/app/Services/Auth/CapabilityResolver.php, apps/platform/app/Services/Auth/WorkspaceMembershipManager.php, apps/platform/app/Services/Auth/TenantMembershipManager.php, apps/platform/app/Support/Workspaces/WorkspaceContext.php, apps/platform/app/Policies/ProviderConnectionPolicy.php, apps/platform/app/Policies/OperationRunPolicy.php, apps/platform/app/Policies/FindingPolicy.php, apps/platform/app/Policies/EvidenceSnapshotPolicy.php, apps/platform/app/Policies/ReviewPackPolicy.php, apps/platform/app/Policies/TenantReviewPolicy.php, apps/platform/app/Policies/TenantOnboardingSessionPolicy.php, apps/platform/app/Filament/Resources/TenantResource/Pages/ManageTenantMemberships.php, apps/platform/app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php, apps/platform/app/Filament/Resources/Workspaces/RelationManagers/WorkspaceMembershipsRelationManager.php, apps/platform/app/Support/Operations/OperationRunCapabilityResolver.php, apps/platform/app/Filament/Resources/TenantResource.php, apps/platform/app/Filament/Resources/Workspaces/WorkspaceResource.php, apps/platform/app/Filament/Resources/ProviderConnectionResource.php, and apps/platform/bootstrap/providers.php to confirm Filament v5 / Livewire v4 compliance, unchanged provider-registration location, truthful non-global-search posture, preserved destructive-action confirmation plus authorization, boundary-safe denied-access diagnostics, unchanged asset strategy, and Specs 284, 286, and 287 staying deferred.

Dependencies & Execution Order

Phase Dependencies

  • Phase 0 (External Gate): no dependencies; complete before implementation starts.
  • Phase 1 (Setup): depends on Phase 0.
  • Phase 2 (Foundational): depends on Phase 1 and blocks all story work.
  • Phase 3 (US1): depends on Phase 2 and establishes workspace-first authorization for environment-owned resources.
  • Phase 4 (US2): depends on Phase 2 and should ship with or immediately after US1 so explicit environment narrowing lands on the final shared access contract.
  • Phase 5 (US3): depends on Phase 2 and should land after or with US1 and US2 so UI semantics match the backend contract.
  • Phase 6 (Polish): depends on all desired user stories being complete.

User Story Dependencies

  • US1 (P1): independently testable after Phase 2 and is the first required increment.
  • US2 (P1): independently testable after Phase 2, but should ship after or with US1 because explicit scope narrowing depends on the final shared workspace-first access contract.
  • US3 (P2): independently testable after Phase 2, but should land after or with US1 and US2 so the UI reflects the final backend semantics instead of an intermediate state.

Within Each User Story

  • Write or extend the listed Pest coverage first and make it fail for the intended gap.
  • Apply the smallest shared-seam changes needed to satisfy the story without reopening Specs 284, 286, or 287.
  • Re-run the narrowest relevant validation command for that story before moving to the next story.

Parallel Execution Examples

  • Setup: T002 through T006 can run in parallel once T000 and T001 fix the bounded scope.
  • Foundational: T007 through T012 can run in parallel before T013 and T014 converge the shared access contract.
  • US1: T015 and T016 can run in parallel; T017 and T018 should merge serially around shared user, context, and policy files.
  • US2: T019 and T020 can run in parallel; T021 and T022 should merge serially around shared tenant-access and run-authorization seams.
  • US3: T023 and T024 can run in parallel; T025 and T026 should merge serially around shared Filament membership surfaces.
  • Polish: T027 through T030 can run in parallel after implementation is complete; T031 should close the bounded-scope review last.

Implementation Strategy

Suggested MVP Scope

  • MVP = US1 + US2 + US3. The spec is not complete until the operator-facing role and scope surfaces are split in the same workspace-first model.

Incremental Delivery

  1. Complete Phase 0, Phase 1, and Phase 2.
  2. Deliver US1 so workspace membership alone authorizes environment-owned resources.
  3. Deliver US2 so optional explicit environment scope narrows visibility without changing role semantics.
  4. Deliver US3 so operators can no longer edit duplicate role truth in the UI.
  5. Finish with the exact validation commands and final bounded-scope review in Phase 6.

Team Strategy

  1. Parallelize the failing test work first.
  2. Serialize merges around apps/platform/app/Services/Auth/, apps/platform/app/Models/User.php, apps/platform/app/Support/Workspaces/WorkspaceContext.php, apps/platform/app/Policies/, and the touched Filament relation managers to avoid conflicting contract-shape edits.
  3. Reject any implementation branch that introduces a second role family, compatibility fallbacks, provider-boundary work, or adjacent-spec cutover work.

Deferred Follow-Ups / Non-Goals

  • Spec 284 provider-neutral artifact source taxonomy work
  • Spec 286 broader UI copy, IA, and localization neutralization
  • Spec 287 cutover quality gates and no-legacy enforcement beyond this bounded RBAC slice