Under the hood
How Bellows follows Kindling v0.1
Bellows is a client. It hosts no Pools and reads the ones the library keeps, by each Pool’s visibility and each person’s rules, with the shared kit’s canMessage and autoAccept. Every setting below links to the spec.
| Setting | Value | Spec | Why |
|---|---|---|---|
| Pools hosted | None | §10 | Bellows is a client. Its well-known file lists no Pools, and it owns no list of people. |
| Which Pools it reads | Public Pools for asks and offers, for anyone; unlisted Pools only for their members; never invite-only | §3.2 | Visibility is the owner’s and the curator’s choice. An unlisted Pool’s address travels between members, so only a member’s client reads it. |
| Pools it never reads | The Check-In Circle, Midspan Students, and any Pool a site names for no app | §3.2 | Foul Weather Friends and Midspan said so. A site’s word about its own Pool is final. |
| Who an ask is shown to | People whose intent tags or about text fit the ask, in the Pools the asker chose | §2.4 | What someone can give is on their own page. Bellows reads it and says which words were read. |
| Messaging rules | KindlingDemo.canMessage for each person and Pool: identity, accept_from, no_cold_messages, block lists | §7.2 | A person’s rules decide. A held ask is not sent, and the reason is shown to the asker. |
| Pool sender floor | Each Pool’s minimum_sender_verification is honored | §7.1 | Friday Subs asks senders to be signed in with OAuth. Maggie is email verified, so a drum sub from her is held there. |
| Standing yes | Auto-accept rules answer an ask at once when its tags include every tag in the rule, the Pool’s keeper is verified enough, and the Pool’s visibility is allowed | §5.5 | Never silent: the owner gets a system message in the same minute and can undo it. At most five rules. |
| Ask window | Until you need it, or the Pool’s own window, whichever ends first | §5.2 | Friday Subs closes asks after 48 hours, from its governance_rules. Other Pools use the default 14 days. |
| Transport | Every ask, reply and notice is an ordinary message by email | §6.1 | Leaving Bellows leaves your conversations where they are: in your mailbox. |
| Asks through a curator | Seen Work Curators, Harbor Trades, Midspan Mentors and Meals When It’s Hard route asks to their keeper | §4.4 | Their charters say so. A vouch is local to one Pool, so the curator who saw the work does the asking. |
| Verification | Shown in words and with an icon beside every person | §4.5 | Everyone can see who is asking and who is answering. |
| Photos | Never copied. Portraits are illustrations described on each person’s own page | §2.5 | Everyone here is invented, so nobody is photographed. |
| Leaving | One action. Bellows deletes what it holds; your Pools are untouched | §5.3 | Leaving an app is not leaving a Pool. Withdrawing from a Pool is on that Pool’s own site. |
| Dormant and archived Pools | Dormant Pools are still read; archived Pools take no new asks | §9.4 | Continuity belongs to the Pool’s members, not to an app. |
| Loading a product | index.html#load-<product key>, from the Kindling registry, embedded when the app is built | §8.3 | Asks, offers and Pools are scoped to that product’s Pools, and routed the same way: standing yeses, each Pool’s window, and curators where the Pool says so. Clear it and everything is as before. |
The Pools it reads
17 Pools, linked to their files
Chosen from the data each time the app is built: Pools a site names for Bellows, the Pools in its brief, and public Pools tagged for asks and offers. The full library, with reasons, is on the About page.
| Pool | Site | Visibility | Asks go | Window | Senders |
|---|---|---|---|---|---|
| Friday Subs | Ferry Room Players | public | to each person | 48 hours | oauth |
| Horns and Strings for Records | Ferry Room Players | public | to each person | up to 14 days | any verified |
| Session Players | Slack Water | public | to each person | up to 14 days | any verified |
| Fix-It Friday Volunteers | The Board | public | to each person | up to 14 days | any verified |
| Door and Sound Crew | Ferry Room Players | public | to each person | up to 14 days | any verified |
| Belay Partners | Drip Line | public | to each person | up to 14 days | |
| The Saturday Run | Drip Line | public | to each person | up to 14 days | any verified |
| Big Game Day | Rain Check | public | to each person | up to 14 days | |
| Carpool to the Coast | The Board | public | to each person | up to 14 days | any verified |
| Rides to Appointments | Foul Weather Friends | public | to each person | up to 14 days | |
| Rides Home | Slack Water | public | to each person | up to 14 days | any verified |
| Lend and Borrow | Foul Weather Friends | public | to each person | up to 14 days | any verified |
| Meals When It’s Hard | Foul Weather Friends | public | to the curator | up to 14 days | any verified |
| Seen Work: Harbor Trades | Seen Work | unlisted | to the curator | up to 14 days | |
| Seen Work Curators | Seen Work | public | to the curator | up to 14 days | any verified |
| Cape Tarrow First-Gen Alumni | Cape Tarrow Alumni | public | to each person | up to 14 days | any verified |
| Midspan Mentors | Midspan | public | to the curator | up to 14 days | any verified |
Manifests and the well-known file
No Pools of its own
Bellows hosts no Pool, so it has no manifest. Its well-known file says so, and names who runs the app §10.2. .well-known/kindling-pool
{
"schema_version": "0.1",
"pools": [],
"operator": {
"name": "Bellows, asks and offers from the Pools you belong to",
"contact": "hello@bellows.example",
"url": "https://bellows.example"
}
}
Messages
What an ask looks like on the wire
An ask is an intro message through one Pool; a standing yes sends its owner a system message; a reply is a reply §6.2. Each file validates against kindling_message.schema.json.
messages/ask-horn-sub-to-kofi.json
{
"schema_version": "0.1",
"message_id": "msg-bellows-horn-sub-kofi",
"type": "intro",
"sender": {
"identity": "lena@mail.example",
"display_name": "Lena Brightwater",
"verification_level": "oauth",
"profile_url": "https://lena-books-the-ferry.carrd.example"
},
"recipient": {
"identity": "kofi@mail.example",
"profile_url": "https://kofi-mensah.example"
},
"via_pool": {
"url": "https://ferryroom.example/pools/horns-and-strings.json",
"id": "horns-and-strings",
"name": "Horns and Strings for Records"
},
"sent_at": "2026-09-28T09:00:00Z",
"subject": "A horn sub for Friday",
"body": {
"content_type": "text/plain",
"content": "A horn sub for Friday. Needed Fri 2 Oct, 8:00 pm, the Ferry Room, Pier 3. Friday 2 October, the late set, doors at seven. Charts by email ahead of time. Paid by the band, never by the Pool. Lena Brightwater"
},
"transport": {
"type": "email",
"message_headers": {
"X-Bellows-Ask": "a1",
"X-Bellows-Needed-By": "2026-10-02T20:00:00Z",
"X-Bellows-Expires-At": "2026-10-02T20:00:00Z"
}
}
}messages/rule-notice-to-mae.json
{
"schema_version": "0.1",
"message_id": "msg-bellows-drum-sub-mae-rule",
"type": "system",
"sender": {
"identity": "hello@bellows.example",
"display_name": "Bellows",
"verification_level": "email"
},
"recipient": {
"identity": "mae@mail.example"
},
"via_pool": {
"url": "https://ferryroom.example/pools/friday-subs.json",
"id": "friday-subs",
"name": "Friday Subs"
},
"sent_at": "2026-09-28T09:00:00Z",
"subject": "Your rule said yes to Lena Brightwater’s ask for you",
"body": {
"content_type": "text/plain",
"content": "Your auto-accept rule 1 (drums + sub, from curators signed in with OAuth, public Pools only) said yes for you to Lena Brightwater’s ask in Friday Subs: A drum sub for Friday, needed Fri 2 Oct, 8:00 pm. Lena knows you said yes and can write to you by email. You can undo it at any time, and Lena is told at once."
},
"transport": {
"type": "email"
}
}messages/ask-drum-sub-to-mae.json
{
"schema_version": "0.1",
"message_id": "msg-bellows-drum-sub-mae",
"type": "intro",
"sender": {
"identity": "lena@mail.example",
"display_name": "Lena Brightwater",
"verification_level": "oauth",
"profile_url": "https://lena-books-the-ferry.carrd.example"
},
"recipient": {
"identity": "mae@mail.example",
"profile_url": "https://maecastellano.bandcamp.example"
},
"via_pool": {
"url": "https://ferryroom.example/pools/friday-subs.json",
"id": "friday-subs",
"name": "Friday Subs"
},
"sent_at": "2026-09-28T09:00:00Z",
"subject": "A drum sub for Friday",
"body": {
"content_type": "text/plain",
"content": "A drum sub for Friday. Needed Fri 2 Oct, 8:00 pm, the Ferry Room, Pier 3. Friday 2 October, the early set. Paid by the door. Lena Brightwater"
},
"transport": {
"type": "email",
"message_headers": {
"X-Bellows-Ask": "a2",
"X-Bellows-Needed-By": "2026-10-02T20:00:00Z",
"X-Bellows-Expires-At": "2026-09-30T09:00:00Z"
}
}
}messages/referral-to-delphine.json
{
"schema_version": "0.1",
"message_id": "msg-bellows-electrician-delphine",
"type": "intro",
"sender": {
"identity": "wendell@mail.example",
"display_name": "Wendell Ashby",
"verification_level": "oauth",
"profile_url": "https://ashby-and-daughter.example"
},
"recipient": {
"identity": "delphine@mail.example",
"profile_url": "https://delphine-arceneaux.example"
},
"via_pool": {
"url": "https://seenwork.example/pools/seen-work-curators.json",
"id": "seen-work-curators",
"name": "Seen Work Curators"
},
"sent_at": "2026-09-28T09:00:00Z",
"subject": "A vouched electrician",
"body": {
"content_type": "text/plain",
"content": "Delphine, could you ask the people you know? A vouched electrician. Needed Mon 12 Oct, 8:00 am, the Net Loft, Cannery Wharf. A subpanel and six new circuits for the workshop floor, two or three days from 12 October. Pay by the day, agreed between us, paid by Ashby and Daughter directly. Wendell Ashby"
},
"transport": {
"type": "email",
"message_headers": {
"X-Bellows-Ask": "a3",
"X-Bellows-Route": "curator",
"X-Bellows-Needed-By": "2026-10-12T08:00:00Z",
"X-Bellows-Expires-At": "2026-10-12T08:00:00Z"
}
}
}messages/yes-from-june.json
{
"schema_version": "0.1",
"message_id": "msg-bellows-generator-june-yes",
"type": "reply",
"in_reply_to": "msg-bellows-generator-june",
"sender": {
"identity": "june@mail.example",
"display_name": "June Okafor",
"verification_level": "email",
"profile_url": "https://june-okafor.notion.example/lend"
},
"recipient": {
"identity": "maggie@mail.example"
},
"via_pool": {
"url": "https://foulweatherfriends.example/pools/lend-and-borrow.json",
"id": "lend-and-borrow",
"name": "Lend and Borrow"
},
"sent_at": "2026-09-28T09:12:00Z",
"subject": "Re: A generator, today",
"body": {
"content_type": "text/plain",
"content": "Yes. I will bring it round at noon with the cords, and set it up outside, well away from her windows. June"
},
"transport": {
"type": "email"
}
}messages/not-this-time-from-wes.json
{
"schema_version": "0.1",
"message_id": "msg-bellows-generator-wes-no",
"type": "reply",
"in_reply_to": "msg-bellows-generator-wes",
"sender": {
"identity": "wes@mail.example",
"display_name": "Wes Adeyemi",
"verification_level": "oauth",
"profile_url": "https://wes-mixes.example/lend"
},
"recipient": {
"identity": "maggie@mail.example"
},
"via_pool": {
"url": "https://foulweatherfriends.example/pools/lend-and-borrow.json",
"id": "lend-and-borrow",
"name": "Lend and Borrow"
},
"sent_at": "2026-09-28T09:40:00Z",
"subject": "Re: A generator, today",
"body": {
"content_type": "text/plain",
"content": "Not this time. Mine is running the kitchen at the Mariners’ Hall until the power is back. Wes"
},
"transport": {
"type": "email"
}
}messages/no-longer-needed-to-wes.json
{
"schema_version": "0.1",
"message_id": "msg-bellows-generator-wes-covered",
"type": "system",
"sender": {
"identity": "hello@bellows.example",
"display_name": "Bellows",
"verification_level": "email"
},
"recipient": {
"identity": "wes@mail.example"
},
"via_pool": {
"url": "https://foulweatherfriends.example/pools/lend-and-borrow.json",
"id": "lend-and-borrow",
"name": "Lend and Borrow"
},
"sent_at": "2026-09-28T09:12:00Z",
"subject": "No longer needed: A generator, today",
"body": {
"content_type": "text/plain",
"content": "Maggie O’Rourke has what she needed: June said yes. There is nothing for you to do, and nothing was recorded about you. Thank you for being on the list."
},
"transport": {
"type": "email"
}
}
Block lists
Honored for every Pool that subscribes
Every Pool Bellows reads subscribes to both lists below, and Bellows checks each one before an ask is sent §7.3.
- Kindling public block list, version 3, 2 entries. The file. The block list the Kindling project will publish under SPEC.md §7.3, for identities and implementations with confirmed abuse. The entries here are illustrative until the registry opens. No personal details are ever published.
- The Circular consortium block list, version 8, 4 entries. The file. Shared by every member of the Circular consortium. Each member subscribes; any member may propose an entry, and two others must second it.
What the v0.1 schema can’t say yet
Where Bellows reads sentences instead of fields
- There is no ask or offer in v0.1. An ask is an ordinary intro message sent through a Pool (§6.3). What someone can give lives in their page’s intent tags and about text; there is no field for an offer, how many, or when.
- A message has no expires_at. The handshake has one; a message does not. Bellows carries the window in a transport header, X-Bellows-Expires-At, and in words in the body. The schema allows headers, so the files stay valid.
- Auto-accept is defined for handshakes, not asks. §5.5 says a rule answers a request to join a Pool. Bellows reads the same rule as a standing yes to an ask whose tags include every tag in the rule, from a Pool whose keeper is verified enough and whose visibility the rule allows. The owner is always told, as §5.5 requires. There is no field to say a rule covers asks too.
- A Pool’s window has no field. §5.2 calls the 14-day window configurable per Pool, and the manifest has no field for it. Friday Subs says “48 hours” in governance_rules, and Bellows reads that sentence.
- “Ask the curator” has no field. Seen Work, Midspan and Meals When It’s Hard say in their charters that asks go to a keeper. Bellows reads their words; v0.1 cannot say it in a machine-readable way.
- Is a keeper a pool-mate? pool-mates-only (accept_from: shared-pool) does not say whether a Pool’s curator counts as in the Pool. Bellows counts the curators a manifest lists, so Lena, who keeps Horns and Strings, can reach Kofi through it.
- Verification level names differ. §4.5 says email-verified and oauth-verified; the schemas say email and oauth, and add cryptographic. The JSON follows the schemas.
- Six message types, not four. §6.3 lists four. The schema has six, adding withdrawal and system. A standing yes’s notice is a system message.
- No extraction_source. §2.3 names a provenance field that parsed_profile.schema.json does not have. Bellows says which words it read in its own interface instead.
- Copies of a Pool have no field. Foul Weather Friends copies its Pools to the library each hour. v0.1 cannot say so except in a sentence; Bellows names the original address in via_pool.
Times in this example are UTC, as written in the files.
Keys
On a keyboard
A for a new ask. 1 to 5 for Your asks, Asks to you, Offers, Pools and You. J and K to move through a list. Y and N to answer an ask to you. Escape closes the ask you are writing. Every key has a button beside it.