1. Decision snapshot
- The full product name is Better YouTube Studio; the short name is byts. Legacy product naming is retired.
- The primary surfaces are web, mobile, and MCP. The CLI and its device-flow infrastructure are removed rather than maintained as a dormant compatibility surface.
- Web remains the only control plane. Mobile and MCP are full-featured but read-only analytics clients.
- An organization may independently track a channel publicly, deeply through OAuth, or both.
- Tracked and deeply tracked channels are separate Durable Object classes with separate storage and source credentials.
- Every organization member can view every node. Per-channel member permissions are deferred.
- Channel capabilities are advertised explicitly and enforced on every targeted request.
- “Top videos” is replaced by one sortable video catalog on both dashboard types.
2. Current architecture
The current repository is a pnpm and Vite+ monorepo. apps/web is a SvelteKit application deployed as a Cloudflare Worker; it serves the browser UI, REST routes, remote functions, static assets, and a stateless Streamable HTTP MCP endpoint. apps/mobile is an Expo application. packages/shared carries analytics response types and formatters.
| Layer | Current responsibility |
|---|---|
| SvelteKit edge | Clerk session authentication, input validation, routes, remote functions, static assets, and MCP transport |
| Application services | Resolve selected channel and Google grant, then orchestrate dashboard, video, comments, Reach, and refresh use cases |
| OrgDO | Organization channel/grant catalog, machine credentials, authorization, and audit records |
| GoogleGrantDO | Encrypted OAuth tokens and refresh lifecycle |
| ChannelDO | Per-channel metadata, videos, private analytics, comments, Reach, caches, alarms, and refresh coordination |
| UserDO | Browser-session selected-channel preference |
| DeviceFlowDO | One-time CLI device authorization and credential handoff |
The strongest current properties should survive: organization authorization is separate from channel data; long-lived secrets are encrypted; machine credentials are hash-verified; stale-good data remains visible during upstream failure; refresh promotion is atomic and generation-ordered; and web, REST, and MCP already share a dashboard service layer.
3. Product surfaces and roles
| Surface | Role | Channel selection | Mutations |
|---|---|---|---|
| Web | Full analytics and sole control plane | Open a node from the organization directory | Admins add/remove nodes and request refreshes; members manage their own connections |
| Mobile | Full read-only analytics | Remember selected node locally per device | None; every member may authorize their own device |
| MCP | Full read-only analytics for agents | Every analytics call supplies a node ID | None; every member may create their own MCP connection |
Organization authorization
- Every member can list and view every tracked and deeply tracked node.
- Every member can authorize their own mobile device and create, view, or revoke their own MCP credentials.
- Admins can manage all organization MCP credentials.
- Only admins can add/remove channel nodes or trigger immediate refreshes.
- No per-channel member permission schema is introduced yet.
4. Channel data model
The organization catalog contains independent channel nodes. A node is uniquely identified within an organization by:
(organization ID, tracking type, YouTube channel ID)
The same YouTube channel may appear once as tracked and once as deeply tracked. Exact duplicates within one tracking type are rejected. The classes do not coordinate or implement an upgrade path; replacing one type with the other is an explicit create-and-delete workflow.
| Concern | TrackedChannelDO | DeeplyTrackedChannelDO |
|---|---|---|
| Source credential | One platform-managed YouTube API key | Encrypted OAuth token material owned by the node |
| Public metadata | Yes, through API key | Yes, through OAuth only |
| Private analytics | No | Yes |
| Comments | Public top-level comments | OAuth-backed comments |
| History | Latest public values only | Private date-ranged reports and source data |
| Synchronization | Object-owned background loop | Object-owned background loop |
Deep OAuth selection
- An admin completes Google OAuth.
- The callback discovers every accessible channel.
OrgDOtemporarily holds encrypted pending token material while the admin selects any subset.- One deeply tracked object is created per selected channel, each with its own encrypted token copy.
- The pending authorization is erased. Abandoned pending material expires automatically.
- Deleting one deep node erases only its local token copy and does not revoke the upstream grant shared by sibling nodes.
5. Capability matrix
list_channels and the web/mobile directory return node ID, YouTube channel ID, tracking type, display metadata, and an explicit capability array. Clients do not infer support solely from tracking type.
| Capability | Meaning | Tracked | Deeply tracked |
|---|---|---|---|
public_stats | Current channel identity, description, subscribers, lifetime views, and public video count | Yes | Yes |
public_videos | Sortable video catalog, individual metadata, and current public counters | Yes | Yes |
comments | Public top-level comments for a video | Yes | Yes |
private_analytics | Date-ranged channel and video performance, daily series, and engagement | No | Yes |
reach | Thumbnail impressions and click-through data | No | Yes |
retention | Audience-retention data for an individual video | No | Yes |
public_stats means current public values only. Date-ranged views belong to private_analytics. Calling an operation without its capability returns a structured capability_not_available error; unsupported metrics are absent or explicitly unavailable, never represented as zero.
MCP shape
MCP credentials are organization-scoped. Every targeted tool requires a node ID and reauthorizes it against OrgDO. Tools remain task-oriented: list channels, get public stats, list/sort videos, get video details, get comments, get private channel/video analytics, get Reach, and get retention. Exact schemas and pagination are intentionally deferred.
6. Video catalog
Both node types use the same catalog boundary:
- Seed the latest 20 uploads at creation.
- Append new uploads during background synchronization.
- Allow an older video to be requested explicitly by YouTube ID.
- Verify channel ownership before adding that video to the catalog.
Records retain title, description, publication time, thumbnails, duration, tags/category when available, current public views/likes/comment count, synchronization metadata, and source-specific data.
Content kind
Every video is normalized as video, short, live, or unknown. Live-stream metadata wins; otherwise a duration under 180 seconds is classified as a Short; everything else is a standard video. Deep analytics may use YouTube’s authoritative content-type dimension when available.
One sortable table
Both tracked and deep dashboards use a sortable videos table. The default is newest first. Sorting by total views yields the practical top-videos view; other sorts can use likes, comments, or capability-specific analytics. There is no separate “Top videos” product concept.
7. Target Durable Object topology
| Class | Owns | Coordination atom |
|---|---|---|
| OrgDO | Unified node catalog, uniqueness, credentials, audit events, and temporary OAuth selection state | One organization |
| TrackedChannelDO | API-key public channel/video/comment data and synchronization | One organization + public channel |
| DeeplyTrackedChannelDO | OAuth token copy, public/private analytics, comments, Reach, retention, and synchronization | One organization + OAuth-backed channel |
User-level state moves to Clerk or the client device. The target removes UserDO, GoogleGrantDO, and DeviceFlowDO. Cloudflare class migration tags and live-data cutover need an explicit migration plan; deleting source files is not sufficient to retire deployed Durable Object classes.
8. The Effect v4 reference migration
OrgDO is the best reference object: it survives the target architecture and exercises identity, migrations, synchronous SQLite, transactions, authorization, credentials, and typed domain failures. It avoids Google network I/O while the Effect boundary is being proven. The smaller current objects are slated for deletion; the large channel object is too entangled for the first migration.
The repository currently has no Effect dependency. The reference should be a behavior-preserving migration before the larger data-model change.
Reference shape
- Pin one Effect v4 version with the package manager, inspect its installed declarations, and configure the matching Effect language service.
- Define small capability services rather than one giant object service: organization catalog repository, credential repository, audit sink, clock/ID generation where useful.
- Model expected failures as tagged errors: identity mismatch, duplicate node/credential, unauthorized channel, revoked credential, invalid scope, and storage failure.
- Keep the exported Durable Object RPC class thin. Each RPC parses ordinary input, runs one composed Effect program, and returns a plain serializable value.
- Keep Effect, Layers, Causes, and service tags behind the RPC boundary.
- Use one runtime per active Durable Object instance only for share-safe, object-instance services. Never put one object’s
ctx, storage, or mutable state in a module-global runtime shared by other object instances. - Do not rely on runtime disposal: Cloudflare may evict or restart the object without an application shutdown hook.
- Keep SQLite transactions synchronous and free of Effect suspension or external fetches. Use
blockConcurrencyWhileonly for fast constructor initialization/migration work. - When channel objects later adopt the pattern, create external YouTube fetches per operation and keep refresh deduplication/generation ordering explicit.
Reference acceptance gate
- Existing RPC inputs, outputs, ordering, and authorization behavior remain unchanged.
- Format, type/framework checks, lint, and focused tests pass.
- The Effect semantic checker is proven active with a temporary negative canary, then passes cleanly.
- Tests cover two sequential invocations on one warm object, concurrent operations, tagged failures, defects, and transaction rollback behavior.
- Cloudflare Workers tests—not ordinary Node-only tests—exercise the reference boundary.
9. Recommended next steps
| Phase | Scope | Exit condition |
|---|---|---|
| 1 | Land the capability specification and update architecture documentation | Decisions are reviewable and no longer live only in conversation |
| 2 | Install/pin Effect v4 and its semantic tooling; add one canonical Durable Object runner/test harness | Negative canary proves semantic diagnostics are active |
| 3 | Migrate current OrgDO behavior to the reference Effect architecture without changing its wire contract | Reference passes Cloudflare tests and preserves behavior |
| 4 | Run an independent correctness and design review of the OrgDO reference, then harden the pattern | Service boundaries, lifetimes, errors, concurrency, and testing are accepted as the project standard |
| 5 | Launch the larger re-architecture job with repository hygiene as its first slice: finish naming cleanup and remove CLI/device-flow code, tests, scripts, and docs | Only web, mobile, and MCP remain; no tombstone documentation |
| 6 | Write and execute the deployed Durable Object migration/cutover plan using the reference conventions | Class additions, renames/deletions, schema changes, rollback, and data ownership are explicit |
| 7 | Implement the target OrgDO catalog, TrackedChannelDO, DeeplyTrackedChannelDO, routes, clients, and MCP | All surfaces converge on the agreed capability matrix |
| 8 | Validate the whole system in stages | Static gates, Workers integration tests, staging smoke paths, then production cutover |
The reference is successful only if it establishes typed domain errors, small service contracts, replaceable test Layers, one clear execution boundary, and correct Durable Object lifetimes. Wrapping existing Promises in Effect.tryPromise without changing ownership or testability would not provide a useful template for the re-architecture.
10. Deliberately deferred
- Per-channel member permissions.
- Exact background synchronization cadence, quota budgets, and freshness targets.
- Detailed MCP tool names, arguments, pagination, and result schemas.
- Automated tracked-to-deep or deep-to-tracked conversion.
- Historical public-counter snapshots and derived public trends.
- The exact Effect v4 API surface until the repository pins a version and its installed declarations are inspected.
- Current source snapshot
mainatcfea7eb- Working specification
docs/capability-matrix.mdoncodex/capability-matrix- Production runtime
- Cloudflare Workers, Static Assets, and SQLite Durable Objects
- Current Effect status
- Not installed; reference migration has not begun