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
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
- Added a SQLite-backed operation event bus with CLI/API timeline readers and
in-process plugin subscriber hooks for extensions.

- Updated the Zeus mutation compatibility target to exact `0.5.0.dev0` at
upstream contract commit `f4a7af8a0ce802b3f9daeed0ee44958ef92abf1a`,
- Updated the Zeus mutation compatibility target to exact `0.5.0` at
upstream contract commit `ce9dfdfd7c9ea7dc367fd6c1cb15ab8be0d1ea95`,
while retaining v0.3.0 and v0.1.4 as legacy read-only contracts.
- Added authenticated Zeus `/ready` support, fail-closed `not_ready` mutation
preflights, schema-version validation, and an exact `0.5.0.dev0`
preflights, schema-version validation, and an exact `0.5.0`
`expected_version` gate.
- Added contract coverage for creating `kimi-k3-coding-bot` using only bot and
template metadata. Provider credentials and harness configuration remain in
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ Zeus. Operators run Zeus from the upstream project on each node, keep the Zeus
API loopback-only, and register those nodes in Olymp for inventory, planning,
approved lifecycle execution, audit trails, and evidence export.

The current mutation compatibility target is Zeus `0.5.0.dev0`, captured
exactly from upstream commit `f4a7af8a0ce802b3f9daeed0ee44958ef92abf1a`
in `docs/zeus-openapi-v0.5.0.dev0.json`. The retained v0.3.0 and v0.1.4
The current mutation compatibility target is Zeus `0.5.0`, captured
exactly from upstream commit `ce9dfdfd7c9ea7dc367fd6c1cb15ab8be0d1ea95`
in `docs/zeus-openapi-v0.5.0.json`. The retained v0.3.0 and v0.1.4
fixtures are legacy read-only contracts.

## Goals
Expand Down Expand Up @@ -70,8 +70,8 @@ fixtures are legacy read-only contracts.
- CLI: `olymp`
- Local API: `127.0.0.1:4321` by default
- State: SQLite for the local control plane, with append-only JSONL audit logs
- Integration: typed Zeus client checked against the Zeus `0.5.0.dev0`
mutation compatibility fixture in `docs/zeus-openapi-v0.5.0.dev0.json`,
- Integration: typed Zeus client checked against the Zeus `0.5.0`
mutation compatibility fixture in `docs/zeus-openapi-v0.5.0.json`,
with v0.3.0 and v0.1.4 kept as legacy read-only fixtures
- Deployment: systemd service, optional Caddy HTTPS front door for the Olymp
UI/API, Zeus nodes kept loopback-only behind local agents or SSH/mTLS tunnels
Expand Down Expand Up @@ -132,7 +132,7 @@ olymp node add local-zeus \
--name "Local Zeus" \
--base-url http://127.0.0.1:4311 \
--api-key-env ZEUS_API_KEY \
--expected-version 0.5.0.dev0
--expected-version 0.5.0

olymp node check local-zeus
olymp zeus ready local-zeus
Expand All @@ -144,7 +144,7 @@ Bot history is returned newest first. Pass the previous response's
`next_before` value to `--before` to fetch the next page.

Mutation plans require every target node to declare the exact reviewed
`0.5.0.dev0` `expected_version`. Health, inventory, and history remain
`0.5.0` `expected_version`. Health, inventory, and history remain
available for versionless or legacy nodes, but execution rechecks the current
registration and authenticated Zeus `/ready` response before any mutation.
Zeus `not_ready` responses fail closed without recording a mutation attempt.
Expand Down
14 changes: 7 additions & 7 deletions docs/OPERATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ requires the spawned instance's nonce.
Olymp operates registered [brainx/zeus](https://github.com/brainx/zeus)
nodes. Install and run Zeus from that upstream project on each host, keep its
API bound to loopback, then register the local or tunneled endpoint in Olymp.
The current mutation compatibility target is Zeus `0.5.0.dev0` at contract
commit `f4a7af8a0ce802b3f9daeed0ee44958ef92abf1a`. Zeus v0.3.0 and
The current mutation compatibility target is Zeus `0.5.0` at contract
commit `ce9dfdfd7c9ea7dc367fd6c1cb15ab8be0d1ea95`. Zeus v0.3.0 and
v0.1.4 remain available only as legacy read-only contracts.

Register a loopback Zeus node:
Expand All @@ -55,11 +55,11 @@ olymp node add local-zeus \
--name "Local Zeus" \
--base-url http://127.0.0.1:4311 \
--api-key-env ZEUS_API_KEY \
--expected-version 0.5.0.dev0
--expected-version 0.5.0
```

Every mutation plan target must declare `expected_version` in the supported
exact `0.5.0.dev0` contract. Planning and execution fail closed for missing,
exact `0.5.0` contract. Planning and execution fail closed for missing,
malformed, older, or unreviewed newer versions. Read-only health, inventory,
and history remain available for legacy/versionless nodes.

Expand Down Expand Up @@ -337,9 +337,9 @@ audit directories, audit files, and audit lock files under the state directory.
## Compatibility

Olymp's mutation compatibility target is
[brainx/zeus](https://github.com/brainx/zeus) `0.5.0.dev0` at commit
`f4a7af8a0ce802b3f9daeed0ee44958ef92abf1a`, captured as an exact, immutable
upstream copy in `docs/zeus-openapi-v0.5.0.dev0.json`. Repository and CI
[brainx/zeus](https://github.com/brainx/zeus) `0.5.0` at commit
`ce9dfdfd7c9ea7dc367fd6c1cb15ab8be0d1ea95`, captured as an exact, immutable
upstream copy in `docs/zeus-openapi-v0.5.0.json`. Repository and CI
contract checks use this vendored fixture and do not require network access.
The retained v0.3.0 and v0.1.4 contracts are legacy read-only fixtures; they
are not mutation compatibility targets.
12 changes: 6 additions & 6 deletions docs/PROJECT_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ node connectors rather than asking operators to expose Zeus directly.

Olymp should treat the upstream [brainx/zeus](https://github.com/brainx/zeus)
OpenAPI file as the integration contract and test against it on every release.
Zeus `0.5.0.dev0` at commit
`f4a7af8a0ce802b3f9daeed0ee44958ef92abf1a` is the current mutation
Zeus `0.5.0` at commit
`ce9dfdfd7c9ea7dc367fd6c1cb15ab8be0d1ea95` is the current mutation
compatibility target, vendored unchanged as
`docs/zeus-openapi-v0.5.0.dev0.json`. The v0.3.0 and v0.1.4 contracts remain
`docs/zeus-openapi-v0.5.0.json`. The v0.3.0 and v0.1.4 contracts remain
available only as legacy read-only fixtures. Mutation planning and execution
require each registered target to declare the exact reviewed `0.5.0.dev0`
require each registered target to declare the exact reviewed `0.5.0`
`expected_version`; read-only access remains available for legacy or
versionless nodes.

Expand Down Expand Up @@ -146,14 +146,14 @@ Status: initial foundation implemented.

### 1. Zeus Client MVP

- Implement a typed client for the Zeus OpenAPI `0.5.0.dev0` mutation surface
- Implement a typed client for the Zeus OpenAPI `0.5.0` mutation surface
while retaining v0.3.0 and v0.1.4 as legacy read-only compatibility.
- Cover auth success/failure, missing key behavior, timeouts, malformed JSON,
response-size limits, and diagnostic endpoint redaction.
- Add contract tests using a fake Zeus server.

Status: the client and fake-Zeus tests are implemented. The exact Zeus
`0.5.0.dev0` contract is the mutation compatibility target; the v0.3.0 and
`0.5.0` contract is the mutation compatibility target; the v0.3.0 and
v0.1.4 fixtures are retained as legacy read-only coverage. Timeout-specific
tests are implemented.

Expand Down
12 changes: 6 additions & 6 deletions docs/STAGING_RUNBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ API:
ZEUS_API_KEY=change-me OLYMP_API_KEY=change-me sh scripts/verify_real_zeus.sh
```

The verifier is pinned to the Zeus `0.5.0.dev0` contract commit
`f4a7af8a0ce802b3f9daeed0ee44958ef92abf1a`, registers the smoke node with
`expected_version` `0.5.0.dev0`, checks authenticated `/ready` plus inventory,
creates and executes an approved lifecycle plan only when a disposable
existing bot is explicitly configured, exports evidence, and removes its
temporary state by default.
The verifier is pinned to the Zeus `0.5.0` contract commit
`ce9dfdfd7c9ea7dc367fd6c1cb15ab8be0d1ea95`, registers the smoke node with
`expected_version` `0.5.0`, checks authenticated `/ready`, requires the
`kimi-k3-coding-bot` template, and reads inventory. It creates and executes an
approved lifecycle plan only when a disposable existing bot is explicitly
configured, exports evidence, and removes its temporary state by default.
It does not create or replace bots. Set
`OLYMP_REAL_ZEUS_KEEP_STATE=1` to preserve the verifier database, audit log, and
evidence bundle for review.
Expand Down
2 changes: 1 addition & 1 deletion docs/THREAT_MODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ That makes Olymp security-sensitive even when the first release is local-only.
- Require dry-run output, policy validation, and explicit approval before
mutating fleet actions.
- Require every mutation target to declare the exact reviewed Zeus
`0.5.0.dev0` `expected_version`, then recheck the current registration and
`0.5.0` `expected_version`, then recheck the current registration and
authenticated `/ready` response before Zeus mutation I/O. Treat
`not_ready` as a fail-closed preflight result.
- Allow normal `bot.create`, keep `bot.replace` and `bot.replace_stop`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "Zeus Local API",
"version": "0.5.0.dev0",
"version": "0.5.0",
"description": "Local JSON API for managing Hermes bot profiles and gateway lifecycle."
},
"servers": [
Expand Down
2 changes: 1 addition & 1 deletion olymp/plans.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from olymp.store import node_fingerprint

LIFECYCLE_ACTIONS = {"start", "stop", "restart", "reconcile"}
SUPPORTED_ZEUS_MUTATION_VERSION = "0.5.0.dev0"
SUPPORTED_ZEUS_MUTATION_VERSION = "0.5.0"
# Zeus readiness waits are deliberately bounded so approved lifecycle plans have
# one predictable execution and transport budget.
LIFECYCLE_WAIT_TIMEOUT_SECONDS = 30
Expand Down
2 changes: 1 addition & 1 deletion scripts/repo_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ for json_file in \
docs/openapi.json \
docs/zeus-openapi-v0.1.4.json \
docs/zeus-openapi-v0.3.0.json \
docs/zeus-openapi-v0.5.0.dev0.json; do
docs/zeus-openapi-v0.5.0.json; do
"$PYTHON" -m json.tool "$json_file" >/dev/null
done
"$PYTHON" -m compileall -q olymp tests
Expand Down
22 changes: 18 additions & 4 deletions scripts/verify_real_zeus.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ esac

state_created=0
started_zeus=0
install_dir="${OLYMP_REAL_ZEUS_DIR:-.tmp/zeus-v0.5.0.dev0}"
zeus_contract_commit="f4a7af8a0ce802b3f9daeed0ee44958ef92abf1a"
install_dir="${OLYMP_REAL_ZEUS_DIR:-.tmp/zeus-v0.5.0}"
zeus_contract_commit="ce9dfdfd7c9ea7dc367fd6c1cb15ab8be0d1ea95"
zeus_host="${ZEUS_HOST:-127.0.0.1}"
zeus_port="${ZEUS_PORT:-4311}"
zeus_url="${ZEUS_BASE_URL:-http://$zeus_host:$zeus_port}"
Expand Down Expand Up @@ -112,7 +112,7 @@ if [ "$checkout" = "1" ]; then
git -C "$install_dir" checkout --detach "$zeus_contract_commit"
fi
validate_zeus_checkout
echo "Zeus 0.5.0.dev0 contract checkout is available at $install_dir"
echo "Zeus 0.5.0 contract checkout is available at $install_dir"
fi

if [ "$start_zeus" = "1" ] && [ "$checkout" = "0" ]; then
Expand Down Expand Up @@ -162,10 +162,24 @@ fi
--name "Real Zeus Smoke" \
--base-url "$zeus_url" \
--api-key-env ZEUS_API_KEY \
--expected-version 0.5.0.dev0 >/dev/null
--expected-version 0.5.0 >/dev/null

"$PYTHON" -m olymp.cli node check "$node_id" >/dev/null
"$PYTHON" -m olymp.cli zeus ready "$node_id" >/dev/null
"$PYTHON" -m olymp.cli zeus templates "$node_id" |
"$PYTHON" -c '
import json
import sys

templates = json.load(sys.stdin)
template_ids = {
item.get("id")
for item in templates
if isinstance(item, dict) and isinstance(item.get("id"), str)
}
if "kimi-k3-coding-bot" not in template_ids:
raise SystemExit("Zeus templates are missing kimi-k3-coding-bot")
'
"$PYTHON" -m olymp.cli zeus inventory "$node_id" >/dev/null

if [ -n "$bot_id" ]; then
Expand Down
8 changes: 4 additions & 4 deletions tests/test_api_security.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def test_cli_redacts_expected_exception_message(self) -> None:
node_id="local",
display_name="Local Zeus",
base_url="http://127.0.0.1:4311",
expected_version="0.5.0.dev0",
expected_version="0.5.0",
)
)
stdout = StringIO()
Expand Down Expand Up @@ -114,7 +114,7 @@ def test_lifecycle_rejects_non_string_text_without_saving_plan(self) -> None:
node_id="123",
display_name="Local Zeus",
base_url="http://127.0.0.1:4311",
expected_version="0.5.0.dev0",
expected_version="0.5.0",
)
)
store = PlanRunStore(path)
Expand Down Expand Up @@ -157,7 +157,7 @@ def test_reconcile_rejects_non_string_text_without_saving_plan(self) -> None:
node_id="123",
display_name="Local Zeus",
base_url="http://127.0.0.1:4311",
expected_version="0.5.0.dev0",
expected_version="0.5.0",
)
)
store = PlanRunStore(path)
Expand Down Expand Up @@ -210,7 +210,7 @@ def bot_status(self, bot_id: str) -> dict[str, str]:
node_id="local",
display_name="Local Zeus",
base_url="http://127.0.0.1:4311",
expected_version="0.5.0.dev0",
expected_version="0.5.0",
)
)
plan = lifecycle_plan(
Expand Down
22 changes: 11 additions & 11 deletions tests/test_bot_creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_single_plan_rechecks_current_version_before_client_construction(self) -
with tempfile.TemporaryDirectory() as temp:
db_path = Path(temp) / "olymp.db"
registry = NodeRegistry(db_path)
node = registry.add(_node(expected_version="0.5.0.dev0"))
node = registry.add(_node(expected_version="0.5.0"))
plan = lifecycle_plan(
node,
bot_id="coder",
Expand All @@ -56,15 +56,15 @@ def test_single_plan_rechecks_current_version_before_client_construction(self) -
self.assertIsNotNone(run)
assert run is not None
self.assertEqual(run["error"]["code"], "incompatible_zeus_version")
self.assertIn("0.5.0.dev0", run["error"]["message"])
self.assertIn("0.5.0", run["error"]["message"])
self.assertEqual(client_requests, [])
self.assertEqual(run["attempts"], [])

def test_rollout_rechecks_each_current_version_before_zeus_io(self) -> None:
with tempfile.TemporaryDirectory() as temp:
db_path = Path(temp) / "olymp.db"
registry = NodeRegistry(db_path)
node = registry.add(_node(expected_version="0.5.0.dev0", tags=("staging",)))
node = registry.add(_node(expected_version="0.5.0", tags=("staging",)))
plan = rollout_lifecycle_plan(
(node,),
selector_tags=("staging",),
Expand Down Expand Up @@ -106,7 +106,7 @@ def test_rollout_validates_all_current_versions_before_any_client_construction(
node_id=f"staging-{suffix}",
display_name=f"Staging {suffix.upper()}",
base_url=f"http://127.0.0.1:{port}",
expected_version="0.5.0.dev0",
expected_version="0.5.0",
tags=("staging",),
)
)
Expand Down Expand Up @@ -208,7 +208,7 @@ def test_create_actions_execute_once_with_exact_body_flags_and_durable_metadata(
with self.subTest(action=action), tempfile.TemporaryDirectory() as temp:
db_path = Path(temp) / "olymp.db"
registry = NodeRegistry(db_path)
node = registry.add(_node(expected_version="0.5.0.dev0"))
node = registry.add(_node(expected_version="0.5.0"))
plan = create_bot_plan(
node,
bot_id="coder",
Expand Down Expand Up @@ -273,7 +273,7 @@ def test_kimi_k3_template_creation_keeps_provider_credentials_in_zeus(self) -> N
with tempfile.TemporaryDirectory() as temp:
db_path = Path(temp) / "olymp.db"
registry = NodeRegistry(db_path)
node = registry.add(_node(expected_version="0.5.0.dev0"))
node = registry.add(_node(expected_version="0.5.0"))
plan = create_bot_plan(
node,
bot_id="kimi-coder",
Expand Down Expand Up @@ -322,7 +322,7 @@ def test_not_ready_preflight_blocks_mutation_without_attempt(self) -> None:
with tempfile.TemporaryDirectory() as temp:
db_path = Path(temp) / "olymp.db"
registry = NodeRegistry(db_path)
node = registry.add(_node(expected_version="0.5.0.dev0"))
node = registry.add(_node(expected_version="0.5.0"))
plan = create_bot_plan(
node,
bot_id="coder",
Expand Down Expand Up @@ -384,7 +384,7 @@ def set_body(plan: dict[str, Any], body: dict[str, Any]) -> None:
with self.subTest(case=name), tempfile.TemporaryDirectory() as temp:
db_path = Path(temp) / "olymp.db"
registry = NodeRegistry(db_path)
node = registry.add(_node(expected_version="0.5.0.dev0"))
node = registry.add(_node(expected_version="0.5.0"))
plan = create_bot_plan(
node,
bot_id="coder",
Expand Down Expand Up @@ -445,7 +445,7 @@ def test_create_postcheck_fails_closed_and_preserves_mutation_evidence(self) ->
with self.subTest(case=name), tempfile.TemporaryDirectory() as temp:
db_path = Path(temp) / "olymp.db"
registry = NodeRegistry(db_path)
node = registry.add(_node(expected_version="0.5.0.dev0"))
node = registry.add(_node(expected_version="0.5.0"))
plan = create_bot_plan(
node,
bot_id="coder",
Expand Down Expand Up @@ -483,7 +483,7 @@ def test_indeterminate_create_is_recorded_once_and_never_automatically_repeated(
with tempfile.TemporaryDirectory() as temp:
db_path = Path(temp) / "olymp.db"
registry = NodeRegistry(db_path)
node = registry.add(_node(expected_version="0.5.0.dev0"))
node = registry.add(_node(expected_version="0.5.0"))
plan = create_bot_plan(
node,
bot_id="coder",
Expand Down Expand Up @@ -852,7 +852,7 @@ def _add_cli_node() -> int:
"--base-url",
"http://127.0.0.1:4311",
"--expected-version",
"0.5.0.dev0",
"0.5.0",
]
)

Expand Down
Loading
Loading