| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Registering from the native client failed with `captcha_failed` while the
checkbox was green — a worse symptom than the one being fixed, because the
widget now looked fine and only the hub's own log said otherwise:
captcha solved on an unexpected host ''; allowed: ['localhost', 'meshbay', 'meshbay.org']
The previous commit assumed Google would report the host component of the
origin, so `app://meshbay` would come back as `meshbay` and could sit in
`allowed_hosts`. It does not. A solve Google cannot attribute to a domain
reports an **empty** hostname, and no allowlist entry can match that. An empty
entry is not the answer either: a blank in a TOML list is a typo far more
often than an intention, and `load_config` drops blanks for that reason —
`captcha.allow_unattributed_host` is a named flag instead, so the trade is
stated where it is made.
What it admits, plainly: every non-web client, not only ours. A file:// page
or somebody else's Electron application look identical from here. That is the
same bar the client's own origin would have been — main.js already records
that `app://meshbay` is not a credential — and it is a bar: the captcha still
has to be solved, per token, in something that can render it. What is given up
is the origin restriction for non-web clients, not the captcha. Off by
default, and a hub without the desktop client should leave it off.
The refusal now names which of the two it is, since they need different
answers: an unexpected host names the host, an unattributed one says to set
the flag.
docs/captcha.md §6 said `meshbay` was the value and told operators to add it;
it now records what was measured and why the guess was wrong. The packaged
example config carries the flag with the same warning.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014UtzVrzM7e2tG9fSpkR9ML
|
|
|
Three defects, found while answering whether installing the .deb would land
where the production server was just moved to by hand.
- **The example config was never packaged.** `build-hub.sh` copied
`packaging/conf/hub.toml.example` under `if [ -f ]`, and that path does not
exist in this repo — so every package ever built shipped no example at all
and said nothing about it. The postinst places no config either, on purpose
(a shipped hub.toml is overwritten on upgrade; a shipped secret gets run in
production), which left an installed hub with nothing to copy from. The file
now exists, documents every key `config.py` reads including the captcha
`allowed_hosts` the desktop client needs, and the copy is a hard failure
rather than a silent skip.
- **`/etc/meshbay` was created 0755.** It holds the hub's Ed25519 private key
and its database password. The file modes protect the contents, but a
world-listable config directory tells anyone with a shell what a hub keeps
and where. Now 0750 root:meshbay, in both the deb postinst and the rpm
scriptlet; the service reads it by group.
- **The rpm would have failed to build on the new file.** `%files` claimed
nothing under /etc, and rpmbuild refuses an installed file no line claims.
It now declares the directory and the example, with explicit `%attr` and
`%config` so an operator's edits become .rpmsave rather than vanishing.
Package modes no longer follow the builder's umask either — the same source
tree produced 775/664 on a machine with umask 002 and 755/644 with 022.
`install -m` sets them.
Verified by building: the deb now carries ./etc/meshbay/ at drwxr-x--- with
hub.toml.example at 0644, and the embedded postinst tightens the directory as
belt and braces rather than as the only thing making it right. The rpm path is
unverified — no rpmbuild on this machine.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014UtzVrzM7e2tG9fSpkR9ML
|