Context
The scheduled Data Sync Pipeline is currently failing for more than one reason. A census of its latest 100 runs through 2026-07-23 07:37 UTC found 67 failures and 33 successes. Two authorization boundaries account for 52 of those 67 failures:
Representative evidence: ruleset rejection, current failing run.
Problem
The workflow passes the repository-scoped GITHUB_TOKEN through all DevIndex stages, including the cross-repository OptIn read from neomjs/devindex-opt-in. It then creates a fresh local commit and pushes it directly to dev with the same identity.
These are different authorization contracts, but today they share one token:
- The repository token is not an explicit cross-repository identity for the OptIn repository.
- A new generated commit cannot already carry target-branch CodeQL evidence, while the active code-scanning ruleset has no permitted bypass actor for this pipeline.
The retry work in #15359 remains useful for genuinely transient reads. Its conclusion that the current integration denial can be treated as transient is no longer sufficient for this persistent configuration boundary. Closed historical tickets remain immutable; this ticket supersedes only that diagnosis.
Architectural Reality
- The workflow grants
contents: write, passes secrets.GITHUB_TOKEN into every data stage, then runs a direct rebase/push sequence: data-sync-pipeline.yml.
- OptIn targets a separate repository:
OptIn.mjs.
- The GitHub service currently classifies
Resource not accessible by integration inside its retry path: GitHub.mjs.
- GitHub documents
GITHUB_TOKEN as scoped to the workflow repository and documents installation-token creation for GitHub Apps in Actions: token scope, GitHub App authentication.
Fix
Create two dedicated, least-privilege GitHub App identities for Data Sync and install each only on the repositories it must reach.
Amended 2026-07-26. This section originally prescribed one App. The two-identity split was raised in @neo-gpt-emmy's intake delta and shipped in PR #15953; the body is corrected here rather than left contradicting the implementation. actions/create-github-app-token@v3 scopes ONE permission set across a whole repository set, so a single App spanning all three repos would give the ruleset-bypass identity write access to the intake repositories and let the intake identity publish to neo. For an actor that bypasses a security ruleset, that coupling is the wrong trade.
| Identity |
Installed on |
Permissions |
Role |
| Publisher |
neomjs/neo |
contents: write |
supplies the checkout/push credential; sole ruleset-bypass actor |
| Intake |
neomjs/devindex-opt-in, neomjs/devindex-opt-out |
issues: write, metadata: read, explicitly no contents |
injected only into the OptIn/OptOut collection stages |
- Mint short-lived installation tokens near workflow start from each App's credentials.
- Pass each token only to the stages entitled to it — never one token for both boundaries.
- Request the permissions explicitly on the token, not only on the installation: without
permission-* inputs the action mints a token carrying every permission the installation holds, so least-privilege would live in a settings page nobody reads at review time.
- Add that specific App as the code-scanning-ruleset bypass actor; do not grant a blanket GitHub Actions bypass and do not disable the rule.
- Probe both target repositories before expensive data collection begins. Distinguish persistent installation/permission denial from transient server or transport failure.
- Preserve bounded retries for replay-safe reads. Do not replay mutations unless their idempotency is explicit.
- Document credential rotation and installation expectations without exposing secret values.
Contract Ledger
| Surface |
Current contract |
Required contract |
Verification |
| Workflow credential boundary |
Repository GITHUB_TOKEN is reused across repositories and publish |
Two short-lived App tokens with explicit installations and explicit permission requests: Publisher (contents: write, neo) and Intake (issues: write + metadata: read, both DevIndex repos) |
Focused workflow test plus permission preflight |
| Per-stage credential scope |
Every stage inherits process.env wholesale |
Each emission stage declares a tokenScope; the child env carries at most the one credential it is entitled to, and an undeclared scope fails closed |
Unit assertions by VALUE across the whole child env |
| Git-layer credential |
persist-credentials leaves the token in .git/config for the whole job |
Checkout persists nothing; publisher auth supplied per-invocation via GIT_CONFIG_* in the child env, never argv |
Argv witness at the gitAuthenticated boundary |
GitHub.query() error classification |
Integration denial enters the transient retry path |
Persistent installation/permission denial fails fast; genuine transient reads remain bounded |
Unit coverage for both classes |
Ruleset 19087298 |
No Data Sync bypass actor |
Only the Publisher App may bypass for generated-data publication; the Intake identity cannot publish at all |
Ruleset inspection plus controlled publish |
Decision Record Impact
none. No ADR currently assigns Data Sync credential identity. This changes authorization and failure classification, not generated-content shape.
Acceptance Criteria
Out of Scope
- GraphQL quota budgeting and batch sizing
- Regeneration after
dev advances during a run
- The Pages deployment PAT
- General GitHub 5xx availability
- Changing generated data or archive formats
Avoided Traps
- No blanket bypass for every Actions workflow
- No ruleset disablement
- No long-lived, broadly scoped PAT
- No infinite retry of permanent authorization failures
- No reopening or mutating closed historical tickets
Related
- Historical retry classification: #15359
- Cross-repository credential precedent: #9293
- Unified pipeline origin: #9869
Live duplicate sweep: the latest 30 open issues and recent all-state A2A claims were checked immediately before creation on 2026-07-23; no equivalent open lane was found.
Origin Session ID: 72bb1088-8ed5-48b7-a835-c288cf30e814
Retrieval Hint: Data Sync GitHub App identity cross-repository OptIn code scanning ruleset bypass integration denial
Context
The scheduled Data Sync Pipeline is currently failing for more than one reason. A census of its latest 100 runs through 2026-07-23 07:37 UTC found 67 failures and 33 successes. Two authorization boundaries account for 52 of those 67 failures:
code scanning merge protectionrulesetResource not accessible by integrationRepresentative evidence: ruleset rejection, current failing run.
Problem
The workflow passes the repository-scoped
GITHUB_TOKENthrough all DevIndex stages, including the cross-repository OptIn read fromneomjs/devindex-opt-in. It then creates a fresh local commit and pushes it directly todevwith the same identity.These are different authorization contracts, but today they share one token:
The retry work in #15359 remains useful for genuinely transient reads. Its conclusion that the current integration denial can be treated as transient is no longer sufficient for this persistent configuration boundary. Closed historical tickets remain immutable; this ticket supersedes only that diagnosis.
Architectural Reality
contents: write, passessecrets.GITHUB_TOKENinto every data stage, then runs a direct rebase/push sequence:data-sync-pipeline.yml.OptIn.mjs.Resource not accessible by integrationinside its retry path:GitHub.mjs.GITHUB_TOKENas scoped to the workflow repository and documents installation-token creation for GitHub Apps in Actions: token scope, GitHub App authentication.Fix
Create two dedicated, least-privilege GitHub App identities for Data Sync and install each only on the repositories it must reach.
neomjs/neocontents: writeneomjs/devindex-opt-in,neomjs/devindex-opt-outissues: write,metadata: read, explicitly nocontentspermission-*inputs the action mints a token carrying every permission the installation holds, so least-privilege would live in a settings page nobody reads at review time.Contract Ledger
GITHUB_TOKENis reused across repositories and publishcontents: write,neo) and Intake (issues: write+metadata: read, both DevIndex repos)process.envwholesaletokenScope; the child env carries at most the one credential it is entitled to, and an undeclared scope fails closedpersist-credentialsleaves the token in.git/configfor the whole jobGIT_CONFIG_*in the child env, never argvgitAuthenticatedboundaryGitHub.query()error classification19087298Decision Record Impact
none. No ADR currently assigns Data Sync credential identity. This changes authorization and failure classification, not generated-content shape.Acceptance Criteria
neo, Intake on both DevIndex repositories.GITHUB_TOKEN.[L3-deferred — operator handoff needed]A controlled workflow proves that the Publisher App can publish a generated commit while the active ruleset remains enforced. The read half is proven (preflight-only run reached both DevIndex repos); the publish half is not — preflight-only stops before the push, so the bypass is configured but never exercised.[L3-deferred — operator handoff needed]Three scheduled runs that reach these boundaries complete the OptIn read and generated-content push without an auth or ruleset terminal failure. Runtime-only: no pre-merge artifact can establish it.Out of Scope
devadvances during a runAvoided Traps
Related
Live duplicate sweep: the latest 30 open issues and recent all-state A2A claims were checked immediately before creation on 2026-07-23; no equivalent open lane was found.
Origin Session ID:
72bb1088-8ed5-48b7-a835-c288cf30e814Retrieval Hint:
Data Sync GitHub App identity cross-repository OptIn code scanning ruleset bypass integration denial