Skip to content

CreatorTrack GitHub integration (inbound events + outbound task actions)

URL: https://mkdocs.justinsforge.com/memory/general/reference_creatortrack_github_integration/

GitHub is ONE connection type (lib/api-connections.ts provider github), not a "dev mode". Both directions, built 2026-07-11 (Phase 2 of the automated-dev-pipeline plan) on branch feat/automations-github-pipeline. All logic in lib/github.ts.

Status: DEPLOYED to prod 2026-07-12 (merged to main 1b4a3b4, github-resolver migration applied, restarted). Verified live: core.github_connection resolver present; public inbound webhook fails closed (bad signature -> 401, no-connection -> uniform 401, no enumeration oracle). Outbound host-locked to api.github.com, idempotent per (task, op, repo).

Connection

  • Workspace api_connections provider github, catalog fields: token (secret, outbound PAT), webhook_secret (secret, inbound HMAC), repo (owner/name), default_branch. Optional config.api_base overrides https://api.github.com (GHE / test double). Secrets AES-256-GCM encrypted at rest.

Inbound (events -> linked task)

  • Public receiver app/api/hooks/github?ws=<workspaceId> (no session). The workspace id is not secret; the X-Hub-Signature-256 HMAC is the gate.
  • Secret resolved pre-identity via SECURITY DEFINER core.github_connection(workspace_id) (migration 20260711T234500_feat_github_inbound_github_connection_resolver.sql), decrypted in Node (resolveWorkspaceGithubConnection). Then acts AS the connection owner under RLS.
  • Linking: the LINKED task is matched by scanning the workspace tasks-db cells for the PR/commit URL (the task's URL field, written by the dev-queue or by an outbound action). Check/status events carry the same PR html_url in pull_requests[].
  • Mapping: PR opened/reopened => status In Review + Result pending; PR merged => Deployed; check/status success => Result passing; failure => status Blocked + Result failing; push => logged. Untrusted payload (Rule #6): only mapped fields acted on. Each event logs a github_event activity row (actor GitHub).

Outbound (task -> branch/PR/issue)

  • runGithubOp(me, workspaceId, task, {op, title?, base?, head?, body?}): opens an issue, creates a branch off the default branch, or opens a PR on the connected repo, then writes the created URL onto the task's URL field (so inbound events later match it).
  • Wired as the automation github action executor (runGithubAutomationAction) AND a manual task action app/api/tasks/[id]/github (POST {op, ...}). So "status to Ready to Merge => open PR" works, plus a manual "Open branch/PR/issue" button.

Verification

scripts/dev-verify-github-inbound.ts (signed PR/check payloads -> status/Result/activity; bad signature 401; ping->pong) and scripts/dev-verify-github-outbound.ts (issue/branch/pr via manual route + automation action against a mock GitHub API, URL written back). All pass. See Phase 2 results.

[Claude Code]