@opengeni/github 0.7.16 → 0.7.17-canary.36239117573001
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +15 -2
package/dist/index.d.ts
CHANGED
|
@@ -104,6 +104,14 @@ export declare function githubOAuthAuthorizeUrl(input: {
|
|
|
104
104
|
}): string;
|
|
105
105
|
export declare function createSignedState(secret: string, payloadOrNow?: Record<string, unknown> | number, nowArg?: number): string;
|
|
106
106
|
export declare function readSignedState(state: string, secret: string, now?: number): GitHubSignedStatePayload | null;
|
|
107
|
+
/**
|
|
108
|
+
* Verifies a signed state's signature and shape without its age limit.
|
|
109
|
+
*
|
|
110
|
+
* Only for explaining a failed callback (for example "this link expired" and
|
|
111
|
+
* which workspace page to return to). An aged payload is never authority: every
|
|
112
|
+
* authorizing read uses {@link readSignedState} or its own stricter lifetime.
|
|
113
|
+
*/
|
|
114
|
+
export declare function inspectSignedState(state: string, secret: string): GitHubSignedStatePayload | null;
|
|
107
115
|
export declare function verifySignedState(state: string, secret: string, now?: number): boolean;
|
|
108
116
|
export declare function envLinesFromGitHubManifestConversion(payload: Record<string, unknown>): string[];
|
|
109
117
|
export declare function convertGitHubAppManifest(code: string): Promise<Record<string, unknown>>;
|
package/dist/index.js
CHANGED
|
@@ -282,6 +282,12 @@ function createSignedState(secret, payloadOrNow = {}, nowArg = Math.floor(Date.n
|
|
|
282
282
|
return `${encoded}.${signStatePayload(encoded, secret)}`;
|
|
283
283
|
}
|
|
284
284
|
function readSignedState(state, secret, now = Math.floor(Date.now() / 1e3)) {
|
|
285
|
+
const payload = inspectSignedState(state, secret);
|
|
286
|
+
if (!payload) return null;
|
|
287
|
+
const age = now - payload.iat;
|
|
288
|
+
return age >= 0 && age <= stateMaxAgeSeconds ? payload : null;
|
|
289
|
+
}
|
|
290
|
+
function inspectSignedState(state, secret) {
|
|
285
291
|
const [encoded, signature] = state.split(".", 2);
|
|
286
292
|
if (!encoded || !signature) {
|
|
287
293
|
return null;
|
|
@@ -299,8 +305,7 @@ function readSignedState(state, secret, now = Math.floor(Date.now() / 1e3)) {
|
|
|
299
305
|
if (!payload || typeof payload !== "object" || typeof payload.iat !== "number" || typeof payload.nonce !== "string") {
|
|
300
306
|
return null;
|
|
301
307
|
}
|
|
302
|
-
|
|
303
|
-
return age >= 0 && age <= stateMaxAgeSeconds ? payload : null;
|
|
308
|
+
return payload;
|
|
304
309
|
}
|
|
305
310
|
function verifySignedState(state, secret, now = Math.floor(Date.now() / 1e3)) {
|
|
306
311
|
return readSignedState(state, secret, now) !== null;
|
|
@@ -1199,6 +1204,7 @@ export {
|
|
|
1199
1204
|
githubPublicRepositoryVerificationTimeoutMs,
|
|
1200
1205
|
githubRepositoryBranchesTimeoutMs,
|
|
1201
1206
|
githubRepositoryLookupTimeoutMs,
|
|
1207
|
+
inspectSignedState,
|
|
1202
1208
|
listGitHubAppInstallationSummaries,
|
|
1203
1209
|
listGitHubAppRepositories,
|
|
1204
1210
|
listGitHubAppRepositoriesWithSigningSettings,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Settings } from \"@opengeni/config\";\nimport type {\n GitHubAppRepositoryBranchPage,\n GitHubInstallationBindingCandidate,\n GitHubInstallationBindingProof,\n GitHubRepository,\n GitHubRepositoryPermissions,\n GitHubUserInstallationAccess,\n GitHubUserRepositoryAccess,\n} from \"@opengeni/contracts\";\nimport type { VerifyPublicGitHubRepositoryRefResponse } from \"@opengeni/contracts/github-repository-contracts\";\nimport {\n parseCanonicalGitHubRepositoryUrl,\n type CanonicalGitHubRepository,\n} from \"@opengeni/contracts/github-repository\";\nimport { readResponseTextBounded } from \"@opengeni/network\";\nimport {\n createCipheriv,\n createDecipheriv,\n createHash,\n createHmac,\n createPrivateKey,\n randomBytes,\n timingSafeEqual,\n} from \"node:crypto\";\nimport { SignJWT, importPKCS8 } from \"jose\";\n\nconst githubApiBase = \"https://api.github.com\";\nconst githubApiVersion = \"2022-11-28\";\nconst githubTokenMintTimeoutMs = 60_000;\n/** Bound for the server-side repository-id lookup at turn start (mint + read). */\nexport const githubRepositoryLookupTimeoutMs = 10_000;\nexport const githubRepositoryBranchesTimeoutMs = 10_000;\nconst githubRepositoryBranchesResponseMaxBytes = 256 * 1024;\nexport const githubPublicRepositoryVerificationTimeoutMs = 10_000;\nconst githubPublicRepositoryVerificationResponseMaxBytes = 128 * 1024;\nconst githubInstallationTokenResponseMaxBytes = 64 * 1024;\nconst githubErrorResponseMaxBytes = 64 * 1024;\nconst githubErrorMessageMaxLength = 1024;\nexport const stateMaxAgeSeconds = 60 * 60;\nconst pkcs8PrivateKeyHeader = `-----BEGIN ${\"PRIVATE KEY\"}-----`;\nconst rsaPrivateKeyHeader = `-----BEGIN ${\"RSA PRIVATE KEY\"}-----`;\n\nconst PERSONAL_GITHUB_GIT_BROKER_TOKEN_PREFIX = \"oggh1\";\nconst PERSONAL_GITHUB_GIT_BROKER_KEY_CONTEXT = \"opengeni:personal-github:git-broker:v1\";\nexport const PERSONAL_GITHUB_GIT_BROKER_TOKEN_TTL_SECONDS = 5 * 60;\n\nexport type PersonalGitHubGitBrokerRepositoryClaim = {\n repositoryId: string;\n fullName: string;\n canonicalUrl: string;\n ref: string;\n access: \"read\" | \"write\";\n selectionGeneration: number;\n routeId: string;\n};\n\nexport type PersonalGitHubGitBrokerClaims = {\n version: 1;\n accountId: string;\n workspaceId: string;\n sessionId: string;\n rootSessionId: string;\n turnId: string;\n attemptId: string;\n executionGeneration: number;\n originWorkspaceId: string;\n connectionId: string;\n connectionAuthorityGeneration: number;\n ownerSubjectId: string;\n credentialBindingId: string;\n selectionGeneration: number;\n nonce: string;\n issuedAt: number;\n expiresAt: number;\n};\n\nexport function personalGitHubGitBrokerRouteId(\n secret: string,\n input: Omit<PersonalGitHubGitBrokerClaims, \"nonce\" | \"issuedAt\" | \"expiresAt\"> & {\n repository: Omit<PersonalGitHubGitBrokerRepositoryClaim, \"routeId\">;\n },\n): string {\n const hmac = createHmac(\"sha256\", personalGitHubGitBrokerKey(secret));\n for (const value of [\n String(input.version),\n input.accountId,\n input.workspaceId,\n input.sessionId,\n input.rootSessionId,\n input.turnId,\n input.attemptId,\n String(input.executionGeneration),\n input.originWorkspaceId,\n input.connectionId,\n String(input.connectionAuthorityGeneration),\n input.ownerSubjectId,\n input.credentialBindingId,\n String(input.selectionGeneration),\n input.repository.repositoryId,\n input.repository.fullName,\n input.repository.canonicalUrl,\n input.repository.ref,\n input.repository.access,\n String(input.repository.selectionGeneration),\n ]) {\n const bytes = Buffer.from(value, \"utf8\");\n hmac.update(Buffer.from(String(bytes.byteLength), \"ascii\"));\n hmac.update(\":\");\n hmac.update(bytes);\n hmac.update(\";\");\n }\n return hmac.digest(\"base64url\");\n}\n\n/**\n * Seal exact Git broker authority into a confidential, authenticated bearer.\n * The payload is encrypted rather than merely signed so tenant, session,\n * connection, and repository identities are not readable from the sandbox's\n * short-lived token file.\n */\nexport function sealPersonalGitHubGitBrokerClaims(\n secret: string,\n claims: PersonalGitHubGitBrokerClaims,\n): string {\n assertPersonalGitHubGitBrokerClaims(claims);\n const iv = randomBytes(12);\n const cipher = createCipheriv(\"aes-256-gcm\", personalGitHubGitBrokerKey(secret), iv);\n cipher.setAAD(Buffer.from(PERSONAL_GITHUB_GIT_BROKER_TOKEN_PREFIX, \"ascii\"));\n const ciphertext = Buffer.concat([cipher.update(JSON.stringify(claims), \"utf8\"), cipher.final()]);\n return [\n PERSONAL_GITHUB_GIT_BROKER_TOKEN_PREFIX,\n iv.toString(\"base64url\"),\n ciphertext.toString(\"base64url\"),\n cipher.getAuthTag().toString(\"base64url\"),\n ].join(\".\");\n}\n\nexport function openPersonalGitHubGitBrokerClaims(\n secret: string,\n token: string,\n nowSeconds = Math.floor(Date.now() / 1_000),\n): PersonalGitHubGitBrokerClaims | null {\n const [prefix, encodedIv, encodedCiphertext, encodedTag, extra] = token.split(\".\");\n if (\n prefix !== PERSONAL_GITHUB_GIT_BROKER_TOKEN_PREFIX ||\n !encodedIv ||\n !encodedCiphertext ||\n !encodedTag ||\n extra !== undefined\n ) {\n return null;\n }\n try {\n const iv = Buffer.from(encodedIv, \"base64url\");\n const ciphertext = Buffer.from(encodedCiphertext, \"base64url\");\n const tag = Buffer.from(encodedTag, \"base64url\");\n if (iv.byteLength !== 12 || tag.byteLength !== 16 || ciphertext.byteLength > 4_096) {\n return null;\n }\n const decipher = createDecipheriv(\"aes-256-gcm\", personalGitHubGitBrokerKey(secret), iv);\n decipher.setAAD(Buffer.from(PERSONAL_GITHUB_GIT_BROKER_TOKEN_PREFIX, \"ascii\"));\n decipher.setAuthTag(tag);\n const payload = JSON.parse(\n Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString(\"utf8\"),\n ) as unknown;\n assertPersonalGitHubGitBrokerClaims(payload);\n if (payload.issuedAt > nowSeconds + 60 || nowSeconds >= payload.expiresAt) return null;\n if (payload.expiresAt - payload.issuedAt > PERSONAL_GITHUB_GIT_BROKER_TOKEN_TTL_SECONDS) {\n return null;\n }\n return payload;\n } catch {\n return null;\n }\n}\n\nfunction personalGitHubGitBrokerKey(secret: string): Buffer {\n const normalized = secret.trim();\n if (!normalized) throw new Error(\"personal GitHub Git broker signing secret is unavailable\");\n return createHash(\"sha256\")\n .update(PERSONAL_GITHUB_GIT_BROKER_KEY_CONTEXT, \"utf8\")\n .update(\"\\0\", \"utf8\")\n .update(normalized, \"utf8\")\n .digest();\n}\n\nfunction assertPersonalGitHubGitBrokerClaims(\n value: unknown,\n): asserts value is PersonalGitHubGitBrokerClaims {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\"invalid personal GitHub Git broker claims\");\n }\n const claims = value as Record<string, unknown>;\n const expectedKeys = new Set([\n \"version\",\n \"accountId\",\n \"workspaceId\",\n \"sessionId\",\n \"rootSessionId\",\n \"turnId\",\n \"attemptId\",\n \"executionGeneration\",\n \"originWorkspaceId\",\n \"connectionId\",\n \"connectionAuthorityGeneration\",\n \"ownerSubjectId\",\n \"credentialBindingId\",\n \"selectionGeneration\",\n \"nonce\",\n \"issuedAt\",\n \"expiresAt\",\n ]);\n const strings = [\n \"accountId\",\n \"workspaceId\",\n \"sessionId\",\n \"rootSessionId\",\n \"turnId\",\n \"attemptId\",\n \"originWorkspaceId\",\n \"connectionId\",\n \"ownerSubjectId\",\n \"credentialBindingId\",\n \"nonce\",\n ];\n if (\n claims.version !== 1 ||\n strings.some(\n (field) =>\n typeof claims[field] !== \"string\" ||\n claims[field].length === 0 ||\n claims[field].length > (field === \"ownerSubjectId\" ? 512 : 128),\n ) ||\n !positiveIntegerClaim(claims.executionGeneration) ||\n !positiveIntegerClaim(claims.connectionAuthorityGeneration) ||\n !positiveIntegerClaim(claims.selectionGeneration) ||\n !positiveIntegerClaim(claims.issuedAt) ||\n !positiveIntegerClaim(claims.expiresAt) ||\n Object.keys(claims).some((key) => !expectedKeys.has(key))\n ) {\n throw new Error(\"invalid personal GitHub Git broker claims\");\n }\n}\n\nfunction positiveIntegerClaim(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value > 0;\n}\n\nexport class GitHubAppConfigurationError extends Error {\n constructor(readonly missing: string[]) {\n super(\"GitHub App is not configured\");\n }\n}\n\nexport class GitHubAppApiError extends Error {\n constructor(\n message: string,\n readonly status: number | null = null,\n ) {\n super(message);\n }\n}\n\nexport type GitHubPublicRepositoryVerificationErrorCode =\n | \"invalid_input\"\n | \"unavailable\"\n | \"provider_unavailable\";\n\nexport class GitHubPublicRepositoryVerificationError extends Error {\n constructor(\n readonly code: GitHubPublicRepositoryVerificationErrorCode,\n message: string,\n readonly status?: number,\n ) {\n super(message);\n this.name = \"GitHubPublicRepositoryVerificationError\";\n }\n}\n\nexport type GitHubInstallationAuthorityFailure =\n | \"authority_denied\"\n | \"authority_unavailable\"\n | \"installation_missing\"\n | \"installation_suspended\"\n | \"repository_access_empty\";\n\nexport class GitHubInstallationAuthorityError extends GitHubAppApiError {\n constructor(\n readonly reason: GitHubInstallationAuthorityFailure,\n message: string,\n status: number | null = null,\n ) {\n super(message, status);\n }\n}\n\nexport type GitHubAppInstallationSummary = {\n installationId: number;\n accountId: number;\n accountLogin: string | null;\n accountType: string | null;\n suspended: boolean;\n};\n\nexport type GitHubSignedStatePayload = {\n nonce: string;\n iat: number;\n accountId?: string;\n workspaceId?: string;\n [key: string]: unknown;\n};\n\nexport function githubAppMissingSettings(settings: Settings): string[] {\n const required: Record<string, string | undefined> = {\n OPENGENI_GITHUB_APP_ID: settings.githubAppId,\n OPENGENI_GITHUB_CLIENT_ID: settings.githubClientId,\n OPENGENI_GITHUB_CLIENT_SECRET: settings.githubClientSecret,\n OPENGENI_GITHUB_APP_SLUG: settings.githubAppSlug,\n OPENGENI_GITHUB_APP_PRIVATE_KEY: settings.githubAppPrivateKey,\n };\n return Object.entries(required).flatMap(([name, value]) => (value && value.trim() ? [] : [name]));\n}\n\nexport function prReviewGitHubAppMissingSettings(settings: Settings): string[] {\n const required: Record<string, string | undefined> = {\n OPENGENI_GITHUB_APP_MANIFEST_STATE_SECRET: settings.githubAppManifestStateSecret,\n OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY: settings.environmentsEncryptionKey,\n OPENGENI_PR_REVIEW_GITHUB_APP_ID: settings.prReviewGithubAppId,\n OPENGENI_PR_REVIEW_GITHUB_CLIENT_ID: settings.prReviewGithubClientId,\n OPENGENI_PR_REVIEW_GITHUB_CLIENT_SECRET: settings.prReviewGithubClientSecret,\n OPENGENI_PR_REVIEW_GITHUB_APP_SLUG: settings.prReviewGithubAppSlug,\n OPENGENI_PR_REVIEW_GITHUB_WEBHOOK_SECRET: settings.prReviewGithubWebhookSecret,\n OPENGENI_PR_REVIEW_GITHUB_APP_PRIVATE_KEY: settings.prReviewGithubAppPrivateKey,\n };\n return Object.entries(required).flatMap(([name, value]) => (value && value.trim() ? [] : [name]));\n}\n\n/** Project the separately configured review App onto the ordinary GitHub App\n * authority client. This keeps its OAuth, signing, webhook, and installation\n * identity disjoint from the platform GitHub App while reusing the same\n * personal-owner / organization-owner proof implementation. */\nexport function settingsForPrReviewGitHubApp(settings: Settings): Settings {\n return {\n ...settings,\n githubAppId: settings.prReviewGithubAppId,\n githubClientId: settings.prReviewGithubClientId,\n githubClientSecret: settings.prReviewGithubClientSecret,\n githubAppSlug: settings.prReviewGithubAppSlug,\n githubWebhookSecret: settings.prReviewGithubWebhookSecret,\n githubAppPrivateKey: settings.prReviewGithubAppPrivateKey,\n };\n}\n\nexport type GitHubAppSigningSettings = Pick<Settings, \"githubAppId\" | \"githubAppPrivateKey\">;\n\nfunction githubAppTokenMissingSettings(settings: GitHubAppSigningSettings): string[] {\n const required: Record<string, string | undefined> = {\n OPENGENI_GITHUB_APP_ID: settings.githubAppId,\n OPENGENI_GITHUB_APP_PRIVATE_KEY: settings.githubAppPrivateKey,\n };\n return Object.entries(required).flatMap(([name, value]) => (value && value.trim() ? [] : [name]));\n}\n\nexport function buildGitHubAppManifest(input: {\n appName: string;\n baseUrl: string;\n public: boolean;\n includeCiPermissions: boolean;\n setupUrl?: string;\n}): Record<string, unknown> {\n const base = input.baseUrl.replace(/\\/+$/, \"\");\n const permissions: Record<string, string> = {\n metadata: \"read\",\n contents: \"write\",\n pull_requests: \"write\",\n // Required for the authenticated-user membership endpoint that proves an\n // active organization owner. Existing installations must approve this\n // permission before organization-owner self-service can succeed.\n members: \"read\",\n };\n if (input.includeCiPermissions) {\n permissions.actions = \"read\";\n permissions.checks = \"read\";\n permissions.statuses = \"write\";\n }\n const manifest: Record<string, unknown> = {\n name: input.appName,\n url: base,\n redirect_url: `${base}/v1/github/app-manifest/callback`,\n callback_urls: [`${base}/v1/github/oauth/callback`],\n public: input.public,\n // A setup URL and OAuth-on-install are mutually exclusive in GitHub's App\n // contract. OpenGeni needs the setup callback to receive the installation\n // id, then starts its own exact user-authorization flow.\n request_oauth_on_install: !input.setupUrl,\n default_permissions: permissions,\n };\n if (input.setupUrl) {\n manifest.setup_url = input.setupUrl;\n manifest.setup_on_update = true;\n }\n return manifest;\n}\n\nexport function personalAppManifestUrl(state: string): string {\n return `https://github.com/settings/apps/new?state=${state}`;\n}\n\nexport function organizationAppManifestUrl(organization: string, state: string): string {\n return `https://github.com/organizations/${encodeURIComponent(organization)}/settings/apps/new?state=${state}`;\n}\n\nexport function githubOAuthAuthorizeUrl(input: {\n clientId: string;\n state: string;\n redirectUri?: string;\n}): string {\n const url = new URL(\"https://github.com/login/oauth/authorize\");\n url.searchParams.set(\"client_id\", input.clientId);\n url.searchParams.set(\"state\", input.state);\n if (input.redirectUri) {\n url.searchParams.set(\"redirect_uri\", input.redirectUri);\n }\n return url.toString();\n}\n\nexport function createSignedState(\n secret: string,\n payloadOrNow: Record<string, unknown> | number = {},\n nowArg = Math.floor(Date.now() / 1000),\n): string {\n const payloadInput = typeof payloadOrNow === \"number\" ? {} : payloadOrNow;\n const now = typeof payloadOrNow === \"number\" ? payloadOrNow : nowArg;\n const payload = {\n ...payloadInput,\n nonce: randomBytes(16).toString(\"base64url\"),\n iat: now,\n };\n const encoded = Buffer.from(JSON.stringify(payload)).toString(\"base64url\");\n return `${encoded}.${signStatePayload(encoded, secret)}`;\n}\n\nexport function readSignedState(\n state: string,\n secret: string,\n now = Math.floor(Date.now() / 1000),\n): GitHubSignedStatePayload | null {\n const [encoded, signature] = state.split(\".\", 2);\n if (!encoded || !signature) {\n return null;\n }\n const expected = signStatePayload(encoded, secret);\n if (!safeEqual(signature, expected)) {\n return null;\n }\n let payload: unknown;\n try {\n payload = JSON.parse(Buffer.from(encoded, \"base64url\").toString(\"utf8\"));\n } catch {\n return null;\n }\n if (\n !payload ||\n typeof payload !== \"object\" ||\n typeof (payload as { iat?: unknown }).iat !== \"number\" ||\n typeof (payload as { nonce?: unknown }).nonce !== \"string\"\n ) {\n return null;\n }\n const age = now - (payload as { iat: number }).iat;\n return age >= 0 && age <= stateMaxAgeSeconds ? (payload as GitHubSignedStatePayload) : null;\n}\n\nexport function verifySignedState(\n state: string,\n secret: string,\n now = Math.floor(Date.now() / 1000),\n): boolean {\n return readSignedState(state, secret, now) !== null;\n}\n\nexport function envLinesFromGitHubManifestConversion(payload: Record<string, unknown>): string[] {\n const privateKey = String(payload.pem ?? \"\").replace(/\\n/g, \"\\\\n\");\n return [\n `OPENGENI_GITHUB_APP_ID=${payload.id ?? \"\"}`,\n `OPENGENI_GITHUB_CLIENT_ID=${payload.client_id ?? \"\"}`,\n `OPENGENI_GITHUB_CLIENT_SECRET=${payload.client_secret ?? \"\"}`,\n `OPENGENI_GITHUB_APP_SLUG=${payload.slug ?? \"\"}`,\n `OPENGENI_GITHUB_WEBHOOK_SECRET=${payload.webhook_secret ?? \"\"}`,\n `OPENGENI_GITHUB_APP_PRIVATE_KEY=\"${privateKey}\"`,\n ];\n}\n\nexport async function convertGitHubAppManifest(code: string): Promise<Record<string, unknown>> {\n const response = await fetch(`${githubApiBase}/app-manifests/${code}/conversions`, {\n method: \"POST\",\n headers: githubHeaders(undefined),\n });\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response));\n }\n const payload = await response.json();\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new GitHubAppApiError(\"GitHub returned an invalid manifest conversion payload\");\n }\n return payload as Record<string, unknown>;\n}\n\nexport async function listGitHubAppInstallationSummaries(\n settings: Settings,\n): Promise<GitHubAppInstallationSummary[]> {\n const missing = githubAppMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n const jwt = await createGitHubAppJwt(settings);\n const installations = await listInstallations(jwt);\n return installations.map(installationSummaryFromPayload);\n}\n\nexport async function getGitHubAppInstallationSummary(\n settings: Settings,\n installationId: number,\n): Promise<GitHubAppInstallationSummary | null> {\n const installations = await listGitHubAppInstallationSummaries(settings);\n return (\n installations.find((installation) => installation.installationId === installationId) ?? null\n );\n}\n\nexport async function verifyGitHubInstallationAccessForUser(\n settings: Settings,\n input: {\n code: string;\n installationId: number;\n },\n): Promise<GitHubAppInstallationSummary> {\n const token = await exchangeGitHubOAuthCodeForUserToken(settings, input.code);\n const installations = await listUserAccessibleInstallations(token);\n const installation = installations.find(\n (candidate) => candidate.installationId === input.installationId,\n );\n if (!installation) {\n throw new GitHubAppApiError(\"GitHub installation is not accessible to the installing user\");\n }\n return installation;\n}\n\n/**\n * Exchange a GitHub App user-authorization code and discover the installations\n * and repositories the user can explicitly access. This is compatibility\n * discovery metadata only: visibility and repository permission bits do not\n * prove that the human may install, configure, or bind the App installation.\n * No production binding path may treat this result as authority.\n */\nexport async function authorizeGitHubAppUser(\n settings: Settings,\n input: { code: string },\n): Promise<GitHubUserInstallationAccess[]> {\n const token = await exchangeGitHubOAuthCodeForUserToken(settings, input.code);\n const installations = await listUserAccessibleInstallations(token);\n return await Promise.all(\n installations.map(async (installation) => ({\n ...installation,\n repositories: installation.suspended\n ? []\n : await listUserInstallationRepositories(token, installation),\n })),\n );\n}\n\n/**\n * Prove current GitHub installation authority without treating repository\n * administration or installation visibility as delegation authority.\n *\n * GitHub exposes an exact personal-account owner through the authenticated\n * user's immutable id. For organizations, GitHub's authenticated membership\n * endpoint exposes active owners as role=admin. GitHub does not expose an\n * equivalent current-authority receipt for App Managers, so that case remains\n * unsupported and fails closed.\n */\nexport async function authorizeGitHubInstallationBinding(\n settings: Settings,\n input: { code: string; installationId: number },\n): Promise<GitHubInstallationBindingProof> {\n const userToken = await exchangeGitHubOAuthCodeForUserToken(settings, input.code);\n const actor = await getAuthenticatedGitHubUser(userToken);\n const visibleInstallations = await listUserAccessibleInstallations(userToken);\n const visible = visibleInstallations.find(\n (installation) => installation.installationId === input.installationId,\n );\n if (!visible) {\n throw new GitHubInstallationAuthorityError(\n \"authority_denied\",\n \"GitHub did not associate this installation with the authorized user\",\n );\n }\n\n const jwt = await createGitHubAppJwt(settings);\n const livePayload = (await listInstallations(jwt)).find(\n (installation) => asInt(installation.id) === input.installationId,\n );\n if (!livePayload) {\n throw new GitHubInstallationAuthorityError(\n \"installation_missing\",\n \"GitHub App installation was deleted or is not owned by this App\",\n );\n }\n const installation = installationSummaryFromPayload(livePayload);\n if (\n installation.accountId !== visible.accountId ||\n installation.accountLogin !== visible.accountLogin ||\n installation.accountType !== visible.accountType\n ) {\n throw new GitHubInstallationAuthorityError(\n \"authority_denied\",\n \"GitHub installation identity changed during authorization\",\n );\n }\n if (installation.suspended) {\n throw new GitHubInstallationAuthorityError(\n \"installation_suspended\",\n \"GitHub App installation is suspended\",\n );\n }\n\n let authorityKind: GitHubInstallationBindingProof[\"authorityKind\"];\n if (installation.accountType === \"User\" && actor.id === installation.accountId) {\n authorityKind = \"personal_owner\";\n } else if (installation.accountType === \"Organization\" && installation.accountLogin) {\n await assertActiveOrganizationOwner(\n userToken,\n installation.accountId,\n installation.accountLogin,\n );\n authorityKind = \"organization_owner\";\n } else {\n throw new GitHubInstallationAuthorityError(\n \"authority_denied\",\n \"Only a GitHub personal-account owner or organization owner may bind an installation\",\n );\n }\n\n const installationToken = await createInstallationToken(jwt, {\n installationId: installation.installationId,\n });\n const repositories = await listInstallationRepositories(\n installationToken.token,\n installation.installationId,\n { login: installation.accountLogin, type: installation.accountType },\n );\n if (repositories.length === 0) {\n throw new GitHubInstallationAuthorityError(\n \"repository_access_empty\",\n \"GitHub App installation does not currently grant access to any repositories\",\n );\n }\n if (authorityKind === \"organization_owner\") {\n // Repository enumeration is an async provider boundary. Re-read the live\n // owner tuple after it so a role revoked after the chooser proof cannot be\n // durably bound with a later, misleading authority timestamp.\n await assertActiveOrganizationOwner(\n userToken,\n installation.accountId,\n installation.accountLogin!,\n );\n }\n return {\n actorId: actor.id,\n actorLogin: actor.login,\n authorityKind,\n installation,\n repositories,\n };\n}\n\n/**\n * Discover existing installations that the freshly authorized GitHub human\n * can bind as an exact personal owner or active organization owner.\n *\n * `GET /user/installations` is discovery input only. Every candidate is\n * cross-checked against the App's live installation inventory and an\n * organization candidate requires a live `state=active, role=admin`\n * membership proof. The later exact authorization still re-runs the complete\n * proof immediately before the durable bind.\n */\nexport async function discoverGitHubInstallationBindingCandidates(\n settings: Settings,\n input: { code: string },\n): Promise<GitHubInstallationBindingCandidate[]> {\n const userToken = await exchangeGitHubOAuthCodeForUserToken(settings, input.code);\n const actor = await getAuthenticatedGitHubUser(userToken);\n const visibleInstallations = await listUserAccessibleInstallations(userToken);\n const jwt = await createGitHubAppJwt(settings);\n const liveInstallations = new Map(\n (await listInstallations(jwt)).map((payload) => {\n const installation = installationSummaryFromPayload(payload);\n return [installation.installationId, installation] as const;\n }),\n );\n const candidates: GitHubInstallationBindingCandidate[] = [];\n\n for (const visible of visibleInstallations) {\n const installation = liveInstallations.get(visible.installationId);\n if (\n !installation ||\n installation.suspended ||\n installation.accountId !== visible.accountId ||\n installation.accountLogin !== visible.accountLogin ||\n installation.accountType !== visible.accountType\n ) {\n continue;\n }\n if (installation.accountType === \"User\" && actor.id === installation.accountId) {\n candidates.push({ installation, authorityKind: \"personal_owner\" });\n continue;\n }\n if (installation.accountType !== \"Organization\" || !installation.accountLogin) {\n continue;\n }\n try {\n await assertActiveOrganizationOwner(\n userToken,\n installation.accountId,\n installation.accountLogin,\n );\n candidates.push({ installation, authorityKind: \"organization_owner\" });\n } catch (error) {\n if (\n error instanceof GitHubInstallationAuthorityError &&\n error.reason === \"authority_unavailable\"\n ) {\n continue;\n }\n if (\n error instanceof GitHubInstallationAuthorityError &&\n error.reason === \"authority_denied\"\n ) {\n continue;\n }\n throw error;\n }\n }\n\n return candidates.sort((left, right) =>\n (left.installation.accountLogin ?? \"\").localeCompare(right.installation.accountLogin ?? \"\"),\n );\n}\n\nexport async function listGitHubAppRepositories(\n settings: Settings,\n input: {\n installationIds?: number[];\n } = {},\n): Promise<GitHubRepository[]> {\n const missing = githubAppMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n return await listGitHubAppRepositoriesWithSigningSettings(settings, input);\n}\n\n/** List repositories for a separately registered App that needs only signing credentials. */\nexport async function listGitHubAppRepositoriesWithSigningSettings(\n settings: GitHubAppSigningSettings,\n input: {\n installationIds?: number[];\n } = {},\n): Promise<GitHubRepository[]> {\n const missing = githubAppTokenMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n const allowedInstallations = input.installationIds ? new Set(input.installationIds) : null;\n if (allowedInstallations && allowedInstallations.size === 0) {\n return [];\n }\n const jwt = await createGitHubAppJwt(settings);\n const installations = await listInstallations(jwt);\n const repositories: GitHubRepository[] = [];\n for (const installation of installations) {\n if (installation.suspended_at) {\n continue;\n }\n const installationId = asInt(installation.id);\n if (installationId === null) {\n continue;\n }\n if (allowedInstallations && !allowedInstallations.has(installationId)) {\n continue;\n }\n const account =\n typeof installation.account === \"object\" && installation.account\n ? (installation.account as Record<string, unknown>)\n : {};\n const token = await createInstallationToken(jwt, { installationId });\n repositories.push(\n ...(await listInstallationRepositories(token.token, installationId, account)),\n );\n }\n repositories.sort((left, right) => left.fullName.localeCompare(right.fullName));\n return repositories;\n}\n\nexport type GitHubAppInstallationRepositoryLookupInput = {\n installationId: number;\n owner: string;\n name: string;\n};\n\nexport type GitHubAppInstallationRepositoryLookup = (\n input: GitHubAppInstallationRepositoryLookupInput,\n) => Promise<GitHubRepository | null>;\n\n/**\n * Resolve one `owner/name` repository through an exact App installation and\n * return GitHub's stable repository identity, or null when that installation\n * cannot see the repository. The server-side lookup token never leaves the\n * caller and grants nothing by itself: the workspace allowlist decides whether\n * the returned id may mint a sandbox-bound token.\n */\nexport async function getGitHubAppInstallationRepository(\n settings: Settings,\n input: GitHubAppInstallationRepositoryLookupInput,\n): Promise<GitHubRepository | null> {\n return await createGitHubAppInstallationRepositoryLookup(settings)(input);\n}\n\n/**\n * One lookup client that reuses a server-side installation token per\n * installation for its lifetime (one worker turn), so several bare repository\n * URIs from the same installation cost one mint plus one read each.\n */\nexport function createGitHubAppInstallationRepositoryLookup(\n settings: Settings,\n): GitHubAppInstallationRepositoryLookup {\n const missing = githubAppMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n const tokens = new Map<number, Promise<GitHubAppInstallationToken>>();\n const installationToken = (installationId: number): Promise<GitHubAppInstallationToken> => {\n let pending = tokens.get(installationId);\n if (!pending) {\n // Metadata-read only: the lookup needs the repository id, never contents.\n // Bounded well below the sandbox mint timeout so a slow GitHub cannot\n // hold turn start; the caller proceeds bare on expiry.\n pending = createGitHubAppJwt(settings).then((jwt) =>\n createInstallationToken(jwt, {\n installationId,\n permissions: { metadata: \"read\" },\n timeoutMs: githubRepositoryLookupTimeoutMs,\n }),\n );\n pending.catch(() => tokens.delete(installationId));\n tokens.set(installationId, pending);\n }\n return pending;\n };\n return async (input) => {\n const owner = input.owner.trim();\n const name = input.name.trim();\n if (\n !/^[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?$/u.test(owner) ||\n !/^[A-Za-z0-9._-]+$/u.test(name)\n ) {\n return null;\n }\n const token = await installationToken(input.installationId);\n const response = await fetch(\n `${githubApiBase}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}`,\n {\n headers: githubHeaders(token.token),\n signal: AbortSignal.timeout(githubRepositoryLookupTimeoutMs),\n },\n );\n if (response.status === 404) {\n return null;\n }\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response), response.status);\n }\n const payload = await response.json();\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repository payload\");\n }\n const record = payload as Record<string, unknown>;\n const account =\n record.owner && typeof record.owner === \"object\" && !Array.isArray(record.owner)\n ? (record.owner as Record<string, unknown>)\n : {};\n return repositoryFromPayload(record, input.installationId, account);\n };\n}\n\n/**\n * List one bounded page of branch suggestions with an exact repository-scoped\n * installation token. The token remains local to this server-side helper and\n * is never returned in repository or branch metadata.\n */\nexport async function listGitHubAppRepositoryBranches(\n settings: Settings,\n input: {\n installationId: number;\n repositoryId: number;\n page: number;\n limit: number;\n },\n): Promise<GitHubAppRepositoryBranchPage> {\n if (\n !Number.isSafeInteger(input.installationId) ||\n input.installationId <= 0 ||\n !Number.isSafeInteger(input.repositoryId) ||\n input.repositoryId <= 0 ||\n !Number.isSafeInteger(input.page) ||\n input.page <= 0 ||\n input.page > 10_000 ||\n !Number.isSafeInteger(input.limit) ||\n input.limit <= 0 ||\n input.limit > 100\n ) {\n throw new GitHubAppApiError(\"GitHub branch lookup requires bounded exact repository input\");\n }\n const minted = await createGitHubAppInstallationTokenWithSigningSettings(settings, {\n installationId: input.installationId,\n repositoryIds: [input.repositoryId],\n permissions: { contents: \"read\", metadata: \"read\" },\n timeoutMs: githubRepositoryBranchesTimeoutMs,\n });\n const repositoryResponse = await githubRepositoryBranchesFetch(\n new URL(`${githubApiBase}/repositories/${input.repositoryId}`),\n minted.token,\n \"GitHub repository branch identity\",\n );\n const repositoryPayload = await githubResponseJsonBounded(\n repositoryResponse,\n \"GitHub repository branch identity response\",\n );\n if (\n !repositoryPayload ||\n typeof repositoryPayload !== \"object\" ||\n Array.isArray(repositoryPayload)\n ) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repository branch identity payload\");\n }\n const repository = repositoryPayload as Record<string, unknown>;\n const repositoryId = asInt(repository.id);\n const fullName = typeof repository.full_name === \"string\" ? repository.full_name : \"\";\n const defaultBranch =\n typeof repository.default_branch === \"string\" ? repository.default_branch : \"\";\n const coordinates = fullName.split(\"/\");\n if (\n repositoryId !== input.repositoryId ||\n coordinates.length !== 2 ||\n !coordinates[0] ||\n !coordinates[1] ||\n defaultBranch.length === 0 ||\n defaultBranch.length > 1024\n ) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repository branch identity payload\");\n }\n const branchUrl = new URL(\n `${githubApiBase}/repos/${encodeURIComponent(coordinates[0])}/${encodeURIComponent(coordinates[1])}/branches`,\n );\n branchUrl.searchParams.set(\"page\", String(input.page));\n branchUrl.searchParams.set(\"per_page\", String(input.limit));\n const branchesResponse = await githubRepositoryBranchesFetch(\n branchUrl,\n minted.token,\n \"GitHub repository branches\",\n );\n const branchPayload = await githubResponseJsonBounded(\n branchesResponse,\n \"GitHub repository branches response\",\n );\n if (!Array.isArray(branchPayload) || branchPayload.length > input.limit) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repository branches payload\");\n }\n const branches: string[] = [];\n const seen = new Set<string>();\n for (const value of branchPayload) {\n const name =\n value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>).name\n : null;\n if (typeof name !== \"string\" || name.length === 0 || name.length > 1024 || seen.has(name)) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repository branches payload\");\n }\n seen.add(name);\n branches.push(name);\n }\n return {\n installationId: input.installationId,\n repositoryId: input.repositoryId,\n defaultBranch,\n branches,\n nextPage: branchPayload.length === input.limit && input.page < 10_000 ? input.page + 1 : null,\n };\n}\n\n/**\n * Verify one exact anonymous github.com repository and ref. The provider URL\n * is derived only from strict canonical coordinates, follows no redirects,\n * sends no credentials, and bounds both request time and response bytes.\n */\nexport async function verifyPublicGitHubRepositoryRef(\n input: { repository: CanonicalGitHubRepository; ref: string },\n fetchImpl: typeof fetch = fetch,\n): Promise<VerifyPublicGitHubRepositoryRefResponse> {\n const ref = input.ref.trim();\n if (!ref || ref.length > 1024 || /[\\u0000-\\u001f\\u007f]/u.test(ref)) {\n throw new GitHubPublicRepositoryVerificationError(\n \"invalid_input\",\n \"Enter a branch, tag, or commit SHA.\",\n );\n }\n const repositoryUrl = new URL(\n `${githubApiBase}/repos/${encodeURIComponent(input.repository.owner)}/${encodeURIComponent(input.repository.name)}`,\n );\n const repositoryPayload = await anonymousGitHubJson(\n fetchImpl,\n repositoryUrl,\n \"GitHub repository\",\n );\n if (\n !repositoryPayload ||\n typeof repositoryPayload !== \"object\" ||\n Array.isArray(repositoryPayload)\n ) {\n throw new GitHubPublicRepositoryVerificationError(\n \"provider_unavailable\",\n \"GitHub returned an invalid repository response.\",\n );\n }\n const repository = repositoryPayload as Record<string, unknown>;\n const fullName = typeof repository.full_name === \"string\" ? repository.full_name : \"\";\n const defaultBranch =\n typeof repository.default_branch === \"string\" ? repository.default_branch : \"\";\n const privateRepository = repository.private;\n if (\n !Number.isSafeInteger(repository.id) ||\n Number(repository.id) <= 0 ||\n privateRepository !== false ||\n !fullName ||\n fullName.toLowerCase() !== input.repository.fullName.toLowerCase() ||\n !defaultBranch ||\n defaultBranch.length > 1024\n ) {\n throw new GitHubPublicRepositoryVerificationError(\n \"unavailable\",\n \"That GitHub repository is private or unavailable.\",\n );\n }\n let canonical: CanonicalGitHubRepository;\n try {\n canonical = parseCanonicalGitHubRepositoryUrl(`https://github.com/${fullName}`);\n } catch {\n throw new GitHubPublicRepositoryVerificationError(\n \"provider_unavailable\",\n \"GitHub returned an invalid repository identity.\",\n );\n }\n const commitUrl = new URL(\n `${githubApiBase}/repos/${encodeURIComponent(canonical.owner)}/${encodeURIComponent(canonical.name)}/commits/${encodeURIComponent(ref)}`,\n );\n const commitPayload = await anonymousGitHubJson(fetchImpl, commitUrl, \"GitHub repository ref\");\n const commitSha =\n commitPayload && typeof commitPayload === \"object\" && !Array.isArray(commitPayload)\n ? (commitPayload as Record<string, unknown>).sha\n : null;\n if (typeof commitSha !== \"string\" || !/^[0-9a-f]{40}$/u.test(commitSha)) {\n throw new GitHubPublicRepositoryVerificationError(\n \"unavailable\",\n \"That branch, tag, or commit SHA is not available on the public repository.\",\n );\n }\n return {\n ...canonical,\n defaultBranch,\n ref,\n commitSha,\n };\n}\n\nexport async function createGitHubAppInstallationToken(\n settings: Settings,\n input: {\n installationId: number;\n repositoryIds: number[];\n },\n): Promise<string> {\n return (await createGitHubAppInstallationTokenWithExpiry(settings, input)).token;\n}\n\nexport type GitHubAppInstallationToken = {\n token: string;\n expiresAt: string | null;\n};\n\nexport async function createGitHubAppInstallationTokenWithExpiry(\n settings: Settings,\n input: {\n installationId: number;\n repositoryIds: number[];\n },\n): Promise<GitHubAppInstallationToken> {\n const missing = githubAppMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n return await createGitHubAppInstallationTokenWithSigningSettings(settings, input);\n}\n\n/** Mint for a separately registered App without requiring unrelated OAuth settings. */\nexport async function createGitHubAppInstallationTokenWithSigningSettings(\n settings: GitHubAppSigningSettings,\n input: {\n installationId: number;\n repositoryIds: number[];\n permissions?: Record<string, \"read\" | \"write\">;\n timeoutMs?: number;\n },\n): Promise<GitHubAppInstallationToken> {\n const missing = githubAppTokenMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n if (!Array.isArray(input.repositoryIds)) {\n throw new GitHubAppApiError(\n \"GitHub installation token mint requires an explicit, unique repository allowlist\",\n );\n }\n const repositoryIds = [...new Set(input.repositoryIds)];\n if (\n !Number.isSafeInteger(input.installationId) ||\n input.installationId <= 0 ||\n repositoryIds.length === 0 ||\n repositoryIds.length !== input.repositoryIds.length ||\n repositoryIds.some((id) => !Number.isSafeInteger(id) || id <= 0)\n ) {\n throw new GitHubAppApiError(\n \"GitHub installation token mint requires an explicit, unique repository allowlist\",\n );\n }\n const jwt = await createGitHubAppJwt(settings);\n return await createInstallationToken(jwt, {\n installationId: input.installationId,\n repositoryIds,\n ...(input.permissions ? { permissions: input.permissions } : {}),\n ...(input.timeoutMs !== undefined ? { timeoutMs: input.timeoutMs } : {}),\n });\n}\n\nexport function githubAppBotIdentity(settings: Settings): { name: string; email: string } | null {\n const appId = settings.githubAppId?.trim();\n const slug = settings.githubAppSlug?.trim();\n if (!appId || !slug) {\n return null;\n }\n const login = `${slug}[bot]`;\n return {\n name: login,\n email: `${appId}+${login}@users.noreply.github.com`,\n };\n}\n\nexport const GITHUB_APP_BOT_IDENTITY_UNAVAILABLE_WARNING =\n \"github_app_bot_identity_unavailable\" as const;\n\n/**\n * Non-secret health posture for the stable sandbox Git identity. API-direct\n * attach and worker-turn startup must add the same identity keys. A complete\n * deployment-level author identity is sufficient because committer values\n * default to it; otherwise a partially configured workspace GitHub App must\n * surface that its bot identity cannot be derived.\n */\nexport function githubAppBotIdentityWarnings(\n settings: Settings,\n): Array<typeof GITHUB_APP_BOT_IDENTITY_UNAVAILABLE_WARNING> {\n const workspaceAppConfigured = [\n settings.githubAppId,\n settings.githubClientId,\n settings.githubClientSecret,\n settings.githubAppSlug,\n settings.githubWebhookSecret,\n settings.githubAppPrivateKey,\n ].some((value) => typeof value === \"string\" && value.trim().length > 0);\n const explicitGitIdentityConfigured =\n typeof settings.gitAuthorName === \"string\" &&\n settings.gitAuthorName.trim().length > 0 &&\n typeof settings.gitAuthorEmail === \"string\" &&\n settings.gitAuthorEmail.trim().length > 0;\n if (\n !workspaceAppConfigured ||\n explicitGitIdentityConfigured ||\n githubAppBotIdentity(settings) !== null\n ) {\n return [];\n }\n return [GITHUB_APP_BOT_IDENTITY_UNAVAILABLE_WARNING];\n}\n\nasync function createGitHubAppJwt(settings: GitHubAppSigningSettings): Promise<string> {\n const privateKey = normalizeGitHubAppPrivateKey(settings.githubAppPrivateKey ?? \"\");\n const appId = settings.githubAppId?.trim();\n if (!appId || !privateKey) {\n throw new GitHubAppConfigurationError(githubAppTokenMissingSettings(settings));\n }\n const key = await importPKCS8(privateKey, \"RS256\");\n const now = Math.floor(Date.now() / 1000);\n return await new SignJWT({})\n .setProtectedHeader({ alg: \"RS256\" })\n .setIssuedAt(now - 60)\n .setExpirationTime(now + 9 * 60)\n .setIssuer(appId)\n .sign(key);\n}\n\nasync function listInstallations(token: string): Promise<Array<Record<string, unknown>>> {\n const out: Array<Record<string, unknown>> = [];\n for (let page = 1; ; page += 1) {\n const payload = await githubGet(\"/app/installations\", token, {\n per_page: \"100\",\n page: String(page),\n });\n if (!Array.isArray(payload)) {\n throw new GitHubAppApiError(\"GitHub returned an invalid installations payload\");\n }\n out.push(\n ...payload.filter((item): item is Record<string, unknown> =>\n Boolean(item && typeof item === \"object\" && !Array.isArray(item)),\n ),\n );\n if (payload.length < 100) {\n return out;\n }\n }\n}\n\nasync function exchangeGitHubOAuthCodeForUserToken(\n settings: Settings,\n code: string,\n): Promise<string> {\n if (!settings.githubClientId || !settings.githubClientSecret) {\n throw new GitHubAppConfigurationError(githubAppMissingSettings(settings));\n }\n const response = await fetch(\"https://github.com/login/oauth/access_token\", {\n method: \"POST\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n client_id: settings.githubClientId,\n client_secret: settings.githubClientSecret,\n code,\n }),\n });\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response));\n }\n const payload = await response.json();\n if (!payload || typeof payload !== \"object\" || typeof payload.access_token !== \"string\") {\n throw new GitHubAppApiError(\"GitHub returned an invalid OAuth token payload\");\n }\n return payload.access_token;\n}\n\nasync function getAuthenticatedGitHubUser(token: string): Promise<{ id: number; login: string }> {\n const payload = await githubGet(\"/user\", token);\n const id = payload && typeof payload === \"object\" ? asInt(payload.id) : null;\n const login =\n payload && typeof payload === \"object\" && typeof payload.login === \"string\"\n ? payload.login\n : null;\n if (id === null || !login) {\n throw new GitHubAppApiError(\"GitHub returned an invalid authenticated user payload\");\n }\n return { id, login };\n}\n\nasync function getAuthenticatedOrganizationMembership(\n token: string,\n organizationLogin: string,\n): Promise<{ organizationId: number; role: string; state: string }> {\n let payload: any;\n try {\n payload = await githubGet(\n `/user/memberships/orgs/${encodeURIComponent(organizationLogin)}`,\n token,\n );\n } catch (error) {\n if (error instanceof GitHubAppApiError) {\n throw new GitHubInstallationAuthorityError(\n \"authority_unavailable\",\n \"GitHub could not prove current organization-owner membership\",\n error.status,\n );\n }\n throw error;\n }\n const organization =\n payload && typeof payload === \"object\" && payload.organization ? payload.organization : null;\n const organizationId =\n organization && typeof organization === \"object\" ? asInt(organization.id) : null;\n if (\n organizationId === null ||\n typeof payload?.role !== \"string\" ||\n typeof payload?.state !== \"string\"\n ) {\n throw new GitHubInstallationAuthorityError(\n \"authority_unavailable\",\n \"GitHub returned an invalid organization membership proof\",\n );\n }\n return { organizationId, role: payload.role, state: payload.state };\n}\n\nasync function assertActiveOrganizationOwner(\n token: string,\n organizationId: number,\n organizationLogin: string,\n): Promise<void> {\n const membership = await getAuthenticatedOrganizationMembership(token, organizationLogin);\n if (\n membership.organizationId !== organizationId ||\n membership.state !== \"active\" ||\n membership.role !== \"admin\"\n ) {\n throw new GitHubInstallationAuthorityError(\n \"authority_denied\",\n \"Only an active GitHub organization owner may bind this installation\",\n );\n }\n}\n\nasync function listUserAccessibleInstallations(\n token: string,\n): Promise<GitHubAppInstallationSummary[]> {\n const out: GitHubAppInstallationSummary[] = [];\n for (let page = 1; ; page += 1) {\n const payload = await githubGet(\"/user/installations\", token, {\n per_page: \"100\",\n page: String(page),\n });\n const installations: unknown[] | null =\n payload && typeof payload === \"object\" && Array.isArray(payload.installations)\n ? (payload.installations as unknown[])\n : null;\n if (!installations) {\n throw new GitHubAppApiError(\"GitHub returned an invalid user installations payload\");\n }\n out.push(\n ...installations\n .filter((item): item is Record<string, unknown> =>\n Boolean(item && typeof item === \"object\" && !Array.isArray(item)),\n )\n .map(installationSummaryFromPayload),\n );\n if (installations.length < 100) {\n return out;\n }\n }\n}\n\nasync function listUserInstallationRepositories(\n token: string,\n installation: GitHubAppInstallationSummary,\n): Promise<GitHubUserRepositoryAccess[]> {\n const out: GitHubUserRepositoryAccess[] = [];\n const account = {\n ...(installation.accountLogin ? { login: installation.accountLogin } : {}),\n ...(installation.accountType ? { type: installation.accountType } : {}),\n };\n for (let page = 1; ; page += 1) {\n const payload = await githubGet(\n `/user/installations/${installation.installationId}/repositories`,\n token,\n { per_page: \"100\", page: String(page) },\n );\n if (\n !payload ||\n typeof payload !== \"object\" ||\n Array.isArray(payload) ||\n !Array.isArray(payload.repositories)\n ) {\n throw new GitHubAppApiError(\n \"GitHub returned an invalid user installation repositories payload\",\n );\n }\n for (const repository of payload.repositories) {\n if (!repository || typeof repository !== \"object\" || Array.isArray(repository)) {\n continue;\n }\n const record = repository as Record<string, unknown>;\n out.push({\n ...repositoryFromPayload(record, installation.installationId, account),\n permissions: repositoryPermissionsFromPayload(record.permissions),\n });\n }\n if (payload.repositories.length < 100) {\n return out;\n }\n }\n}\n\nasync function createInstallationToken(\n appJwt: string,\n input: {\n installationId: number;\n repositoryIds?: number[];\n /** Narrow the token below the installation's granted permissions. */\n permissions?: Record<string, \"read\" | \"write\">;\n timeoutMs?: number;\n },\n): Promise<GitHubAppInstallationToken> {\n const body: Record<string, unknown> = {};\n if (input.repositoryIds && input.repositoryIds.length > 0) {\n body.repository_ids = input.repositoryIds;\n }\n if (input.permissions && Object.keys(input.permissions).length > 0) {\n body.permissions = input.permissions;\n }\n const scoped = Object.keys(body).length > 0;\n const response = await fetch(\n `${githubApiBase}/app/installations/${input.installationId}/access_tokens`,\n {\n method: \"POST\",\n headers: {\n ...githubHeaders(appJwt),\n ...(scoped ? { \"Content-Type\": \"application/json\" } : {}),\n },\n redirect: \"manual\",\n signal: AbortSignal.timeout(input.timeoutMs ?? githubTokenMintTimeoutMs),\n ...(scoped ? { body: JSON.stringify(body) } : {}),\n },\n );\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response), response.status);\n }\n let payload: unknown;\n try {\n payload = JSON.parse(\n await readResponseTextBounded(\n response,\n githubInstallationTokenResponseMaxBytes,\n \"GitHub installation token response\",\n ),\n ) as unknown;\n } catch {\n throw new GitHubAppApiError(\"GitHub returned an invalid installation token payload\");\n }\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new GitHubAppApiError(\"GitHub returned an invalid installation token payload\");\n }\n const record = payload as Record<string, unknown>;\n if (typeof record.token !== \"string\") {\n throw new GitHubAppApiError(\"GitHub returned an invalid installation token payload\");\n }\n return {\n token: record.token,\n expiresAt: typeof record.expires_at === \"string\" ? record.expires_at : null,\n };\n}\n\nasync function listInstallationRepositories(\n token: string,\n installationId: number,\n account: Record<string, unknown>,\n): Promise<GitHubRepository[]> {\n const out: GitHubRepository[] = [];\n for (let page = 1; ; page += 1) {\n const payload = await githubGet(\"/installation/repositories\", token, {\n per_page: \"100\",\n page: String(page),\n });\n if (\n !payload ||\n typeof payload !== \"object\" ||\n Array.isArray(payload) ||\n !Array.isArray(payload.repositories)\n ) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repositories payload\");\n }\n for (const repo of payload.repositories) {\n if (repo && typeof repo === \"object\" && !Array.isArray(repo)) {\n out.push(repositoryFromPayload(repo as Record<string, unknown>, installationId, account));\n }\n }\n if (payload.repositories.length < 100) {\n return out;\n }\n }\n}\n\nfunction installationSummaryFromPayload(\n payload: Record<string, unknown>,\n): GitHubAppInstallationSummary {\n const installationId = asInt(payload.id);\n if (installationId === null) {\n throw new GitHubAppApiError(\"GitHub returned an installation without id\");\n }\n const account =\n typeof payload.account === \"object\" && payload.account\n ? (payload.account as Record<string, unknown>)\n : {};\n const accountId = asInt(account.id);\n if (accountId === null) {\n throw new GitHubAppApiError(\"GitHub returned an installation without an account id\");\n }\n return {\n installationId,\n accountId,\n accountLogin: typeof account.login === \"string\" ? account.login : null,\n accountType: typeof account.type === \"string\" ? account.type : null,\n suspended: Boolean(payload.suspended_at),\n };\n}\n\nasync function githubGet(\n path: string,\n token: string,\n params: Record<string, string> = {},\n): Promise<any> {\n const url = new URL(`${githubApiBase}${path}`);\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n const response = await fetch(url, { headers: githubHeaders(token) });\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response), response.status);\n }\n return await response.json();\n}\n\nasync function githubRepositoryBranchesFetch(\n url: URL,\n token: string,\n label: string,\n): Promise<Response> {\n let response: Response;\n try {\n response = await fetch(url, {\n headers: githubHeaders(token),\n redirect: \"manual\",\n signal: AbortSignal.timeout(githubRepositoryBranchesTimeoutMs),\n });\n } catch {\n throw new GitHubAppApiError(`${label} request failed`);\n }\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response), response.status);\n }\n return response;\n}\n\nasync function githubResponseJsonBounded(response: Response, label: string): Promise<unknown> {\n try {\n return JSON.parse(\n await readResponseTextBounded(response, githubRepositoryBranchesResponseMaxBytes, label),\n ) as unknown;\n } catch {\n throw new GitHubAppApiError(`${label} was invalid or too large`);\n }\n}\n\nasync function anonymousGitHubJson(\n fetchImpl: typeof fetch,\n url: URL,\n label: string,\n): Promise<unknown> {\n let response: Response;\n try {\n response = await fetchImpl(url, {\n headers: githubHeaders(),\n redirect: \"manual\",\n signal: AbortSignal.timeout(githubPublicRepositoryVerificationTimeoutMs),\n });\n } catch {\n throw new GitHubPublicRepositoryVerificationError(\n \"provider_unavailable\",\n `${label} verification is temporarily unavailable.`,\n );\n }\n if (response.status === 404) {\n throw new GitHubPublicRepositoryVerificationError(\n \"unavailable\",\n label === \"GitHub repository\"\n ? \"That GitHub repository is private or unavailable.\"\n : \"That branch, tag, or commit SHA is not available on the public repository.\",\n response.status,\n );\n }\n if (!response.ok) {\n throw new GitHubPublicRepositoryVerificationError(\n \"provider_unavailable\",\n response.status === 429\n ? \"GitHub is temporarily rate limited. Try again shortly.\"\n : `${label} verification is temporarily unavailable.`,\n response.status,\n );\n }\n try {\n return JSON.parse(\n await readResponseTextBounded(\n response,\n githubPublicRepositoryVerificationResponseMaxBytes,\n `${label} verification response`,\n ),\n ) as unknown;\n } catch {\n throw new GitHubPublicRepositoryVerificationError(\n \"provider_unavailable\",\n `${label} verification returned an invalid response.`,\n );\n }\n}\n\nfunction repositoryFromPayload(\n payload: Record<string, unknown>,\n installationId: number,\n account: Record<string, unknown>,\n): GitHubRepository {\n const id = asInt(payload.id);\n const fullName = String(payload.full_name ?? \"\");\n if (id === null || !fullName) {\n throw new GitHubAppApiError(\"GitHub returned a repository without id/full_name\");\n }\n return {\n id,\n installationId,\n fullName,\n name: String(payload.name ?? fullName.split(\"/\").at(-1) ?? fullName),\n private: Boolean(payload.private),\n htmlUrl: String(payload.html_url ?? `https://github.com/${fullName}`),\n cloneUrl: String(payload.clone_url ?? `https://github.com/${fullName}.git`),\n defaultBranch: String(payload.default_branch ?? \"main\"),\n accountLogin: String(account.login ?? fullName.split(\"/\", 1)[0]),\n accountType: typeof account.type === \"string\" ? account.type : null,\n };\n}\n\nfunction repositoryPermissionsFromPayload(payload: unknown): GitHubRepositoryPermissions {\n const permissions =\n payload && typeof payload === \"object\" && !Array.isArray(payload)\n ? (payload as Record<string, unknown>)\n : {};\n return {\n admin: permissions.admin === true,\n maintain: permissions.maintain === true,\n push: permissions.push === true,\n triage: permissions.triage === true,\n pull: permissions.pull === true,\n };\n}\n\nfunction githubHeaders(token?: string): HeadersInit {\n return {\n Accept: \"application/vnd.github+json\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n \"X-GitHub-Api-Version\": githubApiVersion,\n };\n}\n\nasync function githubErrorMessage(response: Response): Promise<string> {\n let text: string;\n try {\n text = await readResponseTextBounded(\n response,\n githubErrorResponseMaxBytes,\n \"GitHub error response\",\n );\n } catch {\n return `GitHub API ${response.status}`;\n }\n try {\n const payload = JSON.parse(text) as unknown;\n if (payload && typeof payload === \"object\" && \"message\" in payload) {\n return `GitHub API ${response.status}: ${String(\n (payload as Record<string, unknown>).message,\n ).slice(0, githubErrorMessageMaxLength)}`;\n }\n } catch {\n // Fall through to the bounded text body.\n }\n return `GitHub API ${response.status}: ${text.slice(0, githubErrorMessageMaxLength)}`;\n}\n\nexport function normalizeGitHubAppPrivateKey(value: string): string {\n const privateKey = value.trim().replace(/\\\\n/g, \"\\n\");\n if (!privateKey || privateKey.startsWith(pkcs8PrivateKeyHeader)) {\n return privateKey;\n }\n if (privateKey.startsWith(rsaPrivateKeyHeader)) {\n return createPrivateKey(privateKey).export({ type: \"pkcs8\", format: \"pem\" }).toString();\n }\n return privateKey;\n}\n\nfunction signStatePayload(encoded: string, secret: string): string {\n return createHmac(\"sha256\", secret).update(encoded).digest(\"base64url\");\n}\n\nfunction safeEqual(left: string, right: string): boolean {\n const a = Buffer.from(left);\n const b = Buffer.from(right);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\nfunction asInt(value: unknown): number | null {\n if (typeof value === \"number\" && Number.isInteger(value)) {\n return value;\n }\n if (typeof value === \"string\" && /^\\d+$/.test(value)) {\n return Number(value);\n }\n return null;\n}\n"],"mappings":"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","names":["installation"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Settings } from \"@opengeni/config\";\nimport type {\n GitHubAppRepositoryBranchPage,\n GitHubInstallationBindingCandidate,\n GitHubInstallationBindingProof,\n GitHubRepository,\n GitHubRepositoryPermissions,\n GitHubUserInstallationAccess,\n GitHubUserRepositoryAccess,\n} from \"@opengeni/contracts\";\nimport type { VerifyPublicGitHubRepositoryRefResponse } from \"@opengeni/contracts/github-repository-contracts\";\nimport {\n parseCanonicalGitHubRepositoryUrl,\n type CanonicalGitHubRepository,\n} from \"@opengeni/contracts/github-repository\";\nimport { readResponseTextBounded } from \"@opengeni/network\";\nimport {\n createCipheriv,\n createDecipheriv,\n createHash,\n createHmac,\n createPrivateKey,\n randomBytes,\n timingSafeEqual,\n} from \"node:crypto\";\nimport { SignJWT, importPKCS8 } from \"jose\";\n\nconst githubApiBase = \"https://api.github.com\";\nconst githubApiVersion = \"2022-11-28\";\nconst githubTokenMintTimeoutMs = 60_000;\n/** Bound for the server-side repository-id lookup at turn start (mint + read). */\nexport const githubRepositoryLookupTimeoutMs = 10_000;\nexport const githubRepositoryBranchesTimeoutMs = 10_000;\nconst githubRepositoryBranchesResponseMaxBytes = 256 * 1024;\nexport const githubPublicRepositoryVerificationTimeoutMs = 10_000;\nconst githubPublicRepositoryVerificationResponseMaxBytes = 128 * 1024;\nconst githubInstallationTokenResponseMaxBytes = 64 * 1024;\nconst githubErrorResponseMaxBytes = 64 * 1024;\nconst githubErrorMessageMaxLength = 1024;\nexport const stateMaxAgeSeconds = 60 * 60;\nconst pkcs8PrivateKeyHeader = `-----BEGIN ${\"PRIVATE KEY\"}-----`;\nconst rsaPrivateKeyHeader = `-----BEGIN ${\"RSA PRIVATE KEY\"}-----`;\n\nconst PERSONAL_GITHUB_GIT_BROKER_TOKEN_PREFIX = \"oggh1\";\nconst PERSONAL_GITHUB_GIT_BROKER_KEY_CONTEXT = \"opengeni:personal-github:git-broker:v1\";\nexport const PERSONAL_GITHUB_GIT_BROKER_TOKEN_TTL_SECONDS = 5 * 60;\n\nexport type PersonalGitHubGitBrokerRepositoryClaim = {\n repositoryId: string;\n fullName: string;\n canonicalUrl: string;\n ref: string;\n access: \"read\" | \"write\";\n selectionGeneration: number;\n routeId: string;\n};\n\nexport type PersonalGitHubGitBrokerClaims = {\n version: 1;\n accountId: string;\n workspaceId: string;\n sessionId: string;\n rootSessionId: string;\n turnId: string;\n attemptId: string;\n executionGeneration: number;\n originWorkspaceId: string;\n connectionId: string;\n connectionAuthorityGeneration: number;\n ownerSubjectId: string;\n credentialBindingId: string;\n selectionGeneration: number;\n nonce: string;\n issuedAt: number;\n expiresAt: number;\n};\n\nexport function personalGitHubGitBrokerRouteId(\n secret: string,\n input: Omit<PersonalGitHubGitBrokerClaims, \"nonce\" | \"issuedAt\" | \"expiresAt\"> & {\n repository: Omit<PersonalGitHubGitBrokerRepositoryClaim, \"routeId\">;\n },\n): string {\n const hmac = createHmac(\"sha256\", personalGitHubGitBrokerKey(secret));\n for (const value of [\n String(input.version),\n input.accountId,\n input.workspaceId,\n input.sessionId,\n input.rootSessionId,\n input.turnId,\n input.attemptId,\n String(input.executionGeneration),\n input.originWorkspaceId,\n input.connectionId,\n String(input.connectionAuthorityGeneration),\n input.ownerSubjectId,\n input.credentialBindingId,\n String(input.selectionGeneration),\n input.repository.repositoryId,\n input.repository.fullName,\n input.repository.canonicalUrl,\n input.repository.ref,\n input.repository.access,\n String(input.repository.selectionGeneration),\n ]) {\n const bytes = Buffer.from(value, \"utf8\");\n hmac.update(Buffer.from(String(bytes.byteLength), \"ascii\"));\n hmac.update(\":\");\n hmac.update(bytes);\n hmac.update(\";\");\n }\n return hmac.digest(\"base64url\");\n}\n\n/**\n * Seal exact Git broker authority into a confidential, authenticated bearer.\n * The payload is encrypted rather than merely signed so tenant, session,\n * connection, and repository identities are not readable from the sandbox's\n * short-lived token file.\n */\nexport function sealPersonalGitHubGitBrokerClaims(\n secret: string,\n claims: PersonalGitHubGitBrokerClaims,\n): string {\n assertPersonalGitHubGitBrokerClaims(claims);\n const iv = randomBytes(12);\n const cipher = createCipheriv(\"aes-256-gcm\", personalGitHubGitBrokerKey(secret), iv);\n cipher.setAAD(Buffer.from(PERSONAL_GITHUB_GIT_BROKER_TOKEN_PREFIX, \"ascii\"));\n const ciphertext = Buffer.concat([cipher.update(JSON.stringify(claims), \"utf8\"), cipher.final()]);\n return [\n PERSONAL_GITHUB_GIT_BROKER_TOKEN_PREFIX,\n iv.toString(\"base64url\"),\n ciphertext.toString(\"base64url\"),\n cipher.getAuthTag().toString(\"base64url\"),\n ].join(\".\");\n}\n\nexport function openPersonalGitHubGitBrokerClaims(\n secret: string,\n token: string,\n nowSeconds = Math.floor(Date.now() / 1_000),\n): PersonalGitHubGitBrokerClaims | null {\n const [prefix, encodedIv, encodedCiphertext, encodedTag, extra] = token.split(\".\");\n if (\n prefix !== PERSONAL_GITHUB_GIT_BROKER_TOKEN_PREFIX ||\n !encodedIv ||\n !encodedCiphertext ||\n !encodedTag ||\n extra !== undefined\n ) {\n return null;\n }\n try {\n const iv = Buffer.from(encodedIv, \"base64url\");\n const ciphertext = Buffer.from(encodedCiphertext, \"base64url\");\n const tag = Buffer.from(encodedTag, \"base64url\");\n if (iv.byteLength !== 12 || tag.byteLength !== 16 || ciphertext.byteLength > 4_096) {\n return null;\n }\n const decipher = createDecipheriv(\"aes-256-gcm\", personalGitHubGitBrokerKey(secret), iv);\n decipher.setAAD(Buffer.from(PERSONAL_GITHUB_GIT_BROKER_TOKEN_PREFIX, \"ascii\"));\n decipher.setAuthTag(tag);\n const payload = JSON.parse(\n Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString(\"utf8\"),\n ) as unknown;\n assertPersonalGitHubGitBrokerClaims(payload);\n if (payload.issuedAt > nowSeconds + 60 || nowSeconds >= payload.expiresAt) return null;\n if (payload.expiresAt - payload.issuedAt > PERSONAL_GITHUB_GIT_BROKER_TOKEN_TTL_SECONDS) {\n return null;\n }\n return payload;\n } catch {\n return null;\n }\n}\n\nfunction personalGitHubGitBrokerKey(secret: string): Buffer {\n const normalized = secret.trim();\n if (!normalized) throw new Error(\"personal GitHub Git broker signing secret is unavailable\");\n return createHash(\"sha256\")\n .update(PERSONAL_GITHUB_GIT_BROKER_KEY_CONTEXT, \"utf8\")\n .update(\"\\0\", \"utf8\")\n .update(normalized, \"utf8\")\n .digest();\n}\n\nfunction assertPersonalGitHubGitBrokerClaims(\n value: unknown,\n): asserts value is PersonalGitHubGitBrokerClaims {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\"invalid personal GitHub Git broker claims\");\n }\n const claims = value as Record<string, unknown>;\n const expectedKeys = new Set([\n \"version\",\n \"accountId\",\n \"workspaceId\",\n \"sessionId\",\n \"rootSessionId\",\n \"turnId\",\n \"attemptId\",\n \"executionGeneration\",\n \"originWorkspaceId\",\n \"connectionId\",\n \"connectionAuthorityGeneration\",\n \"ownerSubjectId\",\n \"credentialBindingId\",\n \"selectionGeneration\",\n \"nonce\",\n \"issuedAt\",\n \"expiresAt\",\n ]);\n const strings = [\n \"accountId\",\n \"workspaceId\",\n \"sessionId\",\n \"rootSessionId\",\n \"turnId\",\n \"attemptId\",\n \"originWorkspaceId\",\n \"connectionId\",\n \"ownerSubjectId\",\n \"credentialBindingId\",\n \"nonce\",\n ];\n if (\n claims.version !== 1 ||\n strings.some(\n (field) =>\n typeof claims[field] !== \"string\" ||\n claims[field].length === 0 ||\n claims[field].length > (field === \"ownerSubjectId\" ? 512 : 128),\n ) ||\n !positiveIntegerClaim(claims.executionGeneration) ||\n !positiveIntegerClaim(claims.connectionAuthorityGeneration) ||\n !positiveIntegerClaim(claims.selectionGeneration) ||\n !positiveIntegerClaim(claims.issuedAt) ||\n !positiveIntegerClaim(claims.expiresAt) ||\n Object.keys(claims).some((key) => !expectedKeys.has(key))\n ) {\n throw new Error(\"invalid personal GitHub Git broker claims\");\n }\n}\n\nfunction positiveIntegerClaim(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value > 0;\n}\n\nexport class GitHubAppConfigurationError extends Error {\n constructor(readonly missing: string[]) {\n super(\"GitHub App is not configured\");\n }\n}\n\nexport class GitHubAppApiError extends Error {\n constructor(\n message: string,\n readonly status: number | null = null,\n ) {\n super(message);\n }\n}\n\nexport type GitHubPublicRepositoryVerificationErrorCode =\n | \"invalid_input\"\n | \"unavailable\"\n | \"provider_unavailable\";\n\nexport class GitHubPublicRepositoryVerificationError extends Error {\n constructor(\n readonly code: GitHubPublicRepositoryVerificationErrorCode,\n message: string,\n readonly status?: number,\n ) {\n super(message);\n this.name = \"GitHubPublicRepositoryVerificationError\";\n }\n}\n\nexport type GitHubInstallationAuthorityFailure =\n | \"authority_denied\"\n | \"authority_unavailable\"\n | \"installation_missing\"\n | \"installation_suspended\"\n | \"repository_access_empty\";\n\nexport class GitHubInstallationAuthorityError extends GitHubAppApiError {\n constructor(\n readonly reason: GitHubInstallationAuthorityFailure,\n message: string,\n status: number | null = null,\n ) {\n super(message, status);\n }\n}\n\nexport type GitHubAppInstallationSummary = {\n installationId: number;\n accountId: number;\n accountLogin: string | null;\n accountType: string | null;\n suspended: boolean;\n};\n\nexport type GitHubSignedStatePayload = {\n nonce: string;\n iat: number;\n accountId?: string;\n workspaceId?: string;\n [key: string]: unknown;\n};\n\nexport function githubAppMissingSettings(settings: Settings): string[] {\n const required: Record<string, string | undefined> = {\n OPENGENI_GITHUB_APP_ID: settings.githubAppId,\n OPENGENI_GITHUB_CLIENT_ID: settings.githubClientId,\n OPENGENI_GITHUB_CLIENT_SECRET: settings.githubClientSecret,\n OPENGENI_GITHUB_APP_SLUG: settings.githubAppSlug,\n OPENGENI_GITHUB_APP_PRIVATE_KEY: settings.githubAppPrivateKey,\n };\n return Object.entries(required).flatMap(([name, value]) => (value && value.trim() ? [] : [name]));\n}\n\nexport function prReviewGitHubAppMissingSettings(settings: Settings): string[] {\n const required: Record<string, string | undefined> = {\n OPENGENI_GITHUB_APP_MANIFEST_STATE_SECRET: settings.githubAppManifestStateSecret,\n OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY: settings.environmentsEncryptionKey,\n OPENGENI_PR_REVIEW_GITHUB_APP_ID: settings.prReviewGithubAppId,\n OPENGENI_PR_REVIEW_GITHUB_CLIENT_ID: settings.prReviewGithubClientId,\n OPENGENI_PR_REVIEW_GITHUB_CLIENT_SECRET: settings.prReviewGithubClientSecret,\n OPENGENI_PR_REVIEW_GITHUB_APP_SLUG: settings.prReviewGithubAppSlug,\n OPENGENI_PR_REVIEW_GITHUB_WEBHOOK_SECRET: settings.prReviewGithubWebhookSecret,\n OPENGENI_PR_REVIEW_GITHUB_APP_PRIVATE_KEY: settings.prReviewGithubAppPrivateKey,\n };\n return Object.entries(required).flatMap(([name, value]) => (value && value.trim() ? [] : [name]));\n}\n\n/** Project the separately configured review App onto the ordinary GitHub App\n * authority client. This keeps its OAuth, signing, webhook, and installation\n * identity disjoint from the platform GitHub App while reusing the same\n * personal-owner / organization-owner proof implementation. */\nexport function settingsForPrReviewGitHubApp(settings: Settings): Settings {\n return {\n ...settings,\n githubAppId: settings.prReviewGithubAppId,\n githubClientId: settings.prReviewGithubClientId,\n githubClientSecret: settings.prReviewGithubClientSecret,\n githubAppSlug: settings.prReviewGithubAppSlug,\n githubWebhookSecret: settings.prReviewGithubWebhookSecret,\n githubAppPrivateKey: settings.prReviewGithubAppPrivateKey,\n };\n}\n\nexport type GitHubAppSigningSettings = Pick<Settings, \"githubAppId\" | \"githubAppPrivateKey\">;\n\nfunction githubAppTokenMissingSettings(settings: GitHubAppSigningSettings): string[] {\n const required: Record<string, string | undefined> = {\n OPENGENI_GITHUB_APP_ID: settings.githubAppId,\n OPENGENI_GITHUB_APP_PRIVATE_KEY: settings.githubAppPrivateKey,\n };\n return Object.entries(required).flatMap(([name, value]) => (value && value.trim() ? [] : [name]));\n}\n\nexport function buildGitHubAppManifest(input: {\n appName: string;\n baseUrl: string;\n public: boolean;\n includeCiPermissions: boolean;\n setupUrl?: string;\n}): Record<string, unknown> {\n const base = input.baseUrl.replace(/\\/+$/, \"\");\n const permissions: Record<string, string> = {\n metadata: \"read\",\n contents: \"write\",\n pull_requests: \"write\",\n // Required for the authenticated-user membership endpoint that proves an\n // active organization owner. Existing installations must approve this\n // permission before organization-owner self-service can succeed.\n members: \"read\",\n };\n if (input.includeCiPermissions) {\n permissions.actions = \"read\";\n permissions.checks = \"read\";\n permissions.statuses = \"write\";\n }\n const manifest: Record<string, unknown> = {\n name: input.appName,\n url: base,\n redirect_url: `${base}/v1/github/app-manifest/callback`,\n callback_urls: [`${base}/v1/github/oauth/callback`],\n public: input.public,\n // A setup URL and OAuth-on-install are mutually exclusive in GitHub's App\n // contract. OpenGeni needs the setup callback to receive the installation\n // id, then starts its own exact user-authorization flow.\n request_oauth_on_install: !input.setupUrl,\n default_permissions: permissions,\n };\n if (input.setupUrl) {\n manifest.setup_url = input.setupUrl;\n manifest.setup_on_update = true;\n }\n return manifest;\n}\n\nexport function personalAppManifestUrl(state: string): string {\n return `https://github.com/settings/apps/new?state=${state}`;\n}\n\nexport function organizationAppManifestUrl(organization: string, state: string): string {\n return `https://github.com/organizations/${encodeURIComponent(organization)}/settings/apps/new?state=${state}`;\n}\n\nexport function githubOAuthAuthorizeUrl(input: {\n clientId: string;\n state: string;\n redirectUri?: string;\n}): string {\n const url = new URL(\"https://github.com/login/oauth/authorize\");\n url.searchParams.set(\"client_id\", input.clientId);\n url.searchParams.set(\"state\", input.state);\n if (input.redirectUri) {\n url.searchParams.set(\"redirect_uri\", input.redirectUri);\n }\n return url.toString();\n}\n\nexport function createSignedState(\n secret: string,\n payloadOrNow: Record<string, unknown> | number = {},\n nowArg = Math.floor(Date.now() / 1000),\n): string {\n const payloadInput = typeof payloadOrNow === \"number\" ? {} : payloadOrNow;\n const now = typeof payloadOrNow === \"number\" ? payloadOrNow : nowArg;\n const payload = {\n ...payloadInput,\n nonce: randomBytes(16).toString(\"base64url\"),\n iat: now,\n };\n const encoded = Buffer.from(JSON.stringify(payload)).toString(\"base64url\");\n return `${encoded}.${signStatePayload(encoded, secret)}`;\n}\n\nexport function readSignedState(\n state: string,\n secret: string,\n now = Math.floor(Date.now() / 1000),\n): GitHubSignedStatePayload | null {\n const payload = inspectSignedState(state, secret);\n if (!payload) return null;\n const age = now - payload.iat;\n return age >= 0 && age <= stateMaxAgeSeconds ? payload : null;\n}\n\n/**\n * Verifies a signed state's signature and shape without its age limit.\n *\n * Only for explaining a failed callback (for example \"this link expired\" and\n * which workspace page to return to). An aged payload is never authority: every\n * authorizing read uses {@link readSignedState} or its own stricter lifetime.\n */\nexport function inspectSignedState(state: string, secret: string): GitHubSignedStatePayload | null {\n const [encoded, signature] = state.split(\".\", 2);\n if (!encoded || !signature) {\n return null;\n }\n const expected = signStatePayload(encoded, secret);\n if (!safeEqual(signature, expected)) {\n return null;\n }\n let payload: unknown;\n try {\n payload = JSON.parse(Buffer.from(encoded, \"base64url\").toString(\"utf8\"));\n } catch {\n return null;\n }\n if (\n !payload ||\n typeof payload !== \"object\" ||\n typeof (payload as { iat?: unknown }).iat !== \"number\" ||\n typeof (payload as { nonce?: unknown }).nonce !== \"string\"\n ) {\n return null;\n }\n return payload as GitHubSignedStatePayload;\n}\n\nexport function verifySignedState(\n state: string,\n secret: string,\n now = Math.floor(Date.now() / 1000),\n): boolean {\n return readSignedState(state, secret, now) !== null;\n}\n\nexport function envLinesFromGitHubManifestConversion(payload: Record<string, unknown>): string[] {\n const privateKey = String(payload.pem ?? \"\").replace(/\\n/g, \"\\\\n\");\n return [\n `OPENGENI_GITHUB_APP_ID=${payload.id ?? \"\"}`,\n `OPENGENI_GITHUB_CLIENT_ID=${payload.client_id ?? \"\"}`,\n `OPENGENI_GITHUB_CLIENT_SECRET=${payload.client_secret ?? \"\"}`,\n `OPENGENI_GITHUB_APP_SLUG=${payload.slug ?? \"\"}`,\n `OPENGENI_GITHUB_WEBHOOK_SECRET=${payload.webhook_secret ?? \"\"}`,\n `OPENGENI_GITHUB_APP_PRIVATE_KEY=\"${privateKey}\"`,\n ];\n}\n\nexport async function convertGitHubAppManifest(code: string): Promise<Record<string, unknown>> {\n const response = await fetch(`${githubApiBase}/app-manifests/${code}/conversions`, {\n method: \"POST\",\n headers: githubHeaders(undefined),\n });\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response));\n }\n const payload = await response.json();\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new GitHubAppApiError(\"GitHub returned an invalid manifest conversion payload\");\n }\n return payload as Record<string, unknown>;\n}\n\nexport async function listGitHubAppInstallationSummaries(\n settings: Settings,\n): Promise<GitHubAppInstallationSummary[]> {\n const missing = githubAppMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n const jwt = await createGitHubAppJwt(settings);\n const installations = await listInstallations(jwt);\n return installations.map(installationSummaryFromPayload);\n}\n\nexport async function getGitHubAppInstallationSummary(\n settings: Settings,\n installationId: number,\n): Promise<GitHubAppInstallationSummary | null> {\n const installations = await listGitHubAppInstallationSummaries(settings);\n return (\n installations.find((installation) => installation.installationId === installationId) ?? null\n );\n}\n\nexport async function verifyGitHubInstallationAccessForUser(\n settings: Settings,\n input: {\n code: string;\n installationId: number;\n },\n): Promise<GitHubAppInstallationSummary> {\n const token = await exchangeGitHubOAuthCodeForUserToken(settings, input.code);\n const installations = await listUserAccessibleInstallations(token);\n const installation = installations.find(\n (candidate) => candidate.installationId === input.installationId,\n );\n if (!installation) {\n throw new GitHubAppApiError(\"GitHub installation is not accessible to the installing user\");\n }\n return installation;\n}\n\n/**\n * Exchange a GitHub App user-authorization code and discover the installations\n * and repositories the user can explicitly access. This is compatibility\n * discovery metadata only: visibility and repository permission bits do not\n * prove that the human may install, configure, or bind the App installation.\n * No production binding path may treat this result as authority.\n */\nexport async function authorizeGitHubAppUser(\n settings: Settings,\n input: { code: string },\n): Promise<GitHubUserInstallationAccess[]> {\n const token = await exchangeGitHubOAuthCodeForUserToken(settings, input.code);\n const installations = await listUserAccessibleInstallations(token);\n return await Promise.all(\n installations.map(async (installation) => ({\n ...installation,\n repositories: installation.suspended\n ? []\n : await listUserInstallationRepositories(token, installation),\n })),\n );\n}\n\n/**\n * Prove current GitHub installation authority without treating repository\n * administration or installation visibility as delegation authority.\n *\n * GitHub exposes an exact personal-account owner through the authenticated\n * user's immutable id. For organizations, GitHub's authenticated membership\n * endpoint exposes active owners as role=admin. GitHub does not expose an\n * equivalent current-authority receipt for App Managers, so that case remains\n * unsupported and fails closed.\n */\nexport async function authorizeGitHubInstallationBinding(\n settings: Settings,\n input: { code: string; installationId: number },\n): Promise<GitHubInstallationBindingProof> {\n const userToken = await exchangeGitHubOAuthCodeForUserToken(settings, input.code);\n const actor = await getAuthenticatedGitHubUser(userToken);\n const visibleInstallations = await listUserAccessibleInstallations(userToken);\n const visible = visibleInstallations.find(\n (installation) => installation.installationId === input.installationId,\n );\n if (!visible) {\n throw new GitHubInstallationAuthorityError(\n \"authority_denied\",\n \"GitHub did not associate this installation with the authorized user\",\n );\n }\n\n const jwt = await createGitHubAppJwt(settings);\n const livePayload = (await listInstallations(jwt)).find(\n (installation) => asInt(installation.id) === input.installationId,\n );\n if (!livePayload) {\n throw new GitHubInstallationAuthorityError(\n \"installation_missing\",\n \"GitHub App installation was deleted or is not owned by this App\",\n );\n }\n const installation = installationSummaryFromPayload(livePayload);\n if (\n installation.accountId !== visible.accountId ||\n installation.accountLogin !== visible.accountLogin ||\n installation.accountType !== visible.accountType\n ) {\n throw new GitHubInstallationAuthorityError(\n \"authority_denied\",\n \"GitHub installation identity changed during authorization\",\n );\n }\n if (installation.suspended) {\n throw new GitHubInstallationAuthorityError(\n \"installation_suspended\",\n \"GitHub App installation is suspended\",\n );\n }\n\n let authorityKind: GitHubInstallationBindingProof[\"authorityKind\"];\n if (installation.accountType === \"User\" && actor.id === installation.accountId) {\n authorityKind = \"personal_owner\";\n } else if (installation.accountType === \"Organization\" && installation.accountLogin) {\n await assertActiveOrganizationOwner(\n userToken,\n installation.accountId,\n installation.accountLogin,\n );\n authorityKind = \"organization_owner\";\n } else {\n throw new GitHubInstallationAuthorityError(\n \"authority_denied\",\n \"Only a GitHub personal-account owner or organization owner may bind an installation\",\n );\n }\n\n const installationToken = await createInstallationToken(jwt, {\n installationId: installation.installationId,\n });\n const repositories = await listInstallationRepositories(\n installationToken.token,\n installation.installationId,\n { login: installation.accountLogin, type: installation.accountType },\n );\n if (repositories.length === 0) {\n throw new GitHubInstallationAuthorityError(\n \"repository_access_empty\",\n \"GitHub App installation does not currently grant access to any repositories\",\n );\n }\n if (authorityKind === \"organization_owner\") {\n // Repository enumeration is an async provider boundary. Re-read the live\n // owner tuple after it so a role revoked after the chooser proof cannot be\n // durably bound with a later, misleading authority timestamp.\n await assertActiveOrganizationOwner(\n userToken,\n installation.accountId,\n installation.accountLogin!,\n );\n }\n return {\n actorId: actor.id,\n actorLogin: actor.login,\n authorityKind,\n installation,\n repositories,\n };\n}\n\n/**\n * Discover existing installations that the freshly authorized GitHub human\n * can bind as an exact personal owner or active organization owner.\n *\n * `GET /user/installations` is discovery input only. Every candidate is\n * cross-checked against the App's live installation inventory and an\n * organization candidate requires a live `state=active, role=admin`\n * membership proof. The later exact authorization still re-runs the complete\n * proof immediately before the durable bind.\n */\nexport async function discoverGitHubInstallationBindingCandidates(\n settings: Settings,\n input: { code: string },\n): Promise<GitHubInstallationBindingCandidate[]> {\n const userToken = await exchangeGitHubOAuthCodeForUserToken(settings, input.code);\n const actor = await getAuthenticatedGitHubUser(userToken);\n const visibleInstallations = await listUserAccessibleInstallations(userToken);\n const jwt = await createGitHubAppJwt(settings);\n const liveInstallations = new Map(\n (await listInstallations(jwt)).map((payload) => {\n const installation = installationSummaryFromPayload(payload);\n return [installation.installationId, installation] as const;\n }),\n );\n const candidates: GitHubInstallationBindingCandidate[] = [];\n\n for (const visible of visibleInstallations) {\n const installation = liveInstallations.get(visible.installationId);\n if (\n !installation ||\n installation.suspended ||\n installation.accountId !== visible.accountId ||\n installation.accountLogin !== visible.accountLogin ||\n installation.accountType !== visible.accountType\n ) {\n continue;\n }\n if (installation.accountType === \"User\" && actor.id === installation.accountId) {\n candidates.push({ installation, authorityKind: \"personal_owner\" });\n continue;\n }\n if (installation.accountType !== \"Organization\" || !installation.accountLogin) {\n continue;\n }\n try {\n await assertActiveOrganizationOwner(\n userToken,\n installation.accountId,\n installation.accountLogin,\n );\n candidates.push({ installation, authorityKind: \"organization_owner\" });\n } catch (error) {\n if (\n error instanceof GitHubInstallationAuthorityError &&\n error.reason === \"authority_unavailable\"\n ) {\n continue;\n }\n if (\n error instanceof GitHubInstallationAuthorityError &&\n error.reason === \"authority_denied\"\n ) {\n continue;\n }\n throw error;\n }\n }\n\n return candidates.sort((left, right) =>\n (left.installation.accountLogin ?? \"\").localeCompare(right.installation.accountLogin ?? \"\"),\n );\n}\n\nexport async function listGitHubAppRepositories(\n settings: Settings,\n input: {\n installationIds?: number[];\n } = {},\n): Promise<GitHubRepository[]> {\n const missing = githubAppMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n return await listGitHubAppRepositoriesWithSigningSettings(settings, input);\n}\n\n/** List repositories for a separately registered App that needs only signing credentials. */\nexport async function listGitHubAppRepositoriesWithSigningSettings(\n settings: GitHubAppSigningSettings,\n input: {\n installationIds?: number[];\n } = {},\n): Promise<GitHubRepository[]> {\n const missing = githubAppTokenMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n const allowedInstallations = input.installationIds ? new Set(input.installationIds) : null;\n if (allowedInstallations && allowedInstallations.size === 0) {\n return [];\n }\n const jwt = await createGitHubAppJwt(settings);\n const installations = await listInstallations(jwt);\n const repositories: GitHubRepository[] = [];\n for (const installation of installations) {\n if (installation.suspended_at) {\n continue;\n }\n const installationId = asInt(installation.id);\n if (installationId === null) {\n continue;\n }\n if (allowedInstallations && !allowedInstallations.has(installationId)) {\n continue;\n }\n const account =\n typeof installation.account === \"object\" && installation.account\n ? (installation.account as Record<string, unknown>)\n : {};\n const token = await createInstallationToken(jwt, { installationId });\n repositories.push(\n ...(await listInstallationRepositories(token.token, installationId, account)),\n );\n }\n repositories.sort((left, right) => left.fullName.localeCompare(right.fullName));\n return repositories;\n}\n\nexport type GitHubAppInstallationRepositoryLookupInput = {\n installationId: number;\n owner: string;\n name: string;\n};\n\nexport type GitHubAppInstallationRepositoryLookup = (\n input: GitHubAppInstallationRepositoryLookupInput,\n) => Promise<GitHubRepository | null>;\n\n/**\n * Resolve one `owner/name` repository through an exact App installation and\n * return GitHub's stable repository identity, or null when that installation\n * cannot see the repository. The server-side lookup token never leaves the\n * caller and grants nothing by itself: the workspace allowlist decides whether\n * the returned id may mint a sandbox-bound token.\n */\nexport async function getGitHubAppInstallationRepository(\n settings: Settings,\n input: GitHubAppInstallationRepositoryLookupInput,\n): Promise<GitHubRepository | null> {\n return await createGitHubAppInstallationRepositoryLookup(settings)(input);\n}\n\n/**\n * One lookup client that reuses a server-side installation token per\n * installation for its lifetime (one worker turn), so several bare repository\n * URIs from the same installation cost one mint plus one read each.\n */\nexport function createGitHubAppInstallationRepositoryLookup(\n settings: Settings,\n): GitHubAppInstallationRepositoryLookup {\n const missing = githubAppMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n const tokens = new Map<number, Promise<GitHubAppInstallationToken>>();\n const installationToken = (installationId: number): Promise<GitHubAppInstallationToken> => {\n let pending = tokens.get(installationId);\n if (!pending) {\n // Metadata-read only: the lookup needs the repository id, never contents.\n // Bounded well below the sandbox mint timeout so a slow GitHub cannot\n // hold turn start; the caller proceeds bare on expiry.\n pending = createGitHubAppJwt(settings).then((jwt) =>\n createInstallationToken(jwt, {\n installationId,\n permissions: { metadata: \"read\" },\n timeoutMs: githubRepositoryLookupTimeoutMs,\n }),\n );\n pending.catch(() => tokens.delete(installationId));\n tokens.set(installationId, pending);\n }\n return pending;\n };\n return async (input) => {\n const owner = input.owner.trim();\n const name = input.name.trim();\n if (\n !/^[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?$/u.test(owner) ||\n !/^[A-Za-z0-9._-]+$/u.test(name)\n ) {\n return null;\n }\n const token = await installationToken(input.installationId);\n const response = await fetch(\n `${githubApiBase}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}`,\n {\n headers: githubHeaders(token.token),\n signal: AbortSignal.timeout(githubRepositoryLookupTimeoutMs),\n },\n );\n if (response.status === 404) {\n return null;\n }\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response), response.status);\n }\n const payload = await response.json();\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repository payload\");\n }\n const record = payload as Record<string, unknown>;\n const account =\n record.owner && typeof record.owner === \"object\" && !Array.isArray(record.owner)\n ? (record.owner as Record<string, unknown>)\n : {};\n return repositoryFromPayload(record, input.installationId, account);\n };\n}\n\n/**\n * List one bounded page of branch suggestions with an exact repository-scoped\n * installation token. The token remains local to this server-side helper and\n * is never returned in repository or branch metadata.\n */\nexport async function listGitHubAppRepositoryBranches(\n settings: Settings,\n input: {\n installationId: number;\n repositoryId: number;\n page: number;\n limit: number;\n },\n): Promise<GitHubAppRepositoryBranchPage> {\n if (\n !Number.isSafeInteger(input.installationId) ||\n input.installationId <= 0 ||\n !Number.isSafeInteger(input.repositoryId) ||\n input.repositoryId <= 0 ||\n !Number.isSafeInteger(input.page) ||\n input.page <= 0 ||\n input.page > 10_000 ||\n !Number.isSafeInteger(input.limit) ||\n input.limit <= 0 ||\n input.limit > 100\n ) {\n throw new GitHubAppApiError(\"GitHub branch lookup requires bounded exact repository input\");\n }\n const minted = await createGitHubAppInstallationTokenWithSigningSettings(settings, {\n installationId: input.installationId,\n repositoryIds: [input.repositoryId],\n permissions: { contents: \"read\", metadata: \"read\" },\n timeoutMs: githubRepositoryBranchesTimeoutMs,\n });\n const repositoryResponse = await githubRepositoryBranchesFetch(\n new URL(`${githubApiBase}/repositories/${input.repositoryId}`),\n minted.token,\n \"GitHub repository branch identity\",\n );\n const repositoryPayload = await githubResponseJsonBounded(\n repositoryResponse,\n \"GitHub repository branch identity response\",\n );\n if (\n !repositoryPayload ||\n typeof repositoryPayload !== \"object\" ||\n Array.isArray(repositoryPayload)\n ) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repository branch identity payload\");\n }\n const repository = repositoryPayload as Record<string, unknown>;\n const repositoryId = asInt(repository.id);\n const fullName = typeof repository.full_name === \"string\" ? repository.full_name : \"\";\n const defaultBranch =\n typeof repository.default_branch === \"string\" ? repository.default_branch : \"\";\n const coordinates = fullName.split(\"/\");\n if (\n repositoryId !== input.repositoryId ||\n coordinates.length !== 2 ||\n !coordinates[0] ||\n !coordinates[1] ||\n defaultBranch.length === 0 ||\n defaultBranch.length > 1024\n ) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repository branch identity payload\");\n }\n const branchUrl = new URL(\n `${githubApiBase}/repos/${encodeURIComponent(coordinates[0])}/${encodeURIComponent(coordinates[1])}/branches`,\n );\n branchUrl.searchParams.set(\"page\", String(input.page));\n branchUrl.searchParams.set(\"per_page\", String(input.limit));\n const branchesResponse = await githubRepositoryBranchesFetch(\n branchUrl,\n minted.token,\n \"GitHub repository branches\",\n );\n const branchPayload = await githubResponseJsonBounded(\n branchesResponse,\n \"GitHub repository branches response\",\n );\n if (!Array.isArray(branchPayload) || branchPayload.length > input.limit) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repository branches payload\");\n }\n const branches: string[] = [];\n const seen = new Set<string>();\n for (const value of branchPayload) {\n const name =\n value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>).name\n : null;\n if (typeof name !== \"string\" || name.length === 0 || name.length > 1024 || seen.has(name)) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repository branches payload\");\n }\n seen.add(name);\n branches.push(name);\n }\n return {\n installationId: input.installationId,\n repositoryId: input.repositoryId,\n defaultBranch,\n branches,\n nextPage: branchPayload.length === input.limit && input.page < 10_000 ? input.page + 1 : null,\n };\n}\n\n/**\n * Verify one exact anonymous github.com repository and ref. The provider URL\n * is derived only from strict canonical coordinates, follows no redirects,\n * sends no credentials, and bounds both request time and response bytes.\n */\nexport async function verifyPublicGitHubRepositoryRef(\n input: { repository: CanonicalGitHubRepository; ref: string },\n fetchImpl: typeof fetch = fetch,\n): Promise<VerifyPublicGitHubRepositoryRefResponse> {\n const ref = input.ref.trim();\n if (!ref || ref.length > 1024 || /[\\u0000-\\u001f\\u007f]/u.test(ref)) {\n throw new GitHubPublicRepositoryVerificationError(\n \"invalid_input\",\n \"Enter a branch, tag, or commit SHA.\",\n );\n }\n const repositoryUrl = new URL(\n `${githubApiBase}/repos/${encodeURIComponent(input.repository.owner)}/${encodeURIComponent(input.repository.name)}`,\n );\n const repositoryPayload = await anonymousGitHubJson(\n fetchImpl,\n repositoryUrl,\n \"GitHub repository\",\n );\n if (\n !repositoryPayload ||\n typeof repositoryPayload !== \"object\" ||\n Array.isArray(repositoryPayload)\n ) {\n throw new GitHubPublicRepositoryVerificationError(\n \"provider_unavailable\",\n \"GitHub returned an invalid repository response.\",\n );\n }\n const repository = repositoryPayload as Record<string, unknown>;\n const fullName = typeof repository.full_name === \"string\" ? repository.full_name : \"\";\n const defaultBranch =\n typeof repository.default_branch === \"string\" ? repository.default_branch : \"\";\n const privateRepository = repository.private;\n if (\n !Number.isSafeInteger(repository.id) ||\n Number(repository.id) <= 0 ||\n privateRepository !== false ||\n !fullName ||\n fullName.toLowerCase() !== input.repository.fullName.toLowerCase() ||\n !defaultBranch ||\n defaultBranch.length > 1024\n ) {\n throw new GitHubPublicRepositoryVerificationError(\n \"unavailable\",\n \"That GitHub repository is private or unavailable.\",\n );\n }\n let canonical: CanonicalGitHubRepository;\n try {\n canonical = parseCanonicalGitHubRepositoryUrl(`https://github.com/${fullName}`);\n } catch {\n throw new GitHubPublicRepositoryVerificationError(\n \"provider_unavailable\",\n \"GitHub returned an invalid repository identity.\",\n );\n }\n const commitUrl = new URL(\n `${githubApiBase}/repos/${encodeURIComponent(canonical.owner)}/${encodeURIComponent(canonical.name)}/commits/${encodeURIComponent(ref)}`,\n );\n const commitPayload = await anonymousGitHubJson(fetchImpl, commitUrl, \"GitHub repository ref\");\n const commitSha =\n commitPayload && typeof commitPayload === \"object\" && !Array.isArray(commitPayload)\n ? (commitPayload as Record<string, unknown>).sha\n : null;\n if (typeof commitSha !== \"string\" || !/^[0-9a-f]{40}$/u.test(commitSha)) {\n throw new GitHubPublicRepositoryVerificationError(\n \"unavailable\",\n \"That branch, tag, or commit SHA is not available on the public repository.\",\n );\n }\n return {\n ...canonical,\n defaultBranch,\n ref,\n commitSha,\n };\n}\n\nexport async function createGitHubAppInstallationToken(\n settings: Settings,\n input: {\n installationId: number;\n repositoryIds: number[];\n },\n): Promise<string> {\n return (await createGitHubAppInstallationTokenWithExpiry(settings, input)).token;\n}\n\nexport type GitHubAppInstallationToken = {\n token: string;\n expiresAt: string | null;\n};\n\nexport async function createGitHubAppInstallationTokenWithExpiry(\n settings: Settings,\n input: {\n installationId: number;\n repositoryIds: number[];\n },\n): Promise<GitHubAppInstallationToken> {\n const missing = githubAppMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n return await createGitHubAppInstallationTokenWithSigningSettings(settings, input);\n}\n\n/** Mint for a separately registered App without requiring unrelated OAuth settings. */\nexport async function createGitHubAppInstallationTokenWithSigningSettings(\n settings: GitHubAppSigningSettings,\n input: {\n installationId: number;\n repositoryIds: number[];\n permissions?: Record<string, \"read\" | \"write\">;\n timeoutMs?: number;\n },\n): Promise<GitHubAppInstallationToken> {\n const missing = githubAppTokenMissingSettings(settings);\n if (missing.length > 0) {\n throw new GitHubAppConfigurationError(missing);\n }\n if (!Array.isArray(input.repositoryIds)) {\n throw new GitHubAppApiError(\n \"GitHub installation token mint requires an explicit, unique repository allowlist\",\n );\n }\n const repositoryIds = [...new Set(input.repositoryIds)];\n if (\n !Number.isSafeInteger(input.installationId) ||\n input.installationId <= 0 ||\n repositoryIds.length === 0 ||\n repositoryIds.length !== input.repositoryIds.length ||\n repositoryIds.some((id) => !Number.isSafeInteger(id) || id <= 0)\n ) {\n throw new GitHubAppApiError(\n \"GitHub installation token mint requires an explicit, unique repository allowlist\",\n );\n }\n const jwt = await createGitHubAppJwt(settings);\n return await createInstallationToken(jwt, {\n installationId: input.installationId,\n repositoryIds,\n ...(input.permissions ? { permissions: input.permissions } : {}),\n ...(input.timeoutMs !== undefined ? { timeoutMs: input.timeoutMs } : {}),\n });\n}\n\nexport function githubAppBotIdentity(settings: Settings): { name: string; email: string } | null {\n const appId = settings.githubAppId?.trim();\n const slug = settings.githubAppSlug?.trim();\n if (!appId || !slug) {\n return null;\n }\n const login = `${slug}[bot]`;\n return {\n name: login,\n email: `${appId}+${login}@users.noreply.github.com`,\n };\n}\n\nexport const GITHUB_APP_BOT_IDENTITY_UNAVAILABLE_WARNING =\n \"github_app_bot_identity_unavailable\" as const;\n\n/**\n * Non-secret health posture for the stable sandbox Git identity. API-direct\n * attach and worker-turn startup must add the same identity keys. A complete\n * deployment-level author identity is sufficient because committer values\n * default to it; otherwise a partially configured workspace GitHub App must\n * surface that its bot identity cannot be derived.\n */\nexport function githubAppBotIdentityWarnings(\n settings: Settings,\n): Array<typeof GITHUB_APP_BOT_IDENTITY_UNAVAILABLE_WARNING> {\n const workspaceAppConfigured = [\n settings.githubAppId,\n settings.githubClientId,\n settings.githubClientSecret,\n settings.githubAppSlug,\n settings.githubWebhookSecret,\n settings.githubAppPrivateKey,\n ].some((value) => typeof value === \"string\" && value.trim().length > 0);\n const explicitGitIdentityConfigured =\n typeof settings.gitAuthorName === \"string\" &&\n settings.gitAuthorName.trim().length > 0 &&\n typeof settings.gitAuthorEmail === \"string\" &&\n settings.gitAuthorEmail.trim().length > 0;\n if (\n !workspaceAppConfigured ||\n explicitGitIdentityConfigured ||\n githubAppBotIdentity(settings) !== null\n ) {\n return [];\n }\n return [GITHUB_APP_BOT_IDENTITY_UNAVAILABLE_WARNING];\n}\n\nasync function createGitHubAppJwt(settings: GitHubAppSigningSettings): Promise<string> {\n const privateKey = normalizeGitHubAppPrivateKey(settings.githubAppPrivateKey ?? \"\");\n const appId = settings.githubAppId?.trim();\n if (!appId || !privateKey) {\n throw new GitHubAppConfigurationError(githubAppTokenMissingSettings(settings));\n }\n const key = await importPKCS8(privateKey, \"RS256\");\n const now = Math.floor(Date.now() / 1000);\n return await new SignJWT({})\n .setProtectedHeader({ alg: \"RS256\" })\n .setIssuedAt(now - 60)\n .setExpirationTime(now + 9 * 60)\n .setIssuer(appId)\n .sign(key);\n}\n\nasync function listInstallations(token: string): Promise<Array<Record<string, unknown>>> {\n const out: Array<Record<string, unknown>> = [];\n for (let page = 1; ; page += 1) {\n const payload = await githubGet(\"/app/installations\", token, {\n per_page: \"100\",\n page: String(page),\n });\n if (!Array.isArray(payload)) {\n throw new GitHubAppApiError(\"GitHub returned an invalid installations payload\");\n }\n out.push(\n ...payload.filter((item): item is Record<string, unknown> =>\n Boolean(item && typeof item === \"object\" && !Array.isArray(item)),\n ),\n );\n if (payload.length < 100) {\n return out;\n }\n }\n}\n\nasync function exchangeGitHubOAuthCodeForUserToken(\n settings: Settings,\n code: string,\n): Promise<string> {\n if (!settings.githubClientId || !settings.githubClientSecret) {\n throw new GitHubAppConfigurationError(githubAppMissingSettings(settings));\n }\n const response = await fetch(\"https://github.com/login/oauth/access_token\", {\n method: \"POST\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n client_id: settings.githubClientId,\n client_secret: settings.githubClientSecret,\n code,\n }),\n });\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response));\n }\n const payload = await response.json();\n if (!payload || typeof payload !== \"object\" || typeof payload.access_token !== \"string\") {\n throw new GitHubAppApiError(\"GitHub returned an invalid OAuth token payload\");\n }\n return payload.access_token;\n}\n\nasync function getAuthenticatedGitHubUser(token: string): Promise<{ id: number; login: string }> {\n const payload = await githubGet(\"/user\", token);\n const id = payload && typeof payload === \"object\" ? asInt(payload.id) : null;\n const login =\n payload && typeof payload === \"object\" && typeof payload.login === \"string\"\n ? payload.login\n : null;\n if (id === null || !login) {\n throw new GitHubAppApiError(\"GitHub returned an invalid authenticated user payload\");\n }\n return { id, login };\n}\n\nasync function getAuthenticatedOrganizationMembership(\n token: string,\n organizationLogin: string,\n): Promise<{ organizationId: number; role: string; state: string }> {\n let payload: any;\n try {\n payload = await githubGet(\n `/user/memberships/orgs/${encodeURIComponent(organizationLogin)}`,\n token,\n );\n } catch (error) {\n if (error instanceof GitHubAppApiError) {\n throw new GitHubInstallationAuthorityError(\n \"authority_unavailable\",\n \"GitHub could not prove current organization-owner membership\",\n error.status,\n );\n }\n throw error;\n }\n const organization =\n payload && typeof payload === \"object\" && payload.organization ? payload.organization : null;\n const organizationId =\n organization && typeof organization === \"object\" ? asInt(organization.id) : null;\n if (\n organizationId === null ||\n typeof payload?.role !== \"string\" ||\n typeof payload?.state !== \"string\"\n ) {\n throw new GitHubInstallationAuthorityError(\n \"authority_unavailable\",\n \"GitHub returned an invalid organization membership proof\",\n );\n }\n return { organizationId, role: payload.role, state: payload.state };\n}\n\nasync function assertActiveOrganizationOwner(\n token: string,\n organizationId: number,\n organizationLogin: string,\n): Promise<void> {\n const membership = await getAuthenticatedOrganizationMembership(token, organizationLogin);\n if (\n membership.organizationId !== organizationId ||\n membership.state !== \"active\" ||\n membership.role !== \"admin\"\n ) {\n throw new GitHubInstallationAuthorityError(\n \"authority_denied\",\n \"Only an active GitHub organization owner may bind this installation\",\n );\n }\n}\n\nasync function listUserAccessibleInstallations(\n token: string,\n): Promise<GitHubAppInstallationSummary[]> {\n const out: GitHubAppInstallationSummary[] = [];\n for (let page = 1; ; page += 1) {\n const payload = await githubGet(\"/user/installations\", token, {\n per_page: \"100\",\n page: String(page),\n });\n const installations: unknown[] | null =\n payload && typeof payload === \"object\" && Array.isArray(payload.installations)\n ? (payload.installations as unknown[])\n : null;\n if (!installations) {\n throw new GitHubAppApiError(\"GitHub returned an invalid user installations payload\");\n }\n out.push(\n ...installations\n .filter((item): item is Record<string, unknown> =>\n Boolean(item && typeof item === \"object\" && !Array.isArray(item)),\n )\n .map(installationSummaryFromPayload),\n );\n if (installations.length < 100) {\n return out;\n }\n }\n}\n\nasync function listUserInstallationRepositories(\n token: string,\n installation: GitHubAppInstallationSummary,\n): Promise<GitHubUserRepositoryAccess[]> {\n const out: GitHubUserRepositoryAccess[] = [];\n const account = {\n ...(installation.accountLogin ? { login: installation.accountLogin } : {}),\n ...(installation.accountType ? { type: installation.accountType } : {}),\n };\n for (let page = 1; ; page += 1) {\n const payload = await githubGet(\n `/user/installations/${installation.installationId}/repositories`,\n token,\n { per_page: \"100\", page: String(page) },\n );\n if (\n !payload ||\n typeof payload !== \"object\" ||\n Array.isArray(payload) ||\n !Array.isArray(payload.repositories)\n ) {\n throw new GitHubAppApiError(\n \"GitHub returned an invalid user installation repositories payload\",\n );\n }\n for (const repository of payload.repositories) {\n if (!repository || typeof repository !== \"object\" || Array.isArray(repository)) {\n continue;\n }\n const record = repository as Record<string, unknown>;\n out.push({\n ...repositoryFromPayload(record, installation.installationId, account),\n permissions: repositoryPermissionsFromPayload(record.permissions),\n });\n }\n if (payload.repositories.length < 100) {\n return out;\n }\n }\n}\n\nasync function createInstallationToken(\n appJwt: string,\n input: {\n installationId: number;\n repositoryIds?: number[];\n /** Narrow the token below the installation's granted permissions. */\n permissions?: Record<string, \"read\" | \"write\">;\n timeoutMs?: number;\n },\n): Promise<GitHubAppInstallationToken> {\n const body: Record<string, unknown> = {};\n if (input.repositoryIds && input.repositoryIds.length > 0) {\n body.repository_ids = input.repositoryIds;\n }\n if (input.permissions && Object.keys(input.permissions).length > 0) {\n body.permissions = input.permissions;\n }\n const scoped = Object.keys(body).length > 0;\n const response = await fetch(\n `${githubApiBase}/app/installations/${input.installationId}/access_tokens`,\n {\n method: \"POST\",\n headers: {\n ...githubHeaders(appJwt),\n ...(scoped ? { \"Content-Type\": \"application/json\" } : {}),\n },\n redirect: \"manual\",\n signal: AbortSignal.timeout(input.timeoutMs ?? githubTokenMintTimeoutMs),\n ...(scoped ? { body: JSON.stringify(body) } : {}),\n },\n );\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response), response.status);\n }\n let payload: unknown;\n try {\n payload = JSON.parse(\n await readResponseTextBounded(\n response,\n githubInstallationTokenResponseMaxBytes,\n \"GitHub installation token response\",\n ),\n ) as unknown;\n } catch {\n throw new GitHubAppApiError(\"GitHub returned an invalid installation token payload\");\n }\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new GitHubAppApiError(\"GitHub returned an invalid installation token payload\");\n }\n const record = payload as Record<string, unknown>;\n if (typeof record.token !== \"string\") {\n throw new GitHubAppApiError(\"GitHub returned an invalid installation token payload\");\n }\n return {\n token: record.token,\n expiresAt: typeof record.expires_at === \"string\" ? record.expires_at : null,\n };\n}\n\nasync function listInstallationRepositories(\n token: string,\n installationId: number,\n account: Record<string, unknown>,\n): Promise<GitHubRepository[]> {\n const out: GitHubRepository[] = [];\n for (let page = 1; ; page += 1) {\n const payload = await githubGet(\"/installation/repositories\", token, {\n per_page: \"100\",\n page: String(page),\n });\n if (\n !payload ||\n typeof payload !== \"object\" ||\n Array.isArray(payload) ||\n !Array.isArray(payload.repositories)\n ) {\n throw new GitHubAppApiError(\"GitHub returned an invalid repositories payload\");\n }\n for (const repo of payload.repositories) {\n if (repo && typeof repo === \"object\" && !Array.isArray(repo)) {\n out.push(repositoryFromPayload(repo as Record<string, unknown>, installationId, account));\n }\n }\n if (payload.repositories.length < 100) {\n return out;\n }\n }\n}\n\nfunction installationSummaryFromPayload(\n payload: Record<string, unknown>,\n): GitHubAppInstallationSummary {\n const installationId = asInt(payload.id);\n if (installationId === null) {\n throw new GitHubAppApiError(\"GitHub returned an installation without id\");\n }\n const account =\n typeof payload.account === \"object\" && payload.account\n ? (payload.account as Record<string, unknown>)\n : {};\n const accountId = asInt(account.id);\n if (accountId === null) {\n throw new GitHubAppApiError(\"GitHub returned an installation without an account id\");\n }\n return {\n installationId,\n accountId,\n accountLogin: typeof account.login === \"string\" ? account.login : null,\n accountType: typeof account.type === \"string\" ? account.type : null,\n suspended: Boolean(payload.suspended_at),\n };\n}\n\nasync function githubGet(\n path: string,\n token: string,\n params: Record<string, string> = {},\n): Promise<any> {\n const url = new URL(`${githubApiBase}${path}`);\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n const response = await fetch(url, { headers: githubHeaders(token) });\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response), response.status);\n }\n return await response.json();\n}\n\nasync function githubRepositoryBranchesFetch(\n url: URL,\n token: string,\n label: string,\n): Promise<Response> {\n let response: Response;\n try {\n response = await fetch(url, {\n headers: githubHeaders(token),\n redirect: \"manual\",\n signal: AbortSignal.timeout(githubRepositoryBranchesTimeoutMs),\n });\n } catch {\n throw new GitHubAppApiError(`${label} request failed`);\n }\n if (!response.ok) {\n throw new GitHubAppApiError(await githubErrorMessage(response), response.status);\n }\n return response;\n}\n\nasync function githubResponseJsonBounded(response: Response, label: string): Promise<unknown> {\n try {\n return JSON.parse(\n await readResponseTextBounded(response, githubRepositoryBranchesResponseMaxBytes, label),\n ) as unknown;\n } catch {\n throw new GitHubAppApiError(`${label} was invalid or too large`);\n }\n}\n\nasync function anonymousGitHubJson(\n fetchImpl: typeof fetch,\n url: URL,\n label: string,\n): Promise<unknown> {\n let response: Response;\n try {\n response = await fetchImpl(url, {\n headers: githubHeaders(),\n redirect: \"manual\",\n signal: AbortSignal.timeout(githubPublicRepositoryVerificationTimeoutMs),\n });\n } catch {\n throw new GitHubPublicRepositoryVerificationError(\n \"provider_unavailable\",\n `${label} verification is temporarily unavailable.`,\n );\n }\n if (response.status === 404) {\n throw new GitHubPublicRepositoryVerificationError(\n \"unavailable\",\n label === \"GitHub repository\"\n ? \"That GitHub repository is private or unavailable.\"\n : \"That branch, tag, or commit SHA is not available on the public repository.\",\n response.status,\n );\n }\n if (!response.ok) {\n throw new GitHubPublicRepositoryVerificationError(\n \"provider_unavailable\",\n response.status === 429\n ? \"GitHub is temporarily rate limited. Try again shortly.\"\n : `${label} verification is temporarily unavailable.`,\n response.status,\n );\n }\n try {\n return JSON.parse(\n await readResponseTextBounded(\n response,\n githubPublicRepositoryVerificationResponseMaxBytes,\n `${label} verification response`,\n ),\n ) as unknown;\n } catch {\n throw new GitHubPublicRepositoryVerificationError(\n \"provider_unavailable\",\n `${label} verification returned an invalid response.`,\n );\n }\n}\n\nfunction repositoryFromPayload(\n payload: Record<string, unknown>,\n installationId: number,\n account: Record<string, unknown>,\n): GitHubRepository {\n const id = asInt(payload.id);\n const fullName = String(payload.full_name ?? \"\");\n if (id === null || !fullName) {\n throw new GitHubAppApiError(\"GitHub returned a repository without id/full_name\");\n }\n return {\n id,\n installationId,\n fullName,\n name: String(payload.name ?? fullName.split(\"/\").at(-1) ?? fullName),\n private: Boolean(payload.private),\n htmlUrl: String(payload.html_url ?? `https://github.com/${fullName}`),\n cloneUrl: String(payload.clone_url ?? `https://github.com/${fullName}.git`),\n defaultBranch: String(payload.default_branch ?? \"main\"),\n accountLogin: String(account.login ?? fullName.split(\"/\", 1)[0]),\n accountType: typeof account.type === \"string\" ? account.type : null,\n };\n}\n\nfunction repositoryPermissionsFromPayload(payload: unknown): GitHubRepositoryPermissions {\n const permissions =\n payload && typeof payload === \"object\" && !Array.isArray(payload)\n ? (payload as Record<string, unknown>)\n : {};\n return {\n admin: permissions.admin === true,\n maintain: permissions.maintain === true,\n push: permissions.push === true,\n triage: permissions.triage === true,\n pull: permissions.pull === true,\n };\n}\n\nfunction githubHeaders(token?: string): HeadersInit {\n return {\n Accept: \"application/vnd.github+json\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n \"X-GitHub-Api-Version\": githubApiVersion,\n };\n}\n\nasync function githubErrorMessage(response: Response): Promise<string> {\n let text: string;\n try {\n text = await readResponseTextBounded(\n response,\n githubErrorResponseMaxBytes,\n \"GitHub error response\",\n );\n } catch {\n return `GitHub API ${response.status}`;\n }\n try {\n const payload = JSON.parse(text) as unknown;\n if (payload && typeof payload === \"object\" && \"message\" in payload) {\n return `GitHub API ${response.status}: ${String(\n (payload as Record<string, unknown>).message,\n ).slice(0, githubErrorMessageMaxLength)}`;\n }\n } catch {\n // Fall through to the bounded text body.\n }\n return `GitHub API ${response.status}: ${text.slice(0, githubErrorMessageMaxLength)}`;\n}\n\nexport function normalizeGitHubAppPrivateKey(value: string): string {\n const privateKey = value.trim().replace(/\\\\n/g, \"\\n\");\n if (!privateKey || privateKey.startsWith(pkcs8PrivateKeyHeader)) {\n return privateKey;\n }\n if (privateKey.startsWith(rsaPrivateKeyHeader)) {\n return createPrivateKey(privateKey).export({ type: \"pkcs8\", format: \"pem\" }).toString();\n }\n return privateKey;\n}\n\nfunction signStatePayload(encoded: string, secret: string): string {\n return createHmac(\"sha256\", secret).update(encoded).digest(\"base64url\");\n}\n\nfunction safeEqual(left: string, right: string): boolean {\n const a = Buffer.from(left);\n const b = Buffer.from(right);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\nfunction asInt(value: unknown): number | null {\n if (typeof value === \"number\" && Number.isInteger(value)) {\n return value;\n }\n if (typeof value === \"string\" && /^\\d+$/.test(value)) {\n return Number(value);\n }\n return null;\n}\n"],"mappings":"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","names":["installation"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/github",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.17-canary.36239117573001",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"prepublishOnly": "bash ../../scripts/prepublish-guard"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@opengeni/config": "^
|
|
35
|
-
"@opengeni/contracts": "^5.
|
|
36
|
-
"@opengeni/network": "^0.3.1",
|
|
34
|
+
"@opengeni/config": "^3.0.0-canary.36239117573001",
|
|
35
|
+
"@opengeni/contracts": "^5.2.0-canary.36239117573001",
|
|
36
|
+
"@opengeni/network": "^0.3.1-canary.36239117573001",
|
|
37
37
|
"jose": "^6.1.3"
|
|
38
38
|
}
|
|
39
39
|
}
|
package/src/index.ts
CHANGED
|
@@ -446,6 +446,20 @@ export function readSignedState(
|
|
|
446
446
|
secret: string,
|
|
447
447
|
now = Math.floor(Date.now() / 1000),
|
|
448
448
|
): GitHubSignedStatePayload | null {
|
|
449
|
+
const payload = inspectSignedState(state, secret);
|
|
450
|
+
if (!payload) return null;
|
|
451
|
+
const age = now - payload.iat;
|
|
452
|
+
return age >= 0 && age <= stateMaxAgeSeconds ? payload : null;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Verifies a signed state's signature and shape without its age limit.
|
|
457
|
+
*
|
|
458
|
+
* Only for explaining a failed callback (for example "this link expired" and
|
|
459
|
+
* which workspace page to return to). An aged payload is never authority: every
|
|
460
|
+
* authorizing read uses {@link readSignedState} or its own stricter lifetime.
|
|
461
|
+
*/
|
|
462
|
+
export function inspectSignedState(state: string, secret: string): GitHubSignedStatePayload | null {
|
|
449
463
|
const [encoded, signature] = state.split(".", 2);
|
|
450
464
|
if (!encoded || !signature) {
|
|
451
465
|
return null;
|
|
@@ -468,8 +482,7 @@ export function readSignedState(
|
|
|
468
482
|
) {
|
|
469
483
|
return null;
|
|
470
484
|
}
|
|
471
|
-
|
|
472
|
-
return age >= 0 && age <= stateMaxAgeSeconds ? (payload as GitHubSignedStatePayload) : null;
|
|
485
|
+
return payload as GitHubSignedStatePayload;
|
|
473
486
|
}
|
|
474
487
|
|
|
475
488
|
export function verifySignedState(
|