TenantAtlas/specs/426-exchange-teams-core-evidence-identity-readiness/plan.md
ahmido f7d06621a0 feat: implement Exchange Teams evidence identity readiness (#493)
Automated PR for spec 426 exchange teams core evidence identity readiness. Includes service changes and coverage/requirement/spec updates from commit fb4dc20c.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #493
2026-07-03 11:43:11 +00:00

30 KiB

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 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)

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:

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.