TenantAtlas/specs/415-generic-content-backed-capture/implementation-report.md
ahmido ca0f54614d feat: add generic content-backed coverage capture (#482)
Automated PR provided by Codex via Gitea API.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #482
2026-06-25 19:55:52 +00:00

11 KiB

Implementation Report: Spec 415 - Generic Content-Backed Capture

Preflight

  • Branch: 415-generic-content-backed-capture
  • Baseline HEAD: dfda397e feat: migrate tcm first coverage core cutover (#481)
  • Initial dirty state: specs/415-generic-content-backed-capture/ untracked as the active spec artifact set.
  • Spec 414 dependency: treated as completed/validated context only; no files under specs/414-tcm-first-coverage-core-cutover/ were modified.
  • Existing equivalent check: no existing tenant_configuration_resources or tenant_configuration_resource_evidence tables/models were present before implementation.

Implementation Scope

  • Added tenant_configuration_resources and tenant_configuration_resource_evidence persistence with workspace_id, managed_environment_id, provider_connection_id, and resource_type_id; no tenant_id fields.
  • Added PostgreSQL composite scope constraints for managed environment/workspace, provider connection/workspace/environment, evidence/resource/provider/type, evidence/latest-resource/provider/type, and evidence/operation-run/workspace/environment integrity while keeping SQLite-compatible migrations for tests.
  • Added a database-level provider_connections(managed_environment_id, workspace_id) binding so provider connections cannot be attached to a managed environment from another workspace.
  • Added a scoped latest_evidence_id foreign key so a resource can only point at evidence for the same resource, workspace, managed environment, provider connection, and resource type.
  • Added models and factories for concrete resources and append-only evidence.
  • Added bounded capture outcomes only: captured, capture_blocked_missing_contract, capture_blocked_permission, capture_blocked_beta, capture_blocked_unsupported, capture_failed.
  • Added contract resolution through GraphContractRegistry with explicit mappings only:
    • deviceAndAppManagementAssignmentFilter -> assignmentFilter -> captured when Graph succeeds.
    • notificationMessageTemplate -> notificationMessageTemplate -> captured when Graph succeeds.
    • roleScopeTag -> beta-backed and blocked by default.
    • Other initial TCM types remain capture_blocked_missing_contract until explicit contracts are introduced.
  • Added deterministic normalization, configured volatile-field stripping, SHA-256 payload hashes, and recursive secret/token/header/cookie redaction for metadata/context.
  • Added tenant_configuration.capture operation type/catalog label and a queued capture job.
  • Added defense-in-depth scope validation before remote provider work: the job resolves provider connections only inside the OperationRun workspace/environment, and the capture service validates tenant/provider/run/context scope before calling the provider gateway.

Capture Eligibility Matrix

Canonical type Source class Source contract key Default outcome
deviceAndAppManagementAssignmentFilter tcm assignmentFilter captured when Graph succeeds
deviceEnrollmentLimitRestriction tcm none capture_blocked_missing_contract
deviceEnrollmentPlatformRestriction tcm none capture_blocked_missing_contract
deviceEnrollmentStatusPageWindows10 tcm none capture_blocked_missing_contract
appProtectionPolicyAndroid tcm none capture_blocked_missing_contract
appProtectionPolicyiOS tcm none capture_blocked_missing_contract
notificationMessageTemplate graph_v1_fallback notificationMessageTemplate captured when Graph succeeds
roleScopeTag graph_beta_experimental roleScopeTag capture_blocked_beta unless beta capture is explicitly enabled

Operation And RBAC

  • Start capability: existing Capabilities::EVIDENCE_MANAGE.
  • Authorization behavior:
    • non-member and excluded explicit environment entitlement -> 404.
    • workspace member without capability / readonly -> 403.
    • same workspace/environment/provider connection -> allowed.
  • OperationRun behavior:
    • creates/reuses tenant_configuration.capture queued runs from idempotent provider/resource-type inputs.
    • remote/provider work is queued through the central OperationRun lifecycle.
    • the central queued execution gate validates provider_connection_id against both the OperationRun workspace and managed environment before provider work is allowed.
    • the capture job and capture service also fail closed before Graph access when the provider connection, managed environment, OperationRun columns, or OperationRun target scope do not match.
    • summary keys are existing canonical keys only: total, processed, succeeded, skipped, failed, errors_recorded.
    • raw payloads and Graph credential options are not written into OperationRun context or audit metadata.
    • exception messages are reduced to bounded RunFailureSanitizer reason codes for resource outcomes; dispatch/job failure audit messages are sanitized before persistence.
  • Audit action IDs used:
    • tenant_configuration.capture.started
    • tenant_configuration.capture.completed
    • tenant_configuration.capture.failed

Product Surface

  • No rendered UI surface changed.
  • No Filament resources, pages, widgets, relation managers, routes, panel providers, navigation entries, views, assets, review/report/evidence pages, or restore readiness surfaces were added or modified.
  • Browser proof: N/A - no rendered UI surface changed.
  • Human Product Sanity: N/A - no product surface changed.
  • Visible complexity outcome: unchanged.
  • Product Surface exceptions: none.
  • No completed historical spec was rewritten or stripped of validation/task/review history.

Filament V5 Contract

  • Livewire v4.0+ compliance: no Livewire/Filament runtime UI code changed; application package baseline remains Livewire v4.
  • Provider registration location: unchanged; Laravel 11+/12 panel provider registration remains bootstrap/providers.php.
  • Global search: no globally searchable resource was added; N/A.
  • Destructive/high-impact actions: no UI action added; queued capture start is backend service only and RBAC-gated.
  • Asset strategy: no assets registered; no filament:assets requirement from this spec.
  • Testing plan: Unit/Feature/PostgreSQL lanes only; no Livewire page/widget/relation-manager/action tests required.

Files Changed

  • Persistence:
    • apps/platform/database/migrations/2026_06_25_000415_create_tenant_configuration_capture_tables.php
    • apps/platform/app/Models/TenantConfigurationResource.php
    • apps/platform/app/Models/TenantConfigurationResourceEvidence.php
    • apps/platform/database/factories/TenantConfigurationResourceFactory.php
    • apps/platform/database/factories/TenantConfigurationResourceEvidenceFactory.php
  • Capture support/services:
    • apps/platform/app/Support/TenantConfiguration/CaptureOutcome.php
    • apps/platform/app/Services/TenantConfiguration/CoverageSourceContractResolver.php
    • apps/platform/app/Services/TenantConfiguration/CoverageSourceContractDecision.php
    • apps/platform/app/Services/TenantConfiguration/GenericPayloadNormalizer.php
    • apps/platform/app/Services/TenantConfiguration/CoveragePayloadRedactor.php
    • apps/platform/app/Services/TenantConfiguration/CoverageCaptureOutcomeSummarizer.php
    • apps/platform/app/Services/TenantConfiguration/CoverageResourceUpserter.php
    • apps/platform/app/Services/TenantConfiguration/CoverageEvidenceWriter.php
    • apps/platform/app/Services/TenantConfiguration/GenericContentEvidenceCaptureService.php
    • apps/platform/app/Services/TenantConfiguration/StartTenantConfigurationCapture.php
    • apps/platform/app/Jobs/TenantConfiguration/CaptureTenantConfigurationEvidenceJob.php
  • Operation/audit registry:
    • apps/platform/app/Services/Operations/QueuedExecutionLegitimacyGate.php
    • apps/platform/app/Support/OperationRunType.php
    • apps/platform/app/Support/OperationCatalog.php
    • apps/platform/app/Support/Audit/AuditActionId.php
  • Tests:
    • apps/platform/tests/Unit/Support/TenantConfiguration/Spec415CoverageSourceContractResolverTest.php
    • apps/platform/tests/Unit/Support/TenantConfiguration/Spec415GenericPayloadNormalizerTest.php
    • apps/platform/tests/Unit/Support/TenantConfiguration/Spec415CoverageRedactionTest.php
    • apps/platform/tests/Unit/Support/TenantConfiguration/Spec415CoverageCaptureOutcomeTest.php
    • apps/platform/tests/Unit/Support/TenantConfiguration/Spec415CoverageCaptureOperationRunSummaryTest.php
    • apps/platform/tests/Feature/TenantConfiguration/Spec415CoverageEvidencePersistenceTest.php
    • apps/platform/tests/Feature/TenantConfiguration/Spec415ProviderConnectionScopeTest.php
    • apps/platform/tests/Feature/TenantConfiguration/Spec415CoverageCaptureAuthorizationTest.php
    • apps/platform/tests/Feature/TenantConfiguration/Spec415CoverageCaptureOperationRunTest.php
    • apps/platform/tests/Feature/TenantConfiguration/Spec415GenericContentBackedCaptureTest.php
    • apps/platform/tests/Feature/TenantConfiguration/Spec415NoLegacyNoUiActivationTest.php
    • apps/platform/tests/Unit/Operations/QueuedExecutionLegitimacyGateTest.php

Validation

  • cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent -> pass.
  • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/TenantConfiguration -> 22 passed, 69 assertions.
  • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Operations/QueuedExecutionLegitimacyGateTest.php -> 12 passed, 106 assertions.
  • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantConfiguration/Spec415GenericContentBackedCaptureTest.php -> 4 passed, 50 assertions.
  • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantConfiguration -> 24 passed, 7 skipped, 129 assertions.
  • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest -c phpunit.pgsql.xml tests/Feature/TenantConfiguration -> 31 passed, 141 assertions.
  • PostgreSQL migration smoke on tenantatlas_testing: migrate:fresh --force -> pass; targeted rollback of 2026_06_25_000415_create_tenant_configuration_capture_tables.php -> pass; final migrate:fresh --force -> pass.
  • PostgreSQL latest-evidence lifecycle coverage: scoped pointer mismatch is rejected, same-scope pointer is accepted, and resource deletion cascades linked evidence without constraint failure.
  • git diff --check -> pass.
  • Additional untracked-file whitespace scan -> pass.

Deployment Impact

  • Migrations: yes, adds two new tenant configuration capture tables with PostgreSQL JSONB/check constraints and composite scope foreign keys; also adds a provider-connection environment/workspace binding constraint on the existing provider_connections table.
  • Queue worker: yes, new queued capture job.
  • Environment variables: no new variables.
  • Scheduler: no change.
  • Storage/volumes: no change.
  • Assets: no change; filament:assets not required by this spec.
  • Staging/production: run migrations before enabling any future caller; ensure queue workers are running; validate staging data has no existing provider-connection workspace/environment mismatches before production promotion.

Deferred Work

  • Add explicit source contracts for the remaining TCM-backed resource types before claiming captured evidence for them.
  • Add any UI start surface only through a future UI-affecting spec with Product Surface review.