@openma/matter-gitlab 0.0.0-stage → 0.2.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["isRecord","isRecord","isRecord","isRecord"],"sources":["../../src/bond/http.ts","../../src/bond/oauth.ts","../../src/bond/tokens.ts","../../src/bond/classify.ts","../../src/bond/receive-pack.ts","../../src/bond/attribution.ts","../../src/bond/provider.ts","../../src/bond/resources.ts","../../src/bond/integration/shared.ts","../../src/bond/integration/client.ts","../../src/bond/integration/delivery.ts","../../src/bond/integration/events.ts","../../src/bond/integration/http.ts","../../src/bond/integration/integration.ts","../../src/bond/integration/templates.ts"],"sourcesContent":["import { ProviderError } from \"@openma/matter/bond\";\nimport { Effect } from \"effect\";\n\nexport type Fetch = typeof globalThis.fetch;\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/**\n * Normalizes a GitLab instance URL to its canonical https origin. Rejects\n * plain http except for loopback hosts, and rejects paths, credentials,\n * queries, and fragments.\n */\nexport const canonicalOrigin = (input: string): string => {\n const url = new URL(input);\n const loopback =\n url.hostname === \"localhost\" ||\n url.hostname === \"127.0.0.1\" ||\n url.hostname === \"[::1]\";\n if (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && loopback)) {\n throw new Error(\"GitLab instance URL must use https\");\n }\n if (url.username || url.password || url.search || url.hash) {\n throw new Error(\n \"GitLab instance URL must not carry credentials, query, or fragment\",\n );\n }\n if (url.pathname !== \"/\" && url.pathname !== \"\") {\n throw new Error(\"GitLab instance URL must be an origin without a path\");\n }\n return url.origin.toLowerCase();\n};\n\nexport interface JsonResponse {\n readonly status: number;\n readonly body: unknown;\n readonly headers?: Headers;\n}\n\n/** One JSON request. Never follows redirects: a redirect is an error. */\nexport const requestJson = (\n fetchImpl: Fetch,\n url: string,\n init: RequestInit,\n): Effect.Effect<JsonResponse, ProviderError> =>\n Effect.tryPromise({\n try: async () => {\n const response = await fetchImpl(url, { ...init, redirect: \"manual\" });\n const text = await response.text();\n let body: unknown = undefined;\n if (text.length > 0) {\n try {\n body = JSON.parse(text);\n } catch {\n body = undefined;\n }\n }\n return { status: response.status, body, headers: response.headers };\n },\n catch: (cause) =>\n new ProviderError({\n message: `GitLab request failed: ${new URL(url).pathname}`,\n rejected: false,\n cause,\n }),\n });\n\nexport const bearer = (token: string) => ({ authorization: `Bearer ${token}` });\n\n/**\n * Maps a non-2xx GitLab response to a ProviderError without echoing bodies.\n * Only OAuth `invalid_grant` is a rejection, the one answer that means the\n * grant itself is gone. `invalid_client`, other 4xx, and 5xx are\n * configuration or transport problems and must not end a link.\n */\nexport const statusError = (\n what: string,\n response: JsonResponse,\n): ProviderError => {\n const error =\n isRecord(response.body) && typeof response.body.error === \"string\"\n ? response.body.error\n : undefined;\n return new ProviderError({\n message: `${what} failed with HTTP ${response.status}${error === undefined ? \"\" : ` (${error})`}`,\n rejected: error === \"invalid_grant\",\n status: response.status,\n });\n};\n","import { ProviderError, type TokenGrant } from \"@openma/matter/bond\";\nimport { Effect } from \"effect\";\nimport {\n canonicalOrigin,\n isRecord,\n requestJson,\n statusError,\n type Fetch,\n} from \"./http.js\";\n\n/**\n * What discovery verified. OAuth calls always use the instance's fixed\n * `/oauth/authorize`, `/oauth/token`, and `/oauth/revoke` under `origin`, so\n * discovery returns no endpoints that callers might follow elsewhere.\n */\nexport interface GitLabInstance {\n readonly origin: string;\n /** Whether the instance enables the device authorization grant. */\n readonly deviceFlow: boolean;\n}\n\nconst base64url = (bytes: Uint8Array): string => {\n let binary = \"\";\n for (const b of bytes) binary += String.fromCharCode(b);\n return btoa(binary)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n};\n\n/**\n * Reads OIDC discovery and requires authorization code with PKCE S256 and\n * refresh tokens, and an issuer equal to the instance origin. Device flow is\n * recorded when present; GitLab can disable it per instance.\n */\nexport const discoverInstance = (\n origin: string,\n fetchImpl: Fetch = globalThis.fetch,\n): Effect.Effect<GitLabInstance, ProviderError> =>\n Effect.gen(function* () {\n const canonical = yield* Effect.try({\n try: () => canonicalOrigin(origin),\n catch: (cause) =>\n new ProviderError({\n message: cause instanceof Error ? cause.message : \"Invalid origin\",\n rejected: true,\n cause,\n }),\n });\n const response = yield* requestJson(\n fetchImpl,\n `${canonical}/.well-known/openid-configuration`,\n { method: \"GET\", headers: { accept: \"application/json\" } },\n );\n if (response.status !== 200 || !isRecord(response.body)) {\n return yield* Effect.fail(statusError(\"OIDC discovery\", response));\n }\n const d = response.body;\n const list = (key: string) =>\n Array.isArray(d[key])\n ? (d[key] as unknown[]).filter((v) => typeof v === \"string\")\n : [];\n const problems: string[] = [];\n if (\n typeof d.issuer !== \"string\" ||\n d.issuer.replace(/\\/$/, \"\").toLowerCase() !== canonical\n ) {\n problems.push(\"issuer does not match the instance origin\");\n }\n if (!list(\"code_challenge_methods_supported\").includes(\"S256\")) {\n problems.push(\"PKCE S256 is not supported\");\n }\n if (!list(\"grant_types_supported\").includes(\"refresh_token\")) {\n problems.push(\"refresh_token grant is not supported\");\n }\n if (\n typeof d.authorization_endpoint !== \"string\" ||\n typeof d.token_endpoint !== \"string\"\n ) {\n problems.push(\"authorization or token endpoint is missing\");\n }\n if (problems.length > 0) {\n return yield* Effect.fail(\n new ProviderError({\n message: `GitLab instance is not usable: ${problems.join(\"; \")}`,\n rejected: true,\n }),\n );\n }\n return {\n origin: canonical,\n deviceFlow: typeof d.device_authorization_endpoint === \"string\",\n };\n });\n\nexport interface Pkce {\n readonly verifier: string;\n readonly challenge: string;\n readonly method: \"S256\";\n}\n\n/** A fresh PKCE verifier and its S256 challenge. Keep the verifier server-side. */\nexport const createPkce = (): Effect.Effect<Pkce> =>\n Effect.promise(async () => {\n const verifier = base64url(\n globalThis.crypto.getRandomValues(new Uint8Array(48)),\n );\n const digest = await globalThis.crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(verifier),\n );\n return {\n verifier,\n challenge: base64url(new Uint8Array(digest)),\n method: \"S256\",\n };\n });\n\nexport interface AuthorizationUrlInput {\n readonly origin: string;\n readonly clientId: string;\n readonly redirectUri: string;\n readonly scopes: readonly string[];\n /** Signed, single-use state bound to the user and ProviderApp. */\n readonly state: string;\n readonly codeChallenge: string;\n}\n\nexport const authorizationUrl = (input: AuthorizationUrlInput): string =>\n `${canonicalOrigin(input.origin)}/oauth/authorize?${new URLSearchParams({\n client_id: input.clientId,\n redirect_uri: input.redirectUri,\n response_type: \"code\",\n scope: input.scopes.join(\" \"),\n state: input.state,\n code_challenge: input.codeChallenge,\n code_challenge_method: \"S256\",\n }).toString()}`;\n\nexport interface OAuthClient {\n readonly origin: string;\n readonly clientId: string;\n /** Absent for public clients. */\n readonly clientSecret?: string;\n readonly fetch?: Fetch;\n /** ISO now, for computing expiry. */\n readonly clock?: () => string;\n}\n\nconst tokenGrant = (body: unknown, now: string): TokenGrant | undefined => {\n if (!isRecord(body) || typeof body.access_token !== \"string\")\n return undefined;\n // GitLab returns created_at (seconds) and expires_in (seconds).\n const createdMs =\n typeof body.created_at === \"number\"\n ? body.created_at * 1000\n : Date.parse(now);\n return {\n accessToken: body.access_token,\n ...(typeof body.refresh_token === \"string\"\n ? { refreshToken: body.refresh_token }\n : {}),\n ...(typeof body.expires_in === \"number\"\n ? {\n accessExpiresAt: new Date(\n createdMs + body.expires_in * 1000,\n ).toISOString(),\n }\n : {}),\n ...(typeof body.scope === \"string\"\n ? { scopes: body.scope.split(\" \").filter(Boolean) }\n : {}),\n };\n};\n\nconst postToken = (\n client: OAuthClient,\n what: string,\n params: Record<string, string>,\n) =>\n Effect.gen(function* () {\n const origin = canonicalOrigin(client.origin);\n const now = (client.clock ?? (() => new Date().toISOString()))();\n const response = yield* requestJson(\n client.fetch ?? globalThis.fetch,\n `${origin}/oauth/token`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n accept: \"application/json\",\n },\n body: new URLSearchParams({\n ...params,\n client_id: client.clientId,\n ...(client.clientSecret === undefined\n ? {}\n : { client_secret: client.clientSecret }),\n }).toString(),\n },\n );\n const grant =\n response.status === 200 ? tokenGrant(response.body, now) : undefined;\n if (grant === undefined)\n return yield* Effect.fail(statusError(what, response));\n return grant;\n });\n\n/** Exchanges an authorization code. A wrong verifier does not consume the code on GitLab. */\nexport const exchangeCode = (\n client: OAuthClient,\n input: {\n readonly code: string;\n readonly redirectUri: string;\n readonly codeVerifier: string;\n },\n) =>\n postToken(client, \"Authorization code exchange\", {\n grant_type: \"authorization_code\",\n code: input.code,\n redirect_uri: input.redirectUri,\n code_verifier: input.codeVerifier,\n });\n\n/**\n * Refreshes a user token. GitLab rotates both tokens and invalidates the old\n * access token immediately, and does not detect refresh-token reuse, so the\n * caller must hold the Bond refresh lease.\n */\nexport const refreshAccessToken = (client: OAuthClient, refreshToken: string) =>\n postToken(client, \"Token refresh\", {\n grant_type: \"refresh_token\",\n refresh_token: refreshToken,\n });\n\n/**\n * Revokes one access or refresh token. GitLab (Doorkeeper) stores an access\n * token and its refresh token as one record, so revoking either ends that\n * pair only. Other tokens the same user holds for the same application keep\n * working: on a live instance, revoking the previous token after a relink left\n * the new one valid.\n */\nexport const revokeToken = (client: OAuthClient, token: string) =>\n Effect.gen(function* () {\n const origin = canonicalOrigin(client.origin);\n const response = yield* requestJson(\n client.fetch ?? globalThis.fetch,\n `${origin}/oauth/revoke`,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n token,\n client_id: client.clientId,\n ...(client.clientSecret === undefined\n ? {}\n : { client_secret: client.clientSecret }),\n }).toString(),\n },\n );\n if (response.status !== 200) {\n return yield* Effect.fail(statusError(\"Token revocation\", response));\n }\n });\n","import type { ProviderError } from \"@openma/matter/bond\";\nimport { Effect } from \"effect\";\nimport {\n bearer,\n canonicalOrigin,\n isRecord,\n requestJson,\n statusError,\n type Fetch,\n} from \"./http.js\";\n\n/** `GET /api/v4/user`. Numeric `id` is the stable key; the rest is display data. */\nexport interface GitLabUser {\n readonly id: string;\n readonly username: string;\n readonly name: string;\n readonly commitEmail?: string;\n readonly bot: boolean;\n readonly identities: readonly {\n readonly provider: string;\n readonly externUid: string;\n }[];\n}\n\n/** `GET /api/v4/personal_access_tokens/self`. Works for personal, project, and group access tokens. */\nexport interface GitLabTokenInfo {\n readonly id: string;\n readonly name: string;\n readonly active: boolean;\n readonly revoked: boolean;\n readonly scopes: readonly string[];\n /** `YYYY-MM-DD`, or undefined for a token without expiry. */\n readonly expiresAt?: string;\n readonly userId: string;\n}\n\nconst api = (origin: string, path: string) =>\n `${canonicalOrigin(origin)}/api/v4${path}`;\n\nexport const readUser = (\n origin: string,\n token: string,\n fetchImpl: Fetch = globalThis.fetch,\n): Effect.Effect<GitLabUser, ProviderError> =>\n Effect.gen(function* () {\n const response = yield* requestJson(fetchImpl, api(origin, \"/user\"), {\n method: \"GET\",\n headers: { ...bearer(token), accept: \"application/json\" },\n });\n const b = response.body;\n if (response.status !== 200 || !isRecord(b) || typeof b.id !== \"number\") {\n return yield* Effect.fail(\n statusError(\"Reading the GitLab user\", response),\n );\n }\n const identities = Array.isArray(b.identities)\n ? b.identities.flatMap((i) =>\n isRecord(i) &&\n typeof i.provider === \"string\" &&\n typeof i.extern_uid === \"string\"\n ? [{ provider: i.provider, externUid: i.extern_uid }]\n : [],\n )\n : [];\n return {\n id: String(b.id),\n username: typeof b.username === \"string\" ? b.username : \"\",\n name: typeof b.name === \"string\" ? b.name : \"\",\n ...(typeof b.commit_email === \"string\" && b.commit_email.length > 0\n ? { commitEmail: b.commit_email }\n : {}),\n bot: b.bot === true,\n identities,\n };\n });\n\nexport const readTokenInfo = (\n origin: string,\n token: string,\n fetchImpl: Fetch = globalThis.fetch,\n): Effect.Effect<GitLabTokenInfo, ProviderError> =>\n Effect.gen(function* () {\n const response = yield* requestJson(\n fetchImpl,\n api(origin, \"/personal_access_tokens/self\"),\n {\n method: \"GET\",\n headers: { ...bearer(token), accept: \"application/json\" },\n },\n );\n const b = response.body;\n if (response.status !== 200 || !isRecord(b) || typeof b.id !== \"number\") {\n return yield* Effect.fail(\n statusError(\"Reading token metadata\", response),\n );\n }\n return {\n id: String(b.id),\n name: typeof b.name === \"string\" ? b.name : \"\",\n active: b.active === true,\n revoked: b.revoked === true,\n scopes: Array.isArray(b.scopes)\n ? b.scopes.filter((s): s is string => typeof s === \"string\")\n : [],\n ...(typeof b.expires_at === \"string\" ? { expiresAt: b.expires_at } : {}),\n userId: String(b.user_id),\n };\n });\n\n/** `DELETE /api/v4/personal_access_tokens/self`: a token revokes itself. */\nexport const revokeSelfToken = (\n origin: string,\n token: string,\n fetchImpl: Fetch = globalThis.fetch,\n): Effect.Effect<void, ProviderError> =>\n Effect.gen(function* () {\n const response = yield* requestJson(\n fetchImpl,\n api(origin, \"/personal_access_tokens/self\"),\n { method: \"DELETE\", headers: bearer(token) },\n );\n if (response.status !== 204 && response.status !== 200) {\n return yield* Effect.fail(statusError(\"Token self-revocation\", response));\n }\n });\n\nexport interface TokenPolicy {\n readonly allowedScopes: readonly string[];\n readonly maxLifetimeDays: number;\n /** ISO now. */\n readonly now: string;\n}\n\nexport type TokenProblem =\n | \"inactive\"\n | \"revoked\"\n | \"no_expiry\"\n | \"expired\"\n | \"lifetime_exceeded\"\n | \"scope_not_allowed\"\n | \"not_a_bot\"\n | \"is_a_bot\"\n | \"user_mismatch\";\n\n/** End of the UTC expiry day, which is when GitLab stops accepting the token. */\nexport const tokenExpiryInstant = (expiresAt: string): string =>\n new Date(`${expiresAt}T23:59:59.999Z`).toISOString();\n\nconst commonProblems = (\n info: GitLabTokenInfo,\n user: GitLabUser,\n policy: TokenPolicy,\n): TokenProblem[] => {\n const problems: TokenProblem[] = [];\n // Both reads must describe the same token: a mixed pair proves nothing.\n if (info.userId !== user.id) problems.push(\"user_mismatch\");\n if (info.revoked) problems.push(\"revoked\");\n if (!info.active) problems.push(\"inactive\");\n if (info.scopes.some((s) => !policy.allowedScopes.includes(s))) {\n problems.push(\"scope_not_allowed\");\n }\n if (info.expiresAt === undefined) {\n problems.push(\"no_expiry\");\n } else {\n const end = Date.parse(tokenExpiryInstant(info.expiresAt));\n const now = Date.parse(policy.now);\n if (end <= now) problems.push(\"expired\");\n else if (end - now > (policy.maxLifetimeDays + 1) * 24 * 60 * 60_000) {\n problems.push(\"lifetime_exceeded\");\n }\n }\n return problems;\n};\n\n/**\n * Checks a pasted personal access token: active, scopes within the allowed\n * set, an expiry within the maximum lifetime, and a human owner.\n */\nexport const validatePersonalAccessToken = (\n info: GitLabTokenInfo,\n user: GitLabUser,\n policy: TokenPolicy,\n): readonly TokenProblem[] => [\n ...commonProblems(info, user, policy),\n ...(user.bot ? ([\"is_a_bot\"] as const) : []),\n];\n\n/**\n * Checks a bot credential registered as an Installation: the same token\n * checks, plus `bot: true` on its user. A human account's token is never\n * accepted as an app principal.\n */\nexport const validateBotCredential = (\n info: GitLabTokenInfo,\n user: GitLabUser,\n policy: TokenPolicy,\n): readonly TokenProblem[] => [\n ...commonProblems(info, user, policy),\n ...(user.bot ? [] : ([\"not_a_bot\"] as const)),\n];\n","// Request classification for application-side GitLab proxies. The\n// application resolves every project reference to a numeric project ID and\n// checks the Session's grant before forwarding anything.\n//\n// Forward a rebuilt URL, never the raw request path: `/api/v4/projects/<id>`\n// plus `restTail` for REST, and the resolved `path_with_namespace` plus the\n// git endpoint for smart HTTP. Then GitLab sees exactly what was classified.\n\nexport type GitLabOperation =\n \"fetch\" | \"push\" | \"read\" | \"open_mr\" | \"comment_mr\";\n\n/**\n * A normalized project reference. Paths are lower-cased and stripped of\n * `.git`; numeric IDs stay numeric. Both forms name one project only after\n * the application resolves them through GitLab.\n */\nexport type ProjectRef =\n | { readonly kind: \"id\"; readonly id: number }\n | { readonly kind: \"path\"; readonly path: string };\n\nexport type GitLabRequestClass =\n | {\n readonly allow: true;\n readonly projectRef: ProjectRef;\n readonly operation: GitLabOperation;\n /** `git` for smart HTTP, `rest` for `/api/v4`. */\n readonly surface: \"git\" | \"rest\";\n /**\n * For `rest`: the validated path after `/api/v4/projects/<ref>`, to\n * append to the resolved numeric project ID. For `open_mr`, the proxy\n * must also check the body with `mergeRequestBodyProblem`.\n */\n readonly restTail?: string;\n }\n | { readonly allow: false; readonly reason: string };\n\nconst deny = (reason: string): GitLabRequestClass => ({ allow: false, reason });\n\nconst normalizePath = (raw: string): string | undefined => {\n let decoded: string;\n try {\n decoded = decodeURIComponent(raw);\n } catch {\n return undefined;\n }\n const path = decoded\n .replace(/\\.git$/i, \"\")\n .replace(/^\\/+|\\/+$/g, \"\")\n .toLowerCase();\n const segments = path.split(\"/\");\n if (\n segments.length < 2 ||\n segments.some(\n (s) => s === \"\" || s === \".\" || s === \"..\" || !/^[\\w.-]+$/.test(s),\n )\n ) {\n return undefined;\n }\n return path;\n};\n\nconst projectRefOf = (raw: string): ProjectRef | undefined =>\n /^\\d+$/.test(raw)\n ? { kind: \"id\", id: Number(raw) }\n : (() => {\n const path = normalizePath(raw);\n return path === undefined ? undefined : { kind: \"path\", path };\n })();\n\n/**\n * REST reads, by exact shape. A branch name may carry encoded slashes\n * (`feature%2Fx`), and nothing else is percent-encoded.\n */\nconst READ_TAILS = [\n /^$/,\n /^\\/merge_requests$/,\n /^\\/merge_requests\\/\\d+(\\/(notes|commits|changes|diffs|approvals))?$/,\n /^\\/repository\\/branches$/,\n /^\\/repository\\/branches\\/([\\w.-]|%2[fF])+$/,\n /^\\/repository\\/commits$/,\n /^\\/repository\\/commits\\/[0-9a-f]{7,64}$/,\n];\n\nconst GIT_ROUTE =\n /^\\/(.+?)(?:\\.git)?\\/(info\\/refs|git-upload-pack|git-receive-pack)$/i;\n\n/**\n * Classifies one request in GitLab's own URL shape. Allows git smart HTTP\n * fetch and push, REST reads of a project, merge request creation, and\n * merge request notes. Denies GraphQL, LFS, archives, raw files, and every\n * other route.\n */\nexport const classifyGitLabRequest = (\n method: string,\n url: string | URL,\n): GitLabRequestClass => {\n const u =\n typeof url === \"string\" ? new URL(url, \"https://gitlab.invalid\") : url;\n const verb = method.toUpperCase();\n const path = u.pathname;\n if (path.includes(\"/../\") || path.endsWith(\"/..\"))\n return deny(\"path traversal\");\n // Encoded dots and backslashes have no legitimate use in allowed routes.\n if (/%2e|%5c/i.test(path)) return deny(\"encoded traversal characters\");\n\n if (/^\\/api\\/graphql\\/?$/i.test(path)) return deny(\"GraphQL is not proxied\");\n if (/\\/info\\/lfs(\\/|$)/i.test(path)) return deny(\"LFS is not proxied\");\n\n const git = path.match(GIT_ROUTE);\n if (git !== null && !/^\\/api\\//i.test(path)) {\n const [, rawProject, endpoint] = git;\n const ref =\n rawProject === undefined ? undefined : normalizePath(rawProject);\n if (ref === undefined) return deny(\"invalid project path\");\n const service =\n endpoint?.toLowerCase() === \"info/refs\"\n ? u.searchParams.get(\"service\")\n : endpoint?.toLowerCase();\n const operation =\n service === \"git-upload-pack\"\n ? \"fetch\"\n : service === \"git-receive-pack\"\n ? \"push\"\n : undefined;\n if (operation === undefined) return deny(\"git service not allowed\");\n const expected = endpoint?.toLowerCase() === \"info/refs\" ? \"GET\" : \"POST\";\n if (verb !== expected) return deny(`method ${verb} not allowed`);\n return {\n allow: true,\n projectRef: { kind: \"path\", path: ref },\n operation,\n surface: \"git\",\n };\n }\n\n const rest = path.match(/^\\/api\\/v4\\/projects\\/([^/]+)(\\/.*)?$/i);\n if (rest !== null) {\n const [, rawProject, rest2] = rest;\n const projectRef =\n rawProject === undefined ? undefined : projectRefOf(rawProject);\n if (projectRef === undefined) return deny(\"invalid project reference\");\n const tail = (rest2 ?? \"\").replace(/\\/$/, \"\");\n if (tail.includes(\"..\")) return deny(\"path traversal\");\n const allow = (operation: GitLabOperation): GitLabRequestClass => ({\n allow: true,\n projectRef,\n operation,\n surface: \"rest\",\n restTail: tail,\n });\n if (verb === \"GET\" && READ_TAILS.some((re) => re.test(tail))) {\n return allow(\"read\");\n }\n if (verb === \"POST\") {\n // Grape merges query parameters into the request parameters, so a\n // write could carry `target_project_id` (or anything else) past a body\n // check. Writes take no query string.\n if (u.search !== \"\") return deny(\"query parameters on a write\");\n if (tail === \"/merge_requests\") return allow(\"open_mr\");\n if (/^\\/merge_requests\\/\\d+\\/notes$/.test(tail)) {\n return allow(\"comment_mr\");\n }\n }\n return deny(\"REST route not allowed\");\n }\n return deny(\"route not allowed\");\n};\n\n/**\n * GitLab lets `POST /projects/:id/merge_requests` name another project in\n * `target_project_id`, so the URL alone does not bound where the merge\n * request opens. Returns the reason to deny, or undefined when the body\n * targets the classified project.\n *\n * Pass the parsed JSON object or form body and the numeric ID the URL's\n * project reference resolved to, then forward the body you checked\n * (re-serialized), never the raw bytes: parsers disagree on repeated keys.\n * For the same reason a form that repeats `target_project_id`, or uses a\n * variant such as `target_project_id[]`, is denied.\n */\nexport const mergeRequestBodyProblem = (\n body: unknown,\n resolvedProjectId: number,\n): string | undefined => {\n let target: unknown;\n if (body instanceof URLSearchParams) {\n const keys = [...body.keys()].filter((k) =>\n k.startsWith(\"target_project_id\"),\n );\n if (keys.some((k) => k !== \"target_project_id\")) {\n return \"target_project_id has an unsupported form\";\n }\n if (keys.length > 1) return \"target_project_id appears more than once\";\n target = body.get(\"target_project_id\") ?? undefined;\n } else if (\n typeof body === \"object\" &&\n body !== null &&\n !Array.isArray(body)\n ) {\n const record = body as Record<string, unknown>;\n if (\n Object.keys(record).some(\n (k) => k.startsWith(\"target_project_id\") && k !== \"target_project_id\",\n )\n ) {\n return \"target_project_id has an unsupported form\";\n }\n target = record.target_project_id;\n } else if (body === undefined || body === null) {\n target = undefined;\n } else {\n return \"merge request body is not an object\";\n }\n if (target === undefined || target === \"\") return undefined;\n const id =\n typeof target === \"number\"\n ? target\n : typeof target === \"string\" && /^\\d+$/.test(target)\n ? Number(target)\n : Number.NaN;\n if (!Number.isSafeInteger(id)) return \"target_project_id is not a project ID\";\n return id === resolvedProjectId\n ? undefined\n : \"target_project_id names another project\";\n};\n","// git-receive-pack request head parsing and push policy. The head is the\n// pkt-line command list and optional push options that precede the pack, so\n// a proxy can decide before streaming the pack upstream.\n\nexport const ZERO_OID = \"0\".repeat(40);\n\nexport interface ReceivePackCommand {\n readonly oldId: string;\n readonly newId: string;\n readonly ref: string;\n}\n\nexport interface ReceivePackHead {\n readonly commands: readonly ReceivePackCommand[];\n readonly capabilities: readonly string[];\n readonly options: readonly string[];\n /** Bytes consumed by the head. The pack starts here. */\n readonly headLength: number;\n}\n\nexport type ReceivePackParse =\n | { readonly _tag: \"Complete\"; readonly head: ReceivePackHead }\n | { readonly _tag: \"Incomplete\" }\n | { readonly _tag: \"Malformed\"; readonly reason: string };\n\n/** Bounds on a hostile head. Exceeding one is Malformed, never Incomplete. */\nexport interface ReceivePackLimits {\n /** Default 1 MiB. */\n readonly maxHeadBytes?: number;\n /** Default 1000. */\n readonly maxCommands?: number;\n /** Default 100. */\n readonly maxOptions?: number;\n}\n\nconst decoder = new TextDecoder(\"utf-8\", { fatal: true });\nconst OID = /^[0-9a-f]{40}([0-9a-f]{24})?$/;\n\n/**\n * A strict subset of `git check-ref-format`: a full `refs/` name with no\n * control characters, no characters git forbids, no empty, dot-leading, or\n * `.lock` components, no `..`, and no `@{`.\n */\nexport const isValidRefName = (ref: string): boolean => {\n if (!ref.startsWith(\"refs/\") || ref.length > 1024) return false;\n if (/[\\x00-\\x20\\x7f~^:?*[\\\\]/.test(ref)) return false;\n if (ref.includes(\"..\") || ref.includes(\"@{\") || ref.endsWith(\".\")) {\n return false;\n }\n return ref\n .split(\"/\")\n .every((c) => c !== \"\" && !c.startsWith(\".\") && !c.endsWith(\".lock\"));\n};\n\nconst concat = (a: Uint8Array, b: Uint8Array): Uint8Array => {\n if (a.length === 0) return b;\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n};\n\nexport interface ReceivePackHeadParser {\n /** Feeds the next chunk of the request body. */\n readonly push: (chunk: Uint8Array) => ReceivePackParse;\n /**\n * Bytes after the head in the chunk that completed it: the start of the\n * pack. Later chunks are not buffered; stream them upstream directly.\n */\n readonly remainder: () => Uint8Array;\n}\n\n/**\n * Incremental receive-pack head parser. Each byte is examined once, and only\n * an unfinished pkt-line is buffered, so a head fed in many small chunks\n * costs linear time. Capabilities are the union over every command line, as\n * in git's `read_head`: a client cannot hide `push-options` behind a later\n * line without them.\n */\nexport const makeReceivePackHeadParser = (\n limits: ReceivePackLimits = {},\n): ReceivePackHeadParser => {\n const maxHeadBytes = limits.maxHeadBytes ?? 1024 * 1024;\n const maxCommands = limits.maxCommands ?? 1000;\n const maxOptions = limits.maxOptions ?? 100;\n let pending: Uint8Array = new Uint8Array(0);\n let consumed = 0;\n let phase: \"commands\" | \"options\" | \"done\" = \"commands\";\n const commands: ReceivePackCommand[] = [];\n const capabilities = new Set<string>();\n const options: string[] = [];\n let result: ReceivePackParse = { _tag: \"Incomplete\" };\n\n const malformed = (reason: string): ReceivePackParse => {\n result = { _tag: \"Malformed\", reason };\n phase = \"done\";\n return result;\n };\n\n const complete = (): ReceivePackParse => {\n phase = \"done\";\n result = {\n _tag: \"Complete\",\n head: {\n commands,\n capabilities: [...capabilities],\n options,\n headLength: consumed,\n },\n };\n return result;\n };\n\n /** One pkt-line: text, null for a flush, undefined when more bytes are needed. */\n const nextPkt = (): string | null | undefined | ReceivePackParse => {\n if (pending.length < 4) return undefined;\n let lenText: string;\n try {\n lenText = decoder.decode(pending.subarray(0, 4));\n } catch {\n return malformed(\"bad pkt-line length\");\n }\n if (!/^[0-9a-f]{4}$/i.test(lenText))\n return malformed(\"bad pkt-line length\");\n const len = Number.parseInt(lenText, 16);\n if (len === 0) {\n pending = pending.subarray(4);\n consumed += 4;\n return null;\n }\n if (len < 4) return malformed(\"bad pkt-line length\");\n if (pending.length < len) return undefined;\n let line: string;\n try {\n line = decoder.decode(pending.subarray(4, len));\n } catch {\n return malformed(\"pkt-line is not valid UTF-8\");\n }\n pending = pending.subarray(len);\n consumed += len;\n return line.endsWith(\"\\n\") ? line.slice(0, -1) : line;\n };\n\n const step = (): ReceivePackParse => {\n for (;;) {\n const pkt = nextPkt();\n if (pkt === undefined) {\n return consumed + pending.length > maxHeadBytes\n ? malformed(\"receive-pack head is too large\")\n : result;\n }\n if (typeof pkt === \"object\" && pkt !== null) return pkt;\n if (phase === \"commands\") {\n if (pkt === null) {\n if (commands.length === 0) {\n return malformed(\"no receive-pack commands\");\n }\n if (!capabilities.has(\"push-options\")) return complete();\n phase = \"options\";\n continue;\n }\n if (pkt.startsWith(\"shallow \")) continue;\n const nul = pkt.indexOf(\"\\0\");\n const command = nul === -1 ? pkt : pkt.slice(0, nul);\n if (nul !== -1) {\n for (const cap of pkt.slice(nul + 1).split(\" \")) {\n if (cap !== \"\") capabilities.add(cap);\n }\n }\n const [oldId, newId, ref, extra] = command.split(\" \");\n if (\n oldId === undefined ||\n newId === undefined ||\n ref === undefined ||\n extra !== undefined ||\n !OID.test(oldId) ||\n !OID.test(newId)\n ) {\n return malformed(\"bad receive-pack command\");\n }\n if (!isValidRefName(ref)) return malformed(\"invalid ref name\");\n if (commands.length >= maxCommands) {\n return malformed(\"too many receive-pack commands\");\n }\n commands.push({ oldId, newId, ref });\n continue;\n }\n // Push options.\n if (pkt === null) return complete();\n if (options.length >= maxOptions)\n return malformed(\"too many push options\");\n options.push(pkt);\n }\n };\n\n return {\n push: (chunk) => {\n if (phase === \"done\") return result;\n pending = concat(pending, chunk);\n return step();\n },\n remainder: () => (phase === \"done\" ? pending : new Uint8Array(0)),\n };\n};\n\n/**\n * Parses as much of the receive-pack head as `bytes` holds. A convenience\n * for a buffered prefix; streaming proxies should use\n * `makeReceivePackHeadParser` and feed chunks as they arrive.\n */\nexport const parseReceivePackHead = (\n bytes: Uint8Array,\n limits?: ReceivePackLimits,\n): ReceivePackParse => makeReceivePackHeadParser(limits).push(bytes);\n\nexport interface PushPolicy {\n /** The project's default branch name, refreshed from GitLab by project ID. */\n readonly defaultBranch: string;\n /** Allow pushing to the default branch. Default false. */\n readonly allowDefaultBranch?: boolean;\n /** Only branches with this prefix may be updated, when set. */\n readonly branchPrefix?: string;\n /** Label every merge request created by push option must carry. */\n readonly requiredMergeRequestLabel: string;\n /** Whether `merge_request.*` options are allowed at all (the `open_mr` grant). */\n readonly allowMergeRequestOptions: boolean;\n}\n\nconst MERGE_REQUEST_OPTIONS = [\n /^merge_request\\.create$/,\n /^merge_request\\.target=[\\w./-]{1,255}$/,\n /^merge_request\\.title=.{1,255}$/s,\n /^merge_request\\.description=.{0,10000}$/s,\n /^merge_request\\.label=[\\w.:-]{1,100}$/,\n /^merge_request\\.remove_source_branch$/,\n /^merge_request\\.draft$/,\n];\n\n/**\n * Returns the reason a push is denied, or undefined when it is allowed.\n * Denies tags and other non-branch refs, deletions, the default branch, and\n * any push option outside the merge request allow-list. GitLab still applies\n * its own branch protection afterwards.\n */\nexport const evaluatePush = (\n head: ReceivePackHead,\n policy: PushPolicy,\n): string | undefined => {\n for (const c of head.commands) {\n if (!c.ref.startsWith(\"refs/heads/\")) return `ref ${c.ref} is not a branch`;\n if (/^0+$/.test(c.newId)) return `deleting ${c.ref} is not allowed`;\n const branch = c.ref.slice(\"refs/heads/\".length);\n if (branch === policy.defaultBranch && policy.allowDefaultBranch !== true) {\n return \"pushing to the default branch is not allowed\";\n }\n if (\n policy.branchPrefix !== undefined &&\n !branch.startsWith(policy.branchPrefix)\n ) {\n return `branch ${branch} is outside ${policy.branchPrefix}`;\n }\n }\n for (const option of head.options) {\n const name = option.split(\"=\")[0] ?? option;\n if (\n !policy.allowMergeRequestOptions ||\n !MERGE_REQUEST_OPTIONS.some((re) => re.test(option))\n ) {\n return `push option ${name} is not allowed`;\n }\n }\n if (\n head.options.includes(\"merge_request.create\") &&\n !head.options.includes(\n `merge_request.label=${policy.requiredMergeRequestLabel}`,\n )\n ) {\n return `merge requests must carry merge_request.label=${policy.requiredMergeRequestLabel}`;\n }\n return undefined;\n};\n","// Pure attribution helpers. GitLab merge requests have no delegation marker,\n// so output carries a content marker that names the application\n// (docs/IDENTITY_MODEL.md).\n\nexport interface CommitIdentity {\n readonly name: string;\n readonly email: string;\n}\n\n/** The commit author for a GitLab user: their name and `commit_email`. */\nexport const commitAuthor = (user: {\n readonly name: string;\n readonly username: string;\n readonly commitEmail?: string;\n}): CommitIdentity => {\n if (user.commitEmail === undefined) {\n throw new Error(`GitLab user ${user.username} has no commit email`);\n }\n return { name: user.name || user.username, email: user.commitEmail };\n};\n\nconst oneLine = (value: string) => value.replace(/[\\r\\n]+/g, \" \").trim();\n\n/** `Assisted-by: <app> <session URL>`, added to every commit. */\nexport const assistedByTrailer = (\n appName: string,\n sessionUrl: string,\n): string => `Assisted-by: ${oneLine(appName)} <${oneLine(sessionUrl)}>`;\n\n/** `Co-authored-by` for a participant or, with the app principal, the requester. */\nexport const coAuthoredByTrailer = (who: CommitIdentity): string =>\n `Co-authored-by: ${oneLine(who.name)} <${oneLine(who.email)}>`;\n\n/** Description footer for merge requests and comments. */\nexport const mergeRequestFooter = (input: {\n readonly appName: string;\n readonly sessionUrl: string;\n /** Username of the requesting user; set when the app principal authors. */\n readonly requestedBy?: string;\n}): string =>\n [\n \"---\",\n input.requestedBy === undefined\n ? `Opened through ${oneLine(input.appName)}: ${oneLine(input.sessionUrl)}`\n : `Requested by @${oneLine(input.requestedBy)} via ${oneLine(input.appName)}: ${oneLine(input.sessionUrl)}`,\n ].join(\"\\n\");\n\n/** `git push -o` options that create a labelled merge request. */\nexport const mergeRequestPushOptions = (input: {\n readonly target: string;\n readonly title: string;\n readonly description: string;\n readonly label: string;\n}): readonly string[] => [\n \"merge_request.create\",\n `merge_request.target=${input.target}`,\n `merge_request.title=${oneLine(input.title)}`,\n // git rejects push options that contain a newline.\n `merge_request.description=${oneLine(input.description)}`,\n `merge_request.label=${input.label}`,\n];\n","import {\n ProviderError,\n type BondProvider,\n type ProviderAppConfig,\n type SecretRef,\n} from \"@openma/matter/bond\";\nimport { Effect } from \"effect\";\nimport type { Fetch } from \"./http.js\";\nimport { refreshAccessToken, revokeToken, type OAuthClient } from \"./oauth.js\";\nimport { revokeSelfToken } from \"./tokens.js\";\n\nexport interface GitLabBondProviderOptions {\n readonly fetch?: Fetch;\n readonly clock?: () => string;\n /** Resolves `oauth.clientSecret` references. Omit for public clients. */\n readonly resolveSecret?: (ref: SecretRef) => Effect.Effect<string, unknown>;\n}\n\n/**\n * Bond's GitLab provider. A configured `oauth.clientSecret` requires\n * `resolveSecret`; the provider never silently degrades to a public client. GitLab has no delegation marker, so user-principal\n * writes need the ProviderApp's `allowUserPrincipalOutput`. The app principal\n * is a registered bot credential stored on the Installation; GitLab 17.1\n * cannot rotate it from the bot itself, so an administrator replaces it.\n */\nexport const makeGitLabBondProvider = (\n options: GitLabBondProviderOptions = {},\n): BondProvider => {\n const client = (config: ProviderAppConfig) =>\n Effect.gen(function* () {\n // Configuration problems are not grant rejections: they must not end\n // every link of the ProviderApp.\n if (config.oauth === undefined) {\n return yield* Effect.fail(\n new ProviderError({\n message: `${config.id} has no OAuth application`,\n rejected: false,\n }),\n );\n }\n const secretRef = config.oauth.clientSecret;\n if (secretRef !== undefined && options.resolveSecret === undefined) {\n return yield* Effect.fail(\n new ProviderError({\n message: `${config.id} has an OAuth client secret but the provider has no resolveSecret`,\n rejected: false,\n }),\n );\n }\n const clientSecret =\n secretRef === undefined || options.resolveSecret === undefined\n ? undefined\n : yield* options.resolveSecret(secretRef).pipe(\n Effect.mapError(\n (cause) =>\n new ProviderError({\n message: \"Unable to resolve the OAuth client secret\",\n rejected: false,\n cause,\n }),\n ),\n );\n const c: OAuthClient = {\n origin: config.baseUrl,\n clientId: config.oauth.clientId,\n ...(clientSecret === undefined ? {} : { clientSecret }),\n ...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n ...(options.clock === undefined ? {} : { clock: options.clock }),\n };\n return c;\n });\n\n return {\n provider: \"gitlab\",\n delegationMarker: false,\n refreshUserToken: (config, refreshToken) =>\n client(config).pipe(\n Effect.flatMap((c) => refreshAccessToken(c, refreshToken)),\n ),\n revokeUserToken: (config, tokens) =>\n tokens.method === \"pat\"\n ? revokeSelfToken(config.baseUrl, tokens.accessToken, options.fetch)\n : client(config).pipe(\n Effect.flatMap((c) => revokeToken(c, tokens.accessToken)),\n ),\n appCredential: (config, installation, stored) =>\n stored === undefined\n ? Effect.fail(\n new ProviderError({\n message: `Installation ${installation.id} of ${config.id} has no bot credential`,\n rejected: true,\n }),\n )\n : Effect.succeed({\n token: stored,\n ...(installation.credentialExpiresAt === undefined\n ? {}\n : { expiresAt: installation.credentialExpiresAt }),\n }),\n };\n};\n","import {\n ProviderError,\n checkResourceRequest,\n resourceId,\n type BondBinding,\n type BondManifest,\n type BondResource,\n type BondResourceCatalog,\n} from \"@openma/matter/bond\";\nimport { Effect } from \"effect\";\nimport type { GitLabOperation } from \"./classify.js\";\nimport {\n bearer,\n isRecord,\n requestJson,\n statusError,\n type Fetch,\n} from \"./http.js\";\nimport {\n makeGitLabBondProvider,\n type GitLabBondProviderOptions,\n} from \"./provider.js\";\n\n/** Minimum GitLab access level per operation: 20 Reporter, 30 Developer. */\nexport const GITLAB_MIN_ACCESS_LEVEL: Readonly<\n Record<GitLabOperation, number>\n> = {\n fetch: 20,\n read: 20,\n push: 30,\n open_mr: 30,\n comment_mr: 30,\n};\n\nexport const gitlabManifest: BondManifest = {\n provider: \"gitlab\",\n title: \"GitLab\",\n docsUrl: \"https://docs.gitlab.com/integration/oauth_provider/\",\n setupSchema: {\n type: \"object\",\n properties: {\n baseUrl: {\n type: \"string\",\n title: \"Instance URL\",\n format: \"uri\",\n description:\n \"Canonical https origin, such as https://gitlab.example.com\",\n },\n oauthClientId: {\n type: \"string\",\n title: \"OAuth application ID\",\n description:\n \"Optional. Without an OAuth application, users link with personal access tokens.\",\n },\n oauthClientSecret: {\n type: \"string\",\n title: \"OAuth application secret\",\n \"x-secret\": true,\n },\n linkMethodPolicy: {\n type: \"string\",\n title: \"Link methods\",\n enum: [\"pat_only\", \"oauth_only\", \"oauth_preferred\"],\n default: \"oauth_preferred\",\n },\n principalPolicy: {\n type: \"string\",\n title: \"Principal policy\",\n enum: [\"user_only\", \"user\", \"app\"],\n default: \"user_only\",\n },\n maxPatLifetimeDays: {\n type: \"integer\",\n title: \"Maximum personal access token lifetime, in days\",\n minimum: 1,\n maximum: 365,\n default: 90,\n },\n allowUserPrincipalOutput: {\n type: \"boolean\",\n title: \"Allow writes as the linked user\",\n default: false,\n },\n },\n required: [\"baseUrl\", \"linkMethodPolicy\", \"principalPolicy\"],\n },\n linkMethods: [\"oauth\", \"pat\"],\n resourceKinds: [\n {\n kind: \"project\",\n title: \"Project\",\n operations: [\n {\n name: \"fetch\",\n description: \"Clone and fetch over git\",\n access: \"read\",\n },\n {\n name: \"read\",\n description: \"Read the project through the REST API\",\n access: \"read\",\n },\n { name: \"push\", description: \"Push branches\", access: \"write\" },\n {\n name: \"open_mr\",\n description: \"Open merge requests\",\n access: \"write\",\n },\n {\n name: \"comment_mr\",\n description: \"Comment on merge requests\",\n access: \"write\",\n },\n ],\n },\n ],\n};\n\nconst PROJECT_ID = /^[1-9][0-9]{0,18}$/;\nconst DEFAULT_PAGE = 20;\nconst MAX_PAGE = 100;\n\nconst toResource = (body: unknown): BondResource | undefined => {\n if (!isRecord(body) || typeof body.id !== \"number\") return undefined;\n const title =\n typeof body.path_with_namespace === \"string\"\n ? body.path_with_namespace\n : typeof body.name === \"string\"\n ? body.name\n : String(body.id);\n return {\n id: resourceId(\"project\", body.id),\n kind: \"project\",\n title,\n ...(typeof body.web_url === \"string\" ? { url: body.web_url } : {}),\n };\n};\n\nconst accessLevel = (body: Record<string, unknown>): number => {\n const permissions = isRecord(body.permissions) ? body.permissions : {};\n const level = (key: string) => {\n const entry = permissions[key];\n return isRecord(entry) && typeof entry.access_level === \"number\"\n ? entry.access_level\n : 0;\n };\n return Math.max(level(\"project_access\"), level(\"group_access\"));\n};\n\nexport interface GitLabResourceCatalogOptions {\n readonly fetch?: Fetch;\n}\n\n/**\n * Projects as Bond resources, with IDs `project:<numeric id>`. Paths are\n * display data only. `list` returns projects where the token holds at least\n * Reporter; `validate` checks the access level each operation needs and\n * refuses writes to archived projects. An instance administrator without a\n * membership reports no access level and is treated as having none.\n */\nexport const makeGitLabResourceCatalog = (\n options: GitLabResourceCatalogOptions = {},\n): BondResourceCatalog => {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n return {\n list: ({ config, token, query, cursor, limit }) =>\n Effect.gen(function* () {\n const perPage = Math.min(Math.max(limit ?? DEFAULT_PAGE, 1), MAX_PAGE);\n const page =\n cursor !== undefined && /^[1-9][0-9]*$/.test(cursor) ? cursor : \"1\";\n const url = new URL(\"/api/v4/projects\", config.baseUrl);\n url.searchParams.set(\"membership\", \"true\");\n url.searchParams.set(\"min_access_level\", \"20\");\n url.searchParams.set(\"simple\", \"true\");\n url.searchParams.set(\"order_by\", \"last_activity_at\");\n url.searchParams.set(\"per_page\", String(perPage));\n url.searchParams.set(\"page\", page);\n if (query !== undefined && query.trim() !== \"\") {\n url.searchParams.set(\"search\", query.trim());\n }\n const response = yield* requestJson(fetchImpl, url.toString(), {\n headers: bearer(token),\n });\n if (response.status < 200 || response.status >= 300) {\n return yield* Effect.fail(\n statusError(\"GitLab project list\", response),\n );\n }\n const rows = Array.isArray(response.body) ? response.body : [];\n const items = rows.flatMap((row) => {\n const resource = toResource(row);\n return resource === undefined ? [] : [resource];\n });\n const next = response.headers?.get(\"x-next-page\") ?? \"\";\n return /^[1-9][0-9]*$/.test(next)\n ? { items, nextCursor: next }\n : { items };\n }),\n validate: ({ config, token, resource, operations }) =>\n Effect.gen(function* () {\n const checked = checkResourceRequest(\n gitlabManifest,\n resource,\n operations,\n );\n if (!checked.ok) return checked;\n if (!PROJECT_ID.test(checked.key)) {\n return {\n ok: false as const,\n reason: \"malformed_id\" as const,\n message: \"GitLab project resources use the numeric project ID\",\n };\n }\n const url = new URL(`/api/v4/projects/${checked.key}`, config.baseUrl);\n const response = yield* requestJson(fetchImpl, url.toString(), {\n headers: bearer(token),\n });\n if (response.status === 404 || response.status === 403) {\n return {\n ok: false as const,\n reason: \"not_found\" as const,\n message: `Project ${checked.key} is not visible to this token`,\n };\n }\n if (\n response.status < 200 ||\n response.status >= 300 ||\n !isRecord(response.body)\n ) {\n return yield* Effect.fail(\n statusError(\"GitLab project lookup\", response),\n );\n }\n const project = toResource(response.body);\n if (project === undefined || project.id !== resource) {\n return yield* Effect.fail(\n new ProviderError({\n message: \"GitLab project lookup returned a different project\",\n rejected: false,\n }),\n );\n }\n const required = Math.max(\n 0,\n ...operations.map(\n (op) => GITLAB_MIN_ACCESS_LEVEL[op as GitLabOperation] ?? Infinity,\n ),\n );\n const held = accessLevel(response.body);\n if (held < required) {\n return {\n ok: false as const,\n reason: \"insufficient_access\" as const,\n message: `Needs GitLab access level ${required}; the token holds ${held}`,\n };\n }\n const writes = operations.some(\n (op) =>\n checked.kind.operations.find((o) => o.name === op)?.access ===\n \"write\",\n );\n if (writes && response.body.archived === true) {\n return {\n ok: false as const,\n reason: \"insufficient_access\" as const,\n message: `Project ${checked.key} is archived`,\n };\n }\n return { ok: true as const, resource: project };\n }),\n };\n};\n\n/** The provider, manifest, and resource catalog a host registers for GitLab. */\nexport const makeGitLabBinding = (\n options: GitLabBondProviderOptions = {},\n): BondBinding => ({\n manifest: gitlabManifest,\n provider: makeGitLabBondProvider(options),\n resources: makeGitLabResourceCatalog(\n options.fetch === undefined ? {} : { fetch: options.fetch },\n ),\n});\n","import type { JsonValue, WorkEvent } from \"@openma/matter\";\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst sensitiveKeys = new Set([\n \"access_token\",\n \"authorization\",\n \"client_secret\",\n \"password\",\n \"private_key\",\n \"private_token\",\n \"runners_token\",\n \"secret\",\n \"secret_token\",\n \"token\",\n \"webhook_secret\",\n]);\n\n/** Webhook payloads are untrusted. Recursively remove conventional credential\n * keys before a provider snapshot can enter the durable event log. */\nexport const withoutGitLabCredentials = (value: JsonValue): JsonValue => {\n if (Array.isArray(value)) return value.map(withoutGitLabCredentials);\n if (!isRecord(value)) return value;\n return Object.fromEntries(\n Object.entries(value).flatMap(([key, nested]) =>\n sensitiveKeys.has(key.toLowerCase())\n ? []\n : [[key, withoutGitLabCredentials(nested as JsonValue)]],\n ),\n );\n};\n\nexport const gitlabSource = (input: {\n readonly authority: string;\n readonly project?: string;\n readonly threadId?: string;\n readonly messageId?: string;\n readonly uri?: string;\n}): WorkEvent[\"source\"] => ({\n provider: \"gitlab\",\n authority: input.authority,\n ...(input.project === undefined ? {} : { conversationId: input.project }),\n ...(input.threadId === undefined ? {} : { threadId: input.threadId }),\n ...(input.messageId === undefined ? {} : { messageId: input.messageId }),\n ...(input.uri === undefined ? {} : { uri: input.uri }),\n});\n\nexport const positiveInteger = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isSafeInteger(value) && value > 0;\n\nexport const nonEmptyString = (value: unknown): value is string =>\n typeof value === \"string\" && value.length > 0;\n\n/** GitLab timestamps come as ISO 8601 or as `2026-08-23 08:00:00 UTC`. */\nexport const isoTimestamp = (\n ...values: readonly unknown[]\n): string | undefined => {\n for (const value of values) {\n if (typeof value !== \"string\") continue;\n const parsed = Date.parse(\n value.replace(/^(\\d{4}-\\d{2}-\\d{2}) (\\d{2}:\\d{2}:\\d{2}) UTC$/, \"$1T$2Z\"),\n );\n if (Number.isFinite(parsed)) return new Date(parsed).toISOString();\n }\n return undefined;\n};\n","import { JsonValueSchema, type JsonValue } from \"@openma/matter\";\nimport {\n CredentialError,\n makeCredentialResolver,\n type CredentialResolver,\n} from \"@openma/matter/credentials\";\nimport { IntegrationError } from \"@openma/matter/integration\";\nimport { Effect, Schema } from \"effect\";\nimport { isRecord, nonEmptyString } from \"./shared.js\";\n\n/**\n * What a GitLab call needs for one authority: the instance and a token with\n * API access (a Bond's app principal token, or a test token).\n */\nexport interface GitLabCredentials {\n /** The instance root, for example `https://gitlab.example.com`. */\n readonly baseUrl: string;\n readonly token: string;\n}\n\nexport type GitLabCredentialResolver = CredentialResolver<GitLabCredentials>;\n\nexport type GitLabCredentialSource = (\n authority: string,\n) =>\n | GitLabCredentials\n | PromiseLike<GitLabCredentials>\n | Effect.Effect<GitLabCredentials, unknown>;\n\nexport type GitLabCredentialOption =\n GitLabCredentials | GitLabCredentialResolver | GitLabCredentialSource;\n\nexport type GitLabCredentialsFor = (\n authority: string,\n) => Effect.Effect<GitLabCredentials, IntegrationError>;\n\nconst invalid = (message: string) =>\n new IntegrationError({ message, retryable: false });\n\nconst validate = (\n value: unknown,\n): Effect.Effect<GitLabCredentials, IntegrationError> => {\n if (\n !isRecord(value) ||\n !nonEmptyString(value.token) ||\n !nonEmptyString(value.baseUrl)\n ) {\n return Effect.fail(\n invalid(\"GitLab credentials must include a baseUrl and a token\"),\n );\n }\n let url: URL;\n try {\n url = new URL(value.baseUrl);\n } catch {\n return Effect.fail(invalid(\"GitLab baseUrl is not a URL\"));\n }\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n return Effect.fail(invalid(\"GitLab baseUrl must use http or https\"));\n }\n return Effect.succeed({ baseUrl: url.href, token: value.token });\n};\n\nexport const makeGitLabCredentialsFor = (\n option: GitLabCredentialOption,\n): GitLabCredentialsFor => {\n if (typeof option === \"object\" && option !== null && !(\"resolve\" in option)) {\n const fixed = validate(option);\n return () => fixed;\n }\n const resolver: GitLabCredentialResolver =\n typeof option === \"function\"\n ? makeCredentialResolver(({ authority }) => option(authority))\n : option;\n return (authority) =>\n authority.length === 0\n ? Effect.fail(\n invalid(\"GitLab authority is required to resolve credentials\"),\n )\n : Effect.suspend(() =>\n resolver.resolve({ integrationId: \"gitlab\", authority }),\n ).pipe(\n Effect.mapError(\n (cause) =>\n new IntegrationError({\n message:\n cause instanceof CredentialError\n ? cause.message\n : `Unable to resolve GitLab credentials for ${authority}`,\n retryable:\n cause instanceof CredentialError ? cause.retryable : true,\n cause,\n }),\n ),\n Effect.flatMap(validate),\n );\n};\n\nexport interface GitLabResponse {\n readonly payload: JsonValue;\n readonly headers: Headers;\n}\n\nexport const makeGitLabClient = (input: {\n readonly credentialsFor: GitLabCredentialsFor;\n readonly fetch: typeof globalThis.fetch;\n readonly clock: () => string;\n}) => {\n const retryAtFrom = (response: Response): string | undefined => {\n const retryAfter = response.headers.get(\"retry-after\");\n if (retryAfter !== null) {\n const seconds = Number.parseFloat(retryAfter);\n if (Number.isFinite(seconds) && seconds >= 0) {\n const now = Date.parse(input.clock());\n if (Number.isFinite(now)) {\n return new Date(now + seconds * 1_000).toISOString();\n }\n }\n const absolute = Date.parse(retryAfter);\n if (Number.isFinite(absolute)) return new Date(absolute).toISOString();\n }\n if (response.status !== 429) return undefined;\n const reset = Number.parseInt(\n response.headers.get(\"ratelimit-reset\") ?? \"\",\n 10,\n );\n return Number.isSafeInteger(reset) && reset >= 0\n ? new Date(reset * 1_000).toISOString()\n : undefined;\n };\n\n /** Calls `/api/v4{path}` on the authority's instance. */\n const request = (options: {\n readonly authority: string;\n readonly method: \"DELETE\" | \"GET\" | \"POST\" | \"PUT\";\n readonly path: string;\n readonly body?: Readonly<Record<string, unknown>>;\n }): Effect.Effect<GitLabResponse, IntegrationError> => {\n const label = `GitLab ${options.method} ${options.path}`;\n return input.credentialsFor(options.authority).pipe(\n Effect.flatMap(({ baseUrl, token }) =>\n Effect.tryPromise({\n try: () =>\n input.fetch(\n new URL(\n `api/v4${options.path}`,\n baseUrl.endsWith(\"/\") ? baseUrl : `${baseUrl}/`,\n ),\n {\n method: options.method,\n headers: {\n accept: \"application/json\",\n authorization: `Bearer ${token}`,\n ...(options.body === undefined\n ? {}\n : { \"content-type\": \"application/json; charset=utf-8\" }),\n },\n ...(options.body === undefined\n ? {}\n : { body: JSON.stringify(options.body) }),\n },\n ),\n catch: (cause) =>\n new IntegrationError({\n message: `${label} request failed`,\n retryable: true,\n cause,\n }),\n }),\n ),\n Effect.flatMap((response) => {\n const retryable = response.status === 429 || response.status >= 500;\n const retryAt = retryAtFrom(response);\n const failure = (message: string, cause?: unknown) =>\n new IntegrationError({\n message,\n retryable,\n ...(retryAt === undefined ? {} : { retryAt }),\n ...(cause === undefined ? {} : { cause }),\n });\n return Effect.tryPromise({\n try: () => response.text(),\n catch: (cause) =>\n failure(`${label} response could not be read`, cause),\n }).pipe(\n Effect.flatMap((text) => {\n let payload: unknown = null;\n if (text.length > 0) {\n try {\n payload = JSON.parse(text) as unknown;\n } catch (cause) {\n return Effect.fail(\n response.ok\n ? failure(`${label} returned invalid JSON`, cause)\n : failure(`${label} failed with HTTP ${response.status}`),\n );\n }\n }\n if (!response.ok) {\n return Effect.fail(\n failure(\n `${label} failed with HTTP ${response.status}`,\n payload,\n ),\n );\n }\n if (!Schema.is(JsonValueSchema)(payload)) {\n return Effect.fail(\n failure(`${label} returned non-portable data`),\n );\n }\n return Effect.succeed({ payload, headers: response.headers });\n }),\n );\n }),\n );\n };\n\n return { request };\n};\n\nexport type GitLabClient = ReturnType<typeof makeGitLabClient>;\n","import {\n IntegrationError,\n type WorkIntegration,\n} from \"@openma/matter/integration\";\nimport { Effect } from \"effect\";\nimport type { GitLabClient } from \"./client.js\";\nimport { isRecord, nonEmptyString, positiveInteger } from \"./shared.js\";\n\n/** Every Effect operation `deliver` accepts. */\nexport const GITLAB_OPERATIONS = [\n \"merge_request.note.create\",\n \"merge_request.discussion.reply\",\n \"issue.note.create\",\n \"issue.discussion.reply\",\n] as const;\n\nexport type GitLabEffectOperation = (typeof GITLAB_OPERATIONS)[number];\n\nconst fail = (message: string) =>\n Effect.fail(new IntegrationError({ message, retryable: false }));\n\n/**\n * Delivers GitLab Effects. Every input names the `authority` whose\n * credentials post the note, the `projectId` (numeric id or full path), the\n * merge request or issue `iid`, and a non-empty `body`. Discussion replies\n * also name the `discussionId`; replying to a single comment turns it into a\n * thread.\n */\nexport const makeGitLabDelivery =\n (client: Pick<GitLabClient, \"request\">): WorkIntegration[\"deliver\"] =>\n (effect) => {\n const operation = GITLAB_OPERATIONS.find(\n (name) => name === effect.operation,\n );\n if (effect.integrationId !== \"gitlab\" || operation === undefined) {\n return fail(`GitLab does not support the operation ${effect.operation}`);\n }\n if (!isRecord(effect.input)) {\n return fail(`GitLab ${operation} requires an object input`);\n }\n const { authority, projectId, body, discussionId } = effect.input;\n const [parent, iidKey] = operation.startsWith(\"merge_request.\")\n ? ([\"merge_requests\", \"mergeRequestIid\"] as const)\n : ([\"issues\", \"issueIid\"] as const);\n const iid = effect.input[iidKey];\n const replying = operation.endsWith(\".discussion.reply\");\n if (\n !nonEmptyString(authority) ||\n !(positiveInteger(projectId) || nonEmptyString(projectId)) ||\n !positiveInteger(iid) ||\n !nonEmptyString(body) ||\n (replying && !nonEmptyString(discussionId))\n ) {\n return fail(\n `GitLab ${operation} requires authority, projectId, a positive ${iidKey}, ${\n replying ? \"discussionId, \" : \"\"\n }and a non-empty body`,\n );\n }\n const base = `/projects/${encodeURIComponent(String(projectId))}/${parent}/${iid}`;\n const path = replying\n ? `${base}/discussions/${encodeURIComponent(discussionId as string)}/notes`\n : `${base}/notes`;\n return client\n .request({ authority, method: \"POST\", path, body: { body } })\n .pipe(\n Effect.map(({ payload }) => ({\n providerReceipt: isRecord(payload)\n ? {\n ...(positiveInteger(payload.id) ? { noteId: payload.id } : {}),\n ...(nonEmptyString(discussionId) ? { discussionId } : {}),\n }\n : null,\n })),\n );\n };\n","import {\n JsonValueSchema,\n type JsonValue,\n type WorkEvent,\n} from \"@openma/matter\";\nimport { IntegrationError } from \"@openma/matter/integration\";\nimport { Effect, Schema } from \"effect\";\nimport type { GitLabWebhookInput } from \"./http.js\";\nimport {\n gitlabSource,\n isRecord,\n isoTimestamp,\n nonEmptyString,\n positiveInteger,\n withoutGitLabCredentials,\n} from \"./shared.js\";\n\nconst MERGE_REQUEST_ACTIONS: Readonly<Record<string, string>> = {\n open: \"opened\",\n reopen: \"reopened\",\n update: \"updated\",\n close: \"closed\",\n merge: \"merged\",\n approved: \"approved\",\n unapproved: \"unapproved\",\n approval: \"approval_added\",\n unapproval: \"approval_removed\",\n};\n\nconst NOTEABLE_KINDS: Readonly<Record<string, string>> = {\n MergeRequest: \"merge_request\",\n Issue: \"issue\",\n Commit: \"commit\",\n Snippet: \"snippet\",\n};\n\nconst PIPELINE_STATUSES = [\n \"created\",\n \"waiting_for_resource\",\n \"preparing\",\n \"pending\",\n \"running\",\n \"success\",\n \"failed\",\n \"canceled\",\n \"skipped\",\n \"manual\",\n \"scheduled\",\n] as const;\n\n/** Every Event type `ingest` can produce. */\nexport const GITLAB_EVENT_TYPES: readonly string[] = [\n ...Object.values(MERGE_REQUEST_ACTIONS).map(\n (action) => `gitlab.merge_request.${action}`,\n ),\n ...Object.values(NOTEABLE_KINDS).flatMap((kind) => [\n `gitlab.${kind}.note.created`,\n `gitlab.${kind}.note.updated`,\n ]),\n ...PIPELINE_STATUSES.map((status) => `gitlab.pipeline.${status}`),\n \"gitlab.event.received\",\n];\n\ntype Fields = Record<string, JsonValue>;\n\ninterface Normalized {\n readonly type: string;\n readonly threadId?: string;\n readonly messageId?: string;\n readonly uri?: string;\n readonly occurredAt?: string;\n readonly fields: Fields;\n}\n\nconst optional = (key: string, value: JsonValue | undefined): Fields =>\n value === undefined ? {} : { [key]: value };\n\nconst mergeRequest = (attributes: Record<string, unknown>): Normalized => {\n const action =\n typeof attributes.action === \"string\"\n ? MERGE_REQUEST_ACTIONS[attributes.action]\n : undefined;\n const iid = positiveInteger(attributes.iid) ? attributes.iid : undefined;\n const lastCommit = isRecord(attributes.last_commit)\n ? attributes.last_commit\n : undefined;\n const draft =\n typeof attributes.draft === \"boolean\"\n ? attributes.draft\n : typeof attributes.work_in_progress === \"boolean\"\n ? attributes.work_in_progress\n : undefined;\n const uri = nonEmptyString(attributes.url) ? attributes.url : undefined;\n const occurredAt = isoTimestamp(attributes.updated_at, attributes.created_at);\n return {\n type:\n action === undefined\n ? \"gitlab.event.received\"\n : `gitlab.merge_request.${action}`,\n ...(iid === undefined ? {} : { threadId: `merge_request:${iid}` }),\n ...(uri === undefined ? {} : { uri }),\n ...(occurredAt === undefined ? {} : { occurredAt }),\n fields: {\n resourceType: \"merge_request\",\n ...optional(\"mergeRequestIid\", iid),\n ...optional(\n \"title\",\n typeof attributes.title === \"string\" ? attributes.title : undefined,\n ),\n ...optional(\"draft\", draft),\n ...optional(\n \"state\",\n typeof attributes.state === \"string\" ? attributes.state : undefined,\n ),\n ...optional(\n \"sourceBranch\",\n nonEmptyString(attributes.source_branch)\n ? attributes.source_branch\n : undefined,\n ),\n ...optional(\n \"targetBranch\",\n nonEmptyString(attributes.target_branch)\n ? attributes.target_branch\n : undefined,\n ),\n ...optional(\n \"headSha\",\n nonEmptyString(lastCommit?.id) ? lastCommit.id : undefined,\n ),\n // GitLab sets `oldrev` on an update only when commits were pushed.\n newCommits:\n attributes.action === \"open\" ||\n attributes.action === \"reopen\" ||\n (attributes.action === \"update\" && nonEmptyString(attributes.oldrev)),\n },\n };\n};\n\nconst note = (\n attributes: Record<string, unknown>,\n payload: Record<string, unknown>,\n): Normalized => {\n const kind =\n typeof attributes.noteable_type === \"string\"\n ? NOTEABLE_KINDS[attributes.noteable_type]\n : undefined;\n // GitLab before 16.x sends no `action`; every such delivery is a creation.\n const action =\n attributes.action === undefined || attributes.action === \"create\"\n ? \"created\"\n : attributes.action === \"update\"\n ? \"updated\"\n : undefined;\n const parent =\n kind === \"merge_request\"\n ? payload.merge_request\n : kind === \"issue\"\n ? payload.issue\n : kind === \"commit\"\n ? payload.commit\n : kind === \"snippet\"\n ? payload.snippet\n : undefined;\n const parentRecord = isRecord(parent) ? parent : undefined;\n const parentIid = positiveInteger(parentRecord?.iid)\n ? parentRecord.iid\n : undefined;\n const threadId =\n kind === \"merge_request\" || kind === \"issue\"\n ? parentIid === undefined\n ? undefined\n : `${kind}:${parentIid}`\n : kind === \"commit\"\n ? nonEmptyString(parentRecord?.id)\n ? `commit:${parentRecord.id}`\n : undefined\n : kind === \"snippet\" && positiveInteger(parentRecord?.id)\n ? `snippet:${parentRecord.id}`\n : undefined;\n const noteId = positiveInteger(attributes.id) ? attributes.id : undefined;\n const uri = nonEmptyString(attributes.url) ? attributes.url : undefined;\n const occurredAt = isoTimestamp(attributes.updated_at, attributes.created_at);\n return {\n type:\n kind === undefined || action === undefined\n ? \"gitlab.event.received\"\n : `gitlab.${kind}.note.${action}`,\n ...(threadId === undefined ? {} : { threadId }),\n ...(noteId === undefined ? {} : { messageId: `note:${noteId}` }),\n ...(uri === undefined ? {} : { uri }),\n ...(occurredAt === undefined ? {} : { occurredAt }),\n fields: {\n resourceType: \"note\",\n ...optional(\"noteId\", noteId),\n ...optional(\n \"text\",\n typeof attributes.note === \"string\" ? attributes.note : undefined,\n ),\n ...optional(\n \"discussionId\",\n nonEmptyString(attributes.discussion_id)\n ? attributes.discussion_id\n : undefined,\n ),\n ...optional(\n \"noteableType\",\n typeof attributes.noteable_type === \"string\"\n ? attributes.noteable_type\n : undefined,\n ),\n ...optional(\n kind === \"issue\" ? \"issueIid\" : \"mergeRequestIid\",\n kind === \"merge_request\" || kind === \"issue\" ? parentIid : undefined,\n ),\n ...optional(\n \"draft\",\n kind === \"merge_request\" && typeof parentRecord?.draft === \"boolean\"\n ? parentRecord.draft\n : undefined,\n ),\n system: attributes.system === true,\n },\n };\n};\n\nconst pipeline = (\n attributes: Record<string, unknown>,\n payload: Record<string, unknown>,\n): Normalized => {\n const status = PIPELINE_STATUSES.find(\n (candidate) => candidate === attributes.status,\n );\n const id = positiveInteger(attributes.id) ? attributes.id : undefined;\n const mergeRequestIid =\n isRecord(payload.merge_request) &&\n positiveInteger(payload.merge_request.iid)\n ? payload.merge_request.iid\n : undefined;\n const uri = nonEmptyString(attributes.url) ? attributes.url : undefined;\n const occurredAt = isoTimestamp(\n attributes.finished_at,\n attributes.created_at,\n );\n return {\n type:\n status === undefined\n ? \"gitlab.event.received\"\n : `gitlab.pipeline.${status}`,\n // A merge request pipeline joins the merge request's thread.\n ...(mergeRequestIid !== undefined\n ? { threadId: `merge_request:${mergeRequestIid}` }\n : id === undefined\n ? {}\n : { threadId: `pipeline:${id}` }),\n ...(id === undefined || status === undefined\n ? {}\n : { messageId: `pipeline:${id}:${status}` }),\n ...(uri === undefined ? {} : { uri }),\n ...(occurredAt === undefined ? {} : { occurredAt }),\n fields: {\n resourceType: \"pipeline\",\n ...optional(\"pipelineId\", id),\n ...optional(\"status\", status),\n ...optional(\n \"ref\",\n nonEmptyString(attributes.ref) ? attributes.ref : undefined,\n ),\n ...optional(\n \"sha\",\n nonEmptyString(attributes.sha) ? attributes.sha : undefined,\n ),\n ...optional(\"mergeRequestIid\", mergeRequestIid),\n },\n };\n};\n\nconst normalize = (payload: Record<string, unknown>): Normalized => {\n const attributes = isRecord(payload.object_attributes)\n ? payload.object_attributes\n : undefined;\n if (attributes !== undefined) {\n if (payload.object_kind === \"merge_request\")\n return mergeRequest(attributes);\n if (payload.object_kind === \"note\") return note(attributes, payload);\n if (payload.object_kind === \"pipeline\")\n return pipeline(attributes, payload);\n }\n return { type: \"gitlab.event.received\", fields: {} };\n};\n\n/**\n * Turns a verified `GitLabWebhookInput` into one WorkEvent. Inputs of another\n * kind produce no Events. The Event id combines the authority and the\n * delivery id, so a GitLab retry is the same Event.\n */\nexport const normalizeGitLabEvents = (\n input: unknown,\n clock: () => string,\n): Effect.Effect<readonly WorkEvent[], IntegrationError> =>\n Effect.try({\n try: () => {\n if (\n !isRecord(input) ||\n input.kind !== \"gitlab.webhook\" ||\n !nonEmptyString(input.authority) ||\n !nonEmptyString(input.eventName) ||\n !nonEmptyString(input.deliveryId) ||\n !isRecord(input.payload) ||\n !Schema.is(JsonValueSchema)(input.payload)\n ) {\n return [];\n }\n const webhook = input as unknown as GitLabWebhookInput;\n const payload = webhook.payload as Record<string, unknown>;\n const project = isRecord(payload.project) ? payload.project : undefined;\n const projectId = positiveInteger(project?.id)\n ? project.id\n : positiveInteger(payload.project_id)\n ? payload.project_id\n : undefined;\n const projectPath = nonEmptyString(project?.path_with_namespace)\n ? project.path_with_namespace\n : undefined;\n const user = isRecord(payload.user) ? payload.user : undefined;\n const actor: Fields = {\n ...optional(\n \"id\",\n positiveInteger(user?.id) ? String(user.id) : undefined,\n ),\n ...optional(\n \"username\",\n nonEmptyString(user?.username) ? user.username : undefined,\n ),\n ...optional(\"name\", nonEmptyString(user?.name) ? user.name : undefined),\n };\n const normalized = normalize(payload);\n const receivedAt = clock();\n const id = `gitlab:${webhook.authority}:${webhook.deliveryId}`;\n const event: WorkEvent = {\n schemaVersion: \"0.1\",\n id,\n type: normalized.type,\n occurredAt: normalized.occurredAt ?? receivedAt,\n receivedAt,\n idempotencyKey: id,\n source: gitlabSource({\n authority: webhook.authority,\n ...(projectPath === undefined ? {} : { project: projectPath }),\n ...(normalized.threadId === undefined\n ? {}\n : { threadId: normalized.threadId }),\n ...(normalized.messageId === undefined\n ? {}\n : { messageId: normalized.messageId }),\n ...(normalized.uri === undefined ? {} : { uri: normalized.uri }),\n }),\n payload: {\n activation: \"observation\",\n eventName: webhook.eventName,\n ...optional(\n \"objectKind\",\n nonEmptyString(payload.object_kind)\n ? payload.object_kind\n : undefined,\n ),\n authority: webhook.authority,\n ...optional(\"instance\", webhook.instance),\n ...optional(\"projectId\", projectId),\n ...optional(\"project\", projectPath),\n // The Bond resource id, so a Loop can match its configured projects.\n ...optional(\n \"resource\",\n projectId === undefined ? undefined : `project:${projectId}`,\n ),\n ...normalized.fields,\n ...(Object.keys(actor).length === 0 ? {} : { actor }),\n },\n raw: withoutGitLabCredentials(webhook.payload),\n };\n return [event];\n },\n catch: (cause) =>\n new IntegrationError({\n message: \"Unable to normalize GitLab webhook\",\n retryable: false,\n cause,\n }),\n });\n","import { JsonValueSchema, type JsonValue } from \"@openma/matter\";\nimport type { HttpEndpoint } from \"@openma/matter/http\";\nimport { Data, Effect, Schema } from \"effect\";\nimport { isRecord } from \"./shared.js\";\n\nexport class GitLabHttpIngressError extends Data.TaggedError(\n \"GitLabHttpIngressError\",\n)<{\n readonly message: string;\n readonly status: 400 | 401;\n readonly cause?: unknown;\n}> {}\n\nexport class GitLabHttpSubmissionError extends Data.TaggedError(\n \"GitLabHttpSubmissionError\",\n)<{\n readonly message: string;\n readonly status: 503;\n readonly cause?: unknown;\n}> {}\n\n/** One verified GitLab webhook delivery, ready for `integration.ingest`. */\nexport interface GitLabWebhookInput {\n readonly kind: \"gitlab.webhook\";\n /**\n * Who received the webhook, chosen by the host (for example a Bond id).\n * It becomes the Event source authority and selects credentials for replies.\n */\n readonly authority: string;\n /** The `X-Gitlab-Event` header, for example `Merge Request Hook`. */\n readonly eventName: string;\n /** Stable across GitLab retries; see `decodeGitLabHttpRequest`. */\n readonly deliveryId: string;\n /** The `X-Gitlab-Instance` header (GitLab 15.5+), when present. */\n readonly instance?: string;\n readonly payload: JsonValue;\n}\n\nexport interface GitLabHttpEndpointOptions {\n /** The secret token configured on the GitLab webhook. */\n readonly webhookToken: string;\n readonly authority: string;\n readonly path?: string;\n readonly submit: (input: GitLabWebhookInput) => Promise<unknown>;\n}\n\nconst sha256 = async (value: string): Promise<Uint8Array> =>\n new Uint8Array(\n await globalThis.crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(value),\n ),\n );\n\n/**\n * Compares the `X-Gitlab-Token` header with the configured secret token in\n * constant time. Both values are hashed first, so the comparison does not\n * reveal the secret's length either. An empty configured token never matches.\n */\nexport const verifyGitLabToken = (input: {\n readonly webhookToken: string;\n readonly received: string;\n}): Effect.Effect<boolean, GitLabHttpIngressError> =>\n Effect.tryPromise({\n try: async () => {\n if (input.webhookToken.length === 0) return false;\n const [expected, received] = await Promise.all([\n sha256(input.webhookToken),\n sha256(input.received),\n ]);\n let difference = 0;\n for (let index = 0; index < expected.length; index += 1) {\n difference |= expected[index]! ^ received[index]!;\n }\n return difference === 0;\n },\n catch: (cause) =>\n new GitLabHttpIngressError({\n message: \"Unable to verify GitLab request\",\n status: 401,\n cause,\n }),\n });\n\nconst header = (request: Request, name: string): string | undefined => {\n const value = request.headers.get(name);\n return value === null || value.length === 0 ? undefined : value;\n};\n\n/**\n * Verifies and decodes one GitLab webhook request. The delivery id is the\n * first of `webhook-id` and `Idempotency-Key` (both stable across retries,\n * GitLab 17.4+) and `X-Gitlab-Event-UUID` (GitLab 14.8+).\n */\nexport const decodeGitLabHttpRequest = (\n request: Request,\n options: Pick<GitLabHttpEndpointOptions, \"webhookToken\" | \"authority\">,\n): Effect.Effect<GitLabWebhookInput, GitLabHttpIngressError> =>\n Effect.gen(function* () {\n const verified = yield* verifyGitLabToken({\n webhookToken: options.webhookToken,\n received: header(request, \"x-gitlab-token\") ?? \"\",\n });\n if (!verified) {\n return yield* new GitLabHttpIngressError({\n message: \"GitLab webhook token is invalid\",\n status: 401,\n });\n }\n const eventName = header(request, \"x-gitlab-event\");\n const deliveryId =\n header(request, \"webhook-id\") ??\n header(request, \"idempotency-key\") ??\n header(request, \"x-gitlab-event-uuid\");\n if (eventName === undefined || deliveryId === undefined) {\n return yield* new GitLabHttpIngressError({\n message: \"GitLab event and delivery id headers are required\",\n status: 400,\n });\n }\n const rawBody = yield* Effect.tryPromise({\n try: () => request.text(),\n catch: (cause) =>\n new GitLabHttpIngressError({\n message: \"Unable to read GitLab request body\",\n status: 400,\n cause,\n }),\n });\n const payload = yield* Effect.try({\n try: () => JSON.parse(rawBody) as unknown,\n catch: (cause) =>\n new GitLabHttpIngressError({\n message: \"GitLab request body is malformed\",\n status: 400,\n cause,\n }),\n });\n if (!isRecord(payload) || !Schema.is(JsonValueSchema)(payload)) {\n return yield* new GitLabHttpIngressError({\n message: \"GitLab request body must be a portable JSON object\",\n status: 400,\n });\n }\n const instance = header(request, \"x-gitlab-instance\");\n return {\n kind: \"gitlab.webhook\",\n authority: options.authority,\n eventName,\n deliveryId,\n ...(instance === undefined ? {} : { instance }),\n payload: payload as JsonValue,\n };\n });\n\nconst jsonResponse = (body: unknown, status: number): Response =>\n new Response(JSON.stringify(body), {\n status,\n headers: { \"content-type\": \"application/json; charset=utf-8\" },\n });\n\n/**\n * A webhook endpoint for one GitLab authority. Hosts that serve many\n * authorities from one route call `decodeGitLabHttpRequest` with the token\n * and authority they look up for the request instead.\n */\nexport const makeGitLabHttpEndpoint = (\n options: GitLabHttpEndpointOptions,\n): HttpEndpoint => ({\n method: \"POST\",\n path: options.path ?? \"/gitlab/events\",\n handle: (request) =>\n Effect.runPromise(\n decodeGitLabHttpRequest(request, options).pipe(\n Effect.flatMap((input) =>\n Effect.tryPromise({\n try: () => options.submit(input),\n catch: (cause) =>\n new GitLabHttpSubmissionError({\n message: \"Unable to submit GitLab work\",\n status: 503,\n cause,\n }),\n }).pipe(Effect.as(new Response(null, { status: 202 }))),\n ),\n Effect.catchAll((error) =>\n Effect.succeed(\n jsonResponse({ ok: false, error: error.message }, error.status),\n ),\n ),\n ),\n ),\n});\n","import type { WorkIntegration } from \"@openma/matter/integration\";\nimport {\n makeGitLabClient,\n makeGitLabCredentialsFor,\n type GitLabCredentialOption,\n} from \"./client.js\";\nimport { GITLAB_OPERATIONS, makeGitLabDelivery } from \"./delivery.js\";\nimport { GITLAB_EVENT_TYPES, normalizeGitLabEvents } from \"./events.js\";\n\nexport interface GitLabIntegrationOptions {\n /**\n * Credentials for replies: fixed `{ baseUrl, token }`, or a resolver keyed\n * by the Event authority (for example a Bond's app principal).\n */\n readonly credentials: GitLabCredentialOption;\n readonly fetch?: typeof globalThis.fetch;\n readonly clock?: () => string;\n}\n\n/**\n * The GitLab work integration: `ingest` takes a `GitLabWebhookInput` from\n * `decodeGitLabHttpRequest`, and `deliver` posts merge request and issue\n * notes.\n */\nexport const makeGitLabIntegration = (\n options: GitLabIntegrationOptions,\n): WorkIntegration => {\n const clock = options.clock ?? (() => new Date().toISOString());\n const client = makeGitLabClient({\n credentialsFor: makeGitLabCredentialsFor(options.credentials),\n fetch: options.fetch ?? ((...args) => globalThis.fetch(...args)),\n clock,\n });\n return {\n manifest: {\n id: \"gitlab\",\n displayName: \"GitLab\",\n events: GITLAB_EVENT_TYPES,\n operations: GITLAB_OPERATIONS,\n },\n ingest: (input) => normalizeGitLabEvents(input, clock),\n deliver: makeGitLabDelivery(client),\n };\n};\n","// The GitLab Loop templates. They are guest Loops: they import only\n// `@openma/matter-loop`, so a host can run them in process or in an isolate, and\n// their definitions are JSON a console can render as a form.\n//\n// GitLab webhooks are unattended, so both templates run as the Bond's app\n// principal (`runAs: \"app\"`); a host enables them only when one is\n// configured. See docs/LOOPS.md, \"Execution principal\".\n\nimport {\n defineLoop,\n type JsonValue,\n type LoopConfig,\n type LoopWork,\n type ReactionDraft,\n type WorkEvent,\n} from \"@openma/matter-loop\";\n\nconst VERSION = \"0.1.0\";\n\nconst agentField = {\n type: \"string\",\n minLength: 1,\n title: \"Agent\",\n \"x-oma-widget\": \"agent\",\n} as const;\n\nconst projectsField = {\n type: \"array\",\n items: { type: \"string\", minLength: 1 },\n minItems: 1,\n title: \"Projects\",\n description: \"Bond resource ids of the projects the Loop watches\",\n \"x-oma-widget\": \"bond-resources\",\n \"x-bond-provider\": \"gitlab\",\n} as const;\n\nconst instructionsField = {\n type: \"string\",\n default: \"\",\n title: \"Extra instructions\",\n description: \"Appended to the instructions the Agent receives\",\n} as const;\n\ntype Fields = { readonly [key: string]: JsonValue };\n\n// `Array.isArray` does not narrow readonly arrays out of a union.\nconst isObject = (value: unknown): value is Fields =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst fields = (event: WorkEvent): Fields =>\n isObject(event.payload) ? event.payload : {};\n\nconst watched = (config: LoopConfig, event: WorkEvent): boolean => {\n const resource = fields(event).resource;\n return (\n typeof resource === \"string\" &&\n Array.isArray(config.projects) &&\n config.projects.includes(resource)\n );\n};\n\ninterface MergeRequestTarget {\n readonly authority: string;\n readonly projectId: number;\n readonly mergeRequestIid: number;\n}\n\nconst mergeRequestTarget = (\n event: WorkEvent,\n): MergeRequestTarget | undefined => {\n const { projectId, mergeRequestIid } = fields(event);\n return typeof projectId === \"number\" && typeof mergeRequestIid === \"number\"\n ? { authority: event.source.authority, projectId, mergeRequestIid }\n : undefined;\n};\n\n/**\n * One Session per merge request: both templates continue the same Work\n * Thread, so an Agent that reviewed a merge request remembers it when\n * mentioned there later.\n */\nconst sessionFor = (target: MergeRequestTarget) => {\n const scopeId = `gitlab:${target.authority}:project:${target.projectId}`;\n return {\n scopeId,\n workThreadId: `merge_request:${target.mergeRequestIid}`,\n privacyPartition: scopeId,\n };\n};\n\n/** Runs one Agent Turn and posts its output as a merge request note. */\nconst answer = async (\n work: LoopWork,\n target: MergeRequestTarget,\n instructions: string,\n reply:\n | { readonly operation: \"merge_request.note.create\" }\n | {\n readonly operation: \"merge_request.discussion.reply\";\n readonly discussionId: string;\n },\n): Promise<ReactionDraft> => {\n const binding = sessionFor(target);\n const capability = `gitlab.${reply.operation}`;\n const context = await work.context.project({\n scopeId: binding.scopeId,\n workThreadId: binding.workThreadId,\n items: [\n work.context.event(),\n work.context.value({\n kind: \"instructions\",\n value: instructions,\n provenance: [{ sourceType: \"loop-template\", sourceId: \"gitlab\" }],\n }),\n ],\n grants: [capability],\n });\n const turn = await work\n .agent(String(work.config.agentId))\n .session(binding)\n .turn({ context, allow: [capability] });\n const body = typeof turn.output === \"string\" ? turn.output.trim() : \"\";\n if (turn.outcome !== \"completed\" || body.length === 0) {\n return work.react.none(\n turn.outcome === \"completed\"\n ? \"The Agent produced no reply\"\n : `The Agent Turn ended ${turn.outcome}`,\n );\n }\n const note = await work.effect(context, {\n integrationId: \"gitlab\",\n operation: reply.operation,\n input: {\n authority: target.authority,\n projectId: target.projectId,\n mergeRequestIid: target.mergeRequestIid,\n body,\n ...(reply.operation === \"merge_request.discussion.reply\"\n ? { discussionId: reply.discussionId }\n : {}),\n },\n });\n return work.react.effects([note]);\n};\n\nconst extra = (config: LoopConfig): string =>\n typeof config.instructions === \"string\" && config.instructions.trim() !== \"\"\n ? `\\n\\n${config.instructions.trim()}`\n : \"\";\n\n/**\n * Reviews a merge request when it opens, reopens, or receives new commits,\n * and posts the review as a note. Title or label edits do not trigger a\n * review. Draft merge requests are skipped unless `skipDrafts` is false.\n */\nexport const gitlabMergeRequestReview = defineLoop(\n {\n id: \"gitlab-mr-review\",\n version: VERSION,\n description: \"Review merge requests when they open or receive new commits\",\n spec: {\n sources: [\n \"gitlab.merge_request.opened\",\n \"gitlab.merge_request.reopened\",\n \"gitlab.merge_request.updated\",\n ],\n workThread: \"gitlab.merge_request\",\n session: \"per-work-thread\",\n reaction: \"effects\",\n },\n runAs: \"app\",\n requiredBonds: [\n { provider: \"gitlab\", operations: [\"fetch\", \"comment_mr\"] },\n ],\n configSchema: {\n type: \"object\",\n properties: {\n agentId: agentField,\n projects: projectsField,\n skipDrafts: {\n type: \"boolean\",\n default: true,\n title: \"Skip draft merge requests\",\n },\n instructions: instructionsField,\n },\n required: [\"agentId\", \"projects\"],\n },\n },\n (app) =>\n app.on(\n [\n \"gitlab.merge_request.opened\",\n \"gitlab.merge_request.reopened\",\n \"gitlab.merge_request.updated\",\n ],\n (work) => {\n const target = mergeRequestTarget(work.event);\n const { draft, newCommits, project } = fields(work.event);\n if (target === undefined) {\n return work.react.none(\"Not a merge request Event\");\n }\n if (!watched(work.config, work.event)) {\n return work.react.none(\"Project is not watched\");\n }\n if (newCommits !== true) {\n return work.react.none(\"No new commits\");\n }\n if (draft === true && work.config.skipDrafts !== false) {\n return work.react.none(\"Draft merge request\");\n }\n return answer(\n work,\n target,\n `Review merge request !${target.mergeRequestIid} in ${String(\n project ?? target.projectId,\n )}. Fetch the source branch through the GitLab Bond, read the diff ` +\n \"against the target branch, and reply with a concise review: \" +\n \"correctness problems first, then risks, then optional \" +\n \"suggestions. Your reply is posted as a merge request note.\" +\n extra(work.config),\n { operation: \"merge_request.note.create\" },\n );\n },\n ),\n);\n\nconst mentionPattern = (username: string): RegExp =>\n new RegExp(\n `(^|[^\\\\w@.-])@${username.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}(?![\\\\w.-])`,\n \"i\",\n );\n\n/**\n * Answers a merge request comment that mentions the Agent's GitLab user, in\n * the same thread. System notes and the Agent's own notes are ignored, so a\n * reply never triggers another reply.\n */\nexport const gitlabMention = defineLoop(\n {\n id: \"gitlab-mention\",\n version: VERSION,\n description: \"Answer merge request comments that mention the Agent\",\n spec: {\n sources: [\"gitlab.merge_request.note.created\"],\n workThread: \"gitlab.merge_request\",\n session: \"per-work-thread\",\n reaction: \"effects\",\n },\n runAs: \"app\",\n requiredBonds: [\n { provider: \"gitlab\", operations: [\"fetch\", \"comment_mr\"] },\n ],\n configSchema: {\n type: \"object\",\n properties: {\n agentId: agentField,\n projects: projectsField,\n username: {\n type: \"string\",\n minLength: 1,\n title: \"GitLab username\",\n description:\n \"The app principal's username, without @. Comments that mention it are answered.\",\n },\n instructions: instructionsField,\n },\n required: [\"agentId\", \"projects\", \"username\"],\n },\n },\n (app, { config }) => {\n const username = String(config.username).replace(/^@/, \"\");\n const mentions = mentionPattern(username);\n app.on(\"gitlab.merge_request.note.created\", (work) => {\n const target = mergeRequestTarget(work.event);\n const { text, system, discussionId, actor } = fields(work.event);\n const author = isObject(actor) ? actor.username : undefined;\n if (target === undefined) {\n return work.react.none(\"Not a merge request comment\");\n }\n if (!watched(work.config, work.event)) {\n return work.react.none(\"Project is not watched\");\n }\n if (system === true) return work.react.none(\"System note\");\n if (\n typeof author === \"string\" &&\n author.toLowerCase() === username.toLowerCase()\n ) {\n return work.react.none(\"The Agent's own note\");\n }\n if (typeof text !== \"string\" || !mentions.test(text)) {\n return work.react.none(\"The Agent is not mentioned\");\n }\n return answer(\n work,\n target,\n `@${String(author ?? \"someone\")} mentioned you (@${username}) in a ` +\n `comment on merge request !${target.mergeRequestIid}. Answer the ` +\n \"comment. Fetch the code through the GitLab Bond if you need it. \" +\n \"Your reply is posted in the same thread.\" +\n extra(work.config),\n typeof discussionId === \"string\" && discussionId.length > 0\n ? { operation: \"merge_request.discussion.reply\", discussionId }\n : { operation: \"merge_request.note.create\" },\n );\n });\n },\n);\n\n/** The GitLab templates, in the order a console lists them. */\nexport const gitlabTemplates = [\n gitlabMergeRequestReview,\n gitlabMention,\n] as const;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,33 @@
1
1
  {
2
2
  "name": "@openma/matter-gitlab",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "description": "GitLab for OpenMatter: the Bond provider, webhook ingest, merge request and issue note delivery, and the GitLab Loop templates.",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/openma-ai/OpenMatter.git",
9
+ "directory": "packages/gitlab"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": false,
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "exports": {
17
+ "./bond": {
18
+ "types": "./dist/bond/index.d.ts",
19
+ "import": "./dist/bond/index.js"
20
+ }
21
+ },
22
+ "publishConfig": {
23
+ "access": "public",
24
+ "provenance": true
25
+ },
26
+ "dependencies": {
27
+ "@openma/matter": "0.2.0",
28
+ "@openma/matter-loop": "0.2.0"
29
+ },
30
+ "peerDependencies": {
31
+ "effect": "^3.22.1"
32
+ }
6
33
  }