Bring stale and spliced comments back in line
Four comments cited Web#unauthorized, which is the error handler now.
web.rb, setup.rb and the Dockerfile described tailscale serve in front
of the app where ProxyAuth and the README describe a proxy writing
Remote-User; the Dockerfile's now says to publish the port on
localhost alone, since the app trusts whatever header it is handed.
Three import comments had been spliced mid-sentence, and one claimed
a doubled membership raises when add_member ignores it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VNdx5qiRSWADBoVfDRcrd
change
commit bfd0f01799f618a0bfc30a700e72f392678b7f70
author Claude <noreply@anthropic.com>
date
parent 5228906f
diff --git a/Dockerfile b/Dockerfile
index 1cfd158..d52f9eb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -34,6 +34,8 @@ COPY --from=build /app /app
 
 EXPOSE 9292
 
-# 0.0.0.0 reaches only the container's own network namespace — exposure
-# to clients is tailscale serve's job, in front of the published port.
+# 0.0.0.0 reaches only the container's own network namespace. Exposure to
+# clients is the proxy's job (ProxyAuth): publish the port on localhost
+# alone (-p 127.0.0.1:9292:9292), because reached directly the app trusts
+# whatever Remote-User it is handed.
 CMD ["rackup", "-o", "0.0.0.0"]
diff --git a/lib/pro_tacts/exchange_log.rb b/lib/pro_tacts/exchange_log.rb
index bb9253c..d162df3 100644
--- a/lib/pro_tacts/exchange_log.rb
+++ b/lib/pro_tacts/exchange_log.rb
@@ -131,7 +131,7 @@ module ProTacts
     end
 
     # A 401 is the identity gate refusing a request that names nobody
-    # (Web#unauthorized): nothing went wrong, and unless everything is
+    # (Web's error handler): nothing went wrong, and unless everything is
     # asked for, a body from outside the tailnet stays off disk.
     #: (Integer status) -> bool
     def failed?(status)
diff --git a/lib/pro_tacts/import/vcf.rb b/lib/pro_tacts/import/vcf.rb
index ce62c57..68a7b59 100644
--- a/lib/pro_tacts/import/vcf.rb
+++ b/lib/pro_tacts/import/vcf.rb
@@ -27,6 +27,13 @@ module ProTacts
       # A file that is not a set of vCards.
       class Invalid < StandardError; end
 
+      # Apple's own name for a row, carried on a line of its own beside
+      # the one it names (`item1.X-ABLabel:_$!<Spouse>!$_`). Known, and
+      # named apart from the rest because what happens to the line it
+      # annotates happens to it too: a label whose line is gone names
+      # nothing (#read).
+      LABEL = "X-ABLABEL" #: String
+
       # The properties this address book reads, and so the properties
       # an import brings in. The envelope (BEGIN, END, VERSION, UID),
       # the fields a screen shows (Contact's own readers: N, FN,
@@ -40,13 +47,6 @@ module ProTacts
       # screen for a property is what brings it in, and until then
       # importing one would only pad the cards with what nobody can
       # read.
-      # Apple's own name for a row, carried on a line of its own beside
-      # the one it names (`item1.X-ABLabel:_$!<Spouse>!$_`). Known, and
-      # named apart from the rest because what happens to the line it
-      # annotates happens to it too: a label whose line is gone names
-      # nothing (#read).
-      LABEL = "X-ABLABEL" #: String
-
       KNOWN = [
         *%w[BEGIN END VERSION UID N FN NICKNAME BDAY TEL EMAIL ADR NOTE PHOTO],
         LABEL,
diff --git a/lib/pro_tacts/import/write.rb b/lib/pro_tacts/import/write.rb
index bf3fe92..c246ec0 100644
--- a/lib/pro_tacts/import/write.rb
+++ b/lib/pro_tacts/import/write.rb
@@ -87,8 +87,8 @@ module ProTacts
         # them off this same store. Deduplicated because two of these
         # can mean one group — a name typed for a group that the box
         # above it already offers, or everyone's book arriving both
-        # ticked and asked for — and a membership written twice is a
-        # constraint violation rather than a second membership.
+        # ticked and asked for — and a second join of one group would
+        # only be asked of Store#add_member to come to nothing.
         join = [*chosen, *named.map { group_id(it) }]
         join << group_id(Group::EVERYONE) if everyone
         @store.regroup(id, join: join.uniq, leave: []) unless join.empty?
@@ -151,9 +151,9 @@ module ProTacts
       # into an empty store creates `sync:*` (Store#everyone_group_id),
       # and a list read before that would send this to create it again.
       # Memoized so that a card given the same name twice reads the
-      # list once rather than making the group twice. The choices read, not the whole groups read:
-      # the match is on name, and a group's members are no part of it
-      # (Store#group_choices).
+      # list once rather than making the group twice. The choices read,
+      # not the whole groups read: the match is on name, and a group's
+      # members are no part of it (Store#group_choices).
       #: (String name) -> String
       def group_id(name)
         @group_ids[name] ||= @store.group_choices.find { it.name == name }&.id || @store.create_group(name:)
diff --git a/lib/pro_tacts/proxy_auth.rb b/lib/pro_tacts/proxy_auth.rb
index f54e168..1193e0c 100644
--- a/lib/pro_tacts/proxy_auth.rb
+++ b/lib/pro_tacts/proxy_auth.rb
@@ -27,7 +27,7 @@ module ProTacts
     # The header the proxy writes the login to, and Rack's spelling of
     # the same field in the environment. One pair, because three places
     # name it: the read below, the 401 that says which header was read
-    # (Web#unauthorized), and the Sentry scrubber that keeps it out of
+    # (Web's error handler), and the Sentry scrubber that keeps it out of
     # an event (config.ru).
     HEADER = "Remote-User" #: String
     ENV_KEY = "HTTP_#{HEADER.upcase.tr("-", "_")}" #: String
diff --git a/lib/pro_tacts/stub_login.rb b/lib/pro_tacts/stub_login.rb
index 90f61d6..bdf2edb 100644
--- a/lib/pro_tacts/stub_login.rb
+++ b/lib/pro_tacts/stub_login.rb
@@ -4,8 +4,8 @@ require "pro_tacts/proxy_auth"
 module ProTacts
   # Rack middleware that writes a fixed login to Remote-User, the way the
   # proxy in front of a deployment does, so a server with nothing in
-  # front answers instead of refusing every request (ProxyAuth,
-  # Web#unauthorized). A request that already carries the header keeps
+  # front answers instead of refusing every request (ProxyAuth, and
+  # Web's error handler). A request that already carries the header keeps
   # its own, so `curl -H` can still ask as someone else.
   #
   # It stands in for the proxy, so it belongs only where there is none.
diff --git a/lib/pro_tacts/web.rb b/lib/pro_tacts/web.rb
index cabd7cc..34b2e0c 100644
--- a/lib/pro_tacts/web.rb
+++ b/lib/pro_tacts/web.rb
@@ -25,8 +25,8 @@ module ProTacts
     # The vendored Gloss CSS and the admin app's own stylesheet (see
     # docs/DESIGN.md); relative to this file rather than $0 for the same
     # reason Store::MIGRATIONS is, and served by Roda's own `public`
-    # plugin rather than a reverse proxy — there is no reverse proxy
-    # here, `tailscale serve` hands requests straight to this app.
+    # plugin rather than by the proxy in front, which passes every
+    # request through and writes the login on it (ProxyAuth).
     PUBLIC_ROOT = Pathname.new(
       __dir__ #: String
     ).parent.parent / "public" #: Pathname
@@ -55,7 +55,7 @@ module ProTacts
 
     # Inside CaptureExceptions, so the exchange tag lands on the scope it
     # opens for the request. Outside the route's identity gate
-    # (#unauthorized), and safe there because a 401 is not a failure it
+    # (the error handler below), and safe there because a 401 is not a failure it
     # keeps (ExchangeLog#failed?). The log opens when Roda builds the
     # stack, not here, so requiring the app writes nothing.
     use ProTacts::ExchangeLog, path: ProTacts.config.exchange_log_path, everything: ProTacts.config.debug?
diff --git a/lib/pro_tacts/web/import.rb b/lib/pro_tacts/web/import.rb
index 858ad9e..509abe2 100644
--- a/lib/pro_tacts/web/import.rb
+++ b/lib/pro_tacts/web/import.rb
@@ -150,8 +150,6 @@ module ProTacts
     end
 
     # A row opened: the card it arrived as beside the card that is
-    # coming in — or the contact itself, for a card this walk has
-    # One contact, the card it arrived as beside the card that is
     # coming in. The right-hand half is the contact editor itself, not a
     # copy of it: a field the two disagreed about would be a field an
     # import writes and an edit cannot undo.
diff --git a/lib/pro_tacts/web/setup.rb b/lib/pro_tacts/web/setup.rb
index 385a8dc..e926500 100644
--- a/lib/pro_tacts/web/setup.rb
+++ b/lib/pro_tacts/web/setup.rb
@@ -16,8 +16,8 @@ module ProTacts
     # the address a device reached this app at is reachable from that
     # device by construction, where an environment variable is a claim
     # about some other machine's idea of where we live. It is the
-    # client's Host header, which behind `tailscale serve` is serve's
-    # own — and past the identity gate in web.rb's trunk, the only
+    # client's Host header, which the proxy in front passes along
+    # (ProxyAuth) — and past the identity gate in web.rb's trunk, the only
     # devices asking are on the tailnet.
     hash_branch("setup") do |r|
       r.is do