Skip to content

feat(api): add /private/config/builder endpoint#2051

Merged
riderx merged 8 commits into
mainfrom
feat/google-oauth-config-endpoint
May 6, 2026
Merged

feat(api): add /private/config/builder endpoint#2051
riderx merged 8 commits into
mainfrom
feat/google-oauth-config-endpoint

Conversation

@WcaleNieWolny
Copy link
Copy Markdown
Contributor

@WcaleNieWolny WcaleNieWolny commented May 6, 2026

Summary

  • Adds GET /private/config/builder, an unauthenticated CORS-enabled endpoint that serves build-onboarding configuration to the Capgo CLI's build init flow.
  • The first (and only, for now) payload it carries is the Google "Desktop app" OAuth client config used by the Android onboarding step: clientId, clientSecret, scopes. The route name is intentionally generic (/config/builder) so future build-related config can ride along without another rename.
  • Returns { enabled: true, clientId, clientSecret, scopes } when GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET worker env vars are both set, and { enabled: false } otherwise — so self-hosted/on-prem deployments can leave the feature off without an error path.
  • Scopes default to https://www.googleapis.com/auth/androidpublisher and can be overridden via the optional GOOGLE_OAUTH_SCOPES env var (comma-separated, whitespace-trimmed, falls back to default if all entries are empty).
  • Mirrors the structure and unauthenticated CORS-enabled posture of the existing /private/config endpoint.

Implementation

  • New file supabase/functions/_backend/private/config_builder.ts (~30 lines, Hono app with a single GET handler).
  • Wired into both deployment targets so local dev / Supabase-only / on-prem environments serve it identically to Cloudflare:
    • cloudflare_workers/api/index.tsappPrivate.route('/config/builder', ...)
    • supabase/functions/private/index.tsappGlobal.route('/config/builder', ...)
  • Unit tests in tests/config-builder.unit.test.ts (8 tests) cover: enabled happy path, disabled branches (neither / only-id / only-secret / whitespace-only), and scope parsing (single / multi-with-whitespace / all-empty fallback to default).

Out of Scope

  • CLI consumer changes — separate PR in the CLI/ submodule will read this endpoint and drive the OAuth flow.
  • Multi-provider OAuth abstraction — Google-only for now (YAGNI). If non-Google build credentials need to ship later, they can be added as additional fields on the same response or as new sibling routes under /private/config/.
  • No wrangler.jsonc changes — secrets are configured via wrangler secret put GOOGLE_OAUTH_CLIENT_ID and wrangler secret put GOOGLE_OAUTH_CLIENT_SECRET.

Test plan

  • Reviewer runs bunx vitest run tests/config-builder.unit.test.ts and sees 8 passing tests.
  • Reviewer runs bunx eslint supabase/functions/_backend/private/config_builder.ts cloudflare_workers/api/index.ts supabase/functions/private/index.ts tests/config-builder.unit.test.ts and sees no errors.
  • After merge: deploy worker, verify curl https://api.capgo.app/private/config/builder returns { "enabled": false } until secrets are set, then { "enabled": true, ... } after wrangler secret put GOOGLE_OAUTH_CLIENT_ID and wrangler secret put GOOGLE_OAUTH_CLIENT_SECRET.
  • Same verification against the Supabase private function (supabase functions serve private locally) returns the same shape.

Notes

  • arktype test-suite failures observed running the full unit-test suite are pre-existing on origin/main (verified) and unrelated to this PR.

Summary by CodeRabbit

  • New Features

    • New private API endpoint at /config/builder that retrieves OAuth authentication configuration by reading client credentials and scopes from environment variables, returning configuration status and details when properly configured
  • Tests

    • Comprehensive unit test suite added for the configuration endpoint, covering credential validation with whitespace handling, missing credentials scenarios, and various scope configurations

Serves Google "Desktop app" OAuth client config (clientId, clientSecret,
scopes) to the Capgo CLI's Android `build init` onboarding flow. Returns
{ enabled: false } when GOOGLE_OAUTH_CLIENT_ID or
GOOGLE_OAUTH_CLIENT_SECRET worker env vars are missing/empty so
self-hosted and on-prem deployments can leave the feature off without
an error path. Scopes default to androidpublisher and are tunable via
GOOGLE_OAUTH_SCOPES (comma-separated).

Mirrors the structure and unauthenticated CORS-enabled posture of the
existing /private/config endpoint.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

This PR introduces a new Config Builder endpoint that reads Google OAuth credentials from environment variables and returns the configuration via a private API route. The implementation is added to Supabase backend functions and wired into both Supabase and Cloudflare Workers private API routes, along with comprehensive unit tests.

Changes

Config Builder Endpoint

Layer / File(s) Summary
Core Implementation
supabase/functions/_backend/private/config_builder.ts
New Hono app with CORS middleware, a parseScopes helper function, and a GET endpoint that reads GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OAUTH_CLIENT_SECRET, and GOOGLE_OAUTH_SCOPES from environment, returning { enabled: true, clientId, clientSecret, scopes } or { enabled: false } if credentials are missing.
Route Wiring
supabase/functions/private/index.ts, cloudflare_workers/api/index.ts
Config Builder app is imported and exposed at /config/builder route in both private API entry points.
Tests / Validation
tests/config-builder.unit.test.ts
Comprehensive test suite covering missing/whitespace client credentials, single and comma-separated scopes with whitespace handling, and default scope fallback behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

A rabbit hops with glee, the builder's here!
OAuth secrets dance, both far and near.
Scopes parsed with care, environments read,
Routes all wired where credentials are fed.
Tests keep it honest, no bugs left to fear! 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(api): add /private/config/builder endpoint' accurately summarizes the main change: adding a new API endpoint for serving builder configuration.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering summary, implementation details, out-of-scope items, and a detailed test plan that matches the template's requirements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/google-oauth-config-endpoint

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 6, 2026

Merging this PR will not alter performance

✅ 28 untouched benchmarks


Comparing feat/google-oauth-config-endpoint (8a6cfbf) with main (879e0a1)

Open in CodSpeed

@chatgpt-codex-connector
Copy link
Copy Markdown

💡 Codex Review

appPrivate.route('/config/google_oauth', configGoogleOauth)

P1 Badge Register endpoint in Supabase private router too

This change wires /private/config/google_oauth only in the Cloudflare API router, but the Supabase private function entrypoint (supabase/functions/private/index.ts) was not updated with the same route. In environments that run the Supabase private function directly (local dev or Supabase-only/self-hosted deployments), the new endpoint will return 404, so the CLI onboarding flow cannot fetch Google OAuth config there even when env vars are set.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
supabase/functions/_backend/private/config_google_oauth.ts (1)

15-17: 💤 Low value

Consider using createHono() for consistency with other endpoints.

Other private endpoints use createHono() from utils/hono.ts which adds standard middleware for logging and error handling. Direct Hono instantiation may bypass these.

♻️ Suggested change
-import { Hono } from 'hono/tiny'
-import { useCors } from '../utils/hono.ts'
+import { createHono, useCors } from '../utils/hono.ts'
 import { getEnv } from '../utils/utils.ts'
+import { version } from '../utils/version.ts'
 
 const DEFAULT_SCOPES = ['https://www.googleapis.com/auth/androidpublisher']
 
 // ... parseScopes unchanged ...
 
-export const app = new Hono<MiddlewareKeyVariables>()
+export const app = createHono('config_google_oauth', version)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/private/config_google_oauth.ts` around lines 15 -
17, The code instantiates Hono directly with "new
Hono<MiddlewareKeyVariables>()" which bypasses the project's standard
middleware; replace that direct instantiation with a call to createHono() from
utils/hono.ts (so the exported "app" uses createHono() instead of new Hono) and
then re-apply the existing middleware (e.g., ensure useCors is still mounted via
app.use('/' , useCors)); keep the exported symbol name "app" and ensure
MiddlewareKeyVariables typing is preserved when adapting to createHono.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@supabase/functions/_backend/private/config_google_oauth.ts`:
- Around line 15-17: The code instantiates Hono directly with "new
Hono<MiddlewareKeyVariables>()" which bypasses the project's standard
middleware; replace that direct instantiation with a call to createHono() from
utils/hono.ts (so the exported "app" uses createHono() instead of new Hono) and
then re-apply the existing middleware (e.g., ensure useCors is still mounted via
app.use('/' , useCors)); keep the exported symbol name "app" and ensure
MiddlewareKeyVariables typing is preserved when adapting to createHono.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e1e4d874-cdde-4fac-bd4a-6540a2f8d6bb

📥 Commits

Reviewing files that changed from the base of the PR and between c0f5ca5 and 467a711.

📒 Files selected for processing (3)
  • cloudflare_workers/api/index.ts
  • supabase/functions/_backend/private/config_google_oauth.ts
  • tests/config-google-oauth.unit.test.ts

…vate function

The endpoint was only wired into the Cloudflare API router, so local dev
and Supabase-only/self-hosted deployments would 404 on it even with env
vars set. Adding the same import and route registration to
supabase/functions/private/index.ts gives both deployment targets the
same surface, mirroring how the existing /private/config is wired in
both files.
…/builder

Generalizes the route name so it can serve other build-onboarding
config in the future without another rename. The response shape and
GOOGLE_OAUTH_* env var names stay as-is — the values it serves today
are still Google "Desktop app" OAuth credentials for the CLI's
`build init` Android flow. File and import variable renamed in
lockstep:
  config_google_oauth.ts -> config_builder.ts
  configGoogleOauth      -> configBuilder

Both router entry points updated:
  - cloudflare_workers/api/index.ts
  - supabase/functions/private/index.ts
@WcaleNieWolny WcaleNieWolny changed the title feat(api): add /private/config/google_oauth endpoint feat(api): add /private/config/builder endpoint May 6, 2026
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 6, 2026

@riderx riderx merged commit dd0f30e into main May 6, 2026
38 checks passed
@riderx riderx deleted the feat/google-oauth-config-endpoint branch May 6, 2026 18:01
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.

2 participants