TenantAtlas/specs/415-generic-content-backed-capture/spec.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

36 KiB

Feature Specification: Spec 415 - Generic Content-Backed Capture

Feature Branch: 415-generic-content-backed-capture Created: 2026-06-25 Status: Draft Input: User-provided candidate "415 - Generic Content-Backed Capture" as the next bounded follow-up after Spec 414.

Candidate Selection Summary

  • Selected candidate: Spec 415 - Generic Content-Backed Capture.
  • Source: Direct user-provided candidate in /Users/ahmeddarrazi/.codex/attachments/b061549c-2e15-4bb3-b5ab-a2c3e23d0d55/pasted-text.txt.
  • Why selected: Spec 414 is implemented as an inactive Coverage v2 kernel and explicitly defers OperationRun-backed content-backed capture. This spec is the next narrow foundation slice: store real v2 payload evidence without activating v2 as customer-facing truth.
  • Roadmap relationship: Supports evidence/coverage hardening, provider-boundary discipline, OperationRun observability, and future Coverage v2 activation. It does not create a new product surface.
  • Close alternatives deferred: docs/product/spec-candidates.md currently has no safe automatic next-best-prep target. Manual backlog items require explicit product promotion. Spec 416 Canonical Identity Engine is deferred until v2 can persist payload-backed evidence.
  • Related completed-spec guardrail: specs/414-tcm-first-coverage-core-cutover/ is completed and validated. It is dependency context only and must not be rewritten. No existing 415-* spec or branch was found before creation.
  • Smallest viable implementation slice: Add internal, OperationRun-backed, contract-driven capture for the Spec 414 initial resource types, with concrete resource/evidence persistence, deterministic normalization/hashing, redaction, RBAC/scope guards, and no rendered UI activation.

Spec Candidate Check (mandatory - SPEC-GATE-001)

  • Problem: Coverage v2 can classify resource types after Spec 414, but it still cannot persist concrete, content-backed evidence for resources in a managed environment.
  • Today's failure: Later activation would risk registry-only claims, metadata-only proof, hidden reliance on v1 snapshots, or future compare/render work without durable v2 payload truth.
  • User-visible improvement: No immediate UI change. The trust improvement is that future customer/operator coverage claims can be grounded in append-only v2 evidence instead of registry assertions.
  • Smallest enterprise-capable version: Persist concrete v2 resources and append-only evidence for the initial 414 resource types, capture only where explicit repo contracts exist, block unsafe/missing/beta contracts, and summarize execution through OperationRun.
  • Explicit non-goals: No Coverage v2 UI activation, no Evidence Overview/Review Workspace/Review Pack/Report/Restore/Compare conversion, no v1-to-v2 adapter, no full TCM catalog import, no semantic diff, no rendering, no restore/apply, no browser-visible UI.
  • Permanent complexity imported: New environment-owned resource/evidence tables and models, a bounded capture outcome family, capture/source/normalization/redaction services, an OperationRun type, job/start service, authorization tests, and focused guard tests.
  • Why now: Spec 414 completed the inactive kernel and named generic content-backed capture as the next dependency. Payload evidence is a prerequisite for identity hardening, operator surface activation, compare/render packs, certification, and legacy removal.
  • Why not local: Reusing v1 snapshots or adding a local metadata helper would keep dual truth and would not prove provider-connection ownership, payload redaction, Graph contract discipline, or OperationRun execution truth.
  • Approval class: Core Enterprise.
  • Red flags triggered: New persisted truth, new service abstractions, new outcome/status-like family, foundation terminology. Defense: the slice is bounded to real current dependency value, no UI activation, no compatibility layer, initial 414 resource types only, and security/audit/queue correctness justify the added structure.
  • Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 1 | Wiederverwendung: 2 | Gesamt: 10/12
  • Decision: approve as a bounded preparation package.

Spec Scope Fields (mandatory)

  • Scope: tenant / managed-environment operational evidence under workspace ownership.
  • Primary Routes: N/A - no route or rendered UI surface is added or changed.
  • Data Ownership: Environment-owned capture records use workspace_id + managed_environment_id; provider-sourced records include provider_connection_id. Provider-native tenant/directory/account IDs remain metadata only.
  • RBAC: Workspace membership and managed-environment entitlement are required. Missing membership/entitlement returns 404. Established members without the capture capability return 403. Server-side Gate/Policy enforcement is required on the start service.

No Legacy / No Backward Compatibility Constraint (mandatory)

TenantPilot is pre-production unless this spec explicitly records a compatibility exception.

  • Compatibility posture: canonical v2 evidence path; no compatibility exception.
  • Legacy aliases, fallback readers, hidden routes, duplicate UI, old labels, or historical fixtures kept?: no.
  • Why clean replacement is safe now: Coverage v2 is inactive and not customer-facing. No production data migration or external contract compatibility is required. Spec 415 must not read v1 snapshots as v2 proof, dual-write v1/v2 evidence, or translate old gap taxonomy.

UI Surface Impact (mandatory - UI-COV-001)

Does this spec add, remove, rename, or materially change any reachable UI surface?

  • No UI surface impact
  • Existing page changed
  • New page/route added
  • Navigation changed
  • Filament panel/provider surface changed
  • New modal/drawer/wizard/action added
  • New table/form/state added
  • Customer-facing surface changed
  • Dangerous action changed
  • Status/evidence/review presentation changed
  • Workspace/environment context presentation changed

UI/Productization Coverage (mandatory when UI Surface Impact is not "No UI surface impact"; otherwise write N/A - no reachable UI surface impact plus rationale)

N/A - no reachable UI surface impact. This spec adds internal persistence, services, a queued job/start service, OperationRun tracking, authorization, and tests. It must not add Filament resources/pages, Blade views, routes, navigation, customer output, report output, or review/evidence UI activation.

Existing generic Monitoring -> Operations and central database-notification surfaces may show OperationRun records produced by this backend operation through the existing shared lifecycle contract. That is allowed only as existing technical/operational truth. This spec must not add feature-local notification copy, custom operation UI, custom run links, or new rendered capture controls without first amending spec.md, plan.md, and tasks.md.

Product Surface Impact (mandatory for UI-affecting specs; otherwise write N/A - no rendered product surface changed plus rationale)

Reference: docs/product/standards/product-surface-contract.md.

  • Product Surface Contract applies?: no - no rendered product surface changes.
  • Page archetype: N/A.
  • Primary user question: N/A.
  • Primary action: N/A.
  • Surface budget result: N/A.
  • Technical Annex / deep-link demotion: N/A - no default product view exposes OperationRun, evidence IDs, source keys, payloads, fingerprints, or logs.
  • Canonical status vocabulary: N/A - no product-facing labels added.
  • Visible complexity impact: neutral; no rendered UI surface changes.
  • Product Surface exceptions: none.

Browser Verification Plan (mandatory)

  • Browser proof required?: no.
  • No-browser rationale: N/A - no rendered UI surface changed.
  • Focused path when required: N/A.
  • Primary interaction to execute: N/A.
  • Console, Livewire, Filament, network, and 500-error checks: N/A.
  • Full-suite failure triage: N/A; no browser lane is expected unless implementation changes rendered UI, routes, downloads, reports, or reachable actions.

Human Product Sanity Check (mandatory)

  • Required?: no.
  • No-human-sanity rationale: N/A - no product surface changed.
  • Reviewer questions: N/A for rendered UI; reviewers should instead verify that v2 evidence remains inactive and hidden from customer/operator proof surfaces.
  • Planned result location: implementation-report.

Product Surface Merge Gate Checklist (mandatory)

  • No-legacy posture or approved exception recorded.
  • Product Surface Impact is completed or N/A is justified.
  • Browser proof is completed or N/A - no rendered UI surface changed is justified.
  • Human Product Sanity is completed or not applicable with rationale.
  • Product Surface exceptions are documented or none.
  • Implementation report will state Livewire v4 compliance, provider registration location, global search posture, destructive/high-impact action posture, asset strategy, tests/browser result, deployment impact, visible complexity outcome, and no completed-spec rewrite assertion.

Cross-Cutting / Shared Pattern Reuse (mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write N/A - no shared interaction family touched)

  • Cross-cutting feature?: yes.
  • Interaction class(es): OperationRun execution lifecycle, terminal notification lifecycle, audit logging, provider Graph contract boundary.
  • Systems touched: OperationRun, OperationRunService, OperationRunType, OperationCatalog if required by current repo conventions, OperationSummaryKeys, GraphClientInterface, GraphContractRegistry, AuditLog/audit recorder path, RBAC capability checks.
  • Existing pattern(s) to extend: OperationRun lifecycle service, Graph contract registry/client seam, canonical capability registry, existing role capability map, existing audit recorder pattern.
  • Shared contract / presenter / builder / renderer to reuse: OperationRun start/lifecycle contract where any start feedback/link is introduced. No rendered start UX is planned, so no local toast/link composition is allowed.
  • Why the existing shared path is sufficient or insufficient: Existing OperationRun and Graph seams are sufficient for execution truth and provider calls. New local UI or notification semantics are unnecessary.
  • Allowed deviation and why: none.
  • Consistency impact: capture must not invent local operation notifications, local run-link wording, or local summary counter keys.
  • Review focus: verify OperationRun transitions use OperationRunService, terminal notification remains lifecycle-owned, Graph calls go through GraphClientInterface, and summary counts use allowed keys.
  • Touches OperationRun start/completion/link UX?: yes for backend execution lifecycle; no rendered start surface.
  • Shared OperationRun UX contract/layer reused: central OperationRun lifecycle and start contract. If any UI/start surface is unexpectedly added, implementation must stop and patch spec/plan/tasks before continuing.
  • Delegated start/completion UX behaviors: no local UI behavior planned; terminal notification path remains central lifecycle mechanism through the existing generic OperationRun notification path only.
  • Local surface-owned behavior that remains: initiation inputs only through an internal service/action; no Filament page/action, no toast, no local run link.
  • Queued DB-notification policy: no queued DB notifications. Terminal notification behavior remains whatever OperationRunService/lifecycle emits for initiator-owned runs.
  • Terminal notification path: central lifecycle mechanism / OperationRunCompleted.
  • Exception required?: none.

Provider Boundary / Platform Core Check (mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write N/A - no shared provider/platform boundary touched)

  • Shared provider/platform boundary touched?: yes.
  • Boundary classification: mixed. Coverage resource/evidence ownership and outcome semantics are platform-core. Microsoft TCM/Graph source details are provider-owned source metadata.
  • Seams affected: Coverage v2 resource type registry, Graph contract resolution, GraphClientInterface, provider connection provenance, source metadata, permission context redaction.
  • Neutral platform terms preserved or introduced: provider, source contract, managed environment, evidence, resource, capture outcome, operation.
  • Provider-specific semantics retained and why: tcm, graph_v1_fallback, and graph_beta_experimental remain from Spec 414 because this is a TCM-first Microsoft coverage path. They must not become generic platform ownership keys.
  • Why this does not deepen provider coupling accidentally: source-specific values stay in registry/source metadata and resolver decisions. Concrete resource/evidence ownership remains workspace_id, managed_environment_id, and same-scope provider_connection_id; provider-native tenant IDs remain metadata.
  • Follow-up path: Spec 416 Canonical Identity Engine is deferred; no multi-provider framework is introduced here.

UI / Surface Guardrail Impact (mandatory when operator-facing surfaces are changed; otherwise write N/A)

Surface / Change Operator-facing surface change? Native vs Custom Shared-Family Relevance State Layers Touched Exception Needed? Low-Impact / N/A Note
Coverage v2 internal capture persistence and service path no N/A OperationRun and Graph service seams only none no N/A - backend/internal evidence capture only

Decision-First Surface Role (mandatory when operator-facing surfaces are changed)

N/A - no operator-facing surface change.

Audience-Aware Disclosure (mandatory when operator-facing surfaces are changed)

N/A - no operator-facing surface change. Raw and normalized payloads are persisted only in internal evidence storage and must not be exposed through customer/operator default views in this spec.

UI/UX Surface Classification (mandatory when operator-facing surfaces are changed)

N/A - no operator-facing surface change.

Operator Surface Contract (mandatory when operator-facing surfaces are changed)

N/A - no operator-facing surface change.

Proportionality Review (mandatory when structural complexity is introduced)

  • New source of truth?: yes. Append-only Coverage v2 evidence becomes durable internal evidence truth for captured resource payloads.
  • New persisted entity/table/artifact?: yes. tenant_configuration_resources and tenant_configuration_resource_evidence or repo-equivalent names.
  • New abstraction?: yes. Bounded source contract resolver, capture service, resource upserter, evidence writer, payload normalizer, and outcome summarizer.
  • New enum/state/reason family?: yes. Capture outcomes: captured, capture_blocked_missing_contract, capture_blocked_permission, capture_blocked_beta, capture_blocked_unsupported, capture_failed.
  • New cross-domain UI framework/taxonomy?: no.
  • Current operator problem: future operators must not receive false Coverage v2 claims or evidence-backed reports when no concrete payload evidence exists.
  • Existing structure is insufficient because: Spec 414 registry/scope/claim guard has no concrete resource rows and no content payload persistence. v1 inventory/snapshot truth would create hidden dual truth and cannot enforce Coverage v2 source class, provider provenance, or claim safety.
  • Narrowest correct implementation: concrete resources, append-only evidence, minimal generic normalization/hash, source-contract resolver, OperationRun-backed async capture, RBAC/scope guards, and tests for the initial 414 resource types only.
  • Ownership cost: new migrations/models/services/jobs/tests and ongoing care for payload redaction, schema constraints, OperationRun keys, and provider contract mapping.
  • Alternative intentionally rejected: using v1 snapshots as v2 evidence, storing metadata-only capture rows, or adding UI activation before evidence is durable. These alternatives would hide dual truth or overclaim coverage.
  • Release truth: current-release foundation required by the completed 414 kernel and immediately following 416/417/418 lanes.

Compatibility posture

This feature assumes a pre-production environment. Backward compatibility, legacy aliases, migration shims, historical fixtures, v1 fallback readers, v1-to-v2 adapters, and compatibility-specific tests are out of scope.

Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)

  • Test purpose / classification: Unit for source contract resolution, normalization, hashing, redaction, and outcomes. Feature/PostgreSQL for persistence, JSONB, provider-connection same-scope constraints, OperationRun, RBAC, fake GraphClientInterface capture, and no-legacy guards.
  • Validation lane(s): fast-feedback, confidence, and PostgreSQL lane where JSONB/check constraints/composite FKs/partial indexes are introduced. Browser lane is N/A unless UI changes are introduced by amendment.
  • Why this classification and these lanes are sufficient: The change is backend/runtime and persistence-heavy. Unit tests prove deterministic pure behavior; feature/PostgreSQL tests prove ownership, authorization, persistence, and OperationRun behavior. Browser tests would not add proof without a rendered UI surface.
  • New or expanded test families: tests/Unit/Support/TenantConfiguration and tests/Feature/TenantConfiguration may expand with Spec 415-specific files.
  • Fixture / helper cost impact: managed-environment, workspace, provider-connection, user-role, and fake Graph setup must remain opt-in and local to Spec 415 tests.
  • Heavy-family visibility / justification: none planned. Do not add heavy-governance or browser families for this slice.
  • Special surface test profile: N/A - no rendered UI surface changed.
  • Standard-native relief or required special coverage: N/A.
  • Reviewer handoff: verify no real Graph/TCM calls, no UI activation, no v1 adapter, no tenant_id, same-scope provider connection, allowed summary keys, redaction, and OperationRunService lifecycle.
  • Budget / baseline / trend impact: none expected; if new tests materially slow fast-feedback, document in implementation report.
  • Escalation needed: document-in-feature if focused tests require a new helper; follow-up-spec only if identity matching or surface activation becomes necessary.
  • Active feature PR close-out entry: Guardrail / N/A no rendered UI surface changed.
  • Planned validation commands:
    • cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
    • 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 migrations add JSONB/check constraints/composite FKs/partial unique indexes
    • git diff --check

User Scenarios & Testing (mandatory)

User Story 1 - Persist Content-Backed Coverage v2 Evidence (Priority: P1)

As a platform engineer preparing Coverage v2 activation, I need concrete managed-environment resources and append-only evidence rows so future claims can be backed by durable payload truth.

Independent Test: Run the capture service against a fake GraphClientInterface response for an eligible resource type and assert concrete resource upsert plus append-only evidence persistence with raw payload, normalized payload, hash, and OperationRun link.

Acceptance Scenarios:

  1. Given an eligible registered resource type with an explicit source contract, When capture runs for a managed environment and same-scope provider connection, Then a concrete Coverage v2 resource exists with deterministic identity fields.
  2. Given a successful payload fetch, When evidence is written, Then a new append-only evidence row stores raw payload, normalized payload, payload hash, source metadata, permission context, captured timestamp, and OperationRun link.
  3. Given the same normalized payload captured twice, When hashes are compared, Then the payload hash is deterministic and identical.
  4. Given a changed normalized payload captured later, When evidence is written, Then a new evidence row is appended instead of mutating prior evidence.

User Story 2 - Fail Safe On Missing, Beta, Unsupported, Or Unauthorized Capture (Priority: P1)

As a release reviewer, I need capture eligibility to fail safe so v2 does not guess endpoints, certify beta data, or emit old v1 gap reasons.

Independent Test: Resolve capture eligibility for one TCM-aligned type, one Graph v1 fallback type, and the beta experimental type; assert missing contracts, beta default, unsupported states, and permission denial produce structured v2 outcomes only.

Acceptance Scenarios:

  1. Given a registered type without an explicit source contract, When capture eligibility is resolved, Then the outcome is capture_blocked_missing_contract.
  2. Given a beta experimental resource type without explicit beta capture opt-in, When capture is requested, Then the outcome is capture_blocked_beta and no customer/certified claim is possible.
  3. Given an unsupported or out-of-scope type, When capture is requested, Then it is skipped safely without endpoint guessing.
  4. Given a missing provider permission, When capture fails due to authorization from the provider, Then the outcome is capture_blocked_permission with sanitized context only.
  5. Given any blocked/failed capture, When outcomes are inspected, Then no old v1 gap vocabulary is emitted.

User Story 3 - Run Capture As An Observable Authorized Operation (Priority: P1)

As an operator-authorized backend workflow, I need generic capture to be authorized, queued when remote work is involved, and observable through OperationRun without rendering a new UI.

Independent Test: Start capture through the internal service for authorized and unauthorized users; assert 404/403 semantics, OperationRun creation/dedupe, queued job dispatch, OperationRunService transitions, numeric-only summary counts, and audit entry.

Acceptance Scenarios:

  1. Given a non-member user, When capture start is attempted, Then access is denied as not found (404).
  2. Given a workspace member without managed-environment entitlement, When capture start is attempted, Then access is denied as not found (404).
  3. Given a managed-environment member without the capture capability, When capture start is attempted, Then access is denied as forbidden (403).
  4. Given an authorized actor, When capture starts, Then a tenant_configuration.capture OperationRun is created or reused and remote work is queued.
  5. Given the capture job runs, When it updates execution state, Then status/outcome transitions go through OperationRunService.
  6. Given capture outcomes are summarized, When summary_counts is saved, Then only canonical numeric keys are used. Default keys are total, processed, succeeded, skipped, failed, and errors_recorded unless the implementation explicitly extends OperationSummaryKeys::all() with tests and spec-aligned rationale.

User Story 4 - Keep Coverage v2 Inactive And Non-Legacy (Priority: P1)

As a product/release reviewer, I need proof that content-backed v2 evidence does not become an active customer/operator truth or compatibility bridge in this slice.

Independent Test: Static/feature guards assert no Filament resources/pages/routes/views/navigation are added, no v1-to-v2 adapter or dual-write path appears, no v1 snapshots are read as v2 evidence, and no Coverage v2 table introduces tenant_id.

Acceptance Scenarios:

  1. Given v2 evidence rows exist, When current customer/operator surfaces render, Then they do not display v2 coverage claims from this spec.
  2. Given existing v1 runtime remains, When capture implementation is inspected, Then there is no v1-to-v2 adapter, fallback reader, or dual-write path.
  3. Given new migrations/models, When schema and code are inspected, Then no Coverage v2 ownership field uses tenant_id.
  4. Given raw provider payloads exist in evidence storage, When logs, OperationRun context/messages, notifications, and audit metadata are inspected, Then raw payloads, tokens, secrets, and PII are absent.

Requirements (mandatory)

Functional Requirements

  • FR-415-001: The system MUST keep Coverage v2 inactive for customer-facing and operator-facing proof surfaces in this spec.
  • FR-415-002: The system MUST create or reuse concrete Coverage v2 resource persistence for managed-environment resources, using workspace_id, managed_environment_id, and provider_connection_id for provider-sourced records.
  • FR-415-003: The system MUST create append-only Coverage v2 evidence persistence linked to concrete resource, workspace, managed environment, provider connection, OperationRun, source metadata, raw payload, normalized payload, payload hash, permission context, and capture timestamp.
  • FR-415-004: The system MUST use JSONB for raw payload, normalized payload, and permission/source metadata where persisted.
  • FR-415-005: The system MUST compute deterministic payload hashes from normalized payloads.
  • FR-415-006: The system MUST normalize payloads minimally: stable JSON key ordering, configured volatile-field handling only where explicit, source metadata separation, and no semantic compare/render/restore mapping.
  • FR-415-007: The system MUST resolve capture source contracts from the Coverage v2 registry and the repo's Graph contract path; it MUST NOT guess endpoints.
  • FR-415-008: All Microsoft Graph calls MUST go through GraphClientInterface; direct HTTP/SDK/quick endpoint calls outside the contract path are forbidden.
  • FR-415-009: The initial resource scope is limited to the Spec 414 resource types: deviceAndAppManagementAssignmentFilter, deviceEnrollmentLimitRestriction, deviceEnrollmentPlatformRestriction, deviceEnrollmentStatusPageWindows10, appProtectionPolicyAndroid, appProtectionPolicyiOS, notificationMessageTemplate, and roleScopeTag.
  • FR-415-010: The implementation MUST classify each initial resource type as captured, capture_blocked_missing_contract, capture_blocked_permission, capture_blocked_beta, capture_blocked_unsupported, or capture_failed.
  • FR-415-011: The implementation MUST prove every initial resource type has an explicit capture decision: each TCM-aligned type is either captured through an explicit contract or blocked with a clear missing-contract reason, the Graph v1 fallback type is captured or blocked with a clear contract reason, and the beta experimental type is blocked by default.
  • FR-415-012: Beta experimental capture MUST be blocked by default unless this spec is amended with explicit beta capture opt-in and safety tests.
  • FR-415-013: Missing contracts MUST produce capture_blocked_missing_contract without failure escalation or endpoint guessing.
  • FR-415-014: Unsupported/out-of-scope types MUST be skipped safely.
  • FR-415-015: Provider connection provenance MUST be same-scope: any stored provider_connection_id must belong to the same workspace_id and managed_environment_id as the resource/evidence row.
  • FR-415-016: External Microsoft tenant/directory/subscription/account IDs MUST be metadata only and MUST NOT become platform ownership keys.
  • FR-415-017: Capture start MUST enforce workspace membership, managed-environment entitlement, and capture capability server-side through Gate/Policy or existing capability resolver.
  • FR-415-018: The default capture capability is Capabilities::EVIDENCE_MANAGE unless implementation discovers a more specific existing repo-approved capture capability. Adding a new capability is allowed only with registry, role-map, and tests in this spec.
  • FR-415-019: Capture MUST create or reuse a canonical tenant_configuration.capture OperationRun for remote/provider-backed work.
  • FR-415-020: Remote/provider capture MUST execute asynchronously through a queued job.
  • FR-415-021: OperationRun status and outcome transitions MUST go through OperationRunService.
  • FR-415-022: OperationRun summary_counts MUST use flat numeric values and canonical keys from OperationSummaryKeys::all(). Default planned keys are total, processed, succeeded, skipped, failed, and errors_recorded.
  • FR-415-023: OperationRun context/messages, notifications, audit metadata, and logs MUST NOT include raw payloads, tokens, secrets, or PII.
  • FR-415-024: Permission context MUST be redacted before persistence.
  • FR-415-025: Capture MUST emit safe audit evidence for start/completion/failure attempts through the repo's existing AuditRecorder / AuditEventBuilder path, using stable action IDs tenant_configuration.capture.started, tenant_configuration.capture.completed, and tenant_configuration.capture.failed, including actor, workspace, managed environment, provider connection, OperationRun, resource type counts, and no raw payloads.
  • FR-415-026: No v1-to-v2 adapter, dual write, fallback reader, old snapshot promotion, legacy route, or old gap taxonomy may be introduced.
  • FR-415-027: No Filament Resource/Page, Blade view, route, navigation entry, customer report/review/evidence surface, or browser-visible Coverage v2 activation may be added in this spec.
  • FR-415-028: An implementation report MUST include the capture eligibility matrix for all initial resource types.

Non-Functional Requirements

  • NFR-415-001: Capture must fail safe under missing contracts, missing permissions, beta resources, provider errors, and cross-scope provider connections.
  • NFR-415-002: Tests must fake all Graph/TCM/provider calls. No test may call real Microsoft Graph or TCM.
  • NFR-415-003: Raw provider payloads may live only in evidence storage and must not leak into logs, audit metadata, OperationRun context/messages, or notifications.
  • NFR-415-004: New indexes must follow proven query paths only. JSONB GIN indexes are allowed only when the implementation adds a real query path.
  • NFR-415-005: The implementation must remain bounded to the initial Spec 414 resource set.
  • NFR-415-006: The queue and deployment impact must be documented: migrations and queue workers are expected; no asset or browser deployment change is expected.

Required Redaction Keys

At minimum, redaction must handle case-insensitive keys containing:

  • access_token
  • refresh_token
  • id_token
  • client_secret
  • secret
  • password
  • private_key
  • certificate
  • authorization
  • cookie
  • set-cookie
  • bearer

Key Entities (include if feature involves data)

  • Tenant Configuration Resource: Concrete Coverage v2 resource observed in one workspace/managed environment/provider connection. It carries resource type, source class, canonical identity key, latest evidence state, and timestamps.
  • Tenant Configuration Resource Evidence: Append-only payload evidence for a concrete Coverage v2 resource, linked to OperationRun and source metadata. It stores raw and normalized JSONB payloads, payload hash, redacted permission context, capture level/state, and captured timestamp.
  • Capture Outcome: Non-UI service result classifying each resource type attempt as captured, blocked, skipped, or failed with a v2 reason.
  • OperationRun: Execution truth for capture lifecycle, queue status, sanitized context, and numeric summary counts. It is not payload truth.

Success Criteria (mandatory)

  • SC-415-001: Focused tests prove concrete v2 resources and append-only evidence can be persisted for an eligible fake source response.
  • SC-415-002: Focused tests prove missing contract, beta default, unsupported, permission blocked, and failed capture outcomes are safe and use v2 vocabulary only.
  • SC-415-003: Focused tests prove Graph calls use GraphClientInterface and no direct endpoint bypass exists in the capture path.
  • SC-415-004: Focused tests prove same-scope provider_connection_id enforcement for resource/evidence writes.
  • SC-415-005: Focused tests prove no tenant_id ownership field is introduced in new Coverage v2 tables/models/migrations.
  • SC-415-006: Focused tests prove OperationRun creation/reuse, queued execution, service-owned transitions, numeric-only summary counts, and sanitized context.
  • SC-415-007: Focused tests prove non-member 404, missing environment entitlement 404, missing capability 403, readonly denial, and authorized capture start.
  • SC-415-008: Static/feature guards prove no v1 adapter, dual-write path, fallback reader, old snapshot promotion, old gap outcome vocabulary, or customer-facing v2 activation is introduced.
  • SC-415-009: Implementation report includes the resource-type capture eligibility matrix and no-browser decision.

Assumptions

  • Spec 414 is implemented and accepted as the inactive Coverage v2 kernel. Repo artifacts show completed tasks, implementation report, tests, and kernel models/services/migration.
  • tenant_configuration_resources and tenant_configuration_resource_evidence were deferred in Spec 414 and are expected to be added in Spec 415 unless implementation discovers equivalent repo-real tables.
  • The local Boost database schema output may not reflect all migrations; implementation should use repo migrations/code as source of truth unless the Sail/PostgreSQL lane is explicitly run.
  • Existing Graph contracts include some related Graph fallback/foundation types such as notificationMessageTemplate, roleScopeTag, and assignmentFilter, but exact source eligibility must be resolved by repo-real contract mapping rather than guessed endpoints.
  • No rendered UI surface is required for capture start in this spec. Tests may start capture through an internal service/action.

Risks

Risk Severity Mitigation
Capture becomes an activation/cutover spec High No UI, no customer proof, no v1 removal, no dual truth, stop-and-amend rule
Graph endpoints get guessed or hardcoded High Graph contract resolver + GraphClientInterface tests
Raw payloads/secrets leak High Redaction tests, OperationRun/audit/log context tests
Provider connection leaks across environments High Same-scope validation and tests
OperationRun lifecycle bypass High Use OperationRunService and existing guards
Summary counts drift into free-form keys Medium Use OperationSummaryKeys only; default existing keys
Capture tries to support too many types Medium Initial 414 resource types only; eligibility matrix
New tests become expensive Medium Unit/feature/pgsql only; fake Graph; no browser

Follow-up Spec Candidates

  • Spec 416 - Canonical Identity Engine.
  • Spec 417 - Coverage v2 Operator Surface.
  • Spec 418 - Legacy Coverage Cutover and Removal.
  • Spec 419 - Intune Core Comparable/Renderable Pack.
  • Spec 420 - Certified Intune Core Coverage Pack.
  • Spec 421 - Pilot Readiness Gate.

Open Questions

None blocking. Implementation must document any repo-real source contract mismatch in the eligibility matrix rather than guessing endpoints or broadening scope.