docs(providers): name the Volcengine maintenance owner and record its evidence - #826
Conversation
… evidence `MAINTAINERS.md` requires a named maintenance owner for every canonical preset — someone who updates it when the base URL, authentication, or catalog contract changes, and a stated way to report a break. #611 landed without one. A canonical preset with no owner is a route nobody has agreed to keep true, so the project owner takes it rather than leaving the gate open on a merged entry. Both Plan entries are `liveModels: false`, which is why this matters more here than for a discovery-backed provider: a stale model id cannot self-heal and reaches the user as an upstream model error. `glm-5.1` was already one such case. Also lands the primary-source evidence ledger the gate asks for: endpoints, operating legal entity, terms, and the 2026-08-01 verification date.
📝 WalkthroughWalkthroughThe PR adds a Volcengine evidence ledger and records matching verification, documentation, usage-restriction, reporting, and maintenance metadata in the provider registry. ChangesVolcengine governance
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md`:
- Line 27: Update Claim 10 in the evidence ledger to include the exact queries,
search date ranges, result links, and defined search boundaries needed to
reproduce the negative search. If this evidence cannot be supplied, change the
claim status to “not verified” and remove it from authorization reasoning.
- Around line 33-42: Revise the “Routing-authorization finding” to avoid marking
authorization as satisfied based on support for named clients, since that does
not explicitly authorize opencodex routing. Keep the conclusions in Lines 55-57
and 65 conditional unless adding a first-party Volcengine statement permitting
opencodex; otherwise reference an inert src/providers/free-directory.ts entry as
required by MAINTAINERS.md.
- Around line 43-45: Update the credential-boundary statement in the evidence
ledger to specify that users provide their own plan key, opencodex stores it
locally in config.json, sends it via the Authorization header to the configured
Volcengine endpoint, and does not transmit it to an opencodex-controlled
intermediary; remove the inaccurate claim that the credential never leaves the
user's machine.
In `@src/providers/registry.ts`:
- Around line 376-377: Update the notes for both `volcengine-coding-plan` and
`volcengine-agent-plan` to state that their Plan Base URL/API key is limited to
designated AI coding tools, non-tool usage may suspend the subscription or ban
the account, and `curl`, Postman, and Dify are excluded clients.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 7e543733-aa3d-441e-8724-ebebf382bd42
📒 Files selected for processing (2)
devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.mdsrc/providers/registry.ts
| | 7 | Officially supported clients include Claude Code, Codex CLI, OpenCode, OpenClaw, Cline, Cursor, Kilo/Roo Code, TRAE | verified | docs.volcengine.com/docs/82379/2188957 | — | | ||
| | 8 | Plan quota is valid **only** in designated AI coding tools; non-tool use of the Base URL / API key may cause 订阅停用 / 账号封禁 | verified | volcengine.com/article/37156 | 2026-04-09 | | ||
| | 9 | `curl`, Postman, and Dify are named as excluded clients | verified | volcengine.com/article/37935 | — | | ||
| | 10 | No public report of a plan key revoked for proxy routing | unreachable (negative) | 10 query families: V2EX/掘金/CSDN/Zhihu/GitHub/Reddit/HN | 2026-08-01 | |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Make the negative search reproducible.
Claim 10 records only ten query families. It does not record exact queries, date ranges, result links, or search boundaries. A future maintainer cannot audit or repeat the negative result. Add that evidence, or change the claim to “not verified” and exclude it from authorization reasoning.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md` at line
27, Update Claim 10 in the evidence ledger to include the exact queries, search
date ranges, result links, and defined search boundaries needed to reproduce the
negative search. If this evidence cannot be supplied, change the claim status to
“not verified” and remove it from authorization reasoning.
| ## Routing-authorization finding | ||
|
|
||
| The gate asks for "resale or routing authorization for aggregators". Two facts | ||
| decide it, and they point the same way: | ||
|
|
||
| 1. Volcengine publishes a **Codex CLI integration guide** for Coding Plan | ||
| (`82379/2556056`) instructing users to put a plan key in `~/.codex/config.toml`. | ||
| Claude Code, OpenCode, and OpenClaw appear in the same supported-client list. | ||
| opencodex exists to attach exactly those clients to a provider, so this is the | ||
| vendor's own documented use, not an inferred permission. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
file='devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md'
printf '%s\n' '--- target ledger ---'
sed -n '25,72p' "$file"
printf '%s\n' '--- related references ---'
rg -n -C 3 'routing|authorization|Codex CLI|82379|2556056|Dify|opencodex|supported-client|gate' devlog/_plan/260801_pr611_volcengine_evidence
printf '%s\n' '--- repository references to the evidence claims ---'
rg -n -C 2 'volcengine|Coding Plan|Codex CLI|third-party routing|authorization' .Repository: lidge-jun/opencodex
Length of output: 50376
🏁 Script executed:
#!/bin/bash
set -eu
file='devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md'
printf '%s\n' '--- target ledger ---'
sed -n '25,72p' "$file"
printf '%s\n' '--- related references ---'
rg -n -C 3 'routing|authorization|Codex CLI|82379|2556056|Dify|opencodex|supported-client|gate' devlog/_plan/260801_pr611_volcengine_evidenceRepository: lidge-jun/opencodex
Length of output: 12892
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- gate language ---'
rg -n -C 5 'resale|routing authorization|aggregator|credential-destination|canonical preset|designated.*tool|Dify' MAINTAINERS.md devlog/_plan/260801_pr611_volcengine_evidence src/providers/registry.ts
printf '%s\n' '--- Volcengine registry block ---'
rg -n -C 18 'volcengine(-coding-plan|-agent-plan)?' src/providers/registry.ts
printf '%s\n' '--- provider routing and credential storage references ---'
rg -n -C 3 'baseUrl|apiKey|credential|local|proxy|route' src/providers/registry.ts | rg -n -C 2 'volcengine|coding|plan|local|credential|baseUrl|apiKey'
printf '%s\n' '--- cited source URLs in repository ---'
rg -n '2556056|2188957|37156|37935|volcengine.com/docs/82379' devlog/_plan/260801_pr611_volcengine_evidenceRepository: lidge-jun/opencodex
Length of output: 50375
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- gate language ---'
rg -n -C 5 'resale|routing authorization|aggregator|credential-destination|canonical preset|designated.*tool|Dify' MAINTAINERS.md devlog/_plan/260801_pr611_volcengine_evidence src/providers/registry.ts
printf '%s\n' '--- Volcengine registry block ---'
rg -n -C 18 'volcengine(-coding-plan|-agent-plan)?' src/providers/registry.tsRepository: lidge-jun/opencodex
Length of output: 27256
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- local proxy and provider-config flow ---'
rg -n -C 4 'OPENCODEX_HOME|provider.*config|routedProviderConfig|preserveCustomDestination|start.*server|localhost|127\.0\.0\.1|baseUrl' README.md docs src | head -n 500
printf '%s\n' '--- references to OpenCode versus opencodex ---'
rg -n -C 3 'OpenCode|opencodex|aggregator|proxy|middleware|routing' README.md docs src devlog/_plan/260801_pr611_volcengine_evidence | head -n 500
printf '%s\n' '--- contributing evidence wording ---'
rg -n -C 8 'evidence|required.*canonical|routing|resale|aggregator' CONTRIBUTING.md docs MAINTAINERS.md 2>/dev/null | head -n 300Repository: lidge-jun/opencodex
Length of output: 50377
🌐 Web query:
Volcengine Coding Plan 82379 2556056 Codex CLI OpenCode OpenClaw Dify routing authorization
💡 Result:
The terms provided refer to specific components within the ecosystems of Volcengine (ByteDance), Dify, and the OpenClaw/Codex CLI environment [1][2][3]. Volcengine Coding Plan Volcengine Coding Plan is a subscription-based AI coding model service provided by ByteDance [4][5]. It is distinct from the general Ark API (which is pay-as-you-go) and uses a dedicated endpoint [4][6][2]. - API Endpoint: https://ark.cn-beijing.volces.com/api/coding/v3 [6][2] - Auth Token: Often configured via ANTHROPIC_AUTH_TOKEN in compatible tools like Claude Code or Cline [1][5][2]. - The numbers 82379 and 2556056 appear to be internal Volcengine documentation IDs (e.g., /docs/82379/...) [1][6]. Codex CLI, OpenCode, and OpenClaw These are tools and harnesses for AI-assisted coding and agent automation [3][7]. - Codex CLI: Historically a standalone tool, now often managed as a backend or plugin within larger frameworks [3][8]. - OpenCode: An AI coding CLI provider that can be used as a backend for tools like OpenClaw or Clawpatch [8][9]. - OpenClaw: An agent orchestration framework that integrates various CLI backends (like codex, claude, opencode) [3][9][7]. It utilizes harnesses to route tasks to these specific CLI providers [3][7]. Dify Routing and Authorization Dify is an LLM application development platform [10][11]. - Routing: Dify manages routing of model traffic through its provider infrastructure [10]. In complex deployments, this can be managed by an AI Gateway, which proxies ingress/egress traffic, enables fallback mechanisms, and enforces routing rules based on path or headers (e.g., /v1/chat-messages) [11]. - Authorization: Dify uses distinct authentication pipelines for different token types (e.g., account vs. external SSO/PAT) to secure its API endpoints [12]. Troubleshooting Volcengine integration in Dify often involves ensuring the plugin is properly registered within the Docker environment (using migration/installation commands) and that models are explicitly enabled in the provider UI, as the plugin typically uses a static model list [10][13].
Citations:
- 1: [Feature Request] Add support for Volcengine Ark Coding Plan (火山引擎方舟) tddworks/ClaudeBar#229
- 2: https://codepick.dev/en/guides/cline-ark-setup/
- 3: https://docs.openclaw.ai/concepts/agent-runtimes
- 4: https://codepick.dev/en/guides/ark-coding-plan-guide/
- 5: https://docs.hagicode.com/en-US/ai-service-subscriptions/volcengine/
- 6: Feature Request: Add Volcano Engine Coding Plan provider support RightNow-AI/openfang#254
- 7: https://github.com/openclaw/openclaw/blob/main/skills/coding-agent/SKILL.md
- 8: feat: add opencode-cli as CLI backend provider openclaw/openclaw#16099
- 9: https://github.com/openclaw/clawpatch/blob/main/docs/providers.md
- 10: I can't use Volcengine when it's enabled in the system. langgenius/dify#28560
- 11: https://www.alibabacloud.com/help/doc-detail/3002412.html
- 12: feat(openapi): redesign auth pipeline with per-token-type routing langgenius/dify#36693
- 13: Volcengine Plugins Can't Add Volcengine Model langgenius/dify-official-plugins#1968
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- local proxy and provider-config flow ---'
rg -n -C 4 'OPENCODEX_HOME|provider.*config|routedProviderConfig|preserveCustomDestination|start.*server|localhost|127\.0\.0\.1|baseUrl' README.md docs src | head -n 500
printf '%s\n' '--- references to OpenCode versus opencodex ---'
rg -n -C 3 'OpenCode|opencodex|aggregator|proxy|middleware|routing' README.md docs src devlog/_plan/260801_pr611_volcengine_evidence | head -n 500Repository: lidge-jun/opencodex
Length of output: 50377
🌐 Web query:
site:volcengine.com/docs/82379/2556056 Codex CLI Coding Plan config.toml supported clients
💡 Result:
There is no publicly available authoritative documentation or technical information confirming the existence of a "Codex CLI" with a "coding plan" feature or a specific config.toml supported client list. Search results for these specific terms did not yield relevant matches [1].
Citations:
🌐 Web query:
site:volcengine.com/article/37935 Dify Postman curl Coding Plan excluded clients
💡 Result:
There is no information in the provided search results regarding a Coding Plan or excluded clients specifically within the Dify platform. The term Coding Plan, along with associated restrictions on clients, appears to be related to the ByteDance Volcengine Ark platform, which explicitly states that subscription quotas are only valid for AI programming tools and cannot be used for API calls [1]. The available documentation for that service emphasizes that using incorrect base URLs for API-compatible tools can lead to unauthorized API charges or service suspension [1]. For Dify-specific API documentation, Postman usage, or curl integration, the provided sources contain no relevant data.
Citations:
Do not mark routing authorization as satisfied.
The cited Volcengine sources support named clients, not opencodex. OpenCode is distinct from opencodex, which the README identifies as a local provider proxy that routes Codex and Claude Code requests to configured providers. User-owned keys and local storage do not establish authorization for this third-party routing.
Keep Lines 55-57 and 65 conditional, or add a first-party Volcengine statement that explicitly permits opencodex routing. Otherwise, use an inert src/providers/free-directory.ts reference as required by MAINTAINERS.md Lines 35-43.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md` around
lines 33 - 42, Revise the “Routing-authorization finding” to avoid marking
authorization as satisfied based on support for named clients, since that does
not explicitly authorize opencodex routing. Keep the conclusions in Lines 55-57
and 65 conditional unless adding a first-party Volcengine statement permitting
opencodex; otherwise reference an inert src/providers/free-directory.ts entry as
required by MAINTAINERS.md.
| 2. opencodex does **not** resell. Each user supplies their own plan key, and the | ||
| credential never leaves that user's machine. The gate's "resale/aggregator" | ||
| concern targets a service reselling pooled third-party capacity; this preset |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
set -eu
printf '%s\n' '--- ledger context ---'
cat -n devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md | sed -n '30,55p'
printf '%s\n' '--- candidate files ---'
git ls-files | rg -i 'volc|ark|credential|key|evidence|opencodex' | head -200
printf '%s\n' '--- credential and endpoint references ---'
rg -n -i --glob '!devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md' \
'volcengine|ark[-_ ]?api|api[_-]?key|authorization|bearer|credential' . | head -300Repository: lidge-jun/opencodex
Length of output: 46355
🏁 Script executed:
set -eu
printf '%s\n' '--- Volcengine provider tests ---'
wc -l tests/volcengine-providers.test.ts tests/volcengine-ark-assistant-content.test.ts
cat -n tests/volcengine-providers.test.ts | sed -n '1,260p'
cat -n tests/volcengine-ark-assistant-content.test.ts | sed -n '1,220p'
printf '%s\n' '--- focused source references ---'
rg -n -i 'volcengine|ark-assistant|coding.?plan|doubao|ark.cn-beijing|ark.cn-shanghai' src tests config* package.json devlog/_plan/260801_pr611_volcengine_evidence 2>/dev/null | head -300
printf '%s\n' '--- provider and request logging code candidates ---'
rg -n 'baseUrl|apiKey|Authorization|JSON.stringify|console\.(log|error|warn|debug)|logger\.' src | head -300Repository: lidge-jun/opencodex
Length of output: 50375
🏁 Script executed:
set -eu
printf '%s\n' '--- adapter outline and focused implementation ---'
ast-grep outline src/adapters/openai-chat.ts --match createOpenAIChatAdapter --view expanded
cat -n src/adapters/openai-chat.ts | sed -n '1,180p'
cat -n src/adapters/openai-chat.ts | sed -n '330,440p'
printf '%s\n' '--- network dispatch references ---'
rg -n 'buildRequest\(|fetch\(|apiKeyTransport|apiKey' src --glob '*.ts' | head -220
printf '%s\n' '--- config DTO and serialization references ---'
rg -n 'safeConfigDTO|providers.*apiKey|apiKey.*providers|JSON\.stringify|serialize|redact|mask|secret' src/server src/providers src/config src 2>/dev/null | head -260Repository: lidge-jun/opencodex
Length of output: 50375
🏁 Script executed:
set -eu
printf '%s\n' '--- OpenAI chat request construction ---'
cat -n src/adapters/openai-chat.ts | sed -n '540,675p'
printf '%s\n' '--- upstream fetch and request logging ---'
cat -n src/server/responses/core.ts | sed -n '1425,1485p'
cat -n src/server/responses/core.ts | sed -n '2080,2140p'
cat -n src/server/request-log.ts | sed -n '300,390p'
cat -n src/server/request-log.ts | sed -n '560,640p'
printf '%s\n' '--- safe configuration projection ---'
cat -n src/server/auth-cors.ts | sed -n '440,500p'
cat -n src/server/management/provider-routes.ts | sed -n '80,115p'
cat -n src/server/management/provider-routes.ts | sed -n '190,225p'
printf '%s\n' '--- debug diagnostic implementation and call sites ---'
cat -n src/lib/debug.ts | sed -n '1,180p'
rg -n 'debugProviderDiagnostic' src/adapters/openai-chat.ts src/server src/router.tsRepository: lidge-jun/opencodex
Length of output: 32436
🏁 Script executed:
set -eu
printf '%s\n' '--- exact upstream fetch path ---'
cat -n src/server/responses/core.ts | sed -n '2130,2170p'
printf '%s\n' '--- provider API-key endpoint responses and persistence ---'
cat -n src/server/management/provider-routes.ts | sed -n '390,455p'
cat -n src/providers/api-keys.ts | sed -n '1,155p'
rg -n 'saveConfig|config\.json|writeFile|apiKeyPool|apiKey' src/config.ts src/providers/api-keys.ts src/server/management/provider-routes.ts | head -180
printf '%s\n' '--- standalone source verifier ---'
python3 - <<'PY'
from pathlib import Path
import re
adapter = Path("src/adapters/openai-chat.ts").read_text()
auth = Path("src/server/auth-cors.ts").read_text()
routes = Path("src/server/management/provider-routes.ts").read_text()
keys = Path("src/providers/api-keys.ts").read_text()
core = Path("src/server/responses/core.ts").read_text()
debug = Path("src/lib/debug.ts").read_text()
checks = {
"chat request targets provider base URL": 'const url = `${provider.baseUrl}/chat/completions`;' in adapter,
"chat request sends provider key upstream": 'headers["Authorization"] = `Bearer ${provider.apiKey}`' in adapter,
"debug request omits raw headers and body": all(x not in adapter[adapter.index('debugProviderDiagnostic("openai-chat", "request"'):adapter.index('debugProviderDiagnostic("openai-chat", "request"')+600] for x in ("headers", "bodyJson", "apiKey")),
"debug logger redacts before JSON serialization": 'JSON.stringify(redactSecrets(details))' in debug,
"safe config exposes only key presence": 'hasApiKey: !!provider.apiKey' in auth and '"apiKey"' not in auth[auth.index('export function safeConfigDTO'):auth.index('export function safeConfigDTO')+2500],
"provider patch rejects raw apiKey": 'apiKey cannot be patched here' in routes,
"key management masks API keys": 'masked: maskApiKey(entry.key)' in keys,
"upstream fetch receives adapter request": 'fetchWithHeaderTimeout(request.url' in core,
}
for name, ok in checks.items():
print(f"{name}: {'PASS' if ok else 'FAIL'}")
PYRepository: lidge-jun/opencodex
Length of output: 22964
🏁 Script executed:
set -eu
printf '%s\n' '--- exact upstream fetch path ---'
cat -n src/server/responses/core.ts | sed -n '2130,2170p'
printf '%s\n' '--- provider API-key endpoint responses and persistence ---'
cat -n src/server/management/provider-routes.ts | sed -n '390,455p'
cat -n src/providers/api-keys.ts | sed -n '1,155p'
rg -n 'saveConfig|config\.json|writeFile|apiKeyPool|apiKey' src/config.ts src/providers/api-keys.ts src/server/management/provider-routes.ts | head -180
printf '%s\n' '--- standalone source verifier ---'
python3 - <<'PY'
from pathlib import Path
adapter = Path("src/adapters/openai-chat.ts").read_text()
auth = Path("src/server/auth-cors.ts").read_text()
routes = Path("src/server/management/provider-routes.ts").read_text()
keys = Path("src/providers/api-keys.ts").read_text()
core = Path("src/server/responses/core.ts").read_text()
debug = Path("src/lib/debug.ts").read_text()
start = adapter.index('debugProviderDiagnostic("openai-chat", "request"')
debug_request = adapter[start:start + 600]
dto_start = auth.index("export function safeConfigDTO")
dto = auth[dto_start:dto_start + 2500]
checks = {
"chat request targets provider base URL": 'const url = `${provider.baseUrl}/chat/completions`;' in adapter,
"chat request sends provider key upstream": 'headers["Authorization"] = `Bearer ${provider.apiKey}`' in adapter,
"debug request omits raw headers and body": all(x not in debug_request for x in ("headers", "bodyJson", "apiKey")),
"debug logger redacts before JSON serialization": 'JSON.stringify(redactSecrets(details))' in debug,
"safe config exposes only key presence": 'hasApiKey: !!provider.apiKey' in auth and '"apiKey"' not in dto,
"provider patch rejects raw apiKey": 'apiKey cannot be patched here' in routes,
"key management masks API keys": 'masked: maskApiKey(entry.key)' in keys,
"upstream fetch receives adapter request": 'fetchWithHeaderTimeout(request.url' in core,
}
for name, ok in checks.items():
print(f"{name}: {'PASS' if ok else 'FAIL'}")
PYRepository: lidge-jun/opencodex
Length of output: 22964
🏁 Script executed:
set -eu
printf '%s\n' '--- provider fetch helper ---'
rg -n 'function providerFetch|const providerFetch|providerFetch\s*=' src/server/responses src/server src | head -40
rg -n -A35 -B10 'providerFetch' src/server/responses/core.ts src/server | head -180
printf '%s\n' '--- corrected diagnostic verifier ---'
python3 - <<'PY'
from pathlib import Path
import re
adapter = Path("src/adapters/openai-chat.ts").read_text()
start = adapter.index('debugProviderDiagnostic("openai-chat", "request"')
end = adapter.index('});', start) + 3
event = adapter[start:end]
fields = re.findall(r'^\s*(\w+):', event, re.MULTILINE)
raw_secret_terms = [term for term in ("apiKey", "Authorization", "headers", "bodyJson", "body:") if term in event]
print("diagnostic fields:", fields)
print("raw secret-bearing terms:", raw_secret_terms)
print("diagnostic metadata only:", fields == [
"host", "model", "stream", "messageCount", "toolCount", "hasCredential", "bodyBytes"
] and not raw_secret_terms)
print("local key persistence documented:", "lives in `provider.apiKeyPool` in config.json" in Path("src/providers/api-keys.ts").read_text())
PYRepository: lidge-jun/opencodex
Length of output: 13631
State the credential boundary precisely.
Replace “credential never leaves that user’s machine” with: “Each user supplies their own plan key. opencodex stores the key locally in config.json and sends it in the Authorization header directly to the configured Volcengine endpoint. opencodex does not send the key to an opencodex-controlled intermediary.” The key is omitted from debug diagnostics and configuration DTOs, but it is serialized locally, so do not claim that it is never serialized or never leaves the machine.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md` around
lines 43 - 45, Update the credential-boundary statement in the evidence ledger
to specify that users provide their own plan key, opencodex stores it locally in
config.json, sends it via the Authorization header to the configured Volcengine
endpoint, and does not transmit it to an opencodex-controlled intermediary;
remove the inaccurate claim that the credential never leaves the user's machine.
| // (北京火山引擎科技有限公司). Plan quota is restricted to supported AI coding tools and misuse | ||
| // is documented as grounds for suspension — see the `note` on both Plan entries. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
rg -n -C 16 'volcengine-(coding-plan|agent-plan)|note:' src/providers/registry.tsRepository: lidge-jun/opencodex
Length of output: 44577
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import re
path = Path("src/providers/registry.ts")
text = path.read_text()
for provider_id in ("volcengine-coding-plan", "volcengine-agent-plan"):
start = text.index(f'id: "{provider_id}"')
end = text.find("\n {", start + 1)
block = text[start:] if end == -1 else text[start:end]
note = re.search(r'note:\s*"([^"]*)"', block)
print(f"{provider_id}:")
print(note.group(1) if note else "NO NOTE")
print()
print("References to excluded clients and Volcengine plan disclosure:")
for line_no, line in enumerate(text.splitlines(), 1):
if re.search(r"curl|Postman|Dify|Volcengine|Coding Plan|Agent Plan|suspend|ban|general-purpose|general API", line, re.I):
print(f"{line_no}: {line}")
PY
printf '\nRepository references:\n'
rg -n -i -C 3 'curl|postman|dify|excluded.client|excluded client|volcengine.*(coding|agent).*plan|coding plan quota|agent plan quota|general-purpose API|general API calls|suspend|ban the account' . \
-g '!node_modules' -g '!dist' -g '!build'Repository: lidge-jun/opencodex
Length of output: 50378
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import re
path = Path("src/providers/registry.ts")
text = path.read_text()
for provider_id in ("volcengine-coding-plan", "volcengine-agent-plan"):
start = text.index(f'id: "{provider_id}"')
end = text.find("\n {", start + 1)
block = text[start:] if end == -1 else text[start:end]
note = re.search(r'note:\s*"([^"]*)"', block)
print(f"{provider_id}:")
print(note.group(1) if note else "NO NOTE")
print()
print("References to excluded clients and Volcengine plan disclosure:")
for line_no, line in enumerate(text.splitlines(), 1):
if re.search(r"curl|Postman|Dify|excluded.client|excluded client|Volcengine|Coding Plan|Agent Plan|suspend|ban|general-purpose|general API", line, re.I):
print(f"{line_no}: {line}")
PY
printf '\nRepository references:\n'
rg -n -i -C 3 'curl|postman|dify|excluded.client|excluded client|volcengine.*(coding|agent).*plan|coding plan quota|agent plan quota|general-purpose API|general API calls|suspend|ban the account' . \
-g '!node_modules' -g '!dist' -g '!build'Repository: lidge-jun/opencodex
Length of output: 50378
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
for log in /tmp/coderabbit-shell-logs/shell-output-rj0qkw /tmp/coderabbit-shell-logs/shell-output-iVUkmj; do
echo "== $log: verifier output =="
sed -n '1,80p' "$log"
done
echo "== Exact excluded-client references =="
rg -n -i -C 3 '\b(curl|postman|dify)\b' . \
-g '!node_modules' -g '!dist' -g '!build' \
-g '*.md' -g '*.ts' -g '*.json' | head -n 240
echo "== Volcengine plan policy references =="
rg -n -i -C 5 'volcengine|coding plan quota|agent plan quota|general-purpose API|general API calls|suspend|ban the account' \
devlog README.md docs-site src tests \
-g '*.md' -g '*.ts' -g '*.json' | head -n 320Repository: lidge-jun/opencodex
Length of output: 50377
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
ledger="devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md"
if [ -f "$ledger" ]; then
echo "== Ledger policy sections =="
rg -n -i -C 8 'curl|postman|dify|excluded|client|coding plan|agent plan|quota|suspend|ban|base.?url|api key|general' "$ledger" | head -n 360
else
echo "Ledger not found: $ledger"
fi
echo "== Exact plan notes with line numbers =="
sed -n '1158,1195p' src/providers/registry.tsRepository: lidge-jun/opencodex
Length of output: 6839
Update both Volcengine Plan notes. volcengine-coding-plan and volcengine-agent-plan must state that only designated AI coding tools may use the Plan Base URL/API key, that non-tool use may suspend the subscription or ban the account, and that curl, Postman, and Dify are excluded clients.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/providers/registry.ts` around lines 376 - 377, Update the notes for both
`volcengine-coding-plan` and `volcengine-agent-plan` to state that their Plan
Base URL/API key is limited to designated AI coding tools, non-tool usage may
suspend the subscription or ban the account, and `curl`, Postman, and Dify are
excluded clients.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ef5cae9afb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| **Disposition:** authorization is established for the documented coding-tool use, | ||
| and the user-facing risk must be disclosed in the preset `note`, matching the |
There was a problem hiding this comment.
Do not certify direct-client docs as proxy authorization
When ocx is bound to a non-loopback address and downstream callers authenticate with proxy access keys (src/server/auth-cors.ts:192-201), they consume the operator-configured Volcengine key through an intermediary, so a guide for configuring Codex directly does not establish the aggregator/routing permission required by MAINTAINERS.md. This ledger itself identifies Dify middleware as excluded and concedes that the absence of reported proxy bans is not authorization, yet still marks the gate satisfied; because Volcengine warns of subscription suspension or account bans, obtain explicit primary-source authorization for proxy routing or demote the preset instead of certifying this requirement.
AGENTS.md reference: AGENTS.md:L150-L156
Useful? React with 👍 / 👎.
| | Documented OpenAI-compatible endpoints | satisfied (claims 1-3) | | ||
| | Terms of service + operating legal entity | satisfied (claims 4-5) | | ||
| | Resale / routing authorization | satisfied for coding-tool use (claims 6-7), with disclosure required (claims 8-9) | | ||
| | Named maintenance owner | satisfied — **@lidge-jun**, recorded in `src/providers/registry.ts` above the Volcengine block | | ||
| | Citable verification date | satisfied by this ledger: 2026-08-01 | |
There was a problem hiding this comment.
Move the completed evidence unit out of _plan
This table records every requirement as satisfied and the remainder of the document assigns ownership without identifying any open work, so creating it under devlog/_plan/ makes the repository's open-unit inventory report a terminal record as unfinished. Move the unit to devlog/_fin/ once the gate has a defensible terminal disposition, as required by the documented devlog lifecycle.
AGENTS.md reference: AGENTS.md:L39-L42
Useful? React with 👍 / 👎.
| - **What must be updated together.** The `note` strings on both Plan entries and the | ||
| restriction blockquote in `docs-site/src/content/docs/guides/providers.md` are the two | ||
| places that state the vendor's usage boundary. If Volcengine changes those terms, both | ||
| change or neither is true. |
There was a problem hiding this comment.
Include every policy copy in the maintenance checklist
If Volcengine changes its Plan terms and the named owner follows this checklist, only the registry notes and English guide blockquote will be updated: the newly added registry comment also states the restriction, while docs-site/src/content/docs/{ja,ko,ru,zh-cn}/guides/providers.md contain parallel Volcengine sections and already omit this warning. Listing only these two update targets therefore guarantees stale or contradictory policy text for localized readers; synchronize the current translations and include every policy-bearing copy in the maintenance procedure, or derive the text from one source.
AGENTS.md reference: AGENTS.md:L163-L164
Useful? React with 👍 / 👎.
Summary
Names a maintenance owner for the three Volcengine Ark presets that landed in #611, and commits the primary-source evidence ledger behind them.
MAINTAINERS.mdrequires a named maintenance owner for every canonical preset — who updates it when the base URL, authentication, or catalog contract changes, and how a break gets reported. #611 satisfied the rest of the credential-destination gate but never supplied that line, and the contributor did not respond to the request before the merge. A canonical preset with no owner is a route nobody has agreed to keep true, so I am taking it rather than leaving the gate open on a merged entry.Why this matters more here than for most presets
Both Plan entries are
liveModels: false. A stale model id cannot self-heal through discovery and reaches the user as an upstream model error —glm-5.1was already exactly that case during review, corrected toglm-5.2. The base URLs and Volcengine's Plan usage terms are the other two moving parts.The ledger also records what must change together: the
notestrings on both Plan entries and the restriction blockquote in the provider guide both state the vendor's usage boundary. If Volcengine changes those terms, both change or neither is true.Evidence recorded
devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.mdcarries the sources opened on 2026-08-01:notedisclosure exists to surfaceValidation
bun run typecheckbun test tests/volcengine-providers.test.ts tests/provider-registry-parity.test.ts— 47 pass, 0 failbun run privacy:scanNo runtime behavior changes: this is a registry comment and a devlog document.
Summary by CodeRabbit