From f6452e0e933eea38e66e31115da886a2275976ae Mon Sep 17 00:00:00 2001 From: iceteaSA <171169159+iceteaSA@users.noreply.github.com> Date: Tue, 8 Sep 2026 23:02:24 +0200 Subject: [PATCH 1/3] client: name the three host facts that make a consumer's tests pass locally Each was found by a consumer shipping green and failing elsewhere: a connection file the daemon leaves at the default path, a suite defaulting into the operator's live config, and a bare `bun` run auto-installing the dependency whose absence the test exists to catch. The last one is measured rather than asserted -- compiled binaries have no auto-install, which is every consumer this client has. --- packages/client/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/client/README.md b/packages/client/README.md index 3ad6b97..fda25e8 100644 --- a/packages/client/README.md +++ b/packages/client/README.md @@ -28,3 +28,26 @@ The client sends `consumerIdentity: null` for every managed request so inherited are exported for tenant plugins consuming the OpenCode handle manifest. The shared `HANDLE_FILE_CONTRACT` is pinned to `maxBytes: 262144`, `mode: 0o600`, `labelRe: /^[a-z0-9][a-z0-9._-]{0,63}$/`, and `handleRe: /^ckh_[A-Za-z0-9_-]{43}$/`. + +## Testing a consumer of this client + +Three things on a developer box silently satisfy what a consumer's test is trying to +prove. Each was found by a consumer shipping green and failing elsewhere. + +• **A connection file at the default path is a host fact, not a fixture.** If the vault + runs on the machine, `detectClaustrumConnection` finds it whether or not a test set it + up, so a suite can pass on the daemon's real socket and fail anywhere without one. + Force it absent (`CLAUSTRUM_SUBC_CONNECTION=/nonexistent/x.json`, and clear + `XDG_RUNTIME_DIR`) and prove the suite still passes. +• **Tests default into the operator's live config.** A suite that resolves + `~/.config/opencode` without an override writes lock files and manifests beside real + credentials — passing locally, and mutating state no CI runner has. +• **A bare `bun` run is not an oracle for module resolution.** The Bun CLI auto-installs + a public dependency it cannot resolve, needing only a `package.json` in scope; a + compiled binary does not. Measured on the same module, same directory, no + `node_modules`: compiled loader gives `ERR_MODULE_NOT_FOUND`, `bun -e` resolves. Since + consumers of a credential client are daemons and plugins, exercise resolution under a + compiled loader (`bun build --compile`) or the real host. + +The shape is the same in all three: the producing machine supplies the thing under test. +A passing check on it is evidence only when the ambient supply is removed first. From 524487e760a6dbdc6c7da484b77533eb3f50be07 Mon Sep 17 00:00:00 2001 From: iceteaSA <171169159+iceteaSA@users.noreply.github.com> Date: Fri, 11 Sep 2026 17:26:11 +0200 Subject: [PATCH 2/3] client: name both compiled-resolution shapes, and pin the readings to a bun version The package.json qualifier came out of a pair whose cache state I had not held fixed, and it does not reproduce: bare bun resolves an uninstalled public dep with or without a package.json, from any cwd, on a cold cache. Dropped rather than reworded. The compiled shapes are the durable half and they fail at opposite ends -- a dep the compiler can see is refused before a binary exists, one it cannot see fails at import inside the host -- so both are named, with the version they were measured on. --- packages/client/README.md | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/client/README.md b/packages/client/README.md index fda25e8..68d6224 100644 --- a/packages/client/README.md +++ b/packages/client/README.md @@ -43,11 +43,30 @@ prove. Each was found by a consumer shipping green and failing elsewhere. `~/.config/opencode` without an override writes lock files and manifests beside real credentials — passing locally, and mutating state no CI runner has. • **A bare `bun` run is not an oracle for module resolution.** The Bun CLI auto-installs - a public dependency it cannot resolve, needing only a `package.json` in scope; a - compiled binary does not. Measured on the same module, same directory, no - `node_modules`: compiled loader gives `ERR_MODULE_NOT_FOUND`, `bun -e` resolves. Since - consumers of a credential client are daemons and plugins, exercise resolution under a - compiled loader (`bun build --compile`) or the real host. + a public dependency it cannot resolve; a compiled binary does not. All readings below + are bun 1.3.14, same module, no `node_modules` — a toolchain behaviour with no version + attached reads as permanent, and this one is a moving target by construction. + + ``` + bun run m.mjs / bun -e resolves with or without a package.json in scope, + from any cwd, on a cold install cache + bun build --compile error: Could not resolve: "X". Maybe you need to + (static import) "bun install"? -- NO BINARY PRODUCED + bun build --compile builds; fails in the consumer's process at import: + (dynamic import of a ERR_MODULE_NOT_FOUND Cannot find package 'X' + disk module) + ``` + + Both compiled shapes matter and they fail at opposite ends. A bare dependency the + compiler can see is refused early and loudly, before any artifact exists. One it cannot + see — a plugin or a path-imported client loaded at runtime — survives the build and + fails at import inside the host, which is exactly where a credential client cannot + afford to fail. Since this client's consumers are daemons and plugins, exercise + resolution under a compiled loader or the real host, never a bare CLI run. + + On macOS, sign the compiled probe (`codesign --force --sign -`) before trusting its + result: a freshly linked unsigned binary is SIGKILLed, and `rc=137` with empty stderr + reads as a resolution failure while being a signature one. The shape is the same in all three: the producing machine supplies the thing under test. A passing check on it is evidence only when the ambient supply is removed first. From a349f2d35303867d222e72e4cc3e60b003747b56 Mon Sep 17 00:00:00 2001 From: iceteaSA <171169159+iceteaSA@users.noreply.github.com> Date: Mon, 14 Sep 2026 10:07:16 +0200 Subject: [PATCH 3/3] docs: unbreak the bun-resolution table, which had become unreadable The three-shape reading was laid out as a two-column table, and the widest label ("dynamic import of a disk module") wrapped mid-phrase. The wrap interleaved the label's tail with the ERR_MODULE_NOT_FOUND text from the outcome column, so the row read as noise -- in a block whose whole job is to be read carefully, since it is the evidence a consumer uses to pick a resolution oracle. Restructured to label-then-outcome rather than side-by-side columns. Nothing about the findings changed; column alignment was doing work that a line break could do without a width budget. Found by review. Rebased onto master 4dce994. --- packages/client/README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/client/README.md b/packages/client/README.md index 68d6224..821a8ce 100644 --- a/packages/client/README.md +++ b/packages/client/README.md @@ -48,13 +48,17 @@ prove. Each was found by a consumer shipping green and failing elsewhere. attached reads as permanent, and this one is a moving target by construction. ``` - bun run m.mjs / bun -e resolves with or without a package.json in scope, - from any cwd, on a cold install cache - bun build --compile error: Could not resolve: "X". Maybe you need to - (static import) "bun install"? -- NO BINARY PRODUCED - bun build --compile builds; fails in the consumer's process at import: - (dynamic import of a ERR_MODULE_NOT_FOUND Cannot find package 'X' - disk module) + bun run m.mjs / bun -e + resolves, with or without a package.json in scope, from any cwd, + on a cold install cache + + bun build --compile, static import + error: Could not resolve: "X". Maybe you need to "bun install"? + NO BINARY PRODUCED + + bun build --compile, dynamic import of a disk module + builds; fails in the consumer's process at import: + ERR_MODULE_NOT_FOUND Cannot find package 'X' ``` Both compiled shapes matter and they fail at opposite ends. A bare dependency the