Skip to main content

ADR-0008: Connector contract, deterministic mock M365, live Graph gating

Status: Accepted · 2026-07-14

Decision

  • Versioned Connector interface per the reference architecture (as implemented in connectors/types.ts): probe / discoverScopes / inventoryPage(scope, cursor) / changes(scope, deltaCursor) / getPermissions / getLabel / getContent(bounded) / getItemVersion / previewLabelAction / executeLabelAction(idempotencyKey), returning canonical observations (external ID, source version/eTag + content version/cTag, change type, observed times, completeness). Item metadata arrives inside the inventory/changes observations rather than via a separate getMetadata; post-execution verification is performed by the actions service re-reading the source through getLabel/getItemVersion (ADR-0010), not by a dedicated verifyAction method.
  • MockM365Connector (default): deterministic fixture tenant (“Meridian Grove”) with two SharePoint sites + one OneDrive, paged inventory, scripted delta sequences (add/edit/rename/permission-change/label-change/delete), cursor semantics including simulated 410 resync and duplicate delivery for tests, and per-item content streams from fixture files.
  • GraphM365Connector: real endpoint shapes (driveItem delta, nextLink/ deltaLink cursors persisted opaquely — verbatim and currently unencrypted, see threat model T16 — Retry-After handling, permissions completeness marking). Live execution requires explicit config with a resolvable secret reference; it was subsequently validated read-only against the live Contoso CDX tenant (ADR-0013).
  • Label catalog sync is its own path, outside the Connector contract, because Graph label listing remains beta: the sensitivity_labels table records provenance via catalog_source (fixture | get_label_import | graph_beta | manual); the fixture seeder (fixtures/labels.ts) is the exercised path and Get-Label CSV import is the documented production path. Label identity is (msTenantId, labelGuid) only.

Consequences

  • Every connector-derived observation records acquisition identity and completeness; “no broad share observed” ≠ “no broad share exists.”
  • Teams/Exchange get contracts + capability notes + backlog entries, no fake depth.