fix(sharing): honest published-address visibility bridge (SHR-8/SHR-10)#131
Merged
Conversation
…invite form
SHR-8: surface + set the account's published-site audience scope so a page set
"public" on a Private address stops silently lying about "anyone with the link".
- sdk: ForwardingClient.getSiteVisibility()/setSiteVisibility() over the EXISTING
owner-only account route (GET/PATCH /api/sites/:id, body {visibility}); add
SiteVisibility + SITE_VISIBILITIES mirroring @book.dev/forwarding. No default,
edge, or account change — the account still whitelist-validates + enforces
ownership server-side; the client only runs on the owner's device.
- ui: ForwardingProvider reads the REAL scope once online and exposes an
owner-only setter; SiteVisibilityControl ("Published address: Private/Public")
in the Sharing settings tab + Share dialog; Share dialog shows an actionable
notice when a page is public but the address is restricted.
SHR-10: remove the iss#sub handle invite affordance (handle resolution stub-fails,
OB-195) — invite by email only across all four locales.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
…+ review nits
Applies the consolidated, pre-endorsed review fixes to the site-visibility bridge:
- SiteVisibilityControl: for a site parked at authenticated/members (scopes this
desktop control never sets, but the account/edge honor distinctly) render an
honest read-only row with a DISABLED toggle + accurate hint + "Manage on the web"
pointer, instead of mislabeling it "Private" and collapsing it to restricted on a
flip. Keep the binary toggle only for the genuinely binary public<->restricted case.
- SiteVisibilityControl: correct the doc comment that wrongly claimed the edge
coarsens every non-public scope to private.
- SiteVisibilityControl: append the Public/Private state to the switch aria-label.
- ShareDialog: fire the site-mismatch notice on the EFFECTIVE scope, so an
inherit->public page is covered too (not just an explicit public).
- ShareDialog: bump the notice body to full contrast (not muted) and add an inline
"Make address Public" button that flips the site scope directly; add a
workspace-global hint under the control.
- SharingPublishingSettings: gate the control behind an explicit canManage guard
(defense-in-depth), matching the ShareDialog gating.
- i18n (en/de/ja/zh): new forwarding.visibility.{authenticated,members,
authenticatedHint,membersHint,manageOnWeb} + share.{makeSitePublic,siteGlobalHint}.
No SDK contract, default, edge, or account change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Owner
Author
|
It's too complicated and wordy, make it more concise. Something like:
|
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Page-visibility (set in-app) and site-visibility (the published
*.book.cloudaddress scope, held on the account, defaulting torestricted) were disconnected. A page set "Anyone with the link" was still silently bounced at the edge for anyone not signed in, because the edge serves only apublicaddress anonymously. So "anyone with the link" was false by default, with no in-app control over the address scope and no honest signal that the link was dead.A first cut of the bridge landed the control but under-stated exposure for the in-between account scopes: it treated everything that wasn't
publicas "Private" (anauthenticatedsite lets any signed-in stranger read; amemberssite lets the whole roster read), and toggling such a site would collapse it torestricted(lossy).Epic: Sharing & publishing — simplify + make honest (IA 2026-07) (Notion). Closes SHR-8, SHR-10.
Solution
get/setSiteVisibilityover the existing account routePATCH /api/sites/:id(owner-only, whitelist-validated + ownership-enforced server-side). No new account surface.authenticated/membersscopes this desktop control doesn't set: accurate hint ("Anyone signed in can open this address" / "Workspace members can open this address"), a disabled toggle that can't collapse the scope, and a "Manage on the web" pointer. Never mislabeled as "Private".iss#subhandle-invite form (email-only invites remain).No account edit, no default change, no edge/relay touched. This is UI/display + one notice-condition + review nits.
Key files:
packages/sdk/.../forwarding,ForwardingProvider,SiteVisibilityControl,ShareDialog,SharingPublishingSettings, i18n ×4 (en/de/ja/zh).Review fixes applied (all pre-endorsed)
authenticated/members(disabled toggle + accurate hint + "Manage on the web"); binary toggle kept only forpublic↔restricted.inherit→publicis covered (effectiveScope = scope === 'inherit' ? defaultVisibility : scope).publicscope to "private".canManage &&owner guard on the control in Settings (defense-in-depth).aria-label.Before / After
The control only renders behind a live forwarding tunnel (
publishedHost), so these are faithful static renders of the shipped component markup using the app's real design tokens. Live capture is the owner's prod-verify (below).authenticated/memberssites shown as "Private" with hint "signed-out visitors are turned away" — a false under-statement; flipping the toggle collapsed the scope torestricted. Mismatch notice was muted-contrast, fired only on an explicitpublicscope (missedinherit→public), and offered no inline fix.State-by-state (renders shown above):
restricted) — binary toggle, off. Hint: "…signed-out visitors are turned away."authenticated) — NEW read-only row, disabled toggle, state pill "Anyone signed in", hint "Anyone signed in can open this address.", "Manage on the web" link.members) — NEW read-only row, disabled toggle, state pill "Members", hint "Workspace members can open this address.", "Manage on the web" link.publicbut the address is Private: full-contrast amber notice + inline Make address Public button + "Applies to your whole published address, not just this page."Test procedure
pnpm verifygreen: build:libs ✓, typecheck ✓ (6 projects), lint ✓ (6 projects), test ✓ — SDK 175, UI 968, server 645 unit tests pass.publishedHost, which the Playwright suite can't stand up), so runtime verification is the owner's prod-verify below — not a CI gate here.Operational notes — OWNER GATE
This is edge-exposure: the owner merges and runs the prod verify (do not merge on gate-clearance alone). Prod-verify checklist:
restricteddefault).*.book.cloudlink → expect BOUNCED (proves the defect this PR surfaces).Sasha's residual notes for prod-verify:
PATCH— glance at the account route's CORS/CSRF posture.members/authenticatedscope (the read-only row handles display, but the setter here only ever writespublic/restricted).Gates cleared: security ✓ Sasha, code ✓ Quinn, design ✓ Devon (blocker fixed to their pre-endorsed shape).
Verify: green (build:libs / typecheck / lint / test — SDK 175 · UI 968 · server 645). Gates: security ✓ Sasha · code ✓ Quinn · design ✓ Devon. Owner merges (edge-exposure).
🤖 Generated with Claude Code
https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w