Skip to content

One safe intake for everything visitors submit #259

Open
12 of 13 issues completed
Open

Description

@Ardnived

The goal

Everything a visitor sends us — signing up for a class, or reporting a problem with a listing — goes through one safe, consistent path, and we can show that it works.

Why it matters

Each kind of submission used to have its own path, with its own gaps in spam protection and its own way of reaching a person. Both atlas forms have been on the one shared path for weeks, and every piece of work filed under this goal is closed. Since the last check, two more of the things that were missing have landed: the live site now runs the real spam check rather than the test setting that let everything through, and both forms now explain a refusal in the same words instead of ending in a bare "something went wrong".

Two things are still outstanding. Nobody has sent a sign-up or a problem report from the live site and watched it arrive — until someone does, we are reading the code rather than watching it work. And since 3 November the spam check only loads on partner sites that are on our list of allowed sites, so the forms on partner sites that are not listed yet, the WordPress ones included, turn every visitor away. sydevs/SahajCloud#1077 fixes that, and this goal waits on it.

The digest of wrongly refused sign-ups, agreed on 21 October, is now built as part of sydevs/SahajCloud#1070, alongside every other manager email, rather than here.

What success looks like

  • Both atlas forms — signing up for a class, and reporting a problem — arrive in the one submissions list, each marked with what kind it is.
  • A visitor can report a problem using an ordinary email address, including a Gmail, Yahoo or Outlook one. (Repaired on 11 October and live since.)
  • The spam check on the live site is the real one, not the test setting that accepts everything, and it cannot quietly revert to that setting. If the test setting ever reaches the live site, both forms stop and an error is recorded, rather than everything passing unnoticed. (Real since 3 November.)
  • A test sign-up and a test problem report, both sent using an ordinary email address, are accepted and arrive within fifteen minutes — the sign-up as a confirmation email, the report in the general contact inbox. Both are sent from sahajatlas.com and from a partner site that shows the map inside its own page.
  • When either form turns a visitor away, it tells them what to change, in the same words for both forms. No submission ends in a bare "something went wrong".

Not included

Decisions

  • Where should a problem report about the map land? → The general contact inbox. Nothing to set up; corrections share it with every other message. (Ardnived, 2026-10-21)
  • What should happen when the spam check wrongly refuses a real class sign-up? → "Notify admins in a digest email, make it configurable via the notifications preferences like all other notifications." Every refusal reaches admins in a digest. Delivered by feat(atlas): open-items homes, per-role digests, simpler preferences SahajCloud#1070, not this goal. (Ardnived, 2026-10-21; moved 2026-11-05)
  • How do we keep the live site's spam check from quietly reverting to the test setting? → Accept what guards it now: if the live site ever carries the test setting, it serves no spam check at all, so both forms stop and an error is recorded. No release check is added. This replaces the 21 October answer, whose release check was removed when the spam check moved onto our own servers. (Ardnived, 2026-11-05)

Open questions

None.

Notes

Twelve of the thirteen pieces of work under this goal are closed. The open one is sydevs/SahajCloud#1077, attached on 2026-11-05: partner sites missing from the allowed-sites list cannot take a sign-up or a report. The production spam-check secret was read on 2026-11-05 and is not the test one (Ardnived).

Related: #195, #214, #216, #257, #343, sydevs/SahajCloud#695, sydevs/SahajCloud#723, sydevs/SahajCloud#724, sydevs/SahajCloud#725, sydevs/SahajCloud#796, sydevs/SahajCloud#797, sydevs/SahajCloud#798, sydevs/SahajCloud#799, sydevs/SahajCloud#800, sydevs/SahajCloud#814, sydevs/SahajCloud#654, sydevs/SahajCloud#899, sydevs/SahajCloud#1072, sydevs/WeMeditateWeb#78, sydevs/WeMeditateWeb#116

Technical notes

TL;DR

  • Settled: production serves the real Turnstile sitekey 0x4AAAAAAEFpp8n3BBZfG0KF, from SahajCloud's own /api/atlas/challenge frame (read live 2026-11-05); both forms now map every refusal code from one shared table.
  • Risky: fix(atlas): list every live embed host in allowedDomains, which the captcha now requires SahajCloud#1077 — /api/atlas/challenge renders only for a parent on a published client's allowedDomains (or first-party/loopback), and production data was never checked against that, so inline embeds on unlisted partner hosts show the captcha-blocked screen.
  • Unknown: no submission has ever been sent from the live site. Production's TURNSTILE_SECRET_KEY was read by Ardnived on 2026-11-05 and is not the test secret; whether it pairs with the served sitekey is what the criterion 4 test settles.
  • Decided 2026-11-05: the runtime 503 is the accepted guard (old question 1, answer A). The refusal digest moved to feat(atlas): open-items homes, per-role digests, simpler preferences SahajCloud#1070.
Verification, criterion by criterion (2026-11-05)
Criterion Verdict Evidence
1. Both forms in one list, each typed met createRegistration sends type: 'registration', sendReport sends type: 'contact', both to /user-submissions (mutate.ts)
2. An ordinary email address is accepted met URL_PATTERN run over 12 providers: 0 refused, was 8. Live since 11 Oct (SahajCloud#899, #922). A link in a message body is still refused
3. Real spam check live, cannot quietly revert met (runtime guard accepted 2026-11-05) Live GET /api/atlas/challenge → 200 carrying 0x4AAAAAAEFpp8n3BBZfG0KF; a test key in production → 503 — see the next block
4. A test sign-up and report arrive within 15 min not done Needs a real browser to pass Turnstile. GET /api/user-submissions → 403: an API client holds create-only, by design. The partner-site half waits on sydevs/SahajCloud#1077
5. Both forms say what to change met REFUSAL_MESSAGE_KEYS is a total Record over each synced union, sharing INPUT_REFUSAL_KEYS with the report form; event_not_found mapped (RegistrationForm.tsx:75, PR #345). A new code fails the build rather than degrading
6. Refused sign-ups digest moved To sydevs/SahajCloud#1070 § Preferences (refused_signups), which keeps PR #1052's registration-refusals collection and screening write
What changed since the 2026-10-24 check
Landed What it did to this goal
SahajAtlasWeb#345 Criterion 5. Both forms refuse in one vocabulary, from ReportIssueForm/refusal-copy.ts. submission_data_invalid is excluded on purpose: no registration this widget sends can earn it (mutate.ts:69)
SahajAtlasWeb#346 Criterion 3's release half: a Vite plugin refused a production build carrying a test key, plus a smoke assertion
SahajAtlasWeb#343 → PR #355, with SahajCloud#1072 Moved the whole challenge into a frame SahajCloud serves, so one hostname covers every partner page and one deployment holds both halves of the credential. VITE_TURNSTILE_SITE_KEY no longer exists in this repo, and #346's guard and smoke assertion went with it

#343 is a Bug, so it stays direct and is not attached as a child. docs/embedding.md already carries the new frame-src cloud.sydevelopers.com row and its failure mode, so the host contract is current.

The release guard became a runtime refusal (question 1)

atlasChallenge returns 503 and logs production carries a Turnstile TEST key when isProductionDeployment() && isTestSiteKey(siteKey) (SahajCloud/src/endpoints/atlas/challenge/index.ts:81, helper at challengeRequest.ts:56, which names this goal). The widget then shows its security-check error and takes no submission.

So the test key can no longer be a silent no-op — the failure is loud. Nothing fails a release; Ardnived accepted that on 2026-11-05. No smoke spec reads the live sitekey any more (#355 removed #346's), so the 503's error log is the only signal.

What is left
Item Who
sydevs/SahajCloud#1077 — list every live inline-embed host in allowedDomains the loop (child, High)
Criterion 4 — one sign-up and one report from sahajatlas.com and from an inline partner embed, Gmail sender a person with a real browser; the partner half after #1077

No SahajAtlasWeb code remains. The refusal digest is sydevs/SahajCloud#1070's.

Facts settled, so they are not asked
Question Answer
Is the report path switched on in production? Yes — form 3 "Report Issue Form": two required fields, textarea:message and email:email
Who receives a report? Unreadable client-side by design (SahajCloud#813). A blank recipient falls back to contact@sydevelopers.com
Does a host see a change? Yes, and it is already documented: frame-src https://cloud.sydevelopers.com is required, and challenges.cloudflare.com now belongs in no host directive (docs/embedding.md)
Who may frame the challenge? Only a published client's allowedDomains, a first-party frontend, or loopback; the page posts to exactly that origin
URL contract touched? No — atlas-url-contract.json names no endpoint, form or submission
Honeypot or edge rate limiting? No honeypot in either repo; rate limiting is a Cloudflare dashboard rule the code only documents
Build vs buy, and priority

Activity

  1. added this to the Sahaj Atlas launch milestone on Oct 8, 2026
  2. added theissue type on Oct 8, 2026
  3. added
    bot:workingLock: a cloud session is running on this item. Removed when it ends.
    on Oct 8, 2026
  4. sydevs-bot commented on Oct 8, 2026

    @sydevs-bot
    Contributor

    🤖 no session running

    recent dispatches
    • 21:38Z revise-roadmap · attempt 1 · session · done
    • 21:38Z revise-roadmap · attempt 1 · session
    • 15:39Z revise-roadmap · attempt 3 · session · timed out
    • 15:39Z revise-roadmap · attempt 3 · session
    • 07:04Z revise-roadmap · attempt 2 · session · timed out

    Written by the sydevs dispatcher. Sessions never edit this comment.

  5. 34 remaining items

  6. added
    bot:workingLock: a cloud session is running on this item. Removed when it ends.
    and removed
    bot:workingLock: a cloud session is running on this item. Removed when it ends.
    on Nov 5, 2026
  7. sydevs-bot commented on Nov 5, 2026

    @sydevs-bot
    Contributor

    The session for revise-roadmap did not finish after 3 attempts. I have stopped retrying. A @sydevs-bot verb or mention from you starts me again.

    🤖 sydevs dispatcher

  8. moved this from Working to Awaiting in SYDevelopers Technical Roadmapon Nov 5, 2026
  9. added
    bot:workingLock: a cloud session is running on this item. Removed when it ends.
    on Nov 5, 2026
  10. moved this from Awaiting to Working in SYDevelopers Technical Roadmapon Nov 5, 2026
  11. sydevs-bot commented on Nov 5, 2026

    @sydevs-bot
    Contributor

    Not yet — three of six lines are met. Two of the three that are not need no code.

    Two more landed since the last check: the live site now runs the real spam check, not the test setting — #343 moved it onto our own servers on 3 November — and both forms now tell a visitor what to change instead of a bare error (#345).

    What is left:

    • One decision — question 1. The release check you asked for on 21 October was built, then removed a week later with the setting it read. What guards the live site now breaks both forms loudly rather than failing the release. Reply @sydevs-bot revise 1A to accept that, or 1B to add the release check too.
    • Someone sends one sign-up and one problem report from the live site and says what arrived. That also settles whether the production spam secret matches the key now served, so nobody need read it.
    • The refused-sign-up digest is not built. A refused sign-up leaves no record at all today, so recording one comes first.

    Once question 1 is answered, @sydevs-bot implement files the remaining work.

    🤖 Written by the sydevs autonomous loop — see what this is


    Generated by Claude Code

  12. removed
    bot:workingLock: a cloud session is running on this item. Removed when it ends.
    on Nov 5, 2026
  13. moved this from Working to Awaiting in SYDevelopers Technical Roadmapon Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Fields

    Priority

    Medium

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions