Automated PR created via MCP by Copilot on user request: "pr gegen platform-dev". Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #332
319 lines
23 KiB
Markdown
319 lines
23 KiB
Markdown
# Implementation Plan: Enterprise Access Boundary & Support Access Governance v1
|
||
|
||
**Branch**: `276-support-access-governance` | **Date**: 2026-05-05 | **Spec**: [spec.md](./spec.md)
|
||
**Input**: Feature specification from `specs/276-support-access-governance/spec.md`
|
||
|
||
## Summary
|
||
|
||
Prepare one bounded support-access governance slice on top of the repo’s current system support and recovery seams. The narrow implementation path is to introduce one workspace-owned support-access grant history with exactly two scopes, reuse the current system workspace detail page as the request and active-state surface, reuse workspace settings as the owner-approval surface, extend existing system and admin audit views for support-access history, and harden the existing owner-repair utility so it requires both active break-glass and an active recovery-scoped support grant.
|
||
|
||
This slice stays explicitly narrow. Filament remains v5 on Livewire v4, panel-provider registration stays in `apps/platform/bootstrap/providers.php`, no new globally searchable resource is introduced, and no asset registration change is expected. The plan does not create impersonation, a delegated admin browsing bridge, SCIM, or a second support console.
|
||
|
||
## Inherited Baseline / Explicit Delta
|
||
|
||
### Inherited baseline
|
||
|
||
- `BreakGlassSession`, the system dashboard break-glass actions, and the current system break-glass banner already provide a global emergency recovery control with TTL and audit.
|
||
- `RepairWorkspaceOwners` already exposes the current owner-repair utility and audit behavior, but today it only requires platform capability plus active break-glass.
|
||
- `ViewWorkspace` already acts as the system-plane workspace detail surface and already owns bounded workspace-scoped admin actions.
|
||
- `WorkspaceSettings` already acts as the admin-plane workspace singleton page and already supports workspace-owner-only actions.
|
||
- `AuditLog` already acts as the admin-plane customer-visible history surface.
|
||
- `AccessLogs` already acts as the system security history surface for platform auth and break-glass events.
|
||
|
||
### Explicit delta in this plan
|
||
|
||
- Add one workspace-owned support-access grant history with bounded lifecycle and expiry.
|
||
- Add one support-scope catalog with exactly `audit_view` and `workspace_recovery`.
|
||
- Add one shared `SupportAccessGrantResolver` or manager so current detail, settings, recovery, and history surfaces consume the same support-access truth.
|
||
- Add a request and end flow on `ViewWorkspace`.
|
||
- Add owner approval or denial for `workspace_recovery` on `WorkspaceSettings`.
|
||
- Extend `AuditLog` with a support-access filter and export path.
|
||
- Extend `AccessLogs` with support-access lifecycle events.
|
||
- Refactor `RepairWorkspaceOwners` so owner repair requires both active break-glass and an active recovery-scoped support grant for the chosen workspace.
|
||
|
||
## Technical Context
|
||
|
||
**Language/Version**: PHP 8.4, Laravel 12
|
||
**Primary Dependencies**: Filament v5, Livewire v4, Pest v4, existing `BreakGlassSession`, existing audit infrastructure, existing workspace settings and system workspace detail surfaces
|
||
**Storage**: PostgreSQL via a new workspace-owned `support_access_grants` table plus existing `audit_logs` and current session-backed break-glass state
|
||
**Testing**: Pest v4 `Unit` plus focused `Feature` coverage
|
||
**Validation Lanes**: fast-feedback, confidence
|
||
**Target Platform**: Laravel monolith in `apps/platform`, reusing existing admin and system Filament pages
|
||
**Project Type**: Web application (Laravel monolith with Filament panels)
|
||
**Performance Goals**: no new queue family, no Graph calls, and DB-only support-access resolution on current detail, settings, and history surfaces
|
||
**Constraints**: no impersonation, no delegated admin browsing bridge, no SCIM, no new support console, no new global-search resource, and no asset registration changes
|
||
**Scale/Scope**: 1 new workspace-owned entity, 1 bounded resolver or manager, 4 existing page families, and focused extensions to existing auth or audit tests
|
||
|
||
## Likely Affected Repo Surfaces
|
||
|
||
- `apps/platform/app/Models/SupportAccessGrant.php` as the new workspace-owned grant model.
|
||
- `apps/platform/database/migrations/*_create_support_access_grants_table.php` for new persistence.
|
||
- `apps/platform/database/factories/SupportAccessGrantFactory.php` for bounded test setup.
|
||
- `apps/platform/app/Services/Auth/SupportAccessGrantResolver.php` and `SupportAccessGrantManager.php` as the shared lifecycle and mutation layer.
|
||
- `apps/platform/app/Filament/System/Pages/Directory/ViewWorkspace.php` for request, end, and active-state summary.
|
||
- `apps/platform/app/Filament/System/Pages/RepairWorkspaceOwners.php` for the combined support-access plus break-glass recovery boundary.
|
||
- `apps/platform/app/Filament/System/Pages/Security/AccessLogs.php` for system-side support-access history.
|
||
- `apps/platform/app/Filament/Pages/Settings/WorkspaceSettings.php` for owner approval or denial and a current support-access summary.
|
||
- `apps/platform/app/Filament/Pages/Monitoring/AuditLog.php` for the support-access filter and export path.
|
||
- `apps/platform/app/Support/Auth/PlatformCapabilities.php` for new bounded platform-side support-access manage capability.
|
||
- `apps/platform/app/Support/Audit/AuditActionId.php`, `WorkspaceAuditLogger`, and `SystemConsoleAuditLogger` for stable support-access audit action IDs and structured metadata.
|
||
- `apps/platform/tests/Unit/System/SupportAccessGrantResolverTest.php` plus focused system, auth, settings, monitoring, and access-log feature tests.
|
||
|
||
## Support Access Fit
|
||
|
||
- Treat support access as a workspace-owned governance truth, not as an extension of `BreakGlassSession`.
|
||
- Keep exactly two scopes in v1 so the slice stays on current repo-real support work:
|
||
- `audit_view`
|
||
- `workspace_recovery`
|
||
- Keep support-access lifecycle distinct from break-glass lifecycle.
|
||
- Keep owner repair as the one high-risk mutation that requires both active break-glass and active recovery-scoped support access.
|
||
- Keep admin history export on the current audit surface rather than adding a second support-history page.
|
||
|
||
## UI / Filament & Livewire Fit
|
||
|
||
- Existing operator-facing surfaces remain native Filament surfaces under Livewire v4.
|
||
- No new Filament resource or globally searchable resource is required; current pages are sufficient.
|
||
- `ViewWorkspace` keeps one dominant support-access action family: request or end support access.
|
||
- `WorkspaceSettings` keeps approval scoped to pending `workspace_recovery` requests and must not become a second platform-control plane.
|
||
- `AuditLog` and `AccessLogs` stay read-only history surfaces and only expand their filter or event scope.
|
||
- Provider registration remains unchanged in `apps/platform/bootstrap/providers.php`, and no new asset strategy is planned. If a later shared asset becomes necessary, deployment remains the standard `cd apps/platform && php artisan filament:assets` path.
|
||
|
||
## RBAC / Policy Fit
|
||
|
||
- Workspace and tenant membership remain the primary admin-plane isolation boundaries. Wrong-plane or non-member requests stay `404`; in-scope actors missing capability stay `403`.
|
||
- Platform-side request and end actions should use one new bounded `PlatformCapabilities::SUPPORT_ACCESS_MANAGE` capability instead of reusing broad console visibility alone.
|
||
- Workspace-owner approval should remain on `WorkspaceSettings` and should reuse existing owner-level manage semantics rather than adding a separate customer support role.
|
||
- `AuditLog` export remains tied to the current admin-plane audit view capability.
|
||
- Business-state blocking on the recovery page must remain distinguishable from authorization failure.
|
||
|
||
## Audit / Logging Fit
|
||
|
||
- Every support-access request, approval, denial, activation, expiry, end, and ownerless waiver must write a stable audit action ID with structured metadata.
|
||
- `AuditLog` remains the customer-visible history substrate.
|
||
- `AccessLogs` remains the system-side security history substrate and expands to include support-access events.
|
||
- No second audit subsystem is needed.
|
||
|
||
## Data & Query Fit
|
||
|
||
- `support_access_grants.workspace_id` must be NOT NULL and indexed.
|
||
- Prevent overlapping `requested` or `active` grants for the same workspace, platform actor, and scope.
|
||
- Keep the v1 table bounded to the fields in `data-model.md`; do not add broad ticketing, provider, or impersonation fields.
|
||
- `SupportAccessGrantResolver` should expose a single current summary for the active workspace plus current page context.
|
||
- `RepairWorkspaceOwners` should query only the targeted workspace’s active recovery grant, not scan across workspaces.
|
||
|
||
## UI / Surface Guardrail Plan
|
||
|
||
- **Guardrail scope**: changed surfaces
|
||
- **Native vs custom classification summary**: native Filament
|
||
- **Shared-family relevance**: system detail summaries, workspace settings approvals, audit-history filters, system security history, and recovery state messaging
|
||
- **State layers in scope**: page, detail
|
||
- **Audience modes in scope**: operator-MSP, support-platform
|
||
- **Decision/diagnostic/raw hierarchy plan**: decision-first, diagnostics-second, support-raw-third
|
||
- **Raw/support gating plan**: raw audit detail remains on existing history surfaces; default-visible content stays on current support posture and approval need
|
||
- **One-primary-action / duplicate-truth control**: `ViewWorkspace` remains the one place to start or end support access; `WorkspaceSettings` remains the one place to approve or deny risky recovery; history pages explain rather than re-decide
|
||
- **Handling modes by drift class or surface**: review-mandatory
|
||
- **Repository-signal treatment**: review-mandatory now; future hard-stop candidate if a second support console or impersonation bridge appears inside this slice
|
||
- **Special surface test profiles**: standard-native-filament, shared-detail-family, monitoring-state-page, exception-coded-surface
|
||
- **Required tests or manual smoke**: functional-core, state-contract, exception-fallback
|
||
- **Exception path and spread control**: the recovery page remains the named separately governed exception and must not spread its combined prerequisite logic to unrelated surfaces
|
||
- **Active feature PR close-out entry**: Guardrail
|
||
|
||
## Shared Pattern & System Fit
|
||
|
||
- **Cross-cutting feature marker**: yes
|
||
- **Systems touched**: `ViewWorkspace`, `WorkspaceSettings`, `AuditLog`, `AccessLogs`, `RepairWorkspaceOwners`, `BreakGlassSession`, audit action IDs, and current audit loggers
|
||
- **Shared abstractions reused**: current system detail pattern, current singleton settings pattern, current admin audit history, current system access logs, and current audit infrastructure
|
||
- **New abstraction introduced? why?**: one bounded `SupportAccessGrantResolver` or manager, because current repo truth has no support-access lifecycle abstraction and several surfaces need the same grant state and dedupe rules
|
||
- **Why the existing abstraction was sufficient or insufficient**: current break-glass and audit abstractions are sufficient for emergency recovery and history rendering, but insufficient for one workspace-scoped ordinary support-access lifecycle with approval and expiry
|
||
- **Bounded deviation / spread control**: no local page-specific support-access helper is allowed outside the shared resolver or manager path
|
||
|
||
## OperationRun UX Impact
|
||
|
||
- **Touches OperationRun start/completion/link UX?**: no
|
||
- **Central contract reused**: `N/A`
|
||
- **Delegated UX behaviors**: `N/A`
|
||
- **Surface-owned behavior kept local**: request or approval inputs only
|
||
- **Queued DB-notification policy**: `N/A`
|
||
- **Terminal notification path**: `N/A`
|
||
- **Exception path**: none
|
||
|
||
## Provider Boundary & Portability Fit
|
||
|
||
- **Shared provider/platform boundary touched?**: no
|
||
- **Provider-owned seams**: none in this slice
|
||
- **Platform-core seams**: support-access grant truth, approval flow, break-glass separation, and workspace-scoped history
|
||
- **Neutral platform terms / contracts preserved**: `support access`, `break-glass`, `workspace recovery`, `audit trail review`
|
||
- **Retained provider-specific semantics and why**: none
|
||
- **Bounded extraction or follow-up path**: future delegated support or impersonation only if promoted by a separate spec
|
||
|
||
## Constitution Check
|
||
|
||
*GATE: Must pass before implementation begins and again before merge.*
|
||
|
||
- Inventory-first / snapshot truth: PASS. This slice does not change tenant inventory or snapshot semantics.
|
||
- Read/write separation: PASS. Every mutation is bounded, confirmation-protected where high risk, and audit-backed.
|
||
- Graph contract path: PASS. No Graph or provider calls are introduced.
|
||
- Deterministic capabilities: PASS. Existing canonical capability registries remain authoritative.
|
||
- Workspace and tenant isolation: PASS. Workspace context and wrong-plane `404` remain unchanged.
|
||
- RBAC-UX plane separation: PASS. `/system` handles request or end; `/admin` handles approval or history.
|
||
- Destructive action discipline: PASS. High-risk approval and recovery remain confirmation-aware.
|
||
- Global search safety: PASS. No new searchable resource is added.
|
||
- OperationRun / Ops-UX: PASS. No new run family or `OperationRun` start surface is introduced.
|
||
- Data minimization: PASS. The new entity stores bounded support-access truth only.
|
||
- Test governance: PASS. Proof remains in one new unit family plus focused feature families.
|
||
- Proportionality / no premature abstraction: PASS. One new entity and one bounded resolver or manager are the narrowest viable path.
|
||
- Persisted truth: PASS. The new table represents independent product truth with its own lifecycle and audit need.
|
||
- Behavioral state: PASS. Grant status and approval mode change recovery behavior, expiry, and audit outcomes.
|
||
- Shared pattern first / UI semantics / Filament-native UI: PASS. Existing detail, settings, recovery, and history surfaces remain authoritative.
|
||
- Provider boundary: PASS. No provider-specific vocabulary or dependency is added.
|
||
- Filament / Laravel planning contract: PASS. Filament stays v5 on Livewire v4, provider registration remains in `apps/platform/bootstrap/providers.php`, no globally searchable resource is added, and no asset registration change is planned.
|
||
|
||
**Gate evaluation**: PASS.
|
||
|
||
**Post-design re-check**: PASS. `research.md`, `data-model.md`, `quickstart.md`, `contracts/workspace-support-access-governance.logical.openapi.yaml`, `checklists/requirements.md`, and `tasks.md` are present and aligned with the package.
|
||
|
||
## Test Governance Check
|
||
|
||
- **Test purpose / classification by changed surface**: `Unit` for grant lifecycle, expiry, and dedupe rules; `Feature` for system detail request flow, owner approval, recovery boundary, and history surfaces
|
||
- **Affected validation lanes**: fast-feedback, confidence
|
||
- **Why this lane mix is the narrowest sufficient proof**: the slice reuses native Filament and current audit surfaces, so focused unit and feature tests can prove the new truth without browser automation
|
||
- **Narrowest proving command(s)**:
|
||
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/System/SupportAccessGrantResolverTest.php`
|
||
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/SupportAccessRequestFlowTest.php tests/Feature/System/SupportAccessRecoveryBoundaryTest.php tests/Feature/Auth/BreakGlassModeTest.php tests/Feature/Auth/BreakGlassWorkspaceOwnerRecoveryTest.php tests/Feature/System/Spec114/AccessLogsTest.php`
|
||
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/Settings/WorkspaceSupportAccessApprovalTest.php tests/Feature/Monitoring/AuditLogSupportAccessHistoryTest.php`
|
||
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
|
||
- **Fixture / helper / factory / seed / context cost risks**: moderate but contained; one new factory is needed, but existing platform user, workspace, membership, and audit fixtures can be reused
|
||
- **Expensive defaults or shared helper growth introduced?**: no
|
||
- **Heavy-family additions, promotions, or visibility changes**: none planned
|
||
- **Surface-class relief / special coverage rule**: standard-native-filament relief for detail, settings, and history surfaces; exception-coded coverage for the recovery boundary
|
||
- **Closing validation and reviewer handoff**: reviewers should rely on the exact commands above, confirm that no impersonation bridge or second console appears, verify that recovery still needs active break-glass plus active recovery support access, and verify that support history export remains workspace-safe
|
||
- **Budget / baseline / trend follow-up**: none expected beyond a small feature-local increase
|
||
- **Review-stop questions**: did the slice add more than two support scopes, did it bypass break-glass on recovery, did it create a second history surface, and did it let admin history leak outside the workspace scope
|
||
- **Escalation path**: `document-in-feature` for contained naming drift; `reject-or-split` if the slice widens into impersonation, SCIM, or a second support console
|
||
- **Active feature PR close-out entry**: Guardrail
|
||
- **Why no dedicated follow-up spec is needed**: routine support-access upkeep should stay inside this feature unless future delegated support or impersonation is explicitly promoted as a separate slice
|
||
- **Test-governance outcome**: keep
|
||
|
||
## Review Checklist Status
|
||
|
||
- **Review checklist artifact**: `checklists/requirements.md`
|
||
- **Review outcome class**: `acceptable-special-case`
|
||
- **Workflow outcome**: `keep`
|
||
- **Test-governance outcome**: `keep`
|
||
- **Escalation rule**: if implementation adds admin-plane browsing, impersonation, SCIM, or a second support console, flip the workflow outcome to `split` before continuing
|
||
|
||
## Rollout Considerations
|
||
|
||
- Land persistence and shared resolver or manager first.
|
||
- Add workspace detail request or end flow next.
|
||
- Add workspace-owner approval next.
|
||
- Harden recovery enforcement only after support-access truth exists.
|
||
- Add history filter and export last so the customer-visible trail reflects the final lifecycle semantics.
|
||
- Keep Filament v5 on Livewire v4, provider registration in `apps/platform/bootstrap/providers.php`, global search unchanged, and assets unchanged.
|
||
|
||
## Risk Controls
|
||
|
||
- Reject any implementation that adds impersonation or delegated admin browsing.
|
||
- Reject any implementation that lets `workspace_recovery` proceed without active break-glass.
|
||
- Reject any implementation that adds more than the two scoped support capabilities in this slice.
|
||
- Reject any implementation that creates a second support history or approval surface outside the current detail, settings, and audit pages.
|
||
- Reject browser-heavy proof as the default validation lane.
|
||
|
||
## Research & Design Outputs
|
||
|
||
- `research.md` resolves the key design choices: workspace-scoped grants, two-scope catalog, recovery plus break-glass coupling, existing-surface reuse, and admin history export.
|
||
- `data-model.md` records the new grant entity, state and approval semantics, dedupe rule, and derived summary shape.
|
||
- `quickstart.md` provides the bounded reviewer flow, explicit approval and waiver expectations, and focused validation commands.
|
||
- `contracts/workspace-support-access-governance.logical.openapi.yaml` captures the logical route and action boundaries for request, approval, end, history, export, and recovery gating.
|
||
- `checklists/requirements.md` records the prep-time review outcome, workflow outcome, and test-governance outcome.
|
||
- `tasks.md` keeps implementation bounded to current support and recovery surfaces.
|
||
|
||
## Project Structure
|
||
|
||
### Documentation (this feature)
|
||
|
||
```text
|
||
specs/276-support-access-governance/
|
||
├── checklists/
|
||
│ └── requirements.md
|
||
├── contracts/
|
||
│ └── workspace-support-access-governance.logical.openapi.yaml
|
||
├── plan.md
|
||
├── research.md
|
||
├── data-model.md
|
||
├── quickstart.md
|
||
└── tasks.md
|
||
```
|
||
|
||
### Source Code (expected implementation surfaces)
|
||
|
||
```text
|
||
apps/platform/
|
||
├── app/
|
||
│ ├── Filament/
|
||
│ │ ├── Pages/
|
||
│ │ │ ├── Monitoring/
|
||
│ │ │ │ └── AuditLog.php
|
||
│ │ │ └── Settings/
|
||
│ │ │ └── WorkspaceSettings.php
|
||
│ │ └── System/Pages/
|
||
│ │ ├── Directory/
|
||
│ │ │ └── ViewWorkspace.php
|
||
│ │ ├── RepairWorkspaceOwners.php
|
||
│ │ └── Security/
|
||
│ │ └── AccessLogs.php
|
||
│ ├── Models/
|
||
│ │ └── SupportAccessGrant.php
|
||
│ ├── Services/
|
||
│ │ ├── Audit/
|
||
│ │ │ └── WorkspaceAuditLogger.php
|
||
│ │ ├── Auth/
|
||
│ │ │ ├── BreakGlassSession.php
|
||
│ │ │ ├── SupportAccessGrantManager.php
|
||
│ │ │ └── SupportAccessGrantResolver.php
|
||
│ │ └── SystemConsole/
|
||
│ │ └── SystemConsoleAuditLogger.php
|
||
│ └── Support/
|
||
│ ├── Audit/
|
||
│ │ └── AuditActionId.php
|
||
│ └── Auth/
|
||
│ └── PlatformCapabilities.php
|
||
├── database/
|
||
│ ├── factories/
|
||
│ │ └── SupportAccessGrantFactory.php
|
||
│ └── migrations/
|
||
│ └── *_create_support_access_grants_table.php
|
||
└── tests/
|
||
├── Feature/
|
||
│ ├── Auth/
|
||
│ │ ├── BreakGlassModeTest.php
|
||
│ │ └── BreakGlassWorkspaceOwnerRecoveryTest.php
|
||
│ ├── Filament/Settings/
|
||
│ │ └── WorkspaceSupportAccessApprovalTest.php
|
||
│ ├── Monitoring/
|
||
│ │ └── AuditLogSupportAccessHistoryTest.php
|
||
│ └── System/
|
||
│ ├── Spec114/AccessLogsTest.php
|
||
│ ├── SupportAccessRecoveryBoundaryTest.php
|
||
│ └── SupportAccessRequestFlowTest.php
|
||
└── Unit/
|
||
└── System/
|
||
└── SupportAccessGrantResolverTest.php
|
||
```
|
||
|
||
## Complexity Tracking
|
||
|
||
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
||
|-----------|------------|-------------------------------------|
|
||
| New persisted support-access entity | Support access now needs its own lifecycle, expiry, and approval lineage | Session-only or audit-log-only approaches could not gate recovery and customer-visible approval safely |
|
||
|
||
## Proportionality Review
|
||
|
||
- **Current operator problem**: current support and recovery seams lack one bounded workspace-scoped support lifecycle that is both customer-visible and strong enough to gate recovery
|
||
- **Existing structure is insufficient because**: `BreakGlassSession` is global and current pages can only infer support state indirectly through scattered audit events
|
||
- **Narrowest correct implementation**: one grant history table plus one shared resolver or manager, added to the current system detail, settings, history, and recovery pages only
|
||
- **Ownership cost**: one new entity, one new resolver or manager, one new factory, one migration, and focused tests
|
||
- **Alternative intentionally rejected**: break-glass-only governance and broad impersonation bridge
|
||
- **Release truth**: current-release truth with bounded future preparation only
|
||
|