Implements the Settings foundation workspace controls. Includes: - Settings foundation UI/controls scoped to workspace context - Related onboarding/consent flow adjustments as included in branch history Testing: - `vendor/bin/sail artisan test --compact --no-ansi --filter=SettingsFoundation` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #119
144 lines
8.1 KiB
Markdown
144 lines
8.1 KiB
Markdown
# Implementation Plan: Settings Foundation (Workspace + Optional Tenant Override)
|
||
|
||
**Branch**: `097-settings-foundation` | **Date**: 2026-02-15 | **Spec**: `/specs/097-settings-foundation/spec.md`
|
||
**Input**: Feature specification from `/specs/097-settings-foundation/spec.md`
|
||
|
||
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts.
|
||
|
||
## Summary
|
||
|
||
Implement a workspace-scoped settings substrate with a canonical registry + validation, a resolver that applies precedence (tenant override → workspace override → system default), a workspace Settings page in Filament, and audit logging for each successful mutation.
|
||
|
||
For v1, the pilot setting is `backup.retention_keep_last_default` (system default `30`), stored as a workspace override and later consumed by backup retention behavior when a schedule has no explicit `retention_keep_last`.
|
||
|
||
## Technical Context
|
||
|
||
**Language/Version**: PHP 8.4 (Laravel 12)
|
||
**Primary Dependencies**: Filament v5, Livewire v4, Laravel Sail
|
||
**Storage**: PostgreSQL (Sail local)
|
||
**Testing**: Pest v4 (PHPUnit 12)
|
||
**Target Platform**: Web app (Filament admin panel)
|
||
**Project Type**: Laravel monolith (Filament pages + services + jobs)
|
||
**Performance Goals**: settings resolution is request-local cached; repeated resolves for the same (workspace, optional tenant, domain, key) do not issue repeated DB reads
|
||
**Constraints**: strict workspace isolation (non-member 404), capability-gated mutations (member without capability 403), audit each successful mutation, no secrets in audit metadata
|
||
**Scale/Scope**: low-volume admin configuration with high auditability and correctness requirements
|
||
|
||
## Constitution Check
|
||
|
||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||
|
||
- Inventory-first: clarify what is “last observed” vs snapshots/backups
|
||
- Read/write separation: any writes require preview + confirmation + audit + tests
|
||
- Graph contract path: Graph calls only via `GraphClientInterface` + `config/graph_contracts.php`
|
||
- Deterministic capabilities: capability derivation is testable (snapshot/golden tests)
|
||
- RBAC-UX: two planes (/admin vs /system) remain separated; cross-plane is 404; tenant-context routes (/admin/t/{tenant}/...) are tenant-scoped; canonical workspace-context routes under /admin remain tenant-safe; non-member tenant/workspace access is 404; member-but-missing-capability is 403; authorization checks use Gates/Policies + capability registries (no raw strings, no role-string checks)
|
||
- Workspace isolation: non-member workspace access is 404; tenant-plane routes require an established workspace context; workspace context switching is separate from Filament Tenancy
|
||
- RBAC-UX: destructive-like actions require `->requiresConfirmation()` and clear warning text
|
||
- RBAC-UX: global search is tenant-scoped; non-members get no hints; inaccessible results are treated as not found (404 semantics)
|
||
- Tenant isolation: all reads/writes tenant-scoped; cross-tenant views are explicit and access-checked
|
||
- Run observability: long-running/remote/queued work creates/reuses `OperationRun`; start surfaces enqueue-only; Monitoring is DB-only; DB-only <2s actions may skip runs but security-relevant ones still audit-log; auth handshake exception OPS-EX-AUTH-001 allows synchronous outbound HTTP on `/auth/*` without `OperationRun`
|
||
- Automation: queued/scheduled ops use locks + idempotency; handle 429/503 with backoff+jitter
|
||
- Data minimization: Inventory stores metadata + whitelisted meta; logs contain no secrets/tokens
|
||
- Badge semantics (BADGE-001): status-like badges use `BadgeCatalog` / `BadgeRenderer`; no ad-hoc mappings; new values include tests
|
||
- Filament UI Action Surface Contract: for any new/modified Filament Resource/RelationManager/Page, define Header/Row/Bulk/Empty-State actions, ensure every List/Table has a record inspection affordance (prefer `recordUrl()` clickable rows; do not render a lone View row action), keep max 2 visible row actions with the rest in “More”, group bulk actions, require confirmations for destructive actions (typed confirmation for large/bulk where applicable), write audit logs for mutations, enforce RBAC via central helpers (non-member 404, member missing capability 403), and ensure CI blocks merges if the contract is violated or not explicitly exempted
|
||
|
||
**Result (pre-Phase 0)**: PASS.
|
||
|
||
- This feature is DB-only and completes in <2s; it intentionally does not create an `OperationRun`, but MUST emit workspace-scoped audit entries on each successful mutation.
|
||
- No Graph calls are introduced.
|
||
- RBAC enforcement must use the canonical capability registry (`App\Support\Auth\Capabilities`) and workspace UI enforcement helper (`App\Support\Rbac\WorkspaceUiEnforcement`) for Filament surfaces.
|
||
|
||
## Project Structure
|
||
|
||
### Documentation (this feature)
|
||
|
||
```text
|
||
specs/097-settings-foundation/
|
||
├── plan.md # This file (/speckit.plan command output)
|
||
├── research.md # Phase 0 output (/speckit.plan command)
|
||
├── data-model.md # Phase 1 output (/speckit.plan command)
|
||
├── quickstart.md # Phase 1 output (/speckit.plan command)
|
||
├── contracts/ # Phase 1 output (/speckit.plan command)
|
||
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
|
||
```
|
||
|
||
### Source Code (repository root)
|
||
|
||
```text
|
||
app/
|
||
├── Filament/
|
||
│ └── Pages/
|
||
│ └── Settings/
|
||
├── Models/
|
||
├── Policies/
|
||
├── Providers/
|
||
├── Services/
|
||
└── Support/
|
||
├── Audit/
|
||
├── Auth/
|
||
├── Rbac/
|
||
└── Settings/
|
||
|
||
config/
|
||
database/migrations/
|
||
tests/
|
||
```
|
||
|
||
Expected additions (at implementation time):
|
||
|
||
```text
|
||
app/Support/Settings/SettingDefinition.php
|
||
app/Support/Settings/SettingsRegistry.php
|
||
app/Services/Settings/SettingsResolver.php
|
||
app/Services/Settings/SettingsWriter.php
|
||
app/Models/WorkspaceSetting.php
|
||
app/Models/TenantSetting.php
|
||
app/Filament/Pages/Settings/WorkspaceSettings.php
|
||
app/Policies/WorkspaceSettingPolicy.php
|
||
database/migrations/*_create_workspace_settings_table.php
|
||
database/migrations/*_create_tenant_settings_table.php
|
||
tests/Feature/SettingsFoundation/*
|
||
tests/Unit/SettingsFoundation/*
|
||
```
|
||
|
||
**Structure Decision**: Laravel monolith (Filament admin + Eloquent models + services + Pest tests). No new top-level directories.
|
||
|
||
## Phase 0 — Outline & Research
|
||
|
||
Deliverable: `research.md` with all implementation decisions resolved.
|
||
|
||
Key questions resolved in research:
|
||
|
||
- Which existing RBAC enforcement helper to use for workspace-scoped Filament pages.
|
||
- Which audit logger to use for workspace-scoped audit events and how to represent stable action IDs.
|
||
- How to model workspace defaults + tenant overrides while staying compliant with the constitution’s scope/ownership rules.
|
||
|
||
## Phase 1 — Design & Contracts
|
||
|
||
Deliverables: `data-model.md`, `contracts/*`, `quickstart.md`.
|
||
|
||
- Data model defines workspace settings and tenant overrides with strict workspace isolation.
|
||
- Contracts define the conceptual read/write/reset operations (even if the first implementation is driven via Filament/Livewire).
|
||
- Quickstart defines how to run migrations, format, and execute focused tests.
|
||
|
||
## Phase 2 — Planning
|
||
|
||
Implementation sequence (high-level):
|
||
|
||
1. Add capability constants in `App\Support\Auth\Capabilities` and map them in `App\Services\Auth\WorkspaceRoleCapabilityMap`.
|
||
2. Add settings registry + validation (`SettingDefinition`, `SettingsRegistry`) including the pilot setting.
|
||
3. Add storage + resolver + writer services with request-local caching.
|
||
4. Add audit action IDs (stable) and emit workspace audit entries for update/reset.
|
||
5. Add Filament workspace Settings page with Save + Reset actions, gated using `WorkspaceUiEnforcement`.
|
||
6. Add Pest tests for precedence, RBAC (404/403), validation, caching behavior, and audit entries.
|
||
|
||
**Constitution re-check (post-design)**: expected PASS (DB-only mutations audited; strict 404/403 semantics; capability registry is canonical).
|
||
|
||
## Complexity Tracking
|
||
|
||
> **Fill ONLY if Constitution Check has violations that must be justified**
|
||
|
||
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
||
|-----------|------------|-------------------------------------|
|
||
| None | N/A | N/A |
|