@monster-orange/den 0.2.8 → 0.4.0

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.
Files changed (158) hide show
  1. package/CHANGELOG.md +1731 -0
  2. package/README.md +4 -2
  3. package/bin/den +2 -1
  4. package/docs/distributions.md +730 -6
  5. package/make/den.mk +19 -4
  6. package/make/journeys.mk +2 -1
  7. package/make/local_dev.mk +6 -13
  8. package/make/secrets-1password.mk +18 -0
  9. package/make/test.mk +1 -1
  10. package/package.json +12 -2
  11. package/schemas/den.plugin.v1.json +156 -0
  12. package/schemas/den.theme.v1.json +269 -0
  13. package/scripts/auth-configure.ts +16 -8
  14. package/scripts/heal-config.ts +0 -5
  15. package/scripts/setup-1password.ts +41 -19
  16. package/scripts/setup-secrets.ts +67 -101
  17. package/src/pillars/api/global-setup.ts +1 -1
  18. package/src/pillars/journeys/sandbox.ts +23 -18
  19. package/src/pillars/journeys/tools/browser-session.ts +2 -2
  20. package/src/scripts/setup-default-workspace.ts +2 -2
  21. package/src/shared/agents/default-pack/be-dev.md +20 -0
  22. package/src/shared/agents/default-pack/devops.md +14 -0
  23. package/src/shared/agents/default-pack/fe-dev.md +20 -0
  24. package/src/shared/agents/default-pack/orchestrator.md +16 -0
  25. package/src/shared/agents/default-pack/planner.md +17 -0
  26. package/src/shared/agents/default-pack/reviewer.md +14 -0
  27. package/src/shared/agents/default-pack/ux-designer.md +15 -0
  28. package/src/shared/agents/den-claude.ts +173 -0
  29. package/src/shared/agents/generic.ts +52 -0
  30. package/src/shared/agents/personas.ts +218 -0
  31. package/src/shared/agents/records.ts +118 -0
  32. package/src/shared/agents/runtime.ts +192 -0
  33. package/src/shared/agents/runtimes.ts +47 -0
  34. package/src/shared/auth/headless-login.ts +1 -1
  35. package/src/shared/auth/sudo-vault.ts +93 -31
  36. package/src/shared/auth/token-providers/index.ts +7 -3
  37. package/src/shared/brand.ts +7 -0
  38. package/src/shared/config-error.ts +33 -3
  39. package/src/shared/constants.ts +3 -24
  40. package/src/shared/den-config.ts +257 -5
  41. package/src/shared/edge/config.ts +147 -21
  42. package/src/shared/edge/exec.ts +31 -0
  43. package/src/shared/edge/included.ts +169 -0
  44. package/src/shared/edge/render.ts +69 -14
  45. package/src/shared/edge/runtime.ts +128 -121
  46. package/src/shared/edge/status.ts +68 -8
  47. package/src/shared/edge/tls.ts +328 -0
  48. package/src/shared/edge/types.ts +25 -9
  49. package/src/shared/engine.ts +23 -0
  50. package/src/shared/environment-manager/default-workspace.ts +16 -1
  51. package/src/shared/environment-manager/health.ts +73 -38
  52. package/src/shared/environment-manager/scope.ts +168 -0
  53. package/src/shared/environment-manager/service-runner.ts +789 -43
  54. package/src/shared/environment-manager/up-targets.ts +132 -0
  55. package/src/shared/environment-manager/workspaces.ts +19 -0
  56. package/src/shared/health/rollup.ts +48 -0
  57. package/src/shared/open-url.ts +21 -2
  58. package/src/shared/org-sources.ts +78 -59
  59. package/src/shared/org.ts +53 -5
  60. package/src/shared/plugins/manifest.ts +406 -0
  61. package/src/shared/plugins/store.ts +358 -0
  62. package/src/shared/process/legacy-adopt.ts +285 -0
  63. package/src/shared/process/process-group.ts +202 -0
  64. package/src/shared/process/spawn-streaming.ts +7 -0
  65. package/src/shared/secret-env.ts +70 -0
  66. package/src/shared/secrets/doppler.ts +1 -1
  67. package/src/shared/secrets/index.ts +279 -50
  68. package/src/shared/secrets/none.ts +56 -0
  69. package/src/shared/secrets/strategies.ts +202 -0
  70. package/src/shared/secrets/types.ts +1 -1
  71. package/src/shared/sessions/client.ts +277 -0
  72. package/src/shared/sessions/den-pty.ts +97 -0
  73. package/src/shared/sessions/env.ts +79 -0
  74. package/src/shared/sessions/host.ts +667 -0
  75. package/src/shared/sessions/names.ts +85 -0
  76. package/src/shared/sessions/paths.ts +27 -0
  77. package/src/shared/sessions/protocol.ts +72 -0
  78. package/src/shared/sessions/pty.ts +141 -0
  79. package/src/shared/sessions/ring-buffer.ts +160 -0
  80. package/src/shared/sessions/types.ts +81 -0
  81. package/src/shared/smoke/git-remote.ts +40 -0
  82. package/src/shared/stacks/manifest-commands.ts +1 -1
  83. package/src/shared/stacks/namespace.ts +178 -0
  84. package/src/shared/stacks/owners.ts +303 -0
  85. package/src/shared/stacks/render.ts +8 -3
  86. package/src/shared/stacks/runtime.ts +100 -16
  87. package/src/shared/stacks/status.ts +63 -12
  88. package/src/shared/strategies/registry.ts +89 -0
  89. package/src/shared/theme/contract.ts +538 -0
  90. package/src/shared/types/index.ts +12 -3
  91. package/src/ui/cli/agents-command.ts +812 -0
  92. package/src/ui/cli/create.ts +24 -7
  93. package/src/ui/cli/doctor-command.ts +260 -0
  94. package/src/ui/cli/edge-command.ts +56 -10
  95. package/src/ui/cli/env-probe.ts +266 -0
  96. package/src/ui/cli/flag-parser.ts +18 -5
  97. package/src/ui/cli/health-display.ts +25 -0
  98. package/src/ui/cli/index.ts +580 -60
  99. package/src/ui/cli/notice.ts +20 -0
  100. package/src/ui/cli/plugin-command.ts +849 -0
  101. package/src/ui/cli/sessions-command.ts +718 -0
  102. package/src/ui/cli/stack-command.ts +63 -2
  103. package/src/ui/cli/test-runner.ts +11 -9
  104. package/src/ui/cli/theme-command.ts +136 -0
  105. package/src/ui/cli/web-command.ts +47 -23
  106. package/src/ui/mcp/api.ts +28 -2
  107. package/src/ui/mcp/scope.ts +145 -20
  108. package/src/ui/mcp/server.ts +27 -2
  109. package/src/ui/mcp/tools.ts +94 -12
  110. package/src/ui/server/appearance-prefs.ts +95 -0
  111. package/src/ui/server/audit.ts +35 -0
  112. package/src/ui/server/daemon-reaper.ts +29 -1
  113. package/src/ui/server/engine-stamp.ts +83 -0
  114. package/src/ui/server/github-service.ts +23 -44
  115. package/src/ui/server/graph-page.ts +20 -0
  116. package/src/ui/server/graph-prefs.ts +44 -1
  117. package/src/ui/server/http-errors.ts +293 -0
  118. package/src/ui/server/http-helpers.ts +22 -3
  119. package/src/ui/server/index.ts +539 -51
  120. package/src/ui/server/public/appearance.js +531 -0
  121. package/src/ui/server/public/edge-page.js +248 -0
  122. package/src/ui/server/public/edge.html +251 -0
  123. package/src/ui/server/public/environments.html +65 -83
  124. package/src/ui/server/public/error-page.js +247 -0
  125. package/src/ui/server/public/error.html +260 -0
  126. package/src/ui/server/public/graph-model.js +332 -14
  127. package/src/ui/server/public/graph.css +141 -47
  128. package/src/ui/server/public/graph.js +223 -44
  129. package/src/ui/server/public/header.js +396 -600
  130. package/src/ui/server/public/health-fit.js +248 -0
  131. package/src/ui/server/public/health-rollup.js +128 -0
  132. package/src/ui/server/public/i18n/es.js +287 -0
  133. package/src/ui/server/public/i18n/ja.js +276 -0
  134. package/src/ui/server/public/index.html +139 -438
  135. package/src/ui/server/public/local-dev.html +3468 -4044
  136. package/src/ui/server/public/logs.html +71 -208
  137. package/src/ui/server/public/panel.js +14 -2
  138. package/src/ui/server/public/release.html +175 -389
  139. package/src/ui/server/public/services.html +596 -770
  140. package/src/ui/server/public/settings-page.js +759 -0
  141. package/src/ui/server/public/settings-registry.js +521 -0
  142. package/src/ui/server/public/settings.html +590 -0
  143. package/src/ui/server/public/shell.js +3869 -0
  144. package/src/ui/server/public/topbar.js +1413 -0
  145. package/src/ui/server/public/version-label.js +12 -0
  146. package/src/ui/server/public/workspace-picker.js +74 -34
  147. package/src/ui/server/readonly-routes.ts +37 -3
  148. package/src/ui/server/services-list.ts +94 -17
  149. package/src/ui/server/settings-distribution.ts +74 -0
  150. package/src/ui/server/shell-prefs.ts +192 -0
  151. package/src/ui/server/theme-routes.ts +292 -0
  152. package/src/ui/server/theme-runtime.ts +407 -0
  153. package/src/ui/server/ui-assets.ts +16 -1
  154. package/src/ui/server/ui-language.ts +50 -0
  155. package/src/ui/server/workspace-routes.ts +48 -18
  156. package/themes/den/den-theme.json +72 -0
  157. package/themes/den/favicon.ico +0 -0
  158. package/themes/den/mark.svg +6 -0
@@ -10,13 +10,23 @@ import { readCatalog } from "../environment-manager/catalog.js";
10
10
  import { readEdgeConfig } from "../edge/config.js";
11
11
  import { routeUrl } from "../edge/render.js";
12
12
  import {
13
+ getActiveWorkspaces,
13
14
  getFocusedWorkspaceName,
14
15
  getWorkspaceByName,
15
16
  listWorkspaceServices,
16
17
  } from "../environment-manager/workspaces.js";
17
18
  import { readManifestStacks, readStacks } from "./config.js";
18
- import { projectName, stackWorkspace } from "./render.js";
19
- import { stackHealth, type StackContext } from "./runtime.js";
19
+ import { STACK_NAMESPACE_RE } from "../den-config.js";
20
+ import {
21
+ resolveStackNamespace,
22
+ type StackNamespaceSource,
23
+ } from "./namespace.js";
24
+ import { projectName } from "./render.js";
25
+ import {
26
+ rejoinEdgeNetworks,
27
+ stackHealth,
28
+ type StackContext,
29
+ } from "./runtime.js";
20
30
 
21
31
  export interface StackRoute {
22
32
  name: string;
@@ -38,40 +48,81 @@ export interface StackStatus {
38
48
  health?: { ok: boolean | null; detail: string };
39
49
  }
40
50
 
41
- const WS_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
42
-
43
51
  /**
44
52
  * The den workspace stacks read their manifests from, and the Compose
45
53
  * project suffix they run under. `denWorkspace` defaults to the CLI's
46
- * -w override, then the focused workspace, then `default`.
54
+ * -w override, then the focused workspace, then `default`. The suffix is
55
+ * the workspace's stack namespace (namespace.ts); DEN_STACK_WORKSPACE, a
56
+ * per-command override, wins over it for this one process (source `env`).
57
+ *
58
+ * The one place a den workspace becomes a Compose project suffix: every
59
+ * stack path (status, runtime, health, container lookup) comes through here.
47
60
  */
48
61
  export function resolveStackWorkspaces(
49
62
  denWorkspace?: string | null,
50
63
  env: NodeJS.ProcessEnv = process.env,
51
- ): { denWorkspace: string; stackWorkspace: string } {
64
+ ): {
65
+ denWorkspace: string;
66
+ stackWorkspace: string;
67
+ source: StackNamespaceSource | "env";
68
+ } {
52
69
  const fkWs =
53
70
  denWorkspace ||
54
71
  env.DEN_WORKSPACE_OVERRIDE ||
55
72
  getFocusedWorkspaceName() ||
56
73
  "default";
57
- const ws = env.DEN_STACK_WORKSPACE || stackWorkspace(fkWs);
58
- if (!WS_RE.test(ws))
74
+ const override = env.DEN_STACK_WORKSPACE;
75
+ const resolved = override ? null : resolveStackNamespace(fkWs);
76
+ const ws = override || resolved!.namespace;
77
+ if (!STACK_NAMESPACE_RE.test(ws))
59
78
  throw new Error(
60
79
  `workspace "${ws}" must be lowercase letters, digits and dashes`,
61
80
  );
62
- return { denWorkspace: fkWs, stackWorkspace: ws };
81
+ return {
82
+ denWorkspace: fkWs,
83
+ stackWorkspace: ws,
84
+ source: resolved ? resolved.source : "env",
85
+ };
63
86
  }
64
87
 
65
88
  /** The edge, the known stacks and the project suffix for one workspace. */
66
89
  export function loadStackContext(denWorkspace?: string | null): StackContext {
67
- const { denWorkspace: fkWs, stackWorkspace: ws } =
68
- resolveStackWorkspaces(denWorkspace);
90
+ const {
91
+ denWorkspace: fkWs,
92
+ stackWorkspace: ws,
93
+ source,
94
+ } = resolveStackWorkspaces(denWorkspace);
69
95
  const edge = readEdgeConfig();
70
96
  // Repo manifests come from that den workspace's checkouts.
71
97
  const stacks = readStacks(undefined, {
72
98
  workspace: getWorkspaceByName(fkWs) ? fkWs : undefined,
73
99
  });
74
- return { edge, stacks, workspace: ws };
100
+ return {
101
+ edge,
102
+ stacks,
103
+ workspace: ws,
104
+ denWorkspace: fkWs,
105
+ namespaceSource: source,
106
+ };
107
+ }
108
+
109
+ /**
110
+ * After edge up: the edge back on the routed networks of every running
111
+ * stack it routes (rejoinEdgeNetworks), across the focused and active
112
+ * workspaces' stack namespaces. A workspace whose stacks cannot be read is
113
+ * skipped.
114
+ */
115
+ export function rejoinRunningStacks(
116
+ onLine: (line: string) => void = console.log,
117
+ ): string[] {
118
+ const contexts: StackContext[] = [];
119
+ for (const ws of new Set([null, ...getActiveWorkspaces()]))
120
+ try {
121
+ contexts.push(loadStackContext(ws));
122
+ } catch {
123
+ /* unreadable: nothing of it to rejoin */
124
+ }
125
+ return rejoinEdgeNetworks(contexts, onLine);
75
126
  }
76
127
 
77
128
  /** Each stack's name, project, routes and (optionally) container health. */
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Strategy registry: every concern that varies by distribution (secrets
3
+ * backend today; TLS and others next) is a strategy, and Den's built-ins
4
+ * register here exactly as a plugin would. An entry is
5
+ * `{ id, kind, detect(), capabilities }`:
6
+ *
7
+ * - `kind` names the concern ("secrets"); ids are unique per kind;
8
+ * - `detect()` is cheap and side-effect free: it never prompts, never
9
+ * spawns a CLI that could prompt, and never prints a secret. It says
10
+ * whether the strategy can work on this machine, and why not;
11
+ * - `capabilities` is the kind's own interface (a factory, optional setup,
12
+ * optional env injection, ...).
13
+ *
14
+ * No plugin loading happens here: a future plugin kind calls
15
+ * registerStrategy() with its entry.
16
+ */
17
+ import * as fs from "fs";
18
+ import * as path from "path";
19
+
20
+ export interface DetectResult {
21
+ available: boolean;
22
+ /** Why the strategy is unavailable, or a note (e.g. "not configured"). */
23
+ reason?: string;
24
+ }
25
+
26
+ export interface StrategyEntry<K extends string = string, C = unknown> {
27
+ id: string;
28
+ kind: K;
29
+ detect(env?: NodeJS.ProcessEnv): DetectResult;
30
+ capabilities: C;
31
+ }
32
+
33
+ const registries = new Map<string, Map<string, StrategyEntry>>();
34
+
35
+ /** Register (or replace) a strategy under its kind. */
36
+ export function registerStrategy<K extends string, C>(
37
+ entry: StrategyEntry<K, C>,
38
+ ): void {
39
+ let byId = registries.get(entry.kind);
40
+ if (!byId) {
41
+ byId = new Map();
42
+ registries.set(entry.kind, byId);
43
+ }
44
+ byId.set(entry.id, entry as StrategyEntry);
45
+ }
46
+
47
+ /** The strategy `id` of `kind`, or undefined. */
48
+ export function getStrategy<K extends string, C>(
49
+ kind: K,
50
+ id: string,
51
+ ): StrategyEntry<K, C> | undefined {
52
+ return registries.get(kind)?.get(id) as StrategyEntry<K, C> | undefined;
53
+ }
54
+
55
+ /** Every kind with a registered strategy, in registration order. */
56
+ export function strategyKinds(): string[] {
57
+ return [...registries.keys()];
58
+ }
59
+
60
+ /** Every registered id of `kind`, in registration order. */
61
+ export function strategyIds(kind: string): string[] {
62
+ return [...(registries.get(kind)?.keys() ?? [])];
63
+ }
64
+
65
+ /**
66
+ * True when an executable named `bin` is on `env.PATH`. A file check only:
67
+ * nothing is run, so it can never prompt (Touch ID, a login) or print.
68
+ */
69
+ export function onPath(
70
+ bin: string,
71
+ env: NodeJS.ProcessEnv = process.env,
72
+ ): boolean {
73
+ const exts =
74
+ process.platform === "win32"
75
+ ? (env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";")
76
+ : [""];
77
+ for (const dir of (env.PATH ?? "").split(path.delimiter)) {
78
+ if (!dir) continue;
79
+ for (const ext of exts) {
80
+ try {
81
+ fs.accessSync(path.join(dir, bin + ext), fs.constants.X_OK);
82
+ if (fs.statSync(path.join(dir, bin + ext)).isFile()) return true;
83
+ } catch {
84
+ /* not here */
85
+ }
86
+ }
87
+ }
88
+ return false;
89
+ }