ADR-0008: Connector contract, deterministic mock M365, live Graph gating
Status: Accepted · 2026-07-14Decision
- Versioned
Connectorinterface per the reference architecture (as implemented inconnectors/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 separategetMetadata; post-execution verification is performed by the actions service re-reading the source throughgetLabel/getItemVersion(ADR-0010), not by a dedicatedverifyActionmethod. - 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 resyncand duplicate delivery for tests, and per-item content streams from fixture files. - GraphM365Connector: real endpoint shapes (
driveItemdelta,nextLink/deltaLinkcursors persisted opaquely — verbatim and currently unencrypted, see threat model T16 —Retry-Afterhandling, 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
Connectorcontract, because Graph label listing remains beta: thesensitivity_labelstable records provenance viacatalog_source(fixture|get_label_import|graph_beta|manual); the fixture seeder (fixtures/labels.ts) is the exercised path andGet-LabelCSV 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.