# Tasks: Spec 339 - Provider Connection Scope Hardening - Input: `specs/339-provider-connection-scope-hardening/spec.md`, `specs/339-provider-connection-scope-hardening/plan.md` - Preparation status: implementation-ready. **Tests**: Required. This spec hardens credential-adjacent scope/authorization semantics. ## Test Governance Checklist - [x] Lane assignment is explicit and narrowest sufficient (Feature). - [x] No new default-heavy helpers/factories/seeds are introduced. - [x] Scope/authority changes are guarded by deterministic tests before refactors. - [x] Any exception resolves as `document-in-feature`, `follow-up-spec`, or `reject-or-split`. ## Phase 1: Preparation And Repo Truth (blocks runtime changes) **Purpose**: Confirm repo truth and identify the exact forbidden fallback seams before changing behavior. - [x] T001 Re-read `spec.md` + `plan.md` + this `tasks.md`. - [x] T002 Confirm working tree intent and record baseline commit (`git status`, `git log -1`). - [x] T003 Inspect the confirmed authority seams: - `apps/platform/app/Policies/ProviderConnectionPolicy.php`: - `currentWorkspace()` (forbidden fallback via `Filament::getTenant()`). - `resolveCreateTenant()` (forbidden fallbacks via remembered environment + Filament tenant). - record-derived checks for workspace/environment ownership (ensure these remain the canonical authority for view/edit/actions). - `apps/platform/app/Filament/Resources/ProviderConnectionResource.php`: - `applyMembershipScope()` (must not infer workspace via tenant context). - `resolveRequestedEnvironment()` / `WorkspaceHubEnvironmentFilter` use (explicit `environment_id` only). - `apps/platform/app/Support/Workspaces/WorkspaceContext.php`: - `lastEnvironmentId()` and remembered-environment helpers (navigation-only; must not grant create authority). - [x] T004 Inventory existing ProviderConnections tests and identify the best location for new regression tests: - `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionListAuthorizationTest.php` - `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionsWorkspaceHubContractTest.php` - `apps/platform/tests/Feature/ProviderConnections/AuthorizationSemanticsTest.php` - `apps/platform/tests/Feature/ProviderConnections/RequiredFiltersTest.php` ## Phase 2: Add failing contract tests first **Purpose**: Make authority changes reviewable and regression-proof. - [x] T005 Add a new Spec 339 test proving create requires explicit `environment_id`: - Create is denied when `/admin/provider-connections/create` is requested without `environment_id`, - even if a remembered environment exists in session (`WorkspaceContext::lastEnvironmentId`). - Implemented via: `apps/platform/tests/Feature/ProviderConnections/ScopeHardeningAuthoritySourcesTest.php` - [x] T006 Add a test proving workspace authority does not fall back to Filament tenant: - When workspace context is missing, Provider Connection access is deny-as-not-found (404), - even if `Filament::getTenant()` is set. - Implemented via: - `apps/platform/tests/Feature/ProviderConnections/ScopeHardeningPolicyWorkspaceAuthorityTest.php` - `apps/platform/tests/Feature/ProviderConnections/ScopeHardeningResourceWorkspaceAuthorityTest.php` - [x] T007 Add a test proving legacy query aliases do not grant authority: - `?managed_environment_id=...`, `?tenant=...`, `?tenant_id=...` must not widen list scope or unlock create. - Implemented via: `apps/platform/tests/Feature/ProviderConnections/ScopeHardeningAuthoritySourcesTest.php` - [x] T008 Add a test proving wrong-workspace environment IDs deny as 404: - `environment_id` from another workspace must not authorize create or list filtering. ## Phase 3: Policy authority hardening (Spec 339 contract) **Purpose**: Remove forbidden authority fallbacks and enforce the 404/403 semantics contract. - [x] T009 Update `apps/platform/app/Policies/ProviderConnectionPolicy.php::currentWorkspace()`: - remove `Filament::getTenant()` as an authority source for workspace selection, - keep workspace membership validation, - keep deny-as-not-found (404) behavior when workspace context is missing. - [x] T010 Update `apps/platform/app/Policies/ProviderConnectionPolicy.php::resolveCreateTenant()`: - require explicit `environment_id`, - remove remembered-environment fallback and Filament-tenant fallback, - ensure wrong-workspace `environment_id` denies as 404. - [x] T011 Confirm 404 vs 403 semantics for all policy methods: - non-member / out-of-scope record → 404, - member missing capability → 403. ## Phase 4: Resource scoping hardening (no hidden context authority) **Purpose**: Ensure list/query and record surfaces do not infer authority from hidden context. - [x] T012 Update `apps/platform/app/Filament/Resources/ProviderConnectionResource.php::applyMembershipScope()`: - remove fallback that infers workspace ID from tenant context when session workspace is missing, - keep query empty (no results) when workspace context is missing. - [x] T013 Confirm Provider Connections list filtering uses explicit `environment_id` only: - validate `environment_id` against current workspace and access scope, - ignore legacy query aliases as authority. - [x] T014 Confirm record pages and action dispatchers use record-derived tenant/workspace authority, not remembered environment or Filament tenant. ## Phase 5: Credential-adjacent actions audit **Purpose**: Ensure high-risk actions remain safe and record-scoped. - [x] T015 Audit all actions on `ProviderConnectionResource` (edit + dedicated credential actions + provider operations): - confirm policy methods are used consistently, - confirm destructive-like actions retain `->requiresConfirmation()`, - confirm record ownership controls scope for all actions. - [x] T016 Confirm audit posture remains intact for credential-adjacent mutations: - no new audit event families are introduced in this slice, - existing audit logging remains correct and record-scoped. ## Phase 6: Optional UX clarification (only if needed) - [x] T017 If create is denied without `environment_id`, ensure the list empty state or guidance makes the required next step obvious (filter/select an environment first) without introducing a new picker or redesign. (No changes needed.) ## Phase 7: Validation - [x] T018 Run narrow tests first: - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections --filter=ScopeHardening` - [x] T019 Run formatting and patch checks: - `cd apps/platform && ./vendor/bin/sail pint --dirty --format agent` - `git diff --check` ## Explicit Non-Goals - [x] NT001 Do not add migrations, new tables, or new persisted truth. - [x] NT002 Do not redesign Provider Connections UX or navigation placement. - [x] NT003 Do not introduce a new scope/authority abstraction framework. - [x] NT004 Do not reopen provider-neutral target-scope/identity refactors (Spec 281 family).