home-hosted 0.7.4 → 0.7.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.
@@ -19,7 +19,7 @@ opt-in, and the bot token never leaves the secrets file.
19
19
  TOKEN='123456:ABC...'
20
20
  WS='?workspace=default' # every notifications route is workspace-scoped; omit for the default one
21
21
 
22
- curl -X POST "http://127.0.0.1:3999/api/notifications/token$WS" \
22
+ curl -X PUT "http://127.0.0.1:3999/api/notifications/token$WS" \
23
23
  -H 'content-type: application/json' -H "Authorization: Bearer $HH_TOKEN" \
24
24
  -d "{\"botToken\":\"$TOKEN\"}"
25
25
 
@@ -64,7 +64,7 @@ panel did not start is ever killed.
64
64
  | `enabled` | A disabled route stays configured but is not served. |
65
65
  | `target` | `server` (a supervised entry), `panel` (this control panel), `external` (any `host:port`). |
66
66
  | `workspace` + `server` | For `target: "server"` — an id is only unique inside its workspace. The upstream address is resolved live; a stopped entry leaves the hostname dark and the page says so. |
67
- | `url` | For `target: "external"`, e.g. `http://10.0.0.5:8080`. An `https://` upstream is dialled with TLS, and **its certificate is not verified** — a homelab upstream behind a self-signed certificate works, and so does an impostor. |
67
+ | `url` | For `target: "external"`, e.g. `http://10.0.0.5:8080`. The port is optional: without one the scheme's own default is used (`:80` for `http:`, `:443` for `https:`). An `https://` upstream is dialled with TLS, and **its certificate is not verified** — a homelab upstream behind a self-signed certificate works, and so does an impostor. |
68
68
  | `path` | Optional prefix, so one hostname can serve several apps. |
69
69
  | `tls` | `auto` (default), `off`, `manual`. |
70
70
 
@@ -79,7 +79,7 @@ refused.
79
79
 
80
80
  | `tls` | What it means |
81
81
  | --- | --- |
82
- | `auto` | The engine decides. A public name gets a Let's Encrypt certificate (HTTP-01 or TLS-ALPN-01, with ZeroSSL as fallback and renewal in the background). A local-only name gets the engine's own locally-trusted CA. |
82
+ | `auto` | The engine decides. A public name gets a Let's Encrypt certificate (HTTP-01 or TLS-ALPN-01, with renewal in the background). A local-only name gets the engine's own locally-trusted CA. |
83
83
  | `off` | Plain HTTP on the http port, no certificate. |
84
84
  | `manual` | One of the uploaded pairs, whichever covers the hostname (the engine picks by SNI). A route set to this with no pair covering it is refused, rather than quietly given a certificate from somewhere else. |
85
85
 
@@ -115,9 +115,9 @@ back asks the CA instead of serving the old pair. A **disabled** route keeps its
115
115
  certificate: it is still configured, and switching it back on should not cost a new
116
116
  issuance.
117
117
 
118
- The wait can be shortened by giving the engine's own issuer a shorter `lifetime` in the
119
- generated policy; the row reads the interval from the certificate, so the confirmation
120
- follows whatever is configured.
118
+ The panel derives that wait from the certificate itself: certmagic renews once a third of
119
+ the lifetime is left, so two thirds of it is the wait — about 8 hours for the engine's own
120
+ 12-hour CA. The interval is read, never configured, so there is no knob to shorten it.
121
121
 
122
122
  A hostname **no route claims** gets a page saying so, on both ports — not a redirect into
123
123
  a handshake that cannot finish. A visitor with no hostname at all (a bare IP on the HTTPS
package/docs/SERVERS.md CHANGED
@@ -186,8 +186,9 @@ normal process, so it is still subject to:
186
186
  own lifecycle to be the only thing that decides.
187
187
  - **A container.** Docker stops everything in the container's PID namespace, so persistence means the
188
188
  panel's lifetime inside that container, not the host's.
189
- - **Windows, on the forced path.** `taskkill /T` walks the parent tree, and `down --force` uses it;
190
- the graceful path (which is what `down` normally takes) leaves a persistent entry alone.
189
+ - **Windows, on the forced path.** `taskkill /T` walks the parent tree, and `down` takes that path
190
+ automatically when the panel has not exited 20s after the shutdown request; the graceful path
191
+ (which is what `down` normally takes) leaves a persistent entry alone.
191
192
 
192
193
  ## Editing fields
193
194
 
@@ -132,14 +132,14 @@ naming one that does not exist is a `404 UNKNOWN_WORKSPACE`, never a silent fall
132
132
  | `GET /api/events` | **the live feed**: `hello` carries the full state, then `state`, `server`, `log` |
133
133
  | `GET /api/servers/:id/stream` | one server's `server` + `log` frames |
134
134
  | `POST /api/servers/:id/{start,stop,restart}`, `/api/servers/{start-all,stop-all}` | lifecycle (workspace-scoped) |
135
- | `POST /api/servers/:id/free-port` | ask whatever holds that server's port to stop (`403`-safe: supervised listeners are refused) |
135
+ | `POST /api/servers/:id/free-port` | ask whatever holds that server's port to stop (`409` when nothing can be freed — a supervised listener is refused, never killed) |
136
136
  | `GET` / `POST /api/servers`, `PATCH` / `DELETE /api/servers/:id` | the entries themselves, in one workspace |
137
137
  | `GET /api/logs`, `/api/logs/:id?tail=&search=`, `/api/logs/:id/download?file=` | persisted logs, for one workspace |
138
138
  | `GET` / `PATCH /api/settings` | the panel-wide settings (`control.label`, host thresholds, backups, UI) |
139
139
  | `GET` / `PATCH /api/settings/workspace` | one workspace's settings: server defaults, log retention, notifications |
140
140
  | `POST` / `DELETE /api/settings/ui` | install or revert a UI — what Global settings calls |
141
141
  | `POST` / `DELETE /api/settings/tls` | upload or clear a PEM pair |
142
- | `GET` / `PATCH /api/proxy`, `POST /api/proxy/{engine,start,stop,apply,revert}`, `PUT` / `DELETE /api/proxy/tls` | the panel-wide reverse proxy: engine, route table, its own PEM pair. Its live view also rides in the state frame as an optional `proxy` — read it defensively |
142
+ | `GET` / `PATCH /api/proxy`, `POST /api/proxy/{engine,start,stop,apply,revert}`, `PUT` / `DELETE /api/proxy/certificates/:id`, `POST /api/proxy/routes/:id/retry-certificate` | the panel-wide reverse proxy: engine, route table, its uploaded PEM pairs. Its live view also rides in the state frame as an optional `proxy` — read it defensively |
143
143
  | `GET` / `POST /api/backups`, `/api/backups/restore`, `/api/backups/:name/download` | archives; entries are global (`global:settings`, `global:secrets`, `global:tls`) or per workspace, whose leaves are `workspace:<id>:settings`, `:servers`, `:secrets` plus `data:<path>`; a create/restore body `include` selects them |
144
144
  | `POST` / `DELETE /api/notifications/token`, `/api/notifications/test`, `/detect-chats` | Telegram, per workspace |
145
145
  | `POST /api/auth/login`, `GET /api/auth/session`, `POST /api/auth/logout` | the session |
@@ -163,8 +163,9 @@ and `GET /api/settings` includes `ui` — which UI is being served, and its meta
163
163
 
164
164
  An entry body is partial by design: `POST /api/servers` and `PATCH /api/servers/:id` take only the
165
165
  fields the person decided, and the workspace's **Server defaults** fill the rest. Sending a value the
166
- person never chose freezes it against those defaults, so build the body as a diff
167
- (`inheritBaseline` and `diffFields` in `src/shared/patch-diff.ts`).
166
+ person never chose freezes it against those defaults, so build the body as a diff: `diffFields` comes
167
+ from `src/shared/patch-diff.ts`, while comparing against the defaults (`inheritBaseline`) is each
168
+ UI's own job — see `uis/stock/src/components/server/addServerForm.ts`.
168
169
 
169
170
  ### Failures
170
171
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "home-hosted",
3
3
  "type": "module",
4
- "version": "0.7.4",
4
+ "version": "0.7.6",
5
5
  "packageManager": "pnpm@12.5.1",
6
6
  "description": "Self-hosted control panel that keeps your home-server processes alive: supervision, restarts, port conflicts, logs — and a UI you can replace.",
7
7
  "author": "NamesMT <dangquoctrung123@gmail.com>",