synology_apm_repo.sdk.units.saas.contact module¶
ContactProvider: M365/GWS Contact via contact_table,
built as a SaasWorkloadProvider + SyntheticGroupedTree config.
An empty contact_table (a tenant with zero contacts) is a legitimate
state, not a gap — ContactProvider still constructs successfully and
finds a real, empty table.
The two platforms differ enough that they aren’t one shared code path:
M365 (
contact_tablehasparent_folder_id— a real, single-parent folder hierarchy resolved to names via_m365_contact_folder_names): metadata JSON is{"version":"1.0","client_metadata":{...Graph API contact fields, camelCase...},"contact_type":"Contact"}; no photo concept at all. Exported as CSV — the only portable format M365 Contact has (no vCard, no PST-equivalent); seebuild_contact_csv.GWS (
contact_tablehas no folder column — contacts instead belong to zero or more groups, an M:N relationship, not a hierarchy): metadata JSON is{"version":"2.0","client_metadata":{...People API Person fields...},"photo_object_id":...}(the last three keys —photo_size/photo_hash/photo_object_id— only present when the contact has a photo). Surfaced as raw JSON. Group membership is a real many-to-many relationship, not synthesized — see_gws_contact_groups— including Google’s own built-in"myContacts"system group alongside any user-named ones.
Tree: a synthetic top-level grouping — M365’s real, name-resolved
parent_folder_id, a single synthetic “Contacts” bucket for GWS —
then a flat leaf per contact (the “grouped flat list” strategy,
SyntheticGroupedTree).
- synology_apm_repo.sdk.units.saas.contact.CONTACT_CONFIG = SaasWorkloadConfig(root_name='Contacts', leaf_kind=<UnitKind.CONTACT: 'contact'>, tables=('contact_table',), tree_factory=<function _build_tree>, assemble=<function _assemble>, object_names={'contact_table': ('contact_db',)}, extra_attrs=<function _contact_extra_attrs>, group_attrs=<function SaasWorkloadConfig.<lambda>>, leaf_size=<function SaasWorkloadConfig.<lambda>>)¶
SaasWorkloadConfigbehindContactProvider— M365 contacts have a real, single-parent folder hierarchy (parent_folder_id); GWS contacts instead belong to zero or more groups, an M:N relationship with no folder column at all.
- async synology_apm_repo.sdk.units.saas.contact.ContactProvider(repo, version, saas_streams, *, shared=None)¶
Constructor-style factory over
CONTACT_CONFIG— callable exactly like a constructor (await ContactProvider(repo, version, saas_streams)), with an optionalsharedcontext passed straight through toSaasWorkloadProvider.createfor M365’s multi-candidateUSER_EXCHANGE/GROUP_EXCHANGEdispatch.