Preserve calendar delivery through native Relay and AISL lifecycle integration
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 15/100
Research direction
Do not begin implementation until the Relay and AISL owners resolve the blocked intent, snapshot, live-resolution, queue, and series-identity decisions. Read the existing calendar_invite.generate_ics/generate_series_ics services, event lifecycle and registration/access services, and the accepted contracts referenced in #1, #2, and #32. Done requires both the synthetic native Relay milestone and donor-bound AISL lifecycle parity checks, with no duplicate delivery or lost calendar semantics.
Written by the indexing model from the issue text.
Description
Preserve calendar delivery through native Relay and AISL lifecycle integration
Status: blocked for implementation; ownership, timing and series decisions remain unresolved. Mandatory P15 integration/adoption follow-up under Relay #30. This contract grants no ownership transfer or runtime permission. The optional MIME capability is an upstream stage, not the full preservation result.
Goal and dependencies
Carry the existing AISL calendar feature through the native authenticated Relay API→durable queue→worker→shared provider path, using the accepted calendar-alternative MIME stage and a thin AISL lifecycle adapter. Preserve recipient subject/plain/HTML/actions, iTIP semantics, trigger eligibility, delivery identity, audit and existing screens/routes. Do not introduce another renderer, version store, calendar generator, worker, provider client or importer.
Required upstream contracts: #1 canonical typed validation, immutable source/version/render/snapshot and credentials; #2 transactional request-hash/lease/state owner and #32 both-path outcome safety; #29 footer/#35 output profile; P03 sender/envelope; P07 accepted live-resolution/privacy/timing boundary; accepted optional MIME stage. Exact Relay/AISL events/jobs/release/ui/history owners must acknowledge overlapping paths/designs. #34/#1885 supply lossless normalized source inputs when needed; no second exporter. Real adoption additionally needs P06 callback/suppression, P08 schedules, #25 readiness/D13, #26 history and A6.1/A6.3/A6.4 owner receipts.
This full preservation contract has separately verifiable Relay and AISL milestones. Follow each repository's issue/role/verification lifecycle; identify the linked AISL implementation/adoption tracking owner before code work. A Relay-only synthetic pass can be recorded without closing the full P15/parent obligation. No duplicate canonical-engine card is created or source ownership granted here.
A. Native Relay capability
- Add only the accepted optional calendar profile to the existing single-recipient native send/dry-run contract and canonical delivery-affecting projection. Reuse MIME-stage validator and builder, #1 source selection/typed-context validation, and #2/#32 request hash/immutable message/state/worker boundaries. No arbitrary MIME/raw-byte escape hatch, AISL type/model import or new route. Expose an explicit documented versioned schema; resolve its exact input-versus-prepared-output placement with owners before implementation.
- Closed calendar shape, declared REQUEST/CANCEL matching unique VCALENDAR METHOD, UTF-8 content, safe Content-Type name, owner-approved capacity and protected-header rules. Reject simultaneous nonempty ordinary message_parts, duplicate calendar profiles/methods, wrong types and unsupported MIME overrides safely. No silent strip/truncate or reinterpretation of ordinary attachments.
- Preflight unsupported input/profile/content/client/version before durable contact/message/event/queue/provider effects. Rendering/dry-run remain zero-write. Calendar cannot be smuggled through unvalidated generic metadata. Generic calendar validation does not rerender or rewrite UID, SEQUENCE, organizer, attendee, timezone or URLs.
- Canonical snapshot/projection owns exact selected version/profile, recipient, sender/options, subject/plain/HTML and calendar content/method/representation reference as agreed by #1/#2. A later draft/profile/event edit must not change already prepared content. Queue payloads are scalar/fenced references, not secret body blobs. Private body/calendar values stay out of logs/errors/audit exports; legitimate final snapshots/history remain according to their accepted retention policy.
- Same client/key/canonical intent replay returns its existing immutable identity/state. Delivery-affecting changes, including calendar method/content/source/options, conflict rather than converting a REQUEST into CANCEL or creating a second send. Canonicalization/hash version and the timing relation between intent identity and late resolved output belong to #2/#1/P07 owners; do not invent a second hash scheme or let volatile minted links make exact replay conflict.
- Existing worker entrypoints/recovery enqueue load the accepted frozen/fenced projection and invoke the one existing SES sender. Claim/suppression/sender eligibility, stale lease completion, SDK retry fencing and unknown-outcome recovery consume #2/#32. Accepted/unknown results never become an automatic second provider request; safe known-unsent retries retain normal behavior. Provider accepted is not delivered.
- Omitted calendar field retains all current native clients, simple/raw headers, ordinary multipart/mixed attachments/dispositions, CC/BCC privacy, Reply-To/configuration-set/rate policy and response/auth/error semantics. Recipient-list/campaign/inbound paths are unchanged; AISL series fan-out uses per-recipient intents, not a generic list payload that shares one ATTENDEE/calendar/key.
B. Durable inputs, live resolution and immutable final snapshots
All original AC6 checks remain: before any durable business-input row/job, recursively reject absolute/scheme-less URLs, bearer-query and AWS-signed forms; only a sanitized top-level return_path is excepted. Errors expose purpose/path, never values. Resolve live relationships and action tokens using accepted delivery-time clocks, augment only in-memory context, preserve stored context/hash, and permanently fail closed for missing/stale/expired/mismatched bindings.
Final rendered email legitimately contains links. Preserve #1's immutable version/message/history snapshots, including approved final calendar delivery content. The published P07 clarification distinguishes retryable business input from final output; it imposes no blanket snapshot ban and grants no early bearer persistence or timing waiver.
Before implementation owners must resolve where intent persistence, live AISL resolution, final source/content preparation, provider queue/claim and snapshot freezing occur. #1 requires final snapshots before provider queueing; P07 requires actual delivery-time token/live checks. If provider work waits after preparation, early rendering is not evidence of freshness. Record an accepted generic native contract that meets both; do not invent a Relay-to-site callback, copy AISL hooks into Relay, remint already frozen content on retry or delete snapshots to make the problem disappear. Until agreed, real AISL API adoption is blocked and donor raw delivery remains.
C. Thin AISL lifecycle adapter
Use existing calendar_invite.generate_ics/generate_series_ics and event lifecycle/registration/access services. AISL owns purpose/classification, sender mapping, scalar relation IDs, recipient/timezone/greeting policy, cancellation/action links, eligibility and semantic revision; Relay consumes the agreed normalized generic contract. Existing authoring, registration/cancel/host/series routes and permissions remain unchanged.
| Flow | Required identity and semantic preservation |
|---|---|
| Attendee registration | Existing event-registration:event:user:registration scope; correct ATTENDEE/organizer; stable event UID and current sequence. Cancel then re-register creates a new registration intent, not a replay of the old REQUEST. |
| Host assignment | Existing event-host-registration:event:user:host_access_version and HostRegistrationDelivery generation; current assignment/access checks; removing/readding uses new generation. |
| Reschedule | Existing event-rescheduled:event:user:ics_sequence scope; semantic revision owned once by AISL. Old and new start future; absolute start/effective-end change at least60seconds. Preserve effective default end and already-sent host generation/sequence guard. |
| Cancellation | First future transition to cancelled bumps sequence once; event-cancelled:event:user:ics_sequence; same UID, CANCEL and STATUS:CANCELLED. Replay cannot bump sequence/send again. |
| Series registration/update | Per-recipient multi-VEVENT with each occurrence UID/sequence; actual enrolled/upcoming/non-draft/non-cancelled/access-eligible occurrences chronologically ordered. Changes/additions preserve donor targeting and changed-occurrence old→new framing, whole-series fallback and partial-access upgrade note. |
| Series cancellation | Single cancelled occurrence VEVENT only to subscribers registered for it; stable occurrence UID/bumped sequence. Preserve one-off versus series recipient separation so the same change does not produce two competing emails. |
Namespace existing keys through canonical client/source mapping without dropping registration/access-generation/sequence. UID alone, recipient email alone or an unordered set of current occurrences is not delivery identity. Series donor service has no explicit durable dedupe key proving replay safety; owners must define a stable source intent/revision identity that distinguishes legitimate registration/update/addition/cancellation yet converges on replay. Document this as an unresolved integration decision, not a pre-existing donor guarantee or new assumed series-wide UID.
Retain permanent-bounce and actual donor access/recipient exclusions, per-recipient failure isolation, named/nameless greeting, timezone/weekday/help lines, full subject/plain/HTML/chrome/footer/action content and safe notices/history behavior. Preserve subject/recipient/provider/source audit facts and historical snapshots through #26/P09 ownership, not a second log engine. Preserve ordering/concurrency and after-commit scheduling; reuse P08 registry and existing AISL trigger logic rather than generic Relay lifecycle rules.
Acceptance and meaningful verification
Native capability milestone — synthetic, no external service
- Authenticated native API→actual durable message/reference→actual queue-shaped entrypoint→worker→mocked shared provider carries exact selected calendar content/method through the accepted snapshot boundary. Parse outgoing raw bytes: multipart/alternative with direct plain,HTML,calendar-last; UTF-8, correct method/name, no Content-Disposition. Compare decoded full content, not a builder or file extension.
- Wrong client/scope/version, wrong type/method/METHOD, duplicate profile, unsafe name/header, oversize or conflicting attachments create/enqueue/send nothing. Dry-run/preview share native validation/source/profile with zero contact/message/event/job/provider effects. Error/redaction canaries expose no protected values.
- Replay/concurrent first insert, changed method/content/options, draft/profile changes after preparation, duplicate worker, expired/stale lease and late result preserve #1/#2 identity/snapshots; provider-accepted response loss stays ambiguous with zero automatic resend through every recovery/SDK path. Existing #2 PostgreSQL/concurrency gates remain; do not replace them with weaker fakes.
- Existing absent-calendar simple/header/ordinary attachment path, tenant isolation, status/errors, sender/options and UI/API/history behaviors remain characterized and pass. Meaningful controls replacing alternatives with mixed/disposition, moving calendar beforeHTML, dropping a body or losing projection fail assertions.
AISL adapter/lifecycle milestone — synthetic donor-bound parity
- Registration→duplicate→reschedule→cancel→cancel replay→re-register preserves stable UID, correct sequence/method/status and distinct legitimate registration intents. Host assignment/removal/readd/current-generation replay preserves access/generation and exactly the intended recipients.
- [ ]59/60second start/end boundaries, past/now/future, effective end and first-cancel-only conditions; stale registration/host/user/series/access bindings and bounce suppression; same UID for two recipients never collapses one. Schedule/job duplicate/reorder and concurrent triggers preserve canonical intent identity without double sequence increments/provider calls.
- Series registration/update/new occurrence/cancellation, partial access/no-access, changed-occurrence framing and fallback, multi-event chronological selection and single-event CANCEL; one-off/series partition. Approved stable series replay decision has explicit concurrent/reordered/restart controls. No claimed guarantee without that decision.
- Compare donor and native subject/plain/HTML/calendar/envelope/header outputs with content-safe synthetic named/nameless/timezone/DST/override/footer/action fixtures. Explicit normalizations only for justified transfer encoding/boundaries, fixed synthetic token/clock values and controlled DTSTAMP; never erase authored formatting, URL targets, UID/SEQUENCE/ATTENDEE/organizer/timezone/STATUS or recipient-visible differences. #35/P03 gates remain dependencies, not assumed defaults.
- Before enqueue all AC6 URL forms/exception/recursive/error tests hold; delayed processing demonstrates accepted token-clock and live-resolution timing, stored context/hash unchanged and final snapshots immutable. Unknown resolution/source identity remains blocked. Mutations omitting registration/access generation, series recipient partition, sequence/relation checks or context guard must fail relevant assertions, not unrelated setup.
Full adoption milestone — separate authorized owner receipts
- Fresh independent Tester terminal reports and PM recipient/lifecycle fidelity bind exact Relay/AISL/package/source/schema/profile/fixture hashes, commands/counts/exits, inspected outgoing/rendered artifacts and unresolved fields. Static test references do not count as executed proof. Each repository follows its own required gates and role/commit process.
- Exact deployed Relay native/OpenAPI contract, required tagged package dependency, real source-of-truth overrides, #25/D13 sender/readiness, callback/history donor equivalence and AISL development-copy rehearsal are accepted by authorized owners. Appropriate owner-operated calendar-client interoperability receipts remain required where local MIME parsing cannot prove client behavior. No agent credential/production access.
- A6.3/A6.4 fence old and new enqueue/schedulers, classify pending/claimed/accepted/ambiguous intents, preserve stable cross-backend identity, drain/transfer/reconcile, revoke stale leases and route callbacks without gaps/duplicates. Rollback pauses Relay and restores only proven unsent intents; accepted/ambiguous sends cannot be automatically replayed on donor. Rehearse lifecycle/series cases as well as ordinary email.
- Keep donor raw path, calendar generator/lifecycle owner, existing screens/routes/tasks/data/history and auth/consent/safety behavior until accepted replacement/adoption/rollback receipts. Any transport/hook/job contraction needs a separate named deletion ledger; no deletion or parent completion follows from capability-only acceptance.
Ownership, size and stop conditions
Proposed Relay changes: thin native send/dry-run payload/schema projection and sender call sites, cohesive calendar projection service only if absent; current mailing/services/transactional.py, transactional_sender.py, shared API-doc source and model/snapshot serializers require exact #1/#2/#32/aisl/ui/history ACKs. MIME builder/ses.py belong to the upstream MIME-stage owner; reuse them, do not reimplement.
Proposed AISL changes: one thin events/services/relay_calendar.py adapter if needed, narrow registration_email.py/calendar_lifecycle.py/series_invite.py and notify_reschedule/notify_cancellation/notify_series_invite/host delivery entrypoints. Current events/jobs/release/#1698 owners must ACK, and #1885/#1851 reserved paths remain excluded unless their owners explicitly coordinate. One business owner per concern, explicit transactions/thin APIs, no ternaries, functions<=30/new handwritten files<=300; no oversized orchestrator/model growth waiver or arbitrary fragments. Cohesive canonical extraction is owner-reviewed if needed, not a calendar-engine refactor.
Stop on missing owner ACK, unresolved input/preparation/provider timing, series intent/hash semantics, unsupported profile/footer/context construct, provenance/output/history mismatch or failed required gate. Do not shrink full P15 acceptance or weaken #1/#2/#32/AC6 to proceed. Parent #30 remains open. No live import/send/deployment/cutover/deletion permission is granted by this specification.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- Avg merge
- 7h 12m
- Merged PRs (30d)
- 12
Getting set up
- Ships a Dockerfile or Docker Compose file
- No pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from DataTalksClub/relay
-
bug
Difficulty 5/5 Over a week Newbie friendliness 20/100
DataTalksClub/relay#42 · 7 comments ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 15/100
DataTalksClub/relay#41 · 9 comments ·
Maintainers usually reply within 1 day
-
community-base enhancement
Difficulty 5/5 Over a week Newbie friendliness 25/100
DataTalksClub/relay#39 · 6 comments ·
Maintainers usually reply within 1 day
-
community-base enhancement
Difficulty 5/5 Over a week Newbie friendliness 15/100
DataTalksClub/relay#35 ·
Maintainers usually reply within 1 day
-
community-base enhancement
Difficulty 5/5 Over a week Newbie friendliness 18/100
DataTalksClub/relay#34 ·
Maintainers usually reply within 1 day
All issues in DataTalksClub/relay
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
KalicoCrew/kalico#1012 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 82/100
esphome/esphome.io#7657 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
VNG-Realisatie/gemma-zaken#2658 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
comp/gateway comp/plugins duplicate P3 type/bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
NousResearch/hermes-agent#137019 ·
Maintainers usually reply within 1 day