Skip to content

Commit 19c9c15

Browse files
wip v28
1 parent 44f154b commit 19c9c15

21 files changed

Lines changed: 307 additions & 19 deletions

File tree

BITCODE_V28_QA.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,12 @@ Automated verification after this implementation pass:
336336
- May 11 externality-readiness check validates the provided GitHub App identity without writing secrets to source: the private key parses, GitHub API returns App ID `244206`, app slug `engi-software-agents`, and the supplied client ID matches the app record. The app can list installations and create an installation token for at least one installation. Initial check found it was not installed on `engineeredsoftware/ENGI`.
337337
- May 12 externality-readiness recheck confirms the GitHub App is now installed on `engineeredsoftware/ENGI`: `GET /repos/engineeredsoftware/ENGI/installation` returns 200, installation token creation returns 201, `engineeredsoftware/ENGI` is readable, default branch is `main`, and `BITCODE_SPEC.txt` is readable through the app installation token. GitHub App externality is ready for V28 Terminal Give/Need QA against ENGI.
338338
- May 12 Supabase readiness resolves project reachability and key acceptance but remains blocked on database schema. The project URL is reachable, auth settings return 200 with the supplied publishable key, and the secret key is accepted by the Supabase API gateway. Core Bitcode tables including `user_profiles`, `user_connections`, `vcs_repositories`, `btd_asset_pack_ranges`, and `btd_mint_receipts` return `PGRST205` table-not-found responses, so migrations have not been applied to this testnet project yet. Source now accepts both the older `NEXT_PUBLIC_SUPABASE_ANON_KEY` / `SUPABASE_SERVICE_ROLE_KEY` names and the newer `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY` / `SUPABASE_SECRET_KEY` names so the provided testnet variables can be used directly after migration.
339+
- May 12 GitHub App setup/callback hardening: the active install link is now `https://github.com/apps/bitcode-github-app-auxillary` in Auxillaries and docs-facing surfaces. The retained public callback route `/github/callback` redirects to `/tps/github/callback`, and the retained setup route `/github/setup` redirects to `/tps/github/app-install`, preserving query fields. The callback handler collects GitHub App installation fields including `installation_id`, `setup_action`, `state`, `target_id`, and `target_type`; when a Supabase user session exists it exchanges the installation for an installation token and stores the GitHub connection as installation-scoped metadata without exposing tokens in client connection status. The GitHub App description copy for the registration form is: `Connect GitHub repositories to Bitcode so Terminal can measure Needs, synthesize BTD-backed AssetPacks, and return proof-bound delivery status.`
340+
- Recommended GitHub App URLs for production registration: homepage `https://bitcode.exchange`, callback URL `https://bitcode.exchange/github/callback`, setup URL `https://bitcode.exchange/github/setup`, public app link `https://github.com/apps/bitcode-github-app-auxillary`. For local callback QA, add a temporary allowed callback/setup pair for the active local port or use the deployed staging domain; GitHub App setup redirects do not inherit the browser's local origin automatically.
341+
- `pnpm -C uapi exec jest --runInBand tests/api/vcsRoutes.test.ts tests/api/vcsGithubCallbackRoute.test.ts tests/auxillariesConnectsPane.test.tsx tests/publicDocsPageContent.test.tsx`: 11 passed after GitHub App install-link and callback/setup handling.
342+
- `pnpm -C uapi exec jest --runInBand --testMatch '**/tests/userConnectionsGithubRoute.test.ts'`: 6 passed after GitHub connection-status token redaction.
343+
- `pnpm -C uapi exec tsc --noEmit --pretty false`: pass after GitHub App callback/setup and public install-link wiring.
344+
- `pnpm -C uapi run build`: pass after GitHub App callback/setup and public install-link wiring.
339345
- `pnpm -C uapi exec tsc --noEmit --pretty false`: pass after the formal protocol package split.
340346
- `pnpm -C uapi run test:e2e:commercial-mvp`: 50 passed after Conversations streaming, Conversations exit, and Terminal transaction-search stabilization.
341347
- `npm --prefix protocol-demonstration run test:integration`: 58 passed after standalone demonstration/package-boundary cleanup.
@@ -406,9 +412,11 @@ NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=<testnet Supabase publishable key> \
406412
SUPABASE_SECRET_KEY=<testnet Supabase secret key> \
407413
GITHUB_APP_CLIENT_ID=<GitHub App client ID> \
408414
GITHUB_APP_CLIENT_SECRET=<GitHub App client secret> \
415+
GITHUB_APP_REDIRECT_URI=http://127.0.0.1:3001/github/callback \
409416
GITHUB_APP_ID=<GitHub App ID> \
410417
GITHUB_PRIVATE_KEY="$(cat /Users/garrettmaring/Downloads/engi-software-agents.2026-05-11.private-key.pem)" \
411418
GITHUB_WEBHOOK_SECRET=<GitHub webhook secret> \
419+
NEXT_PUBLIC_GITHUB_APP_PUBLIC_URL=https://github.com/apps/bitcode-github-app-auxillary \
412420
NEXT_PUBLIC_MASTER_MOCK_MODE=false \
413421
NEXT_PUBLIC_ENABLE_MOCKS=false \
414422
NEXT_PUBLIC_MOCK_USER_AUXILLARIES=false \

packages/vcs/src/__tests__/vcs-config.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ describe('@bitcode/vcs configuration helpers', () => {
2020
delete process.env.GITHUB_CLIENT_ID;
2121
delete process.env.GITHUB_CLIENT_SECRET;
2222
delete process.env.GITHUB_REDIRECT_URI;
23+
delete process.env.GITHUB_APP_CLIENT_ID;
24+
delete process.env.GITHUB_APP_CLIENT_SECRET;
25+
delete process.env.GITHUB_APP_REDIRECT_URI;
2326
delete process.env.GITHUB_APP_ID;
2427
delete process.env.GITHUB_PRIVATE_KEY;
2528
delete process.env.GITHUB_WEBHOOK_SECRET;
@@ -34,6 +37,18 @@ describe('@bitcode/vcs configuration helpers', () => {
3437
expect((cfg as any).privateKey).toBe('private-key');
3538
});
3639

40+
it('prefers GitHub App OAuth client aliases when present', () => {
41+
process.env.GITHUB_APP_CLIENT_ID = 'app-client';
42+
process.env.GITHUB_APP_CLIENT_SECRET = 'app-secret';
43+
process.env.GITHUB_APP_REDIRECT_URI = 'https://app.test/github/callback';
44+
45+
const cfg = getVCSConfig('github');
46+
47+
expect(cfg.clientId).toBe('app-client');
48+
expect(cfg.clientSecret).toBe('app-secret');
49+
expect(cfg.redirectUri).toBe('https://app.test/github/callback');
50+
});
51+
3752
it('returns provider-specific OAuth scopes', () => {
3853
expect(getProviderScopes('github')).toContain('repo');
3954
expect(getProviderScopes('gitlab')).toContain('read_repository');

uapi/app/(root)/components/MarketingScreenshotSection.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import type { Screenshot } from './marketing-types';
3131
// Reuse the global neon underline + glow styles defined for Bitcode headers.
3232
import "@/styles/bitcode-header-shiny-text.css";
3333
import { motion, useInView } from "framer-motion";
34+
import { BITCODE_GITHUB_APP_PUBLIC_URL } from '@/lib/github-app-url';
3435

3536
// Persist a module-level flag so the animation only ever plays once per page
3637
// load, even if the component gets unmounted/remounted (e.g. via Next.js
@@ -795,7 +796,7 @@ const MarketingScreenshotSection: React.FC = () => {
795796
<a
796797
ref={linkRef}
797798
id="esi-link"
798-
href="https://github.com/marketplace/bitcode-github-app"
799+
href={BITCODE_GITHUB_APP_PUBLIC_URL}
799800
target="_blank"
800801
rel="noopener noreferrer"
801802
className="glowing-underline text-slate-100 hover:text-white transition-colors font-semibold"

uapi/app/api/auxillaries/connections/github/route.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ function resolveInstallationId(connectionData: Record<string, unknown> | null |
2727
return Number.isFinite(numeric) ? numeric : null;
2828
}
2929

30+
const sensitiveConnectionDataKeys = new Set([
31+
'access_token',
32+
'oauth_token',
33+
'refresh_token',
34+
'token',
35+
'client_secret',
36+
'private_key',
37+
]);
38+
39+
function sanitizeConnectionData(connectionData: Record<string, unknown>) {
40+
return Object.fromEntries(
41+
Object.entries(connectionData).filter(([key]) => !sensitiveConnectionDataKeys.has(key.toLowerCase())),
42+
);
43+
}
44+
3045
export async function GET(_request: Request) {
3146
const { supabase, user } = await requireUser();
3247
if (!user) {
@@ -49,7 +64,7 @@ export async function GET(_request: Request) {
4964
if (!installationId) {
5065
return NextResponse.json({
5166
success: true,
52-
connectionData,
67+
connectionData: sanitizeConnectionData(connectionData),
5368
repositories: [],
5469
organizations: [],
5570
});
@@ -69,7 +84,7 @@ export async function GET(_request: Request) {
6984

7085
return NextResponse.json({
7186
success: true,
72-
connectionData,
87+
connectionData: sanitizeConnectionData(connectionData),
7388
repositories,
7489
organizations,
7590
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { createRouteWrapper } from '@bitcode/middleware';
2+
3+
import { handleGitHubCallback } from '@/app/tps/github/_callback-handler';
4+
5+
import type { ProviderRouteContext } from '../../_shared';
6+
7+
export const runtime = 'nodejs';
8+
9+
export const GET = createRouteWrapper(async (request: Request, context: ProviderRouteContext) =>
10+
handleGitHubCallback(request, context),
11+
);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const runtime = 'nodejs';
2+
3+
export { GET } from '../callback/route';

uapi/app/docs/DocsArticlePage.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Link from 'next/link';
33

44
import TerminalWorkspaceCard from '@/app/terminal/TerminalWorkspaceCard';
55
import Footer from '@/components/base/bitcode/layout/footer';
6+
import { BITCODE_GITHUB_APP_PUBLIC_URL } from '@/lib/github-app-url';
67

78
import {
89
BITCODE_DOCS_CHAPTERS,
@@ -518,6 +519,16 @@ export default function DocsArticlePage({ page }: DocsArticlePageProps) {
518519
>
519520
Docs hub
520521
</Link>
522+
{page.slug === 'auxillaries' || page.slug === 'commercial-interfaces' ? (
523+
<a
524+
href={BITCODE_GITHUB_APP_PUBLIC_URL}
525+
target="_blank"
526+
rel="noopener noreferrer"
527+
className="inline-flex rounded-full border border-cyan-300/22 bg-cyan-400/10 px-4 py-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-cyan-50 transition hover:border-cyan-300/42 hover:bg-cyan-400/16"
528+
>
529+
Install GitHub App
530+
</a>
531+
) : null}
521532
</div>
522533
</section>
523534

uapi/app/github/callback/route.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const runtime = 'nodejs';
2+
3+
export function GET(request: Request) {
4+
const redirectUrl = new URL('/tps/github/callback', request.url);
5+
redirectUrl.search = new URL(request.url).search;
6+
return new Response(null, {
7+
status: 308,
8+
headers: {
9+
Location: redirectUrl.toString(),
10+
},
11+
});
12+
}

uapi/app/github/setup/route.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const runtime = 'nodejs';
2+
3+
export function GET(request: Request) {
4+
const redirectUrl = new URL('/tps/github/app-install', request.url);
5+
redirectUrl.search = new URL(request.url).search;
6+
return new Response(null, {
7+
status: 308,
8+
headers: {
9+
Location: redirectUrl.toString(),
10+
},
11+
});
12+
}

uapi/app/tps/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
Examples
99
- `/tps/supabase/callback` – Auth OTP/OAuth callback overlay
1010
- `/tps/wallet/connect` – Wallet connection or settlement overlay
11-
- `/tps/github/app-install` – GitHub App installation/verification overlay
11+
- `/tps/github/callback` – GitHub App user-authorization callback handler
12+
- `/tps/github/app-install` – GitHub App installation/setup handler
1213
- `/tps/twilio/sms/[runId]` – SMS run viewer
1314

1415
Transition policy
1516
- Retained callback pages (`/login/callback`, `/github/callback`, `/sms/view/[runId]`) permanently redirect (308) to the new `/tps/...` routes.
17+
- Retained GitHub setup pages (`/github/setup`) permanently redirect (308) to `/tps/github/app-install` and preserve `installation_id`, `setup_action`, `state`, `target_id`, and `target_type`.

0 commit comments

Comments
 (0)