TenantAtlas/specs/097-settings-foundation/tasks.md

130 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Tasks: Settings Foundation (Workspace + Optional Tenant Override) (097)
**Input**: Design documents from `specs/097-settings-foundation/` (spec.md, plan.md, research.md, data-model.md, contracts/)
**Prerequisites**: specs/097-settings-foundation/plan.md (required), specs/097-settings-foundation/spec.md (required for user stories)
**Tests**: REQUIRED (Pest) for all runtime behavior changes in this repo.
**RBAC**: Enforce 404 vs 403 semantics via canonical helpers + capability registry (no raw strings).
**Audit**: DB-only mutations intentionally skip OperationRun; every successful update/reset MUST write a workspace-scoped audit entry.
## Phase 1: Setup (Shared Infrastructure)
- [X] T001 Re-run SpecKit prerequisites and confirm FEATURE_DIR via .specify/scripts/bash/check-prerequisites.sh
- [X] T002 Review RBAC-UX enforcement patterns in app/Support/Rbac/WorkspaceUiEnforcement.php
- [X] T003 Review existing capability registry + caching patterns in app/Support/Auth/Capabilities.php and app/Services/Auth/WorkspaceCapabilityResolver.php
- [X] T004 Review workspace audit patterns + stable action IDs in app/Services/Audit/WorkspaceAuditLogger.php and app/Support/Audit/AuditActionId.php
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Shared primitives (capabilities, persistence, policies) needed by all stories.
- [X] T005 Add settings capabilities in app/Support/Auth/Capabilities.php (WORKSPACE_SETTINGS_VIEW, WORKSPACE_SETTINGS_MANAGE)
- [X] T006 Map new capabilities to roles in app/Services/Auth/WorkspaceRoleCapabilityMap.php (Owner/Manager manage; Operator/Readonly view)
- [X] T007 Create workspace_settings table migration in database/migrations/*_create_workspace_settings_table.php (workspace-owned: MUST NOT include tenant_id)
- [X] T008 [P] Create tenant_settings table migration in database/migrations/*_create_tenant_settings_table.php (tenant-owned: MUST include tenant_id NOT NULL)
- [X] T009 [P] Add Eloquent models in app/Models/WorkspaceSetting.php and app/Models/TenantSetting.php
- [X] T010 [P] Add model factories in database/factories/WorkspaceSettingFactory.php and database/factories/TenantSettingFactory.php
- [X] T011 Add policy for settings writes in app/Policies/WorkspaceSettingPolicy.php (view/manage using WorkspaceCapabilityResolver)
- [X] T012 Register policy mapping in app/Providers/AuthServiceProvider.php
**Checkpoint**: Capabilities + persistence + policies exist; user story work can begin.
---
## Phase 3: User Story 1 — Manage workspace settings safely (Priority: P1) 🎯 MVP
**Goal**: Workspace managers can update/reset the pilot setting with validation + audit logging.
**Independent Test**: A manager changes backup.retention_keep_last_default, sees it reflected, and the retention fallback uses it when schedule retention is null.
### Tests (write first)
- [X] T013 [P] [US1] Add manage workflow tests in tests/Feature/SettingsFoundation/WorkspaceSettingsManageTest.php
- [X] T014 [P] [US1] Add audit logging tests in tests/Feature/SettingsFoundation/WorkspaceSettingsAuditTest.php
- [X] T015 [P] [US1] Add resolver caching tests in tests/Unit/SettingsFoundation/SettingsResolverCacheTest.php
- [X] T016 [P] [US1] Add pilot integration test for retention fallback in tests/Feature/SettingsFoundation/RetentionFallbackUsesWorkspaceDefaultTest.php
- [X] T038 [P] [US1] Add per-schedule override precedence test (schedule override wins) in tests/Feature/SettingsFoundation/RetentionScheduleOverrideWinsTest.php
- [X] T039 [P] [US1] Add validation negative-path test: unknown setting key is rejected; no changes persisted; no audit entry created
- [X] T040 [P] [US1] Add validation negative-path test: invalid value (wrong type/out-of-range) is rejected; no changes persisted; no audit entry created
### Implementation
- [X] T017 [P] [US1] Create setting definition DTO in app/Support/Settings/SettingDefinition.php
- [X] T018 [P] [US1] Create registry for known settings in app/Support/Settings/SettingsRegistry.php (include backup.retention_keep_last_default default=30 + validation)
- [X] T019 [P] [US1] Implement resolver with precedence + request-local cache in app/Services/Settings/SettingsResolver.php
- [X] T020 [P] [US1] Add stable audit action IDs in app/Support/Audit/AuditActionId.php (workspace_setting.updated, workspace_setting.reset)
- [X] T021 [US1] Implement writer (validate, persist, reset deletes row, audit before/after) in app/Services/Settings/SettingsWriter.php
- [X] T022 [US1] Add Filament workspace Settings page shell in app/Filament/Pages/Settings/WorkspaceSettings.php (uses WorkspaceUiEnforcement)
- [X] T023 [US1] Register the Settings page in the admin panel navigation in app/Providers/Filament/AdminPanelProvider.php
- [X] T024 [US1] Implement Save action via Action::make(...)->action(...) in app/Filament/Pages/Settings/WorkspaceSettings.php
- [X] T025 [US1] Implement Reset action with ->requiresConfirmation() and ->action(...) in app/Filament/Pages/Settings/WorkspaceSettings.php
- [X] T026 [US1] Wire retention fallback to resolver when schedule retention is null in app/Jobs/ApplyBackupScheduleRetentionJob.php
---
## Phase 4: User Story 2 — View settings without the ability to change them (Priority: P2)
**Goal**: Workspace operators/readonly can view settings but cannot save/reset; server-side 403 on mutation.
**Independent Test**: A view-only member opens the Settings page and can see values, but attempts to save/reset return 403 and no audit entry is created.
### Tests (write first)
- [X] T027 [P] [US2] Add view-only access tests (view OK, mutation forbidden) in tests/Feature/SettingsFoundation/WorkspaceSettingsViewOnlyTest.php
- [X] T037 [P] [US2] Add non-member deny-as-not-found tests (404) in tests/Feature/SettingsFoundation/WorkspaceSettingsNonMemberNotFoundTest.php
### Implementation
- [X] T028 [US2] Gate page access by view capability and gate mutations by manage capability in app/Filament/Pages/Settings/WorkspaceSettings.php
- [X] T029 [US2] Ensure Save/Reset actions cannot execute for view-only users (server-side enforcement) in app/Filament/Pages/Settings/WorkspaceSettings.php
---
## Phase 5: User Story 3 — Tenant overrides take precedence (backend-ready) (Priority: P3)
**Goal**: Resolver supports tenant overrides; tenant override wins over workspace override; rejects tenant/workspace mismatch.
**Independent Test**: With tenant override present, resolving returns tenant value; without it, returns workspace; without either, returns system default.
### Tests (write first)
- [X] T030 [P] [US3] Add tenant precedence tests (default/workspace/tenant) in tests/Unit/SettingsFoundation/SettingsResolverTenantPrecedenceTest.php
- [X] T031 [P] [US3] Add tenant/workspace mismatch rejection test in tests/Feature/SettingsFoundation/TenantOverrideScopeSafetyTest.php
### Implementation
- [X] T032 [US3] Extend resolver to read tenant overrides from tenant_settings (same workspace) in app/Services/Settings/SettingsResolver.php
- [X] T033 [US3] Add tenant override write/reset methods (backend-ready) in app/Services/Settings/SettingsWriter.php
---
## Phase 6: Polish & Cross-Cutting Concerns
- [X] T034 [P] Run formatting for changed files via vendor/bin/sail bin pint --dirty (see specs/097-settings-foundation/quickstart.md)
- [X] T035 Run focused tests for this feature via vendor/bin/sail artisan test --compact tests/Feature/SettingsFoundation (see specs/097-settings-foundation/quickstart.md)
- [X] T036 Run the full suite via vendor/bin/sail artisan test --compact (see specs/097-settings-foundation/quickstart.md)
---
## Dependencies & Execution Order
### User Story Dependency Graph
- Setup → Foundational
- Foundational → US1
- US1 → US2
- US1 → US3
### Parallel Opportunities (examples)
- US1: T013T016 (tests) and T017T020 (core classes + enum) can be executed in parallel.
- Foundational: T007T012 can be split across DB/model/policy work in parallel.
Example: In US1, execute T013, T014, T017, and T018 concurrently (different files; no dependencies).
## MVP Scope Suggestion
- MVP = Phases 13 (through US1) to ship a workspace settings foundation with the pilot setting wired into retention fallback.