aicodeman 0.9.3 → 0.9.5

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 (80) hide show
  1. package/dist/types/index.d.ts +1 -0
  2. package/dist/types/index.d.ts.map +1 -1
  3. package/dist/types/index.js +1 -0
  4. package/dist/types/index.js.map +1 -1
  5. package/dist/types/update.d.ts +79 -0
  6. package/dist/types/update.d.ts.map +1 -0
  7. package/dist/types/update.js +16 -0
  8. package/dist/types/update.js.map +1 -0
  9. package/dist/web/middleware/auth.d.ts +18 -0
  10. package/dist/web/middleware/auth.d.ts.map +1 -1
  11. package/dist/web/middleware/auth.js +33 -0
  12. package/dist/web/middleware/auth.js.map +1 -1
  13. package/dist/web/network-auth-policy.d.ts +38 -0
  14. package/dist/web/network-auth-policy.d.ts.map +1 -1
  15. package/dist/web/network-auth-policy.js +108 -0
  16. package/dist/web/network-auth-policy.js.map +1 -1
  17. package/dist/web/public/api-client.3adebdc2.js.gz +0 -0
  18. package/dist/web/public/app.c860ea08.js.gz +0 -0
  19. package/dist/web/public/{constants.cb6426c4.js → constants.5b68d2de.js} +39 -3
  20. package/dist/web/public/constants.5b68d2de.js.br +0 -0
  21. package/dist/web/public/constants.5b68d2de.js.gz +0 -0
  22. package/dist/web/public/image-input.7cade6a8.js.gz +0 -0
  23. package/dist/web/public/index.html +22 -4
  24. package/dist/web/public/index.html.br +0 -0
  25. package/dist/web/public/index.html.gz +0 -0
  26. package/dist/web/public/input-cjk.88082175.js.gz +0 -0
  27. package/dist/web/public/keyboard-accessory.cdfd8c04.js.gz +0 -0
  28. package/dist/web/public/mobile-handlers.1e2a8ef8.js.gz +0 -0
  29. package/dist/web/public/mobile.26dc30d6.css.gz +0 -0
  30. package/dist/web/public/notification-manager.9c984ac2.js.gz +0 -0
  31. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  32. package/dist/web/public/{panels-ui.3e304caf.js → panels-ui.5192a2c0.js} +8 -8
  33. package/dist/web/public/panels-ui.5192a2c0.js.br +0 -0
  34. package/dist/web/public/panels-ui.5192a2c0.js.gz +0 -0
  35. package/dist/web/public/ralph-panel.61076370.js.gz +0 -0
  36. package/dist/web/public/ralph-wizard.52d533d2.js.gz +0 -0
  37. package/dist/web/public/respawn-ui.5377f958.js.gz +0 -0
  38. package/dist/web/public/session-ui.3e0cf024.js.gz +0 -0
  39. package/dist/web/public/{settings-ui.c06be9c3.js → settings-ui.da0621e1.js} +8 -8
  40. package/dist/web/public/settings-ui.da0621e1.js.br +0 -0
  41. package/dist/web/public/settings-ui.da0621e1.js.gz +0 -0
  42. package/dist/web/public/styles.e87cb785.css.gz +0 -0
  43. package/dist/web/public/subagent-windows.a366a4ad.js.gz +0 -0
  44. package/dist/web/public/sw.js.gz +0 -0
  45. package/dist/web/public/terminal-ui.37caa926.js.gz +0 -0
  46. package/dist/web/public/upload.html.gz +0 -0
  47. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  48. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  49. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  50. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  51. package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
  52. package/dist/web/public/vendor/xterm.css.gz +0 -0
  53. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  54. package/dist/web/public/voice-input.085e9e73.js.gz +0 -0
  55. package/dist/web/routes/system-routes.d.ts.map +1 -1
  56. package/dist/web/routes/system-routes.js +30 -0
  57. package/dist/web/routes/system-routes.js.map +1 -1
  58. package/dist/web/routes/ws-routes.d.ts +2 -1
  59. package/dist/web/routes/ws-routes.d.ts.map +1 -1
  60. package/dist/web/routes/ws-routes.js +12 -1
  61. package/dist/web/routes/ws-routes.js.map +1 -1
  62. package/dist/web/self-update.d.ts +112 -0
  63. package/dist/web/self-update.d.ts.map +1 -0
  64. package/dist/web/self-update.js +518 -0
  65. package/dist/web/self-update.js.map +1 -0
  66. package/dist/web/server.d.ts +5 -0
  67. package/dist/web/server.d.ts.map +1 -1
  68. package/dist/web/server.js +45 -15
  69. package/dist/web/server.js.map +1 -1
  70. package/dist/web/sse-events.d.ts +5 -3
  71. package/dist/web/sse-events.d.ts.map +1 -1
  72. package/dist/web/sse-events.js +5 -3
  73. package/dist/web/sse-events.js.map +1 -1
  74. package/package.json +1 -1
  75. package/dist/web/public/constants.cb6426c4.js.br +0 -0
  76. package/dist/web/public/constants.cb6426c4.js.gz +0 -0
  77. package/dist/web/public/panels-ui.3e304caf.js.br +0 -0
  78. package/dist/web/public/panels-ui.3e304caf.js.gz +0 -0
  79. package/dist/web/public/settings-ui.c06be9c3.js.br +0 -0
  80. package/dist/web/public/settings-ui.c06be9c3.js.gz +0 -0
@@ -65,4 +65,5 @@ export * from './teams.js';
65
65
  export * from './push.js';
66
66
  export * from './plan.js';
67
67
  export * from './orchestrator.js';
68
+ export * from './update.js';
68
69
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC"}
@@ -65,4 +65,5 @@ export * from './teams.js';
65
65
  export * from './push.js';
66
66
  export * from './plan.js';
67
67
  export * from './orchestrator.js';
68
+ export * from './update.js';
68
69
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @fileoverview Types for the in-app self-updater.
3
+ *
4
+ * Codeman can update itself from the web UI (App Settings → Updates). The flow
5
+ * is driven by a detached `scripts/self-update.sh` that outlives the service
6
+ * restart it triggers, and a status file at `~/.codeman/update-status.json`
7
+ * (see `dataPath('update-status.json')`) that the browser polls across the
8
+ * restart boundary.
9
+ *
10
+ * Backend logic: `src/web/self-update.ts`. Routes: `src/web/routes/system-routes.ts`
11
+ * (`/api/system/update/check`, `POST /api/system/update`, `/api/system/update/status`).
12
+ *
13
+ * @module types/update
14
+ */
15
+ /** Which init system supervises the running server (decides how we restart it). */
16
+ export type SupervisorKind = 'systemd' | 'launchd' | 'none';
17
+ /** How Codeman was installed — only `git` installs can self-update in place. */
18
+ export type InstallKind = 'git' | 'npm' | 'unknown';
19
+ /**
20
+ * Lifecycle of a single update run. `idle`/`completed`/`failed`/
21
+ * `completed-needs-manual-restart` are terminal; the rest are in-flight.
22
+ */
23
+ export type UpdatePhase = 'idle' | 'queued' | 'preparing' | 'stashing' | 'fetching' | 'checkout' | 'installing' | 'building' | 'restarting' | 'completed' | 'completed-needs-manual-restart' | 'failed';
24
+ /** Persisted update progress, written atomically by the updater + boot reconcile. */
25
+ export interface UpdateStatus {
26
+ /** Nonce identifying this run; guards boot-reconcile against stale/foreign status. */
27
+ updateId: string;
28
+ phase: UpdatePhase;
29
+ /** Human-readable one-liner for the UI. */
30
+ message: string;
31
+ /** Version the server was on when the update started. */
32
+ fromVersion: string;
33
+ /** Target version (parsed from the release tag). */
34
+ toVersion?: string;
35
+ /** Target git tag, e.g. `codeman@0.9.4`. */
36
+ toTag?: string;
37
+ /** Commit the repo was on before the update, for rollback. */
38
+ prevSha?: string;
39
+ /** Name of the stash holding local changes (when the tree was dirty), else null. */
40
+ stashRef?: string | null;
41
+ supervisor?: SupervisorKind;
42
+ /** epoch ms — update start (freshness guard for boot reconcile). */
43
+ startedAt: number;
44
+ /** epoch ms — last write. */
45
+ updatedAt: number;
46
+ /** Populated on failure. */
47
+ error?: string;
48
+ /** Shown for the `none` supervisor — the command the user must run by hand. */
49
+ manualRestartCommand?: string;
50
+ }
51
+ /** Describes the running install — drives whether/how the Updates UI is shown. */
52
+ export interface InstallInfo {
53
+ installKind: InstallKind;
54
+ installDir: string;
55
+ /** Current git branch, or `HEAD` when detached (e.g. pinned to a release tag). */
56
+ branch?: string;
57
+ /** Uncommitted local changes present (true → updater will auto-stash). */
58
+ dirty: boolean;
59
+ supervisor: SupervisorKind;
60
+ currentVersion: string;
61
+ /** False when `CODEMAN_DISABLE_SELF_UPDATE=1`. */
62
+ selfUpdateEnabled: boolean;
63
+ }
64
+ /** Result of "check for updates" — current vs. latest release. */
65
+ export interface UpdateCheckResult {
66
+ currentVersion: string;
67
+ latestVersion: string | null;
68
+ latestTag: string | null;
69
+ updateAvailable: boolean;
70
+ /** Release notes (markdown) when available from the GitHub API. */
71
+ notes?: string | null;
72
+ /** Link to the release page. */
73
+ htmlUrl?: string | null;
74
+ /** epoch ms of the check. */
75
+ checkedAt: number;
76
+ source: 'github-api' | 'git-ls-remote' | 'none';
77
+ error?: string;
78
+ }
79
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/types/update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,mFAAmF;AACnF,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5D,gFAAgF;AAChF,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;AAEpD;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,QAAQ,GACR,WAAW,GACX,UAAU,GACV,UAAU,GACV,UAAU,GACV,YAAY,GACZ,UAAU,GACV,YAAY,GACZ,WAAW,GACX,gCAAgC,GAChC,QAAQ,CAAC;AAEb,qFAAqF;AACrF,MAAM,WAAW,YAAY;IAC3B,sFAAsF;IACtF,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,cAAc,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,kEAAkE;AAClE,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,GAAG,eAAe,GAAG,MAAM,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @fileoverview Types for the in-app self-updater.
3
+ *
4
+ * Codeman can update itself from the web UI (App Settings → Updates). The flow
5
+ * is driven by a detached `scripts/self-update.sh` that outlives the service
6
+ * restart it triggers, and a status file at `~/.codeman/update-status.json`
7
+ * (see `dataPath('update-status.json')`) that the browser polls across the
8
+ * restart boundary.
9
+ *
10
+ * Backend logic: `src/web/self-update.ts`. Routes: `src/web/routes/system-routes.ts`
11
+ * (`/api/system/update/check`, `POST /api/system/update`, `/api/system/update/status`).
12
+ *
13
+ * @module types/update
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/types/update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -10,6 +10,7 @@
10
10
  import type { FastifyInstance } from 'fastify';
11
11
  import { StaleExpirationMap } from '../../utils/index.js';
12
12
  import type { AuthSessionRecord } from '../ports/auth-port.js';
13
+ import { type HostPolicy } from '../network-auth-policy.js';
13
14
  export declare const AUTH_COOKIE_NAME = "codeman_session";
14
15
  /** State returned from registerAuthMiddleware for cleanup in server stop() */
15
16
  interface AuthState {
@@ -24,6 +25,23 @@ interface AuthState {
24
25
  * @returns AuthState for lifecycle management (dispose on server stop)
25
26
  */
26
27
  export declare function registerAuthMiddleware(app: FastifyInstance, https: boolean): AuthState;
28
+ /**
29
+ * Register the anti-DNS-rebinding Host allowlist + cross-site (CSRF) Origin guard.
30
+ *
31
+ * This protects the API even on the default no-password install, where there is no
32
+ * cookie/credential to gate on. It must be registered BEFORE the auth middleware so
33
+ * forged cross-site or DNS-rebound requests are rejected up front. `getPolicy` is
34
+ * evaluated per request so a tunnel started at runtime is reflected immediately.
35
+ *
36
+ * - Every request: the `Host` header must be in the allowlist (blocks DNS rebinding,
37
+ * where a custom domain is rebound to 127.0.0.1 but still sends its own name).
38
+ * - State-changing methods: the `Origin` (when the client sends one — i.e. a browser)
39
+ * must be same-site (blocks cross-site CSRF, including the text/plain simple-request
40
+ * trick). Non-browser clients (curl, Claude Code hooks) omit Origin and pass.
41
+ *
42
+ * WebSocket upgrades are validated separately in the ws route handler.
43
+ */
44
+ export declare function registerHostGuard(app: FastifyInstance, getPolicy: () => HostPolicy): void;
27
45
  /**
28
46
  * Register security headers and CORS middleware on every response.
29
47
  */
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/web/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,SAAS,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAS/D,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAElD,8EAA8E;AAC9E,UAAU,SAAS;IACjB,YAAY,EAAE,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI,CAAC;IACnE,YAAY,EAAE,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACxD,cAAc,EAAE,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;CAC3D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,CAwHtF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAgDlF"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/web/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,SAAS,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAgD,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAS1G,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAElD,8EAA8E;AAC9E,UAAU,SAAS;IACjB,YAAY,EAAE,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI,CAAC;IACnE,YAAY,EAAE,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACxD,cAAc,EAAE,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;CAC3D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,CAwHtF;AAKD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,UAAU,GAAG,IAAI,CAazF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAgDlF"}
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { randomBytes, timingSafeEqual } from 'node:crypto';
11
11
  import { StaleExpirationMap } from '../../utils/index.js';
12
+ import { isAllowedRequestHost, isAllowedRequestOrigin } from '../network-auth-policy.js';
12
13
  import { AUTH_SESSION_TTL_MS, MAX_AUTH_SESSIONS, AUTH_FAILURE_MAX, AUTH_FAILURE_WINDOW_MS, } from '../../config/auth-config.js';
13
14
  // Auth session cookie name
14
15
  export const AUTH_COOKIE_NAME = 'codeman_session';
@@ -121,6 +122,38 @@ export function registerAuthMiddleware(app, https) {
121
122
  });
122
123
  return state;
123
124
  }
125
+ /** Methods that don't change server state and so skip the cross-site Origin check. */
126
+ const SAFE_HTTP_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
127
+ /**
128
+ * Register the anti-DNS-rebinding Host allowlist + cross-site (CSRF) Origin guard.
129
+ *
130
+ * This protects the API even on the default no-password install, where there is no
131
+ * cookie/credential to gate on. It must be registered BEFORE the auth middleware so
132
+ * forged cross-site or DNS-rebound requests are rejected up front. `getPolicy` is
133
+ * evaluated per request so a tunnel started at runtime is reflected immediately.
134
+ *
135
+ * - Every request: the `Host` header must be in the allowlist (blocks DNS rebinding,
136
+ * where a custom domain is rebound to 127.0.0.1 but still sends its own name).
137
+ * - State-changing methods: the `Origin` (when the client sends one — i.e. a browser)
138
+ * must be same-site (blocks cross-site CSRF, including the text/plain simple-request
139
+ * trick). Non-browser clients (curl, Claude Code hooks) omit Origin and pass.
140
+ *
141
+ * WebSocket upgrades are validated separately in the ws route handler.
142
+ */
143
+ export function registerHostGuard(app, getPolicy) {
144
+ app.addHook('onRequest', (req, reply, done) => {
145
+ const policy = getPolicy();
146
+ if (!isAllowedRequestHost(req.headers.host, policy)) {
147
+ reply.code(403).send('Forbidden: host not allowed');
148
+ return;
149
+ }
150
+ if (!SAFE_HTTP_METHODS.has(req.method) && !isAllowedRequestOrigin(req.headers.origin, policy)) {
151
+ reply.code(403).send('Forbidden: cross-site request blocked');
152
+ return;
153
+ }
154
+ done();
155
+ });
156
+ }
124
157
  /**
125
158
  * Register security headers and CORS middleware on every response.
126
159
  */
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/web/middleware/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/web/middleware/auth.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,41 @@
1
1
  export declare function isExplicitlyEnabled(value: string | undefined): boolean;
2
2
  export declare function isLoopbackBindHost(host: string): boolean;
3
+ /**
4
+ * Hostname suffixes that are always accepted by the Host/Origin allowlist. These
5
+ * are namespaces an external attacker cannot register DNS-rebinding records under
6
+ * (tailscale MagicDNS, Cloudflare quick/named tunnels), so accepting them keeps
7
+ * the project's documented tunnel access paths working without reopening the
8
+ * rebinding hole. Extend per-deployment via CODEMAN_ALLOWED_HOSTS.
9
+ */
10
+ export declare const DEFAULT_TRUSTED_HOST_SUFFIXES: string[];
11
+ /** Policy inputs for the anti-DNS-rebinding Host allowlist + cross-site Origin guard. */
12
+ export interface HostPolicy {
13
+ /** The host the server is bound to (e.g. '127.0.0.1', '0.0.0.0', or a hostname). */
14
+ bindHost: string;
15
+ /** Extra allowed hosts: exact lowercased names, or a leading-dot '.suffix' for suffix matches. */
16
+ allowedHosts: string[];
17
+ /** Hostname of the currently-active Codeman-managed tunnel, if any. */
18
+ tunnelHost?: string | null;
19
+ }
20
+ /**
21
+ * Extract the lowercased hostname from a Host/authority value, stripping the port
22
+ * and IPv6 brackets. Returns null for empty/garbage input.
23
+ */
24
+ export declare function parseAuthorityHostname(authority: string | undefined): string | null;
25
+ /** Build a HostPolicy from the bind host, CODEMAN_ALLOWED_HOSTS, and an active tunnel URL. */
26
+ export declare function buildHostPolicy(bindHost: string, tunnelUrl?: string | null): HostPolicy;
27
+ /**
28
+ * True if a request's Host header is allowed. Blocks DNS-rebinding: a custom
29
+ * domain rebound to a loopback/LAN address still carries its own name in Host,
30
+ * which will not be in the allowlist.
31
+ */
32
+ export declare function isAllowedRequestHost(hostHeader: string | undefined, policy: HostPolicy): boolean;
33
+ /**
34
+ * True if a request's Origin is allowed for a state-changing / WebSocket request.
35
+ * A MISSING Origin is allowed: non-browser clients (curl, Claude Code hooks) omit
36
+ * it, while browsers always attach it on cross-origin state-changing/WS requests —
37
+ * so a forged cross-site request is caught while local automation keeps working.
38
+ * The opaque origin 'null' (sandboxed iframe, data: URL) is rejected.
39
+ */
40
+ export declare function isAllowedRequestOrigin(originHeader: string | undefined, policy: HostPolicy): boolean;
3
41
  //# sourceMappingURL=network-auth-policy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"network-auth-policy.d.ts","sourceRoot":"","sources":["../../src/web/network-auth-policy.ts"],"names":[],"mappings":"AAIA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEtE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAYxD"}
1
+ {"version":3,"file":"network-auth-policy.d.ts","sourceRoot":"","sources":["../../src/web/network-auth-policy.ts"],"names":[],"mappings":"AAIA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEtE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAYxD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,UAAyD,CAAC;AAEpG,yFAAyF;AACzF,MAAM,WAAW,UAAU;IACzB,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC;IACjB,kGAAkG;IAClG,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAiBnF;AAED,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,CAcvF;AAwBD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAIhG;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAQpG"}
@@ -16,4 +16,112 @@ export function isLoopbackBindHost(host) {
16
16
  }
17
17
  return normalized.startsWith('::ffff:127.');
18
18
  }
19
+ /**
20
+ * Hostname suffixes that are always accepted by the Host/Origin allowlist. These
21
+ * are namespaces an external attacker cannot register DNS-rebinding records under
22
+ * (tailscale MagicDNS, Cloudflare quick/named tunnels), so accepting them keeps
23
+ * the project's documented tunnel access paths working without reopening the
24
+ * rebinding hole. Extend per-deployment via CODEMAN_ALLOWED_HOSTS.
25
+ */
26
+ export const DEFAULT_TRUSTED_HOST_SUFFIXES = ['.ts.net', '.trycloudflare.com', '.cfargotunnel.com'];
27
+ /**
28
+ * Extract the lowercased hostname from a Host/authority value, stripping the port
29
+ * and IPv6 brackets. Returns null for empty/garbage input.
30
+ */
31
+ export function parseAuthorityHostname(authority) {
32
+ if (!authority)
33
+ return null;
34
+ let h = authority.trim();
35
+ if (!h)
36
+ return null;
37
+ if (h.startsWith('[')) {
38
+ // [::1] or [::1]:3000
39
+ const end = h.indexOf(']');
40
+ if (end === -1)
41
+ return null;
42
+ return h.slice(1, end).toLowerCase() || null;
43
+ }
44
+ // host:port — only treat a single trailing colon as a port separator so a
45
+ // bracketless IPv6 literal (multiple colons) is left intact.
46
+ const first = h.indexOf(':');
47
+ if (first !== -1 && first === h.lastIndexOf(':')) {
48
+ h = h.slice(0, first);
49
+ }
50
+ return h.toLowerCase() || null;
51
+ }
52
+ /** Build a HostPolicy from the bind host, CODEMAN_ALLOWED_HOSTS, and an active tunnel URL. */
53
+ export function buildHostPolicy(bindHost, tunnelUrl) {
54
+ const allowedHosts = (process.env.CODEMAN_ALLOWED_HOSTS || '')
55
+ .split(',')
56
+ .map((s) => s.trim().toLowerCase())
57
+ .filter(Boolean);
58
+ let tunnelHost = null;
59
+ if (tunnelUrl) {
60
+ try {
61
+ tunnelHost = new URL(tunnelUrl).hostname.toLowerCase();
62
+ }
63
+ catch {
64
+ tunnelHost = null;
65
+ }
66
+ }
67
+ return { bindHost, allowedHosts, tunnelHost };
68
+ }
69
+ function matchesHost(hostname, policy) {
70
+ // localhost is reserved (always resolves to loopback, not rebindable).
71
+ if (hostname === 'localhost')
72
+ return true;
73
+ // Any IP literal: a literal address cannot be the target of DNS rebinding — the
74
+ // browser connected straight to it, there is no name to re-point.
75
+ if (isIP(hostname) !== 0)
76
+ return true;
77
+ const bind = parseAuthorityHostname(policy.bindHost);
78
+ if (bind && hostname === bind)
79
+ return true;
80
+ if (policy.tunnelHost && hostname === policy.tunnelHost)
81
+ return true;
82
+ for (const suffix of DEFAULT_TRUSTED_HOST_SUFFIXES) {
83
+ if (hostname === suffix.slice(1) || hostname.endsWith(suffix))
84
+ return true;
85
+ }
86
+ for (const entry of policy.allowedHosts) {
87
+ if (entry.startsWith('.')) {
88
+ if (hostname === entry.slice(1) || hostname.endsWith(entry))
89
+ return true;
90
+ }
91
+ else if (hostname === entry) {
92
+ return true;
93
+ }
94
+ }
95
+ return false;
96
+ }
97
+ /**
98
+ * True if a request's Host header is allowed. Blocks DNS-rebinding: a custom
99
+ * domain rebound to a loopback/LAN address still carries its own name in Host,
100
+ * which will not be in the allowlist.
101
+ */
102
+ export function isAllowedRequestHost(hostHeader, policy) {
103
+ const hostname = parseAuthorityHostname(hostHeader);
104
+ if (!hostname)
105
+ return false;
106
+ return matchesHost(hostname, policy);
107
+ }
108
+ /**
109
+ * True if a request's Origin is allowed for a state-changing / WebSocket request.
110
+ * A MISSING Origin is allowed: non-browser clients (curl, Claude Code hooks) omit
111
+ * it, while browsers always attach it on cross-origin state-changing/WS requests —
112
+ * so a forged cross-site request is caught while local automation keeps working.
113
+ * The opaque origin 'null' (sandboxed iframe, data: URL) is rejected.
114
+ */
115
+ export function isAllowedRequestOrigin(originHeader, policy) {
116
+ if (originHeader === undefined || originHeader === '')
117
+ return true;
118
+ if (originHeader === 'null')
119
+ return false;
120
+ try {
121
+ return matchesHost(new URL(originHeader).hostname.toLowerCase(), policy);
122
+ }
123
+ catch {
124
+ return false;
125
+ }
126
+ }
19
127
  //# sourceMappingURL=network-auth-policy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"network-auth-policy.js","sourceRoot":"","sources":["../../src/web/network-auth-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAEjE,MAAM,UAAU,mBAAmB,CAAC,KAAyB;IAC3D,OAAO,KAAK,KAAK,SAAS,IAAI,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,UAAU,GAAG,IAAI;SACpB,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC/B,IAAI,UAAU,KAAK,WAAW,IAAI,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,iBAAiB,EAAE,CAAC;QAC3F,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,UAAU,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAC9C,CAAC"}
1
+ {"version":3,"file":"network-auth-policy.js","sourceRoot":"","sources":["../../src/web/network-auth-policy.ts"],"names":[],"mappings":"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"}
Binary file
@@ -10,7 +10,7 @@
10
10
  * @globals {function} scheduleBackground - scheduler.postTask wrapper (background priority)
11
11
  * @globals {function} getEventCoords - Unified mouse/touch coordinate extractor
12
12
  * @globals {function} escapeHtml - XSS-safe HTML escaping
13
- * @globals {object} SSE_EVENTS - Centralized SSE event type constants (~73 event types)
13
+ * @globals {object} SSE_EVENTS - Centralized SSE event type constants (120 event types; must match backend src/web/sse-events.ts)
14
14
  * @globals {Array} BUILTIN_RESPAWN_PRESETS - Built-in respawn configuration presets
15
15
  *
16
16
  * @dependency None (first in load order)
@@ -241,27 +241,45 @@ const SSE_EVENTS = {
241
241
  SESSION_IDLE: 'session:idle',
242
242
  SESSION_WORKING: 'session:working',
243
243
  SESSION_AUTO_CLEAR: 'session:autoClear',
244
+ SESSION_AUTO_COMPACT: 'session:autoCompact',
244
245
  SESSION_CLI_INFO: 'session:cliInfo',
246
+ SESSION_MESSAGE: 'session:message',
247
+ SESSION_INTERACTIVE: 'session:interactive',
248
+ SESSION_RUNNING: 'session:running',
245
249
 
246
250
  // Scheduled runs
247
251
  SCHEDULED_CREATED: 'scheduled:created',
248
252
  SCHEDULED_UPDATED: 'scheduled:updated',
249
253
  SCHEDULED_COMPLETED: 'scheduled:completed',
250
254
  SCHEDULED_STOPPED: 'scheduled:stopped',
255
+ SCHEDULED_LOG: 'scheduled:log',
256
+ SCHEDULED_DELETED: 'scheduled:deleted',
251
257
 
252
258
  // Respawn
253
259
  RESPAWN_STARTED: 'respawn:started',
254
260
  RESPAWN_STOPPED: 'respawn:stopped',
255
261
  RESPAWN_STATE_CHANGED: 'respawn:stateChanged',
256
262
  RESPAWN_CYCLE_STARTED: 'respawn:cycleStarted',
263
+ RESPAWN_CYCLE_COMPLETED: 'respawn:cycleCompleted',
257
264
  RESPAWN_BLOCKED: 'respawn:blocked',
258
- RESPAWN_AUTO_ACCEPT_SENT: 'respawn:autoAcceptSent',
265
+ RESPAWN_STEP_SENT: 'respawn:stepSent',
266
+ RESPAWN_STEP_COMPLETED: 'respawn:stepCompleted',
259
267
  RESPAWN_DETECTION_UPDATE: 'respawn:detectionUpdate',
268
+ RESPAWN_AUTO_ACCEPT_SENT: 'respawn:autoAcceptSent',
269
+ RESPAWN_AI_CHECK_STARTED: 'respawn:aiCheckStarted',
270
+ RESPAWN_AI_CHECK_COMPLETED: 'respawn:aiCheckCompleted',
271
+ RESPAWN_AI_CHECK_FAILED: 'respawn:aiCheckFailed',
272
+ RESPAWN_AI_CHECK_COOLDOWN: 'respawn:aiCheckCooldown',
273
+ RESPAWN_PLAN_CHECK_STARTED: 'respawn:planCheckStarted',
274
+ RESPAWN_PLAN_CHECK_COMPLETED: 'respawn:planCheckCompleted',
275
+ RESPAWN_PLAN_CHECK_FAILED: 'respawn:planCheckFailed',
260
276
  RESPAWN_TIMER_STARTED: 'respawn:timerStarted',
261
277
  RESPAWN_TIMER_CANCELLED: 'respawn:timerCancelled',
262
278
  RESPAWN_TIMER_COMPLETED: 'respawn:timerCompleted',
263
- RESPAWN_ERROR: 'respawn:error',
264
279
  RESPAWN_ACTION_LOG: 'respawn:actionLog',
280
+ RESPAWN_LOG: 'respawn:log',
281
+ RESPAWN_ERROR: 'respawn:error',
282
+ RESPAWN_CONFIG_UPDATED: 'respawn:configUpdated',
265
283
 
266
284
  // Tasks
267
285
  TASK_CREATED: 'task:created',
@@ -288,6 +306,12 @@ const SSE_EVENTS = {
288
306
  SESSION_BASH_TOOL_END: 'session:bashToolEnd',
289
307
  SESSION_BASH_TOOLS_UPDATE: 'session:bashToolsUpdate',
290
308
 
309
+ // Session: Plan
310
+ SESSION_PLAN_TASK_UPDATE: 'session:planTaskUpdate',
311
+ SESSION_PLAN_CHECKPOINT: 'session:planCheckpoint',
312
+ SESSION_PLAN_ROLLBACK: 'session:planRollback',
313
+ SESSION_PLAN_TASK_ADDED: 'session:planTaskAdded',
314
+
291
315
  // Hooks (Claude Code hook events)
292
316
  HOOK_IDLE_PROMPT: 'hook:idle_prompt',
293
317
  HOOK_PERMISSION_PROMPT: 'hook:permission_prompt',
@@ -338,6 +362,18 @@ const SSE_EVENTS = {
338
362
  ORCHESTRATOR_COMPLETED: 'orchestrator:completed',
339
363
  ORCHESTRATOR_ERROR: 'orchestrator:error',
340
364
 
365
+ // Teams (agent teams)
366
+ TEAM_CREATED: 'team:created',
367
+ TEAM_UPDATED: 'team:updated',
368
+ TEAM_REMOVED: 'team:removed',
369
+ TEAM_TASK_UPDATED: 'team:taskUpdated',
370
+
371
+ // Transcript
372
+ TRANSCRIPT_COMPLETE: 'transcript:complete',
373
+ TRANSCRIPT_PLAN_MODE: 'transcript:plan_mode',
374
+ TRANSCRIPT_TOOL_START: 'transcript:tool_start',
375
+ TRANSCRIPT_TOOL_END: 'transcript:tool_end',
376
+
341
377
  // Clipboard
342
378
  CLIPBOARD_WRITE: 'clipboard:write',
343
379
 
@@ -24,7 +24,7 @@
24
24
  <!-- Preload critical resources — lets browser discover these during HTML parse
25
25
  instead of waiting until <script> tags at bottom-of-body are reached. -->
26
26
  <link rel="preload" href="vendor/xterm.min.js" as="script">
27
- <link rel="preload" href="constants.cb6426c4.js" as="script">
27
+ <link rel="preload" href="constants.5b68d2de.js" as="script">
28
28
  <link rel="preload" href="app.c860ea08.js" as="script">
29
29
  <!-- Self-hosted xterm.js — eliminates CDN DNS/TLS latency (~100ms).
30
30
  'defer' preserves execution order (xterm loads before fit addon). -->
@@ -1078,6 +1078,24 @@
1078
1078
  <span id="tunnelUploadUrlDisplay" class="settings-item-value" style="cursor:pointer; text-decoration:underline; font-family:monospace; font-size:12px" title="Click to copy"></span>
1079
1079
  </div>
1080
1080
 
1081
+ <!-- Updates Section -->
1082
+ <div class="settings-section-header">Updates</div>
1083
+ <div class="settings-item" title="Codeman version currently running">
1084
+ <span class="settings-item-label">Current Version</span>
1085
+ <span class="settings-item-value" id="updateCurrentVersion" style="font-family:monospace">&mdash;</span>
1086
+ </div>
1087
+ <div class="settings-item" id="updateCheckRow" title="Check GitHub for a newer Codeman release">
1088
+ <span class="settings-item-label">Check for Updates</span>
1089
+ <button class="btn-toolbar btn-sm" id="updateCheckBtn" onclick="app.checkForUpdate()">Check now</button>
1090
+ </div>
1091
+ <div id="updateResult" style="display:none; padding:4px 2px 8px; font-size:13px; color:var(--text-secondary)"></div>
1092
+ <div class="settings-item" id="updateActionRow" style="display:none">
1093
+ <span class="settings-item-label" id="updateActionLabel">Update available</span>
1094
+ <button class="btn-toolbar btn-sm btn-primary" id="updateNowBtn" onclick="app.startSelfUpdate()">Update now</button>
1095
+ </div>
1096
+ <div id="updateNotes" style="display:none; max-height:160px; overflow:auto; padding:8px 10px; margin:4px 0 8px; font-size:12px; line-height:1.45; white-space:pre-wrap; word-break:break-word; background:rgba(127,127,127,0.08); border:1px solid var(--border); border-radius:6px"></div>
1097
+ <div id="updateProgress" style="display:none; padding:8px 10px; margin:4px 0 8px; font-size:13px; border:1px solid var(--border); border-radius:6px"></div>
1098
+
1081
1099
  </div>
1082
1100
  </div>
1083
1101
  <!-- Tab-Switch Tab -->
@@ -1816,7 +1834,7 @@
1816
1834
  <!-- Lines drawn dynamically -->
1817
1835
  </svg>
1818
1836
 
1819
- <script defer src="constants.cb6426c4.js"></script>
1837
+ <script defer src="constants.5b68d2de.js"></script>
1820
1838
  <script defer src="mobile-handlers.1e2a8ef8.js"></script>
1821
1839
  <script defer src="voice-input.085e9e73.js"></script>
1822
1840
  <script defer src="notification-manager.9c984ac2.js"></script>
@@ -1827,8 +1845,8 @@
1827
1845
  <script defer src="respawn-ui.5377f958.js"></script>
1828
1846
  <script defer src="ralph-panel.61076370.js"></script>
1829
1847
  <script defer src="orchestrator-panel.js"></script>
1830
- <script defer src="settings-ui.c06be9c3.js"></script>
1831
- <script defer src="panels-ui.3e304caf.js"></script>
1848
+ <script defer src="settings-ui.da0621e1.js"></script>
1849
+ <script defer src="panels-ui.5192a2c0.js"></script>
1832
1850
  <script defer src="session-ui.3e0cf024.js"></script>
1833
1851
  <script defer src="ralph-wizard.52d533d2.js"></script>
1834
1852
  <script defer src="api-client.3adebdc2.js"></script>
Binary file
Binary file