diff --git a/docs/app-profiles/streampixels.md b/docs/app-profiles/streampixels.md index 23eb040..c9054c7 100644 --- a/docs/app-profiles/streampixels.md +++ b/docs/app-profiles/streampixels.md @@ -38,13 +38,17 @@ In the service-first Heimdall version, the most likely reusable slice is: - viewer audience profiles - creator memberships tied to streamer spaces -- creator connector credentials +- creator connector bindings and feature semantics - overlay/runtime state - audience-facing app data in general In plain language: - Heimdall can authenticate and authorize the control plane +- Heimdall can also own OAuth flow and token custody for creator-side provider + connections when that reduces auth duplication +- StreamPixels still owns which creator a connection belongs to, what + subscriptions or sync flows it drives, and how failures are surfaced - StreamPixels audience data stays StreamPixels data ## Capability direction diff --git a/docs/architecture.md b/docs/architecture.md index 96b56a5..85c27a2 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -81,11 +81,18 @@ their brand name appears somewhere in an app. proves who the user is and can supply one `LinkedIdentity` - `Entitlement source` answers whether some access-relevant claim is currently true +- `Managed provider credential` + a user- or account-authorized third-party credential whose OAuth dance, token + custody, refresh, and revocation Heimdall can own on behalf of an app - `Local grant source` records app or operator-issued overrides inside Heimdall -- `App-owned connector OAuth` - authenticates an app's operational integration with a third-party platform - and does **not** become Heimdall territory just because it uses OAuth + +Default rule: + +- if a future app needs user-facing or account-linked OAuth, Heimdall should + own the ugly parts by default +- the app should only need to describe what the resulting connection means in + its own world One provider can play different roles in different apps: @@ -93,8 +100,9 @@ One provider can play different roles in different apps: sources - Bifrost can treat GitHub as identity proof while keeping membership approval, roles, and governance state app-local -- StreamPixels can reuse shared viewer identity patterns while keeping - creator-side Twitch/YouTube connector credentials and runtime plumbing +- StreamPixels can reuse shared viewer identity patterns and even shared + OAuth/token custody for creator-side Twitch/YouTube connections while keeping + creator bindings, subscriptions, diagnostics, and runtime plumbing StreamPixels-owned ## System shape @@ -113,11 +121,12 @@ flowchart TD The important split: - Heimdall owns provider OAuth, identity linking, entitlement refresh, signed - sessions, claims, grants, and audit surfaces + sessions, claims, grants, audit surfaces, and managed provider credential + custody - the host experiment owns its workload, queue, editor, render path, viewer profile model, creator model, or other product-specific machinery -- app-owned operational connector OAuth stays with the app unless there is a - very deliberate reason to centralize it +- the host experiment also owns which local entity a connection attaches to, + what permissions it implies, and what runtime behavior consumes it Do not smear provider logic directly through every host runtime. @@ -246,13 +255,23 @@ Shared adapters should be boring and reusable: - `InviteGrantProvider` - reusable invite-issued app or role grants where that pattern makes sense +Shared connection handling can also cover app integrations when the credential +is user- or account-authorized and worth centralizing: + +- Heimdall can own OAuth start/callback, token exchange, encrypted storage, + refresh, and revocation +- the app still owns binding the connection to a local entity such as + `creator_id`, `workspace_id`, `project_id`, or `channel_id` +- the app still owns sync jobs, subscriptions, diagnostics, feature toggles, + and the domain-specific consequences of that connection + Important rule: - a provider being used anywhere in an app does not automatically make all uses of that provider Heimdall-owned -- creator/operational connector OAuth such as StreamPixels broadcaster - connectors stays app-owned unless it is deliberately promoted into the shared - auth authority +- provider OAuth and token custody should default to Heimdall when the + connection is tied to a user or account rather than a purely app-local secret +- app-specific binding semantics and runtime behavior still stay app-owned ## Policy model @@ -332,6 +351,8 @@ Every hosted experiment should integrate through the same seams: - mark which routes are public, authenticated, or capability-gated - attach `account_id`, `session_id`, and `access_revision` to owned resources such as jobs, drafts, uploads, or queue entries +- if the app uses Heimdall-managed provider connections, bind those connections + onto app-local entities and keep the downstream runtime behavior local - require resource-owner checks on private read/update/delete paths If an app has a queue or job system: @@ -418,8 +439,10 @@ Suggested generic env surface: Only configure the providers Heimdall actually owns for a given deployment. Per-app binding should live in code or profile config, not in cloned provider -env namespaces. App-owned connector OAuth should stay under the app's own env -surface even when the upstream provider name overlaps. +env namespaces. App-local binding and runtime config such as creator +associations, webhook subscriptions, sync toggles, or workspace/project +attachment rules should stay under the app's own config/state even when the +underlying OAuth credential is Heimdall-managed. ## Audit Result diff --git a/state/evidence.jsonl b/state/evidence.jsonl index 886cfe7..f69d964 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -1,5 +1,5 @@ {"ts":"2026-04-26T00:00:00Z","type":"design","status":"accepted","note":"The shared hosted-access plan was extracted from Repixelizer into its own repo so the backbone can evolve separately from app-specific notes."} {"ts":"2026-04-26T00:00:00Z","type":"design","status":"superseded","note":"The initial first implementation hypothesis was an embedded shared gamecult_access package. This was later superseded by the Heimdall service-first shape after the cross-runtime split and Yggdrasil topology review."} -{"ts":"2026-04-26T00:00:00Z","type":"boundary","status":"accepted","note":"StreamPixels can reuse the same auth/control-plane backbone, but streamer-audience data, creator memberships, connector credentials, and runtime state should remain StreamPixels-owned."} +{"ts":"2026-04-26T00:00:00Z","type":"boundary","status":"accepted","note":"StreamPixels can reuse the same auth/control-plane backbone, and Heimdall may own OAuth/token custody for shared provider connections, but streamer-audience data, creator memberships, creator-side connection bindings, and runtime state remain StreamPixels-owned."} {"ts":"2026-04-26T06:00:00Z","type":"design","status":"accepted","note":"The cross-runtime split and current Yggdrasil topology changed the first implementation shape from an embedded shared package to Heimdall: a shared auth authority service whose signed claims are verified locally by each app."} -{"ts": "2026-04-26T11:00:02+00:00", "type": "design", "status": "accepted", "note": "Heimdall's provider model splits shared identity providers and entitlement sources from app-owned connector OAuth. Different provider mixes change adapter inventory and claim vocabulary, not the core service boundary."} +{"ts": "2026-04-26T11:00:02+00:00", "type": "design", "status": "accepted", "note": "Heimdall's provider model splits shared OAuth and credential custody from app-owned binding semantics and runtime use. Different provider mixes change adapter inventory and claim vocabulary, not the core service boundary."}