GitHub Channel — Current Platform Foundation
The GitHub channel is not yet built, but the platform already provides all of the infrastructure it relies on. This document maps what exists today and how the GitHub channel hooks into each piece.
Channel System
ChannelMaster catalog
ChannelMaster is a seeded DB table that defines which channel types are available. Adding GitHub requires one new seed row:
{
type: "GitHub",
name: "GitHub",
description: "Map repository source files to landing pages and websites",
iconKey: "github",
categories: ["Source Control"],
authenticationType: "OAuth",
requiresUrl: false,
isActive: true,
}authenticationType: "OAuth" matches the pattern used by Facebook, Google, LinkedIn, and all other OAuth channels. The connect flow triggers the same OAuth popup pattern already used across the platform.
ConnectedChannel model
ConnectedChannel already has all the fields GitHub needs:
tokenInfo— encrypted JSON{ accessToken, refreshToken?, expireOn?, scope? }— stores the OAuth token received after authorizationuserInfo— plain JSON{ id, name }— stores the authenticated GitHub user (login + display name)subChannelInfo— plain JSON — stores{ owner: string, repo: string, defaultBranch: string }after repository selectiontitle— user-given name (e.g., “Acme Website Repo”)connectionHistory— audit log (already used by all channels)
The isConnected flag is set to true after the OAuth callback completes and a repository is selected. Token refresh follows the same pattern as Google channels (refresh token stored alongside access token; workers refresh before making API calls).
OAuth flow infrastructure
apps/api/src/routers/channel-connect.ts already implements the OAuth popup pattern for 9 providers (Facebook, Instagram, LinkedIn, GSC, Google Ads, GA4, GBP, Bing, Zoho). The GitHub OAuth flow adds entries following the exact same structure:
GET /github/connect— authenticated; returns OAuth authorization URLGET /github/callback— anonymous; receives code, exchanges for token, saves to channel, redirects to repo selectionGET /github/repo/select?state={channelId}— anonymous; returns HTML form listing accessible reposPOST /github/repo/select— anonymous; saves selectedsubChannelInfo, closes popup
Channel analytics route
GET /tenant/v1/channels/:id/analytics already dispatches by channel type. Adding a GitHub case returns: commit count (last 30/90 days), open PR count, last push date, number of source maps, and last sync timestamp.
OAuth App Registration
GitHub uses a platform-level OAuth App (not a GitHub App) registered by Leadmetrics — same model as the Google and Meta OAuth Apps already in use. Two new env vars are required:
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...Required OAuth scopes: repo (read + write for private repos), admin:repo_hook (webhook registration for push events)
These are added to .env.example alongside existing GOOGLE_CLIENT_ID, META_APP_ID, etc.
Provider Packages
Five provider packages already exist (packages/providers/{google,meta,linkedin,microsoft,zoho}/). Each follows the same structure:
packages/providers/{provider}/
src/
index.ts ← public entrypoint
types.ts ← OAuthInfo, TokenInfo, ChannelApiError
{name}.ts ← service classA new packages/providers/github/ package follows this exact pattern. The GitHubService class wraps the GitHub REST API using plain fetch with Authorization: Bearer {accessToken}. It implements the same authorize() / authorizeCallback() / refreshToken() contract as all other OAuth providers, plus repo access and code manipulation methods used by the sync and coding agent workers.
RAG Pipeline
The platform has an existing RAG ingestion pipeline used by blog posts, social posts, and context documents. Synced source file content flows into this pipeline using the same pre-loaded dataset type. The github-source-sync worker calls the RAG ingest endpoint with extracted page content — no RAG changes are needed.
- RAG pipeline location: documented in
docs/—project_rag_pipeline.mdmemory - Role → dataset mapping:
"github-source"maps to a new dataset type; the source sync worker registers it
Insight Worker Base
packages/agents/src/workers/insights/insight-worker-base.ts is the base class for all channel insight workers. The GitHub insight worker extends it. The base handles:
- Loading the
ConnectedChannelrecord - Storing the result in a
ChannelInsightDB record - Token decryption and refresh
- Claude invocation
- Error and status tracking
Approval Flow
The coding agent requires DM approval before running. The platform already implements DM approval gates for blog posts (dm_review status) and deliverable plans (dm_approved status). The AgentCodeChange model follows the same status machine pattern: pending_review → approved → running → pr_opened. The approval API endpoint follows the same pattern as PUT /tenant/v1/blog/:id/dm-approve.
Claude Tool Use (Coding Agent)
The coding agent uses Claude’s tool use capability (Anthropic SDK tools parameter) — not the subprocess adapter system used by content workers. This is the same mechanism used by the Agent Chat feature. The worker instantiates an Anthropic SDK client directly, passes tool definitions for read_file, list_directory, write_file, and create_pr, and lets Claude drive the edit loop until it calls create_pr to finalize. This approach supports deep structural changes because Claude can read multiple files, understand framework context, and make interdependent edits before committing.
Notification System
enqueueNotification() is the existing notification infrastructure used by all channel workers. The GitHub workers use it for:
- Source sync completed (notify DM)
- Source sync failed — token expired, repo not found, rate limit (notify DM)
- Code change PR opened — includes PR URL (notify DM)
- Code change failed (notify DM)
Queue System
packages/queue/src/queues.ts defines all BullMQ queues. Three new queues are added:
| Queue name | Worker | Purpose |
|---|---|---|
agent__github-source-sync | github-source-sync.worker.ts | Fetch + extract source files, ingest to RAG |
agent__github-insights | github-insights.worker.ts | SEO gap analysis from extracted content vs target keywords |
agent__github-code-agent | github-code-agent.worker.ts | Pull source, apply approved recommendations, push PR |
Queue registration follows the existing pattern in queues.ts and types.ts.
Dashboard Channel Detail
apps/dashboard/src/app/(dashboard)/channels/[id]/page.tsx dispatches to a type-specific detail component. Adding a GitHubChannelDetail.tsx component follows the same pattern as all other detail pages. The component receives the ConnectedChannel record and renders:
- Overview tab (repo stats, linked source maps, last sync)
- Source Maps tab (file → channel mappings with sync controls)
- Code Changes tab (all
AgentCodeChangerecords with status and PR links) - AI Insights tab (same
ChannelInsightPanelcomponent used by all channels)
Key Existing Files
| File | Role in GitHub integration |
|---|---|
packages/db/prisma/schema.prisma | Add ChannelSourceMap + AgentCodeChange models |
packages/db/prisma/seed.ts | Add GitHub ChannelMaster seed row |
apps/api/src/routers/channels.ts | Add repo browser endpoints + GitHub analytics case |
apps/api/src/routers/channel-connect.ts | Add GitHub OAuth flow routes (connect/callback/repo-select) |
apps/api/src/routers/source-maps.ts | New — source map CRUD + sync + code change triggers |
apps/api/src/app.ts | Register source-maps router (test entry) |
apps/api/src/index.ts | Register source-maps router (production) |
packages/queue/src/queues.ts | Register three new queues |
packages/queue/src/types.ts | Add job payload types |
apps/dashboard/src/app/(dashboard)/channels/[id]/page.tsx | Add GitHubChannelDetail dispatch case |
.env.example | Add GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET |