/** * caldav-gateway-service.ts, the CalDAV-backed implementation of the daemon's * `calendar.*` verbs. * * A sibling of `google/gateway-calendar-service.ts`, not a replacement for it: * both satisfy the same `CalendarGatewayService` slice that * `control-plane/routes/calendar.ts` is written against, so the five verbs are * served identically whether the operator's calendar is a Google account or any * CalDAV server (Fastmail, iCloud, Nextcloud, Radicale, a corporate DAV host). * The route layer knows about neither. * * This is a port, verb for verb, of the CalDAV surface that lived inside one * product, the same discovery, the same collection mapping, the same * .ics import/export, and the same operator-facing wording, including the * config keys the errors name. Two implementations of one advertised capability * is how a contract drifts, so there is now one. * * Three properties are kept exactly as they were: * * - **`calendarId` is logical.** It maps inward to a collection URL and never * comes back out; ids handed to a caller are host-relative hrefs, so no * response carries the scheme+host a credential is scoped to. * - **Attendees are display names.** A gateway response carries the CN (or the * address local-part) and never the address itself. The raw value survives * only inside a PUT, where the server needs it to address an invitation. * - **Import is per-event and honest.** One bad VEVENT in a file does not * fail the whole import or vanish from the result, the rest land and the * failure is named, per event, in `errors`. * * Everything is injected: the HTTP port, the config port, the secret port, the * clock and the uid source. Nothing here reads a socket, a file, or `Date.now`. */ import type { CalendarGatewayService } from '../control-plane/routes/calendar.js'; import { type CalDavHttpPort } from '../google/caldav-client.js'; import { type CalDavConfigPort, type CalDavSecretPort } from './caldav-gateway-config.js'; import { type CalendarUntrustedIngestRecorder } from './untrusted-events.js'; /** Everything the service needs, all of it injected. */ export interface CalDavCalendarGatewayServiceOptions { /** Reads `surfaces.calendar.*`. */ readonly config: CalDavConfigPort; /** Resolves the CalDAV password from the secret store. */ readonly secrets: CalDavSecretPort; /** The HTTP transport. The fetch-backed adapter is `createFetchCalDavHttpPort`. */ readonly http: CalDavHttpPort; /** Wall clock, injected so DTSTAMP and `createdAt` are deterministic under test. */ readonly now?: (() => number) | undefined; /** UID source for created events, injected for the same reason. */ readonly randomUuid?: (() => string) | undefined; /** * Records that a turn read untrusted event content. * * Events on a CalDAV collection are written by whoever sent the invitation, * so every read path here records: `listEvents`, `getEvent`, `exportIcs` and * `importIcs`. Each of those runs because a caller asked for it, which is the * condition for recording at all, nothing in this service runs on a timer. * See untrusted-events.ts. */ readonly recordUntrustedIngest?: CalendarUntrustedIngestRecorder | undefined; } /** One calendar collection the account can reach. */ export interface CalDavCalendarSummary { readonly calendarId: string; readonly displayName: string; } /** * The gateway slice plus discovery. `listCalendars` is not one of the five * cataloged verbs, it is what a setup flow calls to fill in * `surfaces.calendar.defaultCalendarId` with something real instead of asking * an operator to hand-copy a collection path out of a web UI. */ export interface CalDavCalendarGatewayService extends CalendarGatewayService { listCalendars(): Promise; } export declare function createCalDavCalendarGatewayService(options: CalDavCalendarGatewayServiceOptions): CalDavCalendarGatewayService; //# sourceMappingURL=caldav-gateway-service.d.ts.map