Skip to main content

Calendar editor timezone

Calendar display and the built-in event editor use the same resolved Calendar settings. Explicit personal timezone takes precedence over workspace timezone; when neither is explicit, the canonical resolver detects the browser timezone. The editor’s date/time picker inherits those settings instead of resolving its own browser timezone. This applies to the shared Calendar surface in Web and the standalone Calendar app. It does not change saved user or workspace settings. Timed edits represent an instant and serialize as UTC ISO timestamps. A date-only all-day choice represents midnight in the resolved calendar timezone with an exclusive end boundary. A browser in another timezone must still display the chosen calendar date, including when its local date is the previous day. Existing Google-backed events are patched immediately using their stored external event identifier. Imported recurring occurrences retain the provider’s instance identifier; changing an occurrence must preserve that identifier and calendar source. The patch sends updates to guests. Verify the stored event and the same Google occurrence independently after an edit; a local toast is not provider read-back evidence. The current Google write mapper uses dateTime fields and does not provide native Google date-only all-day writes. Native Tuturuuu all-day events do not require that provider path.

Tasks and Calendar planning

Calendar and Tasks keep cross-product API calls on the active browser origin so host-only app cookies remain available. Their beforeFiles rewrites forward only the other product’s API families, before Tasks’ API catch-all can intercept them. The source proxy refreshes the host session and forwards its signed bearer token; Calendar routes explicitly accept Calendar and Tasks audiences while retaining workspace membership and permission checks. Do not route these APIs through Web: Web no longer owns the Calendar events or Tasks endpoints. Tasks’ session verifier also accepts Calendar for routes that explicitly accept Tasks, including labels, projects, task detail dependencies, and workspace task preferences. It preserves required scopes and does not widen unrelated app audiences. Calendar forwards /api/v1/users/me/workspaces/:wsId/configs/* to Tasks so those preferences use the verified planning actor and membership guard. Collection rewrites must have an exact path before their /:path* variant. Vercel can retain a trailing slash when the wildcard is empty, causing the owning app to return a 308 to the same browser URL and loop. Verify both collection and nested resource requests on the deployed host. Both satellite apps expose local planning views without changing workspace or requiring a cross-app login handoff: The shared sidebar retains locale and personal/internal workspace aliases, including on mobile. Calendar also serves /tasks/boards, /tasks/boards/{boardId}, and /tasks/{taskId} within the workspace. Task views hide the calendar-only mini-month sidebar to leave more room for task work. Tasks’ embedded calendar uses the shared scheduling, connection, event, and task controls and enforces manage_calendar. Each host resolves its own app-session actor. Keep the task route context and dialog manager prefix aligned: Tasks uses an empty prefix, while Calendar and Web use /tasks. Tasks already owns a dialog provider, so its embedded calendar disables the additional dialog wrapper. When validating this integration, check both locales, personal and team workspace links, board/task detail return paths, and mobile navigation with the sidebar closed. Mutations continue through the existing protected product APIs.

Overview

apps/calendar and the Calendar experience inside apps/web are paired Calendar hosts. They must stay 1:1 for product features, data behavior, mutations, permissions, and user-facing workflow updates.
  • Calendar UI and logic should live in shared packages, primarily @tuturuuu/ui/calendar-app/*, with app route files acting as thin auth and workspace-context wrappers.
  • Task-aware Calendar controls (task creation, task scheduling, habits, and task time tracking) live in @tuturuuu/tasks-ui/calendar/*. The generic Calendar shell accepts those controls through typed component seams, keeping @tuturuuu/ui independent from task-only code and preserving narrow Turbo rebuilds.
  • apps/calendar owns its standalone workspace shell, local /login, and local /verify-token completion route.
  • apps/web /{wsId}/calendar renders the same shared Calendar product surface inside the normal platform dashboard shell.
  • Dashboard navigation in apps/web should link to the local /{wsId}/calendar route, not to the standalone Calendar origin.

Auth Model

Calendar does not create local Supabase Auth sessions. It uses central apps/web login plus a Calendar app-session cookie:
  1. /login in apps/calendar normalizes a safe next path.
  2. If both the Calendar app-session cookie and Web-issued app-session cookie are already present, /login redirects to that local next path immediately.
  3. Otherwise /login redirects to apps/web /login with a return URL pointing back to Calendar /verify-token?nextUrl=....
  4. /verify-token posts the handoff token to the Calendar-local verifier, which validates through central Web and sets host-local app-session cookies.
Calendar proxy responses should clear stale sb-*-auth-token cookies. A valid Calendar session is represented by Tuturuuu app-session cookies, not by a local Supabase browser session.

Calendar timezone boundaries

Event start/end values are UTC instants. Display and picker controls resolve personal calendar timezone first, workspace timezone second, and device timezone when both inherit with auto. A browser-local Date used by a date-only calendar widget is a calendar-day carrier, not an event instant: project its year, month and day in the resolved timezone before passing selection, today or bounds. Compare end-time options on that same calendar day and derive minimum/maximum clock values in the same timezone. This matters when the browser and calendar are on different dates, for example Los Angeles and Ho Chi Minh City. Quick previews use the same resolved timezone and clock format as the event form, localized to the current locale. Date/time edits must round-trip the requested wall time; nonexistent DST times must not silently normalize into another hour. Reselecting an unchanged ambiguous time or date preserves the original UTC instant. Tests cover these boundaries; they do not establish exhaustive correctness for every IANA history or changed ambiguous-time choice. Native all-day persistence and the outer calendar Today/header date contract remain separate concerns. Do not infer all-day intent solely from a 24-hour elapsed duration, and do not publish a DST duration helper in isolation from the persistence/rendering contract. Imported recurring provider events require exact-instance and neighboring-instance readback after an authorized UI edit. Never use real user calendar screenshots as public regression fixtures.

API Ownership

apps/calendar owns the Calendar product APIs. Its local handlers cover events and calendars, categories and preferences, hours and default sources, scheduling and sync, Calendar connections, Google and Microsoft provider OAuth, Calendar media/generation helpers, and Calendar-owned cron work. Host-local auth/session and build-info routes are local as well.
  • Exact local handlers win before the fallback /api/:path* rewrite. The fallback remains for cross-product routes that Calendar uses but does not own, including workspace encryption and task, board, habit, and time-tracking families; typed task helpers may target the Tasks app directly.
  • Central platform login, social-provider callbacks, and cross-app token issuance remain Web-owned. Calendar-provider OAuth initiation and callbacks are Calendar-local, even though their configured redirect origins retain Web compatibility for existing provider registrations.
  • Calendar-only routes use targetApp: 'calendar'. Shared cross-product routes must name the exact accepted app audiences, such as targetApp: ['calendar', 'tasks'], rather than accepting generic satellite sessions.
  • Keep workspace membership checks and Calendar/task permissions on the owning route before admin-backed reads or writes. The Calendar proxy guard and app-session refresh do not replace route-level authorization.
  • Prefer typed packages/internal-api helpers. Browser calls remain same-origin so Calendar-local handlers are selected first; server calls to a different owning app must use its configured API base URL with forwarded authentication.

Calendar settings authorization

Personal calendar preferences are scoped to the authenticated user. Settings updates accept supported IANA timezone names or auto inheritance; invalid names and fixed-offset strings are rejected before storage. Workspace calendar settings are readable by members, but updates require manage_workspace_settings. Check that permission explicitly on the owning PATCH route: a verified signed app session can use an admin-backed database client, so membership and table RLS alone do not enforce editing rights. Native clients reach the Calendar owner through the authenticated mobile gateway. The settings allowlist permits only GET and PATCH on /api/v1/users/calendar-settings and /api/v1/workspaces/:wsId/calendar-settings; upstream ownership, workspace permission checks, credential isolation and response limits remain enforced. Native preference GETs use a dedicated Infrastructure guard bucket so calendar event/account fan-out cannot consume their read allowance. The shared guard still enforces the same default anonymous/authenticated limits, verified-session keying, MFA, and IP blocks; PATCH and other gateway requests retain the existing bucket. A preferences 429 emits only policy/caller/window/reason diagnostics, without actor, workspace, IP, credentials or response bodies. This does not bypass an IP block or make an exhausted preferences bucket unlimited. Regression coverage: preference-guard.test.ts exact route/method boundaries and gateway.test.ts upstream diagnostic isolation. Actual authenticated mobile recovery must be verified after deployment. Mobile’s API error retains only fixed known reason, policy, caller and window values from a 429 response, and includes those safe fields in its diagnostic log. Unknown values become unknown; URLs, actor/workspace identifiers, IPs, cookies, credentials and response bodies are never included in that diagnostic. This preserves the server rejection and cooldown rather than treating an unavailable preference as success. Regression: api_client_error_contract_test.dart exercises the HTTP boundary and rejects private or arbitrary header values.

OAuth Token Safety

Calendar OAuth credentials live in calendar_auth_tokens. RLS restricts selects to user_id = auth.uid(), but admin/service-role reads bypass RLS. Calendar server pages must therefore:
  • Check manage_calendar before loading calendar integration state.
  • Scope token reads to both ws_id and the authenticated user_id.
  • Never pass access_token or refresh_token into client components. SSR props should use the shared fetchUserWorkspaceCalendarGoogleTokenForClient() helper from @tuturuuu/utils/calendar-auth-token, which projects only connection metadata (id, account email/name, provider, active state, expiry).
  • Keep token refresh and provider API calls on Calendar-local server routes; never expose provider credentials to client components.
When adding a new Calendar host route, reuse the helper instead of select('*') on calendar_auth_tokens. When adding new Calendar UI that needs protected data, update the shared Calendar component or helper first, then wire both host wrappers in the same change. Extend the route family in its owning app and expose a typed packages/internal-api seam instead of creating a host-local product API fork or adding direct client Supabase reads.

Calendar OAuth And Connections

Google Calendar OAuth initiation and callback handlers are owned by apps/calendar. The local /api/v1/calendar/auth route builds its callback URL from a browser-safe configured origin and ignores wildcard listener addresses such as 0.0.0.0 or ::. Existing provider registrations may still configure the central Web origin; if no safe configured origin is available, the fallback origin is https://tuturuuu.com. After Google returns to the callback, the flow always sends the user to the central Web Calendar page at https://tuturuuu.com/{wsId}/calendar?provider=google&connected=true. Valid local development callback URLs such as http://localhost:7803/api/v1/calendar/auth/callback may still be configured through GOOGLE_REDIRECT_URI, but wildcard listener URLs must never be emitted as Google redirect_uri values or browser redirects. Normal Google Calendar connect and reconnect URLs request access_type=offline and include_granted_scopes=true, but they must not force prompt=consent by default. Google may return a refresh token only during the first authorization, so the callback must preserve an existing stored refresh_token when a reconnect returns only a new access token. If neither the callback nor the existing token row has a refresh token, the flow must fail before saving an active Google connection because provider sync cannot refresh offline. Standalone apps/calendar also exposes the shared Calendar connections manager inside its settings dialog under Calendar -> Integrations. It should fetch the initial connection state through @tuturuuu/internal-api/calendar and render the shared Calendar connections UI inside CalendarSyncProvider rather than forking host-local connection controls.

CI And Deployment

Calendar deploys through dedicated GitHub Actions workflows, not Vercel-owned GitHub auto-builds:
  • Preview deployments use .github/workflows/vercel-preview-calendar.yaml.
  • Production deployments use .github/workflows/vercel-production-calendar.yaml.
  • The Vercel project id is provided through the environment-scoped VERCEL_CALENDAR_PROJECT_ID secret.
  • apps/calendar/vercel.json must keep git.deploymentEnabled and github.enabled set to false so GitHub Actions builds with vercel build and deploys prebuilt artifacts with vercel deploy --prebuilt.
Vercel hosts the Calendar schedules in apps/infrastructure/vercel.json. Infrastructure authenticates the scheduler and forwards through the private Calendar gateway; Calendar validates the scheduler credential again.

Provider Sync

Infrastructure hosts the provider-sync schedule (*/15 * * * *). Both apps’ proxies recognize validated cron credentials independently of browser sessions; invalid credentials still fail authentication. If hosted runs return 401 before Calendar logs a request, check the Infrastructure proxy and matching production CRON_SECRET configuration before investigating provider tokens. The Calendar cron wrapper invokes Calendar’s workspace sync handler locally, preserving cron authentication, running locks, cooldown behavior and calendar_sync_dashboard audit rows. It must not send sync requests to the former Web owner through INTERNAL_WEB_API_ORIGIN or a protected preview URL. Both Tasks and Calendar show Sync needs attention beside the calendar picker when a sync stalls, data becomes stale, a provider needs reconnection, or status cannot be loaded. Open it for a persistent explanation and a Sync now, Check again, or provider-specific Reconnect action. Stored events remain visible during provider outages. Ordinary access-token expiry is not itself a reconnection failure: Google refreshes those tokens automatically. Sync health polls every 30 seconds (every 5 seconds during a run or cooldown). A running entry older than five minutes is stalled; a successful sync older than 45 minutes is stale. Partial provider failures are recorded as failed runs rather than successful syncs. Successful runs use the database’s completed status; completion writes must be checked so a constraint failure cannot leave a run stuck at running. Provider rate limits and transient outages offer retry, while authentication failures offer reconnection. Operators should inspect the Calendar cron execution and dashboard run when retries continue to fail.

Recovering individual calendar failures

The warning names each failed Google calendar after a sync attempt. Pause sync for this calendar turns off only its inbound import; it preserves its saved events and visibility, and does not disconnect the account or affect other calendars. This action is available during the manual retry cooldown. Restore provider access when applicable, then re-enable inbound sync from the calendar’s sync controls. Sync now retries the remaining enabled calendars. The sync handler stores sanitized version-1 failedCalendars diagnostics in the existing calendar_sync_dashboard.error_stack_trace text field. Each entry has only connectionId, calendarName, and a classified code. Never store OAuth credentials, provider response payloads, or headers there. The status API parses this format, filters disabled/paused connections, and returns failedCalendars; it never returns the raw diagnostic field. Older unstructured errors still show an aggregate warning and gain calendar-specific details on the next attempt. Per-calendar failure diagnostics and the pause shortcut currently cover Google inbound sync. Microsoft failures retain account-level reconnect/retry guidance; individual Microsoft calendar failure identification is not yet available.

Views and keyboard support

Calendar views share behavior across Calendar, Tasks, and embedded Web calendars. Use D, 4, W, M, Y, or A for day, four days, week, month, year, or agenda. These page shortcuts are inactive inside editors, menus, and dialogs, during input composition, or alongside Cmd/Ctrl/Alt. Month selection updates the host’s controlled state and is restored from the saved view preference. Month provides event previews and day details; year opens the selected month or day; agenda searches titles and locations across its 30-day window. Event queries must cover the entire year or all 30 agenda days, not just the first day. The event route reads ordered 1,000-row pages so busy years are not truncated by the database response limit. Shared settings list the shortcuts alongside command search, app launcher, and sidebar commands. Verify modified shortcuts in Calendar and Tasks and check typing, modifiers, modal focus, and mobile overflow when changing these views. Global command/app launchers remain available while editing. Calendar view shortcuts are intentionally suppressed throughout editor descendants, including non-editable embedded content, to prevent unexpected view changes while working in an editor.

Two-Way Sync Controls

Calendar sync has two layers of user control:
  • Workspace-user preferences in private.calendar_user_workspace_preferences enable or disable inbound imports, outbound Tuturuuu-to-provider mirroring, the default outbound provider calendar, and the conflict policy.
  • calendar_connections controls each external calendar’s import, outbound write, and provider-delete behavior.
Outbound mirroring is opt-in. When enabled, native Tuturuuu event creates and edits mirror to the selected writable Google or Microsoft connection, and the local event stores provider identity so future updates and deletes propagate externally. Manual or cron sync with direction: "outbound" or "both" may also catch up local-only or previously failed Tuturuuu events in the active sync window. Inbound provider deletes are controlled per connection through sync_delete_enabled. User-initiated deletion of a synced external event still deletes the provider event directly because it is explicit CRUD, not passive provider import cleanup. After adding or changing two-way sync columns, prepare migrations in apps/database; do not run production Supabase push commands from agent sessions. Apply locally with bun sb:up when feasible, then regenerate database types only after the local schema reflects the migration.

Installation and caching

Calendar and Tasks serve their own /serwist/sw.js workers and installable app manifests. Client instrumentation captures the install event before hydration; these hosts explicitly transpile @tuturuuu/ui for that bootstrap entry point. The Settings → Install app control uses the browser prompt when available and gives Home Screen instructions otherwise. /offline.html is a public, bilingual fallback that bypasses authentication middleware. These productivity hosts use cacheNavigations: false and staticAssetsOnly: true: private HTML, APIs, and private images are never persisted by the worker. Installation precaches only the fallback, icons, and manifest. Hashed Next assets cache on demand, with at most 160 runtime entries. This avoids downloading the entire application at installation. Loaded data remains available in an open app through memory caches. Calendar snapshots are keyed by workspace and date range and limited to 12 ranges; event lookups pre-index date intervals and memoize at most 400 day results. Private snapshots are not persisted across app restarts. Reopening a workspace, syncing, and saving changes require connectivity; this release does not add a durable offline write queue. The offline indicator communicates that limitation. Verify worker registration, install manifest, cached asset reuse, offline fallback, and the absence of API/private-page entries in Cache Storage on both Calendar and Tasks. Re-run both app builds when changing the worker routes or tracing configuration.

Calendar regression tests

Calendar owns a workspace test script, so bun test and CI coverage include its provider, authorization, cron and event-route suites automatically. Run ttr resources run -- bun run --cwd apps/calendar test --maxWorkers=2 for the complete focused suite. Manual provider smoke tests supplement these regressions; they do not replace the automated suite or prove that closed-client scheduling is active in production.

Invitation delivery API

Explicit invitations use the events collection POST with an invitation containing guest email addresses, optional-attendee flags and an IANA time zone, plus a UUIDv7 requestId. Choose a writable connected Google or Microsoft calendar. Provider-owned RSVP status is never accepted as organizer input. The same request ID must survive retries. The server binds it to the actor, workspace, source and complete invitation details. It reserves an encrypted local event before sending, then records the provider identity. Google uses a stable event ID and a private request fingerprint; Graph uses transactionId. A duplicate Google event with a different fingerprint is rejected. A timeout does not authorize a fresh send or a new request ID. Calendar requires server-only CLOUDFLARE_COORDINATION_URL and CLOUDFLARE_COORDINATION_TOKEN for its Durable Object request lease. The token has an encrypted backup in the Infrastructure vault. Missing storage fails closed. Only request hashes and completion state enter the Durable Object; provider credentials and guest lists do not. New reservations are accepted for 15 minutes, with one minute of forward clock tolerance. An older request can only resume its existing actor-bound reservation with identical details and the original provider idempotency key. This also recovers pending delivery after provider exceptions or missing responses; an expired request never recreates a deleted reservation. A 409 or ambiguous failure must leave the client in a review/retry state. Check the calendar before creating a replacement request. Pending deliveries cannot be edited or deleted through the event API. POST /api/v1/workspaces/:wsId/calendar/events/:eventId/response accepts accepted, declined or tentative. The selected connected account must actually be an attendee; organizer identity, provider concurrency and workspace authorization are checked before writing. Native clients use the authenticated infrastructure gateway, which permits only POST on this route. Responses are private and uncached. This is the delivery foundation. Scheduling surfaces and assistant tools must present the exact meeting and recipients for user confirmation before calling the send operation. These API tests do not establish live Gmail/Outlook delivery; verify invitations and RSVP updates using explicitly authorized test accounts before claiming provider interoperability.

Google color identity and inheritance

Google inbound sync preserves the provider’s explicit event color ID, calendar-scoped label ID, inherited-color intent and resolved opaque RGB in scheduling_metadata.google_color. The existing canonical event-color foreign key remains a compatibility value, not an exact Google color definition. Google labels take precedence over legacy event color IDs; an event with neither inherits the connected calendar’s current RGB color. Calendar custom RGB takes precedence over its calendar palette ID, which belongs to a different palette from event IDs. Active sync refreshes the matching connection’s source color even when no events changed. Missing provider metadata remains unresolved and observable rather than inventing a custom color. Label-definition changes without an event delta can leave an explicit event’s resolved RGB snapshot stale until the event is fetched again. Unrelated title/time updates read the current Google event, preserve its exact color or label identity and use its ETag to reject concurrent changes. Native creates map their canonical color argument to the Google event palette. The capability-gated shared web picker uses exact event IDs, calendar-scoped label IDs, and inherited color; its choices preserve opaque provider RGB. Microsoft and disabled-candidate surfaces keep their canonical palette. These source paths require the recovery schema and exact-commit build validation before activation. Sync never rewrites a calendar’s label array or implicitly publishes a private native calendar to Google.

Recoverable Google color operation development

Exported-route overlap tests model the authoritative provider-series read-only RPC separately from operation-ledger RPCs. A writable fixture returns false; read-only and unavailable states must still reject PUT/DELETE before reservation or provider dispatch. google-color-operations/route-overlap.test.ts covers these states alongside delayed-request fencing and recovery. When adding an admission lookup, update shared route fixtures to its actual result contract so a fixture failure cannot masquerade as a provider or operation conflict. The same-calendar color-write followup has a server-only operation ledger, immutable prepared patch/ETag and private operation marker. Conditional replay uses the original ETag; it never refreshes an old operation’s precondition. A provider 412 fences the old attempt, then current provider state is fetched and settled by its operation marker. Matching color alone is not completion proof. An authorized resumption must recheck Calendar management permission, connection owner and exact token/calendar/event identity. Only definitely-unsent reserved or prepared operations can cancel. Local commit failures remain recoverable. This is an unpublished implementation stage. A bounded route slice now connects same-calendar color PUT, encrypted content/time/local-lock PUT and conditional DELETE to reservation, immutable conditional dispatch and atomic finalization. The generic operation stores sensitive request content only in an authenticated encrypted journal. Finalization encrypts the authoritative provider projection; route callers do not perform a second local write. Conditional deletion settles habit skips and task/habit links in the same transaction and retains an authorized tombstone for recovery after the event row is gone. Dedicated authenticated color-operation GET/POST/DELETE handlers expose only operation ID/phase, execute recovery, or safely cancel an unsent operation. Recovery bodies accept only operationId; source, generation, prepared patches and force-clear overrides are never caller inputs. Reservation state is private and never added to generic event scheduling metadata. The candidate slice is disabled unless the server-only CALENDAR_GOOGLE_COLOR_OPERATIONS_ENABLED setting is true. That candidate mode supports same-source color, content/time/local-lock edits, invitation responses and deletion through the shared generation boundary. RSVP uses only the authenticated connected account’s self attendee, seals the response against the original provider version, and projects the resulting event before reporting delivery. Cancelled meetings and superseded responses return a conflict. Supported source movement uses the durable provider saga described below. Unsupported move types return 409 before side effects. A pending operation blocks content, color and delete successors. Attendee updates are all for content/time edits and deletion; color/local-lock-only edits use none. Recovery executes the server-stored operation kind and original conditional request, never a new caller-supplied mutation. Status GET may accept a strict operationId query to reauthorize an already-deleted event’s retained operation. Native/Microsoft routes retain their existing behavior. This mode remains disabled by default and is not approved for normal production mutation behavior: every provider writer must cooperate before enabling it; mixed enabled/disabled API versions are unsafe. The private RPC and transaction capability atomically merge Google color into latest metadata and commit sync/completion together. Generation persists after completion. Prepared import changes capture it before provider GET/list, apply through guarded transactions and durably defer conflicting identities before a sync token advances. Deferred replay captures again and fetches fresh provider state, rather than saving old content or credentials. The new SQL/types and combined route/import contracts still require isolated validation. Do not release either migration or enable the candidate setting on its own. Complete adoption by Web, Tasks, outbound sync, RSVP and all other competing writers, plus the source move/create saga, before enabling writes. Regression evidence is in mutation-routes.test.ts, route-overlap.test.ts, the encrypted mutation executor/provider suites and calendar-google-mutation-replay.sql. The sync coordination cooldown is not a lock. Google ETags are opaque equality tokens, not sortable revisions. Google moves lack a documented conditional fence and remain a separate recovery scope. Synthetic controlled overlapping routes demonstrate the intended ordering against an atomic storage double; they do not substitute for SQL, import, owning build or deployment proof.

Event rendering and provider identity

Web event surfaces render opaque provider fills with the higher-contrast black or white foreground. Mobile agenda, day/three-day/week cards, all-day chips and month indicators blend the same read-only provider hue into the active theme. Completed mobile events (end at or before the shared projected wall clock) use a weaker background tint and accent; foreground text remains fully opaque with at least 4.5:1 contrast. All-day ends remain exclusive, so an event stays active until its final midnight boundary. A shared minute clock refreshes completion styles while the Calendar screen is visible. This presentation never changes the stored provider RGB, explicit/inherited intent or event times. Persisted google_color RGB is used when available; only known inherited intent uses a valid current source RGB. Authenticated list/item reads join the current stored connection RGB only for a persisted source calendar link in the actor’s active Google accounts. Unbound legacy rows, mismatched source links, and ambiguous or unavailable account matches retain the event snapshot. Active sync refreshes that connection even without an event delta. This read join does not fetch or mutate Google and does not infer intent for legacy rows. Native and legacy events without resolved provider metadata retain their canonical event color. Rendering does not infer old color intent, fetch a provider palette, or rewrite events. Web timed, all-day, agenda, month/year, location and drag previews use the same read-only color policy. Past web events fade with an overlay over their opaque fills; optimistic/preview status uses outlines. Hovering an overlapped lower card hides upper cards instead of blending their fills, and restores them when the hover ends. Focus/drag/resize states retain opaque backgrounds. The existing preservePastEventOpacity adapter option suppresses this fade. Past external provider events follow the same policy; previews, pending writes and active drag/resize states keep full intensity. Regression coverage for the policy and hover treatment lives in past-event-treatment.test.ts and event-card.test.tsx. Mobile source RGB survives date projections and local cache serialization. Regression coverage lives in calendar-event-colors.test.ts, event-card.test.tsx, calendar-views.test.tsx, dynamic-island.test.tsx and mobile event_colors_test.dart. These checks do not establish full palette editing, legacy-row refresh, or completed Google write reconciliation.

Calendar navigation dates and query boundaries

The legacy calendar treats its selected date and visible grid dates as calendar days: their local year, month, and day fields identify the selection. An explicit YYYY-MM-DD navigation value preserves that day when the effective timezone changes. Timestamp navigation values and Today project the actual instant into the resolved calendar timezone. The Calendar host supplies that timezone to its navigation provider; shared calendar content also supplies it to the event sync provider. Web’s calendar route redirects to the Calendar host. Deep links apply once using the first available resolved timezone so later settings updates cannot reset a user selection. A timestamp link applied before personal settings finish loading retains that initially projected day; following the pending instant until settings settle needs a separate selection ownership contract. Headers, sidebar selection, day/week/month/year/agenda labels, and Today markers use these day fields consistently. A shared minute clock updates Today and the current-time indicator without changing the selected day. Timed event lookup projects event instants into the resolved timezone before grouping by day. Fetch ranges independently construct the first day’s midnight and the midnight after the last day in the effective timezone. This supports 23-hour and 25-hour days across daylight-saving changes. Calendar cache keys include the timezone and the selected calendar-day fields, so a timezone change cannot reuse a range from another timezone. These changes preserve existing event storage, recurrence, and all-day identity contracts. All-day lookup retains its legacy browser-local day identity, so its month/year grouping may still differ from the configured-zone bar for legacy midnight payloads. All-day bar drag and location create/resize/split callbacks retain their existing timestamp conversion: their inferred all-day classification cannot safely represent zoned 23-hour or 25-hour midnight spans without a persistent intent contract. They do not establish a persistent all-day intent flag or verify live provider writes. Focused mounted tests exercise navigation, labels, grouping, and fetch boundaries; deployed browser verification and exact-head CI remain separate release checks.

Recoverable creation and calendar transfers

The candidate mode remains disabled by default. New event, label, and inherited provider-color commands return 409 while it is disabled. The shared web picker reads providerColorWrites from the actor-scoped color-options response and shows the legacy native palette until that capability is enabled; unsupported Microsoft sources retain the legacy palette. Color-only saves send only their color command and do not notify guests. Native mobile resolves the Google connection from fresh, uniquely matching canonical source options. Its full palette requires the same capability; provider-color commands are online only, and combined content/date/color changes must be saved separately. Missing or ambiguous source mapping preserves the legacy mobile palette. Activation requires draining existing legacy writer activity after the schema and retained guards are deployed. Its routes support deterministic Google creation, source-only movement between two calendars of the same Google account, native-to-Google creation, and conditional Google-to-native transfer. Google move preserves the provider event identity and iCalendar UID; a move may include a local lock change, but combined content/color/time changes return 409 before provider effects. A lost move response remains ambiguous: a matching ID and UID at the destination cannot distinguish this operation from an independent copy. Only a successful response from the attempted move permits that invocation to finalize; resumption never attributes an unmarked destination to the operation. Google-to-native transfers reject recurring masters and instances before admission because a single native snapshot cannot preserve the source recurrence. Cross-account copy/delete and Microsoft sagas return 409 before admission because their retry and compensation fences are not established. Google-to-Google moves of events with a calendar-scoped label also return 409 before key resolution or admission because that label cannot be carried safely to another calendar. This restriction applies to legacy and candidate moves. Creation uses a UUIDv7 request ID retained across retries for the same draft. That ID owns the local event, encrypted intent and deterministic Google event ID. The manual draft and every generated draft each retain a separate ID in state. An uncertain draft cannot reuse its ID after edits; recover the submitted intent before deliberately starting a new draft. Independent creation calls allocate new IDs unless their caller supplies an explicit retry ID. An unresolved existing calendar source never defaults to another account during an ordinary edit. Reusing an ID for a different payload is a conflict. Recovery exposes only the operation ID and phase, including terminal native transfers and deleted placeholders, and never returns sealed intent. Retained event generations are consulted independently of the feature flag. A pending generation blocks competing writes; a completed native transfer uses a native generation comparison for subsequent edits and deletion. Disabling the candidate cannot reopen legacy provider writes for a retained event. Legacy batch sync preflights every event before dispatch, and invited creation and automatic outbound mirroring remain blocked in candidate mode until they adopt the same boundary. With candidate mode disabled, ledgerless ordinary native behavior remains unchanged. When enabled, native edits use generation zero as their initial compare-and-set fence, so a concurrently admitted transfer rejects the stale edit. Native-to-Google admission compares the complete stored native row under the event lock before creating its retained generation. A concurrent ledgerless edit returns a conflict without a provider write, without depending on a native mutation timestamp. The transient encrypted row comparison never enters the public binding or persisted journal; route/service regressions and calendar-provider-saga.sql cover stale rejection and fresh admission. Synthetic Google acceptance established stale-version delete and move rejection, identity-preserving movement, duplicate insert rejection, and rejection of late recreation after a tombstone. This does not establish Microsoft behavior or permission on customer events. Source regressions cover stable draft request IDs, lost-response retry, unsupported operation rejection before keys/admission, and public native recovery without private intent. The admission and provider adapter label-move regressions live in provider-saga-request-service.test.ts and provider-saga-adapter.test.ts.

Mobile wall-clock display and timezone preference recovery

Mobile parses offset-bearing API timestamps into UTC instants once, then projects those instants into the selected Calendar timezone once. Agenda labels consume the projected wall-clock fields directly, including when the device timezone differs; they must not call native toLocal on a projected event. Existing UTC date-only all-day identity and DST-aware midnight bounds remain unchanged. Regression coverage lives in agenda_view_test.dart, calendar_date_time_test.dart and calendar_event_presentation_test.dart. Personal and workspace timezone preferences load independently. A successfully loaded scope remains editable if the other scope or the native timezone lookup fails. Saving a named personal preference can resolve Calendar without a device lookup. Workspace saving still requires permission and a loaded workspace scope. Failed reads retain Unknown with an explicit retry; they never imply an automatic preference or cause an implicit save. Failed saves retain the prior preference and allow retry. Account/workspace changes invalidate in-flight replies and editors. timezone_settings_http_contract_test.dart and timezone_settings_http_widget_test.dart exercise production gateway paths, Bearer serialization, failure/retry and explicit saving with synthetic data. Those checks do not prove a real provider session or explain a particular user’s failed authenticated request without runtime evidence. Calendar’s local authentication rejections classify existing IP blocks as ip-already-blocked and upstream authentication backpressure as backend-auth-rate-limit. The native gateway preserves these fixed categories for safe timezone diagnostics. Neither branch invents a limiter policy, caller class or exhausted window; unavailable fields remain Unknown. Status 429, Retry-After, authentication, bans and quotas retain their existing behavior. api-auth-rate-diagnostics.test.ts exercises the real personal preference GET and gateway; api_rate_limit_local_auth_test.dart checks the safe mobile copy. These classifications do not establish the cause of a past rejection without an exact deployed runtime receipt. Mobile Calendar completion styling refreshes at wall-clock minute boundaries. Timed events without an end use the same 30-minute fallback as rendered cards. Timezone retry repeats a failed explicit save for its original scope; read failures reload preferences. Unknown device zones stay unresolved until native lookup succeeds, including after workspace changes during rate-limit cooldown. calendar_minute_clock_test.dart and the HTTP settings tests cover these rules. The shard-zero mobile test job additionally runs agenda_view_test.dart with TZ=Asia/Ho_Chi_Minh and CALENDAR_NATIVE_TZ_REGRESSION=1; its explicit native UTC+07 offset assertion prevents a UTC runner from silently weakening the wall-clock double-conversion regression. Creation recovery on the shared Calendar form keeps the original submitted request ID and body immutable after an uncertain failure. Automatic original retry is available only when the initially submitted Google source advertised durable provider writes; legacy/native or unknown-capability failures require checking the calendar first. An unavailable capability cannot later turn an uncertain legacy create into a retry. The original retry action preserves the edited form. Only a confirmed creation ID allows its next explicit Save to update that event; edited drafts never silently start another creation. This applies to shared web Calendar forms; legacy creation payloads keep optional IDs while explicit recoverable Google payloads require a UUIDv7 ID validated at enabled admission. Regression: use-calendar-draft-save.test.tsx and calendar-creation-request.test.ts. For copy-delete compensation, authoritative fresh absence at both bound endpoints settles a persisted target-removed checkpoint as a superseded tombstone under the current generation. Linked habits and cascading links are skipped. Retained generation and retired identities prevent a stale import from recreating the event. Regression: calendar-provider-saga.sql and provider saga projection tests.

Mobile continuous dates and offline refresh

Mobile Day, Three days, and Week timelines scroll through adjoining dates with one continuous horizontal offset. Date headers, all-day rows, and time columns move together; the time gutter stays fixed. A bounded backing window recenters only after scrolling settles, preserving the visible dates and pixel position. Date picking and Today still move to the requested date. Month and Year retain their calendar-grid navigation. The mobile Calendar displays its actor/workspace-scoped encrypted snapshot first, then awaits a fresh repository read even when that snapshot is still fresh. Transport failures retain authorized events and pending edits. Pagination stores its extended range for offline revisits. Account/workspace changes fence pending responses and cache writes; definitive access denial clears Calendar snapshots, while MFA verification challenges preserve the last authorized snapshot. Regression coverage: continuous_date_scroll_test.dart and calendar_cubit_test.dart cover intermediate drag offsets, synchronized columns, fresh revalidation, workspace races, revoked access, and MFA retention. Exact commit mobile CI and authenticated device verification remain required for release evidence.

Native recurring series

The Calendar API stores native Tuturuuu recurring events as one canonical series and a bounded set of exceptions. It expands instances for the requested viewport; it does not pre-create duplicate event rows or stop at a materialization horizon. Daily, weekly, monthly and yearly rules use a named timezone and preserve local wall-clock dates across daylight-saving changes. All-day ends are exclusive. Counts include cancelled occurrences, but exclude nonexistent DST times. /api/v1/workspaces/{wsId}/calendar/series creates and lists native series. A viewport read supplies from, to and optional limit (maximum 1,000). Reads reject oversized results instead of returning a silently incomplete list. The detail endpoint adds /{seriesId}. All routes require workspace membership and manage_calendar, including after a permission or membership change. A mutation supplies a unique requestId, the last expectedRevision, and scope (this, all, or future). Instance scopes additionally supply the immutable originalStartLocal, even if that instance has moved. Revision conflicts return 409; repeating the same completed request returns its receipt without another write. Encryption is applied to titles, descriptions and locations. Missing encryption keys fail closed instead of exposing encrypted strings. An edit to this changes only the exception at its original slot. An edit to all changes the master; changing the generating rule or anchor resets its exceptions. A future edit splits the series transactionally, preserves remaining COUNT, and resets exceptions at and after the split, returning their discarded count. A first-occurrence future edit behaves as all. Deletes use the same scope and concurrency contract. This API stage accepts native series only. Google and Outlook imports and writes retain their existing behavior until their recoverable series integration ships; unsupported provider rules must remain preserved and read-only. The canonical Google RRULE and Microsoft Graph adapters explicitly reject lossy conversions. Regression evidence: calendar-native-recurrence.sql tests authorization, idempotency, revision conflicts and atomic splitting. recurrence/service.test.ts and calendar-recurrence-edit.test.ts cover encrypted retries, immutable identity, DST slot counts, cancellation, exception edits and truthful bounded reads.

Outlook snapshot completeness

Outlook calendar synchronization follows every calendarView continuation before reconciling removed events. Reads request UTC on every page and preserve the provider’s opaque continuation query. Duplicate event identities across pages collapse to the latest returned version. A failed, malformed, looping or oversized snapshot fails the sync; a partial snapshot must never authorize deletion. Reads are bounded to 50 pages and 25,000 distinct events. Continuations must remain on the same Microsoft Graph calendar collection. This applies to existing Outlook single events, recurring occurrences and moved exceptions; it does not enable canonical series writes by itself. Regression coverage: packages/microsoft/src/calendar/pagination.test.ts.

Recoverable provider series admission

The provider operation endpoints reserve an encrypted, actor-bound intent before remote effects and publish the canonical native result only after every provider step has a durable checkpoint. They preserve Google event IDs and Outlook immutable IDs, use revision preconditions, and keep original occurrence slots separate from moved start times. A partial “this and future” operation resumes from its completed trim instead of blindly repeating both provider writes. POST /api/v1/workspaces/{wsId}/calendar/series/provider-operations accepts requestId, source (provider and connectionId), action, and the native series creation or mutation fields. An update/delete also supplies seriesId. GET .../provider-operations/{operationId} returns actor-scoped status; POST to that detail endpoint retries the retained intent. A pending operation returns HTTP 202 with its operationId, not a false success. An applied operation returns the hydrated result. Journals, OAuth credentials and raw SDK errors never appear in those responses. Workspace membership, manage_calendar, current connection ownership and outbound-sync permission are checked again during recovery. Native mutation routes cannot bypass provider-bound series or a pending provider operation. New admission defaults to disabled unless CALENDAR_PROVIDER_SERIES_OPERATIONS_ENABLED=true. Keep it disabled until the canonical inbound reconciliation and provider UI integration have shipped and been verified together; the operation protocol alone is not full provider parity. Retained operations remain readable/retryable when new admission is disabled. Unsupported provider patterns are rejected rather than converted lossily; mailbox timezone support remains authoritative. Provider delivery and organizer receipts still require authenticated Google/Outlook verification. Regression evidence: calendar-provider-series.sql, provider plan.test.ts and writer.test.ts, plus calendar-provider-series.test.ts in Internal API cover permission revocation, leases, publication ordering, idempotent create recovery, revision conflicts, immutable identities, scope splitting and pending status.

Provider inbound recurrence observations

Canonical provider import uses the same default-disabled admission flag as recoverable external series operations. When enabled for verification, the live Google and Outlook sync paths reconcile supported recurring masters before persisting ordinary expanded instances. This is a staged integration, not a claim that provider editing or full recurrence parity is enabled in production. Google reads complete non-expanded iCalUID exception lists, including cancelled and moved instances outside the viewport. Outlook expands master exceptions and reads complete bounded immutable-ID views twice. Separate occurrence snapshots and the master revision are compared before publication. Windows timezone names use CLDR’s default territory mapping to IANA; unknown/custom names and nonzero fractional occurrence precision fail closed. There is no machine-timezone fallback. Reconciliation rechecks the token-owning actor, workspace membership, manage_calendar, source ownership and inbound permission throughout the read and before commit. The transaction compares the captured local binding ETag and defers while an outbound operation is pending. It publishes encrypted native fields and actor/source-bound encrypted provider metadata before suppressing explicitly represented legacy identities. Other calendars and unrepresented provider rows remain untouched. Outlook cancellations proven inside the complete view replace that covered range; known cancellations outside it survive if their original slots still belong to the current rule. Deleted bound masters are rechecked even when the Outlook view contains no remaining occurrences. Unsupported masters retain encrypted raw snapshots and visibly read-only projections; a previous canonical rule is hidden until safely supported again. Incomplete reads reject the refresh; see read-only rules. Keep admission disabled until metadata-preserving future splits, full legacy identity suppression across ranges, provider UI, and authenticated Google/Outlook verification are completed together. Regression evidence: calendar-provider-reconciliation.sql applies the actual migration and covers actor/source revocation, pending-operation deferral, stale observations, replay, deletion, rollback and scoped legacy suppression. Provider inbound reader/connection/service tests cover complete snapshots, independently changed exceptions, immutable identity bridging, encrypted metadata, cancellation coverage and the disabled default. Microsoft pagination/timezone and shared recurrence-edit tests cover continuation authorization, Windows zones and DST interval boundaries.

Future provider split metadata

A provider this and following edit reads and revision-checks the fresh master before reserving its trim. It retains supported writable metadata in the encrypted create step: guest identities/options, reminders, visibility/privacy, free-busy, Google guest rights and non-operation custom properties, or Outlook categories and response-request settings. Old organizer IDs, attendee RSVP replies, provider IDs and recovery markers are not copied to the new invitation. Outlook HTML notes keep their content type when unchanged; an explicitly edited description uses text. The current preflight rejects Google conferences, attachments, special event types, omitted attendee lists or a non-organizer copy, and Outlook online meetings, attachments, hidden guests or a non-organizer copy. It rejects malformed metadata instead of silently replacing privacy/reminder settings with provider defaults. These exceptions are rejected before any trim. Other edit scopes patch the existing provider event and do not create a replacement metadata copy. New external admission remains disabled; provider UI and authenticated end-to-end verification are still required before rollout. Regression evidence: create-metadata.test.ts, future-admission.test.ts and provider writer.test.ts cover preserved metadata, omitted replies/identities, HTML notes, strict journal shape, preflight-before-reservation, revision conflicts, source mismatch and actual provider create payloads. Recovery fingerprints include the retained metadata so retries cannot silently substitute a different tail.

Google future-series attachment references

A future split preserves up to 25 Google attachment references from the freshly read organizer-owned master. The replacement event uses Google’s supportsAttachments request option and excludes read-only file IDs. This copies links and display metadata, not file content or Drive permissions. Incomplete references fail before the original series is trimmed. Google conference reuse remains blocked because it can change access and expose meeting details; Outlook attachment and online-meeting splits also remain blocked. Provider editing admission stays disabled until the remaining parity checks pass. Regression coverage: create-metadata.test.ts, future-admission.test.ts, and writer.test.ts verify reference validation, preflight ordering, and create request options. See the Google event resource for attachment limits and conference reuse restrictions.

Outlook legacy recurring-instance identity verification

When provider-series admission is explicitly enabled, inbound reconciliation verifies older stored Outlook IDs outside the current viewport against their exact connected calendar. The bounded read-only pass selects IDs only, reads up to 1,000 source rows in batches of 20 with at most three batches in flight, and uses an explicit regular-to-immutable ID translation before requesting event and master identities. The translation requires the already requested User.Read Microsoft scope. Current source authorization is checked before each batch. Only explicitly verified IDs join the existing atomic canonical publication and legacy cleanup; single events, other masters, and missing remote resources are not attributed to the series. An incomplete batch, permission failure, throttling, or source overflow fails closed without publishing a partially verified series. This performs no provider mutation or calendar-wide deletion and does not enable provider editing. Regression coverage: graph-legacy-identities.test.ts verifies source filters, old-slot linkage, permission revocation, receipt completeness, foreign-master isolation, provider failures, and batch bounds.

Editable monthly and yearly weekday patterns

The shared web recurrence editor supports first, second, third, fourth, or last weekday patterns for monthly and yearly native series. Yearly patterns have an explicit month. Selecting multiple weekdays uses the earliest matching date in the selected ordinal week, following the canonical Google/Outlook adapter semantics (Graph recurrence patterns); the initial local date must match the pattern. The form does not silently move the first occurrence when the pattern changes. Absolute month-day rules offer skipping missing dates or using the month’s last day. Details-only edits preserve imported month-end behavior, yearly month and weekly week-start boundaries without adding optional normalization that would reset exceptions. This-occurrence edits do not modify the rule; future edits retain the remaining occurrence count and immutable original slot. Unsupported provider rules stay read-only, and outbound provider admission remains disabled. Regression coverage: native-recurrence-pattern-model.test.ts checks all five ordinals against both provider serializers, multi-weekday patterns, inclusive end dates, imported week boundaries and month-end behavior, invalid input, and edit scopes. native-recurrence-pattern-fields.test.tsx covers the interactive monthly, yearly, month-end and weekly controls.

Smart-scheduling startup enrichment

Calendar server startup loads the current actor’s accessible tasks first. Once those IDs are known, list/workspace metadata and actor-scoped scheduling settings are read concurrently. Empty task sets do not trigger broad enrichment reads; missing settings and list metadata retain their existing defaults. This removes one sequential database stage without changing task visibility or provider admission. The actual production latency benefit still requires authenticated post-deployment timing; focused tests are not a browser performance measurement. Regression coverage: load-smart-scheduling-tasks.test.ts holds list metadata unresolved while proving that actor-filtered scheduling settings have already started, verifies accessible IDs and deduplicated lists, and covers empty/missing responses, settings defaults, and rejected reads. Calendar’s dashboard permission check uses the UUID returned by the verified workspace read while retaining the exact satellite actor. This avoids resolving personal again inside the permission helper. Membership, roles and default permissions still use the same helper; denied navigation retains its URL slug. The page’s scheduling reads begin only after workspace and permission verification. Coverage: dashboard page.test.tsx exercises aliases/UUIDs, actor preservation, verification ordering, permission denial, missing records and rejected reads; workspace-helper tests verify that UUID normalization needs no alias lookup. For notification/event deep links, the page starts token and scheduling reads alongside the scoped event-date lookup after permission verification. A valid explicit date skips the lookup as before; invalid or missing dates use a valid stored event instant when available. Date-query errors retain their original precedence, and concurrent resource failures are handled while that lookup is pending. No resource reads begin before authorization. Coverage: page-date-loading.test.tsx uses an unresolved event response to verify overlap, actor/workspace filters, date-only and DST-offset links, fallbacks and both error paths. Browser latency improvement still requires post-deployment measurement.

Mobile continuous schedule geometry

Mobile three-day and week timelines retain their continuous buffered date window. Dragging remains continuous; releasing settles header, all-day strip and timed grid on the same day boundary. Selected-date navigation and window recentering preserve that alignment without replacing the loaded event range or cache. Timed event widths use connected overlap groups with half-open time intervals. Transitive overlaps share columns; an event starting exactly when a group ends belongs to a new group. Isolated groups receive the full available date-column width. This shared layout also applies to the mobile day timeline. All-day span backgrounds retain their date extent while their title and optional working-location icon stay inside the span’s intersection with the current viewport, clear of the fixed time gutter. Labels truncate when the visible portion is narrow; offscreen spans do not expose duplicate visible labels. All-day rows reserve enough height for the current text scale. These are display rules and do not change event dates, actor permissions, recurrence, providers or cache scope. Regression coverage: calendar_viewport_test.dart, date_snap_scroll_physics_test.dart and continuous_date_scroll_test.dart cover connected groups, visible clipped labels, native scroll settling, synchronized surfaces, continuous month traversal and programmatic date navigation. Widget coverage is separate from native-device gesture and provider verification.

Mobile timeline overlap geometry

Mobile day and multi-day timelines reserve columns for the painted minimum card height as well as timestamp overlap. This keeps adjacent short events and their tap targets separate, including enlarged text, while isolated groups still use the full column width. Card positions and durations retain sub-minute precision so rounded pixels cannot create an untracked overlap. Event timestamps, recurring rules, and provider writes remain unchanged. The fixed all-day gutter label stays on one ellipsized line; the complete localized label remains available to accessibility services. calendar_rendered_overlap_test.dart checks actual card bounds and bottom-edge taps at normal and enlarged text sizes, and the fixed all-day gutter. These widget checks require device gesture verification after delivery.

Mobile timeline zoom

Day, three-day, and week timelines support smooth two-finger pinch zoom from 65% to 250%, defaulting to 100%. The fractional time under the pinch stays under the fingers; shell-owned Timeline zoom controls offer accessible zoom in, zoom out, and reset actions with the same anchored geometry. One-finger scrolling, date swipes and snapping, event taps, and long-press creation keep their existing behavior. Event timestamps, durations, and all-day/date column widths do not change. Completed zoom is stored in the existing account/workspace-scoped Calendar cache and reused across timeline modes and dates. Workspace/account switches cancel unfinished pinches and reject retained control callbacks, including return-to-same scope and logout races; unavailable preference storage leaves zoom usable locally. Month, year, and agenda views retain their existing layout. Shared minimum card height remains part of both painting and overlap grouping at every zoom level. calendar_timeline_zoom_test.dart, calendar_zoom_lifecycle_test.dart, and calendar_timeline_zoom_state_test.dart cover gesture coexistence, focal anchors, bounds, accessible controls, and scoped preference restoration.

Day highlighting, all-day spans and past events

Mobile multi-day headers, timeline columns, month and year date fills highlight only the current civil calendar day in the resolved timezone. The first visible or selected navigation day remains neutral when it is not today; selection still drives navigation. All-day materials retain occurrence identity through row and viewport changes, using workspace, event identifier and start/end boundaries so recurring instances with reused provider identifiers stay distinct. Web and mobile preserve the stored UTC calendar dates of untagged legacy UTC-midnight all-day imports. Their original provider dates/timezone are absent from the current API. Other all-day boundaries project into the resolved display timezone; the end remains exclusive, including 23/25-hour DST days and long spans. This rendering policy does not rewrite provider data or claim date-only provider write support. Past events fade consistently across native, Google and Microsoft providers on Web using an overlay over the opaque fill. All-day spans fade only after their displayed exclusive end, including merged spans, using the shared calendar clock. Explicit adapter preservation, interaction, previews and pending optimistic writes remain exceptions. Mobile keeps its existing past-event presentation. Regression coverage is calendar_day_identity_test.dart, calendar_viewport_test.dart, all-day-event-layout.test.ts and past-event-treatment.test.ts.

Mobile selected-view reset

Tapping the selected floating Calendar view item resets its date and scroll position without changing the exact view mode. Day and three-day views start at today. Week starts at the current week’s boundary using the effective first-day preference (personal, workspace, then locale); it does not force today into the first column. Timed views restore the current-time viewport. Agenda returns to today, month to the current month, and year to the current year. The reset and Today action use Calendar’s projected timezone clock for both date selection and range loading. Repeated taps while already at today still reset scroll position. Reduced-motion settings use immediate scroll positioning. Other apps retain the shell’s existing scroll-first and section-reset behavior; Calendar’s existing explicit section reset still restores its default view. Coverage: calendar_view_reselect_test.dart exercises the real Calendar page and shared floating shell; calendar_scroll_reset_test.dart covers repeated resets, week preferences, timezone/year boundaries, reduced motion, and disposal. These source checks do not establish native-device or deployed runtime verification.