# Implementation Plan: Spec 426 - Exchange / Teams Core Evidence & Stable Identity Readiness **Branch**: `426-exchange-teams-core-evidence-identity-readiness` | **Date**: 2026-07-02 | **Spec**: [spec.md](./spec.md) **Input**: Feature specification from `specs/426-exchange-teams-core-evidence-identity-readiness/spec.md` ## Summary Prepare Exchange/Teams core evidence and stable identity readiness for later certification without overclaiming source support. Post-review correction found that the initially proposed Graph v1.0 endpoints for `transportRule`, `acceptedDomain`, `appPermissionPolicy`, and `meetingPolicy` are not production-safe source contracts. The implementation must therefore keep those four types fail-closed as missing contracts, prove no provider call/resource/evidence is created for blocked capture, and harden identity strategies for future valid source payloads. The work remains a prerequisite unblocker only. It must not certify Exchange/Teams, introduce restore/apply, activate customer claims, add routes/navigation/dashboards, create Exchange/Teams table families, or introduce `tenant_id`. ## Post-Review Correction - Remove unverified `mailFlowRule`, `acceptedDomains`, `teamsAppPermissionPolicy`, and `teamsMeetingPolicy` Graph contract entries. - Keep `transportRule`, `acceptedDomain`, `appPermissionPolicy`, and `meetingPolicy` blocked as `capture_blocked_missing_contract` until a verified repo-canonical provider contract exists. - Preserve typed normalization/hash/redaction tests as helper proof only; do not claim source-backed evidence or compare/render readiness from fixtures. - Harden identity strategies so `Identity`/display-name-like values do not become stable identity. - Final readiness gate for source-backed evidence is `FAIL` by design; no certification follow-up may proceed from this branch. ## Technical Context **Language/Version**: PHP 8.4, Laravel 12, Filament v5, Livewire v4 **Primary Dependencies**: Existing Coverage v2 Tenant Configuration services: `CoverageSourceContractResolver`, `GraphContractRegistry`, `ProviderGateway`, `GraphClientInterface`, `GenericContentEvidenceCaptureService`, `CoverageResourceUpserter`, `CoverageEvidenceWriter`, `CoverageIdentityStrategyRegistry`, `CanonicalIdentityResolver`, `ExchangeTeamsComparablePayloadNormalizer`, `ExchangeTeamsCoverageComparator`, `ExchangeTeamsRenderableSummaryBuilder`, `ClaimGuard`, `OperationRunService` **Storage**: PostgreSQL through existing Coverage v2 resource/evidence/supported-scope tables; no new table planned; readiness labels are derived report assertions over existing states, not new persisted booleans/statuses **Testing**: Pest 4, PHPUnit 12, focused Unit/Feature; Browser only if UI changes **Validation Lanes**: fast-feedback for unit/feature; browser conditional; Pint dirty; diff check **Target Platform**: Laravel Sail locally, Dokploy container deployment **Project Type**: Laravel web monolith under `apps/platform` **Performance Goals**: Capture remains bounded to four selected resource types, remote work is OperationRun-backed, and compare/render readiness is deterministic over persisted evidence **Constraints**: no endpoint guessing, no direct HTTP, no provider bypass, no certification, no restore/apply, no customer output, no new route/navigation/dashboard, no `tenant_id`, no v1 compatibility, no completed-spec rewrites **Scale/Scope**: exactly four mandatory resource types; no optional Exchange/Teams/M365 expansion ## Preparation Preflight Result - Current branch before Spec Kit creation: `platform-dev`. - Current branch after Spec Kit creation: `426-exchange-teams-core-evidence-identity-readiness`. - Current HEAD before creation: `33e496c1 feat: complete spec 425 enta certified compare pack (#492)`. - Initial dirty state: clean. - Existing `426-*` spec/branch check: no existing local branch or spec package found before creation. - Auto-prep queue: `docs/product/spec-candidates.md` currently says no safe automatic next-best-prep target remains. This package is a direct manual promotion from the user-provided candidate. - Related completed/read-only dependency specs: 414, 415, 417, 418, 419, 420, 422, and 425. - Source contract gaps confirmed during preparation before implementation: - `transportRule`: no explicit mapping in `CoverageSourceContractResolver`. - `acceptedDomain`: was explicitly blocked as `missing_source_contract_mapping` before Spec 426 implementation. - `appPermissionPolicy`: was explicitly blocked as `missing_source_contract_mapping` before Spec 426 implementation. - `meetingPolicy`: no explicit mapping in `CoverageSourceContractResolver`. - Identity strategy gaps confirmed during preparation before implementation: - No `CoverageIdentityStrategyRegistry` stable strategy for `transportRule`. - No stable strategy for `acceptedDomain`. - No stable strategy for `appPermissionPolicy`. - No stable strategy for `meetingPolicy`. - Current compare/render evidence: - `ExchangeTeamsComparablePayloadNormalizer`, `ExchangeTeamsCoverageComparator`, and `ExchangeTeamsRenderableSummaryBuilder` support the four resource types. - Spec 422 proof is compare/render for content-backed existing/synthetic rows, not live/source-backed capture proof. - Current capture architecture: - `GenericContentEvidenceCaptureService` uses `ProviderGateway::listPolicies()` through the repo provider abstraction. - `CoverageEvidenceWriter` persists raw payload, normalized payload, payload hash, OperationRun link, source metadata, and content-backed evidence state. - `CoverageResourceUpserter` uses `CanonicalIdentityResolver`. - Implementation must align source-backed Exchange/Teams payloads with the typed Spec 422 normalizer before claiming compare/render readiness. - Current enum/vocabulary alignment: - Use repo-canonical values such as `capture_blocked_missing_contract`, `capture_blocked_permission`, `capture_blocked_beta`, `capture_blocked_unsupported`, `capture_failed`, `content_backed`, `stable`, `derived`, `identity_conflict`, `missing_external_id`, and `unsupported_identity`. - Do not introduce parallel wording such as `capture_blocked_unsupported_source` unless the enum/status family is deliberately amended with tests and proportionality review. ## UI / Surface Guardrail Plan - **Guardrail scope**: no operator-facing surface change by default. - **Affected routes/pages/actions/states/navigation/panel/provider surfaces**: none by default. Existing Coverage v2 readiness/operator surface only if implementation amends artifacts first. - **No-impact class, if applicable**: service/config/test-only. - **Native vs custom classification summary**: N/A - no UI change. - **Shared-family relevance**: evidence capture, identity, source contracts, claim safety, redaction, compare/render readiness. - **State layers in scope**: none in UI; service/evidence state only. - **Audience modes in scope**: internal/operator proof only; no customer/read-only output. - **Decision/diagnostic/raw hierarchy plan**: evidence and readiness proof remain implementation-report/test proof; raw/support details never default-render. - **Raw/support gating plan**: raw payloads, raw provider responses, source keys, OperationRun internals, provider diagnostics, and permission context stay hidden from default UI and excluded from customer output. - **One-primary-action / duplicate-truth control**: no new action. - **Handling modes by drift class or surface**: runtime UI changes require spec/plan/tasks amendment, Product Surface completion, focused browser proof, and Human Product Sanity. New route/navigation/customer/restore/certify scope is a hard stop. - **Repository-signal treatment**: review-mandatory for evidence/status presentation only if UI is amended; hard-stop for customer output, restore/apply, certification, or mini-platform drift. - **Special surface test profiles**: N/A by default; existing Coverage v2 Technical Annex browser smoke only if UI changes. - **Required tests or manual smoke**: focused Unit/Feature always; Browser conditional. - **Exception path and spread control**: none. - **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage. - **UI/Productization coverage decision**: `N/A - no rendered UI surface changed` by default. - **Coverage artifacts to update**: none unless implementation amends runtime UI scope. - **No-impact rationale**: Missing-contract blockers, identity hardening, no-fake-evidence behavior, and no-overclaim guards can be proven by existing shared services and tests without rendered UI changes. - **Navigation / Filament provider-panel handling**: no panel, provider registration, route, or navigation change. - **Screenshot or page-report need**: none unless runtime UI is amended into scope. ## Product Surface Contract Plan - **Product Surface Contract reference**: `docs/product/standards/product-surface-contract.md`. - **No-legacy posture**: canonical Coverage v2 extension; no compatibility exception. - **Page archetype and surface budget plan**: N/A by default. If amended into existing UI, classify as Technical Annex and preserve existing surface budgets. - **Technical Annex and deep-link demotion plan**: OperationRun, evidence IDs, source endpoints, source keys, raw payloads, permission context, provider diagnostics, unsupported internals, and raw compare values remain hidden/collapsed/internal-only. - **Canonical status vocabulary plan**: N/A by default. If rendered, product-facing labels map to canonical vocabulary and never say certified, restore-ready, customer-ready, full Exchange, full Teams, or M365 certified. - **Product Surface exceptions**: none. - **Browser verification plan**: `N/A - no rendered UI surface changed` unless UI files change; otherwise focused existing Coverage v2 route smoke. - **Human Product Sanity plan**: N/A unless UI changes. - **Visible complexity outcome target**: neutral by default. - **Implementation report target**: `specs/426-exchange-teams-core-evidence-identity-readiness/implementation-report.md`. ## Filament / Livewire / Deployment Posture - **Livewire v4 compliance**: unchanged; platform remains Filament v5 on Livewire v4. Must be stated in close-out. - **Panel provider registration location**: no panel change planned. Laravel 12 provider registration remains `apps/platform/bootstrap/providers.php`. - **Global search posture**: no Resource/global search change planned. - **Destructive/high-impact action posture**: none. No restore/apply/certify/start action may be introduced. Existing capture workflow may be reused only if already authorized and OperationRun-backed. - **Asset strategy**: no new assets planned. `filament:assets` is not newly required unless implementation unexpectedly registers assets, which would require spec amendment. - **Testing plan**: Unit/Feature for source contracts, capture eligibility, evidence persistence, identity, normalization/hash, claim guard, redaction, no certification/restore/customer/tenant_id/mini-platform; Browser only if UI changes. - **Deployment impact**: no env vars, migrations, queues, scheduler, storage, or assets expected. If graph contracts/resource defaults change, existing deployment/sync steps must be documented in the implementation report. ## Shared Pattern & System Fit - **Cross-cutting feature marker**: yes. - **Systems touched**: Coverage v2 resource type registry, source contract resolver, graph contract config, provider gateway, generic capture, resource upsert/evidence write, identity strategy registry/resolver, Exchange/Teams typed normalizer/comparator/summary builder, Claim Guard, redaction, operation capture tests. - **Shared abstractions reused**: `CoverageSourceContractResolver`, `GraphContractRegistry`, `ProviderGateway`, `GraphClientInterface`, `GenericContentEvidenceCaptureService`, `CoverageResourceUpserter`, `CoverageEvidenceWriter`, `CoverageIdentityStrategyRegistry`, `CanonicalIdentityResolver`, `ExchangeTeamsComparablePayloadNormalizer`, `ExchangeTeamsCoverageComparator`, `ExchangeTeamsRenderableSummaryBuilder`, `ClaimGuard`, `OperationRunService`. - **New abstraction introduced? why?**: none expected. A small adapter for typed normalization during capture is allowed only if the existing generic normalizer cannot safely persist deterministic Spec 422-compatible payloads. - **Why the existing abstraction was sufficient or insufficient**: Existing Coverage v2 paths provide scope, evidence, identity, and claim safety. They lack the exact four source contracts, identity strategies, and source-backed typed normalization alignment required for later certification. - **Bounded deviation / spread control**: Exchange/Teams-specific logic must remain bounded to typed helpers/contract mappings inside the Tenant Configuration service boundary. No Exchange/Teams platform or generic provider framework. ## OperationRun UX Impact - **Touches OperationRun start/completion/link UX?**: no new UX. - **Central contract reused**: existing OperationRun-backed capture path only. - **Delegated UX behaviors**: N/A - no new start surface. - **Surface-owned behavior kept local**: none. - **Queued DB-notification policy**: no new policy. - **Terminal notification path**: existing central lifecycle mechanism only. - **Exception path**: none. Remote/provider capture must continue to use existing OperationRun service-owned lifecycle and sanitized summary counts. No new operation type is required unless implementation proves the existing `tenant_configuration.capture` cannot represent the capture safely; that would require spec amendment. ## Provider Boundary & Portability Fit - **Shared provider/platform boundary touched?**: yes. - **Provider-owned seams**: Exchange/Teams source contracts, Microsoft Graph/TCM source payload fields, provider IDs/natural keys, provider permission metadata. - **Platform-core seams**: Coverage v2 evidence state, capture outcome, identity state, coverage level, claim state, payload hash, workspace/managed-environment/provider scope. - **Neutral platform terms / contracts preserved**: resource type, evidence, identity, source contract, provider connection, managed environment, claim, compare/render readiness. - **Retained provider-specific semantics and why**: `transportRule`, `acceptedDomain`, `appPermissionPolicy`, and `meetingPolicy` are Microsoft 365 resource semantics required by the exact denominator. - **Bounded extraction or follow-up path**: document-in-feature. Spec 427 should verify/enable production-safe source contracts for the four mandatory Exchange/Teams types or keep each type explicitly blocked. Spec 428 should promote content-backed evidence only after verified contracts exist. Spec 429 should promote compare/render only after source-backed evidence exists. Certification remains a later separate spec. ## Constitution Check - Inventory-first / evidence truth: FAIL-safe. This branch does not capture observed Exchange/Teams provider configuration evidence because verified source contracts are missing; blocked outcomes prevent fake evidence. - Read/write separation: PASS with controls. No provider write, restore, apply, destructive UI action, or fake internal evidence write is introduced. - Graph contract path: FAIL-safe. No unverified contracts are added to `config/graph_contracts.php`; future source contracts must use `GraphClientInterface`/provider gateway only. - Deterministic capabilities: PASS. Readiness criteria and claim blockers are testable. - RBAC-UX: PASS with implementation requirement. Non-member/wrong scope is 404; member missing capability is 403; readonly cannot start capture. - Workspace isolation: PASS with implementation requirement. Same workspace/managed environment/provider connection is required. - Tenant isolation: PASS in current repo vocabulary; no `tenant_id` ownership truth. - Run observability: PASS. Blocked capture is OperationRun-backed and records sanitized missing-contract outcomes; readiness evaluation is DB/service-only. - OperationRun start UX: N/A unless existing start workflow is reused; no new start surface. - Data minimization: PASS. No raw Exchange/Teams provider payload is captured while contracts are missing; future raw payloads must remain evidence-only and never default-rendered/logged/customer-published. - Test governance: PASS. Unit/Feature lane is sufficient unless UI changes. - Proportionality: PASS. Four concrete source/identity gaps justify narrow missing-contract guards, identity strategies, and helper tests. - No premature abstraction: PASS only if implementation avoids a generic Exchange/Teams framework. - Persisted truth: PASS. Uses existing evidence/resource tables. - Behavioral state: PASS if existing enum/status families are reused. - UI semantics: PASS by no-UI default. - Shared pattern first: PASS. Existing Coverage v2 services are the path. - Provider boundary: PASS with provider-specific fields bounded to contracts/typed adapters. - V1 explicitness / few layers: PASS. Explicit four-type implementation only. - Spec discipline / bloat check: PASS. Certification, restore, customer output, and optional types are split out. - Filament-native UI: N/A unless existing UI changes. - Product Surface Contract: PASS with no-rendered-surface rationale. ## Test Governance Check - **Test purpose / classification by changed surface**: Unit for resolver, eligibility, identity, normalization, hash, Claim Guard, redaction. Feature for blocked capture with no fake DB evidence, OperationRun, provider scope, authorization, no certification/restore/customer/tenant_id/mini-platform. Browser only if UI changes. - **Affected validation lanes**: fast-feedback; browser conditional. - **Why this lane mix is the narrowest sufficient proof**: Missing-contract decisions, identity hardening, no-fake-evidence behavior, and claim safety are deterministic service/DB behavior. Browser proof is only meaningful when rendered UI changes. - **Narrowest proving command(s)**: - `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=ExchangeTeamsSourceContractResolverTest` - `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=ExchangeTeamsIdentityStrategyRegistryTest` - `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec426ExchangeTeamsCoreEvidenceReadinessTest` - `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec426ExchangeTeamsStableIdentityReadinessTest` - `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec426ExchangeTeamsClaimGuardFeatureTest` - **Fixture / helper / factory / seed / context cost risks**: Add minimal fake provider payloads for four resource types; avoid full workspace/provider setup defaults outside feature tests. - **Expensive defaults or shared helper growth introduced?**: no. - **Heavy-family additions, promotions, or visibility changes**: none unless UI changes. - **Surface-class relief / special coverage rule**: `N/A - no rendered UI surface changed` by default. - **Closing validation and reviewer handoff**: verify missing-contract blockers, no fake evidence persistence, stable identity strategy hardening, no compare/render overclaim, claim blocking, redaction, no restore/customer/tenant_id/mini-platform. - **Budget / baseline / trend follow-up**: none expected. - **Review-stop questions**: Did any type rely on beta-only source, display-name identity, fake evidence, direct HTTP, endpoint guessing, customer claim, restore path, or `tenant_id`? If yes, fail or split. - **Escalation path**: reject-or-split for certification/restore/customer/mini-platform scope; document-in-feature for bounded source/identity limitations. - **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage. - **Why no dedicated follow-up spec is needed**: This is the dedicated fail-safe readiness unblocker. Source-contract verification, content-backed evidence promotion, compare/render promotion, and certification are intentionally split into later specs. ## Risk Controls And Rollout Considerations - **Rollout shape**: Service/config/test-only by default. No migration, env var, route, navigation, asset, queue, scheduler, storage, or customer-output rollout is planned. - **Staging gate**: Later implementation must validate source contracts, capture outcomes, redaction, provider scope, and no-certification/no-restore/no-customer claims on staging before production promotion. - **Provider-contract risk control**: New source contracts must be explicit registry entries with source class, source version/schema metadata where available, permission metadata where supported, and fake-provider tests. Runtime endpoint guessing is a stop condition. - **Evidence integrity risk control**: Missing contract, missing permission, unsupported source, beta-only source, unavailable source, and provider failure must remain blocked/failed states, not empty evidence. - **Identity risk control**: Any type that cannot produce stable source-backed identity fails readiness instead of falling back to display-name, order, payload-hash, operation-run, or generated identity. - **Claim risk control**: Claim Guard must keep certification, restore-ready, full workload/M365, and customer-ready wording blocked until a later spec. - **Operational risk control**: OperationRun summaries remain numeric-only and sanitized; compare/render readiness evaluation must not call the provider. - **Rollback/forward note**: Because no schema or customer surface is planned, rollback is reverting the source/identity/normalization code and tests. If implementation discovers schema or UI changes are necessary, artifacts must be amended before proceeding. ## Project Structure ### Documentation (this feature) ```text specs/426-exchange-teams-core-evidence-identity-readiness/ ├── checklists/ │ └── requirements.md ├── plan.md ├── spec.md └── tasks.md ``` ### Source Code (repository root) Likely affected runtime/test paths for later implementation: ```text apps/platform/config/ └── graph_contracts.php apps/platform/app/Services/TenantConfiguration/ ├── CoverageSourceContractResolver.php ├── CoverageIdentityStrategyRegistry.php ├── GenericContentEvidenceCaptureService.php # only if typed capture normalization hook is needed ├── GenericPayloadNormalizer.php # only if deterministic collection/hash behavior must be generalized ├── CoverageEvidenceWriter.php # only if typed normalized payload promotion requires writer support ├── ExchangeTeamsComparablePayloadNormalizer.php ├── ExchangeTeamsCoverageComparator.php ├── ExchangeTeamsRenderableSummaryBuilder.php └── ClaimGuard.php apps/platform/tests/Unit/Support/TenantConfiguration/ └── ExchangeTeams*.php apps/platform/tests/Feature/TenantConfiguration/ └── Spec426ExchangeTeams*.php apps/platform/tests/Fixtures/TenantConfiguration/Spec426/ └── exchange-teams/ apps/platform/tests/Browser/ └── Spec426ExchangeTeamsCoreEvidenceReadinessSmokeTest.php # only if UI changes ``` **Structure Decision**: Use existing TenantConfiguration/Coverage v2 service and test directories. Do not create new base folders, migrations, routes, Filament resources/pages/widgets, commands, jobs, dashboards, reports, exports, PDFs, or customer-output surfaces. ## Complexity Tracking | Violation | Why Needed | Simpler Alternative Rejected Because | |---|---|---| | Fail-closed source contract blockers | Later certification needs real source-backed capture for the exact denominator, but no verified contracts exist yet | Registering guessed Graph endpoints would allow fake certification readiness | | Four stable identity strategies | Stable canonical identity is required to compare, track, and later certify resource instances | Display-name or payload-hash identity is unstable and unsafe | | Typed source normalization alignment | Source-backed payloads must enter the existing Spec 422 compare/render pipeline deterministically | Generic raw-payload hashing alone does not prove comparable/renderable shape | ## Proportionality Review - **Current operator problem**: Exchange/Teams certification remains blocked because the denominator lacks source-backed evidence and stable identity. - **Existing structure is insufficient because**: Current source resolver and identity registry do not cover the four mandatory types; Spec 422 does not prove live/source-backed capture. - **Narrowest correct implementation**: Keep missing source contracts blocked, remove unverified mappings, extend identity/normalization tests for exactly four concrete types, and document the source blocker. - **Ownership cost created**: Four identity strategies and focused tests must track future provider contract changes. - **Alternative intentionally rejected**: Certify based on row-level compare/render support or display names. That would weaken evidence integrity and create unsafe claims. - **Release truth**: Current-release prerequisite for later source-contract verification, evidence promotion, compare/render promotion, and eventual certification. ## Technical Approach ### Phase 0 - Hard Preflight - Confirm branch, HEAD, dirty state, active spec path, and activated skills/gates. - Confirm completed dependency specs are read-only context. - Re-check current source contract and identity gaps. - Confirm Coverage v2 capture/identity/evidence infrastructure exists. - Stop if generic capture or canonical identity infrastructure is missing. ### Phase 1 - Source Contract Gap Map - Inspect `CoverageSourceContractResolver`, `config/graph_contracts.php`, `GraphContractRegistry`, `ProviderGateway`, and `GraphClientInterface` patterns. - Record current resolver state for `transportRule`, `acceptedDomain`, `appPermissionPolicy`, and `meetingPolicy`. - Determine source class, contract key, production-safety, permission metadata, response shape, volatile fields, and empty collection semantics. - Identify whether any type is beta/experimental-only; if yes, mark certification readiness blocked. ### Phase 2 - Block Unverified Source Contracts - Do not add resolver mappings or contract definitions for the four mandatory types until verified source contracts exist. - Prove blocked capture makes no `ProviderGateway`/`GraphClientInterface` calls. - Add contract tests proving no endpoint guessing, no direct HTTP, and missing-contract fail-closed behavior. - Preserve missing-permission and unsupported-source outcomes. ### Phase 3 - Block Fake Content-Backed Evidence - Route all four types through existing generic/shared capture path until the source contract decision blocks them. - Persist no resource rows or evidence rows while contracts are missing. - Preserve typed helper payload normalization for future valid source payloads, without claiming readiness/hash proof from blocked capture. - Represent empty successful collections only as safe source-contract capture proof unless an existing repo-approved type-level evidence artifact can carry an explicit empty normalized payload/hash; do not create fake resource instances. - Prevent fake/synthetic evidence from counting as source-backed. ### Phase 4 - Stable Identity - Add identity strategies for the four mandatory types. - Require stable provider/source ID or proven immutable natural key/composite. - Reject display-name-only, array-index, priority/order, payload-hash, random UUID, and operation-run identity. - Use `CanonicalIdentityResolver` and block identity conflicts. ### Phase 5 - Normalization And Compare/Render Helper Proof - Align helper payload fixtures with `ExchangeTeamsComparablePayloadNormalizer`, `ExchangeTeamsCoverageComparator`, and `ExchangeTeamsRenderableSummaryBuilder` so future real source-backed payloads have a bounded path. - Preserve material fields, exclude volatile fields, and record unsupported fields diagnostically. - Mark readiness as compare/render-ready only when source-backed evidence and stable identity both exist; this branch does not satisfy that gate. - Do not assign certified coverage. ### Phase 6 - Claim Guard / Safety - Allow internal evidence-ready and stable-identity-ready wording only when proven. - Block certification, restore-ready, full Exchange/Teams/M365, and customer-ready claims. - Add redaction tests for secrets, tokens, cookies, authorization headers, raw payloads, raw permission context, mail content, and Teams content. ### Phase 7 - Product Surface Decision - Confirm no runtime UI change. - If implementation proves UI is needed, stop, amend spec/plan/tasks with exact affected surfaces, then run Product Surface/browser/Human Product Sanity proof. - Do not add route, navigation, dashboard, certify action, restore action, report, customer output, Review Pack, export, or PDF. ### Phase 8 - Validation - Run Pint dirty. - Run focused unit tests. - Run focused feature tests. - Run browser test only if UI changed. - Run `git diff --check`. - Document exact validation results in implementation report. ### Phase 9 - Implementation Report - Produce required matrices and final candidate gate result. - Record no certification, no restore, no customer claim, no `tenant_id`, no mini-platform, and Product Surface no-impact proof. ## Stop Conditions - Any mandatory type lacks source contract support and is treated as source-backed or compare/render-ready. - Any mandatory type lacks stable source-backed identity. - Any type is beta/experimental-only but treated as certification-ready. - Synthetic/fake evidence is counted as source-backed. - Display name, order, payload hash, or operation run ID is used as stable identity. - Capture bypasses provider gateway/GraphClientInterface or guesses endpoints. - Certification, restore/apply, customer output, full workload/M365 claim, new route/navigation/dashboard, or mini-platform appears. - `tenant_id` is introduced as platform-core ownership truth or compatibility/fallback path. - Raw payload, secrets, mail content, Teams content, or raw permission context leak into logs/UI/output. - Tests cannot prove evidence + identity readiness.