Skip to content

Rewire hub from samod access-policy fork to upstream samod 0.16.0 - #917

Merged
shikokuchuo merged 3 commits into
mainfrom
braid/bd-jvag5d4w-rewire-hub-samod-access
Oct 26, 2026
Merged

shikokuchuo merged 3 commits into
mainfrom
braid/bd-jvag5d4w-rewire-hub-samod-access

Conversation

@shikokuchuo

Copy link
Copy Markdown
Member

Switches the hub's sync engine from our patched samod fork to the official samod 0.16.0 release on crates.io.

  • The quarto-dev/samod fork is retired. samod and samod-core now come from crates.io, and automerge stays at 0.12.0 with no new transitive dependencies.
  • The fork's custom access-policy patch is replaced by samod's built-in SharePolicy. The hub keeps its current behaviour: it only serves documents a client asks for and never advertises document IDs.
  • The per-document "Document accessed" audit lines are removed. samod 0.16 checks the share policy for every loaded document when a client connects, so those lines would name documents the user never opened. The audit log instead gains ws_connect and ws_disconnect events for each sync session.
  • Includes samod 0.15's protocol hardening (stricter identity checks on direct messages) for free.

Verified end to end: all tests pass, existing data directories load unchanged, JS clients sync against the new hub, and presence works across two browser tabs.

Plan: claude-notes/plans/2026-10-26-samod-0-16-share-policy.md (bd-jvag5d4w)

…-jvag5d4w)

Dependency source: samod + samod-core move from the quarto-dev/samod
`access-policy` branch (0.14.0 + one commit, git+ source in Cargo.lock)
to crates.io samod 0.16.0 (registry source; the lockfile diff is only
the two packages' version/source/checksum lines). automerge stays a
single 0.12.0 and no transitive deps are added or removed — no new
native-tls/openssl edges. quarto-hub, quarto-hub-provider and
quarto-preview switch in lockstep so the crates unify to one copy.

API migration:
- The fork's synchronous `AccessPolicy` patch and `AnnouncePolicy`
  (`NeverAnnounce`) are replaced by upstream's `SharePolicy` seam. The
  hub installs a constant `ShareConfig::read_write().with_announce(false)`
  through a named `hub_share_policy()` seam, pinned by a unit test that
  asserts the fields (access=ReadWrite, announce=false) rather than
  comparing against the upstream constructor — the security-critical
  announce-off behavior, so the hub serves only documents an
  authenticated peer actively requests instead of advertising every
  loaded document ID.
- `accept_axum(socket)` becomes `accept_axum(socket, None)` (the 0.15
  signature). `None` is safe because nothing in the hub authorizes on a
  peer ID; bd-07kbzn1d tracks `Transport::with_expected_peer_id` for any
  future policy that does.

Audit logging: REMOVED, not ported. The pre-migration spike showed
SharePolicy subscription is eager per (loaded doc, connected peer):
share() fires at connection establishment for every locally loaded
document, before any find(), so a policy-driven "Document accessed"
line would emit phantom accesses for documents the user never opened.
The security audit also found the peer_emails map — keyed by the
client-chosen peer ID — was a misattribution vector (a client claiming
another user's peer ID overwrote, then deleted, that user's entry).
Session-granularity events on the existing quarto_hub::audit target
replace it: `ws_connect` when the upgrade completes (before samod sees
the socket) and `ws_disconnect` when the connection ends, carrying the
samod reason or "stream_closed"; both carry sub/credential_kind and are
emitted only when auth is enabled, matching auth_ok. bd-tfribfyy
records the loss and the design constraints for any replacement.

Also inherits samod 0.15's protocol hardening for free: direct messages
whose sender differs from the handshake identity, or that are addressed
to another peer, are now rejected before dispatch.

Verification: three-crate suite 840/840 (baseline 844 − 7 deleted
access_policy tests + 3 new); clippy/fmt clean; workspace suite
17291/17292 (sole failure a proven worktree-nesting artifact, passes in
the main checkout); JS↔Rust interop 5/5 against the migrated binary;
on-disk smoke loads the pre-migration index without re-init; zero
"Document accessed" lines under -v; two-client ephemeral/presence
check through the hub passes both directions. cargo xtask verify
passes with the npm legs skipped (no node_modules in the worktree, as
in the July migration) and rust-tests/feature-sets covered in-phase.

Plan: claude-notes/plans/2026-10-26-samod-0-16-share-policy.md
Follow-ups: bd-tfribfyy (audit-log loss), bd-07kbzn1d
(with_expected_peer_id), bd-e2l028k4 (cargo deny baseline).
@posit-snyk-bot

posit-snyk-bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Review follow-ups to a1dcd15 (samod 0.16 SharePolicy rewire):

- Drop the now-dead peer_info.clone() in the ClientConnected arm — it
  existed to keep peer_info alive for the removed connected_peer_id
  move; nothing uses peer_info afterwards anymore.
- format_peer_info takes Option<&PeerInfo> instead of &Option<PeerInfo>
  (idiomatic borrow; unit tests updated).
- ws_disconnect reason is now "repo_stopped" when the repo refuses the
  socket, instead of the misleading "stream_closed"; ops doc updated.
  This arm is compile-covered only — the test harness has no path to a
  stopped repo, same as the pre-existing warn! there.

No snapshot changes. cargo nextest -p quarto-hub: 504/504; clippy
--all-targets -D warnings and fmt clean.
@shikokuchuo
shikokuchuo merged commit a776b46 into main Oct 26, 2026
15 checks passed
@shikokuchuo
shikokuchuo deleted the braid/bd-jvag5d4w-rewire-hub-samod-access branch October 26, 2026 17:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants