oficina / calendar Public

Clone
git clone https://amadan.net/oficina/calendar

Plain git — no account needed to clone.

Download

Download this file

1package calendar
2
3import (
4 "net/http"
5
6 "amadan.net/oficina/home/connect"
7)
8
9// beginSignin is POST /signin, in both modes: rauth's Begin for EVERY
10// address, under connect.OAuthContinuation. What the form answers
11// depends on the address's domain alone, never on the allowlist — any
12// difference between a permitted and a non-permitted address would
13// turn this endpoint into a membership oracle.
14//
15// - A Keymail address (keymail.dev itself, or a domain delegating to
16// Keymail with a `_keymail` TXT record), permitted or not, goes to
17// Keymail. Begin answers with a 303 to Keymail's authorize URL,
18// which OAuthContinuation turns into a page (renderKeymail): CSP's
19// form-action 'self' covers a form submission's whole redirect
20// chain in Safari, so a 303 out of the POST would be refused.
21// Admission is asked only after Keymail has verified the address,
22// by rauth's Authorize, and its refusal is the door saying so
23// (rauth's Refused hook, handlers.refused) — told only to someone
24// who has just proved they hold the address.
25// - Any other address is answered ?sent=1, and mailQueue mails the
26// link only if the allowlist holds it — after the response, in a
27// worker, so not even the response time differs (signin_mail.go) —
28// and this app's sending identity is no open relay for whatever a
29// stranger types.
30//
31// Both kinds of address spend the same rate budgets and parse the same
32// way, and a failed send is logged after the response, not answered.
33//
34// It used to gate the allowlist in front of Begin and set force=1 on
35// every permitted request, which kept Keymail out of Calendar
36// altogether. Paul ruled on 2026-10-06 that Calendar uses Keymail.
37// force now arrives only from the form rastrillo lands a failed
38// Keymail exchange on (?force=1&err=keymail), and asks for an emailed
39// link instead, so nobody is stuck.
40func beginSignin(origin string, begin http.HandlerFunc, render func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
41 return connect.OAuthContinuation(origin, begin, render)
42}
43