SiteOwner becomes one plain type, SiteOwner { atproto_did, deploy_key_public } in lichen-site/src/owner.rs (where OwnerFacts was). The SiteOwner trait, LinkOwner, lichen-site's AuthProvider (it stays in lichen-server's users.rs), link::owner_facts, has_remote, should_push and start_iroh_side are gone, and the handle is dropped from the launch, LaunchIroh and the lent session, so the main runtime holds no handle.
A handle is derived from the DID only when it is verified both ways. The identity resolver moves to lichen-site/src/atproto/identity.rs with its SSRF guard, and gains names_both_ways, verified_handle and a TCP-only DNS resolver at 127.0.0.1:53 (a confined site with iroh off has no /etc/resolv.conf); the admin thread's fetches go through the site's egress. An old pds://<handle>/<domain> remote is pushed only when its handle verifies both ways to the owner's DID, and git is given the DID form per push.
OCTOBER-REVIEW-REVISIONS, subunit 5c. Plan: https://tangled.org/notplants-bot.bsky.social/lichen-orchestrator/blob/main/machine-docs/plans/OCTOBER-REVIEW-REVISIONS-2026-10-28.md
This is a reading copy: only this subunit's product changes, applied in order on its base. Nothing here is to be merged.
Source PRs on lichen.page.review (product), in order, with their original descriptions #
- #3410
s/778-orr-u5c-site-owner-did— ORR 5c: SiteOwner is one plain type; a handle only verified both ways; DID-form remotesOCTOBER-REVIEW-REVISIONS unit 5c, product:
SiteOwneris one plain type, and a handle comes from the DID only when it is verified both ways (C3, R6).-
SiteOwner { atproto_did, deploy_key_public }inlichen-site/src/owner.rs, whereOwnerFactswas; unit 6 moves it toipc/site_owner.rs. Gone:- the
SiteOwnertrait andLinkOwner; AuthProviderfrom lichen-site (it stays in lichen-server'susers.rs);link::owner_facts,has_remote,should_push,start_iroh_side;- the handle in the launch, in
LaunchIrohand in the lent session.
The main runtime holds no handle.
- the
-
The resolver moves to
lichen-site/src/atproto/identity.rs, with its SSRF guard. Its commit is a move: the AST check matched all 20 moved items, and its one difference is a//comment aboveclient.rs'suselines rewritten inside that commit. -
New in
identity.rs:names_both_ways,verified_handle, and a TCP-only DNS resolver at127.0.0.1:53, since a confined site with iroh off has no/etc/resolv.conf. The admin thread's fetches go through the site's egress. -
Remotes:
- An old
pds://<handle>/<domain>remote is pushed only when its handle verifies both ways to the owner's DID. Git is given the DID form per push (-c url.pds://<did>/….insteadOf=…), and the owner's URL is never rewritten. - A handle that names another DID becomes a proposal: "not pushed: this handle no longer names your account".
- A check that fails on the network is not a refusal and not a proposal: "not pushed: the handle could not be checked (network); it is tried again on the next push".
- New remotes and PDS site records are written in DID form; an import reads either.
- An old
-
iroh: collaborator entries stay handles; the site's own entry is recorded by the admin thread.
-
The
git-remote-pdspin moves to the fork's6e0847f2(notplants.net/git-remote-pds #14: the helper takes a DID-form URL). It changes in Cargo.toml, Cargo.lock, the flake hash and the submodule link.
-
Commits #
- 6bbbe5447 ORR 5c: orr-u5c-site-owner-did (#3410)
Count and shas #
count-product-code-lines 1a17a5513d0a..6bbbe5447b29: NET +272 · counted +739 -467 · moved out of the counted set +0 · comment-only deletions flagged 40 · macros flagged 0 · tests-folder code flagged 0
Base 1a17a5513d0af3957f19527a355d242346791c75 (tip of s/777-orr-u5b-no-seams-tests). Head 6bbbe5447b290ff799c86b0c057d5b29ee37e0c6. 48 files changed.
Check #
Every changed file is a file one of the product PRs changed, and each is identical at the head to the same file at the last product branch s/778-orr-u5c-site-owner-did.
Files that differ from the subunit's top branch s/779-orr-u5c-site-owner-did-tests: crates/lichen-site/src/atproto/tests/identity.rs.