Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# PR #611 Volcengine Ark — credential-destination evidence ledger

Research record for the `MAINTAINERS.md` evidence gate on PR #611. Sources were
opened, not read from search snippets. Verification date: **2026-08-01**.

## Why this unit exists

PR #611 adds three canonical presets (`volcengine`, `volcengine-coding-plan`,
`volcengine-agent-plan`). A new preset is a credential-destination change, so
`MAINTAINERS.md` requires five evidence items before merge. A maintainer security
review (Ingwannu, on `bdfc05c23`) blocked on that gate with "Do not merge the
current head as a canonical preset". This ledger settles each item.

## Claim ledger

| # | Claim | Status | Primary source | Date |
|---|-------|--------|----------------|------|
| 1 | Pay-as-you-go base URL is `https://ark.cn-beijing.volces.com/api/v3` | verified | docs.volcengine.com/docs/82379/1494384 | — |
| 2 | Coding Plan base URL is `.../api/coding/v3` | verified | docs.volcengine.com/docs/82379/1528783 | 2026-07-07 |
| 3 | Agent Plan base URL is `.../api/plan/v3`, native Responses | verified | docs.volcengine.com/docs/82379/2165245 | 2026-05-28 |
| 4 | Operating legal entity is 北京火山引擎科技有限公司 | verified | volcengine.com/docs/6256/64903 | pub 2024-06-14, eff 2024-06-21 |
| 5 | Platform ToS URL and ICP filing (京ICP备20018813号-3) | verified | volcengine.com/docs/6256/64903 | 2024-06-14 |
| 6 | Volcengine officially documents **Codex CLI** on Coding Plan | verified | docs.volcengine.com/docs/82379/2556056 | — |
| 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 |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 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.

| 11 | MiniMax terms forbid sublicensing/reselling outside an integrated application | verified | platform.minimax.io/protocol/terms-of-service | crawled 2026-08-01 |

`liveModels: false` on all three entries, so the gate's authenticated
`GET /v1/models` clause does not apply.

## 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.
Comment on lines +33 to +42

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 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_evidence

Repository: 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_evidence

Repository: 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.ts

Repository: 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 300

Repository: 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:


🏁 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

Repository: 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
Comment on lines +43 to +45

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 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 -300

Repository: 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 -300

Repository: 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 -260

Repository: 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.ts

Repository: 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'}")
PY

Repository: 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'}")
PY

Repository: 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())
PY

Repository: 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.

only points a first-party client at a first-party endpoint.

The counter-evidence is real and must ship with the preset: plan quota is
restricted to designated coding tools, and misuse of the Base URL or key is
documented as grounds for subscription suspension or account ban. `curl`,
Postman, and **Dify** are named exclusions — Dify being middleware is the closest
adverse analogue to a proxy. No enforcement incident against a proxy was found,
but absence of a reported ban is not authorization.

**Disposition:** authorization is established for the documented coding-tool use,
and the user-facing risk must be disclosed in the preset `note`, matching the
Comment on lines +55 to +56

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge 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 👍 / 👎.

`tencent-coding-plan` precedent at `src/providers/registry.ts`.

## Gate result

| Requirement | Result |
|---|---|
| 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 |
Comment on lines +63 to +67

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.


## Maintenance ownership

The contributor did not name an owner, and a canonical preset without one is a route
nobody has agreed to keep true. Rather than leave the gate open on a merged entry, the
project owner (**@lidge-jun**) takes it.

What that means concretely:

- **What rots first.** Both Plan entries are `liveModels: false`, so a stale model id
cannot self-heal through discovery and surfaces to the user as an upstream model error
(`glm-5.1` was already one such case, corrected to `glm-5.2` during review). The base
URLs and the Plan usage terms are the other two moving parts.
- **How a break is reported.** Open an issue tagging the owner. A user-visible symptom is
usually an upstream "unknown model" error or a 4xx from a moved base URL.
- **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.
Comment on lines +83 to +86

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

11 changes: 11 additions & 0 deletions src/providers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,17 @@ const TENCENT_CODING_PLAN_MODELS = ["tc-code-latest", "glm-5", "kimi-k2.5", "min
// Volcengine's authenticated /api/v3/models catalog mixes chat models with embedding,
// image, video, and 3D generation resources. Keep the Codex-facing presets scoped to
// models documented for text/agent or Coding Plan use.
//
// Maintenance owner: @lidge-jun. Verified 2026-08-01 against the vendor's own docs —
// endpoints https://docs.volcengine.com/docs/82379/1528783 (Coding Plan) and
// https://docs.volcengine.com/docs/82379/2165245 (Agent Plan); Codex CLI integration
// https://www.volcengine.com/docs/82379/2556056; supported clients
// https://www.volcengine.com/docs/82379/2188957; terms https://www.volcengine.com/docs/6256/64903
// (北京火山引擎科技有限公司). Plan quota is restricted to supported AI coding tools and misuse
// is documented as grounds for suspension — see the `note` on both Plan entries.
Comment on lines +376 to +377

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 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.ts

Repository: 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 320

Repository: 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.ts

Repository: 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.

// Report a break by opening an issue tagging the owner; the three things that rot first are the
// static catalogs (liveModels:false cannot self-heal), the base URLs, and those Plan terms.
// Full evidence ledger: devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md
const VOLCENGINE_ARK_MODELS = [
"doubao-seed-2-1-pro-260628",
"doubao-seed-2-1-turbo-260628",
Expand Down
Loading