Skip to content

Front door — invite-only qren.ai

qren.ai is now one calm page: the name, one line saying what Qren is, and a short form asking for an invite. It sells nothing and creates nothing — sending the form files a note in a queue Hisham reads by hand, and nobody gets an account or access by filling it in. It is the first of the five admission steps settled on 2026-08-20; the four that follow are people and other systems, not this page. Built to be replaced: when the approval queue exists, it reads from the same store.

  • Serves one static page at qren.ai — wordmark, one line, one form. Light and dark are both first-class and follow the reader’s system setting. No analytics, no cookies, no external request, no build step.
  • Accepts POST /api/invite (JSON or form-encoded) and files the request in KV for a human to read.
  • Succeeds with the same sentence every time: “Thank you. Invitations are personal and approved by hand; we’ll write to you.” Without JavaScript the form posts normally and gets a plain page carrying the same words.

No self-serve signup — filling the form grants nothing. No account created, no email sent, no Access policy touched. No marketing: no pricing, no feature list, no screenshots, no newsletter. It never echoes what was typed — every response is a fixed string. It notifies nobody; the queue is read, not pushed.

Stored in the KV namespace bound as INVITES, one key per request:

  • Keyreq:<ISO timestamp>:<uuid>, so a plain key listing is already in the order the requests arrived.
  • Value — JSON: email (required, lowercased), name, company, note (“what would you hand to an agent first?”), ts, ua, country. Optional fields are stored empty, never omitted. Fields are trimmed, stripped of control characters, and capped (email 254, name and company 120, note 500).

Two things guard it: a honeypot field a person never sees — filled means the record is silently dropped and the sender is told nothing — and a counter at rl:<hashed ip>, five an hour, expiring on its own. The address is hashed, never stored. If the INVITES binding is missing the endpoint answers 503 and logs it; it never pretends a request was filed.

1. Request — this page, into INVITES. → 2. Approve — Hisham, by hand: read the queue, add the email to the Cloudflare Access policy (see context/infra.md). → 3. Join the network — portal identity, door and tunnel. → 4. Grant on their machine — app install, permissions, engagement credential. → 5. Live. Only step 1 is built; the rest stay manual until the approval queue and the portal cover them.

  • Reading and approving. The queue has no interface — approving means listing KV by hand. It should become an early client of the shared approval queue, with approve and decline writing a status back onto the same record. Until then, who lists it, and how often?
  • Telling the operator. A request should reach Telegram through the bridge — but that crosses into AOS while AOS is being frozen. Last thing AOS gains, or first thing Qren’s notifications ship?
  • Spam. A honeypot and an hourly counter stop casual bots, not a determined one. Turnstile is the obvious next step, at the cost of a third-party script on a page that makes no external request today.
  • Retention. Nothing expires a declined or stale request.