TenantAtlas/specs/426-exchange-teams-core-evidence-identity-readiness/implementation-report.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

10 KiB

Implementation Report: Spec 426 - Exchange / Teams Core Evidence & Stable Identity Readiness

Branch: 426-exchange-teams-core-evidence-identity-readiness
HEAD: 33e496c1 feat: complete spec 425 enta certified compare pack (#492)
Implementation date: 2026-07-02
Result: PASS WITH CONDITIONS for Spec 426 closure; FAIL-safe for source-backed evidence readiness

Gate Result

  • Activated skills/gates: pest-testing, Spec Readiness Gate, provider-freshness semantics, and TCM cutover guard for the post-review fix. Earlier implementation work also used workspace/RBAC/OperationRun/evidence/customer-output/Product Surface gates.
  • Closure gate: PASS WITH CONDITIONS.
  • Condition: Spec 426 proves fail-safe behavior for Exchange/Teams source-backed evidence. It does not prove readiness, capture support, compare support, render support, or certification. Typed normalizer/hash tests are future-contract helper proof only.
  • Source-backed evidence readiness gate: FAIL-safe/blocked because no verified production-safe source contract exists for the four mandatory types.
  • Completed dependency specs 414, 415, 417, 418, 419, 420, 422, and 425 remain read-only context. No completed spec artifacts were rewritten.
  • Review correction: removed unverified Graph v1.0 endpoint claims for mailFlowRule, acceptedDomains, teamsAppPermissionPolicy, and teamsMeetingPolicy.
  • Final dirty state: runtime service/config/test changes plus active Spec 426 artifacts, as expected for this active spec.

Files Changed

  • Source contracts and capture:
    • apps/platform/app/Services/TenantConfiguration/CoverageSourceContractResolver.php
    • apps/platform/app/Services/TenantConfiguration/GenericContentEvidenceCaptureService.php
    • apps/platform/config/graph_contracts.php was verified to contain no unverified final Spec 426 contract entries; it has no final diff in this correction.
  • Stable identity:
    • apps/platform/app/Services/TenantConfiguration/CoverageIdentityStrategyRegistry.php
  • Tests:
    • Focused Spec 426 unit and feature tests under apps/platform/tests/Unit/Support/TenantConfiguration/ and apps/platform/tests/Feature/TenantConfiguration/
    • Updated Spec 417/420 expectations so the four Exchange/Teams types remain fail-closed until verified contracts exist
  • Spec artifacts:
    • spec.md, plan.md, tasks.md, this implementation report

Source Contract Matrix

Type Contract key Endpoint Source class Outcome
transportRule none none none capture_blocked_missing_contract
acceptedDomain none none none capture_blocked_missing_contract
appPermissionPolicy none none none capture_blocked_missing_contract
meetingPolicy none none none capture_blocked_missing_contract

No endpoint guessing, direct HTTP, runtime documentation lookup, provider bypass, or guessed Microsoft Graph source contract remains. Capture attempts stop before ProviderGateway / GraphClientInterface calls for these four types.

Evidence Matrix

Type Capture outcome Provider call Resource row Evidence row Empty/fake behavior
transportRule capture_blocked_missing_contract no no no no fake resource/evidence
acceptedDomain capture_blocked_missing_contract no no no no fake resource/evidence
appPermissionPolicy capture_blocked_missing_contract no no no no fake resource/evidence
meetingPolicy capture_blocked_missing_contract no no no no fake resource/evidence

OperationRun summaries remain flat numeric counts. Blocked runs record sanitized blocked outcomes only; no raw payload, provider response body, secret, mail content, Teams content, or raw permission context is placed in run context or audit metadata.

Identity Matrix

Type Strategy Stable identity inputs Explicitly rejected
transportRule tcm.exchange.transport_rule.v1 id, sourceId, Guid, RuleId Identity, display/name fields, order, payload hash
acceptedDomain tcm.exchange.accepted_domain.v1 id, sourceId, DomainName, domainName Identity, display/name fields, domain type/default flag
appPermissionPolicy tcm.teams.app_permission_policy.v1 id, sourceId, policyId Identity, display/name fields, settings/app hash
meetingPolicy tcm.teams.meeting_policy.v1 id, sourceId, policyId Identity, display/name fields, settings hash

CanonicalIdentityResolver remains the only identity path. Identity-only payloads resolve to missing_external_id, not stable identity.

Readiness Matrix

Type content_backed identity_strategy_hardened compare_render_ready certified restore_ready customer_claimable
transportRule no yes no no no no
acceptedDomain no yes no no no no
appPermissionPolicy no yes no no no no
meetingPolicy no yes no no no no

Typed normalizer/hash/redaction tests remain as helper proof for future valid source payloads. They are not used to claim source-backed evidence or certification readiness. Post-review coverage now also proves that typed helper output keeps stable source identity fields (Guid, RuleId, DomainName, policyId, sourceId), that the future typed capture handoff preserves that type-specific source_identity, that contract-level volatile fields are excluded from typed unsupported diagnostics/material hashes, and that payload hashes ignore volatile-field diagnostics.

Claim Guard And Redaction

  • Certified, restore-ready, full Exchange/Teams/Microsoft 365, and customer-ready claims remain blocked.
  • Internal compare/render wording remains bounded by Claim Guard, but this report does not claim source-backed compare/render readiness for the four mandatory types.
  • Redaction tests cover provider secrets, tokens, raw provider markers, mail subject/body-like fields, and Teams recording/transcript-like fields in normalized/helper output.

Product Surface / Filament Contract

  • No runtime UI files, routes, navigation, Filament resources/pages/widgets, actions, reports, exports, or customer outputs were changed.
  • Product Surface decision: N/A - no rendered UI surface changed.
  • Product Surface exceptions: none.
  • Browser proof: N/A - no rendered UI surface changed.
  • Human Product Sanity: N/A - no rendered UI surface changed.
  • Livewire v4 compliance: unchanged; Filament v5 remains on Livewire v4.
  • Provider registration: unchanged; Laravel provider registration remains in apps/platform/bootstrap/providers.php.
  • Global search: unchanged; no resource/global search behavior was added.
  • Destructive/high-impact actions: none added.
  • Asset strategy: no new assets; no new filament:assets deployment requirement.

Deployment Impact

  • Migrations: none.
  • Environment variables: none.
  • Queues/cron: no new workers or schedules; existing OperationRun-backed capture job reused.
  • Storage/volumes: none.
  • Assets: none.
  • Runtime config: no new Exchange/Teams graph contract entries remain; deploy through the normal container/config-cache path.
  • Staging/Production: do not promote Exchange/Teams certification from this branch. Next sequence is Spec 427 verified source contract enablement, Spec 428 content-backed evidence promotion, Spec 429 compare/render promotion, and only later certification. A future verified provider contract must pass staging before evidence promotion or certification proceeds.

Validation

Passed after post-review fix and closure review:

  • cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec426
    • terminated with Signal 9 in the container runner.
    • Not a closure blocker because the equivalent direct file runs below passed.
  • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/TenantConfiguration/Spec426ExchangeTeamsSourceContractResolverTest.php tests/Unit/Support/TenantConfiguration/Spec426ExchangeTeamsCanonicalIdentityTest.php
    • 22 passed, 124 assertions.
  • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/TenantConfiguration/Spec426ExchangeTeamsPayloadNormalizationFromSourceTest.php tests/Unit/Support/TenantConfiguration/Spec426ExchangeTeamsEvidenceHashTest.php tests/Unit/Support/TenantConfiguration/Spec426ExchangeTeamsClaimGuardReadinessTest.php tests/Unit/Support/TenantConfiguration/Spec426ExchangeTeamsRedactionTest.php
    • 24 passed, 77 assertions.
  • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantConfiguration/Spec426ExchangeTeamsCoreEvidenceReadinessTest.php tests/Feature/TenantConfiguration/Spec426ExchangeTeamsStableIdentityReadinessTest.php
    • 3 passed, 69 assertions.
  • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantConfiguration/Spec426ExchangeTeamsProviderScopeTest.php tests/Feature/TenantConfiguration/Spec426ExchangeTeamsNoCertificationTest.php tests/Feature/TenantConfiguration/Spec426ExchangeTeamsNoRestoreTest.php tests/Feature/TenantConfiguration/Spec426ExchangeTeamsNoTenantIdTest.php tests/Feature/TenantConfiguration/Spec426ExchangeTeamsNoMiniPlatformTest.php tests/Feature/TenantConfiguration/Spec426ExchangeTeamsClaimGuardFeatureTest.php
    • 7 passed, 55 assertions.
  • Direct file Spec 426 total:
    • 56 passed, 325 assertions.
  • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantConfiguration/Spec420M365GenericEvidenceCaptureTest.php tests/Feature/TenantConfiguration/Spec420M365CaptureOperationRunTest.php tests/Unit/Support/TenantConfiguration/Spec420M365CaptureSourceContractResolverTest.php tests/Unit/Support/TenantConfiguration/Spec420M365CaptureEligibilityTest.php tests/Unit/Support/TenantConfiguration/Spec417CoverageIdentityStrategyRegistryTest.php
    • 16 passed, 259 assertions.
  • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec420M365GenericEvidenceOperatorSurfaceSmokeTest.php
    • 1 passed, 44 assertions.
  • cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
    • passed.
  • git diff --check
    • passed.

Spec 426 browser validation remains N/A - no rendered UI surface changed; the Spec 420 browser regression fixture changed and passed.