Back to Aurora

TRUST  ·  UPDATED

Security

How this website is served, the one endpoint behind its TestFlight form, where its two secrets live, and how a release is approved. Described from the files that implement it, so you can check it.

This page is about the website you are reading. Aurora the app is a separate surface with its own story: recording, transcription, speaker separation, summaries and Ask Aurora run on the iPhone in front of you, and the paths the app does open are listed one by one in the Privacy Notice.

And what it is not. Data leaving the device is the Privacy Notice's own subject: it lists every network path the app can open and, in a section of its own, what a diagnostic report carries and the state its one switch opens in. The article Inside a diagnostic report takes one apart member by member, and Recording & Consent covers recording other people and your responsibility to them. This page links to those rather than retelling them, so there is one account of each and not four.

In short. Leandro Piccione is the sole maintainer and the person a report reaches, at hello@auroraisyours.com. The site is static documents under a content policy with no inline script allowance; it has exactly one endpoint that sends anything anywhere; its two secrets live on the Worker and never in the repository; and production ships from one branch, behind a script that refuses everything else.

There is no bug-bounty program, no third-party penetration test and no certification behind this page. What follows is a description of the configuration, not an audit of it.

Contents

  1. Reporting a vulnerability
  2. The response headers
  3. The one server path
  4. The surfaces that only read
  5. Secrets, and how a release happens
  6. Transport
  7. What this page does not claim

Reporting a vulnerability

Write to hello@auroraisyours.com. The machine-readable version of that is /.well-known/security.txt, in the form RFC 9116 defines: the same address, English or Polish, the Privacy Notice as the policy, and an expiry of 18 September 2027. A test in this repository fails the release when that expiry drifts outside a 30-to-400-day window, because a security.txt nobody maintains is worse than none — it tells a scanner to trust a stale file.

What helps in a report: the exact URL or path, the request you sent, what you saw, what you expected instead, and the smallest reproduction you have. Two requests in return. Please do not put another person's data in a report. And please do not run load or brute-force tests against the access form: it sends mail, on a budget that is small and real, and a flood spends it on nobody.

You will get an answer from one person, not a queue. There is no reward program.

The response headers

Every static response from this origin carries the set below. It is one file — public/_headers, parsed by Cloudflare at deploy — and the same file two tests in this repository read back, so the description here and the configuration cannot drift apart quietly.

Response headers on every static response from this origin.
HeaderValueWhat it is for
X-Content-Type-OptionsnosniffThe declared content type is the one the browser uses.
X-Frame-OptionsDENYNo other site may put this one in a frame.
Referrer-Policystrict-origin-when-cross-originA link out carries the origin, never the path you were reading.
Permissions-Policycamera=(), microphone=(), geolocation=(), payment=(), usb=()The website asks for no device capability at all. Recording is the app's job, not this page's.
Strict-Transport-Securitymax-age=31536000; includeSubDomainsA year of TLS-only, subdomains included.
Cross-Origin-Opener-Policysame-origin-allow-popupsThis document shares a browsing-context group with nothing it opens. See below for why it is not the stricter value.
Content-Security-Policydefault-src 'self'; script-src 'self' plus two audited hashes plus two named Cloudflare origins; frame-ancestors 'none'; object-src 'none'; base-uri 'self'; form-action 'self'What the page may load, and from where.

Why the opener policy is one step down. same-origin-allow-popups rather than same-origin is deliberate: the bot check on the access form can open a popup that then talks back to the page, and the strict value severs that conversation — the widget would render and never resolve. Nothing else on this site opens a window.

There is no 'unsafe-inline' in script-src. Each document ships exactly one inline script, the theme bootstrap, which has to run before the first paint so the page does not open in the wrong appearance. It is allowed by SHA-256 hash, and the policy carries exactly two hashes — one for the landing page's bootstrap, one for the template this page is built from. A test hashes every inline script in every document and fails if the policy is missing one, or carries one that no page uses any more, which is what keeps that pair honest instead of decorative. frame-ancestors is 'none' and object-src is 'none'. style-src does allow 'unsafe-inline', and the reason is plain rather than good: the pages carry style attributes.

Two third-party origins are named, exactly. challenges.cloudflare.com is the bot check, and it is fetched when the access sheet opens rather than on every visit; static.cloudflareinsights.com is Cloudflare's cookieless analytics beacon, which the zone injects. Neither is a wildcard. The typefaces are served from this origin, so font-src is 'self' — a site that tells you your words stay on your device should not fetch its type from somebody else on every visit. There is no font host, no tag manager, no advertising script, and no cookie.

The Worker sets its own. The file above only shapes what Cloudflare's static assets serve, so everything the Worker answers under /api/ carries its own set in code: JSON, cache-control: no-store, nosniff, referrer-policy: no-referrer, the same one-year HSTS, and a policy of default-src 'none'; frame-ancestors 'none'.

The one server path

POST /api/access is the only endpoint this site has, and the only path on it that sends anything anywhere. It talks to two services and to nothing else: Cloudflare Turnstile, which checks that a browser with a person behind it sent the request, and Brevo, which stores the address and sends the mail. There is no endpoint here that receives audio, a transcript, a summary or anything else from a conversation. No such path exists in the product, and adding one to this site would make it lie.

  • A token that did not pass verification is refused. The Turnstile sitekey in the page is public by design; the secret is on the Worker. The check fails closed: no token, a network error, or an answer from Cloudflare the Worker cannot read is a refusal, and the token has to have been minted for the action the page renders and for the hostname the request arrived at.
  • Same origin only. A request whose Origin names another site is answered 403 before its body is read.
  • One mail per address per day. An address that already got its link today is told so, and no second mail is sent. The build-notes confirmation keeps the same daily quota, because the mail provider sends a confirmation every single time it is asked to.
  • A daily ceiling the Worker keeps for itself. The send budget is 280 a day, under the mail plan's own 300, and the hourly retry of queued mail may only spend what is left of it — so a person asking for a link keeps headroom over the retries.
  • Nothing else under the prefix answers. Any other /api/ path is a 404 that says so, a GET on the access route is a 405, and neither is cacheable.

An unattended client cannot complete that form, and /auth.md says so in as many words: nothing on this origin needs a credential, and the one endpoint cannot be driven unattended, because Turnstile stands in front of it and an automated client has no token to offer.

The surfaces that only read

Two other surfaces exist for machines, and both of them read. /mcp is a read-only Model Context Protocol server whose three tools hand back files this origin already publishes: the page list in the sitemap, a page's markdown twin, and a measurement file. A path argument is checked against the characters a page path on this site is made of, so a .. segment, an absolute URL or a protocol-relative host is refused before any lookup happens. It opens no connection, keeps no session, has no tool that reaches the access endpoint, and writes no tool argument to a log — the question an agent asks is the agent's own.

The Worker also counts. A request from a known crawler token is counted as three facts — the token, the path, and the status it got — with no IP address, no full user agent and no query string; browsers are not counted at all. The funnel counters record that a request happened and whether the mail went out, and carry no address and no dimension that points at a person. That is the whole of the measurement on this site.

Secrets, and how a release happens

  • Two secrets exist. The mail provider's API key and the Turnstile secret key. Both live on the Worker, set once from the command line, and neither is in the repository or in anything the build emits. The only key committed anywhere here is the Turnstile sitekey, which is public by design: it is printed in the page you load.
  • No deploy token exists. There is no continuous-integration system holding one. A release runs from the maintainer's own machine, authenticated by his own login to Cloudflare.
  • Production ships from one branch. The release script refuses to run unless the branch is the production branch, the working tree is clean, the commit is exactly the one already pushed to that branch — so only a reviewed, pushed commit can ship — and the typecheck, the tests and the build all pass. That push is the human approval gate, and there is no way around it that does not start by editing the script.

Transport

The site is served over TLS that Cloudflare manages end to end. The Worker answers its own redirect as well: a request that reached Cloudflare over plain HTTP on either production hostname gets a 301 to the same URL over TLS — every route, the API included, and every method, because a request that arrived in the clear must not be answered in the clear. The header that says which scheme the visitor used is overwritten by Cloudflare on the way in, so a client cannot spoof it.

What this page does not claim

No bug-bounty or reward program exists. No third-party penetration test has been run against this site, no certification or compliance attestation stands behind it, and no vocabulary about grades of encryption will be found on this page. It is one maintainer, a static site, one endpoint and a small set of guards — described above in enough detail that you can check each one against the file that implements it, which is the only kind of security claim this site is entitled to make. If it is not in this repository, it is not on this page.

See also

  1. Privacy Notice — what the app keeps on your device, and the named network paths that do exist.
  2. Accessibility — what has been measured, with what, and the pass that has not been done.
  3. Recording & Consent — recording other people, and your responsibility to them.
  4. Changelog — what changed on this website, and when.
  5. /.well-known/security.txt — the same contact, for a scanner.
  6. /auth.md — where an unattended client stands with this origin.