008d638cf77546cee712cda8412c13ed2782c838
braney
  Sat Sep 5 07:29:12 2026 -0700
urlCommandCatalog: describe the recovery-email link and the Share dialog.

--reconcile was reporting six names the tree reads that were in neither
the catalog nor the baseline.  Four are URL parameters and get rows; two
are cart reads and go in the baseline, by the rule that a cgi* read is a
URL parameter and a cart* read is not.

recovEmail          hgLogin.c:1391, cgiUsualString.  The recovery
address a confirmation link is claiming, on the
hgLogin.do.confirmRecovEmail path.  Same shape as
newEmail and authorized by the same sig and exp.
In hgLogin's excludeVars, so it does not persist.
hgS_failIfExists    hgSession.c:1096, cgiBoolean.
hgS_snapshotType    hgSession.c:1099, cgiOptionalString.
hgS_doAnonName      one more of the hgS_do* commands, so it is listed
as a member of the hgS_* family rather than given
a row of its own.

hgLogin_newRecovEmail1, hgLogin_newRecovEmail2   cartUsualString reads
at hgLogin.c:1532 and 1533, the two inputs on the
change-recovery-address form.  Baselined next to
hgLogin_newEmail1 and 2, which are the same thing.

While writing those, hgS_shareAnon turned out to be misfiled.  It sat in
urlNamesNotCataloged.txt as internal state, but hgSession.c:1095 reads it
with cgiBoolean, which makes it a request parameter like the two that
arrived beside it.  It now has a row with them.  All three are
cartRemove'd in the handler, at hgSession.c:1107 to 1109, so none of them
leaks into the saved session.

The baseline also moves s and u from hgBlat.c to hgc.c.  Neither name
changed; hgc.c gained its own reads of the two old BLAT share parameters,
and the annotation records one site.

refs #37923

diff --git src/hg/utils/urlCommandCatalog/urlCommandCatalog.py src/hg/utils/urlCommandCatalog/urlCommandCatalog.py
index b6187e3a082..e5536819290 100755
--- src/hg/utils/urlCommandCatalog/urlCommandCatalog.py
+++ src/hg/utils/urlCommandCatalog/urlCommandCatalog.py
@@ -282,36 +282,66 @@
           note="Whether the saved session may be shared with others."),
         c("hgS_newSessionDescription", "action",
           "hg/hgSession/hgSession.c:2546", value="<text>", verified=True,
           leaks=True,
           partialDrop="cartRemove at hgSession.c:2547 covers "
                       "doDescribeSessionJson, the AJAX endpoint added with the "
                       "opt-in Sessions page at 9f8d33c8b2b.  doSessionChange "
                       "reads the same variable out of the cart at "
                       "hgSession.c:1833 and never removes it, and it is in "
                       "neither hgSession's excludeVars[] nor doSaveSessionJson's "
                       "cleanup beside its two siblings.  In 165 of 6607 saved "
                       "sessions, 41 of them carrying text the user typed.",
           note="Free-text description for a saved session.  Read from the "
                "request by the JSON endpoint and from the cart by the form "
                "path, which is why it appears both here and in the cart."),
+        # The "Share a link" dialog's three request parameters.  All three are
+        # read with cgi* and cartRemove'd in the handler, so none of them
+        # persists.  hgS_shareAnon sat in urlNamesNotCataloged.txt on the
+        # reading that it was internal state, which its cgiBoolean read
+        # contradicts; it is described here beside the two that arrived with it.
+        c("hgS_shareAnon", "action", "hg/hgSession/hgSession.c:1095",
+          verified=True,
+          note="Save under the reserved anonymous user \"l\" with a "
+               "server-generated token name instead of under the logged-in "
+               "user, which is what makes a short /s/l/<token> link.  Implied "
+               "when nobody is logged in, so it is only needed to ask for an "
+               "anonymous link while logged in.  Removed at "
+               "hgSession.c:1107."),
+        c("hgS_failIfExists", "action", "hg/hgSession/hgSession.c:1096",
+          verified=True,
+          note="Answer {\"exists\": true} instead of overwriting a session "
+               "the logged-in user already has under the requested name, so "
+               "the Share dialog can warn before clobbering one.  Removed at "
+               "hgSession.c:1108."),
+        c("hgS_snapshotType", "action", "hg/hgSession/hgSession.c:1099",
+          value="<type>", verified=True,
+          note="Save a lightweight snapshot session holding only one "
+               "feature's declared cart variables (hg/lib/snapshotSession.c) "
+               "rather than the whole cart, e.g. blat.  The stored name is "
+               "forced to the \"__\" snapshot prefix so a token cannot "
+               "collide with a real session name, a type no snapshotTypeFind "
+               "knows is refused, and so is a save whose required cart "
+               "variables are not there yet, rather than minting a link that "
+               "would reopen to nothing.  Removed at hgSession.c:1109."),
         c("hgS_*", "action", "hg/hgSession/hgSession.h:19", value="<varies>",
           note="hgSession's own command family. All transient.",
           members=["hgS_doNewSession", "hgS_doSaveLocal", "hgS_doLoadLocal",
                    "hgS_doMainPage", "hgS_doSessionDetail",
                    "hgS_doSessionChange", "hgS_doReSaveSession",
                    "hgS_doSaveSessionJson", "hgS_doRenameSessionJson",
+                   "hgS_doAnonName",
                    "hgS_load_*", "hgS_delete_*", "hgS_edit_*", "hgS_share_*",
                    "hgS_gallery_*", "hgS_showDownload_*",
                    "hgS_makeDownload_*", "hgS_doDownload_*", "hgS_cancel"]),
     ],
 }
 
 
 # ---------------------------------------------------------------------------
 # hgTracks: navigation
 # ---------------------------------------------------------------------------
 
 HGTRACKS_NAV = {
     "what": "The zoom and scroll buttons. These are form button names rather "
             "than anything a user would type, and #37923 proposes collapsing "
             "them behind one hgt.nav= command while keeping every old name "
@@ -1065,30 +1095,44 @@
               value="<email>", verified=True,
               note="The address a change-of-email confirmation link is "
                    "claiming.  Authorized by sig rather than by a login "
                    "cookie, on purpose, so the link works from the new "
                    "mailbox in any browser."),
             c("exp", "action", "hg/hgLogin/hgLogin.c:1220", value="<epoch>",
               verified=True,
               note="When that confirmation link stops working.  Inside the "
                    "signed material, so it cannot be pushed out by editing "
                    "the URL."),
             c("sig", "action", "hg/hgLogin/hgLogin.c:1221", value="<hmac>",
               verified=True,
               note="The signature over user, newEmail and exp that "
                    "authorizes the change.  Checked before anything else in "
                    "the link is trusted."),
+            c("recovEmail", "action", "hg/hgLogin/hgLogin.c:1391",
+              value="<email>", verified=True,
+              note="The recovery address a confirmation link is claiming, on "
+                   "the hgLogin.do.confirmRecovEmail path.  The same shape as "
+                   "newEmail above, and authorized by the same sig and exp "
+                   "pair, so the link works from the new mailbox with no "
+                   "login cookie.  The signed material also covers the "
+                   "address currently on the account and whether it was "
+                   "confirmed, so changing the recovery address retires every "
+                   "link outstanding against the old one.  The address is "
+                   "written to gbMembers only after the signature checks out "
+                   "and spc_email_isvalid accepts it.  hgLogin's excludeVars "
+                   "(hgLogin.c:47) lists it, so it does not stay in the "
+                   "session."),
         ],
     },
     "smaller CGIs": {
         "what": "One or two commands each.",
         "cmds": [
             c("resource", "action", "hg/hgLinkIn/hgLinkIn.c:121",
               value="<kind>", public=True, verified=True,
               note="hgLinkIn: what kind of external identifier follows."),
             c("id", "action", "hg/hgLinkIn/hgLinkIn.c:121", value="<id>",
               public=True, verified=True,
               note="hgLinkIn: the external identifier to resolve."),
             c("ajaxSection", "action", "hg/hgGene/hgGene.h:264",
               value="<section>", verified=True,
               note="hgGene: render one section of the gene page."),
             c("showAllRef", "action", "hg/hgGene/gad.c:62", value="Y",