@monster-orange/den 0.4.25 → 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 +55 -0
- package/docs/distributions.md +74 -20
- package/package.json +1 -1
- package/src/shared/agents/runtime.ts +2 -2
- package/src/shared/hub.ts +304 -82
- package/src/shared/secrets/onepassword.ts +135 -20
- package/src/ui/cli/agent-ops.ts +17 -3
- package/src/ui/cli/doctor-command.ts +11 -2
- package/src/ui/server/agent-routes.ts +79 -1
- package/src/ui/server/hub-connect.ts +433 -0
- package/src/ui/server/public/i18n/es.js +2 -0
- package/src/ui/server/public/i18n/ja.js +2 -0
- package/src/ui/server/public/settings-registry.js +196 -33
- package/src/ui/server/public/settings.html +23 -0
- package/src/ui/server/public/shell.js +1 -0
- package/src/ui/server/public/topbar.js +5 -1
- package/src/ui/server/route-classes.ts +17 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,61 @@ 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
|
+
|
|
48
|
+
## [0.4.26] - 2026-11-10
|
|
49
|
+
|
|
50
|
+
### Security
|
|
51
|
+
|
|
52
|
+
- **A secret saved to 1Password is never on a command line.** `op`
|
|
53
|
+
wrote the value as an argument (`field[password]=<value>`), which any
|
|
54
|
+
process on the machine can read while `op` runs. Saving the admin
|
|
55
|
+
password (and every other 1Password write) now reads the item as JSON,
|
|
56
|
+
changes the one field and passes it on `op`'s stdin (`op item edit`, or
|
|
57
|
+
`op item create -` for a new item). The item's other fields are kept.
|
|
58
|
+
Nothing to change in config. A sweep of Den's other commands found no
|
|
59
|
+
other secret in argv: sudo and Doppler already read theirs on stdin,
|
|
60
|
+
and agent keys go in the environment.
|
|
61
|
+
|
|
7
62
|
## [0.4.25] - 2026-11-10
|
|
8
63
|
|
|
9
64
|
### Added
|
package/docs/distributions.md
CHANGED
|
@@ -913,9 +913,52 @@ later plugins.
|
|
|
913
913
|
|
|
914
914
|
## Hub
|
|
915
915
|
|
|
916
|
-
|
|
917
|
-
it can search Hub and publish docs and mocks there.
|
|
918
|
-
|
|
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 (
|
|
932
|
-
|
|
933
|
-
|
|
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
|
|
936
|
-
headers naming the caller:
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
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
|
|
948
|
-
it to `false` and Hub's tools ask before they run, like any tool.
|
|
949
|
-
explicit deny in the install's own Claude Code permissions still
|
|
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
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
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
|
@@ -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
|
|
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:
|
|
356
|
+
url: mcp.hub.url,
|
|
357
357
|
headers: mcp.hub.headers,
|
|
358
358
|
},
|
|
359
359
|
}
|