Extend calendar invitation capability contract

This commit is contained in:
2026-08-02 16:38:34 +02:00
parent af5c6af0e7
commit 435b924fd9
2 changed files with 63 additions and 0 deletions
+55
View File
@@ -91,6 +91,16 @@ class CalendarInvitationRef:
degraded_reasons: tuple[str, ...] = () degraded_reasons: tuple[str, ...] = ()
@dataclass(frozen=True, slots=True)
class CalendarInvitationCalendarRef:
id: str
name: str
color: str | None = None
timezone: str = "UTC"
source_kind: str = "local"
writable: bool = True
@dataclass(frozen=True, slots=True) @dataclass(frozen=True, slots=True)
class CalendarExternalProfileRequest: class CalendarExternalProfileRequest:
"""Connector-neutral request for a Calendar-owned external profile.""" """Connector-neutral request for a Calendar-owned external profile."""
@@ -165,6 +175,20 @@ class CalendarOutboxProvider(Protocol):
class CalendarInvitationProvider(Protocol): class CalendarInvitationProvider(Protocol):
"""Correlation-aware invitation boundary for Campaign and Mail adapters.""" """Correlation-aware invitation boundary for Campaign and Mail adapters."""
def list_calendars(
self,
session: object,
*,
tenant_id: str,
user_id: str | None = None,
group_ids: Sequence[str] = (),
can_admin: bool = False,
) -> Sequence[CalendarInvitationCalendarRef]:
...
def render_invitation(self, request: CalendarInvitationRequest) -> str:
...
def upsert_invitation( def upsert_invitation(
self, self,
session: object, session: object,
@@ -184,6 +208,26 @@ class CalendarInvitationProvider(Protocol):
) -> CalendarInvitationRef | None: ) -> CalendarInvitationRef | None:
... ...
def get_invitations(
self,
session: object,
*,
tenant_id: str,
correlation_ids: Sequence[str],
) -> Mapping[str, CalendarInvitationRef]:
...
def summarize_invitations(
self,
session: object,
*,
tenant_id: str,
source_module: str,
source_resource_type: str,
source_resource_id: str | None,
) -> Mapping[str, object]:
...
def record_response( def record_response(
self, self,
session: object, session: object,
@@ -198,6 +242,17 @@ class CalendarInvitationProvider(Protocol):
) -> CalendarInvitationRef: ) -> CalendarInvitationRef:
... ...
def record_icalendar_reply(
self,
session: object,
*,
tenant_id: str,
icalendar: str,
received_at: datetime | None = None,
evidence: Mapping[str, object] | None = None,
) -> Sequence[CalendarInvitationRef]:
...
@runtime_checkable @runtime_checkable
class CalendarExternalProfileProvider(Protocol): class CalendarExternalProfileProvider(Protocol):
+8
View File
@@ -239,6 +239,7 @@ class ModuleSystemTests(unittest.TestCase):
"addresses", "addresses",
"dist_lists", "dist_lists",
"templates", "templates",
"calendar",
"postbox", "postbox",
"approvals", "approvals",
"reporting", "reporting",
@@ -3469,6 +3470,12 @@ finally:
"version_min": "0.1.0", "version_min": "0.1.0",
"version_max_exclusive": "0.2.0", "version_max_exclusive": "0.2.0",
}, modules["campaigns"]["requires_interfaces"]) }, modules["campaigns"]["requires_interfaces"])
self.assertIn({
"name": "calendar.invitations",
"optional": True,
"version_min": "0.2.0",
"version_max_exclusive": "0.3.0",
}, modules["campaigns"]["requires_interfaces"])
self.assertEqual( self.assertEqual(
[ [
"files", "files",
@@ -3477,6 +3484,7 @@ finally:
"addresses", "addresses",
"dist_lists", "dist_lists",
"templates", "templates",
"calendar",
"postbox", "postbox",
"approvals", "approvals",
"reporting", "reporting",