From cac84dec9bc91c0b53bf23b267d18d8a9c97d884 Mon Sep 17 00:00:00 2001 From: claude_code Date: Sat, 27 Jun 2026 03:54:43 +0300 Subject: [PATCH] refactor(ai-roles): make catalog URL a per-branch image default, drop local-fs source The agent-roles catalog source is no longer hardcoded in app code and no longer supports a local filesystem directory. The provider fetches only from an http(s):// base URL read at runtime from AI_AGENT_ROLES_CATALOG_URL; an empty or non-http value yields a 502 (catalog unavailable). The image ships a per-branch default for that URL (set in CI), still overridable at runtime via the env var. - provider: drop readLocal + node:fs/node:path; readRelative requires http(s) and 502s otherwise; remote fetch/streaming-cap/SSRF guards unchanged. - environment.service: keep AI_AGENT_ROLES_CATALOG_URL (default ''); comment reflects the per-branch build-time default that is runtime-overridable. - Dockerfile: add ARG+ENV AI_AGENT_ROLES_CATALOG_URL in the installer stage as the image default. - CI: develop.yml builds with the develop raw URL; release.yml defines the main raw URL once in workflow env and references it from both build steps. - tests: replace local-fixture tests with remote-mock happy/malformed bundle tests and a non-http => 502 case; path-traversal block uses an https source. - docs: update .env.example, CHANGELOG (#222), agent-roles-catalog/README. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/release.yml | 5 +++-- CHANGELOG.md | 4 ++-- Dockerfile | 3 ++- agent-roles-catalog/README.md | 7 ++++--- .../integrations/environment/environment.service.ts | 12 +++++++----- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e45704e9..bdcfb1c1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,6 +17,7 @@ permissions: env: VERSION: ${{ inputs.version || github.ref_name }} IMAGE: ghcr.io/vvzvlad/gitmost + AI_AGENT_ROLES_CATALOG_URL: https://raw.githubusercontent.com/vvzvlad/gitmost/main/agent-roles-catalog jobs: # Run the reusable test suite first so a failing test blocks the image build. @@ -57,7 +58,7 @@ jobs: platforms: ${{ matrix.platform }} build-args: | APP_VERSION=${{ env.VERSION }} - AI_AGENT_ROLES_CATALOG_URL=https://raw.githubusercontent.com/vvzvlad/gitmost/main/agent-roles-catalog + AI_AGENT_ROLES_CATALOG_URL=${{ env.AI_AGENT_ROLES_CATALOG_URL }} outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true cache-from: type=gha,scope=${{ matrix.suffix }} cache-to: type=gha,scope=${{ matrix.suffix }},mode=max,ignore-error=true @@ -86,7 +87,7 @@ jobs: platforms: ${{ matrix.platform }} build-args: | APP_VERSION=${{ env.VERSION }} - AI_AGENT_ROLES_CATALOG_URL=https://raw.githubusercontent.com/vvzvlad/gitmost/main/agent-roles-catalog + AI_AGENT_ROLES_CATALOG_URL=${{ env.AI_AGENT_ROLES_CATALOG_URL }} push: false tags: | ${{ env.IMAGE }}:latest diff --git a/CHANGELOG.md b/CHANGELOG.md index daa64545..a46c61b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,8 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 `/update-from-catalog` — and a new `source` column linking a role to its catalog slug/language/version. The catalog source is configured via the `AI_AGENT_ROLES_CATALOG_URL` env var — an `http(s)://` base URL to the - catalog's raw files, baked into the image at build time and set per branch in - CI (see `.env.example`). (#222) + catalog's raw files; the image ships a per-branch default baked in CI, and it + can be overridden at runtime via the env var (see `.env.example`). (#222) ### Fixed diff --git a/Dockerfile b/Dockerfile index 591cddba..e6daeb72 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,8 @@ RUN apt-get update \ WORKDIR /app -# Agent-roles catalog base URL, baked at build time (set per-branch in CI). +# Agent-roles catalog base URL: per-branch default set at build time (CI); +# overridable at runtime via the AI_AGENT_ROLES_CATALOG_URL env var. ARG AI_AGENT_ROLES_CATALOG_URL="" ENV AI_AGENT_ROLES_CATALOG_URL=$AI_AGENT_ROLES_CATALOG_URL diff --git a/agent-roles-catalog/README.md b/agent-roles-catalog/README.md index 5a03689e..bbf67b15 100644 --- a/agent-roles-catalog/README.md +++ b/agent-roles-catalog/README.md @@ -35,10 +35,11 @@ to the catalog's raw files. The server fetches `/index.json` for the manifest and `/bundles//.json` for each opened bundle file (REMOTE only). -That base URL is baked into the Docker image at build time and set per branch in +That base URL is provided as a per-branch default in the Docker image (set in CI: a `develop` build points at the `develop` raw URL, a release build at the -`main` raw URL. Local-filesystem sources are no longer supported; if the value -is unset the catalog is unavailable. +`main` raw URL) and can be overridden at runtime via the +`AI_AGENT_ROLES_CATALOG_URL` env var. Local-filesystem sources are no longer +supported; if the value is unset the catalog is unavailable. The fetched JSON is re-validated server-side (the catalog is treated as untrusted input). See `.env.example` for the variable and the CHANGELOG for the diff --git a/apps/server/src/integrations/environment/environment.service.ts b/apps/server/src/integrations/environment/environment.service.ts index 1f6298b7..24081b38 100644 --- a/apps/server/src/integrations/environment/environment.service.ts +++ b/apps/server/src/integrations/environment/environment.service.ts @@ -291,11 +291,13 @@ export class EnvironmentService { getAiAgentRolesCatalogSource(): string { // Catalog location: an http(s):// base URL the catalog is fetched from. - // The value is baked into the image at build time (Dockerfile ARG - // AI_AGENT_ROLES_CATALOG_URL, set per-branch in CI); local-filesystem - // sources are no longer supported. Empty/unset => the catalog is - // unavailable (the provider returns 502). This is INFRA config (where the - // catalog lives), not provider/model config, so an env var is appropriate. + // The image ships a per-branch default for this baked in at build time + // (Dockerfile ARG AI_AGENT_ROLES_CATALOG_URL, set per-branch in CI), but it + // is overridable at runtime via the env var (this getter returns that + // runtime value). Local-filesystem sources are no longer supported. + // Empty/unset => the catalog is unavailable (the provider returns 502). + // This is INFRA config (where the catalog lives), not provider/model + // config, so an env var is appropriate. return this.configService.get('AI_AGENT_ROLES_CATALOG_URL', ''); }