diff --git a/CHANGELOG.md b/CHANGELOG.md index 30f889d4..f3520253 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,11 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Packages without a separate changelog are covered by the cross-package notes below. -## [Unreleased] +## [Unreleased - Patch] + +### Changed + +- The self-host container now installs `@relaycast/engine` 8.0.0, matching the hosted deployment, and its runbook documents agent-card discovery as working on the standard well-known path rather than as a known defect. ## [8.0.0] - 2026-08-10 diff --git a/Dockerfile b/Dockerfile index 63eb0abf..8261a5f2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1.7 -ARG RELAYCAST_ENGINE_VERSION=7.0.0 +ARG RELAYCAST_ENGINE_VERSION=8.0.0 # Node 22.23.2, pinned to the multi-platform bookworm-slim index so the same # Dockerfile resolves native linux/amd64 and linux/arm64 images. @@ -16,7 +16,7 @@ RUN apt-get update \ WORKDIR /opt/relaycast COPY docker/package.json docker/package-lock.json ./ -# The lockfile pins @relaycast/engine to 7.0.0 and the source-build setting +# The lockfile pins @relaycast/engine to 8.0.0 and the source-build setting # exercises the C/C++ toolchain for better-sqlite3 on every target architecture. ENV npm_config_build_from_source=true RUN test "$(node -p "require('./package.json').dependencies['@relaycast/engine']")" = "$RELAYCAST_ENGINE_VERSION" \ diff --git a/RUNBOOK.md b/RUNBOOK.md index e1091b18..529e9bbe 100644 --- a/RUNBOOK.md +++ b/RUNBOOK.md @@ -6,7 +6,7 @@ access and does not operate this deployment. ## Operating boundary -The image contains `@relaycast/engine` **7.0.0** on Node 22.23.2 and stores all +The image contains `@relaycast/engine` **8.0.0** on Node 22.23.2 and stores all state locally in SQLite plus a files directory. It requires an explicit HTTPS public origin and exits before starting the engine if `--base-url` is missing, plaintext, single-label, an IP literal, loopback, or in the special-use `.local` @@ -59,7 +59,7 @@ docker compose ps curl --fail --silent --show-error http://127.0.0.1:8787/health ``` -The version command must print `7.0.0`, and Compose should eventually report +The version command must print `8.0.0`, and Compose should eventually report `healthy`. The health response must contain `"ok":true`; its `version` field is the gateway/application version, not reliable evidence of the installed engine package version. @@ -81,25 +81,36 @@ Move it into Ratify's secret manager, then securely remove the bootstrap file. Do not repeat this command: workspace names are not unique, so a repeat creates another workspace and key. -Engine 7.0.0 has a known agent-card discovery defect: the bare standard path -`GET /.well-known/agent-card.json` interprets the leftmost hostname label as the -workspace name. At `relay.ratifyprotocol.com` it therefore looks for `relay`, -not the meaningful workspace name `ratify-protocol`. Host inference also -shadows the documented `/:workspace/.well-known/agent-card.json` route on this -three-label hostname. The only working unauthenticated interim form is: +Agent-card discovery works on the standard path from engine 8.0.0. A +single-tenant deployment — one workspace, which is what this runbook sets up — +answers the bare well-known URL directly, so a counterparty needs no +Relaycast-specific query parameter: ```text +https://relay.ratifyprotocol.com/.well-known/agent-card.json +``` + +The explicit forms also resolve, and an explicit selector now takes precedence +over host-label inference: + +```text +https://relay.ratifyprotocol.com/ratify-protocol/.well-known/agent-card.json https://relay.ratifyprotocol.com/.well-known/agent-card.json?workspace=ratify-protocol ``` -A mismatch returns `workspace_not_found` even while authenticated -`POST /a2a/rpc` works. The query form is documented only as an interim operator -check. A standards-following counterparty will try the bare well-known path, so -do not treat this deployment as federation-ready until the single-tenant -sole-workspace resolver fix is released, this image is pinned to that exact -engine version, and `cast.agentrelay.com` is confirmed on the same version. +Two behaviours worth knowing, because both are deliberate. A deployment holding +more than one workspace does **not** fall back to guessing: it returns +`workspace_not_found` unless a selector identifies one. And a selector that +names a workspace which does not exist also returns `workspace_not_found` +rather than resolving to some other workspace — a typo fails loudly instead of +crossing a tenant boundary. + +Earlier engines interpreted the leftmost hostname label as the workspace name, +so `relay.ratifyprotocol.com` looked for a workspace called `relay` and the bare +path returned `workspace_not_found`. If you see that on the bare path, check the +image is on 8.0.0 or later before looking anywhere else. -In engine 7.0.0, `POST /v1/workspaces` is intentionally unauthenticated for +In engine 8.0.0, `POST /v1/workspaces` is intentionally unauthenticated for initial bootstrap. The tunnel rule below blocks that exact path before the service becomes public; omitting the rule would allow arbitrary public workspace creation and unbounded local state growth. diff --git a/docker/package-lock.json b/docker/package-lock.json index 4eb1dda0..67ee2db9 100644 --- a/docker/package-lock.json +++ b/docker/package-lock.json @@ -1,14 +1,14 @@ { "name": "relaycast-self-host-image", - "version": "7.0.0", + "version": "8.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "relaycast-self-host-image", - "version": "7.0.0", + "version": "8.0.0", "dependencies": { - "@relaycast/engine": "7.0.0" + "@relaycast/engine": "8.0.0" } }, "node_modules/@hono/node-server": { @@ -24,21 +24,21 @@ } }, "node_modules/@relaycast/a2a": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@relaycast/a2a/-/a2a-7.0.0.tgz", - "integrity": "sha512-Qq1PurJ46sn3GmJryOKXkoo6u8PlyXIpElbN0JTnxKobczRk2gNlZwQg4fAQ8RAWg9cMoYpomgRLSL18Qo147Q==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@relaycast/a2a/-/a2a-8.0.0.tgz", + "integrity": "sha512-yx+kwyRdmrMS/VhFt92BcIhRqc2FGSq1TVhaaM7+keE2ZbqkjEDRkfuIztvOp+P66PZGxLElBDJ1J/QilLsYCA==", "dependencies": { "zod": "^4.3.6" } }, "node_modules/@relaycast/engine": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@relaycast/engine/-/engine-7.0.0.tgz", - "integrity": "sha512-6MkKH5cw6GSCywvgrBpJ/JQ9xIeDmhYY4cK0YWhROrquvHeHh6+WCfXA+ac2BhZHps7Kjj2aLpsguKCK53R/sA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@relaycast/engine/-/engine-8.0.0.tgz", + "integrity": "sha512-7tIkIkD5t2F0nBQ9pTmW2wwPWEaiKJC6Cw1xBef2ai+6rkRtdxhCrcXlxDhxPpu6Ofn/OVEK0ChkefNxF6PFQA==", "dependencies": { "@hono/node-server": "^1.13.7", - "@relaycast/a2a": "7.0.0", - "@relaycast/types": "7.0.0", + "@relaycast/a2a": "8.0.0", + "@relaycast/types": "8.0.0", "better-sqlite3": "^11.10.0", "drizzle-orm": "^0.45.1", "hono": "^4.11.9", @@ -50,9 +50,9 @@ } }, "node_modules/@relaycast/types": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@relaycast/types/-/types-7.0.0.tgz", - "integrity": "sha512-fFfBNRoTiC0L2I6+7d8XCHNpYjo/9s1yQAtskU+vKA+HyP2Xfc7kFoHCT8UKDFWt0phswxZhIwKCVNqUEtTXQw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@relaycast/types/-/types-8.0.0.tgz", + "integrity": "sha512-GMBA8doHg6nyhtNJP6s8iX1H/KMN+EcQhWeiiIUoVPNULejB/NrFNre4AyaXsA0JqY2C+2U5AG2K6azUZyvt3Q==", "dependencies": { "zod": "^4.3.6" } diff --git a/docker/package.json b/docker/package.json index ab6a973f..68ba1212 100644 --- a/docker/package.json +++ b/docker/package.json @@ -1,8 +1,8 @@ { "name": "relaycast-self-host-image", "private": true, - "version": "7.0.0", + "version": "8.0.0", "dependencies": { - "@relaycast/engine": "7.0.0" + "@relaycast/engine": "8.0.0" } }