Under the hood
How Sundial keeps the hour.
Every setting Sundial chose, the section of the Kindling spec it answers to, and why. Then one Pool in its three layers, the evening rule as the app runs it, the Pool Sundial keeps, the files anyone can read, and what the v0.1 schema cannot say yet.
Settings, mapped to the spec
| Setting | Value | Spec | Why |
|---|---|---|---|
| The two rules | “Every card shows the Pool’s name, charter and tags.” and “No one is shown as open to dating unless their own tags say so.” | §11.2 | The only rules Sundial claims. Everything else on this page is what the spec, or a Pool, asks of every reader. |
| Pool | sundial-cascadia, public | §3.2 | Sundial’s own Pool, for the date dial. Public, so any app can read it. That is how Face Up, Heartwood and Card Catalog can show the same people. |
| Consent model | universal-opt-in | §5.1 | Nobody is in the Pool without saying yes to a handshake. There is no exception. |
| Curator | Ottilie Varga, signed in with OAuth | §4.5 | The person who asks is always named, with how we know her. |
| Handshake window | 14 days, carried in expires_at | §5.2 | The default. A no is remembered; the same curator cannot ask again without permission. |
| Leaving | One action, removed in under a minute | §5.3 | The spec allows sixty seconds. Leaving is never buried. Someone who only uses other dials leaves Sundial in one action too. |
| Opening a Pool | Any Pool Sundial may read, from “Open a Pool”, a product or its address | §3.2 | An app is a reader. There is no kind of Pool Sundial turns away; only visibility, and a site’s own word, keep a Pool closed. |
| Dials | A date, A conversation partner, Someone new in town, A mentor, A housemate, A seat at game night, A climbing partner | §1.2 | Shortcuts, an app decision: a Pool whose intent_tags carry a dial’s word opens on that dial. They are not gates. |
| A Pool that fits no dial | Opens as a dial under its own name, or its product’s | §1.2 | One introduction a day from it, one way, each card under its own Pool. The yes says “Yes, say hello”, or the Pool’s own verb where its charter gives one. |
| Who the date dial introduces both ways | Members of sundial-cascadia only | §5.1 | A symmetric introduction shows each person to the other, so both must have asked for it. |
| Other dating Pools | One way, by each person’s own rules; unlisted ones only with the address | §3.2 | Reading a public Pool one way is what the Pool already allows any app. Only on an evening with nobody both ways. |
| Who the date dial shows | Only people whose own intent_tags include dating | §2.4 | Read from each person’s own tags, not from the Pools they are in or from their page. The same holds for the person reading. |
| For context only | Only where a Pool’s own charter asks for it | §3.2 | The Orchard Street Household lists itself so the people its members date can see how they are connected. It adds a line to a date card; nobody is introduced from it. |
| Both ways on other dials | Only when both people use Sundial, share the Pool, and asked to be shown there | §5.1 | The consent for a symmetric introduction lives in Sundial, per dial, because a manifest has no field for it. |
| One way on other dials | The viewer sees the card; the person is shown nothing | §3.2 | A public Pool is readable by any client. Reading it one way is what the Pool already allows. |
| A yes through a curator | Only where the charter, governance_rules or the host’s site say so | §4.4 | Midspan Mentors, Late Supper’s tables, Seen Work’s Harbor Trades, Hearthhold’s stewards, Meals When It’s Hard, and Hearthhold people whose page takes introductions only. consent_model says how people join, not how they are introduced, so vouching-required Pools like Belay Partners introduce directly. |
| A yes kept in Sundial | Every other Pool, vouched or not | §6.3 | v0.1 has no message that carries a yes, so it goes nowhere unless the viewer writes. |
| Writing | Each Pool’s rules and each person’s, checked with canMessage and the Pool’s members | §7.2 | accept_from, no_cold_messages, shared-pool and the Pool minimum are theirs, not Sundial’s. The reason is shown in words. |
| Unlisted Pools | Read only for a viewer who gives the address | §3.2 | Visibility is the owner’s choice. Drip Line’s Thursday night asks for exactly this. |
| Invite-only Pools | Never read, address or not | §3.2 | The Heron and Midspan Students are served only to their curators. |
| A site’s own word | The Check-In Circle is never read | §3.2 | Foul Weather Friends asks apps not to read it, and its address travels only by hand. Sundial honors that the way a browser honors a page that asks not to be read. |
| Resting Pools | Open, and say they are resting | §9.1 | Chess After Close and Slack Water 2025 went dormant. Nobody in them is hidden. |
| A Pool’s own verb | Correo Lento’s yes is “Write a letter” | §7.2 | Slow letters by email, one a week at most, and the co-op holds a first letter until both people say yes. Sundial carries no chat there. |
| Introductions | One a day on each dial, 7 pm Pacific | §1.2 | An app decision. UIs are implementation-defined, so other apps need not copy it. |
| Introduction window | 72 hours both ways; none one way | §1.2 | App-local. A no and no answer look the same to the other person. A one-way card waits on nobody. |
| Verification | Level in words and an icon beside every person | §4.5 | Required by the spec, and kept on every screen. A vouch is shown as local to its Pool. |
| Identity gating | Unverified senders are held back | §7.1 | Every viewer here is at least email verified. |
| Block lists | Kindling’s and the Circular consortium’s | §7.3 | Shared safety that travels between apps. |
| Transport | Every message is also an email | §6.1 | So a conversation never depends on Sundial, and leaving costs nobody their people. |
| Message types | system, reply, intro, withdrawal | §6.3 | There is no interest or proposal type yet; see below. |
| Photos | Read from each page, never copied | §2.5 | Portraits are illustrations of invented people, drawn from their pages. People whose page describes no picture get none here either. |
| Discovery | A well-known file lists Sundial’s Pool | §8.3 | So any app or registry can find it without asking. |
One Pool, three layers: Belay Partners
A Pool is a page on its host’s own site, a JSON file anyone can read, and whatever any app makes of that file. Here is Drip Line’s Belay Partners all three ways. Every card in Sundial links back to the first two.
I The site
The Pool on Drip Line’s own site, where the staff who run the belay checks keep it: Belay Partners at Drip Line, and what the belay check is.
Climbers who passed a staff belay check at Drip Line and would like to be asked to climb, most often on Saturday mornings. The check is our vouch in this Pool and nowhere else: one of us watched you tie in, belay, catch a fall and lower, once, here. Say what you climb and when, in your own words. Nobody pays to be here or to be introduced.The charter, as Drip Line wrote it
II The data
The manifest at https://driplineclimbing.example/pools/drip-line-belay.json, copied at examples/drip-line/pools/drip-line-belay.json. One entry, as the file holds it:
{
"schema_version": "0.1",
"id": "drip-line-belay",
"name": "Belay Partners",
"curator": [
{
"identity": "pilar@mail.example",
"display_name": "Pilar Echeverría",
"verification_level": "oauth",
"primary": true
},
{
"identity": "emil@mail.example",
"display_name": "Emil Kowalczyk",
"verification_level": "oauth",
"primary": false
}
],
"intent_tags": [
"climbing",
"belay",
"partners"
],
"visibility": "public",
"consent_model": "vouching-required",
"curator_contact": "desk@driplineclimbing.example",
"charter": "Climbers who passed a staff belay check at Drip Line and would like to be asked to climb, most often on Saturday mornings. The check is our vouch in this Pool and nowhere else: one of us watched you tie in, belay, catch a fall and lower, once, here. Say what you climb and when, in your own words. Nobody pays to be here or to be introduced.",
"geographic_scope": {
"city": "Seattle",
"region": "Washington",
"country": "United States"
},
"governance_rules": "Vouching-required. A member of floor staff watches each climber once, at the gym: a harness on right, a figure-eight follow-through, the device loaded and locked, the brake hand never off the rope, a caught fall, a smooth lower, and the calls. Then they vouch, and the Pool asks. The vouch means that, here, on that day. It is local to this Pool (Kindling §4.4) and carries into no other Pool, app or gym. A check that does not pass is a “not yet”, told in person, and written down nowhere. If staff see an unsafe belay later, they talk to you on the floor and ask you to check again; until then your entry comes off this Pool. Handshake requests wait the default 14 days. Memberships and day passes pay for the gym, the staff and the checks. Nobody pays to be in a Pool or to be introduced.",
"messaging_preferences": {
"block_list_subscriptions": [
"https://protocol.kindling.foundation/blocklist.json",
"https://thecircular.example/blocklist.json"
],
"minimum_sender_verification": "email"
},
"status": "active",
"created_at": "2025-10-07T17:00:00Z",
"updated_at": "2026-09-23T02:05:00Z",
"entries": [
{
"profile_url": "https://jules-marin.example",
"parsed_profile": {
"schema_version": "0.1",
"profile_url": "https://jules-marin.example",
"display_name": "Jules Marín",
"pronouns": "they/them",
"location": {
"city": "Seattle",
"region": "Washington",
"country": "United States"
},
"intent_tags": [
"bouldering",
"climbing",
"belay",
"friendship"
],
"about": "Barista on early shifts, so Tuesday is the late night. Boulders, top ropes, and will belay anyone who has been checked.",
"contact_methods": [
{
"type": "email",
"value": "jules@mail.example",
"label": "Kindling identity"
}
],
"verification": {
"level": "curator-vouched",
"verified_at": "2026-05-06T02:15:00Z",
"verifier": "pilar@mail.example"
},
"messaging_preferences": {
"accept_from": "shared-pool",
"no_cold_messages": false,
"minimum_curator_verification": "email"
},
"kindling_noindex": false,
"parsed_at": "2026-05-06T02:15:00Z",
"parser": "kindling-parser/0.1.1"
},
"parsed_at": "2026-05-06T02:15:00Z",
"consent_proof": {
"handshake_id": "hs-drip-line-drip-line-belay-jules",
"accepted_at": "2026-05-06T02:15:00Z",
"method": "curator-vouching"
},
"verification_level": "curator-vouched",
"added_at": "2026-05-06T02:15:00Z",
"added_by": "pilar@mail.example"
},
"… and 5 more"
]
}III The app
Sundial’s card for Jules, as Fatima sees it on the climbing dial: one way, the yes kept in Sundial, and writing allowed because Jules takes messages from people in Belay Partners, and Fatima is one. The same entry, read on its own terms.
- Only you are seeing this. Jules is in Belay Partners, on Drip Line’s site, not in Sundial. Sundial shows them nothing about you, and they will not learn you looked.
- Your yes stays in Sundial. Kindling v0.1 has no message that carries a yes, so nothing reaches Jules unless you write.
- You can write to Jules after a yes. Jules takes messages from people in Belay Partners, and you are in it. The Pool asks senders to be at least email verified, and you are. (§7, checked with KindlingDemo.canMessage)
In their own words
Barista on early shifts, so Tuesday is the late night. Boulders, top ropes, and will belay anyone who has been checked.
From the Pool’s file
What the v0.1 parsed profile in Belay Partners holds, and nothing else. There is no age, gender or photo field, so there is none here.
- Pronouns
- they/them
- Lives in
- Seattle, Washington
- Their words for it
- bouldering, climbing, belay, friendship
- Verification
- Vouched for by the curatorVouched for in this Pool by Pilar Echeverría, on 6 May 2026. The vouch counts in this Pool only (§4.4).
- Takes messages from
- People in the same Pool
- Contact
- Email (Kindling identity)
- Said yes to this Pool
- 6 May 2026
From their own page
Jules’s page says a little more than the file, and Sundial reads it each time.
- Work
- Barista
- Interests
- bouldering, latte art, zines
- Languages
- English
Where this comes from
Their page: jules-marin.example
The portraits are illustrations of an invented person, drawn from their page. Sundial copies no photos (§2.5).
The evening rule
The rules on the About page, as the app runs them. The same code runs in this demo: assets/app.js.
each evening at 7 pm, Pacific, dial by dial:
the date dial
both ways first, from sundial-cascadia
people: everyone in it now whose own
intent_tags include dating
pairs: every two people who
- fit each other's stated settings:
seeking, hoping for, style, age range,
and each takes the other's messages
(canMessage, both ways)
- were never introduced before
sort the pairs by
1. most shared answers (of 18)
2. whoever joined more recently
walk the list; pair two people if
neither is paired yet tonight
show each pair to both at the same moment
close after 72 hours without two yeses
otherwise one way, the first person who
- is in another dating Pool the dial reads
- has dating in their own intent_tags
- is not in sundial-cascadia
- fits your stated settings, both ways
- was never shown to you, on any dial
sort by
1. most shared answers
2. nearest first
3. whoever said yes to the Pool more recently
every other dial, and every dial under a
Pool's own name, for each person who turned it on
both ways first (on a shortcut dial): two people who
- both use Sundial and turned the dial on
- are in the same Pool the dial reads
- both asked to be shown there
otherwise one way, the first person who
- is in a Pool the dial opens (under it)
- was never shown to you, on any dial
sort by
1. nearest first
2. most words in common, your page and theirs
3. whoever said yes to the Pool more recently
a yes goes where the Pool says:
to its curator, as a letter, or kept in Sundial
writing: canMessage, the Pool's and theirs
a Pool whose tags fit no dial
opens as a dial under its own name,
or under its product's name, one way
money is not an inputMessages Sundial sends
Every message validates against kindling_message.schema.json and travels as email (§6.1). Keisha and Kwame’s date from Thursday, then the other dials: a request to Midspan’s coordinator, a first letter one way, and an evening both ways.
messages/intro-system-to-keisha.json: Sundial introduces Kwame to Keisha at seven (system)messages/answer-keisha-yes.json: Keisha’s yes, to Sundial only, never forwarded (reply)messages/both-yes-system-to-keisha.json: Sundial tells Keisha they both said yes (system)messages/letter-kwame-intro.json: Kwame’s first letter (intro)messages/letter-keisha-reply.json: Keisha writes back (reply)messages/withdrawal-keisha.json: What leaving sends (withdrawal)messages/request-yesenia-to-fina.json: Yesenia’s yes on the mentor dial, sent to Fina at Midspan as a request, and nothing to Priya (intro)messages/letter-walt-to-rosalind.json: Walt’s first letter on the housemate dial, one way: Rosalind takes a first message from any verified sender (intro)messages/both-ways-system-to-theo.json: Theo and Yusra, both ways on the new-in-town dial: both use Sundial, both are in New in Town, and both asked (system)
Sundial’s own Pool: Sundial: Cascadia
The manifest lives at https://sundial.example/pools/sundial-cascadia.json. The copy here is pools/sundial-cascadia.json, and the handshake Simone receives is handshake/demo-request.json. It is the only Pool Sundial keeps; every other dial reads other people’s.
Charter
Sundial introduces you to one person a day, at seven in the evening, and introduces them to you at the same moment. You each see one card. Like or pass; if you both like, you can write. There is no second card to reach for and nothing to buy for more. This is the Pool Sundial keeps for people in Cascadia who asked to be introduced this way.
Governance
Universal opt-in. One introduction a day is how the Sundial app reads this Pool, not a rule of the Pool: any app may read it its own way, and Sundial reads other public Pools the same way. A pass is never shown to the other person. A missed day is just a missed day; nothing is lost, nothing is counted, and there are no streaks. Reports go to the founder, who answers them herself. Leave in one tap.
The manifest, without its entries
{
"schema_version": "0.1",
"id": "sundial-cascadia",
"name": "Sundial: Cascadia",
"curator": [
{
"identity": "ottilie@mail.example",
"display_name": "Ottilie Varga",
"verification_level": "oauth",
"primary": true
}
],
"intent_tags": [
"dating"
],
"visibility": "public",
"consent_model": "universal-opt-in",
"curator_contact": "hello@sundial.example",
"charter": "Sundial introduces you to one person a day, at seven in the evening, and introduces them to you at the same moment. You each see one card. Like or pass; if you both like, you can write. There is no second card to reach for and nothing to buy for more. This is the Pool Sundial keeps for people in Cascadia who asked to be introduced this way.",
"geographic_scope": {
"region": "Cascadia"
},
"governance_rules": "Universal opt-in. One introduction a day is how the Sundial app reads this Pool, not a rule of the Pool: any app may read it its own way, and Sundial reads other public Pools the same way. A pass is never shown to the other person. A missed day is just a missed day; nothing is lost, nothing is counted, and there are no streaks. Reports go to the founder, who answers them herself. Leave in one tap.",
"messaging_preferences": {
"block_list_subscriptions": [
"https://protocol.kindling.foundation/blocklist.json",
"https://thecircular.example/blocklist.json"
]
},
"status": "active",
"created_at": "2026-06-21T19:00:00Z",
"updated_at": "2026-09-27T19:00:00Z",
"entries": "[20 entries, one per member; see the file]"
}The 20 members
| Member | Verification | Joined | Takes messages from |
|---|---|---|---|
| Farah Siddiqui | Email verified | Thursday 25 June 2026 | verified · no cold messages |
| Grace Liang | Signed in with OAuth | Sunday 28 June 2026 | verified · no cold messages |
| Duc Tran | Email verified | Friday 3 July 2026 | verified |
| Birgit Aas | Email verified | Thursday 9 July 2026 | verified |
| Kwame Asante | Signed in with OAuth | Monday 13 July 2026 | verified |
| Fiona MacLeod | Signed in with OAuth | Saturday 18 July 2026 | verified |
| Nils Haugen | Email verified | Thursday 23 July 2026 | shared-pool |
| Ada Quillon | Email verified | Wednesday 29 July 2026 | shared-pool |
| Araceli Montoya | Email verified | Sunday 2 August 2026 | shared-pool |
| Darnell Hayes | Signed in with OAuth | Thursday 6 August 2026 | verified |
| Keisha Holloway | Email verified | Thursday 13 August 2026 | verified |
| Samir Aziz | Signed in with OAuth | Monday 17 August 2026 | verified |
| Thuy Nguyen | Signed in with OAuth | Friday 21 August 2026 | verified · no cold messages |
| Yolanda Greer | Email verified | Tuesday 25 August 2026 | verified |
| Arjun Pillai | Signed in with OAuth | Monday 31 August 2026 | verified · no cold messages |
| Kalani Akana | Email verified | Friday 4 September 2026 | vouched |
| Sione Taufa | Email verified | Friday 11 September 2026 | verified |
| Patrick Sullivan | Email verified | Monday 14 September 2026 | verified |
| Liam O’Connell | Email verified | Sunday 20 September 2026 | verified |
| Emery Stone | Email verified | Friday 25 September 2026 | verified |
The well-known file
Published at sundial.example/.well-known/kindling-pool (§8.3, §10.2). The copy here is .well-known/kindling-pool.
{
"schema_version": "0.1",
"pools": [
{
"manifest_url": "https://sundial.example/pools/sundial-cascadia.json",
"name": "Sundial: Cascadia",
"intent_tags": [
"dating"
],
"visibility": "public",
"status": "active",
"geographic_scope": {
"region": "Cascadia"
},
"last_updated": "2026-09-27T19:00:00Z"
}
],
"operator": {
"name": "Sundial, one introduction a day, at the same hour for both people",
"contact": "hello@sundial.example",
"url": "https://sundial.example"
}
}Block lists it honors
- Kindling public block list, version 3, 2 entries. https://protocol.kindling.foundation/blocklist.json
- The Circular consortium block list, version 8, 4 entries. https://thecircular.example/blocklist.json
Both are checked on every message, on every dial, with each Pool’s and each person’s own rules (§7.3).
What the v0.1 schema can’t say yet
- No interest or proposal message. §6.3 lists four message types and the schema six, and none of them says “I would like to meet this person”. So Sundial carries a date as
systemmessages from the Pool to each person, each answer as areplyto Sundial that is never forwarded, and the first letter as anintro. On the other dials a yes that is kept in Sundial sends nothing at all. - No message that says “please introduce me”. Where a Pool introduces through its curator, Sundial sends the request as an
introaddressed to the curator, through the Pool. A curator cannot tell it apart from any other first letter except by reading it. - No field for how a Pool’s introductions travel.
consent_modelsays how people join, not how they are introduced. Whether a yes goes to a curator is read fromgovernance_rulesand charter prose. Later-Life Housemates says only on Hearthhold’s own page that some people take introductions only through Omar; the manifest cannot say it. - No field for “show me to other apps’ users in this Pool”. Both ways on a dial needs both people to have asked for it. That consent lives in Sundial, per dial, because a manifest and a parsed profile have nowhere to put it, so another app cannot honor it.
- No field for a like or a pass. Sundial’s yes and not this one live only in Sundial, and a pass is never written anywhere another app can read. That is the privacy Sundial wants, but it means an answer cannot follow a person from one app to another.
- No field for the hour or the window. Seven o’clock and the 72-hour window are how the Sundial app reads a Pool. A manifest could only say so in
governance_rules, as prose. - An unlisted Pool cannot say who holds its address. §3.2 makes an unlisted Pool readable by anyone with the address. Nothing records who gave an app the address, or lets a Pool limit which apps may read it. Sundial reads one only for the viewer who pasted it.
- Who a Pool is for is prose. Fifty-five and over (Later-Life Housemates) and eighteen or older (Midspan) live in charters. Nothing verifies them, and Sundial does not guess anyone’s age.
- No age, gender, seeking or answers in a parsed profile.
parsed_profile.schema.jsonforbids extra fields, so the date dial reads these from each person’s own page, every time (§2.1). An age range has nowhere to live at all, so it is Sundial’s own setting. Outside dating, Sundial shows only what a Pool’s file holds. - A personal block has no message. §7.3 block lists are for known abusers and shared between apps. When you block one person, Sundial keeps that itself; nothing is published and nothing is sent.
- Verification names differ. §4.5 says
email-verifiedandoauth-verified; the schemas sayemailandoauth. The JSON here follows the schemas. - The Pool reference and the version field. §6.2 calls the Pool reference
pool_ref; the schema calls itvia_pool. §12.1 nameskindling_version; the schemas useschema_version. The JSON follows the schemas. - The handshake window per Pool. §5.2 says the 14-day window is configurable per Pool, but the manifest has no field for it. Sundial keeps the default and carries it in each request’s
expires_at. - Extraction provenance. §2.3 names an
extraction_sourcefield that the parsed profile schema does not have. - No field for a Pool’s own verb. Correo Lento’s letters, held by the co-op until both people say yes and never more than one a week, live in its charter and
governance_rules, as prose. Sundial reads them there and says “Write a letter”, but another app would have to read the same prose. - No field for “please do not read this Pool”. Foul Weather Friends asks apps not to read the Check-In Circle, on its own site. The Pool is unlisted, so anyone with the address could read its file; nothing in it can say no. Sundial honors the site’s word, but only because it read the site.
- Rule 2 needs people’s own tags to be honest about dating. A person’s own
intent_tags(§2.4) are the only place Sundial reads whether they are open to dating. A matchmaker or a bookshop that keeps a dating list does not say dating in their own tags, and so is never shown on the date dial. Nothing in the schema makes that distinction for them.