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
57 lines
3.6 KiB
Markdown
57 lines
3.6 KiB
Markdown
# Research — Settings Foundation (Workspace + Optional Tenant Override) (097)
|
||
|
||
## Decisions
|
||
|
||
### Decision 1 — Canonical capability registry + role mapping
|
||
- **Chosen**: Add new workspace capabilities as constants in `App\Support\Auth\Capabilities`, and map them in `App\Services\Auth\WorkspaceRoleCapabilityMap`.
|
||
- `Capabilities::WORKSPACE_SETTINGS_VIEW`
|
||
- `Capabilities::WORKSPACE_SETTINGS_MANAGE`
|
||
- **Rationale**: The repo already enforces “no raw strings” and uses `Capabilities::isKnown()` checks in `WorkspaceCapabilityResolver`.
|
||
- **Alternatives considered**:
|
||
- Using raw strings (rejected: violates RBAC-UX-006).
|
||
|
||
### Decision 2 — Workspace RBAC-UX enforcement for Filament actions
|
||
- **Chosen**: Use `App\Support\Rbac\WorkspaceUiEnforcement` for Filament page actions.
|
||
- **Rationale**: This helper already implements the exact semantics required by the constitution:
|
||
- non-member → `abort(404)` (deny-as-not-found)
|
||
- member missing capability → `abort(403)`
|
||
- defense-in-depth server-side guard via `before()`.
|
||
- **Alternatives considered**:
|
||
- Ad-hoc `abort()` checks in each action (rejected: inconsistent and easier to regress).
|
||
|
||
### Decision 3 — Audit logging sink + stable action IDs
|
||
- **Chosen**:
|
||
- Workspace-scoped audit entries: `App\Services\Audit\WorkspaceAuditLogger` (writes `audit_logs` with `workspace_id`, `tenant_id = null`).
|
||
- Stable action identifiers: extend `App\Support\Audit\AuditActionId` enum with two new cases:
|
||
- `WorkspaceSettingUpdated = 'workspace_setting.updated'`
|
||
- `WorkspaceSettingReset = 'workspace_setting.reset'`
|
||
- **Rationale**: The repo already has a stable-action-id convention and tests around audit redaction and scoping; using the existing audit logger preserves sanitizer behavior (no secrets).
|
||
- **Alternatives considered**:
|
||
- Introducing a new audit sink (rejected: violates “use existing audit sinks” precedent and increases inconsistency risk).
|
||
- Using un-enumed string action IDs (possible, but rejected in favor of stronger standardization).
|
||
|
||
### Decision 4 — Storage model for workspace defaults + tenant overrides
|
||
- **Chosen**: Use two tables (scope-pure) rather than a single polymorphic table:
|
||
- `workspace_settings` (workspace-owned; includes `workspace_id`; no `tenant_id`)
|
||
- `tenant_settings` (tenant-owned; includes `workspace_id` and `tenant_id` NOT NULL)
|
||
- **Rationale**: Aligns with the constitution’s scope/ownership rule:
|
||
- “Workspace-owned tables MUST include workspace_id and MUST NOT include tenant_id.”
|
||
- “Tenant-owned tables MUST include workspace_id and tenant_id as NOT NULL.”
|
||
- **Alternatives considered**:
|
||
- Single `workspace_settings` table with nullable `tenant_id` (rejected: risks violating the constitution and blurs ownership).
|
||
|
||
### Decision 5 — Resolver precedence + caching
|
||
- **Chosen**:
|
||
- Precedence: tenant override → workspace override → system default.
|
||
- Caching: request-local only, implemented in-memory inside the resolver (no cross-request cache store in v1).
|
||
- **Rationale**: Matches the clarified spec requirements and mirrors existing request-local caching patterns (e.g., capability resolver).
|
||
- **Alternatives considered**:
|
||
- Cross-request cache with TTL (rejected for v1: adds invalidation complexity and isn’t required).
|
||
|
||
## Notes on existing repo patterns (evidence)
|
||
|
||
- Canonical capability registry exists: `App\Support\Auth\Capabilities`.
|
||
- Workspace capability checks and request-local caching exist: `App\Services\Auth\WorkspaceCapabilityResolver`.
|
||
- Workspace RBAC-UX enforcement helper exists: `App\Support\Rbac\WorkspaceUiEnforcement`.
|
||
- Workspace audit logger exists (with sanitizer): `App\Services\Audit\WorkspaceAuditLogger`.
|