@saptools/cf-debugger 0.2.0 → 0.2.2
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/README.md +66 -29
- package/dist/{chunk-ZWAQD7KL.js → chunk-QBB4N2WN.js} +1671 -785
- package/dist/chunk-QBB4N2WN.js.map +1 -0
- package/dist/cli.js +101 -143
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +27 -9
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-ZWAQD7KL.js.map +0 -1
package/README.md
CHANGED
|
@@ -14,6 +14,9 @@ Node.js 20+ and the official `cf` CLI are required. CF CLI v8 is recommended.
|
|
|
14
14
|
Non-`web` process targeting uses `cf ssh --process` and requires CF CLI v7+.
|
|
15
15
|
On macOS, `lsof` is a soft dependency used to prove which PID owns a local
|
|
16
16
|
listening port. Install it if `cf-debugger` reports `TUNNEL_OWNER_UNVERIFIED`.
|
|
17
|
+
Without it, an explicit stop refuses to signal a state-recorded PID whose port
|
|
18
|
+
ownership cannot be proved; teardown still completes when the spawned child is
|
|
19
|
+
independently confirmed dead.
|
|
17
20
|
|
|
18
21
|
## Quick start
|
|
19
22
|
|
|
@@ -43,9 +46,11 @@ Debugger ready for my-app (eu10/my-org/dev).
|
|
|
43
46
|
Press Ctrl+C to stop.
|
|
44
47
|
```
|
|
45
48
|
|
|
46
|
-
Attach the IDE to `127.0.0.1:20142`.
|
|
47
|
-
`
|
|
48
|
-
|
|
49
|
+
Attach the IDE to `127.0.0.1:20142`. Node derives the advertised
|
|
50
|
+
`webSocketDebuggerUrl` from the incoming request's `Host` header, so a URL
|
|
51
|
+
returned through the forward already names the local forwarded port and is
|
|
52
|
+
directly usable. `cf-debugger` validates that the URL is well formed but does
|
|
53
|
+
not print or follow it.
|
|
49
54
|
|
|
50
55
|
## CLI
|
|
51
56
|
|
|
@@ -63,13 +68,13 @@ When region, org, or space is omitted, the current `cf target` supplies it.
|
|
|
63
68
|
| Flag | Meaning |
|
|
64
69
|
| --- | --- |
|
|
65
70
|
| `--region <key>` | SAP region key; defaults to the current CF target |
|
|
66
|
-
| `--api-endpoint <url>` |
|
|
71
|
+
| `--api-endpoint <url>` | Absolute HTTPS endpoint override, including private/nonstandard hosts |
|
|
67
72
|
| `--org <name>`, `--space <name>`, `--app <name>` | CF target and app |
|
|
68
73
|
| `--process <name>` | CF process, default `web` |
|
|
69
74
|
| `-i, --instance <index>` | Zero-based process instance, default `0` |
|
|
70
75
|
| `--node-pid <pid>` | Exact remote Node PID |
|
|
71
76
|
| `--port <number>` | Preferred local port; otherwise choose from `20000–20999` |
|
|
72
|
-
| `--remote-port <number>` |
|
|
77
|
+
| `--remote-port <number>` | Port where cf-debugger looks for an existing remote inspector, default `9229` |
|
|
73
78
|
| `--timeout <seconds>` | Local-tunnel and inspector-readiness budget, default `180` |
|
|
74
79
|
| `--startup-timeout <seconds>` | Overall startup deadline, default `300`, maximum `1800` |
|
|
75
80
|
| `--allow-ssh-enable-restart` | Permit app-level SSH enablement and one app restart |
|
|
@@ -81,7 +86,15 @@ When region, org, or space is omitted, the current `cf target` supplies it.
|
|
|
81
86
|
> `SSH_NOT_ENABLED` and no deployment mutation. Use
|
|
82
87
|
> `--allow-ssh-enable-restart`, or set `CF_DEBUGGER_ALLOW_RESTART=1`, only when
|
|
83
88
|
> restarting the named app is acceptable. `CF_DEBUGGER_ALLOW_RESTART=0` keeps
|
|
84
|
-
> the guard enabled for a production shell
|
|
89
|
+
> the guard enabled for a production shell and also vetoes a programmatic
|
|
90
|
+
> `allowSshEnableRestart: true`. The environment value `1` can opt in the CLI,
|
|
91
|
+
> but never grants permission to a programmatic caller by itself.
|
|
92
|
+
|
|
93
|
+
`--api-endpoint` accepts arbitrary hostnames but requires an absolute `https:`
|
|
94
|
+
URL with no userinfo, query, fragment, or non-root path. Invalid values are
|
|
95
|
+
rejected before `cf api` or `cf auth`. Version 0.2.2 intentionally rejects
|
|
96
|
+
plaintext `http://` landscapes because credentials would be sent to that
|
|
97
|
+
endpoint.
|
|
85
98
|
|
|
86
99
|
Even with permission, a restart occurs only when all of these are true:
|
|
87
100
|
|
|
@@ -96,15 +109,18 @@ stderr names the app and org/space. With an explicit `--node-pid`, automatic
|
|
|
96
109
|
restart is always rejected because the container replacement invalidates that
|
|
97
110
|
PID.
|
|
98
111
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
still has time.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
Read-only CF commands have a 60-second per-attempt cap and retry transient
|
|
113
|
+
transport errors with bounded exponential delays while the single overall
|
|
114
|
+
startup budget still has time. Deployment-mutating commands have a separate
|
|
115
|
+
180-second cap and are never retried: a timed-out enable/restart reports
|
|
116
|
+
`CF_MUTATION_TIMEOUT` because the server-side mutation may still be completing.
|
|
117
|
+
`cf auth` has no outer retry loop, and rejected credentials fail after one
|
|
118
|
+
attempt; repeated manual failures may count toward a tenant's identity-provider
|
|
119
|
+
lockout policy. The one-shot SSH signal and readiness wait are also clamped to
|
|
120
|
+
the same overall deadline. No retry configuration multiplies startup work past
|
|
121
|
+
`--startup-timeout`. After a timeout, fail-closed tunnel and state cleanup still
|
|
122
|
+
runs; that safety teardown can briefly extend the observed command wall time
|
|
123
|
+
rather than abandoning an unverified child.
|
|
108
124
|
|
|
109
125
|
### `stop`
|
|
110
126
|
|
|
@@ -117,19 +133,20 @@ cf-debugger stop --all
|
|
|
117
133
|
cf-debugger stop --session-id 550e8400-e29b-41d4-a716-446655440000 --force
|
|
118
134
|
```
|
|
119
135
|
|
|
120
|
-
`stop --all` attempts every local session, reports stopped,
|
|
121
|
-
failed outcomes separately, and exits
|
|
136
|
+
`stop --all` attempts every local session, reports stopped, forced, stale,
|
|
137
|
+
pending, and failed outcomes separately, and exits `70` if any tunnel cleanup
|
|
138
|
+
failed (`1` for other failures). It cannot
|
|
122
139
|
be combined with a positional selector, `--session-id`, or target selector
|
|
123
140
|
options; ambiguous scope is rejected instead of widening to every session.
|
|
124
141
|
|
|
125
142
|
`stop --force` means “forget safely,” not “kill harder.” It never signals a PID
|
|
126
|
-
whose tunnel ownership is unproven. It
|
|
127
|
-
exact derived v2 `CF_HOME
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
path, that path is left untouched
|
|
132
|
-
still forgotten.
|
|
143
|
+
whose tunnel ownership is unproven. It forgets the state record first, then
|
|
144
|
+
best-effort removes only the exact derived v2 `CF_HOME`. A deletion failure is
|
|
145
|
+
non-fatal and warns that the retained path may contain a live refresh token;
|
|
146
|
+
`doctor` then reports it as an orphan eligible for `doctor --cleanup`. The
|
|
147
|
+
warning also names the abandoned PID and port for manual investigation. If a
|
|
148
|
+
damaged record names a non-owned home path, that path is left untouched while
|
|
149
|
+
the record is still forgotten.
|
|
133
150
|
|
|
134
151
|
### `list` and `status`
|
|
135
152
|
|
|
@@ -161,12 +178,16 @@ The default is read-only JSON reporting. It includes:
|
|
|
161
178
|
- v2 session homes with no state record;
|
|
162
179
|
- listeners in `20000–20999` that no state record claims;
|
|
163
180
|
- leftover state temp, lock, recovery, stop-intent, and corrupt-backup files;
|
|
164
|
-
- legacy v1 state/homes
|
|
181
|
+
- legacy v1 state/homes, home count, parseable claimed sessions, conservative
|
|
182
|
+
PID liveness, and their credential-retention risk.
|
|
165
183
|
|
|
166
184
|
`--cleanup` removes only canonical orphan v2 homes and sufficiently old,
|
|
167
185
|
package-owned temp/lock/recovery/stop-intent artifacts. It revalidates orphan
|
|
168
186
|
homes against lock-guarded state immediately before deletion. It never signals
|
|
169
187
|
an unclaimed listener, removes corrupt evidence, or removes legacy v1 artifacts.
|
|
188
|
+
Corrupt backups include a manual-removal command in the report while remaining
|
|
189
|
+
ineligible for automatic cleanup. A symlinked v2 homes root is reported and
|
|
190
|
+
never traversed.
|
|
170
191
|
|
|
171
192
|
## Region resolution
|
|
172
193
|
|
|
@@ -205,7 +226,13 @@ explicitly if a worker is the intended target.
|
|
|
205
226
|
|
|
206
227
|
The remote probe reads `/proc/<pid>/exe`, not argv. Its marker lines are filtered
|
|
207
228
|
by a strict `saptools-inspector-*` prefix, so CF SSH banners cannot impersonate
|
|
208
|
-
results.
|
|
229
|
+
results. GNU `find -lname` is capability-probed and is normally fast; the
|
|
230
|
+
portable fallback walks descriptors with `readlink` and can take roughly
|
|
231
|
+
10–12 seconds in a descriptor-heavy non-GNU container.
|
|
232
|
+
|
|
233
|
+
`--remote-port` does not choose the port opened by `SIGUSR1`; Node always uses
|
|
234
|
+
its default inspector port for that signal. A non-default value is therefore
|
|
235
|
+
for an app already started with matching `--inspect=<port>`.
|
|
209
236
|
|
|
210
237
|
### Status sequence
|
|
211
238
|
|
|
@@ -251,6 +278,13 @@ individually, and the original state file is moved to a private
|
|
|
251
278
|
version, or root shape is likewise preserved before a fresh empty v2 file is
|
|
252
279
|
written.
|
|
253
280
|
|
|
281
|
+
During mixed-version use, an older cf-debugger sharing this v2 file may strip
|
|
282
|
+
optional fields it does not understand, including process-identity and startup
|
|
283
|
+
budget data. Newer code treats an absent/legacy identity as “cannot tell” and
|
|
284
|
+
retains the record with PID-only compatibility rather than pruning it; `doctor`
|
|
285
|
+
surfaces that degraded verdict. Updating every installed consumer is the only
|
|
286
|
+
way to restore the stronger identity check persistently.
|
|
287
|
+
|
|
254
288
|
Legacy `~/.saptools/cf-debugger-homes/` directories may still contain live
|
|
255
289
|
refresh and access tokens. `doctor` reports but never deletes them. After
|
|
256
290
|
confirming no v1 tunnel is running, remove them explicitly:
|
|
@@ -274,7 +308,7 @@ and redact sensitive values before they reach errors or verbose output.
|
|
|
274
308
|
| Variable | Meaning |
|
|
275
309
|
| --- | --- |
|
|
276
310
|
| `SAP_EMAIL`, `SAP_PASSWORD` | CF authentication credentials |
|
|
277
|
-
| `CF_DEBUGGER_ALLOW_RESTART=0\|1` |
|
|
311
|
+
| `CF_DEBUGGER_ALLOW_RESTART=0\|1` | CLI default; `0` is also a hard veto for the programmatic API |
|
|
278
312
|
| `CF_DEBUGGER_CF_BIN` | Replace the `cf` executable; useful for wrappers and deterministic test stubs |
|
|
279
313
|
|
|
280
314
|
A caller-provided child environment cannot override the per-session `CF_HOME`.
|
|
@@ -289,6 +323,7 @@ domain code; it is never converted into success.
|
|
|
289
323
|
| --- | --- |
|
|
290
324
|
| `UNKNOWN_REGION`, `UNSAFE_INPUT`, `MISSING_CREDENTIALS` | Invalid endpoint/key, selector, numeric input, or credentials |
|
|
291
325
|
| `CF_LOGIN_FAILED`, `CF_AUTH_FAILED`, `CF_TARGET_FAILED`, `CF_CLI_FAILED`, `CF_CLI_TIMEOUT` | CF command failure; rejected auth is not retried |
|
|
326
|
+
| `CF_MUTATION_TIMEOUT` | A deployment mutation timed out, was not retried, and may still be completing remotely |
|
|
292
327
|
| `STARTUP_TIMEOUT`, `ABORTED` | Overall deadline expired, or caller/stop intent cancelled startup |
|
|
293
328
|
| `APP_NOT_FOUND` | The targeted app does not exist in the selected org/space |
|
|
294
329
|
| `SSH_NOT_ENABLED`, `SSH_PERMISSION_DENIED`, `SSH_STATE_UNKNOWN` | Restart refused/not useful, permission denied, or SSH state ambiguous |
|
|
@@ -302,13 +337,15 @@ domain code; it is never converted into success.
|
|
|
302
337
|
| `TUNNEL_EXITED`, `TUNNEL_TERMINATION_FAILED`, `TUNNEL_OWNERSHIP_UNVERIFIED` | Tunnel died, cleanup could not terminate it, or stop could not safely signal it |
|
|
303
338
|
| `SESSION_ALREADY_RUNNING`, `SESSION_AMBIGUOUS`, `SESSION_NOT_FOUND` | Session selection conflict |
|
|
304
339
|
| `SESSION_STATE_LOST`, `SESSION_STATE_CONFLICT`, `STATE_LOCK_TIMEOUT` | Atomic state/lifecycle invariant failed |
|
|
340
|
+
| `CF_HOME_CLEANUP_FAILED` | Session state was removed but lifecycle cleanup could not remove its exact credential-bearing CF home |
|
|
341
|
+
| `PACKAGE_METADATA_INVALID` | Runtime package metadata has no usable version |
|
|
305
342
|
| `STOP_FAILED` | One entry in a batch stop failed with a non-coded internal error |
|
|
306
343
|
|
|
307
344
|
| Exit | Meaning |
|
|
308
345
|
| --- | --- |
|
|
309
346
|
| `0` | Clean completion |
|
|
310
347
|
| `1` | Coded operational/startup error, including `STARTUP_TIMEOUT` |
|
|
311
|
-
| `70` |
|
|
348
|
+
| `70` | Tunnel or lifecycle cleanup failed; ownership state or a credential-bearing home may remain |
|
|
312
349
|
| SSH child's nonzero code | An unexpected numeric SSH exit is preserved, for example `255` |
|
|
313
350
|
| `128 + signal` | Tunnel child died from a signal, for example `137` for `SIGKILL` |
|
|
314
351
|
| `130`, `143` | User interrupted with `SIGINT` or `SIGTERM` |
|
|
@@ -337,7 +374,7 @@ const handle = await startDebugger({
|
|
|
337
374
|
await handle.dispose();
|
|
338
375
|
|
|
339
376
|
const summary = await stopAllDebuggers();
|
|
340
|
-
//
|
|
377
|
+
// Outcomes and counts distinguish stopped/forced/stale/pending/failed.
|
|
341
378
|
```
|
|
342
379
|
|
|
343
380
|
Persisted schema additions in 0.2.0 are optional. Absence means compatible
|