You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Issue #8 / #11 shipped GitHub sync using a single global `GITHUB_TOKEN` and per-project `githubRepo` selected manually from a dropdown. This works when the admin already has access to the target repo, but creates friction (and a security surface) as the project scales to multiple clients:
The admin must manually create a repo for each new project before pushing tasks
A single PAT must be authorized on every client repo, becoming a master-key
Clients with their own GitHub org need to add the admin's personal account as collaborator
Per discussion in PR/conversation following #11: in the majority of cases the admin will own the repo. Automating that default eliminates manual setup for ~90% of projects without precluding the edge case (client's own org).
What to build
When a spec transitions to `review` (admin approves spec), the data-service automatically creates a private GitHub repo under the configured org and persists its `full_name` to the project. The dropdown shipped in #11 continues to work as a manual override for edge cases (e.g. client owns the repo).
Backend
Org configuration: New worker env var `GITHUB_ORG` (default `auditmos-projects`). Set as a non-secret `var` in `wrangler.jsonc` per environment.
New service: `createRepo(token, org, name, options)` in `apps/data-service/src/hono/services/github-client.ts`:
Handles `422 name already exists` by retrying with `{slug}-{nanoid(4)}` once
Hook into spec approval: In `spec-task-service.ts → approveSpec(slug)`, after the `interviewing/review → review` status transition succeeds:
If `project.githubRepo` is already set → skip (admin manually configured)
Else → call `createRepo(env.GITHUB_TOKEN, env.GITHUB_ORG, project.slug)` and `updateProjectGithubRepo(project.id, fullName)`
Failure to create repo MUST NOT roll back the approval — log the error, return success; admin can manually pick a repo later
PAT scopes (fine-grained, scoped to `auditmos-projects` org):
Repository permissions: Administration: Read and write (create repo), Issues: Read and write (existing), Contents: Read and write
One PAT covers all current and future repos under the org
Frontend
No changes required. The dropdown from #11 already:
Shows current `githubRepo` selection (now auto-populated by the backend)
Allows the admin to override (e.g. switch to client's own repo)
The repo list (`GET /github/repos`) continues to fetch from the same token's accessible repos
Acceptance criteria
New env var `GITHUB_ORG` defined in `worker-configuration.d.ts` and set per-env in `wrangler.jsonc` (`auditmos-projects` for staging/production)
`createRepo()` in github-client.ts: creates private repo via GitHub API, returns `GithubRepo` shape, handles 401 (token invalid) and 422 (name taken) with one retry using suffix
On `POST /projects/:slug/approve`, when project has no `githubRepo`, a private repo `auditmos-projects/{slug}` is created and persisted
If `createRepo` fails (network/422-after-retry/forbidden), spec approval still succeeds; error is logged; admin can use the dropdown override
If project already has `githubRepo` set (manual override), `approveSpec` does NOT create a new repo
TDD: unit tests for `createRepo` (happy path, 401, 422 retry → success, 422 retry → final fail), integration test for `approveSpec` covering both auto-create and skip-when-set branches
TDD slice plan (suggested)
`createRepo` happy path — POSTs to `/orgs/{org}/repos` with private: true, returns `GithubRepo`
`createRepo` 401 — returns `Result.error` with `GITHUB_UNAUTHORIZED`
`createRepo` 422 + retry fail — returns `Result.error` with `GITHUB_REPO_NAME_TAKEN`
`approveSpec` auto-creates — when `githubRepo: null`, calls createRepo and persists
`approveSpec` skips — when `githubRepo` set, no createRepo call
`approveSpec` resilient — when createRepo fails, approval still completes (200), log emitted
Out of scope (defer to future issues)
GitHub App (true multi-tenancy with per-installation tokens) — only needed when many clients want their repo under their own org, and admin doesn't want to be a collaborator. Track separately.
Per-project token storage — only relevant if we move away from single-org model
Reduces friction for the multi-client workflow described in user stories 13-15 (PRD #1) by removing the manual "create repo + select repo" step from project setup.
Notes
`GITHUB_TOKEN` must be re-issued as a fine-grained PAT scoped to `auditmos-projects` org with Administration: write before deploy. Existing PAT (Issues: write only) will fail `createRepo` with 403.
Slug format from `packages/data-ops/src/project/slug.ts` already includes a random suffix, so collisions on first create should be rare; the 422 retry handles the edge case.
Logged `createRepo` failures should include `{ slug, status, githubError }` for debugging without leaking the token.
Parent PRD
#1
Context
Issue #8 / #11 shipped GitHub sync using a single global `GITHUB_TOKEN` and per-project `githubRepo` selected manually from a dropdown. This works when the admin already has access to the target repo, but creates friction (and a security surface) as the project scales to multiple clients:
Per discussion in PR/conversation following #11: in the majority of cases the admin will own the repo. Automating that default eliminates manual setup for ~90% of projects without precluding the edge case (client's own org).
What to build
When a spec transitions to `review` (admin approves spec), the data-service automatically creates a private GitHub repo under the configured org and persists its `full_name` to the project. The dropdown shipped in #11 continues to work as a manual override for edge cases (e.g. client owns the repo).
Backend
Org configuration: New worker env var `GITHUB_ORG` (default `auditmos-projects`). Set as a non-secret `var` in `wrangler.jsonc` per environment.
New service: `createRepo(token, org, name, options)` in `apps/data-service/src/hono/services/github-client.ts`:
Hook into spec approval: In `spec-task-service.ts → approveSpec(slug)`, after the `interviewing/review → review` status transition succeeds:
PAT scopes (fine-grained, scoped to `auditmos-projects` org):
Frontend
No changes required. The dropdown from #11 already:
Acceptance criteria
TDD slice plan (suggested)
Out of scope (defer to future issues)
User stories addressed
Reduces friction for the multi-client workflow described in user stories 13-15 (PRD #1) by removing the manual "create repo + select repo" step from project setup.
Notes