From f746fef81218af9e53e25f9c8d3a2f5776a8ef2a Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Tue, 4 Aug 2026 18:28:51 -0700 Subject: [PATCH 1/3] fix(sdk): allow generated registered user names --- docs/PLUGIN_AUTHOR_GUIDE.md | 11 ++++++----- docs/WIRE_PROTOCOL.md | 5 ++++- sdks/js/index.d.ts | 4 ++-- sdks/python/owncast_plugin/__init__.py | 9 +++++---- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/docs/PLUGIN_AUTHOR_GUIDE.md b/docs/PLUGIN_AUTHOR_GUIDE.md index b358114..802071e 100644 --- a/docs/PLUGIN_AUTHOR_GUIDE.md +++ b/docs/PLUGIN_AUTHOR_GUIDE.md @@ -834,11 +834,12 @@ return { status: 302, headers: { Location: returnTo } }; `users.register` finds or creates an authenticated Owncast user for an external identity. The host scopes `authId` to your slug, so pass the provider's raw -stable ID. `profileUrl` must be empty or an absolute HTTP(S) URL. Set `handle` -to the verified provider label and set `public` true only after the viewer opts -into public display. `grantSession` and `endSession` are meaningful only inside -`onHttpRequest`, where the host attaches or clears the cookie after the handler -returns. +stable ID. `displayName` is optional. Omit it or pass `null` to generate a +display name. `profileUrl` must be empty or an absolute HTTP(S) URL. Set +`handle` to the verified provider label and set `public` true only after the +viewer opts into public display. `grantSession` and `endSession` are meaningful +only inside `onHttpRequest`, where the host attaches or clears the cookie after +the handler returns. ### Re-validating sessions: `onAuthCheck` diff --git a/docs/WIRE_PROTOCOL.md b/docs/WIRE_PROTOCOL.md index 5949b89..948e6d2 100644 --- a/docs/WIRE_PROTOCOL.md +++ b/docs/WIRE_PROTOCOL.md @@ -291,6 +291,9 @@ authentication gate uses this before granting a session. as the unmodified provider-specific ID. The host rejects administrative or otherwise disallowed scopes. + `displayName` is optional and nullable. When omitted or `null`, the host generates + the user's display name. + ### `auth.gate` Only one `auth.gate` plugin can be enabled at a time. These calls are meaningful @@ -745,7 +748,7 @@ type CommandEvent = { type UserRegisterRequest = { authId: string; - displayName?: string; + displayName?: string | null; scopes?: string[]; profileUrl?: string; handle?: string; diff --git a/sdks/js/index.d.ts b/sdks/js/index.d.ts index 74304f1..620e784 100644 --- a/sdks/js/index.d.ts +++ b/sdks/js/index.d.ts @@ -212,8 +212,8 @@ export const Permissions: { export interface UserRegisterRequest { /** Stable external identity within this plugin's provider namespace. */ authId: string; - /** Optional display name to seed on the user. */ - displayName?: string; + /** Optional display name to seed on the user. Omit or pass `null` to generate one. */ + displayName?: string | null; /** Optional scopes to grant the user (e.g. `["MODERATOR"]`). */ scopes?: string[]; /** Verified public profile URL. The host accepts only absolute HTTP(S) URLs. */ diff --git a/sdks/python/owncast_plugin/__init__.py b/sdks/python/owncast_plugin/__init__.py index 626e32e..3e31caf 100644 --- a/sdks/python/owncast_plugin/__init__.py +++ b/sdks/python/owncast_plugin/__init__.py @@ -655,10 +655,11 @@ def register( ): """Find or create an authenticated user for an external identity. - auth_id is the stable, provider-scoped ID. profile_url and handle - describe a verified external profile. Set public=True only when the - viewer agreed to show that identity publicly. Returns an object with - .user_id. Raises on host error. Requires 'users.register'. + auth_id is the stable, provider-scoped ID. Omit display_name to have + Owncast generate one. profile_url and handle describe a verified + external profile. Set public=True only when the viewer agreed to show + that identity publicly. Returns an object with .user_id. Raises on host + error. Requires 'users.register'. """ req = {"authId": str(auth_id)} if display_name is not None: From 5afb557b141d389e60e8211524c767ec2d1a4c7f Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Tue, 4 Aug 2026 18:44:59 -0700 Subject: [PATCH 2/3] build(runtime): update Owncast dependency --- host-runtime/go.mod | 2 +- host-runtime/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/host-runtime/go.mod b/host-runtime/go.mod index e5bc56c..86d91ba 100644 --- a/host-runtime/go.mod +++ b/host-runtime/go.mod @@ -5,7 +5,7 @@ go 1.26.2 require ( github.com/extism/go-sdk v1.7.1 github.com/gobwas/glob v0.2.3 - github.com/owncast/owncast v0.2.6-0.20260803201111-10d12cba1ffb + github.com/owncast/owncast v0.2.6-0.20260804005024-a1ee0743079c modernc.org/sqlite v1.53.0 ) diff --git a/host-runtime/go.sum b/host-runtime/go.sum index db201c8..66327ea 100644 --- a/host-runtime/go.sum +++ b/host-runtime/go.sum @@ -24,8 +24,8 @@ github.com/mattn/go-sqlite3 v1.14.47 h1:jOBI62gS7nKeZv+as1oGEy0+1qISgXwH/QBlR6Kb github.com/mattn/go-sqlite3 v1.14.47/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/owncast/owncast v0.2.6-0.20260803201111-10d12cba1ffb h1:v28vfyeK0/0hsjLA4Xju/pkeu/2wyuGRfwnn+K+DomU= -github.com/owncast/owncast v0.2.6-0.20260803201111-10d12cba1ffb/go.mod h1:/pBiqGTab5UMn37wapn4zzpQUG2476ayj/zlsyJMcgA= +github.com/owncast/owncast v0.2.6-0.20260804005024-a1ee0743079c h1:RUnvkPsZ9PzQB/jhvtV/VezkpSETXRsfqHfYw1l9/Bo= +github.com/owncast/owncast v0.2.6-0.20260804005024-a1ee0743079c/go.mod h1:/pBiqGTab5UMn37wapn4zzpQUG2476ayj/zlsyJMcgA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= From 0cf88d7c67337d311cb30f4aa94b622f931bfc1e Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Tue, 4 Aug 2026 18:50:51 -0700 Subject: [PATCH 3/3] docs(sdk): clarify generated user names --- docs/PLUGIN_AUTHOR_GUIDE.md | 2 +- sdks/python/owncast_plugin/__init__.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/PLUGIN_AUTHOR_GUIDE.md b/docs/PLUGIN_AUTHOR_GUIDE.md index 802071e..3749419 100644 --- a/docs/PLUGIN_AUTHOR_GUIDE.md +++ b/docs/PLUGIN_AUTHOR_GUIDE.md @@ -371,7 +371,7 @@ Each method requires the matching permission in your manifest: | `owncast.users.list()` / `.get(id)` | `users.read` | | `owncast.users.setEnabled(id, enabled, reason?)` | `users.moderate` | | `owncast.users.banIP(ip)` | `users.moderate` | -| `owncast.users.register({authId, displayName?, scopes?, profileUrl?, handle?, public?})` | `users.register` | +| `owncast.users.register({authId, displayName?: string \| null, scopes?, profileUrl?, handle?, public?})` | `users.register` | | `owncast.auth.grantSession({userId, ttl?})` / `owncast.auth.endSession()` | `auth.gate` | | `owncast.kv.get(key)` / `.set(key, value)` (+ `.getJSON` / `.setJSON`) | `storage.kv` | | `owncast.storage.upload(name, bytes)`, returns `{url}` | `storage.upload` | diff --git a/sdks/python/owncast_plugin/__init__.py b/sdks/python/owncast_plugin/__init__.py index 3e31caf..a97641c 100644 --- a/sdks/python/owncast_plugin/__init__.py +++ b/sdks/python/owncast_plugin/__init__.py @@ -655,11 +655,11 @@ def register( ): """Find or create an authenticated user for an external identity. - auth_id is the stable, provider-scoped ID. Omit display_name to have - Owncast generate one. profile_url and handle describe a verified - external profile. Set public=True only when the viewer agreed to show - that identity publicly. Returns an object with .user_id. Raises on host - error. Requires 'users.register'. + auth_id is the stable, provider-scoped ID. Omit display_name or pass + None to have Owncast generate one. profile_url and handle describe a + verified external profile. Set public=True only when the viewer agreed + to show that identity publicly. Returns an object with .user_id. Raises + on host error. Requires 'users.register'. """ req = {"authId": str(auth_id)} if display_name is not None: