@@ -116,6 +116,27 @@ infinite-loops on connection errors against this server.
116116- No new npm dependencies without a good reason. Current set: ` ws ` , ` commander ` ,
117117 ` chokidar ` , ` diff ` .
118118
119+ ### Commit and PR titles
120+
121+ Conventional commits, enforced on the ** PR title** by ` .github/workflows/pr-title.yml `
122+ — the title becomes the squashed commit message and release-please derives the next
123+ version from it, so a title that does not parse is a release that silently never
124+ happens.
125+
126+ Type is one of ` feat ` , ` fix ` , ` perf ` , ` refactor ` , ` docs ` , ` test ` , ` build ` , ` ci ` ,
127+ ` chore ` , ` revert ` . A scope is optional, ** but any scope used must be one of** :
128+
129+ ```
130+ sync auth watch logs json types cli deps docs release main
131+ ```
132+
133+ That list is closed on purpose, to keep the vocabulary small enough to mean something.
134+ A new component does ** not** earn a new scope — ` feat(doctor) ` fails the check, and a
135+ new CLI command belongs under ` cli ` . If a scope genuinely has to be added, add it to
136+ the workflow in the same PR. (` main ` is not a component: it is the branch name in
137+ release-please's own ` chore(main): release x.y.z ` title, and without it the release PR
138+ cannot merge.) Subjects must not end with a full stop.
139+
119140## Commands
120141
121142``` bash
@@ -134,7 +155,8 @@ Directly tested: `client/socket`, `client/objects`, `client/auth` (HTTP and HTTP
134155` config ` , ` credentials ` , ` sync/compare ` , ` sync/mapping ` , ` sync/safe-path ` (path
135156traversal, symlink-file writes, symlinked-directory writes), the ` --json ` record shapes,
136157and the commands ` pull ` , ` push ` , ` status ` , ` diff ` (including ` --against ` ), ` watch ` ,
137- ` logs ` , ` list ` , ` start ` , ` stop ` , ` restart ` , ` new ` , ` rename ` , ` move ` , ` remove ` , ` backup ` .
158+ ` logs ` , ` list ` , ` start ` , ` stop ` , ` restart ` , ` new ` , ` rename ` , ` move ` , ` remove ` , ` backup ` ,
159+ ` doctor ` .
138160` sync/manifest ` and ` sync/scan ` are covered indirectly by every pull/push test.
139161
140162` test/cli.test.ts ` spawns the built ` dist/cli.js ` and asserts on real argv handling.
@@ -146,7 +168,8 @@ there, and it needs `dist/` built first.**
146168` test/fake-server.ts ` serves HTTP and websocket on one port, as real Admin does on 8081.
147169Its ` auth ` field selects how the HTTP side answers the probes in ` client/auth.ts `
148170(` disabled ` → ` GET /login ` 404s, ` oauth ` → ` POST /oauth/token ` , ` legacy ` → ` POST /login ` );
149- ` reset() ` returns it to ` disabled ` , so tests that do not care are unaffected.
171+ ` reset() ` returns it to ` disabled ` , so tests that do not care are unaffected. Its
172+ ` requireCookieOnSocket ` flag reproduces the silent-auth failure below.
150173
151174` pull ` also skips-and-continues per script rather than aborting the whole run: one
152175unwritable script (a bad id, a symlink in the way) is reported and the rest still
@@ -207,6 +230,27 @@ always `!allowSelfSigned` — the value is the user's decision, not a constant,
207230writing it as one both misreports what the code does and trips CodeQL's
208231` js/disabling-certificate-validation ` .
209232
233+ ### Two failures that look like a broken instance and are not
234+
235+ Both cost a session an hour, and ` commands/doctor.ts ` exists because of them.
236+
237+ 1 . ** An unauthenticated socket is silent, not angry.** Admin accepts the connection,
238+ sends ` ___ready___ ` , and then ignores every command. There is no auth error and no
239+ close — requests simply never come back, and the only thing the caller ever sees is
240+ ` Request "..." timed out ` . The timeout in ` client/socket.ts ` therefore carries a
241+ hint naming this cause; ` test/fake-server.ts ` reproduces it via
242+ ` requireCookieOnSocket ` .
243+ 2 . ** An expired self-signed certificate is harmless here.** With ` allowSelfSigned ` the
244+ identity check is the pinned fingerprint, not the chain, so ` iob-sync ` keeps working
245+ after expiry while every other client on that port fails with
246+ ` certificate has expired ` . ` doctor ` reports it as OK plus a note. Do not "fix" this
247+ by tightening the TLS path — the pin is the check, and it is stricter than the chain.
248+
249+ ** ` iob-sync ` is a CLI, not a library.** ` package.json ` exposes ` bin ` only; there is no
250+ ` exports ` map and nothing under ` src/ ` is a supported import. Anything constructing
251+ ` AdminSocketClient ` directly must reproduce ` withContext ` in ` cli.ts ` — certificate
252+ check, then cookie, then socket — and the failure mode when it does not is (1) above.
253+
210254### Two bugs the watch tests caught
211255
212256Both were live in working code, and both are the kind that only show up under a test
@@ -224,8 +268,6 @@ testable at all, which matters given a regression there means an infinite push l
224268
225269## Other known gaps
226270
227- - Self-signed certificates are honoured on the websocket path but not on the HTTP
228- auth path (would require an ` undici ` Agent).
229271- ` init --types ` writes the ioBroker type definitions, but the download of
230272 ` javascript.d.ts ` from GitHub has only been exercised against a live network.
231273
@@ -296,3 +338,10 @@ window so it measures the debounce rather than the disk.
296338If it recurs, that file is the suspect and the fix is more timing margin — ** not**
297339loosening an assertion. The thing being tested is the guard against an infinite push
298340loop against someone's house.
341+
342+ One of these turned out not to be timing at all. The ` --pull ` case waited for the file
343+ content to appear and then asserted on the log line, but ` applyRemote ` writes the file,
344+ saves the manifest and logs ** last** — so the assertions could run inside that window.
345+ It now waits for the ` pull ` line, which is the operation's real completion signal, and
346+ asserts on the file and manifest afterwards. Before assuming load, check what the code
347+ under test does in what order.
0 commit comments