Skip to content

Commit 3569fbe

Browse files
committed
docs: plan dual repo approach
1 parent cb9fbaf commit 3569fbe

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

docs/dual-repo-plan.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Dual-Repo Drift Plan
2+
3+
## Goal
4+
5+
Keep one identical codebase in two repositories:
6+
7+
- `owner/repo-public`: public merge surface, no secrets.
8+
- `owner/repo-private`: private policy engine and secret boundary.
9+
10+
Operationally:
11+
12+
- Drift detection runs in `repo-private` on a schedule.
13+
- If drift is detected, `repo-private` opens or updates a PR in `repo-public`.
14+
- After merge in `repo-public`, a sync-back path updates `repo-private` so both repos converge.
15+
16+
This is eventual consistency with PR-driven enforcement, not direct autonomous mutation of both repos.
17+
18+
## Roles and Trust Model
19+
20+
- `repo-private` is the trust boundary (holds `APP_ID`, `APP_PRIVATE_KEY`, drift secrets).
21+
- `repo-private` is the policy engine (detects/enforces drift contract).
22+
- `repo-public` is the canonical merge/history surface.
23+
- Preferred auth model: GitHub App installation token for all cross-repo writes.
24+
- Rationale: avoids long-lived personal access tokens (PATs) and manual PAT rotation.
25+
- Cross-repo writes must not rely on `GITHUB_TOKEN` from another repo.
26+
27+
## Repository and Remote Setup
28+
29+
1. Create two repos:
30+
31+
- `owner/repo-public`
32+
- `owner/repo-private`
33+
34+
2. In one local clone, add both remotes and push the same branches to both.
35+
3. Keep one shared workflow codebase in git; gate execution by `github.repository` so behavior diverges by target repo, not by file divergence.
36+
37+
## Workflow Gating
38+
39+
Use explicit repo checks in every sensitive job.
40+
41+
Examples:
42+
43+
- Public-safe jobs: `if: github.repository == 'owner/repo-public'`
44+
- Secret drift jobs: `if: github.repository == 'owner/repo-private'`
45+
46+
## Trigger Model
47+
48+
- Drift/policy workflow in `repo-private`: scheduled (`cron`) trigger.
49+
- Public-to-private sync workflow: push-based from `repo-public` default branch (or optional manual dispatch if needed).
50+
51+
Current intent: scheduled drift checks, not check-run gating.
52+
53+
## GitHub App Requirements
54+
55+
GitHub App is the default and recommended auth mechanism for this design.
56+
57+
1. Create one GitHub App and install on both repos.
58+
2. Minimum permissions:
59+
60+
- Contents: read/write (on target repo for branch push)
61+
- Pull requests: read/write (open/update PRs)
62+
63+
3. Store only in `repo-private`:
64+
65+
- `APP_ID`
66+
- `APP_PRIVATE_KEY`
67+
- Drift detection secrets
68+
69+
## Drift Enforcement Flow (Private -> Public)
70+
71+
1. `repo-private` scheduled job runs drift detection.
72+
2. If no drift: exit cleanly.
73+
3. If drift exists:
74+
75+
- Mint installation token.
76+
- Target `repo-public`.
77+
- Create/update branch (for example `drift-sync/<topic>`).
78+
- Commit generated changes.
79+
- Open or update PR in `repo-public`.
80+
81+
## Sync-Back Flow (Public -> Private)
82+
83+
After PR merge in `repo-public`, run sync-back in the opposite direction:
84+
85+
- Push or automation-driven mirror from `repo-public` to `repo-private`.
86+
- Keep branch tips aligned to maintain eventual consistency.
87+
88+
## Loop and Safety Guards
89+
90+
- Add workflow/job concurrency on drift workflow to avoid competing PRs.
91+
- Ignore bot branches (for example `drift-sync/*`) where appropriate.
92+
- Ignore bot-authored commits/events where appropriate.
93+
- Scope triggers (`branches`, `paths`, event types) to reduce self-trigger loops.
94+
- Keep public CI limited to non-secret work.
95+
96+
## First Validation Pass
97+
98+
1. Push identical workflow/code branches to both repos.
99+
2. Verify drift workflow runs only in `repo-private` on schedule.
100+
3. Verify public-safe jobs run only in `repo-public`.
101+
4. Force drift and confirm PR opens/updates in `repo-public`.
102+
5. Merge PR in `repo-public` and confirm sync-back updates `repo-private`.
103+
6. Negative test: verify public workflows cannot access private-only secrets.

0 commit comments

Comments
 (0)