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_connectionsprovidergithub, catalog fields:token(secret, outbound PAT),webhook_secret(secret, inbound HMAC),repo(owner/name),default_branch. Optionalconfig.api_baseoverrideshttps://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; theX-Hub-Signature-256HMAC is the gate. - Secret resolved pre-identity via SECURITY DEFINER
core.github_connection(workspace_id)(migration20260711T234500_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+ Resultpending; PR merged =>Deployed; check/statussuccess=> Resultpassing; failure => statusBlocked+ Resultfailing; push => logged. Untrusted payload (Rule #6): only mapped fields acted on. Each event logs agithub_eventactivity row (actorGitHub).
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
githubaction executor (runGithubAutomationAction) AND a manual task actionapp/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]