Three facts the client cannot produce alone, kept deliberately separate: mtu.pmtud_down (largest datagram that arrives unfragmented — meaningful only because the server sets DF), mtu.frag_delivery (whether larger ones arrive once fragmentation is allowed), and train.udp_downstream (loss, reordering and arrival spacing in the download direction, which a round trip cannot separate from upstream loss). ServerMeasurement now runs them on the same ProbeSession as the echo train. It had to: a fresh session restarts client-side sequence numbers and the server's anti-replay window discards the lot, so the re-primed source is never recorded and every granted send goes to a socket that has already closed. That produced four confidently-wrong FAILED tests and a RED verdict on a healthy network. Live against fmr: path MTU 1500, fragments to 4000, 100/100 downstream, GREEN. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
75 lines
3.6 KiB
Markdown
75 lines
3.6 KiB
Markdown
# Echolot website (`web/`)
|
|
|
|
Minimal single-page site for [echo-lot.app](https://echo-lot.app), served from Cloudflare
|
|
Workers. Static files in `public/` are served straight from the edge; the tiny Worker in
|
|
`src/index.js` only runs for paths that aren't files:
|
|
|
|
| Path | Behavior |
|
|
| ------------- | ------------------------------------------------------------------------ |
|
|
| `/apk` | 302 → newest `.apk` asset of the latest Gitea release (QR-code friendly) |
|
|
| `/apk.sha256` | 302 → the matching `.sha256` asset |
|
|
| `/api/latest` | JSON `{version, published_at, apk, sha256}` — the homepage's version readout |
|
|
| `/fdroid`, `/source` | 302 → the URLs configured in `wrangler.jsonc` vars |
|
|
|
|
The latest release is resolved from the Gitea API **at request time** (edge-cached 5 min), so
|
|
publishing a release — `git tag v0.2.0 && git push origin v0.2.0`, which triggers
|
|
`.gitea/workflows/release.yml` — is the only release step. The site never needs a redeploy for
|
|
a new version, and empty/unreachable values fall back to the homepage instead of 404ing.
|
|
|
|
Light/dark follows the OS (`prefers-color-scheme`), no toggle, no JS required for it. Colors
|
|
come from the branding palette (teal = instrument, single amber point = finding).
|
|
|
|
`public/assets/` (favicon, wordmark, social preview) are **copies** of `../assets/branding/` —
|
|
that directory is the source of truth; re-copy after any branding change.
|
|
|
|
## Deploy
|
|
|
|
Everything is driven by [wrangler](https://developers.cloudflare.com/workers/wrangler/), config
|
|
in `wrangler.jsonc`. No build step, no node_modules to commit.
|
|
|
|
### One-time setup
|
|
|
|
1. In the Cloudflare dashboard, add **echo-lot.app** as a zone (and point the domain's
|
|
nameservers at Cloudflare). The `routes` in `wrangler.jsonc` use `custom_domain: true`, so
|
|
wrangler creates the DNS records for `echo-lot.app` and `www` automatically on first deploy —
|
|
the zone just has to exist in the same account.
|
|
2. Auth, either flavor:
|
|
- **Interactive:** `npx wrangler login` (opens the browser once, stores an OAuth token).
|
|
- **API token (also what CI uses):** dashboard → My Profile → API Tokens → create from the
|
|
**"Edit Cloudflare Workers"** template. Then:
|
|
|
|
```
|
|
$env:CLOUDFLARE_API_TOKEN = "..." # PowerShell; export ... on POSIX
|
|
$env:CLOUDFLARE_ACCOUNT_ID = "..." # dashboard → Workers & Pages, right sidebar
|
|
```
|
|
|
|
### Deploy
|
|
|
|
```
|
|
cd web
|
|
npx wrangler@4 deploy
|
|
```
|
|
|
|
That's it — uploads `src/index.js` + the `public/` assets, wires the custom domains. Useful
|
|
extras: `npx wrangler dev` (local preview at localhost:8787), `npx wrangler tail` (live logs),
|
|
`npx wrangler versions list`.
|
|
|
|
### CI deploy (Gitea Actions)
|
|
|
|
`.gitea/workflows/deploy-site.yml` runs `wrangler deploy` on every push to `main`/`master` that
|
|
touches `web/`. It stays inert until you add two repo secrets (Settings → Actions → Secrets):
|
|
`CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` (same values as above).
|
|
|
|
Cloudflare's raw REST API (`PUT /accounts/:id/workers/scripts/...`) exists, but the assets
|
|
upload needs a manifest/session dance that wrangler already implements — use wrangler even in
|
|
automation.
|
|
|
|
## Config knobs (`wrangler.jsonc` → `vars`)
|
|
|
|
- `GITEA_REPO_API` — Gitea repo API base; releases must be publicly readable.
|
|
- `DOWNLOAD_URL` — manual `/apk` fallback while Gitea is unreachable.
|
|
- `FDROID_URL` — set when the F-Droid listing exists; until then `/fdroid` loops home.
|
|
- `SOURCE_URL` — public source mirror for the footer + `/source`.
|
|
|
|
Vars are plain (non-secret) config; change + `wrangler deploy` to apply.
|