282 lines
20 KiB
Markdown
282 lines
20 KiB
Markdown
# Implementation Plan: Spec 415 - Generic Content-Backed Capture
|
|
|
|
**Branch**: `415-generic-content-backed-capture` | **Date**: 2026-06-25 | **Spec**: `specs/415-generic-content-backed-capture/spec.md`
|
|
**Input**: Feature specification from `/specs/415-generic-content-backed-capture/spec.md`
|
|
|
|
## Summary
|
|
|
|
Prepare Coverage v2 to store real content-backed evidence without activating it as customer/operator truth. The implementation should add concrete Coverage v2 resource and evidence persistence, resolve source contracts through the existing registry/Graph contract path, capture eligible payloads through `GraphClientInterface`, normalize/hash/redact payloads, and run remote capture through an authorized, queued, OperationRun-backed service.
|
|
|
|
The slice is intentionally backend/internal. No Filament page, route, navigation entry, customer output, review/report surface, restore readiness surface, or browser-visible v2 coverage claim is added.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4.15, Laravel 12.52.0
|
|
**Primary Dependencies**: Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, Sail 1.52.0
|
|
**Storage**: PostgreSQL; JSONB for raw payload, normalized payload, permission/source metadata
|
|
**Testing**: Pest 4; unit, feature, and PostgreSQL lanes where database constraints/indexes require PostgreSQL proof
|
|
**Validation Lanes**: fast-feedback, confidence, pgsql; browser N/A unless UI scope is amended
|
|
**Target Platform**: Laravel monolith in `apps/platform`, Sail local, Dokploy container staging/production
|
|
**Project Type**: web application backend/runtime slice
|
|
**Performance Goals**: render-time remains DB-only/no Graph; remote capture queued; indexes limited to known query paths
|
|
**Constraints**: no UI activation, no direct Graph calls, no endpoint guessing, no `tenant_id`, no compatibility shim, no raw payload leakage, OperationRun lifecycle service-owned
|
|
**Scale/Scope**: initial Spec 414 resource types only; no full TCM catalog, compare/render/restore, or legacy removal
|
|
|
|
## Existing Repo Truth
|
|
|
|
- Spec 414 completed the inactive Coverage v2 kernel and contains implementation close-out evidence.
|
|
- Existing Coverage v2 kernel files include:
|
|
- `apps/platform/app/Models/TenantConfigurationResourceType.php`
|
|
- `apps/platform/app/Models/TenantConfigurationSupportedScope.php`
|
|
- `apps/platform/app/Services/TenantConfiguration/ResourceTypeRegistry.php`
|
|
- `apps/platform/app/Services/TenantConfiguration/SupportedScopeResolver.php`
|
|
- `apps/platform/app/Services/TenantConfiguration/ClaimGuard.php`
|
|
- `apps/platform/app/Support/TenantConfiguration/*`
|
|
- `apps/platform/database/migrations/2026_06_25_000414_create_tenant_configuration_kernel_tables.php`
|
|
- Spec 414 deferred `tenant_configuration_resources` and `tenant_configuration_resource_evidence`.
|
|
- `OperationRunType` does not yet contain `tenant_configuration.capture`.
|
|
- `OperationSummaryKeys::all()` does not currently contain `captured` or `blocked`; Spec 415 should use existing numeric keys unless it explicitly extends the canonical list with tests.
|
|
- `config/graph_contracts.php` contains contract entries relevant to `notificationMessageTemplate`, `roleScopeTag`, and `assignmentFilter`. TCM-aligned source eligibility must still be explicit; missing contracts must block capture.
|
|
- `Capabilities::EVIDENCE_MANAGE` exists and is granted to Manager/Owner but not Operator/Readonly. It is the default planned capability unless implementation finds a more specific existing capture capability.
|
|
|
|
## UI / Surface Guardrail Plan
|
|
|
|
- **Guardrail scope**: no operator-facing surface change.
|
|
- **Affected routes/pages/actions/states/navigation/panel/provider surfaces**: N/A.
|
|
- **No-impact class, if applicable**: backend-only internal evidence capture. Existing generic Monitoring -> Operations and central DB-notification surfaces may show OperationRun records through the shared lifecycle contract; no feature-local UI, notification copy, links, or rendered controls are added.
|
|
- **Native vs custom classification summary**: N/A.
|
|
- **Shared-family relevance**: OperationRun lifecycle and Graph service boundary only.
|
|
- **State layers in scope**: none.
|
|
- **Audience modes in scope**: N/A.
|
|
- **Decision/diagnostic/raw hierarchy plan**: raw payloads remain evidence-storage only; no default UI exposure.
|
|
- **Raw/support gating plan**: no rendered access path in this spec.
|
|
- **One-primary-action / duplicate-truth control**: no UI action introduced; no v2 customer/operator truth.
|
|
- **Handling modes by drift class or surface**: hard-stop if UI files/routes/navigation/customer output are touched without spec/plan/tasks amendment.
|
|
- **Repository-signal treatment**: review-mandatory for any UI file change, route addition, new Filament resource, or customer/report/review/evidence activation.
|
|
- **Special surface test profiles**: N/A.
|
|
- **Required tests or manual smoke**: functional-core, persistence, RBAC, OperationRun, no-UI static guards.
|
|
- **Exception path and spread control**: none.
|
|
- **Active feature PR close-out entry**: Guardrail / N/A no rendered UI surface changed.
|
|
- **UI/Productization coverage decision**: No UI surface impact.
|
|
- **Coverage artifacts to update**: none.
|
|
- **No-impact rationale**: backend-only internal capture path; no reachable UI surface changed.
|
|
- **Navigation / Filament provider-panel handling**: no panel/provider change.
|
|
- **Screenshot or page-report need**: no.
|
|
|
|
## Product Surface Contract Plan
|
|
|
|
- **Product Surface Contract reference**: `docs/product/standards/product-surface-contract.md`.
|
|
- **No-legacy posture**: canonical v2 evidence path; no compatibility exception.
|
|
- **Page archetype and surface budget plan**: N/A - no rendered product surface changed.
|
|
- **Technical Annex and deep-link demotion plan**: no default product view exposes OperationRun, raw evidence IDs, source keys, payloads, fingerprints, or logs.
|
|
- **Canonical status vocabulary plan**: N/A - no product-facing status labels.
|
|
- **Product Surface exceptions**: none.
|
|
- **Browser verification plan**: `N/A - no rendered UI surface changed`; existing generic OperationRun surfaces are not customized by this spec.
|
|
- **Human Product Sanity plan**: N/A - no rendered product surface changed.
|
|
- **Visible complexity outcome target**: neutral for rendered UI.
|
|
- **Implementation report target**: `specs/415-generic-content-backed-capture/implementation-report.md`.
|
|
|
|
## Filament / Livewire / Deployment Posture
|
|
|
|
- **Livewire v4 compliance**: Livewire v4.1.4 confirmed; no Livewire UI code planned.
|
|
- **Panel provider registration location**: no panel change; Laravel 12 panel providers remain in `apps/platform/bootstrap/providers.php`.
|
|
- **Global search posture**: no Filament Resource is added. If implementation accidentally adds a resource, stop and amend artifacts before continuing; resource must disable global search or provide safe View/Edit page and `$recordTitleAttribute`.
|
|
- **Destructive/high-impact action posture**: no rendered action. Capture start is high-impact remote/provider work and must authorize server-side, create/reuse OperationRun, audit safely, queue work, and avoid raw payloads.
|
|
- **Asset strategy**: no assets, no `filament:assets` deployment requirement from this spec.
|
|
- **Testing plan**: unit tests for resolver/normalizer/hash/redaction/outcomes; feature/pgsql tests for persistence, RBAC, provider scope, fake Graph, OperationRun, and no-legacy guards.
|
|
- **Deployment impact**: database migrations and queue workers expected; no env vars, scheduler, storage volume, routes, assets, or reverse proxy changes expected unless implementation discovers a repo-real need and amends artifacts.
|
|
|
|
## Shared Pattern & System Fit
|
|
|
|
- **Cross-cutting feature marker**: yes.
|
|
- **Systems touched**: Coverage v2 kernel, OperationRun, Graph contracts/client, capability registry, audit recorder, queue/job infrastructure.
|
|
- **Shared abstractions reused**: `ResourceTypeRegistry`, `SupportedScopeResolver`, `ClaimGuard`, `GraphClientInterface`, `GraphContractRegistry`, `OperationRunService`, `OperationSummaryKeys`, `Capabilities`, `RoleCapabilityMap`.
|
|
- **New abstraction introduced? why?**: bounded capture-specific services are introduced because registry-only Coverage v2 cannot persist content evidence, normalize/hash payloads, or produce safe per-type outcomes.
|
|
- **Why the existing abstraction was sufficient or insufficient**: existing kernel services classify resource types and claims but do not fetch, normalize, or persist payload evidence. Existing OperationRun and Graph seams are sufficient and must be reused.
|
|
- **Bounded deviation / spread control**: no new provider framework, no UI framework, no generic identity engine, no compare/render/restore pipeline.
|
|
|
|
## OperationRun UX Impact
|
|
|
|
- **Touches OperationRun start/completion/link UX?**: backend lifecycle yes; rendered UX no.
|
|
- **Central contract reused**: OperationRun lifecycle via `OperationRunService`; if a start surface appears, central OperationRun Start UX Contract is mandatory and artifacts must be amended first.
|
|
- **Delegated UX behaviors**: no local toast/link/event planned; terminal notifications remain lifecycle-owned through the existing generic OperationRun path.
|
|
- **Surface-owned behavior kept local**: initiation inputs only in an internal service/action.
|
|
- **Queued DB-notification policy**: no queued DB notifications.
|
|
- **Terminal notification path**: central lifecycle mechanism.
|
|
- **Exception path**: none.
|
|
|
|
## Provider Boundary & Portability Fit
|
|
|
|
- **Shared provider/platform boundary touched?**: yes.
|
|
- **Provider-owned seams**: TCM source class, Graph v1 fallback source class, Graph beta experimental source class, provider-specific Graph contract metadata, permission/source context.
|
|
- **Platform-core seams**: concrete Coverage v2 resource/evidence ownership, capture outcome vocabulary, OperationRun execution truth, evidence payload truth.
|
|
- **Neutral platform terms / contracts preserved**: provider, source contract, operation, evidence, resource, managed environment, capture outcome.
|
|
- **Retained provider-specific semantics and why**: Spec 414 source classes remain because this is a TCM-first Microsoft coverage path.
|
|
- **Bounded extraction or follow-up path**: Spec 416 Canonical Identity Engine after payload-backed evidence exists.
|
|
|
|
## Constitution Check
|
|
|
|
- Inventory-first / snapshots-second: PASS. This spec creates explicit evidence capture, not UI claim truth or snapshot replacement.
|
|
- Read/write separation: PASS with controls. Capture writes internal evidence and must be authorized, audited, queued, and OperationRun-backed.
|
|
- Single Graph contract path: PASS. Graph calls must go through `GraphClientInterface` and repo contract registry.
|
|
- Deterministic capabilities: PASS. Authorization uses canonical capability constants; default planned capability is `EVIDENCE_MANAGE`.
|
|
- RBAC-UX: PASS. Non-member/not entitled is 404; member missing capability is 403; server-side Gate/Policy required.
|
|
- Workspace isolation: PASS. `workspace_id` + `managed_environment_id` are required for environment-owned records.
|
|
- Tenant isolation: PASS in current terminology. No `tenant_id` ownership column is introduced.
|
|
- Provider boundary: PASS. Provider-native IDs stay metadata; provider connection must be same workspace/environment.
|
|
- OperationRun observability: PASS. Remote/provider capture uses OperationRun and queue.
|
|
- OperationRun lifecycle: PASS. Transitions must use `OperationRunService`.
|
|
- Summary counts: PASS with constraint. Use `OperationSummaryKeys::all()`; default existing keys avoid new summary-key family.
|
|
- Test governance: PASS. Unit/feature/pgsql lanes are named; browser/heavy-governance are N/A.
|
|
- Proportionality: PASS with justified complexity. New persistence and services are needed for audit/evidence/source-of-truth correctness.
|
|
- No premature abstraction: PASS with bounded exception. Capture services are specific to current Coverage v2 evidence needs and initial resource types.
|
|
- Persisted truth: PASS. Evidence rows are durable append-only proof with independent lifecycle.
|
|
- Behavioral state: PASS. Capture outcomes affect persistence, run summaries, retry/failure handling, and reviewer gates.
|
|
- UI semantics: PASS. No UI framework or rendered status taxonomy.
|
|
- Product Surface Contract: PASS. No rendered UI surface changed.
|
|
- LEAN-001: PASS. No aliases, dual writes, fallback readers, compatibility shims, or legacy fixtures.
|
|
|
|
## Test Governance Check
|
|
|
|
- **Test purpose / classification by changed surface**: Unit for pure capture helpers; Feature/PostgreSQL for persistence, RBAC, OperationRun, Graph fake, provider-scope constraints, no-legacy guards.
|
|
- **Affected validation lanes**: fast-feedback, confidence, pgsql.
|
|
- **Why this lane mix is the narrowest sufficient proof**: no rendered UI exists; backend behavior and persistence are the risk.
|
|
- **Narrowest proving command(s)**:
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/TenantConfiguration`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantConfiguration`
|
|
- `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest -c phpunit.pgsql.xml tests/Feature/TenantConfiguration` when PostgreSQL-only constraints/indexes are added
|
|
- **Fixture / helper / factory / seed / context cost risks**: managed-environment/provider-connection/Graph fake setup must remain explicit and local.
|
|
- **Expensive defaults or shared helper growth introduced?**: no; any helper must be opt-in.
|
|
- **Heavy-family additions, promotions, or visibility changes**: none.
|
|
- **Surface-class relief / special coverage rule**: N/A no rendered UI.
|
|
- **Closing validation and reviewer handoff**: verify no UI activation, no real Graph calls, no `tenant_id`, no old v1 vocabulary, same-scope provider connection, sanitized contexts, OperationRunService lifecycle.
|
|
- **Budget / baseline / trend follow-up**: none expected.
|
|
- **Review-stop questions**: lane fit, hidden Graph call risk, fixture breadth, OperationRun summary keys, provider-scope constraints.
|
|
- **Escalation path**: document-in-feature for local helper cost; follow-up-spec only for identity engine or UI activation.
|
|
- **Active feature PR close-out entry**: Guardrail / no rendered UI.
|
|
- **Why no dedicated follow-up spec is needed**: the runtime capture foundation is the current feature; identity/UI/cutover are already deferred follow-ups.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/415-generic-content-backed-capture/
|
|
├── spec.md
|
|
├── plan.md
|
|
├── tasks.md
|
|
├── checklists/
|
|
│ └── requirements.md
|
|
└── implementation-report.md
|
|
```
|
|
|
|
### Source Code (likely affected in later implementation)
|
|
|
|
```text
|
|
apps/platform/app/Models/
|
|
├── TenantConfigurationResource.php
|
|
└── TenantConfigurationResourceEvidence.php
|
|
|
|
apps/platform/app/Services/TenantConfiguration/
|
|
├── CoverageSourceContractResolver.php
|
|
├── GenericPayloadNormalizer.php
|
|
├── CoverageResourceUpserter.php
|
|
├── CoverageEvidenceWriter.php
|
|
├── GenericContentEvidenceCaptureService.php
|
|
├── StartTenantConfigurationCapture.php
|
|
└── CoverageCaptureOutcomeSummarizer.php
|
|
|
|
apps/platform/app/Support/TenantConfiguration/
|
|
└── CaptureOutcome.php
|
|
|
|
apps/platform/app/Jobs/TenantConfiguration/
|
|
└── CaptureTenantConfigurationEvidenceJob.php
|
|
|
|
apps/platform/database/migrations/
|
|
└── *_create_tenant_configuration_capture_tables.php
|
|
|
|
apps/platform/database/factories/
|
|
├── TenantConfigurationResourceFactory.php
|
|
└── TenantConfigurationResourceEvidenceFactory.php
|
|
|
|
apps/platform/tests/Unit/Support/TenantConfiguration/
|
|
└── Spec415*Test.php
|
|
|
|
apps/platform/tests/Feature/TenantConfiguration/
|
|
└── Spec415*Test.php
|
|
```
|
|
|
|
**Structure Decision**: Use the existing `apps/platform` Laravel monolith. Keep capture domain code under the existing `Services/TenantConfiguration` and `Support/TenantConfiguration` namespaces. Add jobs under a tenant-configuration job namespace only if the repo does not already have a closer convention.
|
|
|
|
## Complexity Tracking
|
|
|
|
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
|
|---|---|---|
|
|
| New resource/evidence tables | Durable append-only v2 evidence needs independent lifecycle and auditability | v1 snapshots or metadata-only rows would create hidden dual truth |
|
|
| New capture services | Fetch/normalize/hash/redact/persist responsibilities must stay out of Filament, models, and jobs | Putting workflow in a job or model would make authorization/audit/Graph seams harder to test |
|
|
| New capture outcome family | Implementation must distinguish missing contract, permission, beta, unsupported, captured, and failed because each has different persistence/run behavior | Reusing old gap taxonomy is explicitly forbidden and misleading |
|
|
|
|
## Proportionality Review
|
|
|
|
- **Current operator problem**: future Coverage v2 operator/customer claims require concrete evidence proof; otherwise the product can overclaim coverage based on registry truth only.
|
|
- **Existing structure is insufficient because**: Spec 414 has registry/scope/claim guard only, while v1 runtime evidence cannot safely stand in for v2 proof.
|
|
- **Narrowest correct implementation**: initial 414 resource types, contract-driven eligibility, append-only evidence, generic normalization/hash, redaction, OperationRun-backed async execution, no UI.
|
|
- **Ownership cost created**: migrations/models/services/job/tests and ongoing care around redaction, queue behavior, and provider contract mapping.
|
|
- **Alternative intentionally rejected**: v1 snapshot promotion, metadata-only capture, UI activation, broad TCM catalog import, semantic compare/render/restore.
|
|
- **Release truth**: current-release foundation after completed Spec 414.
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 0 - Preflight
|
|
|
|
- Confirm branch, HEAD, clean/dirty state.
|
|
- Confirm Spec 414 implementation report and completed tasks remain read-only context.
|
|
- Confirm no existing `tenant_configuration_resources` / `tenant_configuration_resource_evidence` equivalent exists.
|
|
- Confirm graph contract entries and 414 registry metadata for initial resource types.
|
|
|
|
### Phase 1 - Tests First
|
|
|
|
- Add unit tests for resolver, normalizer, hash, redaction, and capture outcome behavior.
|
|
- Add feature/PostgreSQL tests for persistence, JSONB, same-scope provider connection, RBAC, OperationRun, fake Graph, and no-legacy/no-UI guards.
|
|
|
|
### Phase 2 - Persistence
|
|
|
|
- Add concrete resource and evidence tables/models/factories if missing.
|
|
- Enforce `workspace_id`, `managed_environment_id`, same-scope `provider_connection_id`, no `tenant_id`, append-only evidence, and targeted indexes.
|
|
|
|
### Phase 3 - Source Resolution And Normalization
|
|
|
|
- Resolve source contracts from Coverage v2 registry and repo Graph contract registry.
|
|
- Block missing/beta/unsupported sources safely.
|
|
- Normalize payloads minimally, hash deterministically, and redact permission/source context.
|
|
|
|
### Phase 4 - OperationRun Start And Queue
|
|
|
|
- Add `tenant_configuration.capture` OperationRun type/catalog entry if required by repo conventions.
|
|
- Implement authorized internal start service/action.
|
|
- Queue remote capture job and keep lifecycle transitions in `OperationRunService`.
|
|
- Use existing `OperationSummaryKeys` unless a tested canonical extension is required.
|
|
|
|
### Phase 5 - Capture And Evidence Write
|
|
|
|
- Fetch via `GraphClientInterface` fakeable calls only where explicit contracts exist.
|
|
- Upsert concrete resource rows by deterministic identity.
|
|
- Write append-only evidence rows and per-type outcomes.
|
|
- Audit start/completion/failure safely through the existing `AuditRecorder` / `AuditEventBuilder` path with stable `tenant_configuration.capture.started`, `tenant_configuration.capture.completed`, and `tenant_configuration.capture.failed` action IDs.
|
|
|
|
### Phase 6 - Report And Validation
|
|
|
|
- Complete implementation report with eligibility matrix and safety proof.
|
|
- Run focused Pint/tests/pgsql lane as needed and `git diff --check`.
|
|
- Record no-browser, no-assets, no-global-search, no-Filament-provider-change, and deployment impact.
|
|
|
|
## Stop Conditions
|
|
|
|
- Spec 414 kernel is missing or not accepted.
|
|
- Implementation needs customer/operator UI activation.
|
|
- Implementation needs v1 adapter, dual-write, fallback reader, old snapshot promotion, or old gap taxonomy.
|
|
- Implementation needs hardcoded Graph endpoints or direct HTTP/SDK calls outside `GraphClientInterface`.
|
|
- Implementation needs beta capture opt-in.
|
|
- Implementation needs broad identity engine, semantic compare, rendering, restore/apply, or full catalog import.
|
|
- Implementation changes rendered UI files, routes, navigation, reports, downloads, or evidence/review surfaces without amending spec/plan/tasks first.
|