Skip to content

Commit 4b4ef38

Browse files
committed
fix(config): enforce chain.joinbase.ai as public registry default
Codify Compose install templates and docs so public registry/weights stay on https://chain.joinbase.ai, keep validator --master-url operator-explicit (no hard-coded public IP defaults), and guard the contract with unit assertions.
1 parent 0eb4171 commit 4b4ef38

7 files changed

Lines changed: 122 additions & 1 deletion

File tree

deploy/compose/config/master.compose.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ network:
2020
stake: 1000.0
2121

2222
master:
23+
# Public chain/registry control plane for the shipping public network.
2324
registry_url: https://chain.joinbase.ai
2425
proxy_host: 0.0.0.0
2526
proxy_port: 8081
@@ -32,6 +33,7 @@ master:
3233
orchestration_interval_seconds: 30
3334

3435
validator:
36+
# Public network default; do not substitute ad-hoc public IP hosts here.
3537
registry_url: https://chain.joinbase.ai
3638
registry_retry_seconds: 15
3739
weights_url: null

deploy/compose/install-master.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ network:
185185
stake: 1000.0
186186
187187
master:
188+
# Public chain/registry control plane (not an operator master IP inventory).
188189
registry_url: https://chain.joinbase.ai
189190
proxy_host: 0.0.0.0
190191
proxy_port: 8081
@@ -198,6 +199,7 @@ master:
198199
orchestration_interval_seconds: 30
199200
200201
validator:
202+
# Public network registry/weights default; Validators attach via --master-url.
201203
registry_url: https://chain.joinbase.ai
202204
registry_retry_seconds: 15
203205
weights_url: null

deploy/compose/install-validator.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ if [[ -z "${MASTER_URL}" ]]; then
114114
fi
115115

116116
# Reject empty or clearly invalid master URLs early (VAL-SDK-086).
117+
# master_url is the operator's master coordination root (their running master
118+
# API). It is never defaulted to a public IP inventory. Public chain/registry
119+
# docs and Settings defaults remain https://chain.joinbase.ai.
117120
case "${MASTER_URL}" in
118121
http://*|https://*) ;;
119122
*)

docs/compose.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,19 @@ Every deployable first-party reference is immutable: `repository@sha256:<64 hex>
5959

6060
Base and Prism do **not** launch evaluator containers. Prism runs in `PRISM_COMBINED_MODE=true` and verifies/ingests external results. External long-lived TEE runtimes are never lifecycle-managed by this Compose project.
6161

62+
## Public chain and master URL
63+
64+
- Public chain/registry control-plane URL: `https://chain.joinbase.ai`
65+
(master `registry_url` and validator `registry_url` / default weights resolution
66+
for the public network).
67+
- Validator coordination uses an **explicit** operator master URL
68+
(`install-validator.sh --master-url` / `validator.agent.master_url`). That is
69+
the operator's running master API (often loopback in disposable setups), not a
70+
hardcoded public IP host inventory.
71+
- Docker Compose installers must not invent alternate public master IP defaults.
72+
Historical Swarm advertise addresses under `deploy/swarm/` are unsupported for
73+
greenfield Compose installs.
74+
6275
## Validator project
6376

6477
Entrypoint: `deploy/compose/docker-compose.validator.yml`

docs/operations/validator.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,25 @@ On the Compose path the process is packaged as the `validator` service from
7777

7878
```yaml
7979
validator:
80+
# Public network defaults (Settings / examples); resolved_weights_url falls
81+
# back to registry_url when weights_url is null.
82+
registry_url: https://chain.joinbase.ai
83+
weights_url: null
8084
agent:
81-
master_url: https://chain.joinbase.ai
85+
# Operator master coordination root (install-validator --master-url).
86+
# This is *not* the public chain URL. Examples for a local master:
87+
master_url: http://127.0.0.1:3180
8288
capabilities: ["cpu"]
8389
version: "0.1.0"
8490
heartbeat_interval_seconds: 60
8591
poll_interval_seconds: 5.0
8692
```
8793
94+
Public registry and published weights documentation uses
95+
`https://chain.joinbase.ai` (for example `GET /v1/weights/latest` there).
96+
`install-validator.sh --master-url` must point at the operator master API that
97+
owns assignments; it never invents a hardcoded public IP as the master default.
98+
8899
There is no master LLM gateway route and no per-assignment `BASE_LLM_GATEWAY_URL`
89100
/ `BASE_GATEWAY_TOKEN` contract in the shipping target path.
90101

docs/validator/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ The default public weights endpoint is:
1515
https://chain.joinbase.ai/v1/weights/latest
1616
```
1717

18+
Settings defaults for `registry_url` / resolved weights on the public network also
19+
use `https://chain.joinbase.ai`. Installer `--master-url` is the **operator master
20+
coordination root** (required, never invented as a hard-coded public IP). Local
21+
examples often use `http://127.0.0.1:3180`; public operators point both registry
22+
and master at the public control plane when that is the live master.
23+
1824
## Compute Requirements
1925

2026
| Validator profile | Compute |

tests/unit/test_config_template_security.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import os
4+
import re
45
import stat
56
import subprocess
67
from pathlib import Path
@@ -58,9 +59,17 @@ def test_registry_url_defaults_and_examples_use_chain_endpoint() -> None:
5859
validator_example = yaml.safe_load(
5960
(root / "config" / "validator.example.yaml").read_text(encoding="utf-8")
6061
)
62+
master_compose = yaml.safe_load(
63+
(root / "deploy" / "compose" / "config" / "master.compose.yaml").read_text(
64+
encoding="utf-8"
65+
)
66+
)
6167

6268
assert master_example["master"]["registry_url"] == expected
69+
assert master_example["validator"]["registry_url"] == expected
6370
assert validator_example["validator"]["registry_url"] == expected
71+
assert master_compose["master"]["registry_url"] == expected
72+
assert master_compose["validator"]["registry_url"] == expected
6473
assert ValidatorSettings().weights_url is None
6574
assert ValidatorSettings().resolved_weights_url == expected
6675
assert (
@@ -79,19 +88,94 @@ def test_registry_url_defaults_and_examples_use_chain_endpoint() -> None:
7988
assert ValidatorSettings().weights_retries == 3
8089
assert ValidatorSettings().weights_freshness_seconds == 720
8190
assert validator_example["validator"]["weights_url"] is None
91+
assert master_compose["validator"]["weights_url"] is None
8292
assert validator_example["validator"]["weights_interval_seconds"] == 360
8393
assert validator_example["validator"]["weights_timeout_seconds"] == 15.0
8494
assert validator_example["validator"]["weights_retries"] == 3
8595
assert validator_example["validator"]["weights_freshness_seconds"] == 720
8696

8797

98+
def test_compose_shipping_defaults_pin_public_chain_joinbase_url() -> None:
99+
"""Compose install/templates must keep public registry on chain.joinbase.ai.
100+
101+
Operator ``--master-url`` stays an explicit coordination root and must not be
102+
invented as a hard-coded public IP default. Public registry/weights defaults
103+
remain ``https://chain.joinbase.ai``.
104+
"""
105+
root = Path(__file__).resolve().parents[2]
106+
expected = "https://chain.joinbase.ai"
107+
retired_public_hosts = (
108+
"86.38.238.235",
109+
"51.83.112.164",
110+
"88.216.198.199",
111+
)
112+
113+
install_master = (root / "deploy" / "compose" / "install-master.sh").read_text(
114+
encoding="utf-8"
115+
)
116+
install_validator = (
117+
root / "deploy" / "compose" / "install-validator.sh"
118+
).read_text(encoding="utf-8")
119+
master_compose = (
120+
root / "deploy" / "compose" / "config" / "master.compose.yaml"
121+
).read_text(encoding="utf-8")
122+
master_example = (root / "config" / "master.example.yaml").read_text(
123+
encoding="utf-8"
124+
)
125+
validator_example = (root / "config" / "validator.example.yaml").read_text(
126+
encoding="utf-8"
127+
)
128+
validator_docs = (root / "docs" / "validator" / "README.md").read_text(
129+
encoding="utf-8"
130+
)
131+
ops_validator_docs = (root / "docs" / "operations" / "validator.md").read_text(
132+
encoding="utf-8"
133+
)
134+
135+
for shipping in (
136+
install_master,
137+
master_compose,
138+
master_example,
139+
validator_example,
140+
):
141+
assert f"registry_url: {expected}" in shipping
142+
for host in retired_public_hosts:
143+
assert host not in shipping
144+
145+
# Master install renders both master + validator registry defaults to public chain.
146+
assert install_master.count(f"registry_url: {expected}") >= 2
147+
assert "weights_url: null" in install_master
148+
149+
# Validator install requires an explicit operator master URL and never invents
150+
# a hard-coded public IP master default. registry/weights may follow that
151+
# operator root for a private master, but public docs keep the chain host.
152+
assert "--master-url" in install_validator
153+
assert "VALIDATOR_MASTER_URL" in install_validator
154+
assert "validator install requires --master-url" in install_validator
155+
for host in retired_public_hosts:
156+
assert host not in install_validator
157+
# No default IP master for empty --master-url.
158+
assert (
159+
re.search(r'MASTER_URL="\$\{VALIDATOR_MASTER_URL:-[^"]+\}"', install_validator)
160+
is None
161+
)
162+
163+
assert expected in validator_docs
164+
assert f"{expected}/v1/weights/latest" in validator_docs
165+
assert expected in ops_validator_docs
166+
# master_url is the operator coordination root, not the public chain URL.
167+
assert "master_url: https://chain.joinbase.ai" not in ops_validator_docs
168+
169+
88170
def test_registry_facing_defaults_docs_and_examples_do_not_use_rpc_endpoint() -> None:
89171
root = Path(__file__).resolve().parents[2]
90172
registry_facing_files = [
91173
root / "src" / "base" / "config" / "settings.py",
92174
root / "config" / "master.example.yaml",
93175
root / "config" / "validator.example.yaml",
94176
root / "docs" / "validator" / "README.md",
177+
root / "deploy" / "compose" / "config" / "master.compose.yaml",
178+
root / "deploy" / "compose" / "install-master.sh",
95179
root / "deploy" / "swarm" / "master.yaml",
96180
]
97181

0 commit comments

Comments
 (0)