@omega.js/desktop 0.52.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 (273) hide show
  1. package/README.md +17 -12
  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 +11 -11
  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/AGENTS.md +17 -8
  48. package/dist/defaults/config/omega.json5 +7 -7
  49. package/dist/defaults/hooks/build/post.js +1 -1
  50. package/dist/defaults/hooks/build/pre.js +1 -1
  51. package/dist/defaults/hooks/deploy/pre.js +1 -1
  52. package/dist/defaults/hooks/release/post.js +1 -1
  53. package/dist/defaults/hooks/release/pre.js +1 -1
  54. package/dist/defaults/src/assets/js/components/about/index.js +3 -5
  55. package/dist/defaults/src/assets/js/components/main/index.js +3 -5
  56. package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
  57. package/dist/defaults/src/integrations/context-menu/index.js +2 -2
  58. package/dist/defaults/src/integrations/menu/index.js +3 -3
  59. package/dist/defaults/src/integrations/tray/index.js +3 -3
  60. package/dist/defaults/src/main.js +3 -5
  61. package/dist/defaults/src/preload.js +3 -5
  62. package/dist/defaults/test/README.md +2 -2
  63. package/dist/gulp/main.js +9 -10
  64. package/dist/gulp/tasks/audit.js +7 -7
  65. package/dist/gulp/tasks/build-config.js +8 -8
  66. package/dist/gulp/tasks/bundle.js +16 -16
  67. package/dist/gulp/tasks/defaults.js +3 -3
  68. package/dist/gulp/tasks/distribute.js +2 -2
  69. package/dist/gulp/tasks/html.js +9 -9
  70. package/dist/gulp/tasks/package-quick.js +3 -3
  71. package/dist/gulp/tasks/package.js +3 -3
  72. package/dist/gulp/tasks/release.js +3 -3
  73. package/dist/gulp/tasks/sass.js +6 -6
  74. package/dist/gulp/tasks/serve.js +4 -4
  75. package/dist/hooks/notarize-artifacts.js +1 -1
  76. package/dist/hooks/notarize.js +1 -1
  77. package/dist/index.js +5 -8
  78. package/dist/lib/_environment-mixin.js +50 -0
  79. package/dist/lib/_lifecycle-mixin.js +45 -0
  80. package/dist/lib/analytics.js +33 -35
  81. package/dist/lib/app-state.js +14 -14
  82. package/dist/lib/auth-flow.js +18 -18
  83. package/dist/lib/auth-persistence.js +12 -12
  84. package/dist/lib/auth.js +421 -0
  85. package/dist/lib/auto-updater.js +49 -49
  86. package/dist/lib/context-menu.js +13 -13
  87. package/dist/lib/context.js +19 -19
  88. package/dist/lib/deep-link.js +34 -34
  89. package/dist/lib/fontawesome.js +5 -5
  90. package/dist/lib/ipc.js +4 -4
  91. package/dist/lib/menu.js +25 -25
  92. package/dist/lib/protocol.js +5 -5
  93. package/dist/lib/remote-config.js +22 -22
  94. package/dist/lib/remote-scripts.js +21 -21
  95. package/dist/lib/restart-manager/index.js +28 -28
  96. package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
  97. package/dist/lib/sign-helpers/sign-events.js +1 -1
  98. package/dist/lib/startup.js +18 -13
  99. package/dist/lib/storage.js +10 -10
  100. package/dist/lib/templating.js +16 -16
  101. package/dist/lib/theme.js +10 -10
  102. package/dist/lib/tray.js +27 -27
  103. package/dist/lib/usage.js +11 -11
  104. package/dist/lib/window-manager.js +26 -26
  105. package/dist/main.js +398 -483
  106. package/dist/preload.js +236 -176
  107. package/dist/renderer.js +417 -391
  108. package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
  109. package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
  110. package/dist/test/fixtures/consumer-app/src/main.js +5 -7
  111. package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
  112. package/dist/test/harness/boot-entry.js +22 -20
  113. package/dist/test/harness/main-entry.js +31 -30
  114. package/dist/test/harness/renderer-entry.js +5 -5
  115. package/dist/test/harness/renderer-preload.js +137 -141
  116. package/dist/test/index.js +10 -10
  117. package/dist/test/runner.js +2 -2
  118. package/dist/test/runners/boot.js +7 -6
  119. package/dist/test/runners/electron.js +3 -2
  120. package/dist/test/runners/render-event.js +2 -2
  121. package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
  122. package/dist/test/suites/boot/restart-manager.test.js +2 -2
  123. package/dist/test/suites/boot/storage-bundled.test.js +5 -5
  124. package/dist/test/suites/boot/theme.test.js +13 -13
  125. package/dist/test/suites/build/audit.test.js +1 -1
  126. package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
  127. package/dist/test/suites/build/boot-fixture.test.js +2 -2
  128. package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
  129. package/dist/test/suites/build/brand-scss.test.js +1 -1
  130. package/dist/test/suites/build/build-json-bake.test.js +1 -1
  131. package/dist/test/suites/build/cli.test.js +2 -2
  132. package/dist/test/suites/build/config-schema.test.js +5 -5
  133. package/dist/test/suites/build/defaults-scaffold.test.js +2 -2
  134. package/dist/test/suites/build/deploy-hook.test.js +3 -3
  135. package/dist/test/suites/build/ensure-target.test.js +2 -2
  136. package/dist/test/suites/build/env-delivery.test.js +2 -2
  137. package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
  138. package/dist/test/suites/build/exports.test.js +9 -8
  139. package/dist/test/suites/build/get-config.test.js +4 -4
  140. package/dist/test/suites/build/manifest-deps.test.js +1 -1
  141. package/dist/test/suites/build/merge-line-files.test.js +1 -1
  142. package/dist/test/suites/build/omega-shell.test.js +34 -2
  143. package/dist/test/suites/build/omega.test.js +350 -0
  144. package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
  145. package/dist/test/suites/build/runner.test.js +2 -2
  146. package/dist/test/suites/build/sentry.test.js +2 -2
  147. package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
  148. package/dist/test/suites/build/templating.test.js +3 -3
  149. package/dist/test/suites/build/test-stealth.test.js +7 -9
  150. package/dist/test/suites/build/url-helpers.test.js +55 -56
  151. package/dist/test/suites/build/validate-config.test.js +2 -2
  152. package/dist/test/suites/build/wave5-pins.test.js +2 -2
  153. package/dist/test/suites/main/analytics.test.js +59 -59
  154. package/dist/test/suites/main/app-state.test.js +66 -66
  155. package/dist/test/suites/main/auth-flow.test.js +41 -41
  156. package/dist/test/suites/main/auth-persistence.test.js +54 -43
  157. package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
  158. package/dist/test/suites/main/auth.test.js +336 -0
  159. package/dist/test/suites/main/auto-updater.test.js +134 -134
  160. package/dist/test/suites/main/boot-sequence.test.js +37 -49
  161. package/dist/test/suites/main/context-menu.test.js +51 -50
  162. package/dist/test/suites/main/context.test.js +25 -25
  163. package/dist/test/suites/main/deep-link.test.js +74 -74
  164. package/dist/test/suites/main/fontawesome.test.js +27 -27
  165. package/dist/test/suites/main/ipc.test.js +35 -35
  166. package/dist/test/suites/main/menu.test.js +101 -100
  167. package/dist/test/suites/main/protocol.test.js +19 -19
  168. package/dist/test/suites/main/remote-config.test.js +63 -63
  169. package/dist/test/suites/main/remote-scripts.test.js +103 -103
  170. package/dist/test/suites/main/request.test.js +71 -0
  171. package/dist/test/suites/main/restart-manager.test.js +33 -33
  172. package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
  173. package/dist/test/suites/main/startup.test.js +26 -26
  174. package/dist/test/suites/main/stealth-window.test.js +1 -1
  175. package/dist/test/suites/main/storage.test.js +25 -25
  176. package/dist/test/suites/main/theme.test.js +34 -34
  177. package/dist/test/suites/main/tray.test.js +79 -79
  178. package/dist/test/suites/main/url-helpers.test.js +133 -133
  179. package/dist/test/suites/main/usage.test.js +25 -25
  180. package/dist/test/suites/main/window-bounds.test.js +27 -27
  181. package/dist/test/suites/main/window-manager.test.js +44 -44
  182. package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
  183. package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
  184. package/dist/test/suites/renderer/round-trip.test.js +3 -3
  185. package/dist/test/suites/renderer/tooltips.test.js +15 -15
  186. package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +27 -7
  187. package/dist/test/utils/extended-mode-warning.js +1 -1
  188. package/dist/utils/boot-harness.js +56 -0
  189. package/dist/utils/mode-helpers.js +2 -15
  190. package/dist/utils/ship-keys.js +3 -3
  191. package/dist/utils/signing-status.js +51 -0
  192. package/dist/utils/test-events.js +7 -0
  193. package/dist/utils/test-stealth.js +6 -6
  194. package/dist/utils/url-helpers.js +52 -42
  195. package/dist/utils/user-agent.js +44 -0
  196. package/dist/vendor/account/engine.js +3 -3
  197. package/dist/vendor/account/index.js +14 -45
  198. package/dist/vendor/account/resolve-account.js +44 -0
  199. package/dist/vendor/account/schema.js +1 -1
  200. package/dist/vendor/account/user.js +99 -0
  201. package/dist/vendor/config/client-config.js +1 -1
  202. package/dist/vendor/config/environment.js +11 -30
  203. package/dist/vendor/config/index.js +8 -11
  204. package/dist/vendor/config/load.js +1 -2
  205. package/dist/vendor/config/platforms.js +1 -1
  206. package/dist/vendor/config/retired-keys.js +2 -2
  207. package/dist/vendor/config/schema.js +5 -8
  208. package/dist/vendor/config/site-global.js +2 -3
  209. package/dist/vendor/config/validate.js +1 -2
  210. package/dist/vendor/config/winback.js +1 -1
  211. package/dist/vendor/devkit/actions-secrets.js +1 -1
  212. package/dist/vendor/devkit/attach-log-file.js +1 -1
  213. package/dist/vendor/devkit/build-json.js +1 -1
  214. package/dist/vendor/devkit/cli-router.js +3 -4
  215. package/dist/vendor/devkit/defaults-engine.js +9 -11
  216. package/dist/vendor/devkit/local.js +2 -0
  217. package/dist/vendor/devkit/merge-line-files.js +2 -3
  218. package/dist/vendor/devkit/test/runner-core.js +6 -6
  219. package/dist/vendor/monitoring/env.js +2 -2
  220. package/dist/vendor/monitoring/index.js +1 -1
  221. package/dist/vendor/monitoring/main.js +1 -1
  222. package/dist/vendor/monitoring/preload.js +1 -1
  223. package/dist/vendor/monitoring/renderer.js +1 -1
  224. package/docs/analytics.md +8 -8
  225. package/docs/app-state.md +19 -19
  226. package/docs/audit.md +4 -4
  227. package/docs/{client-bridge.md → auth.md} +88 -73
  228. package/docs/auto-updater.md +8 -8
  229. package/docs/boot-sequence.md +11 -6
  230. package/docs/build-system.md +1 -1
  231. package/docs/cdp-debugging.md +1 -1
  232. package/docs/common-mistakes.md +7 -7
  233. package/docs/config-schema.md +1 -1
  234. package/docs/context-menu.md +13 -13
  235. package/docs/context.md +11 -11
  236. package/docs/css.md +3 -9
  237. package/docs/deep-link.md +25 -25
  238. package/docs/environment-detection.md +16 -16
  239. package/docs/fontawesome.md +7 -5
  240. package/docs/hooks.md +8 -8
  241. package/docs/index.md +38 -27
  242. package/docs/ipc.md +10 -10
  243. package/docs/lib-modules.md +9 -9
  244. package/docs/logging.md +12 -14
  245. package/docs/menu.md +18 -18
  246. package/docs/remote-config.md +9 -9
  247. package/docs/remote-scripts.md +12 -12
  248. package/docs/restart-manager.md +8 -8
  249. package/docs/sentry.md +4 -4
  250. package/docs/shared/analytics.md +1 -1
  251. package/docs/shared/breaking-changes.md +79 -13
  252. package/docs/shared/config.md +17 -21
  253. package/docs/shared/logging.md +1 -1
  254. package/docs/shared/monitoring.md +5 -5
  255. package/docs/shared/testing.md +2 -2
  256. package/docs/shared/theming.md +1 -1
  257. package/docs/shared/translation.md +19 -10
  258. package/docs/startup.md +16 -16
  259. package/docs/storage.md +11 -11
  260. package/docs/templating.md +3 -3
  261. package/docs/test-boot-layer.md +12 -12
  262. package/docs/test-framework.md +17 -17
  263. package/docs/themes.md +7 -7
  264. package/docs/tooltips.md +2 -2
  265. package/docs/tray.md +31 -31
  266. package/docs/usage.md +7 -7
  267. package/docs/verts.md +1 -1
  268. package/docs/windows.md +22 -22
  269. package/package.json +3 -4
  270. package/dist/lib/client-bridge.js +0 -374
  271. package/dist/lib/logger.js +0 -4
  272. package/dist/test/suites/build/manager.test.js +0 -213
  273. package/dist/test/suites/main/client-bridge.test.js +0 -262
@@ -1,6 +1,6 @@
1
1
  // Main-process tests for lib/app-state.js — storage-backed launch flags + crash sentinel.
2
2
  //
3
- // The harness already booted Manager once, which incremented launchCount and seeded
3
+ // The harness already booted omega once, which incremented launchCount and seeded
4
4
  // state. We test by calling appState.reset() then re-initializing with crafted
5
5
  // storage state to simulate first-launch / repeat-launch / crash-recovery / upgrade.
6
6
 
@@ -14,60 +14,60 @@ module.exports = defineCases({
14
14
  description: 'app-state (main)',
15
15
  cleanup: async (ctx) => {
16
16
  // Restore a sane state for any later suites that look at appState.
17
- ctx.manager.appState.reset();
17
+ ctx.omega.appState.reset();
18
18
  // Mark _initialized=false so we can re-init cleanly.
19
- ctx.manager.appState._initialized = false;
20
- await ctx.manager.appState.initialize(ctx.manager);
19
+ ctx.omega.appState._initialized = false;
20
+ await ctx.omega.appState.initialize(ctx.omega);
21
21
  },
22
22
  tests: [
23
23
  {
24
24
  name: 'initialize ran during boot',
25
25
  run: (ctx) => {
26
- ctx.expect(ctx.manager.appState._initialized).toBe(true);
26
+ ctx.expect(ctx.omega.appState._initialized).toBe(true);
27
27
  },
28
28
  },
29
29
  {
30
30
  name: 'first launch: flags + counters seeded correctly',
31
31
  run: async (ctx) => {
32
- ctx.manager.appState.reset();
33
- ctx.manager.appState._initialized = false;
34
- await ctx.manager.appState.initialize(ctx.manager);
35
-
36
- ctx.expect(ctx.manager.appState.isFirstLaunch()).toBe(true);
37
- ctx.expect(ctx.manager.appState.getLaunchCount()).toBe(1);
38
- ctx.expect(ctx.manager.appState.getInstalledAt()).toBeInstanceOf(Date);
39
- ctx.expect(ctx.manager.appState.getLastLaunchAt()).toBeNull();
40
- ctx.expect(ctx.manager.appState.recoveredFromCrash()).toBe(false);
32
+ ctx.omega.appState.reset();
33
+ ctx.omega.appState._initialized = false;
34
+ await ctx.omega.appState.initialize(ctx.omega);
35
+
36
+ ctx.expect(ctx.omega.appState.isFirstLaunch()).toBe(true);
37
+ ctx.expect(ctx.omega.appState.getLaunchCount()).toBe(1);
38
+ ctx.expect(ctx.omega.appState.getInstalledAt()).toBeInstanceOf(Date);
39
+ ctx.expect(ctx.omega.appState.getLastLaunchAt()).toBeNull();
40
+ ctx.expect(ctx.omega.appState.recoveredFromCrash()).toBe(false);
41
41
  },
42
42
  },
43
43
  {
44
44
  name: 'second launch: not first, count incremented, lastLaunchAt populated',
45
45
  run: async (ctx) => {
46
- ctx.manager.appState.reset();
47
- ctx.manager.appState._initialized = false;
48
- await ctx.manager.appState.initialize(ctx.manager);
46
+ ctx.omega.appState.reset();
47
+ ctx.omega.appState._initialized = false;
48
+ await ctx.omega.appState.initialize(ctx.omega);
49
49
 
50
50
  // Simulate a graceful quit from the first launch.
51
- const after1 = ctx.manager.storage.get(STORAGE_KEY);
51
+ const after1 = ctx.omega.storage.get(STORAGE_KEY);
52
52
  after1.sentinel = false;
53
53
  after1.lastQuitAt = Date.now();
54
- ctx.manager.storage.set(STORAGE_KEY, after1);
54
+ ctx.omega.storage.set(STORAGE_KEY, after1);
55
55
 
56
56
  // Boot again.
57
- ctx.manager.appState._initialized = false;
58
- await ctx.manager.appState.initialize(ctx.manager);
57
+ ctx.omega.appState._initialized = false;
58
+ await ctx.omega.appState.initialize(ctx.omega);
59
59
 
60
- ctx.expect(ctx.manager.appState.isFirstLaunch()).toBe(false);
61
- ctx.expect(ctx.manager.appState.getLaunchCount()).toBe(2);
62
- ctx.expect(ctx.manager.appState.getLastLaunchAt()).toBeInstanceOf(Date);
63
- ctx.expect(ctx.manager.appState.recoveredFromCrash()).toBe(false);
60
+ ctx.expect(ctx.omega.appState.isFirstLaunch()).toBe(false);
61
+ ctx.expect(ctx.omega.appState.getLaunchCount()).toBe(2);
62
+ ctx.expect(ctx.omega.appState.getLastLaunchAt()).toBeInstanceOf(Date);
63
+ ctx.expect(ctx.omega.appState.recoveredFromCrash()).toBe(false);
64
64
  },
65
65
  },
66
66
  {
67
67
  name: 'crash detection: previous launch left sentinel and no quit timestamp',
68
68
  run: async (ctx) => {
69
69
  // Seed storage with a "we were running and never gracefully quit" state.
70
- ctx.manager.storage.set(STORAGE_KEY, {
70
+ ctx.omega.storage.set(STORAGE_KEY, {
71
71
  installedAt: Date.now() - 10000,
72
72
  launchCount: 3,
73
73
  lastLaunchAt: Date.now() - 1000,
@@ -76,17 +76,17 @@ module.exports = defineCases({
76
76
  version: '1.0.0',
77
77
  });
78
78
 
79
- ctx.manager.appState._initialized = false;
80
- await ctx.manager.appState.initialize(ctx.manager);
79
+ ctx.omega.appState._initialized = false;
80
+ await ctx.omega.appState.initialize(ctx.omega);
81
81
 
82
- ctx.expect(ctx.manager.appState.recoveredFromCrash()).toBe(true);
83
- ctx.expect(ctx.manager.appState.getLaunchCount()).toBe(4);
82
+ ctx.expect(ctx.omega.appState.recoveredFromCrash()).toBe(true);
83
+ ctx.expect(ctx.omega.appState.getLaunchCount()).toBe(4);
84
84
  },
85
85
  },
86
86
  {
87
87
  name: 'graceful quit: sentinel cleared on next boot, no crash flag',
88
88
  run: async (ctx) => {
89
- ctx.manager.storage.set(STORAGE_KEY, {
89
+ ctx.omega.storage.set(STORAGE_KEY, {
90
90
  installedAt: Date.now() - 10000,
91
91
  launchCount: 5,
92
92
  lastLaunchAt: Date.now() - 1000,
@@ -95,17 +95,17 @@ module.exports = defineCases({
95
95
  version: '1.0.0',
96
96
  });
97
97
 
98
- ctx.manager.appState._initialized = false;
99
- await ctx.manager.appState.initialize(ctx.manager);
98
+ ctx.omega.appState._initialized = false;
99
+ await ctx.omega.appState.initialize(ctx.omega);
100
100
 
101
- ctx.expect(ctx.manager.appState.recoveredFromCrash()).toBe(false);
102
- ctx.expect(ctx.manager.appState.getLaunchCount()).toBe(6);
101
+ ctx.expect(ctx.omega.appState.recoveredFromCrash()).toBe(false);
102
+ ctx.expect(ctx.omega.appState.getLaunchCount()).toBe(6);
103
103
  },
104
104
  },
105
105
  {
106
106
  name: 'version upgrade: previousVersion populated when version changes',
107
107
  run: async (ctx) => {
108
- ctx.manager.storage.set(STORAGE_KEY, {
108
+ ctx.omega.storage.set(STORAGE_KEY, {
109
109
  installedAt: Date.now() - 10000,
110
110
  launchCount: 10,
111
111
  lastLaunchAt: Date.now() - 1000,
@@ -114,19 +114,19 @@ module.exports = defineCases({
114
114
  version: '0.9.0', // previous version
115
115
  });
116
116
 
117
- // Force the manager's reported version to differ.
118
- const origConfig = ctx.manager.config.app;
119
- ctx.manager.config.app = { ...origConfig, version: '1.0.0' };
117
+ // Force the omega instance's reported version to differ.
118
+ const origConfig = ctx.omega.config.app;
119
+ ctx.omega.config.app = { ...origConfig, version: '1.0.0' };
120
120
 
121
121
  try {
122
- ctx.manager.appState._initialized = false;
123
- await ctx.manager.appState.initialize(ctx.manager);
122
+ ctx.omega.appState._initialized = false;
123
+ await ctx.omega.appState.initialize(ctx.omega);
124
124
 
125
- ctx.expect(ctx.manager.appState.getVersion()).toBe('1.0.0');
126
- ctx.expect(ctx.manager.appState.getPreviousVersion()).toBe('0.9.0');
127
- ctx.expect(ctx.manager.appState.wasUpgraded()).toBe(true);
125
+ ctx.expect(ctx.omega.appState.getVersion()).toBe('1.0.0');
126
+ ctx.expect(ctx.omega.appState.getPreviousVersion()).toBe('0.9.0');
127
+ ctx.expect(ctx.omega.appState.wasUpgraded()).toBe(true);
128
128
  } finally {
129
- ctx.manager.config.app = origConfig;
129
+ ctx.omega.config.app = origConfig;
130
130
  }
131
131
  },
132
132
  },
@@ -134,7 +134,7 @@ module.exports = defineCases({
134
134
  name: 'no version change: wasUpgraded false, previousVersion preserved',
135
135
  run: async (ctx) => {
136
136
  // Seed with a previousVersion that should NOT be overwritten when version doesn't change.
137
- ctx.manager.storage.set(STORAGE_KEY, {
137
+ ctx.omega.storage.set(STORAGE_KEY, {
138
138
  installedAt: Date.now() - 10000,
139
139
  launchCount: 20,
140
140
  lastLaunchAt: Date.now() - 1000,
@@ -144,53 +144,53 @@ module.exports = defineCases({
144
144
  previousVersion: '0.9.0',
145
145
  });
146
146
 
147
- const origConfig = ctx.manager.config.app;
148
- ctx.manager.config.app = { ...origConfig, version: '1.0.0' };
147
+ const origConfig = ctx.omega.config.app;
148
+ ctx.omega.config.app = { ...origConfig, version: '1.0.0' };
149
149
 
150
150
  try {
151
- ctx.manager.appState._initialized = false;
152
- await ctx.manager.appState.initialize(ctx.manager);
151
+ ctx.omega.appState._initialized = false;
152
+ await ctx.omega.appState.initialize(ctx.omega);
153
153
 
154
- ctx.expect(ctx.manager.appState.wasUpgraded()).toBe(false);
154
+ ctx.expect(ctx.omega.appState.wasUpgraded()).toBe(false);
155
155
  // Should preserve the historical previousVersion rather than nuking it.
156
- ctx.expect(ctx.manager.appState.getPreviousVersion()).toBe('0.9.0');
156
+ ctx.expect(ctx.omega.appState.getPreviousVersion()).toBe('0.9.0');
157
157
  } finally {
158
- ctx.manager.config.app = origConfig;
158
+ ctx.omega.config.app = origConfig;
159
159
  }
160
160
  },
161
161
  },
162
162
  {
163
163
  name: 'launchedFromDeepLink: defaults false, set/cleared via setter',
164
164
  run: (ctx) => {
165
- ctx.expect(ctx.manager.appState.launchedFromDeepLink()).toBe(false);
166
- ctx.manager.appState.setLaunchedFromDeepLink(true);
167
- ctx.expect(ctx.manager.appState.launchedFromDeepLink()).toBe(true);
168
- ctx.manager.appState.setLaunchedFromDeepLink(false);
169
- ctx.expect(ctx.manager.appState.launchedFromDeepLink()).toBe(false);
165
+ ctx.expect(ctx.omega.appState.launchedFromDeepLink()).toBe(false);
166
+ ctx.omega.appState.setLaunchedFromDeepLink(true);
167
+ ctx.expect(ctx.omega.appState.launchedFromDeepLink()).toBe(true);
168
+ ctx.omega.appState.setLaunchedFromDeepLink(false);
169
+ ctx.expect(ctx.omega.appState.launchedFromDeepLink()).toBe(false);
170
170
  },
171
171
  },
172
172
  {
173
173
  name: 'launchedAtLogin returns a boolean',
174
174
  run: (ctx) => {
175
- ctx.expect(typeof ctx.manager.appState.launchedAtLogin()).toBe('boolean');
175
+ ctx.expect(typeof ctx.omega.appState.launchedAtLogin()).toBe('boolean');
176
176
  },
177
177
  },
178
178
  {
179
179
  name: 'getLastQuitAt reads live storage (returns null when sentinel is active)',
180
180
  run: async (ctx) => {
181
- ctx.manager.appState.reset();
182
- ctx.manager.appState._initialized = false;
183
- await ctx.manager.appState.initialize(ctx.manager);
181
+ ctx.omega.appState.reset();
182
+ ctx.omega.appState._initialized = false;
183
+ await ctx.omega.appState.initialize(ctx.omega);
184
184
  // After init, sentinel=true and lastQuitAt=null.
185
- ctx.expect(ctx.manager.appState.getLastQuitAt()).toBeNull();
185
+ ctx.expect(ctx.omega.appState.getLastQuitAt()).toBeNull();
186
186
  },
187
187
  },
188
188
  {
189
189
  name: 'reset() wipes persisted state',
190
190
  run: (ctx) => {
191
- ctx.expect(ctx.manager.storage.has(STORAGE_KEY)).toBe(true);
192
- ctx.manager.appState.reset();
193
- ctx.expect(ctx.manager.storage.has(STORAGE_KEY)).toBe(false);
191
+ ctx.expect(ctx.omega.storage.has(STORAGE_KEY)).toBe(true);
192
+ ctx.omega.appState.reset();
193
+ ctx.expect(ctx.omega.storage.has(STORAGE_KEY)).toBe(false);
194
194
  },
195
195
  },
196
196
  ],
@@ -1,7 +1,7 @@
1
1
  // Main-process tests for lib/auth-flow.js — the openAuthFlow() sign-in round trip.
2
2
  // The dev loopback listener is REAL (http server on 127.0.0.1, real GETs simulate the
3
3
  // browser's redirect back); only the pieces that would leave the machine are stubbed
4
- // (shell.openExternal, omega.handleAuthToken, windows.get's show/focus surface).
4
+ // (shell.openExternal, auth.handleToken, windows.get's show/focus surface).
5
5
 
6
6
  const http = require('http');
7
7
  const defineCases = require('../../../vendor/devkit/test/define-cases.js');
@@ -25,7 +25,7 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
25
25
  // getWebsiteUrl(), which since
26
26
  // [#834](https://github.com/Omega-JS-Stack/omega/issues/834) answers from the
27
27
  // resolved dev map the bundle task bakes (whose floor is @omega.js/config's
28
- // classic numbers) and throws when an artifact carries none. The harness manager
28
+ // classic numbers) and throws when an artifact carries none. The harness instance
29
29
  // loads src/defaults' config, which has no build behind it, so a real dev
30
30
  // artifact's block is stated here.
31
31
  function stubExternals(ctx) {
@@ -35,23 +35,23 @@ function stubExternals(ctx) {
35
35
  const tokens = [];
36
36
  const shown = [];
37
37
  const origOpen = electron.shell.openExternal;
38
- const origHandle = ctx.manager.omega.handleAuthToken;
39
- const origShow = ctx.manager.windows.show;
40
- const origDev = ctx.manager.config.dev;
38
+ const origHandle = ctx.omega.auth.handleToken;
39
+ const origShow = ctx.omega.windows.show;
40
+ const origDev = ctx.omega.config.dev;
41
41
  electron.shell.openExternal = async (url) => { opened.push(url); };
42
- ctx.manager.omega.handleAuthToken = (t) => { tokens.push(t); };
43
- ctx.manager.windows.show = (name) => { shown.push(name); };
44
- ctx.manager.config.dev = { ports: { ...CLASSIC_PORTS } };
42
+ ctx.omega.auth.handleToken = (t) => { tokens.push(t); };
43
+ ctx.omega.windows.show = (name) => { shown.push(name); };
44
+ ctx.omega.config.dev = { ports: { ...CLASSIC_PORTS } };
45
45
  return {
46
46
  opened,
47
47
  tokens,
48
48
  shown,
49
49
  restore() {
50
50
  electron.shell.openExternal = origOpen;
51
- ctx.manager.omega.handleAuthToken = origHandle;
52
- ctx.manager.windows.show = origShow;
53
- if (origDev !== undefined) ctx.manager.config.dev = origDev; else delete ctx.manager.config.dev;
54
- ctx.manager.authFlow.cancel();
51
+ ctx.omega.auth.handleToken = origHandle;
52
+ ctx.omega.windows.show = origShow;
53
+ if (origDev !== undefined) ctx.omega.config.dev = origDev; else delete ctx.omega.config.dev;
54
+ ctx.omega.authFlow.cancel();
55
55
  },
56
56
  };
57
57
  }
@@ -64,7 +64,7 @@ module.exports = defineCases({
64
64
  {
65
65
  name: 'initialize ran during boot',
66
66
  run: (ctx) => {
67
- ctx.expect(ctx.manager.authFlow._initialized).toBe(true);
67
+ ctx.expect(ctx.omega.authFlow._initialized).toBe(true);
68
68
  },
69
69
  },
70
70
  {
@@ -72,7 +72,7 @@ module.exports = defineCases({
72
72
  run: async (ctx) => {
73
73
  const stubs = stubExternals(ctx);
74
74
  try {
75
- const { url, port } = await ctx.manager.openAuthFlow();
75
+ const { url, port } = await ctx.omega.openAuthFlow();
76
76
  ctx.expect(typeof port).toBe('number');
77
77
  ctx.expect(stubs.opened[0]).toBe(url);
78
78
 
@@ -85,19 +85,19 @@ module.exports = defineCases({
85
85
  ctx.expect(returnUrl.hostname).toBe('127.0.0.1');
86
86
  ctx.expect(Number(returnUrl.port)).toBe(port);
87
87
  ctx.expect(returnUrl.pathname).toBe('/auth/token');
88
- ctx.expect(returnUrl.searchParams.get('state')).toBe(ctx.manager.authFlow._pending.nonce);
88
+ ctx.expect(returnUrl.searchParams.get('state')).toBe(ctx.omega.authFlow._pending.nonce);
89
89
  } finally {
90
90
  stubs.restore();
91
91
  }
92
92
  },
93
93
  },
94
94
  {
95
- name: 'valid browser return: 200 page, token → handleAuthToken, listener torn down, app surfaced',
95
+ name: 'valid browser return: 200 page, token → handleToken, listener torn down, app surfaced',
96
96
  run: async (ctx) => {
97
97
  const stubs = stubExternals(ctx);
98
98
  try {
99
- const { port } = await ctx.manager.openAuthFlow();
100
- const nonce = ctx.manager.authFlow._pending.nonce;
99
+ const { port } = await ctx.omega.openAuthFlow();
100
+ const nonce = ctx.omega.authFlow._pending.nonce;
101
101
 
102
102
  const res = await get(`http://127.0.0.1:${port}/auth/token?authToken=TOK-1&state=${nonce}`);
103
103
  ctx.expect(res.status).toBe(200);
@@ -106,7 +106,7 @@ module.exports = defineCases({
106
106
  ctx.expect(stubs.shown).toEqual(['main']);
107
107
 
108
108
  // One-shot: the listener is gone.
109
- ctx.expect(ctx.manager.authFlow._pending).toBeNull();
109
+ ctx.expect(ctx.omega.authFlow._pending).toBeNull();
110
110
  let refused = false;
111
111
  await get(`http://127.0.0.1:${port}/auth/token?authToken=x&state=${nonce}`).catch(() => { refused = true; });
112
112
  ctx.expect(refused).toBe(true);
@@ -116,12 +116,12 @@ module.exports = defineCases({
116
116
  },
117
117
  },
118
118
  {
119
- name: 'bad state or missing token: 400, no handleAuthToken, listener SURVIVES for the real return',
119
+ name: 'bad state or missing token: 400, no handleToken, listener SURVIVES for the real return',
120
120
  run: async (ctx) => {
121
121
  const stubs = stubExternals(ctx);
122
122
  try {
123
- const { port } = await ctx.manager.openAuthFlow();
124
- const nonce = ctx.manager.authFlow._pending.nonce;
123
+ const { port } = await ctx.omega.openAuthFlow();
124
+ const nonce = ctx.omega.authFlow._pending.nonce;
125
125
 
126
126
  const bad1 = await get(`http://127.0.0.1:${port}/auth/token?authToken=EVIL&state=wrong`);
127
127
  ctx.expect(bad1.status).toBe(400);
@@ -145,8 +145,8 @@ module.exports = defineCases({
145
145
  run: async (ctx) => {
146
146
  const stubs = stubExternals(ctx);
147
147
  try {
148
- const first = await ctx.manager.openAuthFlow();
149
- const second = await ctx.manager.openAuthFlow();
148
+ const first = await ctx.omega.openAuthFlow();
149
+ const second = await ctx.omega.openAuthFlow();
150
150
 
151
151
  // The first port no longer answers (unless the OS re-issued the same port to the
152
152
  // second listener, in which case the nonce changed anyway).
@@ -155,7 +155,7 @@ module.exports = defineCases({
155
155
  await get(`http://127.0.0.1:${first.port}/auth/token`).catch(() => { refused = true; });
156
156
  ctx.expect(refused).toBe(true);
157
157
  }
158
- ctx.expect(ctx.manager.authFlow._pending.port).toBe(second.port);
158
+ ctx.expect(ctx.omega.authFlow._pending.port).toBe(second.port);
159
159
  } finally {
160
160
  stubs.restore();
161
161
  }
@@ -166,12 +166,12 @@ module.exports = defineCases({
166
166
  run: async (ctx) => {
167
167
  const stubs = stubExternals(ctx);
168
168
  try {
169
- const { port } = await ctx.manager.openAuthFlow({ timeoutMs: 50 });
170
- ctx.expect(ctx.manager.authFlow._pending.port).toBe(port);
169
+ const { port } = await ctx.omega.openAuthFlow({ timeoutMs: 50 });
170
+ ctx.expect(ctx.omega.authFlow._pending.port).toBe(port);
171
171
  await sleep(150);
172
- ctx.expect(ctx.manager.authFlow._pending).toBeNull();
173
- ctx.manager.authFlow.cancel();
174
- ctx.manager.authFlow.cancel();
172
+ ctx.expect(ctx.omega.authFlow._pending).toBeNull();
173
+ ctx.omega.authFlow.cancel();
174
+ ctx.omega.authFlow.cancel();
175
175
  } finally {
176
176
  stubs.restore();
177
177
  }
@@ -181,25 +181,25 @@ module.exports = defineCases({
181
181
  name: 'production open(): plain external open of getAuthUrl(), no listener',
182
182
  run: async (ctx) => {
183
183
  const stubs = stubExternals(ctx);
184
- const m = ctx.manager;
185
- const origIsProd = m.isProduction;
186
- m.config.brand = m.config.brand || {};
187
- const origUrl = m.config.brand.url;
188
- m.isProduction = () => true;
189
- m.config.brand.url = 'https://example.com';
184
+ const omega = ctx.omega;
185
+ const origIsProd = omega.isProduction;
186
+ omega.config.brand = omega.config.brand || {};
187
+ const origUrl = omega.config.brand.url;
188
+ omega.isProduction = () => true;
189
+ omega.config.brand.url = 'https://example.com';
190
190
  try {
191
- const { url, port } = await m.openAuthFlow();
191
+ const { url, port } = await omega.openAuthFlow();
192
192
  ctx.expect(port).toBeUndefined();
193
- ctx.expect(ctx.manager.authFlow._pending).toBeNull();
193
+ ctx.expect(ctx.omega.authFlow._pending).toBeNull();
194
194
  ctx.expect(stubs.opened[0]).toBe(url);
195
195
  // Prod URL must ride the custom scheme, not a loopback return.
196
196
  const signin = new URL(url);
197
197
  const tokenUrl = new URL(signin.searchParams.get('authReturnUrl'));
198
198
  const finalHop = tokenUrl.searchParams.get('authReturnUrl');
199
- ctx.expect(finalHop).toBe(`${m.config.brand.id}://auth/token`);
199
+ ctx.expect(finalHop).toBe(`${omega.config.brand.id}://auth/token`);
200
200
  } finally {
201
- m.isProduction = origIsProd;
202
- if (origUrl !== undefined) m.config.brand.url = origUrl; else delete m.config.brand.url;
201
+ omega.isProduction = origIsProd;
202
+ if (origUrl !== undefined) omega.config.brand.url = origUrl; else delete omega.config.brand.url;
203
203
  stubs.restore();
204
204
  }
205
205
  },
@@ -1,5 +1,5 @@
1
- // Main-process tests for lib/auth-persistence.js (pluggable session vault) and the
2
- // bridge's desktop:auth:account-resolved intake (renderer → main plan resolution cache).
1
+ // Main-process tests for lib/auth-persistence.js (pluggable session vault) and
2
+ // lib/auth.js's desktop:auth:account-resolved intake (renderer → main account).
3
3
  // The safeStorage strategy runs REAL (OS keychain + real file under userData) when
4
4
  // encryption is available in the test environment; adapter logic is covered against
5
5
  // a real in-memory strategy either way.
@@ -27,27 +27,27 @@ module.exports = defineCases({
27
27
  {
28
28
  name: 'resolve(): a test run is none, whatever the config says',
29
29
  run: async (ctx) => {
30
- const m = ctx.manager;
31
- ctx.expect(m.isTesting()).toBe(true);
32
- m.config.omega = m.config.omega || {};
33
- const orig = m.config.omega.authPersistence;
30
+ const omega = ctx.omega;
31
+ ctx.expect(omega.isTesting()).toBe(true);
32
+ omega.config.omega = omega.config.omega || {};
33
+ const orig = omega.config.omega.authPersistence;
34
34
  try {
35
35
  // Unset, and explicitly asking for the vault, both land on none: the harness
36
36
  // never signs a real user in, so it never asks the OS keychain
37
37
  // ([#907](https://github.com/Omega-JS-Stack/omega/issues/907)).
38
- delete m.config.omega.authPersistence;
39
- ctx.expect(await authPersistence.resolve(m)).toBeNull();
38
+ delete omega.config.omega.authPersistence;
39
+ ctx.expect(await authPersistence.resolve(omega)).toBeNull();
40
40
  ctx.expect(authPersistence.getActive()).toBeNull();
41
41
 
42
- m.config.omega.authPersistence = 'safeStorage';
43
- ctx.expect(await authPersistence.resolve(m)).toBeNull();
42
+ omega.config.omega.authPersistence = 'safeStorage';
43
+ ctx.expect(await authPersistence.resolve(omega)).toBeNull();
44
44
 
45
- m.config.omega.authPersistence = 'none';
46
- ctx.expect(await authPersistence.resolve(m)).toBeNull();
45
+ omega.config.omega.authPersistence = 'none';
46
+ ctx.expect(await authPersistence.resolve(omega)).toBeNull();
47
47
  } finally {
48
- if (orig !== undefined) m.config.omega.authPersistence = orig;
49
- else delete m.config.omega.authPersistence;
50
- await authPersistence.resolve(m); // restore the active strategy for later suites
48
+ if (orig !== undefined) omega.config.omega.authPersistence = orig;
49
+ else delete omega.config.omega.authPersistence;
50
+ await authPersistence.resolve(omega); // restore the active strategy for later suites
51
51
  }
52
52
  },
53
53
  },
@@ -58,7 +58,7 @@ module.exports = defineCases({
58
58
 
59
59
  authPersistence.register('desktop-test-custom', fakeStrategy());
60
60
  try {
61
- // Selection by config is proven at the build layer, on a production manager:
61
+ // Selection by config is proven at the build layer, on a production omega instance:
62
62
  // under test mode resolve() answers none before it reads a thing.
63
63
  ctx.expect(authPersistence._strategies['desktop-test-custom'].name).toBe('desktop-test-custom');
64
64
  ctx.expect(await authPersistence._strategies['desktop-test-custom'].available()).toBe(true);
@@ -116,47 +116,58 @@ module.exports = defineCases({
116
116
  },
117
117
  },
118
118
  {
119
- name: 'bridge account-resolved intake: uid-guarded, cached, broadcast once per change, cleared on sign-out',
119
+ name: 'auth account-resolved intake: uid-guarded, lands a User, broadcasts { document } once per change, dropped on sign-out',
120
120
  run: async (ctx) => {
121
- const m = ctx.manager;
122
- const bridge = m.omega;
123
- const origAuth = bridge._firebaseAuth;
124
- const origBroadcast = m.ipc.broadcast;
121
+ const omega = ctx.omega;
122
+ const auth = omega.auth;
123
+ const origAuth = auth._firebaseAuth;
124
+ const origBroadcast = omega.ipc.broadcast;
125
125
  const broadcasts = [];
126
- m.ipc.broadcast = (ch, payload) => { if (ch === 'desktop:auth:plan-changed') broadcasts.push(payload); };
126
+ omega.ipc.broadcast = (ch, payload) => { if (ch === 'desktop:auth:plan-changed') broadcasts.push(payload); };
127
+
128
+ // What a signed-in renderer pushes: its User's stored document (resolved,
129
+ // metadata stamped) and its identity
130
+ const { User } = require('../../../vendor/account/index.js');
131
+ const IDENTITY = { uid: 'u1', email: 'x@y.z', displayName: 'X', photoURL: null, emailVerified: true };
132
+ const DOCUMENT = new User({ subscription: { product: { id: 'premium' }, status: 'active' }, roles: { betaTester: true } }, IDENTITY).toJSON();
133
+
127
134
  try {
128
- // Main signed out → any push is rejected.
129
- bridge._firebaseAuth = { currentUser: null };
130
- let res = await m.ipc.invoke('desktop:auth:account-resolved', { uid: 'u1', resolved: { plan: 'pro', active: true } });
135
+ // Main signed out → any push is rejected, `user` stays signed out.
136
+ auth._firebaseAuth = { currentUser: null };
137
+ let res = await omega.ipc.invoke('desktop:auth:account-resolved', { uid: 'u1', document: DOCUMENT, identity: IDENTITY });
131
138
  ctx.expect(res.accepted).toBe(false);
132
- ctx.expect(bridge.getResolvedPlan()).toBeNull();
139
+ ctx.expect(auth.user.authenticated).toBe(false);
140
+ ctx.expect(auth.user.plan).toBe('basic');
133
141
 
134
- // Matching uid → cached + broadcast.
135
- bridge._firebaseAuth = { currentUser: { uid: 'u1', email: 'x@y.z' } };
136
- res = await m.ipc.invoke('desktop:auth:account-resolved', { uid: 'u1', resolved: { plan: 'pro', active: true }, roles: { betaTester: true } });
142
+ // Matching uid → main builds its User from the WHOLE document + broadcasts it.
143
+ auth._firebaseAuth = { currentUser: { uid: 'u1', email: 'x@y.z' } };
144
+ res = await omega.ipc.invoke('desktop:auth:account-resolved', { uid: 'u1', document: DOCUMENT, identity: IDENTITY });
137
145
  ctx.expect(res.accepted).toBe(true);
138
- ctx.expect(bridge.getResolvedPlan()).toEqual({ plan: 'pro', active: true });
139
- ctx.expect(bridge.getResolvedRoles()).toEqual({ betaTester: true });
146
+ ctx.expect(auth.user.uid).toBe('u1');
147
+ ctx.expect(auth.user.plan).toBe('premium');
148
+ ctx.expect(auth.user.roles.betaTester).toBe(true);
149
+ ctx.expect(auth.user.profile.displayName).toBe('X');
140
150
  ctx.expect(broadcasts.length).toBe(1);
151
+ ctx.expect(broadcasts[0]).toEqual({ document: auth.user.toJSON() });
141
152
 
142
153
  // Identical push → accepted but NO second broadcast.
143
- await m.ipc.invoke('desktop:auth:account-resolved', { uid: 'u1', resolved: { plan: 'pro', active: true }, roles: { betaTester: true } });
154
+ await omega.ipc.invoke('desktop:auth:account-resolved', { uid: 'u1', document: DOCUMENT, identity: IDENTITY });
144
155
  ctx.expect(broadcasts.length).toBe(1);
145
156
 
146
- // Mismatched uid (stale renderer) → dropped, cache intact.
147
- res = await m.ipc.invoke('desktop:auth:account-resolved', { uid: 'other', resolved: { plan: 'max', active: true } });
157
+ // Mismatched uid (stale renderer) → dropped, account intact.
158
+ res = await omega.ipc.invoke('desktop:auth:account-resolved', { uid: 'other', document: { subscription: { product: { id: 'max' }, status: 'active' } } });
148
159
  ctx.expect(res.accepted).toBe(false);
149
- ctx.expect(bridge.getResolvedPlan()).toEqual({ plan: 'pro', active: true });
160
+ ctx.expect(auth.user.plan).toBe('premium');
150
161
 
151
- // Sign-out clears the cache.
152
- bridge._handleAuthStateChange(null);
153
- ctx.expect(bridge.getResolvedPlan()).toBeNull();
154
- ctx.expect(bridge.getResolvedRoles()).toBeNull();
162
+ // Sign-out drops the account.
163
+ auth._handleAuthStateChange(null);
164
+ ctx.expect(auth.user.authenticated).toBe(false);
165
+ ctx.expect(auth.user.plan).toBe('basic');
155
166
  } finally {
156
- bridge._firebaseAuth = origAuth;
157
- m.ipc.broadcast = origBroadcast;
158
- bridge._resolvedPlan = null;
159
- bridge._resolvedRoles = null;
167
+ // A case that failed midway still leaves main signed out for the suites after it
168
+ if (auth.user.authenticated) auth._handleAuthStateChange(null);
169
+ auth._firebaseAuth = origAuth;
170
+ omega.ipc.broadcast = origBroadcast;
160
171
  }
161
172
  },
162
173
  },
@@ -1,4 +1,4 @@
1
- // Integration tests for client-bridge — actually hits Firebase.
1
+ // Integration tests for lib/auth.js (`omega.auth`): actually hits Firebase.
2
2
  //
3
3
  // The SIGN-IN proof lives in #904: web, desktop and extension each sign in as a
4
4
  // persona the backend emulator seeds, so this suite no longer mints a custom
@@ -25,32 +25,33 @@ const skipReason = checkSkipReason();
25
25
  module.exports = defineCases({
26
26
  type: 'suite',
27
27
  layer: 'main',
28
- description: 'client-bridge (main, integration)',
28
+ description: 'auth (main, integration)',
29
29
  skip: skipReason || false,
30
30
  cleanup: async (ctx) => {
31
31
  try {
32
- await ctx.manager.omega.signOut();
32
+ await ctx.omega.auth.signOut();
33
33
  } catch (e) { /* ignore */ }
34
34
  },
35
35
  tests: [
36
36
  {
37
37
  name: 'firebase loaded (cloud.config present in test config)',
38
38
  run: (ctx) => {
39
- if (!ctx.manager.omega._firebaseAuth) {
39
+ if (!ctx.omega.auth._firebaseAuth) {
40
40
  ctx.skip('cloud.config not set in default config — set one in src/defaults/config/omega.json5 to run');
41
41
  }
42
- ctx.expect(ctx.manager.omega._firebaseAuth).toBeTruthy();
42
+ ctx.expect(ctx.omega.auth._firebaseAuth).toBeTruthy();
43
43
  },
44
44
  },
45
45
  {
46
- name: 'sign-out clears the current user and broadcasts',
46
+ name: 'sign-out ends the session, drops the account, and broadcasts',
47
47
  run: async (ctx) => {
48
- if (!ctx.manager.omega.getCurrentUser()) {
48
+ if (!ctx.omega.auth._firebaseAuth?.currentUser) {
49
49
  ctx.skip('not signed in (previous test may have skipped)');
50
50
  }
51
- const r = await ctx.manager.omega.signOut();
51
+ const r = await ctx.omega.auth.signOut();
52
52
  ctx.expect(r.success).toBe(true);
53
- ctx.expect(ctx.manager.omega.getCurrentUser()).toBeNull();
53
+ ctx.expect(ctx.omega.auth._firebaseAuth.currentUser).toBeNull();
54
+ ctx.expect(ctx.omega.auth.user.authenticated).toBe(false);
54
55
  },
55
56
  },
56
57
  ],