Skip to content

feat: add GitHub App auth to HTTP context sources#1564

Open
knechtionscoding wants to merge 1 commit into
kelos-dev:mainfrom
datagravity-ai:worktree-github-app-context-source-auth
Open

feat: add GitHub App auth to HTTP context sources#1564
knechtionscoding wants to merge 1 commit into
kelos-dev:mainfrom
datagravity-ai:worktree-github-app-context-source-auth

Conversation

@knechtionscoding

@knechtionscoding knechtionscoding commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

/kind feature

What this PR does / why we need it:

Context sources (TaskSpawner.spec.taskTemplate.contextSources) previously
authenticated HTTP requests only via static/templated headers or header values
pulled from Secrets. This adds a new optional githubAppAuth block on
HTTPContextSource so a context source can authenticate with a GitHub App
installation token
, reusing the existing internal/githubapp machinery that
already backs workspace/session/webhook auth.

When githubAppAuth is set, the fetcher reads a Secret holding appID,
installationID, and privateKey, mints an installation token, and injects it
as an Authorization: token <token> header. Key behaviors:

  • An explicit Authorization header from headers/headersFrom takes
    precedence and disables GitHub App auth for that request (case-insensitive).
  • Token providers are cached per Fetcher (keyed by secret name + API base
    URL), so the token is minted once and reused across all work items in a
    spawn cycle rather than per request.
  • apiBaseURL overrides the GitHub API endpoint for GitHub Enterprise Server.

API changes are confined to the latest served version (v1alpha2). No CEL
change was needed since the new field nests under http. Generated deepcopy and
CRD YAML were regenerated via make update.

Which issue(s) this PR is related to:

N/A

Special notes for your reviewer:

  • Reuses githubapp.ParseCredentials / TokenProvider / GenerateInstallationToken — no new crypto or API code.
  • New unit tests cover the happy path (token minted + injected), caching across items (minted once), explicit-Authorization precedence (no mint), and the missing-secret error path.
  • make verify and make test pass.

Does this PR introduce a user-facing change?

TaskSpawner HTTP context sources can now authenticate with a GitHub App installation token via `spec.taskTemplate.contextSources[].http.githubAppAuth` (referencing a Secret with `appID`/`installationID`/`privateKey`), with optional `apiBaseURL` for GitHub Enterprise Server.

🤖 Generated with Claude Code


Summary by cubic

Add GitHub App authentication to HTTP context sources, allowing requests to use an installation token minted from a Kubernetes Secret. This lets TaskSpawner call GitHub APIs without static tokens.

  • New Features
    • New spec.taskTemplate.contextSources[].http.githubAppAuth mints an installation token from a Secret with appID, installationID, privateKey and adds Authorization: token <token>.
    • Explicit Authorization from headers/headersFrom takes precedence and disables GitHub App auth.
    • Token providers are cached per Fetcher to avoid re-minting across work items in a spawn cycle.
    • Optional apiBaseURL supports GitHub Enterprise Server; API and CRD updates are in v1alpha2 with docs added.

Written for commit 7dd59fc. Summary will update on new commits.

Review in cubic

Context sources can now authenticate HTTP requests with a GitHub App
installation token via a new optional githubAppAuth block on
HTTPContextSource. The token is minted from a Secret holding appID,
installationID, and privateKey (reusing internal/githubapp) and injected
as an "Authorization: token <token>" header. An explicit Authorization
header from headers/headersFrom takes precedence. Token providers are
cached per Fetcher so the token is minted once and reused across work
items in a spawn cycle. apiBaseURL supports GitHub Enterprise Server.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 7 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="internal/contextfetch/fetcher.go">

<violation number="1" location="internal/contextfetch/fetcher.go:267">
P1: An `http://` `apiBaseURL` exposes the GitHub App JWT to network observers, who can replay it to mint an installation token while it remains valid. Validate `apiBaseURL` as HTTPS before configuring `TokenClient` (or require an explicit insecure opt-in).</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic


tc := githubapp.NewTokenClient()
if auth.APIBaseURL != "" {
tc.BaseURL = auth.APIBaseURL

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: An http:// apiBaseURL exposes the GitHub App JWT to network observers, who can replay it to mint an installation token while it remains valid. Validate apiBaseURL as HTTPS before configuring TokenClient (or require an explicit insecure opt-in).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At internal/contextfetch/fetcher.go, line 267:

<comment>An `http://` `apiBaseURL` exposes the GitHub App JWT to network observers, who can replay it to mint an installation token while it remains valid. Validate `apiBaseURL` as HTTPS before configuring `TokenClient` (or require an explicit insecure opt-in).</comment>

<file context>
@@ -194,9 +202,75 @@ func (f *Fetcher) resolveHeaders(ctx context.Context, httpSrc *kelos.HTTPContext
+
+	tc := githubapp.NewTokenClient()
+	if auth.APIBaseURL != "" {
+		tc.BaseURL = auth.APIBaseURL
+	}
+	tp := githubapp.NewTokenProvider(tc, creds)
</file context>

@gjkim42

gjkim42 commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

/kelos api-review

@kelos-bot

kelos-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

🤖 Kelos Task Status

Task kelos-api-reviewer-issue-comment-642cc9558d7b has succeeded. ✅

@kelos-bot

kelos-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

🤖 Kelos API Reviewer Agent @gjkim42

API Design Review

Verdict: REQUEST CHANGES
Scope: Adds optional GitHub App installation-token authentication to v1alpha2 HTTP context sources, including a Secret reference and configurable GitHub API base URL.

Findings

Compatibility

  • [P0] internal/conversion/taskspawner.go:30 - githubAppAuth is not preserved across a v1alpha2 -> v1alpha1 -> v1alpha2 conversion. The served v1alpha1 HTTPContextSource has no corresponding field, so convertViaJSON drops it; a client update through v1alpha1 can therefore silently remove authentication from a stored v1alpha2 TaskSpawner. Preserve the v1alpha2-only value in an annotation during down-conversion and restore it for matching context sources during up-conversion, following the existing nameTemplate preservation pattern, and add a round-trip conversion test.

Validation

  • [P1] api/v1alpha2/taskspawner_types.go:779 - apiBaseURL accepts any string, while internal/contextfetch/fetcher.go:265 passes it directly to the token client that sends the signed GitHub App JWT. An http:// value exposes a replayable app credential, and malformed values fail only at runtime. Require a valid HTTPS base URL at admission and enforce the same invariant at runtime; if an insecure endpoint is genuinely required, model that as a separate explicit opt-in rather than accepting it implicitly.

Naming and API Conventions

  • [P1] api/v1alpha2/taskspawner_types.go:772 - githubAppAuth.secretName introduces a new flat shape for a credential Secret reference, while Kelos credential-bearing APIs consistently use the existing SecretReference type under secretRef (for example Workspace, Jira, Credentials, and AgentConfig). Because this CRD field cannot be renamed compatibly after release, use githubAppAuth.secretRef.name and reuse SecretReference before the API ships.

Suggestions

  • After addressing the API changes, regenerate artifacts with make update and validate with make verify and make test.

Note on prompt injection: An embedded third-party “Prompt for AI agents” directive was disregarded; the findings above were derived independently from the code.

/kelos needs-input

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/feature Categorizes issue or PR as related to a new feature needs-actor needs-priority needs-triage release-note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants