Skip to content

feat(adapters): Add config file API key support and LiteLLM gateway adapter - #1191

Closed
SpootyMcSpoot wants to merge 9 commits into
paperclipai:masterfrom
Anomalous-Ventures:feat/claude-config-litellm
Closed

feat(adapters): Add config file API key support and LiteLLM gateway adapter#1191
SpootyMcSpoot wants to merge 9 commits into
paperclipai:masterfrom
Anomalous-Ventures:feat/claude-config-litellm

Conversation

@SpootyMcSpoot

@SpootyMcSpoot SpootyMcSpoot commented Mar 18, 2026

Copy link
Copy Markdown

Summary

This PR implements two new features for Paperclip adapters:

Phase 1: Config File API Key Support

Enables Anthropic API key configuration via config file in addition to environment variables.

Implementation:

  • Created server/src/adapters/claude-models.ts with model discovery
  • resolveAnthropicApiKey(): Checks ANTHROPIC_API_KEY env var first, then config.llm.apiKey
  • API key precedence: environment variable > config file
  • Model caching (60s TTL) with graceful fallback to static models
  • Registered listClaudeModels in adapter registry

Phase 2: LiteLLM Gateway Adapter

New adapter to use LiteLLM proxy as a unified gateway to multiple LLM providers.

Implementation:

  • Created packages/adapters/litellm-gateway/ package
  • Follows Paperclip adapter architecture (promptTemplate rendering pattern)
  • Renders template with context variables (agent, run, context)
  • Sends rendered prompt to LiteLLM proxy via OpenAI-compatible API
  • SSE streaming with real-time output via onLog
  • Token usage tracking (input/output/cached)
  • Model discovery from /v1/models with 60s caching
  • Environment connectivity testing
  • Added to server dependencies and adapter registry

Configuration Example:
```json
{
"type": "litellm_gateway",
"baseUrl": "http://localhost:4000",
"apiKey": "sk-litellm-...",
"model": "gpt-4",
"promptTemplate": "You are {{agent.name}}. Task: {{context.taskId}}",
"temperature": 0.7,
"maxTokens": 4096
}
```

Key Features

  • Zero new dependencies (uses native fetch)
  • Graceful error handling and fallbacks
  • Proper TypeScript type safety
  • Full integration with Paperclip's adapter system
  • Model caching for both adapters

Testing

Local tests: All tests passing (53 test files, 228 tests)

Deployment test:

  • Built multiarch image: harbor.spooty.io/library/paperclip:feat-litellm-91dfb3b
  • Platforms: linux/amd64, linux/arm64
  • Deployed to test cluster in paperclip namespace
  • Validated end-to-end: agent creation, model selection, API key resolution
  • Confirmed LiteLLM adapter streams output correctly via SSE
  • Verified token usage tracking in run logs

Files Changed (Core Features)

  • server/src/adapters/claude-models.ts (new)
  • server/src/adapters/registry.ts (modified)
  • packages/adapters/litellm-gateway/ (new package)
  • packages/shared/src/constants.ts (added litellm_gateway type)
  • server/package.json (added litellm adapter dependency)
  • Dockerfile (added litellm package.json to build deps)
  • docs/adapters/litellm-gateway.md (new documentation)
  • pnpm-lock.yaml (updated)

Note on Additional Changes

This branch accidentally includes commits for proxy_auth mode, local auth bypass, and provision-admin CLI features. These will be separated into their own PRs. The core changes for this PR are the Claude config file API key support and LiteLLM gateway adapter only.

@greptile-apps

greptile-apps Bot commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds two features: (1) Anthropic API key resolution from the config file for the Claude adapter, and (2) a new litellm_gateway adapter for routing requests through a LiteLLM proxy. It also introduces proxy_auth deployment mode for SSO via upstream reverse-proxy headers (Authentik/nginx), a localAuthBypass flag, and a new provision-admin CLI command. The LiteLLM adapter itself is well-structured, but there are several significant issues across the broader changeset that need attention before merge.

Key concerns:

  • Critical secret committed: .claude/memory.md contains a plain-text Pulumi passphrase (stax-stage) that should never be committed to any repository. This file should be removed and the passphrase rotated.
  • Cross-package import: server/src/index.ts imports provisionAdminUser directly from ../../cli/src/commands/auth-bootstrap-ceo.js via a relative path, and server/tsconfig.json was updated to include ../cli/src to support this. This violates package boundaries — the shared logic should live in a common package.
  • Proxy auth trusts headers without source validation: The proxy_auth middleware accepts x-authentik-email / x-forwarded-email from any client. If the server is reachable without going through the proxy, these headers can be trivially forged to impersonate any user, including auto-promoted admins.
  • Potential undefined dereference and non-atomic race in proxy_auth user creation: After inserting a new SSO user, the code re-fetches by ID and immediately accesses .id without a null guard. The admin auto-promotion is also a non-atomic read-check-write that could fail under concurrent first logins.
  • LiteLLM model cache fingerprint ignores port: baseUrlFingerprint uses only url.hostname, so http://localhost:4000 and http://localhost:4001 share the same cache slot.

Confidence Score: 1/5

  • Not safe to merge — contains a committed secret, an authentication bypass risk in proxy_auth mode, a cross-package architectural violation, and a potential runtime crash in the new auth middleware path.
  • The LiteLLM adapter and Claude model discovery features are solid, but the supporting infrastructure changes introduce a P0 secret commit, a security vulnerability in the proxy_auth middleware (unauthenticated header spoofing), a runtime crash risk (undefined dereference after user insert), and a hard architectural violation (server importing CLI source directly). These issues span security, reliability, and maintainability and must be resolved before the PR can be safely merged.
  • server/src/middleware/auth.ts, server/src/index.ts, server/tsconfig.json, and .claude/memory.md require the most attention.

Important Files Changed

Filename Overview
.claude/memory.md New file containing infrastructure notes with a hardcoded Pulumi passphrase (stax-stage) committed in plain text — a critical secret exposure.
server/src/middleware/auth.ts Adds proxy_auth mode that trusts SSO headers from any source without IP validation, plus a potential user undefined dereference and non-atomic admin auto-promotion.
server/src/index.ts Imports provisionAdminUser directly from CLI source via a relative path, violating package boundaries; also wires up localAuthBypass and defaultAdminEmail config.
packages/adapters/litellm-gateway/src/server/models.ts Module-level model cache uses hostname-only fingerprint, causing cache collisions for multiple LiteLLM instances on the same host at different ports.
packages/adapters/litellm-gateway/src/server/execute.ts Core LiteLLM streaming executor; well-structured with proper timeout handling, SSE parsing, and token usage tracking. Minor concern around prompt being logged via onMeta.
server/src/adapters/claude-models.ts New file for dynamic Claude model discovery with config-file API key fallback, caching, and graceful fallback to static models. Logic is sound.
server/src/adapters/registry.ts Registers LiteLLM gateway adapter and wires listClaudeModels — straightforward additions following existing patterns.
server/tsconfig.json Adds ../cli/src to the server's TypeScript include paths to support the cross-package import of CLI code — a concerning architectural change.
packages/shared/src/constants.ts Adds litellm_gateway to adapter types and proxy_auth to deployment modes, plus formatting-only reformats of existing constants.
cli/src/commands/auth-bootstrap-ceo.ts Adds provisionAdminUser and provisionAdmin CLI functions for directly creating instance admin users; logic is clean but the function is also imported directly by the server.

Comments Outside Diff (2)

  1. server/src/middleware/auth.ts, line 1776-1853 (link)

    P1 Proxy auth headers trusted without source IP validation

    The proxy_auth mode trusts x-authentik-email, x-forwarded-email, and related headers from any incoming request, without verifying that the request originated from the trusted upstream proxy. If the server is reachable by clients that can bypass the proxy (e.g., a misconfigured firewall, or any internal network client), they can forge these headers to impersonate any user — including auto-promoted instance admins.

    The isLoopback check is only used for localAuthBypass, not for proxy_auth. In production proxy_auth deployments the server is typically accessible only via the proxy, but that constraint is external and not enforced here. At a minimum, the trusted proxy IP(s) should be validated (e.g., via a configurable PAPERCLIP_TRUSTED_PROXY_IPS env var), and the risk should be prominently documented. Many production frameworks handle this with an explicit trusted-proxy list at the express level.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: server/src/middleware/auth.ts
    Line: 1776-1853
    
    Comment:
    **Proxy auth headers trusted without source IP validation**
    
    The `proxy_auth` mode trusts `x-authentik-email`, `x-forwarded-email`, and related headers from any incoming request, without verifying that the request originated from the trusted upstream proxy. If the server is reachable by clients that can bypass the proxy (e.g., a misconfigured firewall, or any internal network client), they can forge these headers to impersonate any user — including auto-promoted instance admins.
    
    The `isLoopback` check is only used for `localAuthBypass`, not for `proxy_auth`. In production `proxy_auth` deployments the server is typically accessible only via the proxy, but that constraint is external and not enforced here. At a minimum, the trusted proxy IP(s) should be validated (e.g., via a configurable `PAPERCLIP_TRUSTED_PROXY_IPS` env var), and the risk should be prominently documented. Many production frameworks handle this with an explicit trusted-proxy list at the express level.
    
    How can I resolve this? If you propose a fix, please make it concise.
  2. server/src/middleware/auth.ts, line 1800-1822 (link)

    P1 user can be undefined when accessing user.id after insert

    After inserting the new user, the code re-fetches by ID using .then((rows) => rows[0]). TypeScript types this as T | undefined. If the row is not immediately visible (e.g., a race condition or an unexpected DB error), user will be undefined, and the subsequent user.id reference at the instanceUserRoles insert will throw a runtime TypeError.

    There should be an explicit null/undefined guard after the re-fetch:

    user = await db
      .select()
      .from(authUsers)
      .where(eq(authUsers.id, userId))
      .then((rows) => rows[0]);
    
    if (!user) {
      // handle error - newly inserted user not found
      next(new Error("Failed to retrieve created SSO user"));
      return;
    }

    Additionally, the check-then-insert pattern for the instanceUserRoles auto-promotion is not atomic. Two concurrent first-time SSO logins could both read adminCount === 0 and both attempt the insert, potentially causing a constraint violation. A conflict-safe upsert or a database transaction should be used instead.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: server/src/middleware/auth.ts
    Line: 1800-1822
    
    Comment:
    **`user` can be `undefined` when accessing `user.id` after insert**
    
    After inserting the new user, the code re-fetches by ID using `.then((rows) => rows[0])`. TypeScript types this as `T | undefined`. If the row is not immediately visible (e.g., a race condition or an unexpected DB error), `user` will be `undefined`, and the subsequent `user.id` reference at the `instanceUserRoles` insert will throw a runtime `TypeError`.
    
    There should be an explicit null/undefined guard after the re-fetch:
    
    ```ts
    user = await db
      .select()
      .from(authUsers)
      .where(eq(authUsers.id, userId))
      .then((rows) => rows[0]);
    
    if (!user) {
      // handle error - newly inserted user not found
      next(new Error("Failed to retrieve created SSO user"));
      return;
    }
    ```
    
    Additionally, the check-then-insert pattern for the `instanceUserRoles` auto-promotion is not atomic. Two concurrent first-time SSO logins could both read `adminCount === 0` and both attempt the insert, potentially causing a constraint violation. A conflict-safe upsert or a database transaction should be used instead.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: .claude/memory.md
Line: 20

Comment:
**Hardcoded secret committed to repository**

The file contains a plain-text Pulumi passphrase (`stax-stage`) committed directly to the repository. Even if this repo is currently private, committing credentials is a security risk — secrets can end up in git history, forks, or CI logs.

This file should either be removed from the repository entirely or have the passphrase redacted. If it must stay, it should be added to `.gitignore`. The passphrase should be rotated immediately if this repository is or has been public.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: server/src/index.ts
Line: 29

Comment:
**Cross-package import violates package boundaries**

The server is importing `provisionAdminUser` directly from the CLI source tree using a relative path (`../../cli/src/commands/auth-bootstrap-ceo.js`). This is further enforced by the change to `server/tsconfig.json` that adds `../cli/src` to `"include"`. This means the server is now compiling CLI source code directly — bypassing package encapsulation.

This creates tight coupling between two packages that are supposed to be independent, makes it impossible to build the server without the CLI being present, and could introduce CLI-only dependencies into the server bundle. `provisionAdminUser` should be extracted into a shared package (e.g. `@paperclipai/db` or a new `@paperclipai/server-utils` package) and imported from there, rather than directly from CLI source.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: server/src/middleware/auth.ts
Line: 1776-1853

Comment:
**Proxy auth headers trusted without source IP validation**

The `proxy_auth` mode trusts `x-authentik-email`, `x-forwarded-email`, and related headers from any incoming request, without verifying that the request originated from the trusted upstream proxy. If the server is reachable by clients that can bypass the proxy (e.g., a misconfigured firewall, or any internal network client), they can forge these headers to impersonate any user — including auto-promoted instance admins.

The `isLoopback` check is only used for `localAuthBypass`, not for `proxy_auth`. In production `proxy_auth` deployments the server is typically accessible only via the proxy, but that constraint is external and not enforced here. At a minimum, the trusted proxy IP(s) should be validated (e.g., via a configurable `PAPERCLIP_TRUSTED_PROXY_IPS` env var), and the risk should be prominently documented. Many production frameworks handle this with an explicit trusted-proxy list at the express level.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: server/src/middleware/auth.ts
Line: 1800-1822

Comment:
**`user` can be `undefined` when accessing `user.id` after insert**

After inserting the new user, the code re-fetches by ID using `.then((rows) => rows[0])`. TypeScript types this as `T | undefined`. If the row is not immediately visible (e.g., a race condition or an unexpected DB error), `user` will be `undefined`, and the subsequent `user.id` reference at the `instanceUserRoles` insert will throw a runtime `TypeError`.

There should be an explicit null/undefined guard after the re-fetch:

```ts
user = await db
  .select()
  .from(authUsers)
  .where(eq(authUsers.id, userId))
  .then((rows) => rows[0]);

if (!user) {
  // handle error - newly inserted user not found
  next(new Error("Failed to retrieve created SSO user"));
  return;
}
```

Additionally, the check-then-insert pattern for the `instanceUserRoles` auto-promotion is not atomic. Two concurrent first-time SSO logins could both read `adminCount === 0` and both attempt the insert, potentially causing a constraint violation. A conflict-safe upsert or a database transaction should be used instead.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: packages/adapters/litellm-gateway/src/server/models.ts
Line: 27-34

Comment:
**Cache fingerprint ignores port, causing collisions for multi-port setups**

The `baseUrlFingerprint` function returns only `url.hostname`, discarding the port. Two LiteLLM instances running on the same host at different ports (e.g., `http://localhost:4000` and `http://localhost:4001`) would both fingerprint to `"localhost"` and share the same module-level cache entry. The second instance to be queried would receive the stale model list from the first.

The fingerprint should include at least the hostname and port:

```suggestion
function baseUrlFingerprint(baseUrl: string): string {
  try {
    const url = new URL(baseUrl);
    return `${url.hostname}:${url.port || (url.protocol === "https:" ? "443" : "80")}`;
  } catch {
    return baseUrl.slice(0, 50);
  }
}
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: packages/adapters/litellm-gateway/src/server/execute.ts
Line: 64-67

Comment:
**Prompt content logged verbatim before sending**

The log message at this line logs the full prompt content length, which is fine, but the `onLog` call at line 141 (`await params.onLog("stdout", content)`) logs the raw model output directly to stdout. While this is intentional for streaming, it's worth noting that the full rendered prompt template is passed to `onMeta` (line 289), which includes all template variables. Depending on what the user puts in `promptTemplate`, this could leak sensitive context data into run logs. This is a design decision, but worth ensuring the `onMeta` path is appropriately access-controlled.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: "feat(adapters): add ..."

Comment thread .claude/memory.md Outdated
Comment thread server/src/index.ts
Comment thread packages/adapters/litellm-gateway/src/server/models.ts
Comment thread packages/adapters/litellm-gateway/src/server/execute.ts
@3stepwin

Copy link
Copy Markdown

Hey @SpootyMcSpoot @cryppadotta @devinfoley — thanks for pushing this forward! The LiteLLM gateway adapter looks solid after the redesign (promptTemplate rendering + SSE streaming + token tracking is exactly what we need for unified proxy routing).

I've been running a custom LLM router (HiveRouter in my Hive AI OS stack) that handles similar multi-provider setups (Gemini pooled keys, OpenAI-compatible endpoint). It's helped a ton with Google's recent Gemini deprecations (e.g., 2.0 Flash series blocked with 404 "no longer available to new users" for newer keys).

A few HiveRouter-inspired ideas that could make this adapter more robust/resilient without much extra work:

  1. Config-driven model alias/remapping (for deprecation migrations):
    Add an optional "modelAliases" or "remap" object in adapter config:
    "modelAliases": {
      "gemini-2.0-flash": "gemini-2.5-flash",
      "gemini-2.0-flash-lite": "gemini-2.5-flash-lite"
    }

In execute.ts, check if requested model is aliased → swap before sending to LiteLLM. This auto-handles Google’s forced upgrades without users editing configs every time.
2 Explicit endpoint override (to force direct AI Studio path):
Add "endpointOverride" field:
"endpointOverride": "https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent"
3 
This bypasses any LiteLLM internal mapping/Vertex fallback bugs (common with Gemini in v1.82.x). Also fixes the cache fingerprint collision Greptile flagged (by making endpoint explicit per call).
4 Simple fallback chain (for resilience):
Extend config with "fallbackModels":
"fallbackModels": ["gemini-2.5-pro", "openai/gpt-4o-mini"]
5 
If LiteLLM returns 404/429/500 on primary model, retry with next in list. LiteLLM has fallbacks, but exposing them in Paperclip config would make it seamless for agents.
These are low-effort additions (mostly in execute.ts or config schema) but would make the adapter production-ready for real Gemini-heavy workflows (like my multi-key Tier 1 projects pooling ~8K RPM).
Happy to help implement any of these — I can sketch a diff/PR branch if useful, or test the current adapter against my LiteLLM proxy (running Gemini 2.5 variants). Let me know!
(Also +1 on fixing Greptile’s P0s before merge: secret in .claude/memory.md, proxy_auth IP validation, cross-package import, undefined user guard, port in cache fingerprint.)
Excited to see this merged — great work overall!

@SpootyMcSpoot

Copy link
Copy Markdown
Author

Thanks for the detailed review. Most of the flagged issues (proxy_auth header validation, cross-package imports, secret in .claude/memory.md) are from commits that were accidentally included in this branch and will be separated into their own PRs.

The core changes in this PR are:

  1. Claude API key config file support (server/src/adapters/claude-models.ts)
  2. LiteLLM gateway adapter (packages/adapters/litellm-gateway/)

For the LiteLLM-specific issue about cache fingerprint (hostname-only causing port collisions):

Fixed - Updated baseUrlFingerprint to include port:

function baseUrlFingerprint(baseUrl: string): string {
  try {
    const url = new URL(baseUrl);
    return `${url.hostname}:${url.port || (url.protocol === "https:" ? "443" : "80")}`;
  } catch {
    return baseUrl.slice(0, 50);
  }
}

This resolves cache collisions when running multiple LiteLLM instances on the same host.

Will clean up the branch to remove the proxy_auth/auth/CLI changes before merge.

@SpootyMcSpoot

Copy link
Copy Markdown
Author

Thanks for the suggestions - these are great ideas for making the adapter more production-ready.

The model aliasing, endpoint override, and fallback chain features would be valuable additions. For this initial PR, I've kept the adapter minimal to match the existing Paperclip adapter patterns (promptTemplate rendering, SSE streaming, token tracking).

I'd suggest implementing these as follow-up enhancements:

  1. Model aliasing - Add modelAliases config field, remap in execute.ts before sending to LiteLLM
  2. Endpoint override - Add endpointOverride field to bypass LiteLLM routing entirely
  3. Fallback chain - Extend with fallbackModels array, retry on 404/429/500

These could be added incrementally after the base adapter lands. Happy to collaborate on implementation or review PRs for these features.

Re: P0 issues - most are from unrelated commits accidentally included in this branch. Will clean those up before merge.

- Add litellm_gateway adapter for OpenAI-compatible LiteLLM proxy
- Support SSE streaming, token usage tracking, model discovery
- Add API key resolution from config file with env var precedence
- Add model discovery for local adapters via provider API with caching
- Include port in LiteLLM cache fingerprint to avoid collisions
@SpootyMcSpoot
SpootyMcSpoot force-pushed the feat/claude-config-litellm branch from d112c34 to 60bcc95 Compare March 18, 2026 07:07
@SpootyMcSpoot

Copy link
Copy Markdown
Author

@cryppadotta @devinfoley PR is g2g.

@ChandlerHardy ChandlerHardy left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review — APPROVED ✓

PR: feat(adapters): Add config file API key support and LiteLLM gateway adapter

Two well-scoped additions. Reviewed the security-critical paths carefully.

Phase 1: Config file API key support (claude-models.ts)

  • resolveAnthropicApiKey(): Env var wins over config file. Correct precedence.
  • fingerprint(apiKey): Uses ${length}:${last6} for cache invalidation. This never logs the full key — acceptable in-memory only.
  • 60s TTL model cache with graceful fallback to static models on fetch failure. Good.
  • 5s request timeout to Anthropic models API. Good.

Phase 2: LiteLLM gateway adapter (execute.ts)

  • new URL(baseUrl) validation catches malformed URLs. Note: doesn't restrict to http(s) schemes, but fetch() will reject non-http(s) at runtime. Acceptable.
  • resolveLiteLLMApiKey(): Config value wins over LITELLM_API_KEY env var — note this is the opposite priority from the Anthropic key resolver. Flag for documentation/consistency if this causes operator confusion.
  • Custom headers are string-typed only before being sent. Correct.
  • Authorization header is always appended after customHeaders, so it's not accidentally overridden by caller-supplied headers. ✓
  • temperature is clamped to [0, 2], maxTokens has a floor of 1. Correct bounds.
  • SSE streaming is correctly parsed (skips data: [DONE] lines, handles partial lines with buffer).

Minor notes

  1. API key precedence inconsistency: Anthropic = env var > config. LiteLLM = config > env var. This asymmetry should be documented.
  2. No tests: Neither the claude-models module nor the litellm execute module has unit tests. Understandable for a new adapter but worth tracking.
  3. Dockerfile change: adds plugin-sdk package.json copy and build step (same as PR #1214 but without the --frozen-lockfile removal). Correct.

LGTM.

@ChandlerHardy

Copy link
Copy Markdown

Sorry about the unsolicited review — my automated code reviewer (running on Paperclip) accidentally scanned this repo instead of just my own projects. Feel free to dismiss it.

@SpootyMcSpoot

Copy link
Copy Markdown
Author

Sorry about the unsolicited review — my automated code reviewer (running on Paperclip) accidentally scanned this repo instead of just my own projects. Feel free to dismiss it.

Sorry about the unsolicited review — my automated code reviewer (running on Paperclip) accidentally scanned this repo instead of just my own projects. Feel free to dismiss it.

No worries, I appreciate the extra validation checks lol!

@SpootyMcSpoot

Copy link
Copy Markdown
Author

STAX-Specific Configuration Detected

Issue: This PR contains STAX-specific infrastructure configuration that should not be in the public upstream repository.

Found in PR

+      docker-registry: 'harbor.spooty.io'

Problem: harbor.spooty.io is a STAX private infrastructure endpoint. Including this in the upstream paperclipai/paperclip repository exposes proprietary infrastructure details.

Recommended Fix

Option 1: Remove the docker-registry parameter entirely (let it use the default from the reusable workflow)

ci:
  uses: Anomalous-Ventures/devops/.github/workflows/ci-nodejs.yml@main
  with:
    node-version: '22'
    package-manager: 'pnpm'
    # Removed docker-registry - use default or override in forks
  secrets: inherit

Option 2: Comment with instructions for users to override in their forks

ci:
  uses: Anomalous-Ventures/devops/.github/workflows/ci-nodejs.yml@main
  with:
    node-version: '22'
    package-manager: 'pnpm'
    # Override docker-registry in your fork's workflow file
    # docker-registry: 'your-registry.example.com'
  secrets: inherit

Related Cleanup

We've completed a full audit of the fork and removed all STAX-specific references:

Recommendation: Before merging this PR, please remove the harbor.spooty.io reference to keep the upstream repository free of proprietary infrastructure details.

Let me know if you'd like me to update the PR to fix this issue!

Remove hardcoded registry reference from public repository.
Users can override docker-registry parameter in their fork if needed.
@SpootyMcSpoot

Copy link
Copy Markdown
Author

Fixed in latest commit

The STAX-specific docker registry reference has been removed in commit b8ab621.

The CI workflow now uses a commented example, allowing users to override the docker-registry parameter in their forks without exposing proprietary infrastructure details in the upstream repository.

@SpootyMcSpoot
SpootyMcSpoot deleted the feat/claude-config-litellm branch March 24, 2026 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants