Seed catalogue · Scheduling

Dial

An invitee-first, self-hosted scheduler for one business or independent host.

Alternative to
Calendly, under MIT
Domain
booking against an availability rule
Version
0.1.0
Contract
69 clauses across 12 areas
Maturity
runtime-spine-public-port
Dial screenshot 1: home desktop
Dial screenshot 2: profile desktop
Dial screenshot 3: preview desktop
Dial screenshot 4: operator dashboard desktop

4 screenshots from the product's own visual and verification artifacts. Its handover records what was exercised.


What you get

Everything below is generated from the seed's own manifest and contract. No rounded-off claims, no numbers we made up.

Operating cost

Estimated, not free by default

The seed's own cost declaration, unedited.

Status
estimated
Estimated At
2026-08-31
Currency
USD
Basis
One host, one operator, 1,000 bookings per month, the default two reminders when both offsets apply, four to six transactional emails per unchanged booking, and usage inside Google Calendar's standard quota.
Low Monthly
20
Typical Monthly
25
Notes
At this basis, Resend Pro is the $20 low case and adding Cloudflare Workers Paid gives the $25 typical case. Smaller deployments can fit both free allowances. More operators, changes, requests, or retries increase mail volume. Google Calendar standard use currently has no additional charge below its quota, but Google states over-quota billing is planned later in 2026.

Externals declared

3 externals, each with a reason

Under BASE-DATA-004, user data leaves only through what is declared here.

google-calendar
A scheduler must read the host's real busy time and place accepted bookings on the calendar people already use; Cloudflare has no calendar primitive. EVENT-006 blocks publishing any event type without a healthy destination-calendar connection, and AVAIL-004 fails booking closed without a readable calendar.
google-meet
The prototype's default location is a real Google Meet conference, which requires provider-side conference creation. EVENT-004 also lets an event type use a fixed link, a phone number, or an in-person address instead, so a deployment can run with no event type ever using Meet.
resend
Cloudflare does not provide transactional email delivery or bounce webhooks; confirmations and change notices must reach external inboxes. EVENT-006 also blocks publishing any event type without a healthy mail-provider connection.

Extension points

41 declared integration conveniences

These hooks are optional conveniences. Owners may change any source, including core logic, schema and infrastructure; their agents adapt useful upstream fixes and verify the result.

operator.route.v1operator.page.v1operator.navigation.v1operator.settings-section.v1job.handler.v1cron.handler.v1queue.consumer.v1operator.management.v1booking.questions.v1availability.recommendation.v1booking.reschedule.v1booking.cancellation.v1availability-request.routing.v1reminder.schedule.v1calendar.external-deletion.v1profile.updated.v1event-type.published.v1event-type.disabled.v1event-type.deleted.v1booking.confirmed.v1booking.rescheduled.v1booking.cancelled.v1availability-request.created.v1availability-request.handled.v1availability-request.closed.v1calendar.connection-health-changed.v1delivery.failed.v1operator.navigation.after.v1operator.dashboard.after.v1event-type.header.actions.v1event-type.settings.after.v1booking.list.row-actions.v1booking.detail.sidebar.after.v1booking.detail.actions.after.v1availability-request.detail.after.v1public.profile.after.v1public.event.before-booking.v1public.confirmation.after.v1settings.calendar.after.v1calendar.provider.v1mail.sender.v1

Declared limits

Capacity, stated up front

Straight from seed.json → limits. Where a value is an estimate the seed says so.

Status
estimated-until-load-tested
Estimated At
2026-08-31
Max Operators
10
Max Event Types
100
Max Focus Areas
6
Max Focus Area Chars
40
Max Social Proof Entries
3
Max Social Proof Chars
280
Max Booking Questions Per Event Type
25
Max Question Options Per Question
50
Max Availability Overrides Per Event Type
1,000
Max Request Dates Per Request
10
Max Request Windows Per Request
20
Max Conflict Calendars
10
Availability Lookahead Days
365
Max Bookings
100,000
Max Bookings Per Month
10,000
Concurrent Slot Claims
50
Public Requests Per Ip Per Minute
120
Booking Mutations Per Ip Per Minute
10
Alternative Requests Per Ip Per Hour
5
Webhook Requests Per Provider Per Minute
600
Max Upload Bytes
5,242,880
Allowed Upload Types
image/jpeg, image/png, image/webp, image/avif

Non-goals, stated proudly

A product that says what it will never do is a product you can trust to stay small, fast and legible. These are refusals, not gaps.

  • Multiple hosts or workspaces
  • Roles and permissions
  • Team round-robin or collective scheduling
  • Group events, classes, waitlists, or resource capacity
  • Additional invitee guests on a booking
  • Bookings that wait for host approval before they are confirmed
  • Payments, deposits, refunds, or booking fees
  • Recurring booking series or scheduling polls
  • Marketplace discovery, ratings, or invitee-submitted reviews
  • SMS, WhatsApp, phone automation, CRM, campaigns, or marketing automation
  • Automatic adoption of arbitrary external-calendar time or location edits
  • AI routing or ranking
  • Native mobile apps

The contract

All 69 clauses of Dial, from its own CONTRACT.md. Stable IDs identify requirements; the source handover and verification evidence distinguish implemented, tested and uncovered behavior.

AUTH5 clauses

AUTH-001
Public authority.

Supersedes BASE-ACCESS-004 for the paths listed in seed.json → deploy.publicPaths and for no others. Those paths authorise the caller by the capability material named in AUTH-002 to AUTH-005 instead of an operator session, each capability grants exactly the one action or record it names, and a request carrying no valid capability material changes nothing. Every other mutation requires a valid operator session and a server-side ownership check.

AUTH-002
Booking nonce.

Reaching the details step for a selected slot, and reaching the review step of an alternative request, each issue a single-use nonce of at least 256 bits from a cryptographically secure random source, bound to the event type and to either the selected slot or the composed alternative request, and expiring 30 minutes after issue. The nonce is not bound to a browser: possession of an unexpired, unconsumed nonce is what authorises the confirmation. A confirmation whose nonce is missing, unknown, expired, or bound to different values creates nothing and answers per PUBLIC-003; a nonce that has already been consumed is answered by BOOK-003.

AUTH-003
Booking access.

A booking is readable and changeable from a public surface only through the manage token defined in BOOK-006. A booking ID, an invitee email address, or any other guessable identifier grants access to no booking data.

AUTH-004
Calendar authorisation callback.

The calendar OAuth callback accepts only signed state that is bound to the operator session that started the connection and was issued less than 10 minutes earlier. State that is missing, unsigned, mismatched, replayed, or expired stores no credential, connects no account, and returns 400.

AUTH-005
Provider callbacks.

A calendar or mail provider callback is accepted only when the provider's own authentication passes — its registered channel identity or its request signature — together with the secret configured for that provider. A callback that fails the check returns 401 and changes nothing.

OPER4 clauses

OPER-001
Equal operators.

Every operator can see and act on the same host profile, event types, availability, calendar connections, bookings, and requests. There are no roles.

OPER-002
Operator management.

Operators are invited to, and removed from, the sign-in allow-list in settings. Removing an operator ends their sessions within 60 seconds and changes no record they created, including the calendar connection they authorised. Policy: operator.management.v1; default: any operator may invite or remove another, the operator configured at setup can be removed only by themselves, and the last remaining operator cannot be removed.

OPER-003
Booking workspace.

Operators can list bookings filtered by the lifecycle states of BOOK-004, and independently by whether the start instant is in the future or the past, by event type, by date range, and by whether any external delivery has failed. Case-insensitive substring search over invitee name and email address returns within 500ms. Lists are sorted by start instant.

OPER-004
Booking record.

A booking record shows the event type, every invitee answer and custom-field value, the start and end in both the host's and the invitee's IANA zones, the location or meeting link, the history from BOOK-010, the separate state of the calendar event, the meeting link, and each email, and every recorded failure with its CAL-005 or NOTIFY-005 reason.

PROFILE3 clauses

PROFILE-001
Host profile.

Operators edit the host's name, title, biography, avatar, IANA timezone, focus areas, and social-proof entries, within the counts and lengths in seed.json → limits. A social-proof entry is a quotation and an attribution typed by an operator: Dial collects no invitee feedback and publishes no rating, score, or count it did not receive from an operator. There is exactly one host timezone per deployment and it is the zone every other clause means by "the host's zone". The in-app preview renders the same content as the public page.

PROFILE-002
Public profile.

The host profile is served at /book/<handle>, where the handle is set by an operator. It shows the configured host content and every published, listed event type, and never a draft, unlisted, or disabled one. An operator can change the handle; the previous handle then answers per PUBLIC-005.

PROFILE-003
Avatar asset.

Supersedes BASE-INPUT-003 for the /media/ prefix only. The avatar is an upload within the size and type limits in seed.json → limits, stored in R2 and served under /media/ with its declared content type and inline rather than with a download disposition, because it renders as an image on the public profile and event pages. That prefix is the public delivery channel the baseline requires a product contract to name; every other upload rule still applies, and no other upload in this product is publicly readable.

EVENT6 clauses

EVENT-001
Event type lifecycle.

Operators create, edit, publish, disable, and delete event types. An event type is draft, published, or disabled, and a published one is either listed on the public profile or unlisted and reachable only by its own URL. Each carries a title, description, a single duration of 5 to 480 minutes, colour, location, and a slug unique among event types, and is served at /book/<handle>/<slug>. A slug can be edited; the previous slug is not retained and then answers per PUBLIC-005, while existing bookings and their manage links are unaffected.

EVENT-002
Scheduling constraints.

Each event type configures its recurring availability, date-specific overrides, slot start increment of 5, 10, 15, 30, or 60 minutes, minimum notice of 0 minutes to 7 days, maximum booking horizon of 1 day to seed.json → limits.availabilityLookaheadDays, before and after buffers of 0 to 120 minutes each, and an optional maximum number of bookings per host day, where a host day is one calendar date in the host's timezone. A new event type starts at a 30-minute duration, a 15-minute increment, 4 hours' minimum notice, a 60-day horizon, no buffers, and no host-day limit.

EVENT-003
Invitee questions.

Each event type has ordered booking questions of type text, textarea, single choice, multiple choice, or checkbox, each required or optional, within the question and option counts in seed.json → limits. Choice options have stable values and editable labels, and a submitted option not configured on the event type is rejected. A name and a syntactically valid email address are always required. Policy: booking.questions.v1; default: name and email, plus an optional agenda of at most 500 characters, on every new event type.

EVENT-004
Location.

An event type uses exactly one location: a Google Meet conference provisioned per CAL-003, a fixed link the operator supplies, a host phone number the invitee calls, or an in-person address. The public event page shows only the location's label; the link, number, or street address appears only after confirmation — in the receipt, the invitee's email, and the calendar event. Dial never collects an invitee phone number.

EVENT-005
Removing an event type.

Supersedes BASE-DATA-003 for event types only: disabling or deleting an event type removes its public page and all its future availability but does not cascade to its bookings, which keep their times, manage links, calendar events, history, and their own copy of the event title, duration, and location. Invitee data is erased under DATA-002, not by deleting an event type.

EVENT-006
Publication readiness.

An event type can be published only when it has at least one open availability window and when its transactional-mail configuration, its destination calendar, and, where its location is provider-generated, its conferencing capability each passed a connection check within the last 24 hours or since they last changed. A connection check is a live read of the destination calendar, a credential probe against the mail provider, and, where conferencing is used, a capability check against the conferencing provider; an operator can run it on demand. The operator sees each unmet requirement named. A requirement that becomes unhealthy after publication does not unpublish the event type: the connection state changes under CAL-006 and public booking behaves under AVAIL-004.

HOME1 clause

HOME-001
Owner front door.

The deployment root / is a sessionless owner-facing landing, not a vendor marketing page. It renders the deployment-configured owner identity and single-line description, and links to the host's public booking profile when one is available. Its Powered by Dial · runeditrun.com footer credit is a static link controlled by deployment configuration, enabled by default and omitted when disabled.

PUBLIC6 clauses

PUBLIC-001
Event presentation.

A published event page names the host and the event and shows its description, duration, public location label, the invitee's selected timezone, the recommended times of AVAIL-007, every other valid slot in the displayed week, week-by-week navigation bounded by today and the booking horizon, the change window the booking.reschedule.v1 and booking.cancellation.v1 policies currently enforce, and, when the event type enables it, the alternative-request path.

PUBLIC-002
Invitee-first flow.

An invitee views availability and completes a booking without an account and without signing in. Before confirmation the flow asks only for the event type's configured questions, names who receives the answers — the host and the connected calendar provider — and links the privacy notice URL configured for the deployment.

PUBLIC-003
Progress and recovery.

The public flow has distinct choose-time, details, and confirmation states, each at its own URL, and reloading or navigating back preserves a still-valid selection. The selection and its nonce are carried in the URL and in the browser's session storage; the public flow sets no cookie. An expired nonce, or an expired or rotated manage token, returns 410; an unknown or mismatched one returns 404. Both render a page that offers a fresh start and that contains no booking, invitee, or sample data.

PUBLIC-004
Embed.

Operators copy an asynchronous script tag naming a public event slug and inline or modal mode. Inline mode renders where the tag sits; modal mode opens only from an element whose data-dial-embed attribute names that embed. The initial script is under 50KB gzipped, and the embedded flow offers the same booking, reschedule, and cancel actions as the standalone page.

PUBLIC-005
Unavailable pages.

An unknown, draft, disabled, deleted, or renamed profile or event URL returns 404 and reveals nothing about whether a record ever existed there. This governs profile and event URLs only; manage-token responses are governed by PUBLIC-003, where a rotated or expired token deliberately returns 410 so the invitee knows to ask for a new link. A published event type with no valid slot inside its horizon still returns 200, says so, and offers the alternative-request path when the event type enables it.

PUBLIC-006
Abuse.

A public request refused by the rate limits of BASE-ACCESS-003 returns 429 and the flow keeps the invitee's selection and answers so the same person can retry without re-entering them. An operator can block an email address or a domain; a submission from a blocked address is refused with a message that does not say it was blocked, and creates no booking, request, notification, or calendar event.

AVAIL9 clauses

AVAIL-001
Schedule and overrides.

Recurring availability is a set of wall-clock windows per weekday in the host's IANA timezone. A date override replaces the recurring windows for one host date and may open or close that whole date. Editing a schedule or an override changes future availability only; it never alters a confirmed booking.

AVAIL-002
Valid slots.

A slot is offered only when every one of these holds: its start falls on the event type's start increment measured from the start of its open window; the full duration fits inside that one window; the start is within the booking horizon and beyond the minimum notice; its host day is under the event type's booking limit; and it overlaps no booking in the confirmed state for this host on any event type and no busy interval from any selected conflict calendar, an external event the provider marks free being ignored. Anything else is not offered.

AVAIL-003
Buffers.

The event type's before and after buffers extend the interval that must be free around a candidate slot, over both confirmed Dial bookings and external busy intervals. A buffer never changes the invitee's start or end time, the duration shown anywhere, or the times on the calendar event and invitation.

AVAIL-004
Freshness and failure.

Availability is recomputed when the event page or a week loads. Changing the invitee's timezone re-renders and re-ranks the same slots and needs no new calendar read, because slot validity does not depend on the invitee's zone. A displayed slot may rest on cached provider busy data no more than 5 minutes old; the final check in BOOK-001 uses provider data no more than 60 seconds old. Every selected conflict calendar is required, and a provider read that does not complete within 5 seconds counts as unreadable. If a required calendar is unreadable at either point, Dial offers and confirms no slot for that host and tells the invitee that booking is temporarily unavailable, rather than offering unverified time.

AVAIL-005
Timezones.

Every invitee-facing time is rendered in the invitee's selected timezone, which starts as the browser's IANA zone when the browser reports one and as the host's zone when it does not. The zone is resolved in the browser and slot instants are fetched in UTC, so no visitor-derived value reaches the server on page load, as BASE-PUBLIC-001 requires: the invitee's zone is sent only with a request their own action causes — changing the zone, moving week, or selecting a slot. The invitee can change the zone at any point before confirmation, every rendered time carries its zone name and UTC offset, and the details and confirmation surfaces also show the host's local time. A confirmed booking stores the UTC instant and both the host's and the invitee's IANA zone identifiers.

AVAIL-006
Daylight saving time.

A local time that does not exist during a forward transition is never offered. Repeated wall-clock times during a backward transition are shown with distinct UTC offsets, so each offered time maps to exactly one instant. A DST transition between confirmation and the meeting never moves a booking's stored UTC instant, and the host and invitee renderings each follow their own zone's rules.

AVAIL-007
Recommendations and filters.

At most 5 recommended times are shown, each a slot already valid under AVAIL-002 and each showing the reason it was chosen. The ordering is deterministic: the same inputs always produce the same order. The first render of a page ranks in the host's zone alone; the ranking is recomputed once the invitee's zone reaches the server under AVAIL-005. An invitee-facing filter only narrows or reorders slots already valid under AVAIL-002 and can never surface one that is not. Policy: availability.recommendation.v1; default: slots fully inside 09:00–17:00 in both the host's and the invitee's selected zone first, then the larger sum of contiguous free minutes immediately before and after the slot, then the earlier UTC start.

AVAIL-008
Response time.

Loading one week of availability for one event type returns within 2 seconds.

AVAIL-009
Operator diagnostics.

For any time an operator evaluates, Dial names which rule excluded it — schedule, date override, start increment, minimum notice, horizon, buffer, host-day limit, an existing Dial booking, or a conflict-calendar busy interval — without disclosing external event detail that CAL-002 does not retain.

BOOK12 clauses

BOOK-001
Final validation.

Confirming a booking revalidates every answer against the event type's current questions and rechecks the selected slot under AVAIL-002 against a fresh conflict-calendar read. Any failure creates no booking, no calendar event, and no email, and names the reason: an invalid or missing answer returns 400, and a slot that is no longer valid returns 409.

BOOK-002
Atomic claim.

Every slot admits at most one booking in the confirmed state. Claiming the slot and recording its calendar, meeting, and notification commands happen in one transaction that either commits entirely or leaves nothing behind. Of any number of concurrent confirmations for the same slot exactly one commits; every other returns 409 with a slot_taken code and is returned to the choose-time step with availability recomputed.

BOOK-003
Idempotent confirmation.

Replaying a confirmation with an already-consumed nonce and an identical payload returns the stored result of the original booking and creates no second booking, calendar event, meeting link, or email. Replaying it with a different payload returns 409 and creates nothing.

BOOK-004
States and occurrences.

A booking is confirmed, cancelled, or rescheduled, and has one or more occurrences of which exactly one is current: a reschedule closes the current occurrence and opens a new one under the same booking ID and iCalendar UID. The calendar event, the meeting link, and each email carry their own pending, succeeded, or failed state; none of them changes the booking's state, and no external failure silently cancels or moves a booking.

BOOK-005
Confirmation receipt.

Within 2 seconds of a successful claim the invitee is shown the event, the start and end in their own zone and in the host's, the duration, the host, the location or its pending state, the calendar file of CAL-009, and the manage link of BOOK-006. The join control is enabled only when a provisioned joining URL is stored on the booking; while CAL-003 is still pending it is disabled and labelled as pending.

BOOK-006
Manage link.

Every confirmed booking has a manage link whose token carries at least 256 bits from a cryptographically secure random source and grants view and change access to that one booking, without creating an invitee account. The token is transmitted only to the invitee, in their own email and on their confirmation page; operator surfaces show the booking but never the token, offering an action that copies or resends the link instead. A reschedule keeps the token, which always resolves to the booking's current occurrence. The token expires 90 days after the booking's start instant, and an operator can rotate it, which invalidates the previous token immediately. A request with an expired, rotated, or unknown token answers per PUBLIC-003 and discloses no booking data.

BOOK-007
Invitee rescheduling.

The holder of a booking's manage link can move it to another slot on the same event type. The new slot is validated under BOOK-001 with only this booking's own occurrence excluded from internal conflicts, then claimed under BOOK-002 before the old slot is released; if any step fails, the original booking is unchanged and still confirmed. Policy: booking.reschedule.v1; default: any number of reschedules, allowed until the booking's start.

BOOK-008
Invitee cancellation.

The holder of a booking's manage link can cancel it with an optional reason. Cancellation cannot be reversed, releases the slot and its buffers within 5 seconds and before the next availability computation, and repeating it returns the same result without sending a second notification. Policy: booking.cancellation.v1; default: allowed until the booking's start.

BOOK-009
Operator changes.

An operator can reschedule or cancel any confirmed booking under BOOK-002, BOOK-007, BOOK-008, BOOK-010, CAL-003, and NOTIFY-004. The reschedule and cancellation policies constrain invitees only: an operator may also act on a booking that has already started, and may reschedule onto a time outside published availability after confirming that override explicitly, but never onto a time that overlaps another confirmed booking.

BOOK-010
History.

Rescheduling records the original occurrence as rescheduled and links it to its replacement. Every creation, cancellation, and reschedule records who acted — the manage-link holder, the named operator, or the calendar provider under CAL-008 — the time, the previous and new start, and any reason given.

BOOK-011
Attendance.

After a booking has ended an operator can mark it attended or a no-show and add a note. The mark records the operator and the time, appears in the booking record and the export, changes no lifecycle state and no calendar event, and sends the invitee nothing.

BOOK-012
Operator-created booking.

An operator can create a booking, for an invitee whose name and email address they enter, on any slot valid under AVAIL-002, optionally overriding the minimum notice and the horizon but never the conflict and buffer checks. The invitee then receives the ordinary NOTIFY-001 confirmation and manage link, and BOOK-010 records the operator as the actor.

CAL9 clauses

CAL-001
Calendar connection.

An operator connects the host's Google Calendar account through OAuth under AUTH-004, selects up to seed.json → limits.maxConflictCalendars calendars whose busy intervals block availability, and selects exactly one calendar to receive Dial's bookings. There is exactly one connection; it belongs to the deployment rather than to the operator who authorised it, reconnecting replaces it and keeps the destination selection, and an operator can disconnect. After a disconnect, sync stops, the connection shows as disconnected, published event types keep their pages but offer no slot under AVAIL-004, and existing bookings and their history are unchanged. The implementation is replaceable through calendar.provider.v1.

CAL-002
Busy privacy.

A calendar read retains only the identifiers, time bounds, transparency, and deletion state needed for conflict detection and sync. Titles, descriptions, attendees, and locations from conflict calendars are never stored, and so are never shown to an invitee or to an operator.

CAL-003
Managed event.

Within 60 seconds of a successful claim the destination calendar holds one event for the booking carrying the event title, the booking's start and end with explicit timezone data, a stable iCalendar UID, the configured location or a Google Meet conference provisioned for this booking, and the invitee as an attendee so the provider's own invitation and updates also reach them — or the booking's calendar state is pending and CAL-005 applies. An unsuccessful or ambiguous result is handled under CAL-004 and CAL-005.

CAL-004
Idempotent side effects.

Every calendar and meeting command carries the booking and occurrence IDs as its provider idempotency key. After a timeout, a lost response, or any other ambiguous result, the next attempt looks the object up by that key and updates it instead of creating a second one.

CAL-005
Provider failure.

A transient calendar or meeting failure is retried up to 5 times over 1 hour. Until it succeeds the operator and the invitee receipt show the side effect as pending; after the retries are exhausted the operator sees a typed sanitised error code, safe remediation, and a retry action, while the invitee sees only that calendar setup is incomplete and that they should contact the host. The booking stays confirmed, and raw provider errors are neither persisted nor rendered.

CAL-006
Connection health.

Revoked credentials, a refused token refresh, an invalid sync cursor, a push channel that cannot be renewed, or exhausted provider quota puts the connection in an unhealthy state that operators see in settings by name and that raises calendar.connection-health-changed.v1. An invalid cursor or a lapsed channel triggers a full resync before the next availability computation. While a required conflict or destination calendar is unreadable, public booking fails closed under AVAIL-004 and no event type can be published under EVENT-006.

CAL-007
Provider callbacks.

Calendar push channels are renewed before they expire. A callback authenticated under AUTH-005 is processed independently of arrival order: duplicate or out-of-order delivery cannot duplicate a booking change or undo a newer one, and a callback describing a state older than the one held is discarded.

CAL-008
External deletion and edits.

Deleting Dial's managed event in the destination calendar cancels the booking exactly once and sends the ordinary cancellation notices of NOTIFY-004. Any other external edit to the event's time or location is recorded as a sync conflict on the booking showing both times; the operator resolves it by restoring the managed event to the canonical time or by cancelling under BOOK-009, and Dial never adopts such an edit by itself. Policy: calendar.external-deletion.v1; default: deletion cancels the booking.

CAL-009
Calendar file.

The confirmation and manage pages offer an .ics download for the booking carrying its stable UID and current occurrence. A reschedule increments that file's sequence and a cancellation marks the occurrence cancelled, so an invitee's calendar updates the same entry rather than gaining an unrelated one. The download makes no request to any provider not declared in seed.json → externals.

REQUEST5 clauses

REQUEST-001
Compose.

Where an event type enables it, an invitee can select future dates and time windows within the counts in seed.json → limits, whose starts precede their ends and which do not overlap each other, together with their IANA timezone, a name, an email address, and an optional note of at most 500 characters, and can review the exact request before submitting. A request that omits a date, a window, a name, or a valid email address, or that contains an overlapping or reversed window, is rejected with the offending field named and stores nothing.

REQUEST-002
Submit.

A valid request is recorded once, acknowledged to the invitee on screen, and notified to operators within 60 seconds. The acknowledgement states the response expectation the operator configured, or, where none is configured, only that the host will follow up by email. Replaying the same nonce returns the existing request. A request reserves no time and creates no booking.

REQUEST-003
Operator workflow.

Operators can list requests by submitted, handled, or closed state, open the invitee's windows rendered in both the invitee's and the host's zone, mark one handled or closed, and create a booking for an agreed time. That booking runs the ordinary BOOK-012 path and marks the request handled.

REQUEST-004
Routing.

A new request notifies every operator unless the routing policy selects a subset or suppresses email; suppressing email never suppresses the in-app record. Policy: availability-request.routing.v1; default: every operator.

REQUEST-005
Invitee updates.

Submitting sends the invitee one acknowledgement email restating the requested windows in their own zone. Marking a request handled or closed sends the invitee exactly one further email; the closed one says the host cannot offer a time, and neither is sent twice however often the state is set again.

NOTIFY7 clauses

NOTIFY-001
Booking confirmation.

Within 60 seconds of confirmation Dial emails, through mail.sender.v1, the invitee and every operator: the event, the time in each recipient's relevant zone, the duration, the answers, and the current calendar state. The invitee's copy also carries their manage link and the .ics file of CAL-009; no operator copy contains the manage token. Where the meeting link is still pending the email says so instead of inventing one. An operator can mute booking mail — confirmations, changes, and reminders — for themselves in settings; the invitee's copy is never suppressed.

NOTIFY-002
Link completion.

When a pending joining link becomes available Dial updates the managed calendar event and sends the invitee exactly one link-ready email, however many times the completion job runs.

NOTIFY-003
Reminders.

A confirmed future booking schedules invitee and operator reminders carrying the event, the time in the recipient's zone, the location or join link, and, for the invitee, the manage link. A reminder is sent within 5 minutes of its scheduled offset. Rescheduling replaces the scheduled times and cancellation removes them, so no reminder is ever sent for a time the booking no longer holds. Policy: reminder.schedule.v1; default: 24 hours and 1 hour before the start, scheduling only the offsets still in the future at confirmation or reschedule.

NOTIFY-004
Changes.

A reschedule or a cancellation sends the invitee and every operator exactly one email naming who made the change, the previous time, the new time or the cancellation reason, and the current calendar state.

NOTIFY-005
Delivery failure.

A transient email failure is retried up to 5 times over 1 hour. A permanent failure or a bounce is marked failed on the booking or request with a typed sanitised reason and safe remediation, and can be resent without duplicating a delivery that already succeeded. Raw provider errors are neither persisted nor rendered.

NOTIFY-006
No mail loops.

Product mail is sent from a no-reply address. Mail delivered to that address is discarded and never creates a booking, a request, or a notification.

NOTIFY-007
Connection alerts.

Within 60 seconds of the calendar connection becoming unhealthy under CAL-006, every operator is emailed once, naming the cause and the reconnect action, because public booking is failing closed meanwhile. This alert is operational and the mute of NOTIFY-001 does not suppress it. No further alert is sent for that connection until it has recovered, and recovery is announced the same way.

DATA2 clauses

DATA-001
Export contents.

Supersedes BASE-DATA-001 for OAuth credentials only. The export contains every operator, host profile, event type, question, availability rule and override, calendar-connection metadata and sync state, booking and occurrence, invitee answer and custom-field value, attendance mark, alternative request, delivery attempt, setting, and audit entry as JSON, plus every uploaded asset in its original form. Access and refresh tokens are credentials and are never exported: after an import the calendar connection is unhealthy under CAL-006 until an operator re-authorises it.

DATA-002
Erasure targets.

An operator can delete a booking or an alternative request. Deleting one removes its invitee answers, notes, attendance mark, and uploaded content, invalidates its manage token, and cancels its managed calendar event without sending the invitee a Dial email; the audit entries survive with the invitee reference anonymised, as BASE-DATA-003 requires. Deleting every booking and request carrying an email address erases that person from the deployment, since Dial keeps no separate invitee record.


Baseline guarantees

22 declared clauses from this product's BASELINE.md. Selected ownership guarantees are shown below; execution evidence is separate.

BASE-DATA-005
Independence.

The deployment makes no request to the marketplace or the seed author. There is no telemetry, phone-home, licence check, or kill switch.

Declared guarantee
BASE-DATA-001
Export and import.

pnpm export produces every record and attachment; pnpm import restores it into an empty deployment; export, import, export yields an archive with equivalent contents.

Declared guarantee
BASE-DATA-004
Outbound flows.

User data leaves the deployment only through externals declared in seed.json → externals. No other outbound request carries user data.

Declared guarantee
BASE-PUBLIC-001
Privacy.

Public surfaces (widgets, booking pages, forms, status pages) set no cookies, load nothing from third-party domains, and send no visitor data before the visitor's first interaction.

Declared guarantee
BASE-SECRET-001
No leakage.

No secret appears in the client bundle, in logs, or in an error response.

Declared guarantee

BASELINE.md for Dial


Release history

Honest version: there is one release line so far, and we will not invent the rest.

v0.1.0
Current — runtime-spine-public-port

The manifest states this version and maturity. Consult the source verification evidence before deployment.


DIY quickstart

The code is MIT and the deployment is yours. Nothing below talks to us; optional management remains planned.

This edition has not published a source README yet; use its manifest and contract for current scope and status.


View as agent

Everything on this page exists as machine-readable files. If you are an agent evaluating Dial for someone, read these instead of the prose.

No catalogue install command or source README is declared for this edition.

Catalogue endpoint

/agents/catalogue.json

Every seed with its id, category, version, clause count, install command and links to the files on the left. Generated from the seeds' own artifacts on every build, so it cannot drift from what ships.

The machine face

Dial landing screenshot

Run Dial on your own cloud.

MIT code, your data, your infrastructure. Leave whenever you like and it keeps running.