@monster-orange/den 0.0.0 → 0.2.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 (255) hide show
  1. package/CHANGELOG.md +204 -0
  2. package/LICENSE +21 -0
  3. package/README.md +165 -1
  4. package/bin/den +68 -0
  5. package/docs/distributions.md +499 -0
  6. package/make/demo.mk +82 -0
  7. package/make/den.mk +80 -0
  8. package/make/journeys.mk +57 -0
  9. package/make/local_dev.mk +154 -0
  10. package/make/security.mk +59 -0
  11. package/make/test.mk +405 -0
  12. package/package.json +101 -4
  13. package/scripts/auth-configure.ts +415 -0
  14. package/scripts/heal-config.ts +92 -0
  15. package/scripts/jsonl-playwright-reporter.js +70 -0
  16. package/scripts/manifest-read.cjs +91 -0
  17. package/scripts/setup-1password.ts +570 -0
  18. package/scripts/setup-secrets.ts +149 -0
  19. package/scripts/view-results.js +156 -0
  20. package/service/install.sh +112 -0
  21. package/src/pillars/api/fixtures/index.ts +128 -0
  22. package/src/pillars/api/fixtures/openapi-validator.ts +111 -0
  23. package/src/pillars/api/global-setup.ts +103 -0
  24. package/src/pillars/api/playwright.config.ts +105 -0
  25. package/src/pillars/api/schemas/example-api.json +110 -0
  26. package/src/pillars/api/tests/health/health.spec.ts +19 -0
  27. package/src/pillars/api/tests/health/manifest.yml +6 -0
  28. package/src/pillars/browser/fixtures/index.ts +232 -0
  29. package/src/pillars/browser/fixtures/package.json +10 -0
  30. package/src/pillars/browser/global-setup.ts +140 -0
  31. package/src/pillars/browser/global-teardown.ts +48 -0
  32. package/src/pillars/browser/playwright.config.ts +212 -0
  33. package/src/pillars/browser/setup.ts +219 -0
  34. package/src/pillars/journeys/app-config.ts +237 -0
  35. package/src/pillars/journeys/discover.ts +160 -0
  36. package/src/pillars/journeys/hooks/deny-shell.cjs +44 -0
  37. package/src/pillars/journeys/observability/events.ts +288 -0
  38. package/src/pillars/journeys/observability/sdk-mapper.ts +306 -0
  39. package/src/pillars/journeys/report/friction.ts +304 -0
  40. package/src/pillars/journeys/report/junit.ts +105 -0
  41. package/src/pillars/journeys/report/render.ts +273 -0
  42. package/src/pillars/journeys/report/results.ts +323 -0
  43. package/src/pillars/journeys/run.ts +673 -0
  44. package/src/pillars/journeys/runner.ts +1025 -0
  45. package/src/pillars/journeys/sandbox.ts +403 -0
  46. package/src/pillars/journeys/spec/loader.ts +152 -0
  47. package/src/pillars/journeys/spec/schema.ts +208 -0
  48. package/src/pillars/journeys/teardown.ts +98 -0
  49. package/src/pillars/journeys/tools/browser-session.ts +219 -0
  50. package/src/pillars/journeys/tools/browser-tool.ts +914 -0
  51. package/src/pillars/journeys/tools/http-tool.ts +564 -0
  52. package/src/pillars/journeys/tools/ledger.ts +278 -0
  53. package/src/pillars/journeys/tools/snapshot-store.ts +117 -0
  54. package/src/pillars/journeys/verify/assertions.ts +502 -0
  55. package/src/pillars/journeys/verify/verdict.ts +71 -0
  56. package/src/pillars/perf/build-report.ts +36 -0
  57. package/src/pillars/perf/k6.config.js +112 -0
  58. package/src/pillars/perf/run.ts +345 -0
  59. package/src/pillars/perf/scenarios/load-profile.js +97 -0
  60. package/src/pillars/perf/staging.ts +73 -0
  61. package/src/pillars/security/discover.ts +124 -0
  62. package/src/pillars/security/findings.ts +151 -0
  63. package/src/pillars/security/plan.ts +355 -0
  64. package/src/pillars/security/run.ts +757 -0
  65. package/src/pillars/smoke/admin-probe.ts +68 -0
  66. package/src/pillars/smoke/base-url.ts +56 -0
  67. package/src/pillars/smoke/cleanup.ts +8 -0
  68. package/src/pillars/smoke/discover.ts +237 -0
  69. package/src/pillars/smoke/ensure-smoke-teardown.ts +40 -0
  70. package/src/pillars/smoke/fixture-manager.ts +217 -0
  71. package/src/pillars/smoke/fixtures.ts +468 -0
  72. package/src/pillars/smoke/global-setup-all.ts +262 -0
  73. package/src/pillars/smoke/global-setup-global.ts +262 -0
  74. package/src/pillars/smoke/global-setup.ts +273 -0
  75. package/src/pillars/smoke/global-teardown-all.ts +8 -0
  76. package/src/pillars/smoke/global-teardown-global.ts +8 -0
  77. package/src/pillars/smoke/global-teardown.ts +139 -0
  78. package/src/pillars/smoke/playwright-all.config.ts +147 -0
  79. package/src/pillars/smoke/playwright-global.config.ts +141 -0
  80. package/src/pillars/smoke/playwright.config.ts +162 -0
  81. package/src/pillars/smoke/setup-env.ts +132 -0
  82. package/src/pillars/smoke/setup-global.ts +126 -0
  83. package/src/pillars/smoke/setup.ts +115 -0
  84. package/src/pillars/smoke/smoke-repo.ts +16 -0
  85. package/src/pillars/smoke/staging.ts +49 -0
  86. package/src/pillars/suites/run.ts +147 -0
  87. package/src/scripts/configure-aws-profiles.ts +114 -0
  88. package/src/scripts/register-repos.ts +307 -0
  89. package/src/scripts/setup-default-workspace.ts +203 -0
  90. package/src/shared/agent-actor.ts +77 -0
  91. package/src/shared/applications.ts +138 -0
  92. package/src/shared/auth/api-token.ts +416 -0
  93. package/src/shared/auth/auth0-helper.ts +284 -0
  94. package/src/shared/auth/headless-login.ts +265 -0
  95. package/src/shared/auth/jwt-helper.ts +186 -0
  96. package/src/shared/auth/sudo-vault.ts +69 -0
  97. package/src/shared/auth/test-accounts.ts +98 -0
  98. package/src/shared/auth/token-injection.ts +184 -0
  99. package/src/shared/auth/token-providers/auth0.ts +80 -0
  100. package/src/shared/auth/token-providers/index.ts +182 -0
  101. package/src/shared/auth/token-refresh.ts +273 -0
  102. package/src/shared/banner.ts +15 -0
  103. package/src/shared/brand.ts +79 -0
  104. package/src/shared/cli-tabs.ts +131 -0
  105. package/src/shared/constants.ts +128 -0
  106. package/src/shared/den-config.ts +688 -0
  107. package/src/shared/dev-metrics/emit.ts +354 -0
  108. package/src/shared/edge/config.ts +229 -0
  109. package/src/shared/edge/render.ts +221 -0
  110. package/src/shared/edge/runtime.ts +268 -0
  111. package/src/shared/edge/status.ts +74 -0
  112. package/src/shared/edge/types.ts +62 -0
  113. package/src/shared/engine.ts +67 -0
  114. package/src/shared/environment/aws-profiles.ts +49 -0
  115. package/src/shared/environment/env-selector.ts +161 -0
  116. package/src/shared/environment/playwright-env.ts +82 -0
  117. package/src/shared/environment-manager/catalog.ts +77 -0
  118. package/src/shared/environment-manager/clone-guard.ts +163 -0
  119. package/src/shared/environment-manager/dag.ts +286 -0
  120. package/src/shared/environment-manager/default-workspace.ts +182 -0
  121. package/src/shared/environment-manager/derivation/alias.ts +90 -0
  122. package/src/shared/environment-manager/derivation/cache.ts +97 -0
  123. package/src/shared/environment-manager/derivation/derive-graph.ts +421 -0
  124. package/src/shared/environment-manager/derivation/derived-up.ts +354 -0
  125. package/src/shared/environment-manager/derivation/load-alias.ts +11 -0
  126. package/src/shared/environment-manager/derivation/rules-compose.ts +42 -0
  127. package/src/shared/environment-manager/derivation/rules-events.ts +50 -0
  128. package/src/shared/environment-manager/derivation/rules-http.ts +247 -0
  129. package/src/shared/environment-manager/derivation/rules-infra.ts +64 -0
  130. package/src/shared/environment-manager/derivation/rules-readiness.ts +96 -0
  131. package/src/shared/environment-manager/derivation/scan.ts +160 -0
  132. package/src/shared/environment-manager/derivation/text.ts +40 -0
  133. package/src/shared/environment-manager/derivation/types.ts +69 -0
  134. package/src/shared/environment-manager/health.ts +635 -0
  135. package/src/shared/environment-manager/index.ts +6 -0
  136. package/src/shared/environment-manager/load-applications.ts +108 -0
  137. package/src/shared/environment-manager/log-tail.ts +213 -0
  138. package/src/shared/environment-manager/make-targets.ts +78 -0
  139. package/src/shared/environment-manager/opctl.ts +335 -0
  140. package/src/shared/environment-manager/readiness.ts +93 -0
  141. package/src/shared/environment-manager/register-local.ts +72 -0
  142. package/src/shared/environment-manager/secrets-check.ts +260 -0
  143. package/src/shared/environment-manager/service-container.ts +47 -0
  144. package/src/shared/environment-manager/service-env.ts +110 -0
  145. package/src/shared/environment-manager/service-runner.ts +1603 -0
  146. package/src/shared/environment-manager/sync-targets.ts +66 -0
  147. package/src/shared/environment-manager/up-plan.ts +326 -0
  148. package/src/shared/environment-manager/workspace-manager.ts +905 -0
  149. package/src/shared/environment-manager/workspaces.ts +860 -0
  150. package/src/shared/manifest/deps.ts +27 -0
  151. package/src/shared/manifest/merge-override.ts +75 -0
  152. package/src/shared/manifest/migrate-manifest.ts +101 -0
  153. package/src/shared/manifest/placement.ts +321 -0
  154. package/src/shared/manifest/read-manifest.ts +278 -0
  155. package/src/shared/manifest/schema.ts +313 -0
  156. package/src/shared/manifest/service-links.ts +93 -0
  157. package/src/shared/manifest/validate-layers.ts +229 -0
  158. package/src/shared/manifest/validate-manifest.ts +200 -0
  159. package/src/shared/manifest/workspace-manifests.ts +92 -0
  160. package/src/shared/open-url.ts +122 -0
  161. package/src/shared/org.ts +44 -0
  162. package/src/shared/paths.ts +190 -0
  163. package/src/shared/perf/optional-fields.ts +105 -0
  164. package/src/shared/perf/report-normalizer.ts +404 -0
  165. package/src/shared/perf/report-paths.ts +19 -0
  166. package/src/shared/perf/report-store.ts +110 -0
  167. package/src/shared/perf/report-types.ts +70 -0
  168. package/src/shared/perf/test-paths.ts +25 -0
  169. package/src/shared/process/log-rotation.ts +147 -0
  170. package/src/shared/process/spawn-streaming.ts +229 -0
  171. package/src/shared/product.ts +92 -0
  172. package/src/shared/profile.ts +141 -0
  173. package/src/shared/redact.ts +107 -0
  174. package/src/shared/repo-kind.ts +32 -0
  175. package/src/shared/reporting/jsonl-reporter.ts +131 -0
  176. package/src/shared/reporting/slack-reporter.ts +340 -0
  177. package/src/shared/results/result-reader.ts +266 -0
  178. package/src/shared/results/result-writer.ts +168 -0
  179. package/src/shared/secrets/doppler.ts +126 -0
  180. package/src/shared/secrets/env.ts +48 -0
  181. package/src/shared/secrets/index.ts +197 -0
  182. package/src/shared/secrets/keys.ts +33 -0
  183. package/src/shared/secrets/onepassword.ts +75 -0
  184. package/src/shared/secrets/types.ts +52 -0
  185. package/src/shared/service-url.ts +119 -0
  186. package/src/shared/smoke/branch-resolver.ts +141 -0
  187. package/src/shared/smoke/git-remote.ts +70 -0
  188. package/src/shared/smoke/repo-cloner.ts +151 -0
  189. package/src/shared/stacks/config.ts +137 -0
  190. package/src/shared/stacks/manifest-commands.ts +118 -0
  191. package/src/shared/stacks/render.ts +253 -0
  192. package/src/shared/stacks/runtime.ts +334 -0
  193. package/src/shared/stacks/status.ts +99 -0
  194. package/src/shared/stacks/types.ts +53 -0
  195. package/src/shared/terminal/tabs.ts +212 -0
  196. package/src/shared/test-discovery/module-scanner.ts +569 -0
  197. package/src/shared/types/index.ts +701 -0
  198. package/src/shared/ui-marker.ts +19 -0
  199. package/src/ui/cli/applications-command.ts +148 -0
  200. package/src/ui/cli/config-command.ts +68 -0
  201. package/src/ui/cli/create-main.ts +9 -0
  202. package/src/ui/cli/create.ts +360 -0
  203. package/src/ui/cli/edge-command.ts +81 -0
  204. package/src/ui/cli/flag-parser.ts +246 -0
  205. package/src/ui/cli/graph-command.ts +570 -0
  206. package/src/ui/cli/health-display.ts +63 -0
  207. package/src/ui/cli/index.ts +3742 -0
  208. package/src/ui/cli/init.ts +855 -0
  209. package/src/ui/cli/invocation-target.ts +175 -0
  210. package/src/ui/cli/logs-command.ts +104 -0
  211. package/src/ui/cli/mcp-main.ts +13 -0
  212. package/src/ui/cli/mcp-stdout-guard.ts +10 -0
  213. package/src/ui/cli/module-selection.ts +31 -0
  214. package/src/ui/cli/prompts.ts +767 -0
  215. package/src/ui/cli/results-viewer.ts +436 -0
  216. package/src/ui/cli/secrets-preflight.ts +91 -0
  217. package/src/ui/cli/stack-command.ts +117 -0
  218. package/src/ui/cli/stalled-setup-recovery.ts +129 -0
  219. package/src/ui/cli/test-runner.ts +1319 -0
  220. package/src/ui/cli/web-command.ts +1073 -0
  221. package/src/ui/mcp/api.ts +284 -0
  222. package/src/ui/mcp/guards.ts +141 -0
  223. package/src/ui/mcp/server.ts +147 -0
  224. package/src/ui/mcp/tools.ts +565 -0
  225. package/src/ui/server/audit.ts +71 -0
  226. package/src/ui/server/changelog-parser.ts +105 -0
  227. package/src/ui/server/daemon-reaper.ts +129 -0
  228. package/src/ui/server/editor-manager.ts +301 -0
  229. package/src/ui/server/github-service.ts +223 -0
  230. package/src/ui/server/graph-prefs.ts +89 -0
  231. package/src/ui/server/health-row.ts +15 -0
  232. package/src/ui/server/http-helpers.ts +98 -0
  233. package/src/ui/server/index.ts +3350 -0
  234. package/src/ui/server/log-history.ts +453 -0
  235. package/src/ui/server/perf-report.ts +42 -0
  236. package/src/ui/server/public/environments.html +496 -0
  237. package/src/ui/server/public/favicon.ico +0 -0
  238. package/src/ui/server/public/graph-model.js +416 -0
  239. package/src/ui/server/public/graph.css +976 -0
  240. package/src/ui/server/public/graph.js +986 -0
  241. package/src/ui/server/public/header.js +1373 -0
  242. package/src/ui/server/public/index.html +2595 -0
  243. package/src/ui/server/public/local-dev.html +5344 -0
  244. package/src/ui/server/public/logs.html +1496 -0
  245. package/src/ui/server/public/panel.js +787 -0
  246. package/src/ui/server/public/perf-report.js +359 -0
  247. package/src/ui/server/public/release.html +2111 -0
  248. package/src/ui/server/public/services.html +1103 -0
  249. package/src/ui/server/public/workspace-picker.js +69 -0
  250. package/src/ui/server/readonly-routes.ts +200 -0
  251. package/src/ui/server/release-deploy-session.ts +246 -0
  252. package/src/ui/server/release-service.ts +1125 -0
  253. package/src/ui/server/sudo-store.ts +111 -0
  254. package/src/ui/server/ui-assets.ts +73 -0
  255. package/src/ui/server/workspace-routes.ts +2185 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,204 @@
1
+ # Changelog
2
+
3
+ All notable changes to Den are documented here. Each release lists the
4
+ config and manifest changes a distribution must make to move to it under
5
+ **Migrations**.
6
+
7
+ ## [0.2.0] - 2026-11-04
8
+
9
+ ### Added
10
+
11
+ - **Manifest overrides.** An optional `manifests/<repo>.override.yml` in the
12
+ distribution is deep-merged onto the repo's base manifest (its own, or the
13
+ held one): maps merge by key, lists and scalars replace, and an explicit
14
+ `null` deletes a key. An override may only name services and keys the base
15
+ has, and an override with no base is an error. See "Overriding a manifest"
16
+ in `docs/distributions.md`.
17
+ - **Manifest layers are visible.** `/api/services` returns `manifestLayers`
18
+ per service (`["repo"]`, `["held", "override"]`, …) and the Services cards
19
+ show them; `GET /api/manifest/validate?path=<repo dir>` returns each layer's
20
+ result.
21
+ - **`validate` checks each layer.** For a repo folder it validates the base
22
+ and the override separately, each error naming its file, then the merged
23
+ result.
24
+ - **`<cli> mcp`: an MCP server over stdio** for agents, a thin client of the
25
+ running web server (it never starts it, and says how when it is down). Read
26
+ tools are always on, including the new `stacks` and `edge_status`; the
27
+ actions `service_up`, `service_down`, `service_restart`, `workspace_sync`
28
+ and `run_tests` are opt-in per org with `mcp.actions`. Guards: lifecycle
29
+ commands and env=local only, locally run services only, `run_tests` limited
30
+ to `mcp.run_tests.envs` (default `[local]`, never production), security runs
31
+ must pass the owned-host plan and `full` is local only, log tools read
32
+ local sources unless `mcp.logs.remote: true`, and all text returned is
33
+ secret-redacted. No deploy tool. Pinned `@modelcontextprotocol/sdk` 1.32.1.
34
+ See "MCP server" in `docs/distributions.md`.
35
+ - **Agent audit trail.** Every service exec, test run and sync is recorded
36
+ with who asked: an agent's actions carry actor `agent`, the MCP client's
37
+ self-reported name and version, and the MCP pid and session id, and show as
38
+ `[agent]` lines in the web server log on the Logs page.
39
+ - **Read-only status endpoints:** `/api/stacks` (what `stack ls/health` show),
40
+ `/api/edge` (what `edge status` shows) and `/api/security/plan` (the
41
+ security CLI's own dry run). `stack ls` and `edge status` now print from the
42
+ same code.
43
+ - **Graph: cards and a details panel.** The Local Dev graph is laid out by
44
+ ELK (layered, compound org or application › repo › service, orthogonal
45
+ edges; elkjs vendored and served by Den, so it works offline). Cards are
46
+ full size (detailed or compact) on a canvas you pan and zoom; Fit zooms out
47
+ to 35%. A card shows status, name, repo, placement and health, and its main
48
+ actions on hover. Clicking a card or a repo opens a side panel: one primary
49
+ action (Start when down, Open when up, else Logs), two common ones, and More
50
+ (manifest commands, tools, and careful actions that confirm on a second
51
+ click); tabs Overview, Logs (live tail), Config and Activity (the audit
52
+ trail, yours and agents'). ⤢ pops the panel out as a dialog. Layout
53
+ direction, grouping, card density and panel width are remembered per user
54
+ (`/api/settings` `graph`). Find highlights and centres on matches. The
55
+ panel is built from registries (actions, tabs, sections) a distribution or
56
+ later release can add to.
57
+ - `GET /api/activity`: the audit trail, filtered by service or repo.
58
+ - **One secret redactor** (`src/shared/redact.ts`), shared by the journeys and
59
+ security pillars and the MCP server.
60
+ - **Placement (R13): what runs here and what runs in the cloud.** A
61
+ manifest's service may say `runs: { local: remote, dev: remote }` (per env,
62
+ `local` or `remote`) and `target: { env, account?, url?, expect? }`.
63
+ Without `runs`, a service is local when it or any service of its repo has
64
+ local commands (or the repo is a compose stack), remote when it has only an
65
+ HTTP health URL and nothing in its repo runs here, and otherwise has no
66
+ placement. `/api/services`
67
+ and `/api/health` rows carry `runs` and `target`; `/api/applications`
68
+ carries `placements` per service address, and per application `placement`
69
+ (`local | remote | hybrid | none`) and a `summary`
70
+ (`shop-frontend local · shop-core remote (dev)`). `<cli> status`,
71
+ `services` and `apps` suffix remote services `☁ remote (dev)`, and
72
+ `<cli> graph` marks remote and hybrid nodes. See "Placement" in
73
+ `docs/distributions.md`.
74
+ - **Remote health.** A remote service is checked by the health declared for
75
+ its `target.env`; only when there is none does Den GET `target.url`, up when
76
+ the status is one of `target.expect` (a code or a list, 100–599; default
77
+ any 2xx). Its health row's label names the target (`dev · AWS`).
78
+ - **`production_envs`** in the org config: the envs that count as production
79
+ (default `[prod, production]`).
80
+
81
+ ### Changed
82
+
83
+ - **`/api/health` rows: `url` is only ever a URL.** A shell health check's
84
+ command (a compose stack's `<cli> stack health …`, or any declared shell
85
+ check) is now in a new `check` field and `url` is null; the UI shows the
86
+ same tooltips as before. Clients that read the command from `url` should
87
+ read `check`.
88
+ - `/api/server-info` returns Den's `version`.
89
+ - **Nothing runs a command on a remote service.** `/api/service/exec`,
90
+ `<cli> up|down|restart`, workspace up and down, and `<cli> up`'s plan refuse
91
+ it (`runs in dev (AWS); nothing to start here`; a `down` succeeds with
92
+ nothing to stop). The MCP guard `runsLocally()` reads `runs`. Security
93
+ `auto_targets` excludes remote services explicitly, a remote service is
94
+ never scanned as if it were local, and one whose `target.env` counts as
95
+ production is never scanned at all.
96
+ - **Overrides may add placement.** `runs` and `target` are the one thing a
97
+ `manifests/<repo>.override.yml` may add to a service its base has.
98
+ - `validate` checks env names: a `runs` key or `target.env` that is not one of
99
+ the org's `environments` is an error.
100
+ - `<cli> status` keeps a hybrid repo's remote service as its own row instead
101
+ of rolling it into the entrypoint.
102
+
103
+ ### Fixed
104
+
105
+ - **Logs of compose-stack services.** The live tail (`/api/service/taillog`,
106
+ so the UI's log view and `logs_tail`), log history and search
107
+ (`logs_search`) and `<cli> logs` now find a stack service's container,
108
+ `<stack>-<workspace>-<service>-1`, through the stacks naming helpers. They
109
+ looked only for opctl containers, so they fell back to the startup log
110
+ ("container log unavailable") or found nothing.
111
+ - **`<cli> mcp` against an older web server.** A tool whose route the web
112
+ server predates (`stacks`, `edge_status`, a security `run_tests`) now says
113
+ `web server is Den <x>; <tool> needs >= <y>: run <cli> web restart`
114
+ instead of a bare 404; other 404s name the tool and the route.
115
+ - Sync never touches a dev-managed checkout: a managed entry whose path is,
116
+ holds or sits inside one is refused with the reason, and naming a
117
+ dev-managed repo says so instead of doing nothing.
118
+ - The What's new dialog showed every changelog bullet cut off mid-sentence.
119
+ - With nothing run yet, the empty output pane no longer takes 200px from the
120
+ Local Dev page.
121
+ - A security run's mode chosen on the Tests page (`api`, `full`) now reaches
122
+ the scan; it always ran `baseline` before.
123
+
124
+ ### Security
125
+
126
+ - Dependency advisories: `npm audit fix` plus `@cursor/sdk` 1.0.23 → 1.0.40
127
+ (drops its `undici` 5 / `zod` 3 tree) clear every critical and high
128
+ advisory. Left: a `minimatch` ReDoS under `openapi-typescript` (only fix is
129
+ a downgrade to 6.x; it matches local config globs only) and dev-only
130
+ tooling (jest, eslint) moderates.
131
+
132
+ ### Migrations
133
+
134
+ - None required: with no override files, manifests resolve as in 0.1.0.
135
+ - To let agents act through `<cli> mcp`, add `mcp.actions` to the org config.
136
+ - Placement needs no change: without `runs`, services keep working as
137
+ before. A service with an HTTP health URL, no commands, and nothing else
138
+ in its repo that runs here now shows as remote; add `runs: { local: local }`
139
+ if it is really on this machine. To
140
+ mark more envs as production than `prod` and `production`, set
141
+ `production_envs`.
142
+
143
+
144
+ ## [0.1.0] - 2026-11-04
145
+
146
+ The first Den release: one engine for local development, tests and releases
147
+ across an organisation's repos, shipped as `@monster-orange/den` and used
148
+ through thin distributions that pin an exact version.
149
+
150
+ ### Added
151
+
152
+ - **`den create <name> [dir]`** (also `npx @monster-orange/den create`)
153
+ scaffolds a distribution: `den.yml`, a `package.json` pinning this exact
154
+ Den, a `bin/<cli>` shim, a Makefile including `make/den.mk`, an org config
155
+ with a brand, and empty `manifests/` and `tests/pillars/`.
156
+ `examples/distribution/` is its output for `acme`. See
157
+ `docs/distributions.md`.
158
+ - **Den runs as an installed package.** Den's own files resolve from the
159
+ engine root (`node_modules/@monster-orange/den`), the distribution's from
160
+ its root; scripts run with Den's tsx, never through `npx` or the current
161
+ directory. The package ships `src/` and runs it with tsx (a dependency
162
+ now); CI proves it with `scripts/dist-smoke.sh`.
163
+ - **Org > Application > Repo > Services.** Declared applications (config
164
+ `applications:` or a manifest's `application:`) group repos; the Local Dev
165
+ graph boxes each one inside its org's frame, next to the connected groups of
166
+ repos that are their own application.
167
+ - **Security scans keep a latest record.** Every run writes
168
+ `reports/security/<env>/latest-<mode>.json`; the Tests page shows it, with
169
+ findings marked new since the previous run.
170
+ - **Repo suites** (`tests:` in a manifest) run from the Tests page and CLI.
171
+ - **Edge opt-ins**: a project CA and route certificates are opt-in; with none
172
+ set, the rendered edge is unchanged.
173
+
174
+ - **launchd service from a distribution.** `service/install.sh` ships in the
175
+ package and runs from `DEN_ROOT`; `DEN_SERVICE_LABEL` and `DEN_SERVICE_LOGS`
176
+ keep an existing label and log folder; `print` shows the plist.
177
+
178
+ ### Migrations
179
+
180
+ From the engine this release was generalised from:
181
+
182
+ - Run Den from the package: a `bin/<cli>` shim that sets `DEN_ROOT` to the
183
+ distribution and execs `node_modules/@monster-orange/den/bin/den`, and a
184
+ Makefile that does `include node_modules/@monster-orange/den/make/den.mk`
185
+ (`den create` writes both; `docs/distributions.md` shows them).
186
+ - Add `den.yml` at the distribution root with `product: { name: <your name> }`.
187
+ Env vars, the config and manifest file names, the state, managed-clone and
188
+ workspace directories all derive from that name, so an existing install
189
+ keeps every on-disk and env name by naming itself as before.
190
+ - Workspace mode `<name>-managed` is now `managed`. Old values are still
191
+ read, and rewritten on the next save.
192
+ - The CLI command `use-<name>` is now `use-managed`.
193
+ - `github_org` has no default: set it in the org config.
194
+ - The shared local-infra repo is configuration: `graph.infra: { repo,
195
+ signals }`. Without it no infra edges are derived. The default-workspace
196
+ entry repo is `defaults.workspace.entry`.
197
+ - Perf suites come from the distribution (`tests/pillars/perf/<module>/test.js`)
198
+ or from repo manifests; Den ships none.
199
+ - Service and setup make targets are `<prefix>-up`, `-status`, … where the
200
+ prefix is `DEN_TARGET_PREFIX` (set before including `make/den.mk`; `den
201
+ create` sets it to the CLI name, so `make <name>-up` keeps working).
202
+ - `service_env` has no built-in entries: a shared-infra secrets file is
203
+ configured as `service_env: { <KEY>: "{repo:<infra repo>}/<path>" }`.
204
+ - The smoke and browser make targets have no default repo: pass `repo=<repo>`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Monster Orange
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,167 @@
1
1
  # Den
2
2
 
3
- A config-driven local development appliance. This is a name placeholder; the first release is 0.1.0.
3
+ Den is a config-driven local development appliance. It starts the repos you
4
+ work on in dependency order, puts them behind a local HTTPS edge, gives you a
5
+ web UI and a CLI over all of it, and runs smoke, browser, API, journey,
6
+ security and performance suites against the environments you declare.
7
+
8
+ Den knows nothing about any particular organisation. Everything specific to
9
+ yours — product name, repos, environments, hosts, secrets backend, test
10
+ accounts — lives in **your distribution**, not in Den.
11
+
12
+ > **Status: 0.2.0**: `npm install @monster-orange/den`. Den is pre-1.0; each release lists the changes a distribution makes under **Migrations** in [CHANGELOG.md](CHANGELOG.md).
13
+
14
+ ## Make it your own
15
+
16
+ 1. **Create** a distribution named after your product:
17
+
18
+ ```sh
19
+ npx @monster-orange/den create acme # → ./acme
20
+ cd acme && npm install
21
+ ```
22
+
23
+ 2. **Name** it: `den.yml` holds `product: { name: acme }`, so the CLI is
24
+ `./bin/acme`, env vars are `ACME_*`, state lives in `~/.acme`. Pass
25
+ `--cli`, `--env-prefix` or `--title` to `create`, or edit `den.yml`.
26
+ 3. **Brand** it: `brand:` in `config/acme.yml` sets the name, tagline and
27
+ banner people see in the CLI and web UI.
28
+ 4. **Point it at your repos**: set `github_org` in `config/acme.yml`, then
29
+ `./bin/acme register ../shop-api` (or add a manifest per repo under
30
+ `manifests/`).
31
+ 5. **Run** it: `./bin/acme up`, `./bin/acme web`, `make test`.
32
+
33
+ Every field, the bin shim, the make fragment and upgrading are in
34
+ [docs/distributions.md](docs/distributions.md);
35
+ [examples/distribution/](examples/distribution) is what `create acme` writes.
36
+
37
+ ## Distributions
38
+
39
+ You run Den through a small repo of your own (a _distribution_):
40
+
41
+ ```
42
+ my-dev/
43
+ ├── den.yml # who this distribution is (below)
44
+ ├── package.json # pins an exact @monster-orange/den version
45
+ ├── config/<name>.yml # your org config
46
+ ├── config/environments/ # one <env>.json per environment
47
+ ├── manifests/ # manifests for repos that don't carry their own
48
+ ├── tests/pillars/<pillar>/ # your own suites (e.g. tests/pillars/perf/<module>/test.js)
49
+ ├── bin/<cli> # shim: DEN_ROOT=<this dir> exec node_modules/@monster-orange/den/bin/den
50
+ └── Makefile # include node_modules/@monster-orange/den/make/den.mk
51
+ ```
52
+
53
+ `den.yml` names the product. Every runtime name derives from it:
54
+
55
+ ```yaml
56
+ product:
57
+ name:
58
+ acme # CLI "acme", env vars ACME_*, config/acme.yml,
59
+ # manifests .acme.yml, state ~/.acme,
60
+ # managed clones .acme-services/, workspaces acme-workspaces/
61
+ # Override any of them: cli, env_prefix, config, manifest, state_dir,
62
+ # services_dir, workspaces_dir
63
+ ```
64
+
65
+ Den's own checkout is a distribution named `den`, so in this repo the CLI is
66
+ `./bin/den`, the config is `config/den.yml`, and env vars are `DEN_*`.
67
+
68
+ ## Repos opt in with a manifest
69
+
70
+ A repo joins by carrying a manifest at its root (`.<name>.yml`, e.g.
71
+ `.den.yml`) whose commands delegate to the repo's own targets. Den never
72
+ reaches inside a repo beyond that. When a repo has no manifest, the
73
+ distribution can hold one for it in `manifests/<repo>.<name>.yml`; the repo's
74
+ own manifest always wins.
75
+
76
+ ```yaml
77
+ # demo-api: a self-contained service. Nothing it calls, so it starts alone.
78
+ version: 1
79
+ name: demo-api
80
+ application: shop # the application this repo belongs to (den apps)
81
+ compose:
82
+ files: [docker-compose.yml]
83
+ routes:
84
+ api: api:8080 # https://api.demo-api.<edge domain>
85
+ services:
86
+ demo-api:
87
+ commands:
88
+ local:
89
+ setup: make setup
90
+ preflight: make test
91
+ # OWASP ZAP target for the security pillar (`make test-sec-api env=local`).
92
+ security:
93
+ api:
94
+ hosts:
95
+ local: ["https://api.demo-api.globex.localhost"]
96
+ ```
97
+
98
+ That is `examples/demo/demo-api/.den.yml`; the other demo repos are in
99
+ [`examples/demo/`](examples/demo/).
100
+
101
+ ## What it does
102
+
103
+ - **Workspaces.** A workspace is a set of repos. Each is either
104
+ _dev-managed_ (your checkout, your branch) or _managed_ (cloned by Den and
105
+ kept on a tracking branch).
106
+ - **Derived dependency graph.** Start and stop order comes from real signals in
107
+ each repo — SDK imports, `*_URL` env vars, IaC references, event rules,
108
+ readiness probes — tuned in config with `graph.aliases`, `graph.edges` and
109
+ an optional shared local-infra repo (`graph.infra`).
110
+ - **Local HTTPS edge.** One local proxy routes `https://<route>.<domain>` to
111
+ each service, with an optional project CA.
112
+ - **Test pillars.** `smoke`, `browser` (synthetic Playwright), `api`,
113
+ `journeys` (agent-driven), `perf` (k6), `security` (OWASP ZAP against hosts
114
+ you own) and `suites` (a repo's own commands).
115
+ - **Releases.** A release view over the repos and deploy workflows your config
116
+ lists.
117
+ - **Web UI and CLI** over the same state.
118
+
119
+ ## Strategies
120
+
121
+ Concerns that vary by org are strategies selected in config, never hard-wired:
122
+
123
+ | Concern | Built-in choices | Chosen in |
124
+ | ---------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
125
+ | Secrets backend | `env`, `doppler`, `1password` | `secrets.provider` in the org config; per engineer in `config/local/user.yml`; per shell `<PREFIX>_SECRETS_PROVIDER` |
126
+ | Test-user tokens | `local-jwt`, `cognito`, `auth0`, `none` | `auth.provider` in `config/environments/<env>.json` |
127
+
128
+ A new secrets backend implements `SecretsProvider`
129
+ (`src/shared/secrets/types.ts`); a new identity provider implements a token
130
+ provider in `src/shared/auth/token-providers/`.
131
+
132
+ ## CLI
133
+
134
+ ```bash
135
+ den up [repo] # start the repo's derived dependency closure (-x deps only, -n dry run)
136
+ den down [repo] # stop it cleanly
137
+ den status # service health for the active workspace
138
+ den apps # Org > Application > Repo > Services
139
+ den graph [repo] # the derived dependency graph
140
+ den logs [repo] # tail a repo's local logs
141
+ den use-local [repo] # use your checkout · use-managed [repo] to switch back
142
+ den workspace list # workspaces (activate · deactivate · use · create · delete)
143
+ den run # run test suites (interactive, or with options)
144
+ den web # the web UI
145
+ den --help # everything else
146
+ ```
147
+
148
+ In a distribution the command is that distribution's `cli` name.
149
+
150
+ ## Developing Den
151
+
152
+ ```bash
153
+ npm ci
154
+ npm run typecheck
155
+ npm run lint
156
+ npm test
157
+ DEN_ORG_NAMES_FILE=<patterns file> node scripts/org-name-gate.mjs
158
+ ```
159
+
160
+ CI runs the same gates. The org-name gate fails the build when any file names
161
+ an organisation, product, host or account; its patterns are kept out of this
162
+ repo (a CI secret) so the list itself is never published. See
163
+ [CONTRIBUTING.md](CONTRIBUTING.md).
164
+
165
+ ## License
166
+
167
+ [MIT](LICENSE)
package/bin/den ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Two roots (see src/shared/paths.ts):
5
+ # DEN_ENGINE_ROOT Den's own package: this script's parent directory, which
6
+ # in a distribution is node_modules/@monster-orange/den.
7
+ # DEN_ROOT the distribution: the directory holding den.yml. A
8
+ # distribution's bin/<cli> shim sets it; in Den's own
9
+ # checkout (where the engine dir holds den.yml) it is set
10
+ # here. Otherwise it is left unset and Den walks up from
11
+ # the entry script to find den.yml.
12
+ DEN_ENGINE_ROOT="$(cd "$(dirname "$(realpath "$0")")/.." && pwd)"
13
+ export DEN_ENGINE_ROOT
14
+ if [ -z "${DEN_ROOT:-}" ] && [ -f "$DEN_ENGINE_ROOT/den.yml" ]; then
15
+ DEN_ROOT="$DEN_ENGINE_ROOT"
16
+ export DEN_ROOT
17
+ fi
18
+ export DEN_INVOKE_CWD="$PWD"
19
+ export OP_ACCOUNT="${OP_ACCOUNT:-example.1password.com}"
20
+
21
+ # tsx: Den's own (a checkout) or hoisted into the distribution's node_modules.
22
+ find_tsx() {
23
+ local dir="$DEN_ENGINE_ROOT"
24
+ while :; do
25
+ if [ -x "$dir/node_modules/.bin/tsx" ]; then
26
+ printf '%s\n' "$dir/node_modules/.bin/tsx"
27
+ return 0
28
+ fi
29
+ [ "$dir" = "/" ] && return 1
30
+ dir="$(dirname "$dir")"
31
+ done
32
+ }
33
+
34
+ # `create` scaffolds a new distribution: it needs no den.yml, so it runs on
35
+ # its own entry point rather than the full CLI.
36
+ entry="src/ui/cli/index.ts"
37
+ built="dist/src/ui/cli/index.js"
38
+ if [ "${1:-}" = "create" ]; then
39
+ shift
40
+ entry="src/ui/cli/create-main.ts"
41
+ built="dist/src/ui/cli/create-main.js"
42
+ fi
43
+ # `mcp` speaks the MCP protocol on stdout: its own entry point, so nothing
44
+ # the full CLI prints can reach the protocol stream.
45
+ if [ "${1:-}" = "mcp" ]; then
46
+ shift
47
+ entry="src/ui/cli/mcp-main.ts"
48
+ built="dist/src/ui/cli/mcp-main.js"
49
+ fi
50
+
51
+ # Escape hatch: force the compiled build (e.g. to test the prod artifact).
52
+ if [ "${DEN_USE_DIST:-}" = "1" ] && [ -f "$DEN_ENGINE_ROOT/$built" ]; then
53
+ exec node "$DEN_ENGINE_ROOT/$built" "$@"
54
+ fi
55
+
56
+ # Prefer live TypeScript source (the package ships src/ and runs it with tsx).
57
+ # A built dist/ is gitignored and only refreshed by `npm run build`, so
58
+ # preferring it would silently shadow local source edits with a stale build.
59
+ if tsx="$(find_tsx)"; then
60
+ exec "$tsx" "$DEN_ENGINE_ROOT/$entry" "$@"
61
+ fi
62
+
63
+ if [ -f "$DEN_ENGINE_ROOT/$built" ]; then
64
+ exec node "$DEN_ENGINE_ROOT/$built" "$@"
65
+ fi
66
+
67
+ echo "den: no runnable entrypoint: run 'npm install'" >&2
68
+ exit 1