Skip to main content
Glama
codepawl

codepawl-video-lab

Official
by codepawl
README.md
# CodePawl Video Lab

Self-hosted, evidence-first YouTube analysis for CodePawl. The Chrome extension collects only the active YouTube URL plus data the user deliberately imports. A Cloudflare Worker stores dossiers and authorized channel analytics in D1. Codex reads and writes analysis through a stateless Streamable HTTP MCP server; there is no LLM inside the extension.

```text
YouTube URL → Chrome side panel → Worker + D1 → /mcp → Codex
                                      ↑             │
                                      └── reports ──┘
```

## Workspace

```text
apps/extension   WXT + React MV3 side panel and library
apps/worker      Cloudflare Worker, D1, Cron, Google OAuth and remote MCP
packages/contracts  shared Zod schemas, parsers and evidence rules
docs             architecture, security and approval-gated deployment notes
```

The extension has no content script. Its built manifest requests `sidePanel`, `storage`, `activeTab` and `tabs`; it does not inspect the YouTube DOM, download captions, or access video/audio bytes.

## Local development

Requirements: Node 22+, npm 12+, Chrome 114+.

```bash
git clone git@github.com:codepawl/codepawl-video-lab.git
cd codepawl-video-lab
npm ci
npm run cf:types
npm run db:migrate:local
npm run dev:worker
npm run dev:extension
```

Copy `apps/worker/.dev.vars.example` to the gitignored `.dev.vars` and fill only local credentials. Generate `TOKEN_ENCRYPTION_KEY` as 32 random bytes encoded with base64 or base64url. Google OAuth redirect URI for local development is:

```text
http://127.0.0.1:8787/oauth/youtube/callback
```

Create a ten-minute pairing code through the local admin route, then enter it in the side panel. The resulting extension token expires after 30 days and can be revoked with **Ngắt thiết bị**:

```bash
curl -X POST http://127.0.0.1:8787/api/v1/admin/pairing-codes \
  -H "Authorization: Bearer $LOCAL_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"label":"Chrome extension"}'
```

Build the unpacked extension:

```bash
npm run build --workspace @codepawl/video-lab-extension
```

Then load `apps/extension/.output/chrome-mv3` from `chrome://extensions` with Developer mode enabled. Installing it into a personal Chrome profile is intentionally a manual/approval-gated action.

## Data rules

- Reference videos: metadata and anonymized comment text come from YouTube Data API v3. Comments are cached briefly; author identity is never stored.
- Transcripts: user paste or `.srt`, `.vtt`, `.txt` import only.
- CodePawl: `youtube.readonly` and `yt-analytics.readonly` only. No upload, metadata edit or publish scopes exist.
- `Stayed to watch`: manual Studio observation with explicit provenance. It is not represented as an Analytics API metric.
- Reference-channel retention, CTR and `Stayed to watch` are never inferred.
- Every finding must point to evidence with source, observation time, confidence and limitation.
- Public API data expires after 30 days. Cron first attempts a fresh API observation; expired reference data is removed if refresh is unavailable.
- Google refresh and access tokens are AES-256-GCM encrypted before D1 persistence.

## MCP

`/mcp` is a stateless `createMcpHandler` server backed by D1. It exposes:

- `video_inbox_list`
- `video_dossier_get`
- `video_dossiers_compare`
- `channel_performance_get`
- `retention_curve_get`
- `analysis_report_save`
- `experiment_create`
- `experiment_update`

Resource: `codepawl://rubrics/shorts-v1`.

In production, Cloudflare Access Managed OAuth protects `/mcp`; the Worker independently verifies the Access assertion issuer, audience and RS256 signature. After deployment and Access setup:

```bash
codex mcp add codepawl-video-lab --url https://video-lab.codepawl.com/mcp
codex mcp login codepawl-video-lab
```

Run those two `codex mcp` commands on each machine that should connect to the deployed server. Authentication is per machine; credentials and local Codex configuration are not stored in this repository.

## Tracking

Cron runs every 15 minutes and discovers uploads through the authorized channel uploads playlist. New videos receive real future targets at 2h, 24h and 72h plus daily rollups. Historical imports get an initial observation at connection time and never receive fake backdated milestone timestamps. Empty Analytics responses remain `pending` and retry with bounded backoff. Job unique keys and snapshot constraints make repeated runs idempotent.

## Validation

```bash
npm run typecheck
npm test
npm run build
npm run db:migrate:local
npm run worker:dry-run
```

The visual fixture is local-only:

```bash
cd apps/worker
npx wrangler d1 execute video-lab --local --file test/fixtures/visual-qa.sql
cd ../..
npm run visual:dev --workspace @codepawl/video-lab-extension
```

Open `http://127.0.0.1:4173/visual.html?surface=sidepanel` or `visual.html` for the library. The harness uses fixture data and is not included in the MV3 build.

## Approval boundary

No Cloudflare resource, DNS record, Access application, Google OAuth credential or production deployment is created by this repository setup. See [docs/deployment.md](docs/deployment.md) for the exact resource packet that requires separate approval.

## License

MIT. See [LICENSE](LICENSE).

## Primary references

- [Chrome Side Panel API](https://developer.chrome.com/docs/extensions/reference/api/sidePanel)
- [YouTube Analytics metrics](https://developers.google.com/youtube/analytics/metrics)
- [YouTube API developer policies](https://developers.google.com/youtube/terms/developer-policies)
- [YouTube Captions API](https://developers.google.com/youtube/v3/docs/captions/list)
- [Cloudflare stateless MCP handler](https://developers.cloudflare.com/agents/model-context-protocol/apis/handler-api/)
- [Cloudflare Access Managed OAuth](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/managed-oauth/)
- [Cloudflare Access JWT validation](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/validating-json/)
- [Codex Streamable HTTP MCP](https://learn.chatgpt.com/docs/extend/mcp#streamable-http-servers)