1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//! Bind-address resolution and the loopback/remote-exposure policy, split out of `cli/mod.rs` to
//! stay under the repo's per-file line gate: this is a self-contained decision (where the server
//! binds, and whether a non-loopback bind is allowed) with no dependency on the lifecycle commands
//! that remain in `cli/mod.rs`.
/// Address the server binds to and that the client talks to.
pub const BIND_ADDR: &str = "127.0.0.1:5784";
/// Environment variable overriding [`BIND_ADDR`] (test seam): lets tests run the server and probe
/// it on an ephemeral port instead of the fixed default, so they never collide with a real daemon.
pub const BIND_ADDR_ENV: &str = "MOADIM_BIND_ADDR";
/// The socket address to bind/probe, honoring the [`BIND_ADDR_ENV`] override when set.
/// Returns `true` if `addr` (as returned by [`bind_addr`]) resolves to a loopback interface.
///
/// The REST/MCP API has no authentication (issue #504): binding to a non-loopback address
/// exposes unauthenticated routine CRUD to the network. An address this can't parse is treated
/// as non-loopback so callers warn rather than stay silent.
/// Environment variable that opts into binding [`bind_addr`] to a non-loopback address. Must be
/// set to exactly `"1"`; anything else (unset, `"true"`, `"yes"`, …) is treated as not opted in,
/// so a typo fails closed instead of silently exposing the unauthenticated API (issue #253).
const ALLOW_REMOTE_ENV: &str = "MOADIM_ALLOW_REMOTE";
/// Returns `true` if the operator has explicitly opted into a non-loopback bind via
/// [`ALLOW_REMOTE_ENV`].
/// The outcome of checking a resolved bind address against the loopback/opt-in policy, decided by
/// [`classify_bind`].
/// Pure decision function for the startup bind-address gate (issue #253): the unauthenticated
/// REST/MCP API must never end up reachable off-host by accident, so a non-loopback bind requires
/// an explicit opt-in (`allow_remote`, sourced from [`remote_bind_allowed`]) or startup is refused.