feat(rkd): check the server API version before signing in #8

Merged
dozken merged 1 commit from feat/server-api-version into main 2026-09-23 18:11:37 +02:00
Owner

Summary

The RKD server now reports its API contract version on GET /api/health (rkd#1019, merged there as PR #1020): {"status":"ok","api_version":N}, with a bare OK from older servers counting as 0. This plugin needs App hosts, which no version-0 server has, so until now the sign-in died on a bare HTTP 404 and a signed-in channel retried its socket forever without saying why. The plugin now checks first and says what is wrong.

Closes #7

What it does

src/server-version.ts parses /api/health exactly like the RKD app does and compares it against MIN_SERVER_API_VERSION = 1.

  • Below the minimum: login stops before asking for a code, naming the server, both versions and the fix. The channel doesn't start its socket, and status shows the error.
  • Can't tell (unreachable, non-2xx, a body it doesn't recognise): it only warns and carries on, so a flaky network is never mistaken for an old server. This mirrors how checkClientVersion treats the Claude Code version.
  • status gains a server api: N (needs 1 or newer) line.

The pre-login checks move into loginPreflight() so they are testable. Plugin 0.4.0; README ("Tested with") and /rkd:configure mention the requirement.

Before / after

Real CLI, login prod. Prod still runs a pre-contract server:

BEFORE 0.3.0   login failed: RKD /api/app-hosts/device → HTTP 404:
AFTER  0.4.0   login failed: https://prod.rkd.nanoya.biz runs an RKD server with API version 0; this plugin needs 1 or newer. Update the server, or sign in to another one with /rkd:configure

Against a stub reporting api_version: 1, 0.4.0 goes straight on to the sign-in code (STUB-0001).

Channel mode (RKD_CHANNEL=1, fake token, throwaway state dir), status tool plus stderr, against a stub that answers a bare OK:

BEFORE 0.3.0   connected: no
               stderr: socket error: Unexpected server response: 404 | socket closed (1006), reconnecting | socket error: … (forever)
AFTER  0.4.0   server api: 0 (needs 1 or newer)
               connected: no
               error: http://127.0.0.1:18121 runs an RKD server with API version 0; this plugin needs 1 or newer. …
               (no socket attempts)

Against a stub reporting 1, 0.4.0 shows server api: 1 (needs 1 or newer) and starts the socket as before.

Test plan

  • pnpm test: 124 passed (19 new in server-version.test.ts: parser, check, loginPreflight)
  • pnpm typecheck, pnpm check:dist (committed bundle is current), scripts/smoke-handshake.mjs
  • Mutation-checked by hand, all 8 killed: dropping the OK→0 rule, <→<=, the negative-version guard, the non-2xx and unrecognised-body warnings, the unreachable short-circuit, the ok/problem split, and not passing fetch through
  • Before/after above, with the real bundles

Notes

The runtime gate in server.ts has no unit test because the module is the entry script. It is covered by the channel-mode run above. When the server later bumps API_VERSION for something this plugin uses, raise MIN_SERVER_API_VERSION in the same release.

https://claude.ai/code/session_01GK26pQScDqE52RKrrCTVso

## Summary The RKD server now reports its API contract version on `GET /api/health` (rkd#1019, merged there as PR #1020): `{"status":"ok","api_version":N}`, with a bare `OK` from older servers counting as 0. This plugin needs App hosts, which no version-0 server has, so until now the sign-in died on a bare `HTTP 404` and a signed-in channel retried its socket forever without saying why. The plugin now checks first and says what is wrong. Closes #7 ## What it does `src/server-version.ts` parses `/api/health` exactly like the RKD app does and compares it against `MIN_SERVER_API_VERSION = 1`. - **Below the minimum:** `login` stops before asking for a code, naming the server, both versions and the fix. The channel doesn't start its socket, and `status` shows the error. - **Can't tell** (unreachable, non-2xx, a body it doesn't recognise): it only warns and carries on, so a flaky network is never mistaken for an old server. This mirrors how `checkClientVersion` treats the Claude Code version. - `status` gains a `server api: N (needs 1 or newer)` line. The pre-login checks move into `loginPreflight()` so they are testable. Plugin 0.4.0; README ("Tested with") and `/rkd:configure` mention the requirement. ## Before / after Real CLI, `login prod`. Prod still runs a pre-contract server: ``` BEFORE 0.3.0 login failed: RKD /api/app-hosts/device → HTTP 404: AFTER 0.4.0 login failed: https://prod.rkd.nanoya.biz runs an RKD server with API version 0; this plugin needs 1 or newer. Update the server, or sign in to another one with /rkd:configure ``` Against a stub reporting `api_version: 1`, 0.4.0 goes straight on to the sign-in code (`STUB-0001`). Channel mode (`RKD_CHANNEL=1`, fake token, throwaway state dir), `status` tool plus stderr, against a stub that answers a bare `OK`: ``` BEFORE 0.3.0 connected: no stderr: socket error: Unexpected server response: 404 | socket closed (1006), reconnecting | socket error: … (forever) AFTER 0.4.0 server api: 0 (needs 1 or newer) connected: no error: http://127.0.0.1:18121 runs an RKD server with API version 0; this plugin needs 1 or newer. … (no socket attempts) ``` Against a stub reporting 1, 0.4.0 shows `server api: 1 (needs 1 or newer)` and starts the socket as before. ## Test plan - [x] `pnpm test`: 124 passed (19 new in `server-version.test.ts`: parser, check, `loginPreflight`) - [x] `pnpm typecheck`, `pnpm check:dist` (committed bundle is current), `scripts/smoke-handshake.mjs` - [x] Mutation-checked by hand, all 8 killed: dropping the `OK`→0 rule, `<`→`<=`, the negative-version guard, the non-2xx and unrecognised-body warnings, the unreachable short-circuit, the ok/problem split, and not passing `fetch` through - [x] Before/after above, with the real bundles ## Notes The runtime gate in `server.ts` has no unit test because the module is the entry script. It is covered by the channel-mode run above. When the server later bumps `API_VERSION` for something this plugin uses, raise `MIN_SERVER_API_VERSION` in the same release. https://claude.ai/code/session_01GK26pQScDqE52RKrrCTVso
dozken self-assigned this 2026-09-23 17:55:14 +02:00
feat(rkd): check the server's API version before signing in (#7)
All checks were successful
CI / rkd-plugin (pull_request) Successful in 30s
26915174c2
The RKD server now reports its API contract version on /api/health
({"status":"ok","api_version":N}; a server from before the contract
answers a bare OK = 0). This plugin needs App hosts, which no
version-0 server has, so against one the sign-in died on a bare
`HTTP 404` from /api/app-hosts/device and a signed-in channel retried
its socket forever without a reason.

server-version.ts parses /api/health the same way the RKD app does and
compares against MIN_SERVER_API_VERSION = 1. Below it:
- `login` stops before asking for a code, naming the server, both
  versions and the fix;
- the channel doesn't start its socket, and `status` shows the error.
`status` also shows `server api: N (needs 1 or newer)`. An unreachable
server, a non-2xx or an unrecognised body only warns, so a flaky
network is never mistaken for an old server.

The login checks move into loginPreflight() so they are testable; 19
new tests, every hand-applied mutation killed. Plugin 0.4.0; README
and /rkd:configure mention the requirement.

Claude-Session: https://claude.ai/code/session_01GK26pQScDqE52RKrrCTVso
dozken merged commit fee1014a6d into main 2026-09-23 18:11:37 +02:00
dozken deleted branch feat/server-api-version 2026-09-23 18:11:38 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rkd/claude-plugins!8
No description provided.