Skip to content

Support cross-org remote policy references - #1359

Merged
asvoboda merged 8 commits into
palantir:developfrom
clarkemn:worktree-cross-org-remote-policy
Oct 7, 2026
Merged

asvoboda merged 8 commits into
palantir:developfrom
clarkemn:worktree-cross-org-remote-policy

Conversation

@clarkemn

@clarkemn clarkemn commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Before this PR

A .policy.yml can reference a remote policy file via remote: org/repo, but this only works if the remote repo is in the same GitHub org as the requesting repo. The fetch reuses the requesting repo's own app installation client, which has no access outside its org, so a cross-org reference fails (typically a 404) even when policy-bot is installed on the target org too.

This blocks a common setup: one centrally managed policy repo referenced via remote: from many other orgs in the same GitHub Enterprise. (The vendored go-githubapp/appconfig package has a commented-out WithPrivateRemotes stub referencing #111 describing this exact gap.)

After this PR

A remote: reference can now point to a repository in a different GitHub org than the one defining it, as long as policy-bot is also installed on that org — resolved by looking up the target org's own app installation
(the same lookup CrossOrgMembershipContext already uses for cross-org team/org membership checks). Same-org remotes are unaffected: no installation lookup happens, the original client is reused exactly as before. Only 1 level of remote configuration is still supported, and a missing/misconfigured remote file still produces the same "invalid remote reference: file does not exist" error as before.

Possible downsides?

None expected for existing setups — same-org remote references and local policy files go through unchanged code paths. For a genuinely cross-org remote: reference, the resolution now depends on policy-bot's app being installed on the target org: if it isn't, the failure mode changes from a generic 404 to a clearer wrapped error ("policy-bot is not installed on organization ..."), which is a behavior change for anyone currently relying on that specific 404 message/error type, though none is known.

@palantirtech

Copy link
Copy Markdown
Member

Thanks for your interest in palantir/policy-bot, @clarkemn! Before we can accept your pull request, you need to sign our contributor license agreement - just visit https://cla.palantir.com/ and follow the instructions. Once you sign, I'll automatically update this pull request.

@changelog-app

changelog-app Bot commented Aug 25, 2026 •

Copy link
Copy Markdown

Generate changelog in changelog/@unreleased

Type (Select exactly one)

  • Feature (Adding new functionality)
  • Improvement (Improving existing functionality)
  • Fix (Fixing an issue with existing functionality)
  • Break (Creating a new major version by breaking public APIs)
  • Deprecation (Removing functionality in a non-breaking way)
  • Migration (Automatically moving data/functionality to a new system)

Description

Support cross-org remote policy references

Check the box to generate changelog(s)

  • Generate changelog entry

@clarkemn clarkemn changed the title Worktree cross org remote policy Support cross-org remote policy references Aug 25, 2026
@clarkemn
clarkemn marked this pull request as ready for review August 25, 2026 17:21
@asvoboda

Copy link
Copy Markdown
Member

Policy bot definitely works with cross org policies today, as we use this functionality extensively internally on GHES (currently 3.19.x).

Is policy-bot installed on both organizations, so it can read the policy?

@clarkemn

Copy link
Copy Markdown
Contributor Author

Hi @asvoboda

We are not on GHES (we are on Github.com) and have a single GitHub App registered at the enterprise level, installed separately on each organization (so it has its own installation per org, not one shared cross-org installation).

We hit an error when testing this cross-org access where a PR in one of our orgs referenced remote: <other-org>/policy-bot (a private repo), and got:

Error loading policy from <other-org>/policy-bot
invalid remote reference: file does not exist

The file does exist — the message is misleading. Tracing appconfig.Loader.loadRemoteConfig: it fetches the remote file using the requesting repo's own installation client, not a client for the org that owns the remote repo. Since <other-org>/policy-bot is private and our requesting org's installation was never granted access to it, GitHub returns a 404 (by design — it doesn't distinguish "doesn't exist" from "no access" for private repos), which the vendored loader maps directly to invalid remote reference: file does not exist.

So back to your questions - yes, policy-bot is installed on both organizations — but each installation only has access to its own org's repos. The existing code never looks up the target org's installation for a cross-org remote: reference, it just reuses whatever client the caller already has.

@bluekeyes

bluekeyes commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Thanks for clarifying. As you found (and as noted in #111), it's expected that Policy Bot cannot load remote policies from private (or internal) repositories right now.

To add this support, I think the correct fix is actually in https://github.com/palantir/go-githubapp, another library that we maintain. As noted in your PR body, something like the WithPrivateRemotes option is likely a better fit: it avoids duplicating config loading logic here and means anyone else using the library can also take advantage of this support.

At a high level, when this option is present, I think you want to modify the loadRemoteConfig method so that it attempts to use an alternate client when the owner in the remote reference differs from the owner passed to the LoadConfig call. Because both ClientCreator and InstallationsService have caching variants, we can probably omit caching from ConfigLoader (unless it's trivial to add) and recommend using the caching versions in the option function docs. If there's no installation (or constructing the client fails) make sure to log this and then fallback to the existing client to handle the public repository case.

Once we release the change as part of go-githubapp, we can update the version here and add the new option.

@clarkemn

Copy link
Copy Markdown
Contributor Author

@bluekeyes Thanks for taking a look! palantir/go-githubapp#618 is now open. If we're able to get that merged and released, I'll update this PR to take advantage of the new option

@bluekeyes

Copy link
Copy Markdown
Contributor

Version 0.47.2 of go-githubapp has this change, if you want to update this PR. Per the security note on the new option, I think we'll want to also add a server option (default disabled) to Policy Bot that controls whether it can load policies from private remotes or not.

Adds handler.CrossOrgConfigLoader which resolves remote: references to
repositories in different GitHub organizations by looking up the target
org's app installation, enabling policy-bot to fetch shared policies
across organizational boundaries.
Replace appconfig.NewLoader with handler.NewCrossOrgConfigLoader in NewServer,
passing cc, appClient via githubapp.NewInstallationsService, and shared
repository config options.
The remote-fetch loader inherited appconfig's default .github org-fallback
behavior, so a missing or misconfigured remote policy file would silently
resolve to the target org's .github default policy instead of producing
the documented "invalid remote reference: file does not exist" error, with
that content mislabeled as coming from the requested remote. Add
appconfig.WithOwnerDefault("", nil) to disable the fallback, and add a
regression test that drives the real production loader end-to-end.
@clarkemn
clarkemn force-pushed the worktree-cross-org-remote-policy branch from b7c597e to 8ec460a Compare September 2, 2026 19:12

@asvoboda asvoboda left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty reasonable. Sorry about the delay in reviewing. Do you mind pushing a new commit to fix the oauth problem and I can allow CI for your branch?

Comment thread go.mod Resolved
@changelog-app

changelog-app Bot commented Oct 6, 2026

Copy link
Copy Markdown

✅ Successfully generated changelog entry!

Need to regenerate?

Simply interact with the changelog bot comment again to regenerate these entries.


📋Changelog Preview

💡 Improvements

  • Support cross-org remote policy references (#1359)

@asvoboda asvoboda left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@asvoboda
asvoboda merged commit 8d370fb into palantir:develop Oct 7, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants