Skip to content

WIP: first-class session sharing (shared flag + built-in Share button)#114

Draft
benvinegar wants to merge 1 commit into
mainfrom
prototype/first-class-sharing
Draft

WIP: first-class session sharing (shared flag + built-in Share button)#114
benvinegar wants to merge 1 commit into
mainfrom
prototype/first-class-sharing

Conversation

@benvinegar

Copy link
Copy Markdown
Member

Draft / RFC. Prototype exploring whether "sharing" should be a first-class concept in the OSS core, so a wrapping host (sideshow cloud) can own only the share dialog while the engine owns the button. Opening for design discussion, not merge.

Idea

Today a session has no notion of being shared, and the viewer's ss:session-actions slot is empty by default — an embedder (cloud) projects its own Share button + dialog. This prototype moves the button into the engine as built-in chrome and lets the host own just the dialog:

  • Self-hosted: a real Share button that marks the session shared and hands over its stable /session/:id URL (built-in fallback dialog — no host code needed).
  • Embedded (cloud): the same button, but the host supplies the dialog via a new onShareClick hook (cloud mints a tenant-scoped link). The button's "Shared" pill is driven by session.shared.

Changes

  • shared boolean on the session — SQLite column (probe-and-ALTER migration like agentSeq), Session type, both stores (JsonFileStore + SqlStore), contract test.
  • PATCH /api/sessions/:id now accepts { shared? } (still accepts { title? }), broadcasting session-updated so live viewers relight.
  • Host contract gains onShareClick?(sessionId) — engine owns the button, host owns the dialog. Omitted → built-in copy-the-URL fallback, so self-hosted parity holds.
  • Viewer renders the built-in Share button + "Shared" pill in the session header.

Verified

  • 201 tests pass (3 new: store-contract shared, PATCH route), typecheck, full build + embed.
  • Live self-hosted run (Playwright): button renders → click opens dialog → PATCH flips session.shared → pill relights to "Shared".

Deliberately deferred (for discussion)

Enforcement of read access from the flag — i.e. a per-session publicRead mode that gates unauthenticated reads on session.shared. This prototype proves the UX/architecture split; today shared is cosmetic in OSS (no read gate). The cloud already gates per-session reads at its edge, so it doesn't block on this — but self-hosted sharing only becomes "real" once enforcement lands. That's the main open design question.

🤖 Generated with Claude Code

…button)

Make "sharing" a first-class concept in the OSS core so the cloud can stop
owning the Share button and own only the dialog.

- Session gains a `shared` boolean: SQLite column (probe-and-ALTER migration
  like agentSeq), Session type, JsonFileStore + SqlStore, and a contract test.
- PATCH /api/sessions/:id now accepts `{ shared? }` (still accepts `{ title? }`),
  broadcasting session-updated so live viewers relight.
- Host contract gains onShareClick?(sessionId): the engine owns the Share BUTTON
  and its "Shared" pill (lit from session.shared); the host owns the DIALOG. When
  no host provides it, a built-in copy-the-/session/:id-URL dialog is the
  self-hosted fallback, so self-hosted needs no host code.
- Viewer renders the built-in Share button in the session header.

Deferred (noted in code): ENFORCING read access from the flag (per-session
publicRead). This proves the UX/architecture split; the cloud already gates
reads at the edge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant