@catheadowl/ukp 0.2.5 → 0.2.6
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 +10 -5
- package/docs/remote-deployment.md +94 -16
- package/package.json +1 -1
- package/src/capabilities/door-health.ts +480 -0
- package/src/capabilities/tls-identity.ts +3 -2
- package/src/cli.ts +6 -0
- package/src/commands/diagnose.ts +80 -2
- package/src/commands/guide-content/remote.txt +1 -1
- package/src/commands/init.ts +27 -0
- package/src/commands/serve-task.ts +334 -44
- package/src/commands/serve.ts +101 -19
- package/src/server.ts +76 -43
package/README.md
CHANGED
|
@@ -71,8 +71,9 @@ predictable scope, and a single command surface. Use UKP when:
|
|
|
71
71
|
- Propose changes as an idempotent, reviewable suggestion — the proposal
|
|
72
72
|
lands in the endpoint's inbox and the verdict stays with its owner.
|
|
73
73
|
- Update provider-owned indexes through a stable UKP command (QMD-backed).
|
|
74
|
-
- Serve an endpoint over HTTP — a single endpoint,
|
|
75
|
-
a host door — when you want it reachable from other
|
|
74
|
+
- Serve an endpoint over HTTP — a single endpoint, a `--select`ed subset, or
|
|
75
|
+
every local binding as a host door — when you want it reachable from other
|
|
76
|
+
machines.
|
|
76
77
|
- Want a read-only endpoint? Declare zero capabilities — an empty
|
|
77
78
|
`[capabilities]` table still registers one (derived `read`/`nav` only).
|
|
78
79
|
- Give agents JSON output (`--json`; `ukp read` uses `--format json`),
|
|
@@ -163,7 +164,7 @@ Operations commands:
|
|
|
163
164
|
| `ukp diagnose` | Checks a Service folder or endpoint scope for wiring problems. |
|
|
164
165
|
| `ukp inspect` | Explains current scope, bindings, manifest capabilities, and provider availability. |
|
|
165
166
|
| `ukp update` | Runs provider-owned maintenance when `update/qmd` is declared (local endpoints today). |
|
|
166
|
-
| `ukp serve` | Serves one endpoint — or, without `--endpoint`,
|
|
167
|
+
| `ukp serve` | Serves one endpoint — or, without `--endpoint`, local bindings as a **host door** (every one of them, or just the ones `--select` names — unselected endpoints are not served, routed, or declared) — over HTTP (a discovery document plus the five command routes; loopback by default). |
|
|
167
168
|
|
|
168
169
|
Help commands:
|
|
169
170
|
|
|
@@ -203,10 +204,14 @@ NAT/EIP cloud host (public IP on no NIC)? Name it with
|
|
|
203
204
|
over the same key, so the pin (and every registration) survives; details in
|
|
204
205
|
the deployment guide.
|
|
205
206
|
|
|
206
|
-
Registration mechanics: a **host door** url imports every endpoint
|
|
207
|
+
Registration mechanics: a **host door** url imports every endpoint it declares
|
|
207
208
|
(`--endpoint <name>` checks the served name and narrows the import to that
|
|
208
209
|
one, `--select` narrows to a subset); `--token` is stored with the binding;
|
|
209
|
-
re-running a registration refreshes it idempotently.
|
|
210
|
+
re-running a registration refreshes it idempotently. A host whose registry
|
|
211
|
+
mixes shareable knowledge with internal projects can serve
|
|
212
|
+
`ukp serve --select a,b,c` — one port for exactly those endpoints; everything
|
|
213
|
+
the door does not select behaves as if it did not exist (discovery, routes,
|
|
214
|
+
and 404 rosters alike).
|
|
210
215
|
|
|
211
216
|
Remote endpoints take the same commands as local ones — search, read, nav,
|
|
212
217
|
rg, propose. The full guide — the host door (one port for the whole
|
|
@@ -123,12 +123,23 @@ one bun process always running — with **no visible window** (a hidden
|
|
|
123
123
|
launcher owns the console; a popping cmd box is not an acceptable product
|
|
124
124
|
form) and bounded crash retry. Verified end to end (register/TOFU →
|
|
125
125
|
read → nav, plus zero-flash and crash-recovery drills) on a Windows 11
|
|
126
|
-
host with a plain user-level install
|
|
126
|
+
host with a plain user-level install; the task recipe and the log
|
|
127
|
+
ownership were re-verified end to end on 2026-09-23 (unelevated
|
|
128
|
+
per-user registration, no execution time limit, whole-tree restart).
|
|
129
|
+
Steps 3–6 are exactly what
|
|
127
130
|
`ukp serve --print-task --host 0.0.0.0 --tls`
|
|
128
131
|
(or `--tls-cert/--tls-key`) prints for you — the generator assembles the
|
|
129
132
|
mechanical half (start script, hidden launcher, Task Scheduler command,
|
|
130
133
|
firewall rule, token placeholder); this section keeps the judgment calls
|
|
131
|
-
and the pitfalls the verification run caught
|
|
134
|
+
and the pitfalls the verification run caught. A fast path exists for the
|
|
135
|
+
two file artifacts: `ukp serve --print-task --write ...` writes
|
|
136
|
+
`start-door.cmd` (token interpolated from your `UKP_SERVE_TOKEN` — never
|
|
137
|
+
displayed) and the hidden launcher straight into `%USERPROFILE%\.ukp\`,
|
|
138
|
+
CRLF by construction; existing files are never overwritten (manual edits
|
|
139
|
+
— a PATH patch, say — are safe; regeneration means removing the old files
|
|
140
|
+
first, as the removal section prescribes). The task-registration and
|
|
141
|
+
firewall steps stay on stdout for you to run; the print-only form remains
|
|
142
|
+
the full playbook (its Notes and the removal section):
|
|
132
143
|
|
|
133
144
|
1. Install the usual way (bun's official installer + `npm i -g
|
|
134
145
|
@catheadowl/ukp` — the npm shim needs bun on PATH, both land in
|
|
@@ -143,8 +154,11 @@ and the pitfalls the verification run caught:
|
|
|
143
154
|
-subj "/CN=ukp" -addext "subjectAltName=IP:<lan-ip>,DNS:localhost"`
|
|
144
155
|
4. `%USERPROFILE%\.ukp\start-door.cmd` (CRLF!) — set UKP_SERVE_TOKEN,
|
|
145
156
|
run `ukp serve --host 0.0.0.0 --port 8570 --tls-cert ... --tls-key ...`
|
|
146
|
-
with the door.log
|
|
147
|
-
|
|
157
|
+
with **no redirect on the serve line** — door.log is owned solely by
|
|
158
|
+
the vbs launcher's outer redirect; a second redirect here deadlocks
|
|
159
|
+
the nested append-open and the door never starts. No PATH export: the
|
|
160
|
+
launcher finds bun itself, and the logged-on task carries the
|
|
161
|
+
per-user PATH. Write it
|
|
148
162
|
with a real editor (writing cmd files over ssh echo mangles `%`
|
|
149
163
|
escaping — copy the file instead).
|
|
150
164
|
5. `%USERPROFILE%\.ukp\start-door-hidden.vbs` (CRLF, real editor) — the
|
|
@@ -152,11 +166,16 @@ and the pitfalls the verification run caught:
|
|
|
152
166
|
at process creation (nothing ever flashes), captures everything to
|
|
153
167
|
door.log, propagates the exit code, and retries a crashed door
|
|
154
168
|
3 times, 30s apart. `ukp serve --print-task` prints it verbatim.
|
|
155
|
-
6.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
ukp-
|
|
169
|
+
6. Scheduled task — register from a **plain PowerShell shell** (no
|
|
170
|
+
elevation needed: a per-user logon trigger is the OneDrive/Teams-class
|
|
171
|
+
autostart path; a machine-level logon trigger or another user's
|
|
172
|
+
session still needs the elevated schtasks route). Use the
|
|
173
|
+
`Register-ScheduledTask` block `ukp serve --print-task` prints —
|
|
174
|
+
per-user `AtLogOn -User` trigger, battery flags, `IgnoreNew`, and
|
|
175
|
+
deliberately **no execution time limit**
|
|
176
|
+
(`-ExecutionTimeLimit ([TimeSpan]::Zero)`). Then the firewall rule
|
|
177
|
+
for the port (that one does need an elevated shell), and
|
|
178
|
+
`Start-ScheduledTask -TaskName ukp-door` to start now.
|
|
160
179
|
7. Client: `ukp register --url https://<host>:8570 --token <token>` —
|
|
161
180
|
TOFU pins the certificate; re-registering refreshes the pin.
|
|
162
181
|
|
|
@@ -168,16 +187,66 @@ Pitfalls the verification run caught:
|
|
|
168
187
|
- ONLOGON starts at LOGON, not boot, and the launcher's crash retry is
|
|
169
188
|
bounded (3×30s): after an unattended reboot nobody logs into, or after
|
|
170
189
|
exhausted retries, the door is down until the next logon or a manual
|
|
171
|
-
`
|
|
172
|
-
wrapping — or prefer ssh:// there. (Task
|
|
173
|
-
restart-on-failure setting does not fire on exit
|
|
174
|
-
on it.)
|
|
175
|
-
-
|
|
176
|
-
|
|
177
|
-
|
|
190
|
+
`Start-ScheduledTask -TaskName ukp-door`. Unattended-boot always-on
|
|
191
|
+
would need WinSW/NSSM-class wrapping — or prefer ssh:// there. (Task
|
|
192
|
+
Scheduler's own restart-on-failure setting does not fire on exit
|
|
193
|
+
codes — do not rely on it.)
|
|
194
|
+
- **The 72-hour default**: a task without an explicit execution time
|
|
195
|
+
limit is stopped by Task Scheduler 72 hours after it starts — for a
|
|
196
|
+
resident door that is a silent kill (no window, no log line). The
|
|
197
|
+
recipe pins `-ExecutionTimeLimit ([TimeSpan]::Zero)` (PT0S in the task
|
|
198
|
+
XML); keep it when editing the task by hand.
|
|
199
|
+
- To restart the door by hand (new token, ukp upgrade, new cert): kill
|
|
200
|
+
the **launcher root**, not just the serve leaf — `taskkill /PID
|
|
201
|
+
<wscript-pid> /T /F` on the `wscript.exe` running
|
|
202
|
+
`start-door-hidden.vbs`, then `Start-ScheduledTask -TaskName
|
|
203
|
+
ukp-door`. A leaf-only kill leaves the launcher's bounded retry to
|
|
204
|
+
re-grab the port within 30 seconds, racing the manual start (which
|
|
205
|
+
`IgnoreNew` turns into a no-op while the old launcher lives); the
|
|
206
|
+
scheduler's End-Task does not reliably kill the tree either. Each
|
|
207
|
+
door has its own wscript — in PowerShell, `Get-CimInstance
|
|
208
|
+
Win32_Process -Filter "Name='wscript.exe'" | Select-Object
|
|
209
|
+
ProcessId,CommandLine` and match the vbs name.
|
|
210
|
+
- **Git Bash path conversion**: MSYS rewrites slash-style arguments into
|
|
211
|
+
Git paths (`taskkill /PID …` fails with a misleading
|
|
212
|
+
Invalid-argument error that reads like a permission problem). Prefix
|
|
213
|
+
such commands with `MSYS_NO_PATHCONV=1`.
|
|
214
|
+
- **Do not edit start-door.cmd while the door runs**: cmd.exe resumes
|
|
215
|
+
reading a running batch file at a stale byte offset, so an in-place
|
|
216
|
+
edit above the current line makes it execute garbled fragments when
|
|
217
|
+
the current command returns (observed live: a mid-comment `a` ran as
|
|
218
|
+
a command). Stop the door first, edit, then restart.
|
|
178
219
|
- `rg` on the host is the host's business — no ripgrep installed means
|
|
179
220
|
the remote `rg` capability reports unavailable (everything else works).
|
|
180
221
|
|
|
222
|
+
To remove the door — the inverse of steps 4–0, in three levels (stopping
|
|
223
|
+
is not disabling, and disabling is not erasing; `ukp serve --print-task`
|
|
224
|
+
prints this checklist as its §5):
|
|
225
|
+
|
|
226
|
+
1. **Stop now**: `taskkill /PID <wscript-pid> /T /F` on the launcher
|
|
227
|
+
root (same lookup as the restart pitfall above). With the task still
|
|
228
|
+
registered, the next logon brings the door back.
|
|
229
|
+
2. **Stop for good**:
|
|
230
|
+
`Unregister-ScheduledTask -TaskName ukp-door -Confirm:$false` from a
|
|
231
|
+
plain shell — the same zero-elevation path as registering it. The
|
|
232
|
+
cmdlet confirms by default (hence the flag), and unregistering does
|
|
233
|
+
**not** stop a running instance: the kill in step 1 is not optional.
|
|
234
|
+
3. **Erase everything**: `netsh advfirewall firewall delete rule
|
|
235
|
+
name="ukp-door"` (the elevated shell again), then delete
|
|
236
|
+
`%USERPROFILE%\.ukp\start-door.cmd` (**it carries the token in
|
|
237
|
+
plaintext** — deleting it destroys this copy; if it ever left the
|
|
238
|
+
machine, treat the token as burned), `start-door-hidden.vbs`, and
|
|
239
|
+
`door.log`, plus the certificate material: your `--tls-cert` /
|
|
240
|
+
`--tls-key` paths, or — with `--tls` — the identity in the served
|
|
241
|
+
folder's `.ukp\tls\` (single-endpoint door: *inside* the KB folder,
|
|
242
|
+
so git or cloud sync carries the private key out;
|
|
243
|
+
`ukp init service` drops a self-ignoring `.ukp\.gitignore` there) or
|
|
244
|
+
beside the host registry (host door). The endpoints stay registered
|
|
245
|
+
on the host for local use — `ukp unregister --endpoint <name>` per
|
|
246
|
+
endpoint only if you are done with them; and every consumer that
|
|
247
|
+
registered holds the token in plaintext in its own registry —
|
|
248
|
+
`ukp unregister --endpoint <name>` there too.
|
|
249
|
+
|
|
181
250
|
## Socket activation (Linux — no resident process on the https path either)
|
|
182
251
|
|
|
183
252
|
systemd can hold the listening port itself and spawn the door on first
|
|
@@ -236,6 +305,15 @@ Notes:
|
|
|
236
305
|
addresses — a public EIP is not among them, and registration would fail
|
|
237
306
|
CERT_ALTNAME_INVALID. Add `--tls-san <public-ip>` next to `--tls`
|
|
238
307
|
(see Native TLS above): the SAN grows, the key (and pin) does not.
|
|
308
|
+
- **Removing the door** (the setup block's inverse — the same three
|
|
309
|
+
levels as the Windows teardown above, in one gesture):
|
|
310
|
+
`systemctl --user disable --now ukp-door.socket` (a door still
|
|
311
|
+
running stops with `systemctl --user stop ukp-door.service`), then
|
|
312
|
+
delete the two unit files and the token env file, and
|
|
313
|
+
`rm -rf ~/.ukp/tls` if you are done with the self-signed identity;
|
|
314
|
+
`loginctl disable-linger "$USER"` too if nothing else on the host
|
|
315
|
+
needs it. Nothing else is resident — consumer and host registry
|
|
316
|
+
bindings come off exactly as on the Windows side.
|
|
239
317
|
|
|
240
318
|
## Host door (one host, many endpoints — one gesture, zero tokens)
|
|
241
319
|
|