diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d4514ff..3bcdde43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -452,6 +452,25 @@ Detailed per-release notes are on the command says where. The wallet (0.4.0) restores its key from there, or from its own copy in `~/.pilot/keys/io.pilot.wallet`, when it is installed again. If the dir cannot be moved, nothing is deleted. +- **The daemon's log no longer repeats routine lines as warnings.** On a Mac + the log held 1,574 copies of `appstore skip io.pilot.wallet: read manifest: + … no such file or directory` in under an hour, and the Mac app listed them, + with two other routine lines, as warnings the daemon repeats: + - The app store rescans its install root every 2 s and logged a dir it + skipped every time. The wallet binary, run outside the daemon, keeps its + identity in `~/.pilot/apps/io.pilot.wallet`, a dir with no manifest. A + skipped dir is now logged once, and again only if the reason changes + (app-store v1.0.7); a dir with no manifest is left alone. + - The app store's lines had no level at all. They now go through the + daemon's logger: INFO for routine ones (`starting`, discovered and + removed apps, spawns), WARN for problems (crash loops, failed + verification, a manifest that does not parse or verify). A refused + downgrade, a rescan error, an uninstall and a reinstall no longer raise + repeated or spurious warnings. + - `tunnel bound to wildcard address` was a warning on every start of every + default install. Binding every interface is what a node does to hear its + peers, and the hint it gave (`-listen 127.0.0.1:0`) would cut the node + off; the address stays in the `tunnel listening` line. - **A write followed at once by a close no longer loses its end under loss.** A FIN that overtook a lost segment was acted on at once: the receiver closed the stream with the segment missing, and its FIN-ACK made diff --git a/cmd/daemon/main.go b/cmd/daemon/main.go index 766c219c..0ceb8f6a 100644 --- a/cmd/daemon/main.go +++ b/cmd/daemon/main.go @@ -540,12 +540,12 @@ func main() { ) if err := cataloguePins.Refresh(); err != nil { if cataloguePins.LoadCache() { - log.Printf("appstore: catalogue refresh failed (%v); using %d cached publisher pin(s)", err, cataloguePins.Count()) + slog.Warn(fmt.Sprintf("appstore: catalogue refresh failed (%v); using %d cached publisher pin(s)", err, cataloguePins.Count())) } else { - log.Printf("appstore: catalogue refresh failed (%v) and no cache; catalogue apps fail closed until the next refresh succeeds", err) + slog.Warn(fmt.Sprintf("appstore: catalogue refresh failed (%v) and no cache; catalogue apps fail closed until the next refresh succeeds", err)) } } else { - log.Printf("appstore: loaded %d catalogue publisher pin(s)", cataloguePins.Count()) + slog.Info(fmt.Sprintf("appstore: loaded %d catalogue publisher pin(s)", cataloguePins.Count())) } // Refresh the pins periodically so newly-catalogued apps become spawnable // without a daemon restart. Daemon-lifetime loop; the process exit stops it. @@ -554,7 +554,8 @@ func main() { defer t.Stop() for range t.C { if err := cataloguePins.Refresh(); err != nil { - log.Printf("appstore: catalogue pin refresh failed: %v (keeping previous pins)", err) + // Every 10 minutes while offline; the previous pins stay. + slog.Info(fmt.Sprintf("appstore: catalogue pin refresh failed: %v (keeping previous pins)", err)) } } }() @@ -581,6 +582,11 @@ func main() { // supervisor confirms each non-sideloaded app's manifest publisher // against this before spawning. nil/unpinned => fail closed. CataloguePublisher: cataloguePins.Publisher, + // The daemon's own logger, so the app store's lines carry a + // level (INFO routine, WARN problems) like the rest of the log. + // Through its default log.Logger they had none, and the Mac app + // counted every one of them as a warning. + Slog: slog.Default(), }), }); err != nil { log.Fatalf("register appstore: %v", err) diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go index 437b918a..bbf856ce 100644 --- a/pkg/daemon/daemon.go +++ b/pkg/daemon/daemon.go @@ -1103,17 +1103,12 @@ func (d *Daemon) Start() error { return fmt.Errorf("tunnel listen: %w", err) } actualAddr = d.tunnels.LocalAddr().String() + // The tunnel binds every interface by default, as a node must to + // receive from its peers: that is not a warning. It was one, on + // every start of every default install, with a hint (-listen + // 127.0.0.1:0) that would cut the node off from the network. slog.Info("tunnel listening", "addr", actualAddr) - // Warn when the tunnel bound to a wildcard address — reachable - // from any network interface that can route to this host. - // Pass -listen 127.0.0.1:0 to restrict to localhost only. - if host, _, hostErr := net.SplitHostPort(actualAddr); hostErr == nil && (host == "0.0.0.0" || host == "::") { - slog.Warn("tunnel bound to wildcard address", - "addr", actualAddr, - "hint", "pass -listen 127.0.0.1:0 to restrict to localhost; see -endpoint for fixed public IP") - } - // Collect LAN addresses using the actual tunnel port (not config port which may be 0) _, actualPort, _ := net.SplitHostPort(actualAddr) if actualPort == "" || actualPort == "0" {