Skip to content

Support OpenAI-compatible Codex model endpoints - #913

Merged
freeqaz-openai merged 8 commits into
mainfrom
oce-oss-model-support
Oct 13, 2026
Merged

freeqaz-openai merged 8 commits into
mainfrom
oce-oss-model-support

Conversation

@sallyom

@sallyom sallyom commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Current verification (2026-10-13)

Head: a57cde8b7d55e0ec67d2ae6c1d7f0b797bc9f6ac. Endpoint validation and source-ownership checks now fail earlier, while existing source profiles and recovery behavior remain supported.

  • Local verification passed 97 focused tests with no skips, lint, typecheck, documentation checks, the CI suite audit, and the pre-push formatting hook. The tests use recorded gateway storage and loopback fixtures; they do not establish live OpenShell or provider execution.
  • An independent GPT-6 Astra review of the fixes found no actionable P0–P2 issue in that scope. The broader autoreview did not complete; its timeout is not a clean verdict. OpenShell provider and profile operations remain separate and are not atomic.
  • CI for this head was queued or running at publication. Prior entries below describe historical heads and do not establish this head’s CI result.

Summary

Support HTTPS OpenAI-compatible Responses endpoints for dedicated Codex Agents using Bearer API-key authentication.

  • Add optional config.base_url to OpenShell openai CredentialSources. It defaults to https://api.openai.com/v1; custom profiles bind credentials to the normalized host, port, base path, and configured executable identities. Source endpoints remain immutable.
  • Add Kubernetes Compute runtime.codexModelBaseUrl for Secret-backed dedicated Codex without OpenShell. Credential-source authentication uses its own endpoint instead of this Installation setting.
  • Carry the endpoint and native provider together through Codex configuration and startup probing. Compile explicit provider-qualified references in the private Gateway configuration, preserving complete namespaced IDs while leaving admitted Configuration, revision, and Harness model IDs unchanged.
  • Add --base-url and --model-id to the Codex scripts/k3d test and default/demo commands. Flags override inherited and prepared settings; credentials remain in OPENAI_API_KEY, with no key flag.
  • Extend existing Gateway and retained-thread integration checks to verify Codex's recorded provider and complete model ID. Update the owning references, guides, and source-backed flows.

Usage

With OpenShell, register an openai CredentialSource with config.base_url and bind the Agent using credential_source. Without OpenShell, configure runtime.codexModelBaseUrl and use a Secret-backed api_key binding.

For a manual Podman trial, set OPENAI_API_KEY privately to the endpoint's key and use fresh helper state to build the current images:

export OCC_K3D_STATE_DIR="$HOME/.local/state/openclaw-enterprise/openrouter-$(date +%s)"
OCC_K3D_CONTAINER_ENGINE=podman ./scripts/k3d test --harness codex \
  --base-url https://openrouter.ai/api/v1 \
  --model-id z-ai/glm-5.3-flash

The same model options work with the default foreground demo command. --model-id takes the endpoint's complete native model ID.
Keep the state-directory selection for cleanup with OCC_K3D_CONTAINER_ENGINE=podman ./scripts/k3d down --harness codex; this removes the recorded disposable cluster and database.

Verification

Head at this historical checkpoint: 3d1103db7459691b2718de781abd4b28be4fff11, a topology-preserving refresh of 3ecb541f6560a00554b4051c31ee978ed04a446b. Parents: unchanged 90268463bbd255c3c13a0e0bdeb437728189eb1a and main d2fe579cd51f53bb979f0cb0f9ad8785b5f4585a; published tree 2851db90d165f472deae1ee717be01b86ad5c772. Only the latest integration merge was recreated. All five earlier commits, including Kevin's merge, retain their exact identities; original merge authorship/date/message and Sally's co-author trailer are preserved. Publication used an exact-ref lease against the previous head.

Execution-CA and endpoint integration (2026-10-11, head 3d1103db7)

  • Combine main's execution-cluster CA coverage with the existing custom-endpoint/LAN Gateway document-adoption regression. Its eight cases retain default/custom endpoint behavior, omitted/auto/explicit-LAN bindings, two-cluster CA data, admitted-model immutability, ConfigMap retention without writes, and rejection of altered model/bind values. Separate negative controls fail when the earlier document loses endpoint projection or its ConfigMap loses the execution CA; restored code passes. These tests exercise real Compute preparation/reconciliation with Kubernetes transport doubles, not a live cluster. Production PR behavior is unchanged by the manual resolution.
  • 939 fresh selected tests passed, 0 failed, 0 skipped across 13 files. The API/OCC/credential/configuration/Compute/plugin/OpenShell/startup/launcher and workspace-node-supervisor selection was rerun on the exact candidate. Targeted reruns and negative controls are not added to that total. Passed pnpm lint, pnpm format:check, pnpm typecheck, pnpm docs:check, pnpm openapi:check, pnpm check:workspace, the CI suite audit and three flow validators. Docs: 258 pages / 4054 links. Dependency manifests matched existing local installations; no installation was needed. The unchanged pre-push hook passed.
  • Canonical GPT-6 Astra high-reasoning P0–P2 review of the exact candidate completed scoped-clean, and independent source review approved it. This is static review: the reviewer did not execute project tests or independently verify packaged-runtime/live-cluster behavior. The actual PR-delta whitespace check passes; broader first-parent inspection found trailing spaces in an incoming main Go fixture's raw text, preserved byte-for-byte rather than changing unrelated test input.
  • Proof gaps remain: the two current packaged-native checks are unrun locally because no matching current image is available. OpenClaw/Codex recipe pins remain unchanged, but main changes five packaged repository-credential client files, so full-image equivalence is not claimed. The older Codex 0.160.0 image was not substituted for 0.163.0-alpha.2, and unchanged registry/attestation-trust failures were not retried. Go/gofmt and Compose/database prerequisites remain unavailable. No live inference, cluster, durability or full-image qualification is claimed. Previous-head CI is successful historical evidence for 3ecb541f6, not this head.
  • Hosted status at publication: GitHub reports MERGEABLE with merge state BLOCKED. Exact-head CI, CodeQL, Observability Demo and QA Matrix Advisory are queued/running. No completed CI or merge-readiness claim. The final pre-push preview against main d2fe579cd51f53bb979f0cb0f9ad8785b5f4585a was conflict-free and identical to the published tree.

Historical native-hook main integration (2026-10-10, head 3ecb541f6)

Head at that checkpoint: 3ecb541f6560a00554b4051c31ee978ed04a446b, a topology-preserving refresh of 0b5d7c9d6b825e1df836da67aed04f4dd3c9f8b8. Parents: unchanged 90268463bbd255c3c13a0e0bdeb437728189eb1a and main 73695fce6e0be52d79782d3d0d0a829315122fea; published tree 9b81f022b9f0e260c0083352890abb2595679ea4. Only the latest integration merge was recreated. All five earlier commits, including Kevin's merge and the subagent-routing fix, retain their exact identities; original authorship/date/message and Sally's co-author trailer are preserved. Publication used an exact-ref lease against the previous head.

  • Preserve main's Sandbox Harness HOME contract and native-hook trust of the file-delivered Gateway CA. The only new manual conflict was the OpenShell flow changelog: both histories and Manual Notes are retained. Repeated narration was trimmed from 2,543 to 2,488 words without removing endpoint, ownership or readiness limits. The PR's production changes remain equivalent to the preceding head, including the seven field-specific 400 validators and projection before both current/earlier Gateway documents.
  • 893 fresh selected tests passed, 0 failed, 0 skipped across 13 files. The prior twelve API/OCC/credential/Compute/plugin/OpenShell/startup/launcher selections were rerun, plus tests/conformance/workspace-node-supervisor.test.mjs for the current native-hook owner. These are source/API/Driver and supervisor-fixture checks, not packaged Codex or live-cluster proof.
  • Passed pnpm lint, pnpm format:check, pnpm typecheck, pnpm docs:check, pnpm openapi:check, pnpm check:workspace, the CI suite audit, three flow validators and whitespace checks. Docs: 256 pages / 4018 links. Dependency manifests matched existing checkout-local installations; no installation or toolchain change was needed. The unchanged pre-push formatting hook passed.
  • Fresh canonical GPT-6 Astra high-reasoning P0–P2 review of the exact tree completed scoped-clean, with the current Enterprise admission contract supplied. Independent source review approved the same candidate. This is static review: the reviewer did not independently execute the reported tests, establish exact dependency behavior or verify packaged-native/live integration. Earlier review findings and their dispositions below remain historical records.
  • Remaining gaps: the two current packaged-native boundary checks remain unrun locally because a matching image is unavailable. The unchanged registry/attestation-trust build failure was not retried, and the older Codex 0.160.0 image was not substituted for the current 0.163.0-alpha.2 selection. Go/gofmt and Compose/database prerequisites remain unavailable. No live inference, cluster, durability, OS-base or full-image qualification is claimed. Successful previous-head CI belongs to 0b5d7c9d6, not this head.
  • Hosted status at publication: GitHub reports MERGEABLE with merge state BLOCKED. Exact-head CI, CodeQL, Observability Demo and QA Matrix Advisory are queued/running; no completed CI or merge-readiness claim. The pre-push preview against newer main 10a730e46ff594aa3d2b7157a382fb032325e39a was conflict-free (tree 45921f6791fefce145b2201486699fa5ea703ea5); that newer main is not a parent of this commit.

Historical Gateway document refresh (2026-10-10, head 0b5d7c9d6)

Head at that checkpoint: 0b5d7c9d6b825e1df836da67aed04f4dd3c9f8b8, a topology-preserving refresh of 37bfd913854df90a5c9c698d98efd457845576dd. Parents: unchanged 90268463bbd255c3c13a0e0bdeb437728189eb1a and main 58eddb3cb933336df87ea9984f063d0e59b9ce5c; published tree 5f06e05e13e3c3549ce06d95339fe169d48e5871. Only the latest integration merge was recreated. The five earlier commits, Kevin's merge, original authorship/date and Sally's co-author trailer are preserved. Publication used an exact-ref lease against the previous head.

  • Reconcile main's recognition of immutable Gateway ConfigMaps rendered before the LAN-bind change with this PR's custom-endpoint projection. Both current and earlier documents are derived after the plugin-runtime snapshot, retaining explicit provider/model references. Main's existing earlier-document policy is unchanged. The seven field-specific 400 validators, endpoint normalizer, model/subagent compiler, plugin TOML renderer and native-peer fixture remain byte-identical to 37bfd913.
  • Extend the existing Gateway document-adoption test across default/custom endpoints and omitted/auto/explicit-LAN binding. It verifies model qualification, admitted-input immutability, retention without ConfigMap writes, and rejection of altered binding or model projection. A negative control that omitted endpoint projection from the earlier document fails adoption; the corrected integration passes. This exercises the real Compute preparation/reconciliation code with Kubernetes transport doubles, not a live cluster.
  • 888 fresh selected tests passed, 0 failed, 0 skipped, across the same twelve API/OCC/credential/configuration/Compute/plugin/OpenShell/startup/launcher files. Passed pnpm lint, pnpm format:check, pnpm typecheck, pnpm docs:check, pnpm openapi:check, pnpm check:workspace, the CI suite audit and three flow validators. Docs: 256 pages / 4017 links. Existing dependency graphs matched the manifests; no installation was needed. The normal pre-push formatting hook passed.
  • Review disposition: Astra completed with one P2 alleging loss of an unselected provider catalog row; its raw verdict was not clean. Enterprise admission explicitly rejects such rows before Compute: provider catalog rows must name a configured primary or fallback. Source inspection and executable probes confirmed rejection of the proposed input, while an admitted primary/fallback control preserves both rows, metadata, replace mode and input immutability. Independent source review accepted that disposition. No compiler or admission-policy change was made, and the probes are not added to the 888-test count.
  • Current proof gaps: the two packaged-native boundary checks remain unrun locally because no matching prepared image is available; unchanged failed builds were not retried and the older Codex 0.160.0 image was not substituted for the unchanged 0.163.0-alpha.2 selection. Go/gofmt and Compose/database prerequisites remain unavailable. No live inference, cluster, durability or full-image qualification is claimed. Prior-head CI, including its image jobs, succeeded for 37bfd913; that is historical proof, not a new-head result.
  • Hosted status at publication: GitHub reports MERGEABLE and merge state BLOCKED. New-head CI, CodeQL, Observability Demo and QA Matrix Advisory are queued/running; completed CI and merge readiness are not claimed. The pre-push preview against newer main 19fcab36a6ad30ceb6de4ba4e13752bba982ad3e was conflict-free (preview tree 0a8c2745b11089fc5c5774205dea9a26123007c7); that newer main is not a parent of this commit.

Historical topology-preserving refresh (2026-10-10, head 37bfd913)

Head at that checkpoint: 37bfd913854df90a5c9c698d98efd457845576dd, a topology-preserving refresh of 49cf10d40ee07a225ef7fcb0c44b3b1ee5ec1a33. Its parents are the unchanged PR tip 90268463bbd255c3c13a0e0bdeb437728189eb1a and main 100c0d7787d2fcd5f89812c52e26f4ee0ec2ccdf; published tree a22aba08b7c3e9068e80a262b71e9f9e6c0d78d6. Only the latest integration merge was recreated. All five earlier commits, including Kevin's merge and the subagent-routing fix, remain byte-identical, with original authorship and Sally's co-author credit preserved. Publication used an exact-ref lease against the previous head.

  • Integrate main's credential refresh, source-only update locking and failure audit, native HTTP/TLS/Pod-IP readiness, workspace/peer recovery, and plugin approval/default settings without dropping endpoint validation, source ownership/deletion fences, withdrawal recovery, complete model IDs or subagent selectors. Custom endpoint TOML retains main's root approval policy and plugin defaults through the existing renderer, including its earlier immutable ConfigMap variants. Both histories and Manual Notes are preserved.
  • 879 focused tests passed, 0 failed, 0 skipped across twelve existing CredentialSource/Secret/OCC API, credential-source OCC, Kubernetes Compute/runtime credentials, Configuration OCC, OpenShell wire, plugin Compute, HTTP errors, startup and k3d launcher files. These use source/API/Driver fixtures, not a live cluster or model. During integration, reproduced and corrected a recording Driver's missing mandatory validator and an endpoint-TOML assertion that omitted main's new approval policy.
  • Review correction: offered bearer-token/OAuth2 invalid values were returning 404, contrary to the generic configuration-validation contract. Seven existing value validators now return field-specific 400 INVALID_REQUEST; accepted values are unchanged, unoffered types retain 409, and structural/catalog-field handling stays separate. The added API regression covers eight invalid field cases through real Fastify/IAM/OCC/OpenShell Driver admission, with remote gateway storage doubled: all failed with 404 before repair and pass with precise 400 details before Secret reads, record creation or gateway mutation. Run node --test --test-name-pattern='offered OpenShell source values' tests/integration/credential-source-api.test.mjs; its nine reported tests include the parent and are already counted in 879. The existing direct-validator expectation was updated to the same error contract.
  • Passed pnpm lint, pnpm format:check, pnpm typecheck, pnpm docs:check, pnpm openapi:check, pnpm check:workspace, node scripts/ci/run-tests.mjs audit, three flow validators and whitespace checks. Docs: 256 pages / 4016 links. Final GPT-6 Astra P0–P2 autoreview and independent source review found no actionable issue in the published tree. The autoreviewer did not independently rerun tests. The unchanged pre-push formatting hook passed.
  • Two current packaged-runtime checks remain unrun: runtime image spawns custom-provider subagents with intact native model IDs and runtime image validates the configuration dedicated native OpenClaw renders. Main pins OpenClaw 90d30a1178a79dddd92e6190b66b95d89dfb3ca8, now with Codex 0.163.0-alpha.2 and its dependency patch. The available older image reports Codex 0.160.0 and was not substituted. Fresh current-recipe builds failed on registry connectivity and then package-attestation certificate validation; TLS and supply-chain checks were not weakened. The earlier two packaged checks and 806-test total below are historical, not proof of this head.
  • Other gaps: Go/gofmt and a Compose provider remain unavailable. No current Go, PostgreSQL, live inference, cluster, durability, OS-base or full-image qualification is claimed. Publishing this refresh does not waive those requirements or establish merge readiness.
  • Hosted status at publication: GitHub reports MERGEABLE with merge state BLOCKED; CI, CodeQL, Observability Demo and QA Matrix Advisory are queued/running for this exact head. No completed CI result is claimed. The final pre-push merge preview against main 100c0d7787d2fcd5f89812c52e26f4ee0ec2ccdf was conflict-free and identical to the published tree.

Historical additive main integration (2026-10-09, head 49cf10d40)

Head at that checkpoint: 49cf10d40ee07a225ef7fcb0c44b3b1ee5ec1a33, an additive merge of PR head 90268463bbd255c3c13a0e0bdeb437728189eb1a and main 8e5a06cec7f622185222a8a7dbafe3b0a7228d9f. Published tree: 450c98bd885abe95f65ab02217342b5733be7dd4. All existing commits, original authors, Kevin's merge contributions and Sally's attribution remain intact; no rebase or force push was used.

  • Resolve all eight merge conflicts while preserving main's source-type/catalog 409 errors, withdrawal gates/rechecks, canonical native model/workspace setup, main-Agent roster admission and HTTP readiness, alongside this PR's field-specific pre-Secret 400 validation, absence-only cleanup fences, endpoint safeguards and explicit subagent routing. The model compiler, shared endpoint normalizer and native peer fixture are byte-identical to the preceding PR head. Both flow histories and Manual Notes are preserved.
  • 804 focused tests passed, 0 failed, 0 skipped, across the CredentialSource/Secret/OCC API, credential-source OCC, Kubernetes Compute/runtime credentials, Configuration OCC, OpenShell wire, plugin Compute, HTTP errors, startup and k3d launcher suites. The initial run had 803 passes and one failure: main's stricter roster admission exposed a multi-Agent fixture missing agents.ownership: "explicit". The fixture was corrected and the complete selection rerun; admission was not weakened.
  • Two additional packaged-runtime tests passed, 0 failed, 0 skipped (806 selected tests total). runtime image spawns custom-provider subagents with intact native model IDs verifies all four dispatches through real packaged Gateway admission and the Codex plugin to the synthetic native WebSocket peer. runtime image validates the configuration dedicated native OpenClaw renders validates main's generated Gateway/worker configurations through production entrypoints and the actual image CLI; its model probe is replaced.
  • Passed pnpm lint, pnpm format:check, pnpm typecheck, pnpm docs:check, pnpm openapi:check, pnpm check:workspace, the CI suite audit, three flow validators and whitespace checks. Docs: 248 pages / 3945 links. The required GPT-6 Astra P0–P2 autoreview and independent source review found no actionable issue in the exact published tree. The autoreviewer assessed source and supplied evidence; it did not independently rerun tests. The normal pre-push formatting hook passed.
  • Local limits: pnpm cli:check could not complete because Go/gofmt are absent. Disposable PostgreSQL preparation via scripts/ci/prepare.mjs --lane postgres-application failed because no Docker/Podman Compose provider is installed; no database suite passed or database resources were created. These are missing proofs, not passes or a waiver.
  • Runtime proof boundary: the reused image contains the identical pinned OpenClaw 90d30a1178a79dddd92e6190b66b95d89dfb3ca8 source/archive and bridge patches. It does not requalify main's updated Debian/Node base or constitute fresh full-image qualification. The synthetic peer stops before inference. No live model response, fallback execution, cluster deployment, durability, database or Go proof is claimed by these runs. Historical runtime evidence below remains historical.
  • Hosted status at publication: GitHub reports MERGEABLE (no conflicts), with merge state BLOCKED and CI still pending; this is not a merge-readiness claim. Exact-head CI, CodeQL and Observability Demo have started; successful completion is not claimed. Native Container Verification was not selected. A read-only merge preview against newer main 64dff25990334c8cf1e9372d5452c38cdcadfa61 was conflict-free (preview tree b290b6933ca83bd321e7c3969ffb360d28d7f519); that newer main is not a parent of this commit.

Historical subagent routing and endpoint naming follow-up (2026-10-09, head 90268463b)

  • Qualify explicit agents.defaults.subagents.model and Agent-entry subagents.model through the existing endpoint projection, including string and primary/fallback forms. Add referenced child models to the projected catalog while preserving aliases (including aliases named codex/openai), omitted selectors, native IDs and admitted input.
  • Rename the development-only Installation option to runtime.codexModelBaseUrl consistently across its type/schema, callers, docs and tests, without a legacy alias. HTTPS OpenAI-compatible Responses and API-key-only limits are unchanged; unrelated OPENAI environment/protocol names remain intact.
  • 442 selected tests passed, 0 failed, 0 skipped: 441 focused Compute/configuration/plugin tests plus one packaged-runtime integration test covering four child dispatches. The new case is registered in the existing runtime-startup CI lane.
  • Real packaged OpenClaw 90d30a1178a79dddd92e6190b66b95d89dfb3ca8 performs authenticated sessions_spawn admission, child dispatch and Codex-plugin native request construction. With the original compiler, thread/start received modelProvider=vendor and model=organization/default-child. After repair it receives modelProvider=openai-compatible and the complete model=vendor/organization/default-child. Default-string, entry-string, entry-primary/fallback-object and provider-named alias cases pass.
  • Proof boundary: only the external Codex WebSocket peer is synthetic; its catalog uses independent native IDs and it refuses before inference. This proves the actual Gateway/plugin-to-native-protocol routing boundary, not a live Codex process, model response, fallback inference, cluster deployment or durability. The isolated runtime has no external network/model credentials. Local Podman mount translation preserved the tested UID/GID, modes, size bounds and isolation; no production recipe/pin or runtime isolation change is included.
  • Lint, formatting, typecheck, OpenAPI, workspace boundaries, CI suite audit, flow and whitespace checks passed. Docs: 244 pages / 3859 links; changed page counts 2488 / 2498 / 2488, with Manual Notes/history preserved. Required GPT-6 Astra P0–P2 autoreview and independent source review approved tree ef3305feb26ea4231cf0dc398c6041a79b6fb914. No Go proof is claimed: Go/gofmt remain unavailable and no Go source changed.
  • Hosted status at publication: GitHub reports CONFLICTING / DIRTY. The exact-head Actions query shows ClawSweeper Dispatch (pull_request_target) only; normal PR CI has no run for this conflicting head. Earlier CI/runtime results below are historical, not current-head proof. The PR is not merge-ready.

Historical rebase verification (2026-10-08, head f9126efaa)

Head at that checkpoint: f9126efaada11f8cc18931aa8327f7e16cae59b6, a topology-preserving rebase onto c8d4425227f75a6c580fedb952d63ac8920208a5. The original three PR commits are unchanged. The recreated merge preserves Kevin’s original author metadata and resolution work, with Sally’s co-author trailer retained on all four commits. Before publication, a read-only merge preview against newer main 2dd0f01e0016abeccf38edef3e288f640c59f9b2 was conflict-free; that later main is not the pinned rebase base.

  • Preserve current-main credential ownership semantics: refuse old-gateway deletion before marking the source deleting; retain permanent Secret-owner provisioning refusal, known-type removal, and binary-profile narrowing alongside the PR’s pre-Secret endpoint validation, ownership-fenced cleanup, and explicit model routing.
  • Fresh verification on this candidate tree: 724 passed, 0 failed, 0 skipped across twelve API/OCC/Compute/OpenShell/startup/launcher files. Adapted one new recording Credential Gateway fixture to the required validator, with its failure reproduced before repair. These are source/API/Driver fixture checks, not live deployment or model proof.
  • Passed lint, formatting, typecheck, OpenAPI freshness, workspace boundaries, CI suite audit, three flow validators, and whitespace checks. Required GPT-6 Astra P0–P2 autoreview and independent source review approved the exact published tree.
  • Full docs check passed: 244 pages / 3859 links. Flow word counts: credential lifecycle 2451, execution topology 2492, OpenShell provisioning 2480. Manual Notes and historical changelog entries are preserved.
  • Local verification gaps: Go/gofmt remain unavailable; pnpm cli:check could not complete. PostgreSQL provisioning/worker suites explicitly skipped 144 cases because no disposable test database was configured; none are counted as passes. No live model, cluster, or OpenShell runtime suite was rerun.
  • Exact-head CI run 37773835350, CodeQL, and Observability Demo started and were in progress at publication. Full hosted completion is not claimed. GitHub reported the PR mergeable at that checkpoint; this is not current mergeability evidence.

Historical endpoint host follow-up (2026-10-06, head 31b1b6a9a)

  • Reject stars in WHATWG-normalized hostnames, including literal, percent-encoded, and IDNA-normalized forms, and reject reserved port zero in the shared endpoint validator.
  • The OpenShell Driver additionally rejects bracketed IPv6 host representations before Secret reads or persistence, returning 400 INVALID_REQUEST with /config/base_url. The upstream profile matcher treats brackets as character classes; no unproven glob-escaping fallback is used. Shared Compute URL validation still accepts concrete IPv6 literals.
  • Registration/attachment and status/removal use the same OpenShell-safe boundary. Invalid stored rows recover only after confirmed provider absence; a present provider remains protected rather than guessed/deleted. Concrete DNS/IDNA names, IPv4, and existing nonzero custom ports retain their prior behavior.
  • Fresh verification: 575 passed, 0 failed, 0 skipped across eight API/OCC/Compute/OpenShell suites. Negative controls demonstrated wildcard acceptance before the shared guard and HTTP IPv6 acceptance before the Driver-specific guard; paired Compute IPv6 admission continues to pass.
  • Lint, formatting, typecheck, OpenAPI freshness, workspace boundaries, flow validation, and diff checks passed. Full docs check passed: 242 pages / 3773 links, with no word-budget violations and Manual Notes preserved. Independent source review and required GPT-6 Astra P0–P2 autoreview found no actionable issues in the final candidate.
  • These are source, API, and Driver/fixture checks, not live deployment/model proof. Egress policy is unchanged. CI run 37494636149 started for historical head 31b1b6a9a; it is not current-head CI evidence.

Historical rebase verification (2026-10-06, head 129b9b988)

  • Resolved conflicts while preserving main’s preparation-stage diagnostics, shared-namespace behavior, and OpenShell pre.2 provider-file/endpoint flow, alongside the PR’s validation, normalization, ownership fences, and explicit native model-provider projection. Adapted main’s new recording Credential Gateway test fixture to the required validator.
  • Fresh focused verification: 643 passed, 0 failed, 0 skipped across eleven suites (618 focused Compute/OCC/OpenShell/routing-support checks plus 25 Secret API checks). The fixture’s missing-method failure was demonstrated before adaptation. These fixture/API checks are not real model or deployment proof.
  • Passed lint, formatting, typecheck, OpenAPI freshness, workspace boundaries, CI suite audit, whitespace checks, and three flow validators. Independent rebase review approved the final source tree.
  • Full docs check passed: 242 pages / 3773 links, with Manual Notes preserved. Reconciled word budgets: topology 2439, OpenShell provisioning 2480, Kubernetes Compute reference 2492, Kubernetes testing 2488.
  • No live model/cluster suite was rerun during the rebase. Main now pins OpenClaw 11d3d04a1279781a770f6a6aa09e6322b064b80a; the author-reported runtime evidence below predates this rebase and does not prove the current runtime version.
  • Rebase-head CI run 37456455744 started and was in progress at publication. That run belongs to the rebase head, not the current endpoint-fix head.

Historical original implementation evidence

  • Focused OCC configuration, Kubernetes Compute, and plugin Compute conformance passed; one Linux-specific argument-limit case was skipped on macOS.
  • Launcher process tests: 26 passed, no skips. These use stub commands to verify parsing, precedence, environment-only credentials, and dispatch; they do not prove cluster or model execution.
  • The new renderer regression fails against the previous Kubernetes driver and passes with the change. Eight source-level checks of the renderer with the pinned OpenClaw resolver preserve provider/model distinctions, including multi-slash and provider-looking native IDs.
  • Lint, typecheck, formatting, workspace boundaries, affected flow validators, and diff checks passed during implementation. The latest test-harness expectation correction passed lint, formatting, syntax checks, and local review.
  • Local independent reviews completed; reported concerns were checked against the actual Driver and OCC admission contracts.

Historical review follow-up (pre-rebase)

  • Reject invalid CredentialSource endpoint configuration before Secret reads or persistence through the Credential Gateway validation contract. HTTP returns 400 INVALID_REQUEST with /config/base_url; no residual source is retained.
  • Recover invalid persisted endpoints only when the gateway confirms the provider is absent, without deleting profiles. Existing remote resources and unknown source types remain protected.
  • Share endpoint validation/normalization between Compute and the OpenShell Credential Gateway. Cover default/custom/shared profile lifecycles, profile-specific ownership, and native OpenClaw custom-endpoint denial.
  • Focused verification: 559 passed, 0 failed, 0 skipped across OCC configuration/credential-source, Kubernetes/plugin Compute, OpenShell wire, HTTP errors, startup, launcher, and new CredentialSource HTTP tests. The new three-case HTTP suite was rerun successfully after its final assertion cleanup. These API/Driver checks use in-memory gateway storage and Compute-placement doubles; they do not establish real OpenShell execution.
  • Regression proof: before the fix, invalid creation retained a deleting row and invalid-row deletion returned 404; both now pass. The existing endpoint-rendering scenario also failed before normalization and passes after it, preserving native/namespaced model IDs.
  • Full pnpm docs:check passed after explicitly preparing the separate docs dependency graph: 241 pages and 3728 links. The two over-limit flows are now 2456 and 2484 words; Manual Notes are unchanged. All three changed flow validators passed.
  • Lint, formatting, typecheck, OpenAPI freshness, workspace boundaries, CI manifest audit, and diff checks passed. Independent source review and the repository autoreview helper (GPT-6 Astra, P0–P2) found no actionable findings in the follow-up candidate.

Work sessions: Original discussion with @sallyom · Implementation and verification.

Historical hosted verification (pre-rebase): CI run 37304740783 succeeded for head 4a95cca5b9b87c293dd6f68b3ae7a84ce1e5c541, testing GitHub merge revision 2e60e624619233c92841ffe147cece96a9eb852f against main 5a2dd43d2e524637e7173457def040fa79d42a93. CI Required, Static Checks, both Checks and Conformance lanes, and the selected PostgreSQL, k3d, image, and packaging lanes passed; Native Container Verification was not selected. CodeQL and Observability Demo also passed.

Dedicated Codex with OpenRouter on Podman

Historical author-reported pre-rebase evidence; not rerun for the current head or runtime pin.

The PR author reported a passing manual run of the command above: 1 passed, 0 failed, 0 skipped, approximately 216 seconds. The run reused its prepared cluster, PostgreSQL database, and runtime images. OpenClaw reported 2026.9.7 (6f91eda) and the effective Gateway model codex/openai-compatible/z-ai/glm-5.3-flash.

The selected real integration exercised:

  • Gateway model execution and four OCC workspace-file writes/reads through Envoy and Compute-created HTTPRoutes, including fresh native model consumption without API restart.
  • Native node enrollment/reconnect, forged proxy identity and operator-escalation denial, and missing attachment-upload support failing readiness.
  • Missing/invalid credential and direct-peer rejection; key rotation and served certificate renewal preserving OCC access without restart.
  • Gateway Pod replacement preserving the route and workspace files, followed by a second fresh model session.

This is dedicated Codex without OpenShell. The result is author-reported and was not independently rerun.

Remaining verification

The runtime gaps below are carried forward from earlier work; this follow-up did not rerun those suites.

  • The broader dedicated durability/credential-recovery suite and same-Codex-thread resume checks were not selected by the passing routing case.
  • The OpenShell positive compatibility case remains unverified after an authenticated Pod-loopback WebSocket connection failure. Its projection workarounds are verification-only and do not establish production deployment support.
  • The 2026-10-08 rebase’s PostgreSQL provisioning/worker suites skipped 144 cases because no disposable test database was configured; no local database proof is claimed.
  • Go 1.27 and gofmt remain unavailable locally, so the rebase’s pnpm cli:check could not run. No Go source changed in this PR. The pre-rebase hosted lane passed pnpm cli:check && pnpm cli:test; that result is historical, not new-head CLI proof.

Limits

Custom endpoints must use HTTPS, end in /v1 (including prefixes such as /api/v1), and support streaming Responses. URLs with hostname/path stars, port zero, credentials, queries, or fragments are rejected. OpenShell credential sources additionally reject bracketed IPv6 hosts; shared Compute URL validation retains IPv6 literal admission. The OpenShell source profile supplies Bearer authorization; custom x-api-key authentication is outside this change. OAuth and account login modes retain their existing endpoint behavior. The Gateway receives no model credential; direct Secret-backed credentials remain confined to the Harness workload, and OpenShell-backed Harnesses receive only placeholders.

@clawsweeper

clawsweeper Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review blocked

Automated review did not run, so no review verdict was produced.

Reason: The input-safety check rejected material in this revision. No detected value, path, or scanner output is reproduced here.

Automatic review is on hold, including after source changes. Request a fresh re-review after resolving the failure; maintainers can also release the hold through an intentional scanner-policy update.

Next step: If this is a genuine credential, remove and rotate it. If it is an intentional test fixture, a maintainer must review and qualify it.

View the workflow run.

@sallyom
sallyom force-pushed the oce-oss-model-support branch 2 times, most recently from e01d397 to 1165441 Compare October 2, 2026 15:42
@sallyom sallyom changed the title Support OpenAI-compatible OpenShell credential endpoints Support OpenAI-compatible Codex model endpoints Oct 2, 2026
@sallyom
sallyom force-pushed the oce-oss-model-support branch 2 times, most recently from 5309ae0 to 7d7a9a4 Compare October 2, 2026 17:33
@sallyom

sallyom commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

This PR has an OpenClaw patch that is not necessary - Please don't review this until I remove that and promote from Draft! removed

Comment thread packages/occ/src/configured-harness.ts Resolved
@freeqaz

freeqaz commented Oct 3, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here (an AI agent reviewing on Free's behalf).

This is a lighter pass, since the PR is a draft and the description says the dedicated k3d case still fails. Checked head 7d7a9a4 against main 10a9756. The merge with main is clean, including today's changes to runtime-entrypoints.ts, plugin-runtime.ts and credential-gateway/openshell.ts.

Verdict: needs changes.

  1. Namespaced model IDs, the headline case, are still truncated on the dedicated OpenClaw path. apps/controller/src/drivers/compute/kubernetes/index.ts:1384 still uses reference.split("/", 2), so openai/vendor/model resolves to catalog id vendor and is rejected as missing model metadata. configured-harness.ts lines 43, 63 and 173 also still use split("/", 2) for the provider. This is the same issue as the open thread on configured-harness.ts:81. Suggested fix: build on fix(occ): accept nested-slash model IDs #875, which adds a shared splitModelRef and converts every split site (including kubernetes/index.ts), and drop this PR's local slice(indexOf("/")) edits in configured-harness.ts. The two PRs conflict textually in that file today, so fix(occ): accept nested-slash model IDs #875 should land first.
  2. CI Required is red on docs:check-length. Four changed pages are over the 2500-word hard limit on the merged tree: docs/flows/harness-execution-topology.md (2713), docs/reference/harness-execution.md (2602), docs/reference/drivers/kubernetes-compute.md (2606) and docs/testing/kubernetes.md (2597). The docs dependency problem in the description is fixed by pnpm run docs:install, after which node scripts/docs-site/word-count.mjs runs locally.
  3. Maintenance surface: deploy/runtime/openclaw-codex-native-model-ids.patch (127 lines) patches the pinned runtime and has to be carried through every runtime bump. It would help to say in the description whether this is meant to go upstream, and whether the patch is still needed once OCC preserves the full ID.
  4. Proof: the description reports the dedicated k3d case still failing (two Codex rollouts with the session marker where the test expects one) and the OpenShell path unverified. Both need to pass before this can leave draft.

It also overlaps #925, #906, #851 and #875 in apps/controller/src/drivers/compute/kubernetes/index.ts; expect to merge main again as those land.

@freeqaz

freeqaz commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here (an AI agent reviewing on Free's behalf).

Re-review of head 9958ef0 against main 2470aff (merge-base 4cda651). The branch was rebuilt as one commit on main; git merge-tree against current main is clean (39 behind, no conflicts).

Resolved since the last review

  1. Namespaced model IDs: fixed. fix(occ): accept nested-slash model IDs #875 landed splitModelRef, no split("/", 2) site remains in apps/controller or packages/occ, and the new apps/controller/src/drivers/compute/codex-model-configuration.ts uses it throughout. The conformance case covers vendor/organization/model, a native ID that itself starts with codex/, and a provider/* policy key.
  2. Runtime patch: gone. deploy/runtime/openclaw-codex-native-model-ids.patch, the Dockerfile and scripts/build-runtime-assets.mjs changes are no longer in the diff.
  3. Docs length: three of the four pages are now under the limit (kubernetes-compute.md 2438, harness-execution.md 2451, testing/kubernetes.md 2496).
  4. Proof: the description now reports the dedicated k3d routing case passing with a namespaced model (author-reported, not independently rerun). The OpenShell positive case is still unverified, which the description says.

Still blocking

  1. CI Required is red on docs:check-length. Two pages are over the 2500-word hard limit on this head: docs/flows/harness-execution-topology.md at 2512 (2301 on main) and docs/flows/openshell-sandbox-provisioning.md at 2611 (2491 on main). Trimming 12 and 111 words respectively clears it. Note that lane Checks and Conformance 1 stops at the docs step, so typecheck, cli:check and the lane-1 suites never ran in CI on this head. I ran pnpm typecheck and the affected suites locally (kubernetes-compute, credential-source-occ, configuration-occ, openshell-gateway-wire, plugin-compute, sandbox-driver-startup, k3d-launcher): typecheck clean, 484 tests pass, 0 fail.

  2. An invalid base_url creates a credential source that can never be deleted. The create path persists the record as registering after checking only the config field names (packages/occ/src/index.ts:3584-3597, credentialSourceFieldsMatch validates keys, not values). registerSource then throws ScopeViolationError from sourceBaseUrl at apps/controller/src/drivers/credential-gateway/openshell.ts:246, before any gateway call. The create path's recovery, abandonCredentialRegistration, calls removeSource, which calls profileId and therefore sourceBaseUrl again at openshell.ts:355 (and at :343 when a provider exists), so removal throws too, removed is false, and the record is marked deleting instead of deleted (index.ts:3774-3777). Every later DELETE repeats the same throw at index.ts:3888, so the record is stuck for good. A typo such as http:// or a missing /v1 is enough to trigger it, and the caller sees a 404 (ScopeViolationError maps to NOT_FOUND in apps/controller/src/http/errors.ts:617), which hides the cause. status at openshell.ts:329 and attachForRevision at :380-381 throw the same way for such a record. Suggested fix: validate the value before the record is persisted (a value validator on the catalog config spec, or a driver-level validation hook called next to credentialSourceFieldsMatch), and make removeSource and status tolerate an invalid stored endpoint (no profile could exist for it, so treat it as absent) so a stuck record can still be removed. A conformance case for a rejected base_url that confirms the record is gone afterwards would pin this.

Security review (not blocking)

The credential path holds up. On the OpenShell path the Harness still gets only the openshell:resolve:env: placeholder; the profile binds the real key to the normalized host, port and path/**, and the proxy substitutes it only there. On the Secret-backed path nothing moves: the key stays in the Codex Pod as before, and the endpoint is the Installation-level runtime.codexOpenaiBaseUrl, which only applies to harnessAuth.method === "api_key" (kubernetes/index.ts:9391-9397), so a credential-source binding (method credential_source) can never be redirected to the Installation endpoint and a tenant cannot redirect a Secret-backed key at all. attachForRevision fails closed for dedicated OpenClaw with a custom endpoint (openshell.ts:382-388). The TOML and the probe's -c overrides JSON-escape the URL and use a literal provider ID, so there is no injection surface. The Gateway's providers.codex.baseUrl stays at the fail-closed loopback.

Follow-ups worth a look, none blocking:

  • Egress scope. sourceBaseUrl (openshell.ts:161-184) accepts any HTTPS host, including RFC1918 and link-local IP literals and .svc / .cluster.local names. A tenant with credential-source create rights therefore opens the Sandbox profile's egress toward an internal address and has the proxy attach their own key there. The Secret-backed Pod is already protected by the model-egress NetworkPolicy exceptions at kubernetes/index.ts:10119-10137; the OpenShell profile has no equivalent. Mirroring that denylist in sourceBaseUrl, or stating it as an accepted limit while the OpenShell custom-endpoint path is unverified, would close the gap.
  • Test gap. The 154-line change to credential-gateway/openshell.ts has no unit coverage; tests/conformance/openshell-gateway-wire.test.mjs still only exercises the default oce-openai profile. Cases to add: custom base_url yields oce-openai-<12 hex> with host, port and /api/v1/**; ownedBy per profile; removing a custom-endpoint source leaves the default profile alone; attachForRevision rejects dedicated OpenClaw with a custom endpoint; and the invalid-URL rejection above.
  • Compute passes the raw config.base_url (kubernetes/index.ts:3710, :4390, :4494) rather than the normalized value, so a trailing slash reaches config.toml and the probe. Harmless today, but the same URL rule now lives twice (openshell.ts:161 and kubernetes/index.ts:1987-2006); one shared validator that also normalizes would keep them from drifting.
  • codex-model-configuration.ts:84-87: when the admitted provider is openai, an existing models.providers.codex entry is overwritten by the openai one. Fine if admission forbids both, otherwise worth a guard.
  • The Service-selector expectation change in tests/integration/harness-topology-k3d-real.test.mjs matches the openclaw.dev/network-profile label main already puts on the Service (kubernetes/index.ts:11472). Correct, just unrelated to this PR's title.

Verdict: needs changes. Trim the two docs pages and fix the stuck-record bug; the rest is follow-up. After those two, this is ready to land from my side.

@freeqaz

freeqaz commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here (an AI agent reviewing on Free's behalf).

Re-review of head 4a95cca (fix(credentials): validate OpenShell endpoints before persistence). I merged it locally with current main eb9803c (166 behind, git merge-tree clean, only three test files needed a three-way merge) and reviewed and tested that merged tree. Main has 4 commits since the CI run's base 5a2dd43 and none touch the files this PR changes.

Verdict: ready to land from my side. Both blockers from the last review are fixed, and the test gap is closed.

Resolved

  1. Stuck record on an invalid base_url: fixed. packages/occ/src/index.ts:3587 now calls validateSourceConfig after the field-name checks and before readCredentialSourceSecrets and createCredentialSource (:3589), so a bad value is rejected before any Secret read or row. The driver's validateSourceConfig (credential-gateway/openshell.ts:226) throws CredentialSourceConfigError, mapped at http/errors.ts:551 to 400 INVALID_REQUEST with details [{ path: "/config/base_url", code: "INVALID_VALUE" }], so callers see the cause instead of the old 404. config is immutable on update (updateCredentialSource passes source.config), so the create path is the only way a value gets stored. For rows that already exist with a bad value, sourceStatus (:316) now reports failed instead of throwing, and removeSource (:338-353) returns cleanly when no remote provider exists, so DELETE completes and the row is gone. The one path that still refuses is a remote provider that exists under the source's name while the stored endpoint is invalid (:349-351): ownership cannot be proven without the profile id, so the row stays deleting rather than deleting someone else's provider. That is the right call; an operator removes the stray provider and retries. attachForRevision (:374) still derives the profile id strictly, which is fine because bindings only accept ready sources and a ready source has passed validation.

  2. Docs length: fixed. On the merged tree node scripts/docs-site/word-count.mjs passes; harness-execution-topology.md 2456, openshell-sandbox-provisioning.md 2484, kubernetes-compute.md 2438, harness-execution.md 2451, testing/kubernetes.md 2496. build.mjs --check (241 pages, 3735 links) and check-specs.mjs also pass.

  3. Test coverage: closed. tests/integration/credential-source-api.test.mjs runs the real Fastify app, IAM, OCC and the OpenShell Driver against an in-memory gateway client and covers: six invalid URL shapes rejected with 400 and no row, provider, profile or gateway call; a seeded invalid deleting row deleted through the API without touching the default profile; the collision case above left deleting; custom base_url producing oce-openai-<12 hex> with host, port 8443 and /api/v1/** after normalising https://MODELS.example.test:8443/api/v1/; per-profile ownership (a provider on the wrong profile flips status to failed and makes register/remove reject); attachForRevision rejecting dedicated OpenClaw and accepting Codex; and the shared profile surviving until its last source goes. It is in checks-baseline-1, which impact.mjs always selects, so it runs on every CI pass.

  4. Shared validator: apps/controller/src/drivers/openai-endpoint.ts replaces the two copies, and pluginRuntimeSnapshot (kubernetes/index.ts:9388) now normalises before the value reaches config.toml or the probe, which closes the raw-config.base_url note from last time.

Local verification on the merged tree

pnpm typecheck clean. node --test over credential-source-api, credential-source-occ, kubernetes-compute, openshell-gateway-wire, plugin-compute, configuration-occ, http-errors, kubernetes-runtime-credentials, sandbox-driver-startup, k3d-launcher: 535 pass, 0 fail, 0 skipped. I did not rerun the Postgres or k3d lanes; the CI run on this head covers them.

Security pass (not blocking)

The key still never reaches an unvalidated host. On the OpenShell path the Harness only holds the openshell:resolve:env: placeholder and the proxy substitutes the real key solely on the profile's host, port and path/**; a redirect to another host from the Harness carries the placeholder, not the key. On the Secret-backed path the endpoint stays the Installation-level runtime.codexOpenaiBaseUrl and only applies to harnessAuth.method === "api_key", so a credential-source binding cannot be redirected to it. Neither openshell.ts nor openai-endpoint.ts logs endpoints or credentials.

Optional follow-up

  • Egress scope (unchanged from last review): normalizeOpenAiBaseUrl accepts any HTTPS host, including RFC1918 and link-local IP literals and .svc / .cluster.local names, so a tenant with credential-source create rights can point the Sandbox profile's egress at an internal address. The Secret-backed Pod gets the model-egress NetworkPolicy exceptions at kubernetes/index.ts; the OpenShell profile has no equivalent. openai-endpoint.ts is now the single place to add that denylist, or to document it as an accepted limit. Not blocking.

@roboclaw-bot

Copy link
Copy Markdown
Contributor

Follow-up from @sallyom’s k3d/OpenRouter test: z-ai/glm-5.3-flash turns succeed, but each turn shows “Model metadata … not found. Defaulting to fallback metadata.”

This is emitted by stock Codex 0.158.0, not an API-key or routing failure. Codex lacks native metadata for this model and uses generic capability/context defaults.

Suggested follow-up: have OCE provision a Codex-native catalog via model_catalog_json, with accurate metadata for the exact wire model ID. OpenClaw catalog registration alone does not populate it. This remedy is source-verified, not yet runtime-tested; simply hiding the warning would leave the fallback assumptions unchanged.

derekwaynecarr pushed a commit to derekwaynecarr/openclaw-enterprise that referenced this pull request Oct 5, 2026
Marking each entry (and moving the longest entries to the front) made a
conflict with every open PR that adds a file to a Checks lane (openclaw#1370, openclaw#913).
The lane now lists its audited files in parallelFiles, which also sets their
start order (longest first, from main run 37308745808), and names serial-only
files with a reason in serialFiles. File entries are unchanged, so a file a
PR adds stays unlisted and runs alone. The audit rejects listed paths that are
not lane files, duplicates, and files listed as both.
@freeqaz

freeqaz commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here. Heads-up: #2298 just landed on main and moved withCredentialGateway (and the credential-source withdrawal tests) out of tests/integration/postgres-worker-agent-revision.test.mjs into tests/integration/postgres-worker-agent-revision-credential-sources.test.mjs. This PR's one-line change to that helper (validateSourceConfig() {}, on the credential gateway double) will now conflict when you sync with main. To resolve it, drop the hunk from the old file and add the same line to withCredentialGateway in the new file. Nothing else in this PR overlaps.

Preserve endpoint validation and native subagent routing alongside current credential lifecycle, ownership, workspace and readiness contracts.

Co-authored-by: sallyom <11166065+sallyom@users.noreply.github.com>
@sallyom

sallyom commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator Author

@freeqaz @stevenlee-oai I believe everything has been addressed here, should be ready for a merge ty!

# Conflicts:
#	apps/controller/src/drivers/credential-gateway/openshell.ts
#	docs/flows/credential-source-lifecycle.md
#	docs/reference/drivers/openshell-credential-gateway.md
@freeqaz-openai
freeqaz-openai merged commit 669cf7a into main Oct 13, 2026
46 checks passed
@freeqaz-openai
freeqaz-openai deleted the oce-oss-model-support branch October 13, 2026 22:17

This branch was previously deployed

1 inactive deployment
integration-qa-pr — a57cde8b Deployed Oct 13, 2026 by freeqaz-openai via QA advisory (compose) #717
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.

6 participants