@monster-orange/den 0.4.26 → 0.4.27

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
@@ -4,6 +4,47 @@ All notable changes to Den are documented here. Each release lists the
4
4
  config and manifest changes a distribution must make to move to it under
5
5
  **Migrations**.
6
6
 
7
+ ## [0.4.27] - 2026-11-10
8
+
9
+ ### Added
10
+
11
+ - **Connect to Hub (HUB-1.7).** Settings › Agents › Hub has **Connect**:
12
+ type Hub's address, sign in on Hub, pick the company and approve this
13
+ install, and you come back connected. Nobody copies a token or edits
14
+ config. Den uses PKCE and a single-use state; the token goes to the
15
+ install's own secrets store (1Password or Doppler), else to a 0600
16
+ file in Den's state dir, and never to a page, log or command line.
17
+ **Disconnect** revokes it on Hub first. A token Hub no longer accepts
18
+ shows **Reconnect**; a role that may no longer connect says to ask a
19
+ Hub admin. The row shows the company (a link), your role, who signed
20
+ in and this install. Doctor's Hub row names the company and role.
21
+ - Agents' Hub MCP server uses Hub's own `mcp_url` from Connect, and
22
+ sends `X-Den-Agent-Id` (the agent's stable id) for attribution.
23
+
24
+ ### Changed
25
+
26
+ - Hub status comes from Hub's `GET /connect/whoami` (it was the
27
+ `hub_whoami` MCP tool).
28
+
29
+ ### Fixed
30
+
31
+ - **Saving to 1Password never makes a second item.** A save created a
32
+ new item whenever reading the old one failed, even for a timeout, so a
33
+ slow `op` could leave two items with one title (which `op` then
34
+ refuses). It now creates only when `op` says the item isn't there, and
35
+ otherwise shows `op`'s reason. A failed create shows create's own
36
+ reason (say, a vault that isn't available), not "isn't an item".
37
+ - `op`'s `[ERROR] <date> <time>` prefix is gone from the messages Den
38
+ shows.
39
+ - After the admin password is saved to the install's store, the note
40
+ says so: "Admin password kept for this session and saved to <store>".
41
+
42
+ ### Migrations
43
+
44
+ - None. A `hub.token` set by hand keeps working. `hub.token` may now
45
+ also be a source (`file:`, `keychain:`, `env:`), and `hub.mcp_url` is
46
+ new and optional.
47
+
7
48
  ## [0.4.26] - 2026-11-10
8
49
 
9
50
  ### Security
@@ -913,9 +913,52 @@ later plugins.
913
913
 
914
914
  ## Hub
915
915
 
916
- With `hub.url` set, every agent Den launches gets Hub's tools (HUB-1.5):
917
- it can search Hub and publish docs and mocks there. Without `hub.url`,
918
- nothing changes and nothing about Hub shows.
916
+ Connect an install to your company's Hub and every agent Den launches
917
+ gets Hub's tools: it can search Hub and publish docs and mocks there.
918
+ Without it, nothing about agents changes.
919
+
920
+ ### Connect to Hub (HUB-1.7)
921
+
922
+ Settings › Agents › Hub: type Hub's address (or keep the one the
923
+ distribution set in `hub.url`) and press **Connect**. Hub opens; sign
924
+ in, pick the company and approve this install. Hub sends you back to
925
+ Settings, connected. Nobody copies a token or edits config.
926
+
927
+ - Den makes a PKCE verifier (S256) and a single-use state and keeps both
928
+ in memory for 10 minutes. Hub's answer comes back to
929
+ `<this Den>/hub/callback`, which trades the one-time code for the
930
+ install's token server to server (`POST <hub>/connect/token`). A
931
+ replayed or old state changes nothing.
932
+ - `/hub/callback` needs no sign-in: the session cookie is SameSite
933
+ Strict, so Hub's redirect doesn't carry it. The state this server
934
+ issued to a signed-in Connect, and the verifier only it holds, are
935
+ what protect it. It then moves on to Settings by script, which carries
936
+ the cookie again.
937
+ - Hub can only send the person back to https or to this machine, so
938
+ open Den over https (its edge address) or on localhost to Connect.
939
+ - This install's label on Hub is `<cli> on <machine>`.
940
+ - The token is the install's (SEC-0), kept in the install's own secrets
941
+ store when it keeps secrets: a 1Password item `<Product> Hub token`
942
+ (field `token`), or a Doppler key `<PREFIX>_HUB_TOKEN`. Otherwise Den
943
+ keeps it in `<state dir>/hub/token` (mode 0600, folder 0700). It goes
944
+ to the store on stdin or into the file, never in a command line, and
945
+ never to a page, a log or an API answer. If it can't be kept, Den
946
+ revokes it on Hub at once.
947
+ - Connect writes `hub.url` (Hub's own address), `hub.token` (the store
948
+ ref, or `file:<path>`) and `hub.mcp_url` (Hub's MCP address, as given)
949
+ to `config/local/user.yml`.
950
+ - **Disconnect** revokes the token on Hub (`POST <hub>/connect/revoke`),
951
+ then removes it here and clears `hub.token` and `hub.mcp_url`;
952
+ `hub.url` stays, so Connect is one click. If Hub can't be reached,
953
+ nothing is removed; **Remove it here anyway** removes it, and says the
954
+ token still works on Hub until an admin revokes the install.
955
+ - A token Hub no longer accepts (revoked, or replaced by a newer
956
+ connect) shows **Reconnect**. A role that may no longer connect Den
957
+ installs says to ask a Hub admin; Den never retries it.
958
+
959
+ ### Config
960
+
961
+ A distribution can preset Hub's address, or set everything by hand:
919
962
 
920
963
  ```yaml
921
964
  # config/local/user.yml (or the org config; user.yml wins)
@@ -923,20 +966,27 @@ hub:
923
966
  url: https://hub.example.com
924
967
  token: { vault: Private, item: Acme Hub, field: token }
925
968
  # or the name of a secrets.refs entry: token: hub_install
969
+ # or a source: token: "file:/path/to/token" (also keychain:, env:)
970
+ mcp_url: https://hub.example.com/mcp # default: <url>/mcp
926
971
  allow_tools: true # the default: agents use Hub's tools without asking
927
972
  ```
928
973
 
929
974
  - `hub.url` must be https. Plain http works only to this machine
930
- (`localhost`, `*.localhost`).
931
- - `hub.token` is this install's Hub token (`hubi_…`, one per install,
932
- made in Hub), as a ref in this install's own secrets store
933
- (`secrets.provider`). Den never assumes a vault, item or field for it.
975
+ (`localhost`, `127.0.0.1`, `*.localhost`).
976
+ - `hub.token` is this install's Hub token (one per install), as a ref in
977
+ this install's own secrets store (`secrets.provider`) or a source. Den
978
+ never assumes a vault, item or field for it.
979
+
980
+ ### What agents get
981
+
934
982
  - Each agent's MCP config gets a server named `hub`: Streamable HTTP at
935
- `<hub.url>/mcp`, with `Authorization: Bearer <token>` and four plain
936
- headers naming the caller: `X-Den-Agent` (its name), `X-Den-Session`
937
- (a new opaque id per launch), `X-Den-Workspace` and `X-Den-Repos` (the
938
- workspace's repos, `owner/repo`, comma-separated). Hub sets the team
939
- from the token and the project from the repos.
983
+ `hub.mcp_url` (default `<hub.url>/mcp`), with
984
+ `Authorization: Bearer <token>` and plain headers naming the caller:
985
+ `X-Den-Agent` (its name), `X-Den-Agent-Id` (its stable id, which Hub
986
+ keys attribution on), `X-Den-Session` (a new opaque id per launch),
987
+ `X-Den-Workspace` and `X-Den-Repos` (the workspace's repos,
988
+ `owner/repo`, comma-separated). Hub sets the company from the token
989
+ and the project from the repos.
940
990
  - Its prompt gets one line: "You can search Hub and publish docs and
941
991
  mocks there with the hub\_\* tools; your team and project are set from
942
992
  this Den install."
@@ -944,18 +994,22 @@ hub:
944
994
  in a command line, a record, a log, a page or an API answer.
945
995
  - `hub.allow_tools` (default `true`): agents use Hub's tools without
946
996
  asking (Den allows `mcp__hub` for every agent it launches). The token
947
- limits writes to this install's team, and Hub keeps every version. Set
948
- it to `false` and Hub's tools ask before they run, like any tool. An
949
- explicit deny in the install's own Claude Code permissions still wins.
950
- Settings › Agents › Hub has the checkbox (it saves to
997
+ limits writes to this install's company, and Hub keeps every version.
998
+ Set it to `false` and Hub's tools ask before they run, like any tool.
999
+ An explicit deny in the install's own Claude Code permissions still
1000
+ wins. Settings › Agents › Hub has the checkbox (it saves to
951
1001
  `config/local/user.yml`).
952
1002
  - A Hub that is down, or a token that can't be read, never stops an
953
1003
  agent: it starts without Hub.
954
1004
 
955
- Settings › Agents › Hub shows the URL, connected or not, the team and
956
- this install's label (from Hub's whoami tool), or why it can't connect.
957
- `GET /api/hub` answers the same. `<cli> doctor` has a Hub row: ✓ when
958
- connected, ⚠ with the reason when not. A Hub that is down never fails
1005
+ ### Status
1006
+
1007
+ Settings › Agents › Hub shows Hub's address, connected or not, the
1008
+ company (a link to it on Hub), your role, who signed in and this
1009
+ install's label (from `GET <hub>/connect/whoami`), or why it can't
1010
+ connect. `GET /api/hub` answers the same (never the token). `<cli>
1011
+ doctor` has a Hub row: ✓ when connected, ⚠ with the reason when not,
1012
+ and where to Connect or Reconnect. A Hub that is down never fails
959
1013
  doctor.
960
1014
 
961
1015
  ## doctor
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monster-orange/den",
3
- "version": "0.4.26",
3
+ "version": "0.4.27",
4
4
  "description": "Den: a local multi-repo dev orchestrator, HTTPS edge and E2E harness",
5
5
  "type": "module",
6
6
  "bin": {
@@ -62,7 +62,7 @@ export interface AgentMcp {
62
62
  scope: string;
63
63
  /**
64
64
  * HUB-1.5: Den Hub's MCP server (Streamable HTTP), when hub.url is set:
65
- * its base URL and the headers (the bearer token among them). The
65
+ * its MCP endpoint (HUB-1.7: Hub's mcp_url, default <hub.url>/mcp) and the headers (the bearer token among them). The
66
66
  * headers go only into the agent's own 0600 MCP file, never into argv,
67
67
  * a record, a log or a page.
68
68
  */
@@ -353,7 +353,7 @@ export function mcpConfigJson(mcp: AgentMcp): string {
353
353
  ? {
354
354
  [mcp.hub.name]: {
355
355
  type: "http",
356
- url: `${mcp.hub.url}/mcp`,
356
+ url: mcp.hub.url,
357
357
  headers: mcp.hub.headers,
358
358
  },
359
359
  }