Key Broker
Separating the App private key from native review containers, without overstating the broker's authorization controls.
This page describes the broker in the deployed-engine lineage, son-of-anton-review on feat/cloudflare-native. It is not an endpoint in the unmerged feat/greptile-operator-parity operator API.
The native configuration keeps GITHUB_APP_PRIVATE_KEY in a separate Worker. The review container receives scoped installation tokens instead of the App private key. This removes the key from the container environment; it does not make a compromised container incapable of requesting broader tokens.
Deployment boundary
cloudflare-native/wrangler.key-broker.jsonc selects src/key-broker.js, sets workers_dev: false, and defines no public route. Its default fetch handler returns 404. The main Worker binds service son-of-anton-key-broker, entrypoint KeyBroker, as KEY_BROKER.
The broker reads GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY from its own environment. The main container environment allowlist does not forward the private key. Keep that separation when provisioning; it is a property of this configuration, not a claim about every self-host deployment.
Sources: engine cloudflare-native/wrangler.key-broker.jsonc:5-26; cloudflare-native/wrangler.jsonc:102-105; cloudflare-native/src/key-broker.js:13-33; cloudflare-native/src/container-env.js:15-85.
RPC contract
The service method is mintToken({ installationId, repositories, permissions }). Its successful result contains token and scope.
| Input | Actual broker behavior |
|---|---|
installationId | Required to be non-null by shapeTokenRequest |
permissions omitted or null | Defaults to contents: read, pull_requests: write, checks: write, metadata: read |
permissions supplied | Passed through, not checked against a purpose allowlist |
Nonempty repositories array | Passed through to scope the GitHub token request |
Empty or omitted repositories | Omitted from the GitHub request, so the broker does not enforce repository restriction |
GitHub remains responsible for accepting or refusing the requested installation, repositories and permissions. The broker does not implement the design document's publish, clone, reconcile, or audit purpose authorization, nor an explicit denial of contents:write or administration.
Source: engine cloudflare-native/src/key-broker-core.js:15-55.
Container transport and normal callers
The container sends POST http://broker.internal/mint. Outbound interception invokes handleBrokerRequest, which forwards the caller's installation, repositories and permissions directly to KEY_BROKER.mintToken. This handler does not bind the requested scope to the active review lease.
The normal container client is stricter than the broker:
mintPublishTokenrequires a broker, installation ID, repository scope and nonempty returned token.- Clone setup requests
contents:readandmetadata:readfor the target repository, including in shadow publish mode. - Check publication requests
checks:write; review/comment publication requestspull_requests:write, scoped to the repository. - The broker-backed GitHub client mints for each request. Reads use up to three fetch attempts; writes use one attempt because a lost response is ambiguous.
These are caller conventions, not a security boundary against a caller that bypasses the helper. A compromised container with outbound broker access is not limited to the read token already present in its environment. The model-provider key is also present in the orchestration container.
Sources: engine cloudflare-native/src/state-transport.js:583-599; cloudflare-native/src/broker-github-client.js:26-99; cloudflare-native/container/entrypoint.mjs:97-123; src/github-publisher.js:13-78; cloudflare-native/src/container-env.js:49-69.
Lifetime, caching and revocation
The broker does not set a custom token expiry. GitHubAppClient uses the expiry returned by GitHub. Its instance cache reuses a scope-matched token until 60 seconds before expiry.
However, each broker RPC constructs a new GitHubAppClient. The cache therefore does not persist across broker RPC calls. Do not use the client's cache implementation as evidence of broker-wide reuse.
Neither key-broker.js nor the internal broker HTTP handler exposes a revoke operation. There is no automatic post-use revocation in this path. Clearing the clone credential environment in the container's finally block restores local environment state; it does not invalidate the GitHub token.
Sources: engine cloudflare-native/src/key-broker-core.js:41-55; src/github-app.js:75-111; cloudflare-native/src/key-broker.js:13-33; cloudflare-native/src/state-transport.js:583-599; cloudflare-native/container/entrypoint.mjs:178-183.
Node self-host differs
server.mjs and worker.mjs can load GITHUB_APP_PRIVATE_KEY or read GITHUB_APP_PRIVATE_KEY_PATH, then construct GitHubAppClient in-process. The native broker isolation does not apply to those branches of the Node runtime.
GILF_BROKER_URL, GILF_BROKER_TOKEN and GILF_BROKER_ALLOW_LOCAL_KEY are design-only names, not configuration read by these entrypoints or the audited engine/broker modules. Do not set them expecting a broker cutover. The earlier unverified claims about these flags, purpose enforcement and revocation are replaced here with their implemented status.
Sources: engine server.mjs:52-59; worker.mjs:35-40; cloudflare-native/src/key-broker-core.js:26-55. A source search of engine src/, native src/, server.mjs and worker.mjs found no reads of those three variables or /token/revoke.
See Security model and Publish modes. Token isolation is one control, not a certification or a complete hostile-code containment guarantee.