@retasc/cli 1.35.0 → 1.35.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,17 @@ release commits and the issues they reference.
6
6
 
7
7
  Dates are the npm publish date. Each entry names the RTSC issue behind it.
8
8
 
9
+ ## 1.35.1 (2026-08-25)
10
+
11
+ - **RTSC-478** — a network failure now names its own cause. Node reports every failed
12
+ `fetch` as the literal `fetch failed` and puts the diagnosis on `err.cause.code`, which
13
+ the CLI read past, so `retasc login` on a machine whose TLS trust store Node cannot read
14
+ died on `✗ fetch failed` and nothing else. It now prints
15
+ `✗ fetch failed (UNABLE_TO_GET_ISSUER_CERT_LOCALLY)` — a searchable string naming the
16
+ real problem. `cli/README.md` gains a troubleshooting entry keyed on that code, covering
17
+ both causes: a corporate TLS-inspecting proxy, and a Homebrew `openssl@3` keg that lost
18
+ its CA symlink (the confusing one, since `curl` and `npm` keep working).
19
+
9
20
  ## 1.35.0 (2026-08-25)
10
21
 
11
22
  - **RTSC-709** — `retasc issue show` and `retasc issue list` read the queue from a
package/README.md CHANGED
@@ -122,6 +122,34 @@ Two more are reachable but not as their own command, which is also deliberate:
122
122
  If you want any of the above from a terminal anyway, say so in an issue: the point of this
123
123
  list is that their absence is a choice we wrote down, not one nobody has noticed.
124
124
 
125
+ ## Troubleshooting
126
+
127
+ ### `fetch failed (UNABLE_TO_GET_ISSUER_CERT_LOCALLY)` or `(SELF_SIGNED_CERT_IN_CHAIN)`
128
+
129
+ Node cannot verify the TLS certificate, so every request the CLI makes dies before it is
130
+ sent. It usually shows up on `retasc login`, because that is the first command that talks
131
+ to the network. Two causes, and the code tells you which:
132
+
133
+ - **A corporate TLS-inspecting proxy** (Zscaler and similar) re-signs traffic with a root
134
+ Node does not trust — normally `SELF_SIGNED_CERT_IN_CHAIN`. Point Node at your
135
+ organisation's CA bundle:
136
+
137
+ ```bash
138
+ export NODE_EXTRA_CA_CERTS=/path/to/your-company-ca.pem
139
+ ```
140
+
141
+ - **A Homebrew Node whose OpenSSL keg lost its CA symlink** — normally
142
+ `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`, and the confusing one, because `curl` and `npm`
143
+ keep working: they do not read the file Node reads. Relink it:
144
+
145
+ ```bash
146
+ brew postinstall openssl@3
147
+ ```
148
+
149
+ Never set `NODE_TLS_REJECT_UNAUTHORIZED=0`. It turns off certificate verification for
150
+ every connection the process makes, including the one carrying your session token.
151
+ `NODE_EXTRA_CA_CERTS` fixes the same failures with verification left on.
152
+
125
153
  ## Links
126
154
 
127
155
  - Website — [retasc.com](https://retasc.com)
package/dist/api.js CHANGED
@@ -3,6 +3,7 @@ import { makeFunctionReference } from "convex/server";
3
3
  import { loadConfig } from "./config.js";
4
4
  import { refreshSession, deviceLogin } from "./auth.js";
5
5
  import { selfCommand } from "./lib/launcher.js";
6
+ import { clean as sanitize } from "./lib/text.js";
6
7
  import { VERSION } from "./version.js";
7
8
  // Typed-ish references to the public management functions in convex/manage.ts.
8
9
  // The CLI is a standalone package, so we reference functions by name rather than
@@ -100,6 +101,19 @@ export function formatError(e) {
100
101
  .split("\n")[0]
101
102
  .replace(/^.*?Uncaught Error:\s*/, "")
102
103
  .trim();
104
+ // RTSC-478: a failed `fetch` throws the literal `TypeError: fetch failed` and puts the
105
+ // actual diagnosis on `cause.code` — `UNABLE_TO_GET_ISSUER_CERT_LOCALLY` when Node cannot
106
+ // read the machine's CA roots, `SELF_SIGNED_CERT_IN_CHAIN` behind a corporate
107
+ // TLS-inspecting proxy, `ECONNREFUSED`, `ENOTFOUND`. Reading `message` alone throws away
108
+ // the diagnosis Node already handed us, and leaves `retasc login` — the FIRST command a
109
+ // new user runs — dead-ended on a string that names nothing and searches for nothing:
110
+ // ✗ fetch failed → ✗ fetch failed (UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
111
+ // Fallback branch only: a structured backend error (above) already carries its own `code`.
112
+ // Sanitized like every other string we print, because `cause` is not always ours.
113
+ const raw = e?.cause?.code;
114
+ const code = typeof raw === "string" ? sanitize(raw).trim() : "";
115
+ if (code && !message.includes(code))
116
+ return { message: `${message} (${code})` };
103
117
  return { message };
104
118
  }
105
119
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retasc/cli",
3
- "version": "1.35.0",
3
+ "version": "1.35.1",
4
4
  "description": "Retasc CLI — the issue tracker AI agents pull work from. Sign in with GitHub or Google, create projects, mint agent API keys, and wire your agent to the Retasc MCP server in one command.",
5
5
  "type": "module",
6
6
  "bin": {