@omega.js/desktop 0.51.0 → 0.53.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 (289) hide show
  1. package/README.md +18 -13
  2. package/dist/assets/css/core/_initialize.scss +1 -1
  3. package/dist/assets/js/core/app-shell.js +14 -15
  4. package/dist/assets/themes/_template/_theme.js +6 -6
  5. package/dist/assets/themes/base/_includes/global/sections/account.html +4 -4
  6. package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +5 -5
  7. package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +3 -3
  8. package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +1 -1
  9. package/dist/assets/themes/base/_layouts/frontend/pages/blog/tags/tag.html +1 -1
  10. package/dist/assets/themes/base/_layouts/frontend/pages/payment/confirmation.html +1 -1
  11. package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.js +2 -3
  12. package/dist/assets/themes/base/_sections/verts/unit/section.html +1 -1
  13. package/dist/assets/themes/base/_sections/verts/unit/section.js +3 -4
  14. package/dist/assets/themes/base/_theme.js +4 -3
  15. package/dist/assets/themes/bootstrap/_theme.js +2 -2
  16. package/dist/assets/themes/bootstrap/overrides/_links.scss +1 -1
  17. package/dist/assets/themes/classy/_theme.js +8 -6
  18. package/dist/assets/themes/classy/css/marketing/_sections.scss +1 -2
  19. package/dist/assets/themes/classy/js/hero-demo-form.js +3 -2
  20. package/dist/assets/themes/neobrutalism/_theme.js +5 -5
  21. package/dist/assets/themes/neobrutalism/js/pages/test/libraries/layers/index.js +1 -1
  22. package/dist/assets/themes/newsflash/_theme.js +6 -6
  23. package/dist/assets/themes/newsflash/js/pages/test/libraries/layers/index.js +1 -1
  24. package/dist/build.js +87 -111
  25. package/dist/cli.js +1 -1
  26. package/dist/commands/build.js +2 -2
  27. package/dist/commands/cdp/capture.js +2 -2
  28. package/dist/commands/cdp/quit.js +2 -2
  29. package/dist/commands/cdp/relaunch.js +2 -2
  30. package/dist/commands/cdp/theme.js +1 -1
  31. package/dist/commands/clean.js +2 -2
  32. package/dist/commands/deploy.js +4 -4
  33. package/dist/commands/finalize-release.js +4 -4
  34. package/dist/commands/install.js +3 -3
  35. package/dist/commands/launch.js +2 -2
  36. package/dist/commands/lib/deploy-precheck.js +3 -3
  37. package/dist/commands/lib/ensure-target.js +6 -6
  38. package/dist/commands/package.js +2 -2
  39. package/dist/commands/publish.js +2 -2
  40. package/dist/commands/release.js +3 -3
  41. package/dist/commands/runner.js +145 -48
  42. package/dist/commands/sign-windows.js +5 -5
  43. package/dist/commands/test.js +4 -4
  44. package/dist/commands/update.js +2 -2
  45. package/dist/commands/validate-certs.js +4 -4
  46. package/dist/commands/version.js +3 -3
  47. package/dist/defaults/.github/workflows/build.yml +2 -0
  48. package/dist/defaults/AGENTS.md +17 -8
  49. package/dist/defaults/config/omega.json5 +7 -7
  50. package/dist/defaults/hooks/build/post.js +1 -1
  51. package/dist/defaults/hooks/build/pre.js +1 -1
  52. package/dist/defaults/hooks/deploy/pre.js +1 -1
  53. package/dist/defaults/hooks/release/post.js +1 -1
  54. package/dist/defaults/hooks/release/pre.js +1 -1
  55. package/dist/defaults/src/assets/js/components/about/index.js +3 -5
  56. package/dist/defaults/src/assets/js/components/main/index.js +3 -5
  57. package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
  58. package/dist/defaults/src/integrations/context-menu/index.js +2 -2
  59. package/dist/defaults/src/integrations/menu/index.js +3 -3
  60. package/dist/defaults/src/integrations/tray/index.js +3 -3
  61. package/dist/defaults/src/main.js +3 -5
  62. package/dist/defaults/src/preload.js +3 -5
  63. package/dist/defaults/test/README.md +2 -2
  64. package/dist/gulp/main.js +9 -10
  65. package/dist/gulp/tasks/audit.js +7 -7
  66. package/dist/gulp/tasks/build-config.js +8 -8
  67. package/dist/gulp/tasks/bundle.js +16 -16
  68. package/dist/gulp/tasks/defaults.js +3 -3
  69. package/dist/gulp/tasks/distribute.js +2 -2
  70. package/dist/gulp/tasks/html.js +9 -9
  71. package/dist/gulp/tasks/package-quick.js +3 -3
  72. package/dist/gulp/tasks/package.js +3 -3
  73. package/dist/gulp/tasks/release.js +3 -3
  74. package/dist/gulp/tasks/sass.js +6 -6
  75. package/dist/gulp/tasks/serve.js +4 -4
  76. package/dist/hooks/notarize-artifacts.js +1 -1
  77. package/dist/hooks/notarize.js +1 -1
  78. package/dist/index.js +5 -8
  79. package/dist/lib/_environment-mixin.js +50 -0
  80. package/dist/lib/_lifecycle-mixin.js +45 -0
  81. package/dist/lib/analytics.js +33 -35
  82. package/dist/lib/app-state.js +14 -14
  83. package/dist/lib/auth-flow.js +18 -18
  84. package/dist/lib/auth-persistence.js +12 -12
  85. package/dist/lib/auth.js +421 -0
  86. package/dist/lib/auto-updater.js +49 -49
  87. package/dist/lib/context-menu.js +13 -13
  88. package/dist/lib/context.js +19 -19
  89. package/dist/lib/deep-link.js +34 -34
  90. package/dist/lib/fontawesome.js +5 -5
  91. package/dist/lib/ipc.js +4 -4
  92. package/dist/lib/menu.js +25 -25
  93. package/dist/lib/protocol.js +5 -5
  94. package/dist/lib/remote-config.js +22 -22
  95. package/dist/lib/remote-scripts.js +21 -21
  96. package/dist/lib/restart-manager/index.js +28 -28
  97. package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
  98. package/dist/lib/sign-helpers/sign-events.js +1 -1
  99. package/dist/lib/startup.js +18 -13
  100. package/dist/lib/storage.js +10 -10
  101. package/dist/lib/templating.js +16 -16
  102. package/dist/lib/theme.js +10 -10
  103. package/dist/lib/tray.js +27 -27
  104. package/dist/lib/usage.js +11 -11
  105. package/dist/lib/window-manager.js +26 -26
  106. package/dist/main.js +398 -483
  107. package/dist/preload.js +236 -176
  108. package/dist/renderer.js +417 -391
  109. package/dist/runner/job-started.js +1 -1
  110. package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
  111. package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
  112. package/dist/test/fixtures/consumer-app/src/main.js +5 -7
  113. package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
  114. package/dist/test/harness/boot-entry.js +22 -20
  115. package/dist/test/harness/main-entry.js +31 -30
  116. package/dist/test/harness/renderer-entry.js +5 -5
  117. package/dist/test/harness/renderer-preload.js +137 -141
  118. package/dist/test/index.js +10 -10
  119. package/dist/test/runner.js +2 -2
  120. package/dist/test/runners/boot.js +7 -6
  121. package/dist/test/runners/electron.js +3 -2
  122. package/dist/test/runners/render-event.js +2 -2
  123. package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
  124. package/dist/test/suites/boot/restart-manager.test.js +2 -2
  125. package/dist/test/suites/boot/storage-bundled.test.js +5 -5
  126. package/dist/test/suites/boot/theme.test.js +13 -13
  127. package/dist/test/suites/build/audit.test.js +1 -1
  128. package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
  129. package/dist/test/suites/build/boot-fixture.test.js +2 -2
  130. package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
  131. package/dist/test/suites/build/brand-scss.test.js +1 -1
  132. package/dist/test/suites/build/build-json-bake.test.js +1 -1
  133. package/dist/test/suites/build/cli.test.js +2 -2
  134. package/dist/test/suites/build/config-schema.test.js +5 -5
  135. package/dist/test/suites/build/defaults-scaffold.test.js +2 -2
  136. package/dist/test/suites/build/deploy-hook.test.js +3 -3
  137. package/dist/test/suites/build/ensure-target.test.js +2 -2
  138. package/dist/test/suites/build/env-delivery.test.js +2 -2
  139. package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
  140. package/dist/test/suites/build/exports.test.js +9 -8
  141. package/dist/test/suites/build/get-config.test.js +4 -4
  142. package/dist/test/suites/build/manifest-deps.test.js +1 -1
  143. package/dist/test/suites/build/merge-line-files.test.js +1 -1
  144. package/dist/test/suites/build/omega-shell.test.js +34 -2
  145. package/dist/test/suites/build/omega.test.js +350 -0
  146. package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
  147. package/dist/test/suites/build/runner.test.js +612 -5
  148. package/dist/test/suites/build/sentry.test.js +2 -2
  149. package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
  150. package/dist/test/suites/build/templating.test.js +3 -3
  151. package/dist/test/suites/build/test-stealth.test.js +7 -9
  152. package/dist/test/suites/build/url-helpers.test.js +55 -56
  153. package/dist/test/suites/build/validate-config.test.js +2 -2
  154. package/dist/test/suites/build/wave5-pins.test.js +2 -2
  155. package/dist/test/suites/main/analytics.test.js +59 -59
  156. package/dist/test/suites/main/app-state.test.js +66 -66
  157. package/dist/test/suites/main/auth-flow.test.js +41 -41
  158. package/dist/test/suites/main/auth-persistence.test.js +54 -43
  159. package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
  160. package/dist/test/suites/main/auth.test.js +336 -0
  161. package/dist/test/suites/main/auto-updater.test.js +134 -134
  162. package/dist/test/suites/main/boot-sequence.test.js +37 -49
  163. package/dist/test/suites/main/context-menu.test.js +51 -50
  164. package/dist/test/suites/main/context.test.js +25 -25
  165. package/dist/test/suites/main/deep-link.test.js +74 -74
  166. package/dist/test/suites/main/fontawesome.test.js +27 -27
  167. package/dist/test/suites/main/ipc.test.js +35 -35
  168. package/dist/test/suites/main/menu.test.js +101 -100
  169. package/dist/test/suites/main/protocol.test.js +19 -19
  170. package/dist/test/suites/main/remote-config.test.js +63 -63
  171. package/dist/test/suites/main/remote-scripts.test.js +103 -103
  172. package/dist/test/suites/main/request.test.js +71 -0
  173. package/dist/test/suites/main/restart-manager.test.js +33 -33
  174. package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
  175. package/dist/test/suites/main/startup.test.js +26 -26
  176. package/dist/test/suites/main/stealth-window.test.js +1 -1
  177. package/dist/test/suites/main/storage.test.js +25 -25
  178. package/dist/test/suites/main/theme.test.js +34 -34
  179. package/dist/test/suites/main/tray.test.js +79 -79
  180. package/dist/test/suites/main/url-helpers.test.js +133 -133
  181. package/dist/test/suites/main/usage.test.js +25 -25
  182. package/dist/test/suites/main/window-bounds.test.js +27 -27
  183. package/dist/test/suites/main/window-manager.test.js +44 -44
  184. package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
  185. package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
  186. package/dist/test/suites/renderer/round-trip.test.js +3 -3
  187. package/dist/test/suites/renderer/tooltips.test.js +15 -15
  188. package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +27 -7
  189. package/dist/test/utils/extended-mode-warning.js +1 -1
  190. package/dist/utils/boot-harness.js +56 -0
  191. package/dist/utils/mode-helpers.js +2 -15
  192. package/dist/utils/ship-keys.js +3 -3
  193. package/dist/utils/signing-status.js +51 -0
  194. package/dist/utils/test-events.js +7 -0
  195. package/dist/utils/test-stealth.js +6 -6
  196. package/dist/utils/url-helpers.js +52 -42
  197. package/dist/utils/user-agent.js +44 -0
  198. package/dist/vendor/account/engine.js +3 -3
  199. package/dist/vendor/account/index.js +14 -45
  200. package/dist/vendor/account/resolve-account.js +44 -0
  201. package/dist/vendor/account/schema.js +1 -1
  202. package/dist/vendor/account/user.js +99 -0
  203. package/dist/vendor/config/client-config.js +1 -1
  204. package/dist/vendor/config/environment.js +11 -30
  205. package/dist/vendor/config/index.js +13 -12
  206. package/dist/vendor/config/load.js +1 -2
  207. package/dist/vendor/config/platforms.js +1 -1
  208. package/dist/vendor/config/repo.js +24 -0
  209. package/dist/vendor/config/retired-keys.js +2 -2
  210. package/dist/vendor/config/schema.js +5 -8
  211. package/dist/vendor/config/site-global.js +2 -3
  212. package/dist/vendor/config/validate.js +1 -2
  213. package/dist/vendor/config/winback.js +1 -1
  214. package/dist/vendor/devkit/actions-secrets.js +1 -1
  215. package/dist/vendor/devkit/attach-log-file.js +1 -1
  216. package/dist/vendor/devkit/brand-version.js +162 -1
  217. package/dist/vendor/devkit/build-json.js +1 -1
  218. package/dist/vendor/devkit/cli-router.js +3 -4
  219. package/dist/vendor/devkit/defaults-engine.js +9 -11
  220. package/dist/vendor/devkit/deploy.js +64 -4
  221. package/dist/vendor/devkit/git-remote.js +78 -1
  222. package/dist/vendor/devkit/local.js +53 -3
  223. package/dist/vendor/devkit/lockfile.js +127 -0
  224. package/dist/vendor/devkit/merge-line-files.js +2 -3
  225. package/dist/vendor/devkit/pack-local.js +4 -7
  226. package/dist/vendor/devkit/preludes/origin-heal.js +35 -49
  227. package/dist/vendor/devkit/target-secrets.js +34 -45
  228. package/dist/vendor/devkit/test/runner-core.js +6 -6
  229. package/dist/vendor/monitoring/env.js +2 -2
  230. package/dist/vendor/monitoring/index.js +1 -1
  231. package/dist/vendor/monitoring/main.js +1 -1
  232. package/dist/vendor/monitoring/preload.js +1 -1
  233. package/dist/vendor/monitoring/renderer.js +1 -1
  234. package/docs/analytics.md +8 -8
  235. package/docs/app-state.md +19 -19
  236. package/docs/audit.md +4 -4
  237. package/docs/{client-bridge.md → auth.md} +88 -73
  238. package/docs/auto-updater.md +8 -8
  239. package/docs/boot-sequence.md +11 -6
  240. package/docs/build-system.md +1 -1
  241. package/docs/cdp-debugging.md +1 -1
  242. package/docs/common-mistakes.md +7 -7
  243. package/docs/config-schema.md +1 -1
  244. package/docs/context-menu.md +13 -13
  245. package/docs/context.md +11 -11
  246. package/docs/css.md +3 -9
  247. package/docs/deep-link.md +25 -25
  248. package/docs/environment-detection.md +16 -16
  249. package/docs/fontawesome.md +7 -5
  250. package/docs/hooks.md +8 -8
  251. package/docs/index.md +39 -28
  252. package/docs/ipc.md +10 -10
  253. package/docs/lib-modules.md +9 -9
  254. package/docs/logging.md +12 -14
  255. package/docs/menu.md +18 -18
  256. package/docs/releasing.md +4 -2
  257. package/docs/remote-config.md +9 -9
  258. package/docs/remote-scripts.md +12 -12
  259. package/docs/restart-manager.md +8 -8
  260. package/docs/runner.md +12 -10
  261. package/docs/sentry.md +4 -4
  262. package/docs/shared/analytics.md +1 -1
  263. package/docs/shared/brands.md +1 -1
  264. package/docs/shared/breaking-changes.md +79 -13
  265. package/docs/shared/config.md +24 -21
  266. package/docs/shared/deploys.md +30 -7
  267. package/docs/shared/local-dev.md +5 -3
  268. package/docs/shared/logging.md +1 -1
  269. package/docs/shared/monitoring.md +5 -5
  270. package/docs/shared/testing.md +2 -2
  271. package/docs/shared/theming.md +1 -1
  272. package/docs/shared/translation.md +19 -10
  273. package/docs/signing.md +1 -1
  274. package/docs/startup.md +16 -16
  275. package/docs/storage.md +11 -11
  276. package/docs/templating.md +3 -3
  277. package/docs/test-boot-layer.md +12 -12
  278. package/docs/test-framework.md +17 -17
  279. package/docs/themes.md +7 -7
  280. package/docs/tooltips.md +2 -2
  281. package/docs/tray.md +31 -31
  282. package/docs/usage.md +7 -7
  283. package/docs/verts.md +1 -1
  284. package/docs/windows.md +22 -22
  285. package/package.json +3 -4
  286. package/dist/lib/client-bridge.js +0 -374
  287. package/dist/lib/logger.js +0 -4
  288. package/dist/test/suites/build/manager.test.js +0 -213
  289. package/dist/test/suites/main/client-bridge.test.js +0 -262
package/docs/index.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  > **Note for contributors and Claude:** This file is the guide for `@omega.js/desktop` — identity, top-level conventions, and a map to the deep references. It lives in the monorepo's `docs/` tree and is loaded on demand (the omega Claude plugin's hooks inject it by context; the repo-root AGENTS.md map is the one agent entry — packages carry no agent docs). The **meat** (per-subsystem APIs, edge cases, behavior tables, defaults lists) lives in the package's own [`docs/<topic>.md`](../docs) files. When extending or adding content, write it in the matching `docs/*.md` file and cross-link from here — do NOT inline it. If a topic doesn't have a doc yet, create one.
4
4
 
5
- > **Mirrored structure:** the four framework guides — `docs/web/index.md`, `docs/backend/index.md`, `docs/extension/index.md`, and `docs/desktop/index.md` — mirror each other (the legacy UJM/BEM/BXM/EM lineage): shared sections (Supply-Chain Security, Development Workflow, File Conventions, Doc-update parity, etc.) appear in the **same order at the same position** across all four. When adding a section that applies to multiple frameworks, insert it in the same spot in all of them.
5
+ > **Mirrored structure:** the four framework guides (`docs/web/index.md`, `docs/backend/index.md`, `docs/extension/index.md`, and `docs/desktop/index.md`) mirror each other: shared sections (Supply-Chain Security, Development Workflow, File Conventions, Doc-update parity, etc.) appear in the **same order at the same position** across all four. When adding a section that applies to multiple frameworks, insert it in the same spot in all of them. Each consumer template (`src/defaults/AGENTS.md`; web's lives at `scaffold/AGENTS.md`, beside its one-line `@AGENTS.md` `CLAUDE.md` pointer) mirrors its guide the same way.
6
6
 
7
7
  ## Identity
8
8
 
9
- OMEGA Desktop (@omega.js/desktop) is a comprehensive framework for building modern Electron desktop apps. Sister project to @omega.js/extension and Ultimate Jekyll Manager (UJM). Provides one-line-import bootstrap per Electron process, modular feature library with file-based extensibility, a multi-platform build/release pipeline, and a built-in test framework.
9
+ OMEGA Desktop (@omega.js/desktop) is a comprehensive framework for building modern Electron desktop apps, the desktop of the OMEGA family beside @omega.js/web, @omega.js/extension and @omega.js/backend. Each process module's default export is ONE ready-made instance, `omega`. It provides a one-line-import bootstrap per Electron process, a modular feature library with file-based extensibility, a multi-platform build/release pipeline, and a built-in test framework.
10
10
 
11
11
  ## Recommended skills
12
12
 
@@ -15,7 +15,7 @@ OMEGA Desktop (@omega.js/desktop) is a comprehensive framework for building mode
15
15
 
16
16
  ## 🚨 READ @omega.js/client TOO
17
17
 
18
- **@omega.js/desktop ships `@omega.js/client` as a runtime singleton inside the renderer process** — it powers auth, Firebase, reactive `data-omega-bind` directives, analytics, error tracking, and utilities (`escapeHTML`, etc.). Any task that touches auth flows, Firestore reads/writes, subscription resolution, push notifications, or DOM bindings means you are working with @omega.js/client as much as with @omega.js/desktop.
18
+ **@omega.js/desktop's renderer instance extends `@omega.js/client`'s base class**: `omega.auth`, `omega.storage`, `omega.bindings`, `omega.firestore` and the rest of the client are properties of the renderer's `omega`, beside `omega.desktop`, the preload's bridge to main. The client powers auth, Firebase, reactive `data-omega-bind` directives, analytics, error tracking, and utilities (`escapeHTML`, etc.). Any task that touches auth flows, Firestore reads/writes, subscription resolution, push notifications, or DOM bindings means you are working with @omega.js/client as much as with @omega.js/desktop.
19
19
 
20
20
  **Required reading:**
21
21
  - **`docs/client/index.md`** (in the framework monorepo) — the client guide: identity, module list, conventions
@@ -52,59 +52,70 @@ OMEGA Desktop (@omega.js/desktop) is a comprehensive framework for building mode
52
52
 
53
53
  ## Architecture
54
54
 
55
- ### Per-process Manager singletons
55
+ ### The consumer entry
56
56
 
57
- Each Electron process has its own one-line bootstrap:
57
+ Each Electron process's module exports ONE ready-made instance, `omega`; the class is exported by name (`Omega`) for tests only, and a consumer never writes `new`:
58
58
 
59
59
  ```js
60
60
  // src/main.js
61
- new (require('@omega.js/desktop/main'))().initialize(); // auto-loads JSON5 config
61
+ const omega = require('@omega.js/desktop/main'); // auto-loads JSON5 config
62
+ omega.initialize().then(() => { const { logger, windows } = omega; });
62
63
 
63
64
  // src/preload.js
64
- new (require('@omega.js/desktop/preload'))().initialize(); // exposes window.desktop
65
+ const omega = require('@omega.js/desktop/preload'); // exposes window.desktop
66
+ omega.initialize();
65
67
 
66
68
  // src/assets/js/components/<view>/index.js
67
- new (require('@omega.js/desktop/renderer'))().initialize();
69
+ import omega from '@omega.js/desktop/renderer';
70
+ omega.initialize().then(() => { const { logger, desktop } = omega; });
68
71
  ```
69
72
 
70
- `manager.initialize()` runs a fixed boot order (startup → ipc → storage → theme → sentry → protocol → deepLink → appState → whenReady → autoUpdater → tray/menu/contextMenu → startup → omega → remoteConfig → remoteScripts → windows). See [docs/boot-sequence.md](../docs/boot-sequence.md) for the full ordered list + rationale.
73
+ `initialize()` returns the instance, and `omega.ready` is the same promise, so a module that did not call it can still await it. In main, `omega.initialize()` runs a fixed boot order (startup → ipc → storage → theme → fontawesome → sentry → protocol → deepLink → authFlow → appState → context → usage → whenReady → autoUpdater → tray/menu/contextMenu → startup → auth → remoteConfig → remoteScripts → analytics → restartManager → windows). See [docs/boot-sequence.md](../docs/boot-sequence.md) for the full ordered list + rationale.
74
+
75
+ ### The instance (`omega`)
76
+
77
+ - **main**: every lib is a plain property: `omega.windows`, `tray`, `menu`, `contextMenu`, `ipc`, `storage`, `deepLink`, `autoUpdater`, `appState`, `startup`, `protocol`, `authFlow`, `theme`, `fontawesome`, `context`, `usage`, `remoteConfig`, `remoteScripts`, `restartManager`, `analytics`, `sentry`, `logger`, plus `config`, the environment helpers, the URL helpers (`getApiUrl()`, `getWebsiteUrl()`, `getFunctionsUrl()`, `getAuthUrl()`), `quit()`, `relaunch()`, `openAuthFlow()`, `request(url, options)` (the client base's harmonized API fetch, carrying a fresh Bearer token from main's session when signed in) and `require(name)`. `omega.auth` is the signed-in account: `.user` (always a `User`), `.listen()`, `.signOut()`, `.getIdToken()`, `.handleToken()` ([docs/auth.md](../docs/auth.md)).
78
+ - **preload**: exposes `window.desktop` through `contextBridge`; `omega.logger` and the environment helpers.
79
+ - **renderer**: `@omega.js/client`'s base class (`omega.auth`, `omega.storage` the page store, `omega.bindings`, `omega.firestore`, ...) plus `omega.desktop`, the preload's bridge under main's names: `omega.desktop.{ipc,storage,theme,fontawesome,autoUpdater,analytics,context,usage,remoteConfig}`. `omega.desktop.storage` is the app store, async over IPC. The renderer carries the same auth click triggers as the extension's pages: `.omega-signin` runs main's `openAuthFlow()`, `.omega-account` opens the website's `/account` page in the user's browser, and `.omega-signout` (the client's trigger) signs the whole app out through main, whose broadcast then signs every window out ([docs/auth.md](../docs/auth.md)).
71
80
 
72
81
  ### Lib modules
73
82
 
74
- `src/lib/*.js` — every Electron concern its own module. Each exports a singleton with `initialize(manager)`. Deep dive per module: see `docs/<lib-name>.md`. Authoring guide (initialization contract, adding a new lib, flat-vs-split): [docs/lib-modules.md](../docs/lib-modules.md).
83
+ `src/lib/*.js`: every Electron concern its own module. Each exports one object with `initialize(omega)`, and main hangs it on the instance by name. Deep dive per module: see `docs/<lib-name>.md`. Authoring guide (initialization contract, adding a new lib, flat-vs-split): [docs/lib-modules.md](../docs/lib-modules.md).
75
84
 
76
85
  | Module | Description |
77
86
  |---|---|
78
87
  | `ipc` | typed channel bus, single registration point |
79
88
  | `storage` | electron-store wrapper, sync main / async renderer via IPC |
80
- | `theme` | system-aware appearance — `nativeTheme.themeSource` ('system'/'light'/'dark'), persisted override, live `<html data-bs-theme>` in every renderer via matchMedia |
89
+ | `theme` | system-aware appearance: `nativeTheme.themeSource` ('system'/'light'/'dark'), persisted override, live `<html data-bs-theme>` in every renderer via matchMedia |
81
90
  | `window-manager` | lazy-creation registry, bounds persistence, Discord-style hide-on-close, inset titlebar, dock-show on first window, re-surface on user re-launch |
82
91
  | `tray` / `menu` / `context-menu` | file-based definitions; unified id-path API; default templates with id-tagged items |
83
92
  | `startup` | `mode: 'normal' \| 'hidden'`; `'hidden'` bakes `LSUIElement: true` for zero dock bounce |
84
93
  | `app-state` | storage-backed launch flags + crash sentinel |
85
94
  | `protocol` | single-instance lock + scheme registration |
95
+ | `fontawesome` | serves the bundled icon SVGs to renderers over IPC (`desktop:fontawesome:get`); the renderer auto-renders `fa-*` markup ([docs/fontawesome.md](../docs/fontawesome.md)) |
86
96
  | `deep-link` | unified deep-link dispatch (cold + warm start, mac + win + linux), built-in routes, pattern matching |
87
- | `client-bridge` | main = source-of-truth Firebase Auth, renderers reflect via IPC; session persists via `auth-persistence`; renderers push the @omega.js/client-resolved plan → `getResolvedPlan()` |
97
+ | `auth` | `omega.auth`: main = source-of-truth Firebase Auth, renderers reflect via IPC; session persists via `auth-persistence`; renderers push the account document their client resolved, so main's `omega.auth.user` is the same `User` |
98
+ | `auth-flow` | `omega.authFlow` / `omega.openAuthFlow()`: the sign-in round trip in the user's default browser, returning over the deep link (production) or a one-shot loopback listener (dev/test) |
88
99
  | `auth-persistence` | pluggable main-session vault (default: safeStorage OS-keychain encryption; `omega.authPersistence` config) |
89
100
  | `auto-updater` | electron-updater wrapper, idle-aware install, 30-day pending gate, dev simulation |
90
101
  | `sentry` | `@omega.js/monitoring` — the shared error-reporting contract, auto auth attribution, dev-mode gating |
91
- | `templating` | `{{ }}` token replacement (BXM/UJM convention), used at build time by `gulp/html` |
92
- | `context` | runtime info — `manager.context.{geolocation,client,session,app}` |
102
+ | `templating` | `{{ }}` token replacement, used at build time by `gulp/html` |
103
+ | `context` | runtime info: `omega.context.{geolocation,client,session,app}` |
93
104
  | `usage` | `opens` / `hoursTotal` / `hoursThisSession`; crash-safe |
94
105
  | `remote-config` | "Hot config" fetched from `${brand.url}/data/resources/main.json`, polled hourly |
95
- | `remote-scripts` | Emergency remote code execution — OPT-IN (`remoteScripts.enabled: true`) + https-only; fetches `${brand.url}/data/scripts/main.js`, content-hash dedup, async `manager` + `require` in scope |
106
+ | `remote-scripts` | Emergency remote code execution: OPT-IN (`remoteScripts.enabled: true`) + https-only; fetches `${brand.url}/data/scripts/main.js`, content-hash dedup, async `omega` + `require` in scope |
96
107
  | `analytics` | GA4 Measurement Protocol; cross-platform `uuidv5` identity; the app's ONE sender — renderer events forward here over IPC ([docs/analytics.md](../docs/analytics.md)) |
97
108
  | `restart-manager` | external guardian app for crash relaunches — localhost HTTP protocol v1 (register/heartbeat/deregister), silent install when missing (mac zip / win NSIS `/S` / linux AppImage; RM self-updates via its own @omega.js/desktop autoUpdater); split dir ships the protocol SSOT the RM app imports |
98
109
 
99
110
  ### File-based feature definitions
100
111
 
101
- Trays, menus, and context-menus are NOT defined in config — they're defined in JS files the consumer authors at fixed conventional paths (`src/integrations/{tray,menu,context-menu}/index.js`). To opt out, call `manager.{tray,menu,contextMenu}.disable()` at runtime.
112
+ Trays, menus, and context-menus are NOT defined in config: they're defined in JS files the consumer authors at fixed conventional paths (`src/integrations/{tray,menu,context-menu}/index.js`). To opt out, call `omega.{tray,menu,contextMenu}.disable()` at runtime. Each file exports one function of an object: `({ omega, tray })`, `({ omega, menu, defaults })`, and `({ omega, menu, params, webContents })` for the context menu, called per right-click.
102
113
 
103
114
  All three ship sensible default templates and share a unified id-path API (`.find/.has/.update/.remove/.enable/.show/.hide/.insertBefore/.insertAfter/.appendTo`), implemented once in `src/lib/_menu-mixin.js`. See [docs/tray.md](../docs/tray.md), [docs/menu.md](../docs/menu.md), [docs/context-menu.md](../docs/context-menu.md).
104
115
 
105
116
  ### Windows
106
117
 
107
- @omega.js/desktop does NOT auto-create any windows. Consumers call `manager.windows.create('main', { show: !startup.isLaunchHidden() })` from inside `manager.initialize().then(...)`. Inset titlebar by default; Discord-style hide-on-close on `main`; auto re-surface on user re-launch. See [docs/windows.md](../docs/windows.md).
118
+ @omega.js/desktop does NOT auto-create any windows. Consumers call `omega.windows.create('main', { show: !startup.isLaunchHidden() })` from inside `omega.initialize().then(...)`. Inset titlebar by default; Discord-style hide-on-close on `main`; auto re-surface on user re-launch. See [docs/windows.md](../docs/windows.md).
108
119
 
109
120
  ### Icons
110
121
 
@@ -148,7 +159,7 @@ All three bundles strip `@dev-only` blocks in production builds — code between
148
159
 
149
160
  ### Config flow
150
161
 
151
- `config/omega.json5` (JSON5, in consumer; shared sections top-level + desktop settings under `targets.desktop`) → `Manager.getConfig()` (resolves via `@omega.js/config`: `targets.desktop` overlays the top level, brand-monorepo walk-up included), then applies derived defaults: `app.appId` ← `<certificates.providers.apple.bundleIdPrefix>.<brand.id>` with the brand id's dashes as dots, the very id the certificates service registers ([#909](https://github.com/Omega-JS-Stack/omega/issues/909); no prefix declared, and it falls back to the reverse-domain of `brand.url`, then `app.<brand.id>`), `app.productName` ← `brand.name`) → injected into the NODE bundles (main, preload) at build time as an esbuild `define` of `OMEGA_BUILD_JSON` plus a banner that assigns the same literal to `globalThis`, and written for the RENDERER as the ONE `dist/build.js` every view's shell loads with its first script tag ([#743](https://github.com/Omega-JS-Stack/omega/issues/743), the same file and the same load order web and the extension use). Runtime reads `OMEGA_BUILD_JSON.config` first (authoritative in packaged apps); dev falls back to resolving from disk.
162
+ `config/omega.json5` (JSON5, in consumer; shared sections top-level + desktop settings under `targets.desktop`) → `build.getConfig()` (resolves via `@omega.js/config`: `targets.desktop` overlays the top level, brand-monorepo walk-up included), then applies derived defaults: `app.appId` ← `<certificates.providers.apple.bundleIdPrefix>.<brand.id>` with the brand id's dashes as dots, the very id the certificates service registers ([#909](https://github.com/Omega-JS-Stack/omega/issues/909); no prefix declared, and it falls back to the reverse-domain of `brand.url`, then `app.<brand.id>`), `app.productName` ← `brand.name`) → injected into the NODE bundles (main, preload) at build time as an esbuild `define` of `OMEGA_BUILD_JSON` plus a banner that assigns the same literal to `globalThis`, and written for the RENDERER as the ONE `dist/build.js` every view's shell loads with its first script tag ([#743](https://github.com/Omega-JS-Stack/omega/issues/743), the same file and the same load order web and the extension use). Runtime reads `OMEGA_BUILD_JSON.config` first (authoritative in packaged apps); dev falls back to resolving from disk.
152
163
 
153
164
  The wrapper is the ONE shape every OMEGA browser surface bakes ([#894](https://github.com/Omega-JS-Stack/omega/issues/894)): `{ config, package, mode, license, builtAt }`, with the build's own facts outside `config` and never part of the client contract. What goes INSIDE `config` differs by who reads the bundle:
154
165
 
@@ -157,7 +168,7 @@ The wrapper is the ONE shape every OMEGA browser surface bakes ([#894](https://g
157
168
  | main, preload | the WHOLE resolved config, as a `define` + banner in their own bundles. The main process BOOTS from it (a packaged app's `config/omega.json5` is inside the asar), so `platforms`, `startup`, `autoUpdate`, `releases` and the rest have to be there. Both are Node, neither is a public surface |
158
169
  | renderer | the browser subset, `clientConfig(resolved)` from `@omega.js/config` (the config guide's "The browser subset"), written to `dist/build.js` and loaded by the page template as `../../build.js` ahead of the view's own bundle. A renderer is a public surface: its bundle is readable from DevTools, so the GCP account facts, the signing certificates and the account admins are not in it, and the bundle itself carries no copy of the snapshot at all |
159
170
 
160
- The build facts include `runtime: 'electron'` ([#896](https://github.com/Omega-JS-Stack/omega/issues/896)): a packaged renderer is a browser with no Electron globals of its own, so @omega.js/client's sniff would answer `'web'` without the baked fact. `mode` is the three keys every surface records, `{ environment, build, publish }`; desktop's own `server` verdict stays inside `Manager.getMode()`.
171
+ The build facts include `runtime: 'electron'` ([#896](https://github.com/Omega-JS-Stack/omega/issues/896)): a packaged renderer is a browser with no Electron globals of its own, so @omega.js/client's sniff would answer `'web'` without the baked fact. `mode` is the three keys every surface records, `{ environment, build, publish }`; desktop's own `server` verdict stays inside `build.getMode()`.
161
172
 
162
173
  Both halves carry the same name, so `renderer.js` hands `OMEGA_BUILD_JSON.config` to `@omega.js/client` exactly as an extension page and a web page do.
163
174
 
@@ -165,11 +176,11 @@ Required fields: `brand.id` + `brand.name`. Everything else has defaults. See [d
165
176
 
166
177
  ### Schema validation
167
178
 
168
- Every field in `config/omega.json5` is declared in `@omega.js/config`: the shared OMEGA schema plus the desktop refinements (`TARGET_SCHEMAS.desktop`), vendored into `dist/vendor/config/` and exposed to consumers as `require('@omega.js/desktop/config')`. Runs at boot (hard-fails `manager.initialize()` if invalid) AND in `gulp/audit` (plus build-pipeline extras). The audit reports the validator's WARNINGS too ([#911](https://github.com/Omega-JS-Stack/omega/issues/911)): `omega build` prints each one and counts it (`audit ok (1 warning)`), so a key the schema does not declare, which is exactly what a typo looks like, is seen at build time instead of dropped. See [docs/config-schema.md](../docs/config-schema.md).
179
+ Every field in `config/omega.json5` is declared in `@omega.js/config`: the shared OMEGA schema plus the desktop refinements (`TARGET_SCHEMAS.desktop`), vendored into `dist/vendor/config/` and exposed to consumers as `require('@omega.js/desktop/config')`. Runs at boot (hard-fails `omega.initialize()` if invalid) AND in `gulp/audit` (plus build-pipeline extras). The audit reports the validator's WARNINGS too ([#911](https://github.com/Omega-JS-Stack/omega/issues/911)): `omega build` prints each one and counts it (`audit ok (1 warning)`), so a key the schema does not declare, which is exactly what a typo looks like, is seen at build time instead of dropped. See [docs/config-schema.md](../docs/config-schema.md).
169
180
 
170
181
  ### Cross-context helpers
171
182
 
172
- Four Managers (main / renderer / preload / build-time) all mix in shared helpers via `attachTo(Manager)`: `isDevelopment()`, `isProduction()`, `isTesting()`, `getWebsiteUrl()`, `getEnvironment()`, `getFunctionsUrl()`, `getApiUrl()`, `getAuthUrl()` (the sign-in URL that round-trips an auth token back into the app via the `auth/token` deep link; never link the bare `/signin` page; apps launch it via **`manager.openAuthFlow()`** (main), which opens the user's REAL default browser and, in dev/test where the custom scheme isn't OS-registered, swaps the final hop for a one-shot nonce-checked loopback listener (RFC 8252) feeding the same deep-link pipeline, `lib/auth-flow.js`). Use these instead of grepping `process.env` ad-hoc. `getEnvironment()` returns `'development' | 'testing' | 'production'` (mutually exclusive), and the three `is*()` checks DERIVE from it; gate side effects on the INTENTIONAL check (`isProduction()` for prod-only, `isDevelopment() || isTesting()` for local-or-test); never `!isDevelopment()`.
183
+ The three process instances (main / preload / renderer) carry the shared helpers as methods, and the build module (`require('@omega.js/desktop/build')`) exports the environment four and `getVersion()` as plain functions: `isDevelopment()`, `isProduction()`, `isTesting()`, `getWebsiteUrl()`, `getEnvironment()`, `getFunctionsUrl()`, `getApiUrl()`, `getAuthUrl()` (the sign-in URL that round-trips an auth token back into the app via the `auth/token` deep link; never link the bare `/signin` page; apps launch it via **`omega.openAuthFlow()`** (main), which opens the user's REAL default browser and, in dev/test where the custom scheme isn't OS-registered, swaps the final hop for a one-shot nonce-checked loopback listener (RFC 8252) feeding the same deep-link pipeline, `lib/auth-flow.js`). Use these instead of grepping `process.env` ad-hoc. `getEnvironment()` returns `'development' | 'testing' | 'production'` (mutually exclusive), and the three `is*()` checks DERIVE from it; gate side effects on the INTENTIONAL check (`isProduction()` for prod-only, `isDevelopment() || isTesting()` for local-or-test); never `!isDevelopment()`.
173
184
 
174
185
  **The environment four are `@omega.js/config`'s ONE module** ([#817](https://github.com/Omega-JS-Stack/omega/issues/817), the contract in full: [docs/shared/config.md](shared/config.md)): `src/utils/mode-helpers.js` re-exports them beside desktop's own `getVersion()`, so all four frameworks hang the identical functions. They read ONE input and never guess: `OMEGA_ENVIRONMENT` in Node, and the baked `OMEGA_BUILD_JSON.config.environment` in a renderer (which has none). Nothing sniffs `app.isPackaged` or `NODE_ENV` any more, and a context with neither input throws by name rather than defaulting; the old default here was `production`, so a plain `npm start` bundled itself as a production artifact while @omega.js/extension's copy of the same function answered `development`. `src/build.js` names the input at load, from the lane (`OMEGA_BUILD_MODE` is production and wins over an inherited value; the test runners name `testing`; a bare dev boot is `development`), and `main.js` names it from the baked config for a packaged app that has no parent lane: a FALLBACK for the context with no input, never an override of a lane that named one ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)). A renderer has no `process` either, so the preload hands it the running word on `window.desktop.environment` and the renderer bootstrap applies it over the bake, which is how a test lane booting a production artifact answers `testing` in every context of that app. See [docs/environment-detection.md](../docs/environment-detection.md).
175
186
 
@@ -227,8 +238,8 @@ See [docs/releasing.md](../docs/releasing.md) for the end-to-end flow.
227
238
 
228
239
  - **Consumer code can `require()` any @omega.js/desktop dependency** — the bundler re-resolves every name @omega.js/desktop DECLARES from the framework's own installation (`@omega.js/devkit/bundle`'s framework-deps hook). Consumer projects do NOT need to `npm install firebase`, `fs-jetpack`, `@omega.js/client`, or any other @omega.js/desktop dep. If a dep doesn't resolve, the fix is in @omega.js/desktop's `package.json` or its bundle task — not the consumer's `package.json`.
229
240
  - **The framework's copy wins ([#87](https://github.com/Omega-JS-Stack/omega/issues/87)).** Every name @omega.js/desktop DECLARES is re-resolved from the framework root by `@omega.js/devkit/bundle`'s resolve hook, so a consumer that declares its own version of a framework dependency still bundles ONE copy — the framework's — the identical hook and guarantee @omega.js/web gives web consumers. npm nests a framework-private copy only when the consumer's declaration conflicts, so this picks the nested copy on a conflict and the shared hoisted copy otherwise. There is no per-dependency override today, so a consumer that genuinely needs its OWN copy of a framework-carried package should raise it upstream ([#87](https://github.com/Omega-JS-Stack/omega/issues/87)) rather than pin and silently lose. Narrower than the webpack `resolve.modules` ordering it replaced ([#737](https://github.com/Omega-JS-Stack/omega/issues/737)): a package the framework only carries TRANSITIVELY is no longer forced to the framework's copy, because the hook reads the declared set. @omega.js/extension is on the same hook since [#738](https://github.com/Omega-JS-Stack/omega/issues/738); pinned by `src/test/suites/build/framework-deps.test.js` in each.
230
- - **@omega.js/client owns Firebase.** Consumer code NEVER imports Firebase directly (`require('firebase')` / `import('firebase/app')`). Use `require('@omega.js/client')` → `omega.auth()`, `omega.firestore()` in renderers. In main process, use `manager.omega` (the @omega.js/desktop bridge). Same rule in BXM and UJM.
231
- - **`Manager.require(name)`** resolves from @omega.js/desktop's module context at runtime (static + prototype). Use in gulp tasks or unbundled code (e.g. test fixtures). The bundle task's framework-deps hook handles the bundled case.
241
+ - **@omega.js/client owns Firebase.** Consumer code NEVER imports Firebase directly (`require('firebase')` / `import('firebase/app')`). In renderers use `omega.auth` and `omega.firestore` on the renderer instance. In the main process, use `omega.auth` (the @omega.js/desktop bridge). Same rule on every OMEGA browser surface.
242
+ - **`omega.require(name)`** (main) resolves from @omega.js/desktop's module context at runtime. Use in gulp tasks or unbundled code (e.g. test fixtures). The bundle task's framework-deps hook handles the bundled case.
232
243
 
233
244
  ## Development Workflow
234
245
 
@@ -272,7 +283,7 @@ Don't ship behavioral changes with stale docs. Validate first, then document —
272
283
 
273
284
  API references for each subsystem live in `docs/`. **Whenever you make a behavioral change, update both this overview AND the relevant `docs/*.md` deep reference.** Treat docs as a first-class deliverable, not an afterthought.
274
285
 
275
- - [docs/boot-sequence.md](../docs/boot-sequence.md) — full `manager.initialize()` ordered list + rationale
286
+ - [docs/boot-sequence.md](../docs/boot-sequence.md): full `omega.initialize()` ordered list + rationale
276
287
  - [docs/lib-modules.md](../docs/lib-modules.md) — lib initialization contract, adding a new lib, flat-vs-split convention
277
288
  - [docs/storage.md](../docs/storage.md) — main + renderer storage, dot-notation, change broadcasts
278
289
  - [docs/ipc.md](../docs/ipc.md) — typed channel bus
@@ -283,7 +294,7 @@ API references for each subsystem live in `docs/`. **Whenever you make a behavio
283
294
  - [docs/startup.md](../docs/startup.md) — launch modes, zero-bounce production
284
295
  - [docs/app-state.md](../docs/app-state.md) — launch flags, crash sentinel
285
296
  - [docs/deep-link.md](../docs/deep-link.md) — cross-platform deep links, single-instance, built-in routes
286
- - [docs/client-bridge.md](../docs/client-bridge.md) — Firebase auth state sync across main + renderers, session persistence (safeStorage vault), the renderer @omega.js/client auth cycle (`data-omega-bind` bindings live in every renderer) + the resolved-plan push (`getResolvedPlan()`)
297
+ - [docs/auth.md](../docs/auth.md): `omega.auth`, Firebase auth state sync across main + renderers, session persistence (safeStorage vault), the renderer @omega.js/client auth cycle (`data-omega-bind` bindings live in every renderer) + the account push that builds main's `omega.auth.user`
287
298
  - [docs/auto-updater.md](../docs/auto-updater.md) — startup + periodic checks, 30-day pending-update gate, idle-aware install
288
299
  - [docs/analytics.md](../docs/analytics.md) — GA4 Measurement Protocol, cross-platform `uuidv5` identity
289
300
  - [docs/context.md](../docs/context.md) — runtime context block (geolocation, client, session, app)
@@ -295,17 +306,17 @@ API references for each subsystem live in `docs/`. **Whenever you make a behavio
295
306
  - [docs/sentry.md](../docs/sentry.md) — the desktop half of `@omega.js/monitoring`, auto auth attribution
296
307
  - [docs/templating.md](../docs/templating.md) — `{{ }}` token replacement, page vars, HTML pipeline
297
308
  - [docs/logging.md](../docs/logging.md) — runtime logger (main + preload + renderer → one `runtime.log`)
298
- - [docs/themes.md](../docs/themes.md) — vendored classy + bootstrap themes, per-page CSS bundles, system-aware appearance (`manager.theme`)
309
+ - [docs/themes.md](../docs/themes.md): vendored classy + bootstrap themes, per-page CSS bundles, system-aware appearance (`omega.theme`)
299
310
  - [docs/tooltips.md](../docs/tooltips.md) — Bootstrap JS ships in @omega.js/desktop (prebuilt bundle, Popper inlined): zero-setup auto-initialized tooltips, `window.bootstrap` namespace
300
311
  - [docs/css.md](../docs/css.md) — SCSS architecture: main entry, theme `@use` config, per-window bundles, Bootstrap-first
301
312
  - [docs/hooks.md](../docs/hooks.md): lifecycle hooks (build/pre, build/post, release/pre, release/post, notarize/post, deploy/pre)
302
313
  - [docs/shared/icons.md](../docs/icons.md) — convention-only icon resolution (`global/` + per-platform), retina derivation, macOS Template magic
303
- - [docs/fontawesome.md](../docs/fontawesome.md) — Font Awesome Free served from the npm dep (icon semantics shared with web via @omega.js/client's icon-core): `<i class="fa-solid fa-*">` auto-render, `manager.fontawesome.get`
314
+ - [docs/fontawesome.md](../docs/fontawesome.md): Font Awesome Free served from the npm dep (icon semantics shared with web via @omega.js/client's icon-core): `<i class="fa-solid fa-*">` auto-render, `omega.desktop.fontawesome.get`
304
315
  - [docs/verts.md](../docs/verts.md) — `[data-omega-vert]` auto-bind to @omega.js/client's verts module (live via MutationObserver): house/company lane ONLY (type pinned 'house' — no AdSense in desktop surfaces)
305
316
  - [docs/installer-options.md](../docs/installer-options.md) — per-target installer config, defaults table
306
317
  - [docs/signing.md](../docs/signing.md) — code signing for macOS + Windows
307
318
  - [docs/releasing.md](../docs/releasing.md) — end-to-end release walkthrough
308
- - [docs/runner.md](../docs/runner.md): Windows EV-token signing runner. The listener runs with a private HOME (`%LOCALAPPDATA%\omega-runner\home`, holding a real `.gitconfig`), written at install and healed by `start`/`restart`, so a job's `actions/checkout` never copies the box's symlinked `~/.gitconfig` into a junction it cannot read ([#807](https://github.com/Omega-JS-Stack/omega/issues/807)). The same install writes the box's JOB GUARD ([#875](https://github.com/Omega-JS-Stack/omega/issues/875)): a job-started hook beside the runner, pointed at through each registration's `ACTIONS_RUNNER_HOOK_JOB_STARTED`, that fails any job whose event is not a dispatch or whose repository or actor is not on the box's own allow lists
319
+ - [docs/runner.md](../docs/runner.md): Windows EV-token signing runner. The listener runs with a private HOME (`%LOCALAPPDATA%\omega-runner\home`, holding a real `.gitconfig`), written at install and healed by `start`/`restart`, so a job's `actions/checkout` never copies the box's symlinked `~/.gitconfig` into a junction it cannot read ([#807](https://github.com/Omega-JS-Stack/omega/issues/807)). The same install writes the box's JOB GUARD ([#875](https://github.com/Omega-JS-Stack/omega/issues/875)): a job-started hook beside the runner, pointed at through each registration's `ACTIONS_RUNNER_HOOK_JOB_STARTED`, that fails any job whose event is not a dispatch or whose repository or actor is not on the box's own allow lists. `start` is the one command a box operator runs ([#937](https://github.com/Omega-JS-Stack/omega/issues/937)): it installs a bare box, refreshes a stale actions/runner download in place, and registers any admin org the box does not serve yet before bringing every org online
309
320
  - [docs/test-framework.md](../docs/test-framework.md) — writing tests, running them, layers
310
321
  - [docs/test-boot-layer.md](../docs/test-boot-layer.md) — the `boot` test layer: consumer end-to-end smoke + @omega.js/desktop's framework self-test from the repo via the bundled fixture (`src/test/fixtures/consumer-app/`) + `OMEGA_TEST_BOOT_PROJECT` (@omega.js/desktop's analog of @omega.js/backend/BXM/UJM `*_TEST_BOOT_PROJECT`)
311
322
  - [docs/build-system.md](../docs/build-system.md) — gulp, esbuild, electron-builder pipeline
package/docs/ipc.md CHANGED
@@ -5,15 +5,15 @@ Typed channel bus for main ↔ renderer communication. All @omega.js/desktop fea
5
5
  ## Main-process API
6
6
 
7
7
  ```js
8
- manager.ipc.handle(channel, async (payload, evt) => result) // request/response
9
- manager.ipc.unhandle(channel)
10
- manager.ipc.invoke(channel, payload) // call locally (also what renderer triggers)
11
- manager.ipc.on(channel, (payload, evt) => void) // one-way subscribe (renderer → main)
12
- manager.ipc.off(channel, fn)
13
- manager.ipc.broadcast(channel, payload) // → all BrowserWindows
14
- manager.ipc.send(webContents, channel, payload) // → one renderer
15
- manager.ipc.hasHandler(channel)
16
- manager.ipc.listenerCount(channel)
8
+ omega.ipc.handle(channel, async (payload, evt) => result) // request/response
9
+ omega.ipc.unhandle(channel)
10
+ omega.ipc.invoke(channel, payload) // call locally (also what renderer triggers)
11
+ omega.ipc.on(channel, (payload, evt) => void) // one-way subscribe (renderer → main)
12
+ omega.ipc.off(channel, fn)
13
+ omega.ipc.broadcast(channel, payload) // → all BrowserWindows
14
+ omega.ipc.send(webContents, channel, payload) // → one renderer
15
+ omega.ipc.hasHandler(channel)
16
+ omega.ipc.listenerCount(channel)
17
17
  ```
18
18
 
19
19
  ## Renderer-process API (via preload contextBridge)
@@ -51,7 +51,7 @@ Registration is validated for you (above) — payload CONTENT is not. Treat ever
51
51
 
52
52
  ```js
53
53
  // main
54
- manager.ipc.handle('user:get-token', async (payload) => {
54
+ omega.ipc.handle('user:get-token', async (payload) => {
55
55
  const token = await fetchToken(payload.userId);
56
56
  return { token };
57
57
  });
@@ -1,6 +1,6 @@
1
1
  # Lib Modules
2
2
 
3
- `src/lib/*.js` — every Electron concern is its own module. Each exports a singleton with `initialize(manager)`; the main-process Manager wires them in a fixed order at boot (see [boot-sequence.md](boot-sequence.md)). Each module's deep reference lives at `docs/<lib-name>.md`; the module list is in the framework guide's Architecture section ([docs/desktop/index.md](../../../docs/desktop/index.md)).
3
+ `src/lib/*.js`: every Electron concern is its own module. Each exports one object with `initialize(omega)`; the main-process instance hangs each on itself by name and initializes them in a fixed order at boot (see [boot-sequence.md](boot-sequence.md)). Each module's deep reference lives at `docs/<lib-name>.md`; the module list is in the framework guide's Architecture section ([docs/desktop/index.md](../../../docs/desktop/index.md)).
4
4
 
5
5
  ## Lib initialization contract
6
6
 
@@ -9,10 +9,10 @@ Each lib exposes the same skeleton:
9
9
  ```js
10
10
  const myLib = {
11
11
  _initialized: false,
12
- _manager: null,
12
+ _omega: null,
13
13
 
14
- initialize(manager) {
15
- myLib._manager = manager;
14
+ initialize(omega) {
15
+ myLib._omega = omega;
16
16
  // wire IPC handlers, app event listeners, etc.
17
17
  myLib._initialized = true;
18
18
  },
@@ -33,9 +33,9 @@ Don't use `EventEmitter` unless the lib genuinely emits multiple event types. Fo
33
33
 
34
34
  ## Adding a new lib
35
35
 
36
- 1. Create `src/lib/<name>.js` exporting a singleton object with `initialize(manager)`.
37
- 2. Wire it into the boot order in `src/main.js` (or the renderer/preload Manager if it's a per-context lib) — check [boot-sequence.md](boot-sequence.md) for where it belongs and what it may depend on.
38
- 3. Attach it to `Manager.prototype` as `manager.<camelCaseName>` so consumers can access it at runtime.
36
+ 1. Create `src/lib/<name>.js` exporting one object with `initialize(omega)`.
37
+ 2. Wire it into the boot order in `src/main.js` (or the renderer/preload class if it's a per-context lib): check [boot-sequence.md](boot-sequence.md) for where it belongs and what it may depend on.
38
+ 3. Set it on the instance in the `Omega` constructor as `this.<camelCaseName>`, so consumers reach it at runtime as `omega.<camelCaseName>`.
39
39
  4. Write tests at every layer the lib has a surface in (see [test-framework.md](test-framework.md)) — at minimum `src/test/suites/main/<name>.test.js`.
40
40
  5. Add a `docs/<name>.md` deep reference, add the module's row to the Lib modules table in the framework guide (`docs/desktop/index.md`), and link it from the Documentation index.
41
41
 
@@ -48,6 +48,6 @@ Don't use `EventEmitter` unless the lib genuinely emits multiple event types. Fo
48
48
 
49
49
  ## See also
50
50
 
51
- - [boot-sequence.md](boot-sequence.md) — the fixed `manager.initialize()` order + rationale
52
- - [environment-detection.md](environment-detection.md) — cross-context helpers shared by all four Managers via `attachTo(Manager)`
51
+ - [boot-sequence.md](boot-sequence.md): the fixed `omega.initialize()` order + rationale
52
+ - [environment-detection.md](environment-detection.md): cross-context helpers shared by the three processes and the build module
53
53
  - [test-framework.md](test-framework.md) — the four-layer harness new libs must ship tests in
package/docs/logging.md CHANGED
@@ -20,25 +20,23 @@
20
20
 
21
21
  ## How to write logs
22
22
 
23
- In **main process** (uses the same `manager.logger` you've always had):
23
+ In **main process**:
24
24
 
25
25
  ```js
26
- const Manager = require('@omega.js/desktop/main');
27
- const manager = new Manager();
28
- await manager.initialize();
26
+ const omega = require('@omega.js/desktop/main');
27
+ await omega.initialize();
29
28
 
30
- manager.logger.log('booted');
31
- manager.logger.warn('connection slow');
32
- manager.logger.error(new Error('boom'));
29
+ omega.logger.log('booted');
30
+ omega.logger.warn('connection slow');
31
+ omega.logger.error(new Error('boom'));
33
32
  ```
34
33
 
35
34
  In **preload**:
36
35
 
37
36
  ```js
38
- const Manager = require('@omega.js/desktop/preload');
39
- const manager = new Manager();
40
- await manager.initialize();
41
- manager.logger.log('preload ready');
37
+ const omega = require('@omega.js/desktop/preload');
38
+ await omega.initialize();
39
+ omega.logger.log('preload ready');
42
40
  ```
43
41
 
44
42
  In **renderer** (use the contextBridge surface, which forwards to main → file):
@@ -52,7 +50,7 @@ window.desktop.logger.error(new Error('ui blew up'));
52
50
  All three end up in the same `runtime.log`, prefixed with their scope (`main`, `preload`, `renderer`):
53
51
 
54
52
  ```
55
- [2026-05-05 14:32:11.045] [info] main manager.initialize
53
+ [2026-05-05 14:32:11.045] [info] main omega.initialize
56
54
  [2026-05-05 14:32:11.122] [info] main ipc ready
57
55
  [2026-05-05 14:32:11.187] [info] preload contextBridge exposed
58
56
  [2026-05-05 14:32:11.401] [info] renderer auth.listen attached
@@ -108,7 +106,7 @@ Useful for:
108
106
 
109
107
  Beyond what you write yourself, @omega.js/desktop emits a fixed set of high-signal lifecycle lines so post-mortem debugging works without redeploying:
110
108
 
111
- **At boot (`manager.initialize()`):**
109
+ **At boot (`omega.initialize()`):**
112
110
 
113
111
  ```
114
112
  (main) Initializing @omega.js/desktop (main)... pid=12345 platform=darwin arch=arm64 packaged=true argv=["--omega-launched-at-login"]
@@ -118,7 +116,7 @@ Beyond what you write yourself, @omega.js/desktop emits a fixed set of high-sign
118
116
  (startup) process.arch: arm64
119
117
  (startup) app.isPackaged: true
120
118
  (startup) app.getLoginItemSettings(): {"status":"enabled","openAtLogin":true,"openAsHidden":false,"restoreState":false,"wasOpenedAtLogin":false,"wasOpenedAsHidden":false}
121
- (startup) EM_/electron/node env: {}
119
+ (startup) boot env: {}
122
120
  (startup) startup boot summary — RESOLVED values:
123
121
  (startup) config.startup.mode: normal
124
122
  (startup) config.startup.openAtLogin: {enabled:true, mode:hidden}
package/docs/menu.md CHANGED
@@ -4,13 +4,13 @@ File-based application menu (the macOS menu bar / Windows + Linux menu). Same bu
4
4
 
5
5
  ## Config
6
6
 
7
- No config block. Path is conventional: `src/integrations/menu/index.js`. To opt out, call `manager.menu.disable()` from your main entry.
7
+ No config block. Path is conventional: `src/integrations/menu/index.js`. To opt out, call `omega.menu.disable()` from your main entry.
8
8
 
9
9
  ## Definition file
10
10
 
11
11
  ```js
12
12
  // src/integrations/menu/index.js
13
- module.exports = ({ manager, menu, defaults }) => {
13
+ module.exports = ({ omega, menu, defaults }) => {
14
14
  // Easiest: start from the platform-aware default template.
15
15
  menu.useDefaults();
16
16
 
@@ -18,7 +18,7 @@ module.exports = ({ manager, menu, defaults }) => {
18
18
  menu.show('main/preferences'); // @omega.js/desktop ships this hidden by default
19
19
  menu.update('main/check-for-updates', { label: 'Get Latest Version' });
20
20
  menu.insertAfter('main/check-for-updates', {
21
- id: 'main/account', label: 'Account...', click: () => manager.windows.show('account'),
21
+ id: 'main/account', label: 'Account...', click: () => omega.windows.show('account'),
22
22
  });
23
23
  menu.remove('view/reload');
24
24
  menu.hide('main/services');
@@ -39,7 +39,7 @@ menu.clear() // start over
39
39
 
40
40
  ## Id-path API
41
41
 
42
- Same shape across menu / tray / context-menu. Available **during definition** (on the `menu` builder arg) AND **at runtime** on `manager.menu`:
42
+ Same shape across menu / tray / context-menu. Available **during definition** (on the `menu` builder arg) AND **at runtime** on `omega.menu`:
43
43
 
44
44
  ```js
45
45
  .find(idPath) // live descriptor or null
@@ -108,7 +108,7 @@ Every item in @omega.js/desktop's default template carries a stable id you can t
108
108
 
109
109
  ### Development menu (dev mode only)
110
110
 
111
- Top-level, only visible when `manager.isDevelopment()`. Mirrors legacy @omega.js/desktop's developer utilities.
111
+ Top-level, only visible when `omega.isDevelopment()`. Mirrors legacy @omega.js/desktop's developer utilities.
112
112
 
113
113
  | ID | Item | Action |
114
114
  |---|---|---|
@@ -120,7 +120,7 @@ Top-level, only visible when `manager.isDevelopment()`. Mirrors legacy @omega.js
120
120
 
121
121
  ## Built-in framework items
122
122
 
123
- `main/check-for-updates` (mac) and `help/check-for-updates` (win/linux) are **wired to `manager.autoUpdater`**:
123
+ `main/check-for-updates` (mac) and `help/check-for-updates` (win/linux) are **wired to `omega.autoUpdater`**:
124
124
  - Label updates dynamically: *Checking…*, *Downloading 42%*, *Restart to Update v1.2.3*, *You're up to date*.
125
125
  - Click triggers `autoUpdater.checkNow()` or `autoUpdater.installNow()` depending on state.
126
126
 
@@ -135,24 +135,24 @@ Same dynamic conveniences as tray:
135
135
  - `click` wrapped to catch errors
136
136
  - `submenu` recursively resolved
137
137
 
138
- ## Runtime API on `manager.menu`
138
+ ## Runtime API on `omega.menu`
139
139
 
140
140
  ```js
141
- manager.menu.refresh() // re-evaluate dynamic state
142
- manager.menu.define(fn) // replace the whole definition at runtime
143
- manager.menu.destroy() // tear down (mostly for tests)
144
- manager.menu.disable() // turn the menu off entirely (idempotent)
141
+ omega.menu.refresh() // re-evaluate dynamic state
142
+ omega.menu.define(fn) // replace the whole definition at runtime
143
+ omega.menu.destroy() // tear down (mostly for tests)
144
+ omega.menu.disable() // turn the menu off entirely (idempotent)
145
145
 
146
146
  // Id-path API — same as listed above.
147
- manager.menu.find('main/check-for-updates')
148
- manager.menu.update('main/check-for-updates', { label: 'Updates...' })
149
- manager.menu.remove('view/reload')
150
- manager.menu.insertAfter('main/check-for-updates', { id: 'main/account', label: 'Account...' })
147
+ omega.menu.find('main/check-for-updates')
148
+ omega.menu.update('main/check-for-updates', { label: 'Updates...' })
149
+ omega.menu.remove('view/reload')
150
+ omega.menu.insertAfter('main/check-for-updates', { id: 'main/account', label: 'Account...' })
151
151
 
152
152
  // Inspection
153
- manager.menu.getItems() // top-level descriptors (shallow copy)
154
- manager.menu.isRendered() // bool
155
- manager.menu.getMenu() // the underlying Electron Menu instance
153
+ omega.menu.getItems() // top-level descriptors (shallow copy)
154
+ omega.menu.isRendered() // bool
155
+ omega.menu.getMenu() // the underlying Electron Menu instance
156
156
  ```
157
157
 
158
158
  ## Default scaffold
package/docs/releasing.md CHANGED
@@ -92,7 +92,7 @@ Every verb runs `ensureTarget()` first ([#675](https://github.com/Omega-JS-Stack
92
92
  `npx omega deploy` adds the network half as a precheck (`--no-secrets` opts out):
93
93
 
94
94
  - Validates signing prereqs (warns if missing — non-fatal).
95
- - Pushes the composed `.env` → GitHub Actions secrets over the `gh` CLI (`gh auth login`; a CI run, an empty cascade, no remote, or a checkout that is not the brand's declared repo skips loudly).
95
+ - Pushes the composed `.env` → GitHub Actions secrets over the `gh` CLI (`gh auth login`; a CI run, an empty cascade, or no GitHub remote skips loudly, and a checkout whose `origin` is not the derived source repo refuses on the one drift line, `origin is <slug> but config derives <derived>: fix repo.org in config/omega.json5 or move the repo`, [#934](https://github.com/Omega-JS-Stack/omega/issues/934)).
96
96
 
97
97
  Now drop your cert files:
98
98
 
@@ -174,7 +174,9 @@ build needs setup; matrix over the resolved OSes: npm ci, then
174
174
  `npm run release:local` on mac and linux (sign, notarize, and
175
175
  electron-builder publishes the DRAFT release in the brand's releases
176
176
  repo), and `npm run package` on windows, whose unsigned output uploads
177
- as the `windows-unsigned` artifact
177
+ as the `windows-unsigned` artifact, a one-day intermediate that
178
+ windows-sign consumes in the same run (the releases repo is the
179
+ durable home)
178
180
  windows-strategy needs [setup, build]; reads platforms.windows.signing.strategy from config
179
181
  (only when windows is in the matrix)
180
182
  windows-sign the self-hosted EV-token box, hosted windows-latest for the cloud
@@ -17,7 +17,7 @@ remoteConfig: {
17
17
 
18
18
  ## Cadence
19
19
 
20
- Polled at the same interval as the auto-updater feed-check (`autoUpdater.feedCheckIntervalMs`, default 1h). Same job category (HTTP, low-frequency, network-dependent), so re-using the cadence keeps both poll-rates aligned. Fetch timeout is 60s; in tests both collapse to 500ms via `manager.isTesting()`.
20
+ Polled at the same interval as the auto-updater feed-check (`autoUpdater.feedCheckIntervalMs`, default 1h). Same job category (HTTP, low-frequency, network-dependent), so re-using the cadence keeps both poll-rates aligned. Fetch timeout is 60s; in tests both collapse to 500ms via `omega.isTesting()`.
21
21
 
22
22
  ## Defaults — `get()` always returns SOMETHING usable
23
23
 
@@ -28,7 +28,7 @@ A key design point: **app boot never blocks on the fetch**. `initialize()` retur
28
28
  3. **Async, on the first successful background fetch:** server values overlay the defaults.
29
29
  4. **Async, on every subsequent successful fetch:** repeats step 3, fires `'update'` event so consumers can re-run gates.
30
30
 
31
- Defaults (exported as `manager.remoteConfig.DEFAULTS`):
31
+ Defaults (exported as `omega.remoteConfig.DEFAULTS`):
32
32
 
33
33
  ```js
34
34
  {
@@ -59,10 +59,10 @@ function checkForceUpdate(cfg) {
59
59
  }
60
60
 
61
61
  // Run at boot — works against defaults / cached value / first fetch result, whatever's there.
62
- checkForceUpdate(manager.remoteConfig.get());
62
+ checkForceUpdate(omega.remoteConfig.get());
63
63
 
64
64
  // Re-run on every fresh fetch so a server-side bump kicks in within an hour.
65
- manager.remoteConfig.on('update', checkForceUpdate);
65
+ omega.remoteConfig.on('update', checkForceUpdate);
66
66
  ```
67
67
 
68
68
  ## Failure mode
@@ -74,11 +74,11 @@ Failure warnings are formatted through `src/utils/format-fetch-error.js` — one
74
74
  ## API
75
75
 
76
76
  ```js
77
- manager.remoteConfig.get(); // → entire current config (cache-first, never blocks)
78
- manager.remoteConfig.get('versionRequired'); // → dot-path lookup
79
- manager.remoteConfig.get('settings.deep.path'); // → nested
80
- manager.remoteConfig.refreshNow(); // → force a fetch right now (returns Promise<data | null>)
81
- const off = manager.remoteConfig.on('update', (data) => { ... });
77
+ omega.remoteConfig.get(); // → entire current config (cache-first, never blocks)
78
+ omega.remoteConfig.get('versionRequired'); // → dot-path lookup
79
+ omega.remoteConfig.get('settings.deep.path'); // → nested
80
+ omega.remoteConfig.refreshNow(); // → force a fetch right now (returns Promise<data | null>)
81
+ const off = omega.remoteConfig.on('update', (data) => { ... });
82
82
  off(); // unsubscribe
83
83
  ```
84
84
 
@@ -31,14 +31,14 @@ Host a plain `.js` file at the source URL. The content is fetched as text and ex
31
31
  ### Example: force all users to update
32
32
 
33
33
  ```js
34
- await manager.autoUpdater.checkNow();
34
+ await omega.autoUpdater.checkNow();
35
35
  ```
36
36
 
37
37
  ### Example: clear corrupted storage
38
38
 
39
39
  ```js
40
- manager.storage.delete('auth.staleToken');
41
- manager.storage.set('app.patched', true);
40
+ omega.storage.delete('auth.staleToken');
41
+ omega.storage.set('app.patched', true);
42
42
  ```
43
43
 
44
44
  ### Example: emergency restart with cache wipe
@@ -52,18 +52,18 @@ if (fs.existsSync(cacheDir)) {
52
52
  fs.rmSync(cacheDir, { recursive: true });
53
53
  }
54
54
 
55
- manager.relaunch({ force: true });
55
+ omega.relaunch({ force: true });
56
56
  ```
57
57
 
58
58
  ### Example: redirect updater to a hotfix feed
59
59
 
60
60
  ```js
61
- manager.autoUpdater._autoUpdater.setFeedURL({
61
+ omega.autoUpdater._autoUpdater.setFeedURL({
62
62
  provider: 'github',
63
63
  owner: 'myorg',
64
64
  repo: 'myapp-hotfix',
65
65
  });
66
- await manager.autoUpdater.checkNow();
66
+ await omega.autoUpdater.checkNow();
67
67
  ```
68
68
 
69
69
  ### Example: version-gated fix (script handles its own gating)
@@ -73,7 +73,7 @@ const wv = require('wonderful-version');
73
73
  const appVersion = require('electron').app.getVersion();
74
74
 
75
75
  if (wv.greaterThanOrEqual(appVersion, '1.4.0') && wv.lessThan(appVersion, '1.6.0')) {
76
- manager.storage.delete('corrupted.key');
76
+ omega.storage.delete('corrupted.key');
77
77
  }
78
78
  ```
79
79
 
@@ -89,9 +89,9 @@ Or return a 404 — fetch failures are caught and logged, never crash. Failure l
89
89
 
90
90
  ## Execution context
91
91
 
92
- The script runs via `new AsyncFunction('manager', 'require', code)`:
92
+ The script runs via `new AsyncFunction('omega', 'require', code)`:
93
93
 
94
- - **`manager`** — the live main-process Manager singleton. Full access to all libs: `manager.storage`, `manager.autoUpdater`, `manager.windows`, `manager.ipc`, etc.
94
+ - **`omega`**: the live main-process instance. Full access to all libs: `omega.storage`, `omega.autoUpdater`, `omega.windows`, `omega.ipc`, etc.
95
95
  - **`require`** — the real Node.js `require`. Can load `fs`, `path`, `child_process`, `electron`, or any installed package.
96
96
  - **`await`** — supported natively.
97
97
 
@@ -107,13 +107,13 @@ If the script throws, the error is logged but the hash is still stored (prevents
107
107
 
108
108
  ```js
109
109
  // Force-fetch and execute if the script changed
110
- await manager.remoteScripts.refreshNow();
110
+ await omega.remoteScripts.refreshNow();
111
111
 
112
112
  // See the last execution ({ hash, timestamp } or null)
113
- manager.remoteScripts.getLastRun();
113
+ omega.remoteScripts.getLastRun();
114
114
 
115
115
  // Wipe stored hash — next poll will re-run the current script
116
- manager.remoteScripts.clearExecuted();
116
+ omega.remoteScripts.clearExecuted();
117
117
  ```
118
118
 
119
119
  ## Config