The contract, by its classical elements

Accountability partner contract: the four legal elements, each a line of code

Every template you will find for this phrase is a fillable PDF. On this site there is no PDF and nothing is signed. The contract has four classical elements (offer, acceptance, consideration, mutual assent) and each one resolves to a specific URL, INSERT statement, or SQL boolean in the repo. The meeting of the minds is a single AND on two columns. The consideration is a row in a table. The offer is two links. The acceptance is two GET requests.

M
Matthew Diakonov
10 min read
4.9from direct meditator feedback
Every contract element tied to a file path and line number in a public repo
Free, in the dana tradition; no fee is the consideration, presence is
No operational practice instruction; technique goes through dhamma.org

The contract in four numbers

A paper contract has blanks and signatures. A code-enforced contract has columns and booleans. The four numbers that describe it.

0classical elements, each mapped to one file and one line
0SQL AND that determines whether the contract has formed
0GET requests required for formation, one from each party
0signatures, PDFs, or notarized pages in the flow

What every other guide on this topic actually gives you

I read the pages that come up first for this phrase. Almost all of them are a PDF with blanks, or a page instructing you to build one. A title, two name fields, a shared goal, a cadence, a missed-session penalty, and two signature lines. The best ones add a review clause and a grace period. The worst are a bullet list pretending to be a document.

Templates like that work for two people trying to invent a partnership from scratch, where neither the cadence, nor the goal, nor the consequences are predetermined. On a product where all of those are already fixed, a template is redundant. What a template asks partners to fill in, the product already has filled in: daily cadence (RRULE:FREQ=DAILY), one permanent Meet URL, a one-click exit, a 72-hour confirmation window. So instead of writing out a template this page describes the shape of the contract that actually forms, in terms a contract lawyer would recognize.

Offer, acceptance, consideration, mutual assent — visualized

The left side of this diagram is the pre-contract state. The hub is the handler that evaluates mutual assent. The right side is what comes into being the instant the boolean flips.

confirm-match route, as the contract-formation hub

Offer (email to A)
Offer (email to B)
Acceptance 1
Acceptance 2
confirmMatchPerson
Meet URL created
meet_links rows inserted
Intro email sent
matches.status = pending

The four elements (plus two), each mapped to one file

Each card names one classical element of a contract, and points at the exact place in the repo where it is implemented. Every one of these references is checkable against the code that runs in production.

Element 1. Offer

The confirmation email is the offer. Its two URLs (/api/confirm-match?response=yes and &response=no) are the specific terms. The email template lives at src/lib/emails.ts:330, the yes URL is built on line 345, the no URL on line 346. The offer is open for 72 hours.

Element 2. Acceptance

A GET request to the yes URL. The handler at src/app/api/confirm-match/route.ts line 20 reads token and response from searchParams, validates, and records the single side's yes. Two acceptances required, one from each party, each a separate browser click.

Element 3. Consideration

Presence, written as rows in the meet_clicks table. Every call to /meet/<token> triggers an INSERT at src/app/meet/[token]/route.ts lines 26 to 29. The row (token, match_id, person_id, meet_url, ip, user_agent) is the payment each partner renders to the other.

Element 4. Mutual assent

A single SQL boolean AND. confirmMatchPerson at src/lib/db.ts line 496 returns { bothConfirmed: !!(m?.person_a_confirmed && m?.person_b_confirmed) }. When that returns true, and only then, does the contract form.

Element 5. Capacity (informally)

Addressed by the disclaimer at src/app/disclaimer/page.tsx:60. Signups with relevant mental-health history are asked to consult a professional before committing. No capacity database column; the disclaimer carries the weight.

Element 6. Lawful purpose

Sitting in silence over Google Meet is not a regulated activity. The product refuses scopes it cannot legally enforce (coaching, therapy, technique instruction). Out-of-scope requests are redirected to dhamma.org and authorized teachers.

Mutual assent, in code

This is the anchor fact of the whole page. In classical contract doctrine, the meeting of the minds is a mental event, inferred from words and conduct. In this system it is a literal boolean: two columns in the matches row, an AND on those columns, and a return value. When the AND returns true, the contract forms. When it returns false, the contract has not formed yet.

src/lib/db.ts

Acceptance, in code

An acceptance is a GET request. No fancier than that. The token identifies the party and the side, the response=yes parameter is the content of the acceptance. The same handler services both parties, on whatever order the clicks arrive. On the second call, the inner conditional runs, and the contract forms inside the same HTTP request.

src/app/api/confirm-match/route.ts

Consideration, in code

No money changes hands here, so the consideration cannot be cash. It is presence. Each party's consideration to the other is a row in meet_clicks, produced by the act of opening the shared Meet room. The INSERT below is the entire payment rail. Two rows a day on the same match_id is the full bilateral exchange.

src/app/meet/[token]/route.ts

Formation, diagrammed

The sequence of the second yes click, from the partner's browser through the confirm-match handler, to Postgres, to Google Calendar, to Resend. The contract exists only after all of these have run, in order, in a single request.

the second yes click, expanded

Partnerconfirm-matchPostgresGoogle CalendarResendGET ?token=X&response=yesUPDATE person_b_confirmed=truebothConfirmed=truePOST events, recurrence=DAILYmeetUrl + eventIdINSERT 2 rows meet_linkssend intro email, replyTo=[A,B]redirect /match-confirmed

The full lifecycle of the contract

Pre-contract, offer, two acceptances, formation, performance, termination. Every contract has these phases. In a paper world, phase transitions are events on a calendar. In this product they are values the matches.status column walks through.

1

Pre-contract: the matcher assembles the offer

auto-match/route.ts runs on a 30-minute cron. It scores pairs, picks one, writes a row to matches with status='confirming', generates two UUID tokens (person_a_token, person_b_token), and hands the pair off to the email sender. No Meet URL yet. No meet_links rows yet. Only an offer in flight.

2

Offer: two confirmation emails

Each side gets a confirmation email with buildConfirmationEmailHtml (src/lib/emails.ts:330). The body contains two buttons: yes and no. The yes button links to /api/confirm-match?token=<theirToken>&response=yes. That URL is the literal terms of the offer. The 72-hour window is stated italicized on line 376.

3

Acceptance 1: the first yes click

The recipient clicks yes. The handler at confirm-match/route.ts:20 reads the token, looks up the match, identifies which side (a or b), and calls confirmMatchPerson. That sets person_a_confirmed or person_b_confirmed to true, reads back, and returns { bothConfirmed: false } because only one side has clicked. No Meet URL is created yet. The first party has accepted; the contract has not formed.

4

Formation: the second yes click

The second party clicks yes. Same handler, same confirmMatchPerson. This time the SELECT on line 494 returns both booleans as true. The expression on line 496 evaluates to true. bothConfirmed is returned true to the route handler, which enters the if-branch at confirm-match/route.ts:59. The Meet URL is generated, two meet_links rows are inserted, the calendar event is created with RRULE:FREQ=DAILY, and the intro email is sent. The contract is now in force.

5

Performance: daily presence, written to meet_clicks

From formation onward, each partner's consideration is a row in meet_clicks. They open the Meet via their per-person tracking URL, which hits /meet/<token>, which INSERTs the row at lines 26 to 29, and redirects them to the real Meet URL. Two rows a day, at roughly the same wall-clock time, under the same match_id. That is the ambient performance signal.

6

Termination: rescission or non-performance

Either party can rescind by clicking unsubscribe. One SQL UPDATE at unsubscribe/route.ts:59 ends every active match for that person in one pass. Alternatively, both sides stop performing (no meet_clicks rows for days), the operator notices, the pair is quietly ended on the dashboard. In either case, the remaining party returns to 'ready' and is eligible for a new match that the matcher will not pair with the former partner.

The contract forms on bothConfirmed === true

Classical doctrine says a contract forms at the moment of mutual assent. This product says the same thing, in code. The moment is the 0th line of src/lib/db.ts, inside confirmMatchPerson. Two boolean columns, 0 AND, and the return value is handed back to the route handler, which decides whether to do nothing (and wait for the other side) or to proceed with 0 side effects: create the Meet URL, insert two meet_links rows, set the calendar recurrence, send the intro email. Nothing forms before that AND. Everything forms in the same request that makes it true.

If you want to inspect the contract at any time after formation, read vipassana_activity_log. Each state transition gets one row with event_type, triggered_by, and a note. That table is the archival copy.

Template contract vs. code-enforced contract

FeaturePaper / PDF / Google Doc templatevipassana.cool
Form factorA printable PDF or Google Doc with name, goal, cadence, consequences, and signature fields.No form factor. The contract is distributed across a URL scheme, an INSERT statement, and one SQL boolean column pair.
Who is the offerorBoth partners draft together; there is no clear offeror or offeree.The matcher is the offeror. Each confirmation email is a separate offer to one party, with matching terms.
What the acceptance looks likeTwo handwritten signatures.Two GET requests to /api/confirm-match?token=...&response=yes. The browser's User-Agent and IP are the acceptance metadata.
What the consideration isSometimes money (for coaches). Often nothing — 'mutual support' is not legally sufficient consideration.Rows in meet_clicks, one per partner per day. A recorded, tied-to-match_id act of showing up.
Where mutual assent is recordedThe two signatures, side by side at the bottom of the PDF.One SQL boolean AND: !!(person_a_confirmed && person_b_confirmed), computed in confirmMatchPerson at src/lib/db.ts:496.
What happens on breachNothing enforceable. The PDF was never admissible anyway.The other party sees an empty Meet room. Silence in meet_clicks surfaces on the operator dashboard. Remedy is rematch, not damages.
Termination mechanismA conversation. Sometimes a follow-up email.One click on the unsubscribe footer. One SQL UPDATE. Every active match for that person ends in the same transaction.
ArchivalA scanned image of the signed PDF, sitting in one or both parties' Drive.Every state transition is a row in vipassana_activity_log with triggered_by, event_type, timestamps, and notes. Queryable, not paginated.
1 AND

bothConfirmed = !!(m?.person_a_confirmed && m?.person_b_confirmed)

the literal return of confirmMatchPerson at src/lib/db.ts line 496 — the meeting of the minds, in SQL

The vocabulary the runtime speaks

A paper contract uses words like undertake, covenant, whereas, and party of the second part. The contract on this site uses these tokens instead. Every one of them is something the runtime can evaluate on its own, without asking a human.

matches.status = 'confirming'token = crypto.randomUUID()response=yesconfirmMatchPerson(matchId, side)bothConfirmed = person_a_confirmed AND person_b_confirmedINSERT INTO meet_clicksrecurrence: ['RRULE:FREQ=DAILY']UPDATE matches SET status='ended'expireStaleMatches(3)replyTo: [personA.email, personB.email]

Why the contract is deliberately this thin

A fatter contract with declared goals, weekly check-ins, and scheduled consequences would be a richer document. It would also be the wrong document. The lineage this product orbits is Goenka-style Vipassana, taught on a donation basis by authorized assistant teachers at 10-day residential courses run through dhamma.org. The teaching of technique is not something a web product can legitimately do. What a web product can do, legitimately, is help two meditators reliably open the same Meet room at the same time every day and record that they did. That, and exactly that, is the subject matter of this contract. A wider scope would have the product impersonating a teacher it is not authorized to impersonate.

For anything about how to sit, how to handle a difficult session, or how to work with whatever arises on the cushion, the correct redirect is dhamma.org and an authorized assistant teacher in person, at a course. The four elements on this page cover only the form of the partnership contract. The practice itself is a separate, older, and much larger undertaking with a lineage.

Want to watch the contract actually form on a test signup?

Book a short call. We'll walk through the offer email, both yes clicks, the bothConfirmed boolean flipping true, and the Meet URL appearing, live.

Frequently asked questions

Is this actually a contract in the legal sense?

Depends on which lens you use. In the narrow sense of a document you sign, no — nothing gets signed, nothing gets notarized, and there is no paper artifact anywhere in the flow. In the broader sense that lawyers teach in first-year contracts (offer, acceptance, consideration, mutual assent, and capacity), yes: each of those elements has a concrete implementation in this repo, and the page walks through which file and line each of them lives on. The contract is not a piece of paper, it is a pattern the runtime enacts. Whether that pattern would survive litigation is not the point; the point is that a daily meditation partnership is not the kind of relationship courts adjudicate, so the only enforcement that matters is the one the code does on its own every day.

What exactly is the offer, what is the acceptance, and when does the contract form?

The offer is the confirmation email, more precisely the two hyperlinks inside it: /api/confirm-match?token=<yours>&response=yes and /api/confirm-match?token=<yours>&response=no. That pair of URLs is the offer, made by the matcher to each party separately. The acceptance is a GET request to the yes URL, performed by the recipient's browser when they click the button. Two acceptances are required, one from each side. The contract forms at the exact instant the second acceptance arrives: specifically when confirmMatchPerson in src/lib/db.ts lines 487 to 496 returns { bothConfirmed: true }. That boolean is the formation event. Before it flips, there is no Meet URL, no calendar event, no meet_links rows, nothing. After it flips, all of that comes into being in the same request.

What is the consideration? No money changes hands.

The consideration is presence. Specifically: a row in the meet_clicks table, with the fields token, match_id, person_id, meet_url, ip, and user_agent. Every time either party opens their per-person tracking URL at /meet/<token>, src/app/meet/[token]/route.ts lines 26 to 29 INSERT that row. Your consideration to your partner is the row you generate today; their consideration to you is the row they generate today; and the two rows, landing within a few minutes of each other on the same match_id, are the bilateral exchange. It is not money, but it is measurable, tied to a specific partner, and required for the relationship to continue. That matches the classical definition of consideration (a benefit bargained for, given in exchange) while using an entirely non-financial currency.

You keep saying mutual assent is a SQL boolean. What does that literally mean?

It means that the place where the runtime decides whether the two sides have 'met in their minds' is a single AND of two boolean columns. confirmMatchPerson at src/lib/db.ts line 487 takes a matchId and a side ('a' or 'b'), sets the corresponding person_a_confirmed or person_b_confirmed column to true, reads both columns back, and returns { bothConfirmed: !!(m?.person_a_confirmed && m?.person_b_confirmed) } on line 496. The !! is there to coerce undefined-from-an-empty-row into a proper boolean. That return value, evaluated in src/app/api/confirm-match/route.ts line 57 as const { bothConfirmed } = await confirmMatchPerson(...), is the entire mutual-assent determination. If it is true, the contract is in force. If it is false, the contract is still only an offer plus one acceptance, which in common-law terms is not yet a contract.

What about the fourth element, capacity, and the counterpart of 'legal purpose'?

Capacity is addressed via the disclaimer page (src/app/disclaimer/page.tsx), which asks any signup with relevant mental-health history to consult a professional before committing. That is the closest this product comes to a capacity check. 'Legal purpose' is trivial: sitting in silence next to another adult over Google Meet for an hour a day is not a regulated activity in any jurisdiction I am aware of. If it were, the purpose would be invalid and the contract would fail on that element. That is a hard line: the product refuses to take on purposes it cannot legally enforce (coaching, therapy, technique instruction), which is why those are explicitly out of scope.

How does breach work? There is no damages clause.

There is no damages clause because there are no damages. The worst-case outcome of one side not performing is that the other side sits alone in the Meet room for a few minutes, notices the absence, and leaves. The failure is private, it is same-day, and it does not accumulate. The breach signal in the data is simple: meet_clicks has a row from only one person_id under the match_id for the day, instead of two. The operator dashboard surfaces this. The remedy is not damages, the remedy is rematch: the remaining party can unsubscribe (one click) and rejoin the waitlist, and the matcher will pair them with someone new. Doctrine that fits: this product uses a version of efficient breach, where the cost of enforcing performance would be higher than the cost of finding a replacement partner, so the system optimizes for replacement rather than enforcement.

How is the contract terminated?

Three paths. One, mutual non-performance: both sides stop generating meet_clicks rows, the operator notices, both matches quietly age out. Two, unilateral rescission: either party clicks the unsubscribe footer link on any email, which hits /api/unsubscribe and runs UPDATE matches SET status='ended' on every row where that person is on either side of the pair (src/app/api/unsubscribe/route.ts around line 59). The other party is notified and returned to the 'ready' state on the waitlist. Three, pre-contract voidance: if the 3-day confirmation window elapses without both acceptances, expire-matches runs on its cron, calls expireStaleMatches(3), and voids the offer without a contract ever having formed. In all three cases, the termination is one-sided, cost-free, and does not require either party to justify the decision to the other.

Why does this page treat the contract as four elements instead of listing clauses like an NDA?

Because clauses are the shape of the document, and this is not a document. The sibling page /t/accountability-partner-agreement does the clause-by-clause reading: seven clauses, seven files. That framing is useful when the question is 'what does the agreement actually commit me to day by day.' This page takes the prior question: is there a contract here at all, and if so, by which classical elements? That question is what a lawyer would ask first, and it has a more interesting answer here than on any fillable-PDF site because the implementation is visible and unambiguous. Each of the four elements is a specific, checkable thing in the repo, not a paragraph of boilerplate.

Is the contract unilateral or bilateral?

Bilateral. Both parties make promises to each other, each promise is the consideration for the other's, and performance is symmetric. An example of a unilateral contract would be 'I will pay anyone who finds my lost dog' — only one side makes a promise, the other side earns the reward by performing the act. An example of a bilateral contract is 'I will pay you this salary, and you will work on this team' — both make promises, both have duties. The partnership on this site is squarely bilateral: each partner promises to open the same Meet URL at the daily time, and each partner's promise is the consideration for the other's. The matcher's scoring function, at src/app/api/auto-match/route.ts, makes this concrete by ranking only on symmetric attributes: sessionMatch, bothOld, readyScore, timezone offsets. It has no asymmetric fields.

Where does this leave anything about meditation technique?

Out of scope, by design. This page is entirely about the form of the contract that governs the partnership infrastructure: who meets whom, how consent is recorded, how presence is measured, how exit works. It does not cover any aspect of how to practice, how to sit, or how to handle what arises in a session. Those questions are operational, and the only honest answer is that they belong to the living tradition, not to a web product. For anything technique-related, the redirect is dhamma.org and a conversation with an authorized assistant teacher at a 10-day residential course. Nothing on this site will teach you to meditate, and nothing in the contract described here pretends to.

Related pages on the same topic

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.