endthismeeting
an anonymous button for the whole room

You decide if this meeting
could have been an email.

Add one address to a Teams invite and the whole room gets a quiet, anonymous way to say we're good here. No app, no login, no names. That is the whole product.

how it works

Three steps. The third one is everyone else's.

01

Add a guest, or forward the invite.

If you're the organizer, add vote@endthismeeting.com to your Teams invite, exactly like you'd add a coworker. If you're not, but you want to launch an anonymous survey, just forward the invitation.

02

Everyone gets a quiet button.

Each guest (including the organizer) receives a companion calendar event carrying a unique, one-time voting token. It only works while the meeting is actually happening. Nothing to install, nothing to remember.

03

The room has spoken.

The organizer gets a realtime, gentle, honest nudge. No call-outs, no awkwardness, no names attached. Just a quiet signal that this meeting could have been an email.

privacy

No data is stored. The boring, literal kind, not the marketing kind.

01

Processed, then forgotten

The invite is read, the voting links are sent, and everything else is instantly deleted. No emails are kept, so there is nothing to lose, leak, or subpoena.

02

IDs, not identities

Every meeting is an opaque ID. Every participant is a salted hash. Run it on the next meeting and there would be no way to tell who anyone was.

03

Non-blockchain auditability

Every meeting has a public audit log. All the receipts of a blockchain, none of the theatrics, just a fast little database you are welcome to inspect.

Honest caveat: to hand a companion to each guest, the email provider has to see the recipient address in transit, exactly like any email does, and keeps a short delivery log of it. Nothing of that is stored here, the subject carries no meeting title, and self-hosting lets you own or remove that log entirely.

warranty & support

No warranty. No support. On purpose.

This is the pure instance of the open-source repo, with no guarantee and no support. Storing no email makes it genuinely impossible to help with a problem. Ignorance really is bliss. No upsell, no talk to sales, no subscription to nag about. A social experiment, not a startup.

Companion invite didn't show up? Check the spam folder, ask the IT department, or just host it yourself.

Companion invites are issued only for meetings that clear the gate: the invite has to be sent by Outlook or Teams itself (not hand-forwarded), from a verified Microsoft 365 tenant, with the organizer's domain matching the meeting organizer and the message authenticated. Authentication passes on a DMARC pass, or an aligned SPF or DKIM result, so tenants with no DMARC record (including every onmicrosoft.com) still work. Anything that fails, Gmail and hand-forwarded invites included, gets silence, with zero data kept.

teams only · it's science

Why only Microsoft Teams?

According to rigorous, peer-reviewed vibes, the most boring meetings happen on Teams. So only verified Microsoft 365 tenants are supported. Mystery senders get a polite silence and zero data kept. There's a whole section below on how the tenant is verified.

conscious forwarding

Forward the invitation, not the calendar event.

Forwarding a Teams invitation by email reaches no one but the recipient. Forwarding the calendar item is different: it fires a Meeting Forward Notification straight to the organizer's inbox. So the email should be a quiet path, unless configured differently by your organization.

code

Nerd talk ahead.

Every claim above is reproducible from the code. The repository's URL is at the bottom of the page. Poke around, host it yourself, try to break it.

meeting_id, an opaque public id
meeting_id = HMAC-SHA256( secret, "meeting-id-v1|" + calendarUID )

Deterministic and opaque. Not reversible without the secret. The calendar UID, the title and every email are used only to derive this or send the mail, and are never stored.

voting_id, a one-time, time-bound capability token
jti = 16 random bytes
k0  = HMAC(secret, jti)        ; k1 = HMAC(k0, "meeting=" + meeting_id)
k2  = HMAC(k1, "nbf=" + start) ; sig = HMAC(k2, "exp=" + end)

A salted hash chain, verified offline. The jti is the anonymous participant id in the audit log. Voting works only while the meeting is live.

the entire database
meetings(meeting_id, starts_at, ends_at, tz_offset, threshold)
participants(jti, meeting_id, used, used_at)

No emails. No titles. No calendar UIDs. That is the whole schema.

who gets acted on (anti-spoofing)
act  ⇔  authenticated  ∧  aligned  ∧  verified M365 tenant

authenticated  =  DMARC pass
              ∨  DKIM pass, header.d aligned to the From domain
              ∨  SPF  pass, smtp.mailfrom aligned to the From domain
aligned        =  From domain == .ics ORGANIZER domain

The invite's organizer and the sender address are both forgeable, so nothing happens unless the message is cryptographically authenticated, by DMARC or its aligned SPF or DKIM leg, and that authenticated sender matches the meeting's organizer. A spoofed or misaligned invite is dropped in silence: no companions, not even a reply, so it can't be turned into spam in anyone else's name.

how a Microsoft 365 tenant is verified
verifyOrganizer(domain):
  mx       = DNS MX  → ends with ".mail.protection.outlook.com"
  spf      = DNS TXT → includes "spf.protection.outlook.com"
  tenantId = GET login.microsoftonline.com/<domain>/v2.0/
                 .well-known/openid-configuration  → issuer

  tenant-verified  ⇔  tenantId != null  ∧  tenantId == .ics Teams Tid
  corporate-m365   ⇔  mx  ∨  spf  ∨  tenantId != null
  consumer / disposable domain  →  rejected

The organizer's domain is checked live against Microsoft over DNS-over-HTTPS and OpenID discovery, with no API key, account, or app registration. The strongest level binds the domain's own Entra tenant id to the tenant id Teams stamped into the meeting invite, so a look-alike domain cannot impersonate the meeting's tenant.