engine: downstream MTU and downstream train in the measurement document
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>
This commit is contained in:
co-authored by
Claude Fable 5
parent
ce1aaa332a
commit
14e5fad1b2
@@ -0,0 +1,74 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user