@omega.js/desktop 0.50.0 → 0.51.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.
- package/README.md +1 -1
- package/dist/assets/css/tokens/_index.scss +1 -1
- package/dist/assets/themes/base/_includes/frontend/sections/account-section-header.html +4 -1
- package/dist/assets/themes/base/_includes/frontend/sections/footer.html +13 -6
- package/dist/assets/themes/base/_includes/frontend/sections/nav.html +10 -8
- package/dist/assets/themes/base/_includes/global/sections/account.html +3 -1
- package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +12 -8
- package/dist/assets/themes/base/_includes/global/sections/app-topbar.html +10 -6
- package/dist/assets/themes/base/_includes/global/sections/page-header.html +8 -4
- package/dist/assets/themes/base/_layouts/backend/pages/dashboard/index.html +24 -24
- package/dist/assets/themes/base/_layouts/frontend/pages/about.html +10 -10
- package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +35 -35
- package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +4 -4
- package/dist/assets/themes/base/_layouts/frontend/pages/auth/signin.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/auth/signup.html +4 -4
- package/dist/assets/themes/base/_layouts/frontend/pages/contact.html +3 -3
- package/dist/assets/themes/base/_layouts/frontend/pages/download.html +34 -33
- package/dist/assets/themes/base/_layouts/frontend/pages/extension/index.html +11 -11
- package/dist/assets/themes/base/_layouts/frontend/pages/legal/document.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/status.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/team/index.html +9 -7
- package/dist/assets/themes/base/_layouts/frontend/pages/team/member.html +5 -3
- package/dist/assets/themes/base/_sections/about/letter/section.html +1 -1
- package/dist/assets/themes/base/_sections/about/letter/section.json5 +4 -4
- package/dist/assets/themes/base/_sections/marketing/bento/section.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/bento/section.json5 +15 -15
- package/dist/assets/themes/base/_sections/marketing/cta/section.json5 +1 -1
- package/dist/assets/themes/base/_sections/marketing/hero/section.html +6 -6
- package/dist/assets/themes/base/_sections/marketing/hero/section.json5 +10 -10
- package/dist/assets/themes/base/_sections/marketing/product-demo/section.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/product-demo/section.json5 +2 -2
- package/dist/assets/themes/base/_sections/marketing/stats/section.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/stats/section.json5 +5 -5
- package/dist/assets/themes/base/_sections/marketing/trusted-by/section.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/trusted-by/section.json5 +2 -2
- package/dist/assets/themes/neobrutalism/_layouts/frontend/pages/index.html +10 -10
- package/dist/assets/themes/newsflash/_layouts/frontend/pages/index.html +10 -10
- package/dist/assets/themes/newsflash/_sections/marketing/desks/section.html +2 -2
- package/dist/assets/themes/newsflash/_sections/marketing/desks/section.json5 +4 -4
- package/dist/build.js +69 -28
- package/dist/cli-run.js +20 -13
- package/dist/cli.js +12 -7
- package/dist/commands/build.js +0 -2
- package/dist/commands/deploy.js +116 -44
- package/dist/commands/finalize-release.js +5 -4
- package/dist/commands/launch.js +12 -7
- package/dist/commands/lib/deploy-precheck.js +66 -34
- package/dist/commands/lib/ensure-target.js +71 -11
- package/dist/commands/package.js +0 -1
- package/dist/commands/publish.js +11 -4
- package/dist/commands/release.js +99 -252
- package/dist/commands/runner.js +42 -5
- package/dist/commands/sign-windows.js +46 -15
- package/dist/commands/test.js +4 -3
- package/dist/commands/validate-certs.js +291 -115
- package/dist/config/page-template.html +4 -0
- package/dist/defaults/.github/workflows/build.yml +144 -64
- package/dist/defaults/AGENTS.md +3 -2
- package/dist/defaults/_.gitignore +4 -2
- package/dist/defaults/config/certs/README.md +25 -45
- package/dist/defaults/config/omega.json5 +66 -32
- package/dist/defaults/hooks/deploy/pre.js +10 -0
- package/dist/defaults/src/assets/scss/main.scss +12 -2
- package/dist/defaults/src/integrations/tray/index.js +1 -1
- package/dist/gulp/main.js +13 -25
- package/dist/gulp/tasks/audit.js +18 -6
- package/dist/gulp/tasks/build-config.js +181 -60
- package/dist/gulp/tasks/bundle.js +108 -36
- package/dist/gulp/tasks/release.js +86 -4
- package/dist/gulp/tasks/sass.js +11 -0
- package/dist/hooks/lib/notarize-tools.js +137 -0
- package/dist/hooks/notarize-artifacts.js +57 -0
- package/dist/hooks/notarize.js +59 -8
- package/dist/lib/auth-persistence.js +25 -0
- package/dist/lib/client-bridge.js +11 -8
- package/dist/lib/deep-link.js +15 -8
- package/dist/lib/protocol.js +7 -1
- package/dist/lib/restart-manager/install.js +6 -3
- package/dist/lib/sign-helpers/auto-unlock.js +65 -27
- package/dist/lib/sign-helpers/console-lock.js +34 -0
- package/dist/lib/sign-helpers/exec-with-limit.js +68 -0
- package/dist/lib/sign-helpers/resolve-icons.js +6 -4
- package/dist/lib/tray.js +7 -6
- package/dist/main.js +16 -0
- package/dist/preload.js +8 -0
- package/dist/renderer.js +16 -4
- package/dist/runner/job-started.js +104 -0
- package/dist/test/fixtures/consumer-app/config/omega.json5 +7 -0
- package/dist/test/fixtures/consumer-app/package.json +1 -1
- package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +7 -1
- package/dist/test/harness/main-entry.js +2 -1
- package/dist/test/harness/renderer-preload.js +12 -3
- package/dist/test/runners/boot.js +101 -11
- package/dist/test/runners/electron.js +1 -1
- package/dist/test/suites/boot/consumer-app-boots.test.js +54 -0
- package/dist/test/suites/build/audit.test.js +45 -6
- package/dist/test/suites/build/auth-persistence-resolve.test.js +119 -0
- package/dist/test/suites/build/auto-unlock.test.js +105 -0
- package/dist/test/suites/build/boot-runner-timeout.test.js +253 -0
- package/dist/test/suites/build/brand-scss.test.js +106 -0
- package/dist/test/suites/build/build-config.test.js +146 -36
- package/dist/test/suites/build/build-json-bake.test.js +245 -0
- package/dist/test/suites/build/build-verbs.test.js +48 -15
- package/dist/test/suites/build/build-workflow-jobs.test.js +190 -0
- package/dist/test/suites/build/cli.test.js +32 -10
- package/dist/test/suites/build/config-schema.test.js +4 -4
- package/dist/test/suites/build/console-lock.test.js +51 -0
- package/dist/test/suites/build/defaults-scaffold.test.js +71 -2
- package/dist/test/suites/build/deploy-direct.test.js +241 -0
- package/dist/test/suites/build/deploy-dispatch.test.js +287 -0
- package/dist/test/suites/build/deploy-hook.test.js +169 -0
- package/dist/test/suites/build/ensure-target.test.js +14 -2
- package/dist/test/suites/build/env-delivery.test.js +19 -10
- package/dist/test/suites/build/env-watch.test.js +18 -7
- package/dist/test/suites/build/esm-only-dependency.test.js +127 -0
- package/dist/test/suites/build/exec-with-limit.test.js +53 -0
- package/dist/test/suites/build/finalize-release.test.js +2 -2
- package/dist/test/suites/build/get-config.test.js +120 -8
- package/dist/test/suites/build/github-utils.test.js +12 -6
- package/dist/test/suites/build/license-stamp.test.js +6 -4
- package/dist/test/suites/build/manager.test.js +88 -68
- package/dist/test/suites/build/manifest-deps.test.js +116 -0
- package/dist/test/suites/build/merge-line-files.test.js +27 -4
- package/dist/test/suites/build/notarize-artifacts.test.js +135 -0
- package/dist/test/suites/build/notarize-tools.test.js +38 -0
- package/dist/test/suites/build/notarize.test.js +207 -0
- package/dist/test/suites/build/release-pipeline.test.js +38 -60
- package/dist/test/suites/build/release-skipped-upload.test.js +107 -0
- package/dist/test/suites/build/resolve-icons.test.js +35 -35
- package/dist/test/suites/build/runner-job-guard.test.js +182 -0
- package/dist/test/suites/build/runner.test.js +25 -2
- package/dist/test/suites/build/sentry.test.js +8 -3
- package/dist/test/suites/build/setup-scripts.test.js +3 -0
- package/dist/test/suites/build/sign-windows.test.js +92 -8
- package/dist/test/suites/build/test-stealth.test.js +17 -11
- package/dist/test/suites/build/url-helpers.test.js +37 -17
- package/dist/test/suites/build/validate-certs.test.js +428 -55
- package/dist/test/suites/build/validate-config.test.js +3 -3
- package/dist/test/suites/main/auth-flow.test.js +12 -0
- package/dist/test/suites/main/auth-persistence.test.js +14 -17
- package/dist/test/suites/main/auto-updater.test.js +2 -2
- package/dist/test/suites/main/boot-sequence.test.js +1 -1
- package/dist/test/suites/main/client-bridge.integration.test.js +5 -82
- package/dist/test/suites/main/client-bridge.test.js +19 -6
- package/dist/test/suites/main/deep-link.test.js +54 -0
- package/dist/test/suites/main/startup-paths-and-ua.test.js +1 -1
- package/dist/test/suites/main/url-helpers.test.js +81 -72
- package/dist/test/suites/renderer/cross-context-helpers.test.js +19 -16
- package/dist/utils/build-pipeline.js +10 -10
- package/dist/utils/github.js +12 -51
- package/dist/utils/load-env.js +66 -0
- package/dist/utils/mode-helpers.js +43 -111
- package/dist/utils/platform.js +37 -0
- package/dist/utils/runner-env.js +2 -1
- package/dist/utils/runner-job-guard.js +149 -0
- package/dist/utils/ship-keys.js +52 -0
- package/dist/utils/test-stealth.js +5 -3
- package/dist/utils/url-helpers.js +33 -17
- package/dist/vendor/config/bundle-id.js +53 -0
- package/dist/vendor/config/client-config.js +141 -0
- package/dist/vendor/config/company.js +334 -15
- package/dist/vendor/config/dev-facts.js +48 -0
- package/dist/vendor/config/env-delivery.js +231 -9
- package/dist/vendor/config/env-retired.js +137 -0
- package/dist/vendor/config/env-rules.js +22 -3
- package/dist/vendor/config/env-schema.js +234 -117
- package/dist/vendor/config/env.js +55 -26
- package/dist/vendor/config/environment.js +189 -0
- package/dist/vendor/config/hooks.js +13 -11
- package/dist/vendor/config/index.js +121 -44
- package/dist/vendor/config/load.js +366 -115
- package/dist/vendor/config/merge.js +2 -2
- package/dist/vendor/config/order.js +3 -3
- package/dist/vendor/config/platforms.js +276 -0
- package/dist/vendor/config/repo.js +226 -104
- package/dist/vendor/config/retired-keys.js +232 -27
- package/dist/vendor/config/schema.js +525 -99
- package/dist/vendor/config/site-global.js +63 -53
- package/dist/vendor/config/targets.js +187 -0
- package/dist/vendor/config/validate.js +119 -59
- package/dist/vendor/devkit/argv.js +118 -0
- package/dist/vendor/devkit/attach-log-file.js +21 -13
- package/dist/vendor/devkit/brand-tokens.js +278 -0
- package/dist/vendor/devkit/brand-version.js +264 -0
- package/dist/vendor/devkit/build-json.js +91 -0
- package/dist/vendor/devkit/bundle.js +48 -0
- package/dist/vendor/devkit/certificate-expiry.js +108 -0
- package/dist/vendor/devkit/certs.js +16 -194
- package/dist/vendor/devkit/ci-workflows.js +124 -8
- package/dist/vendor/devkit/cli-router.js +3 -3
- package/dist/vendor/devkit/defaults-engine.js +69 -7
- package/dist/vendor/devkit/deploy-follow.js +297 -0
- package/dist/vendor/devkit/deploy-precheck.js +23 -8
- package/dist/vendor/devkit/deploy-record.js +11 -27
- package/dist/vendor/devkit/deploy-snapshot.js +661 -0
- package/dist/vendor/devkit/deploy.js +445 -75
- package/dist/vendor/devkit/git-auth.js +73 -0
- package/dist/vendor/devkit/git-remote.js +95 -0
- package/dist/vendor/devkit/github-repo.js +290 -0
- package/dist/vendor/devkit/local.js +47 -0
- package/dist/vendor/devkit/merge-line-files.js +23 -16
- package/dist/vendor/devkit/omega-bin.js +18 -3
- package/dist/vendor/devkit/pack-local.js +391 -0
- package/dist/vendor/devkit/preludes/index.js +120 -0
- package/dist/vendor/devkit/preludes/origin-heal.js +156 -0
- package/dist/vendor/devkit/service-account.js +43 -0
- package/dist/vendor/devkit/ship-plan.js +112 -0
- package/dist/vendor/devkit/signing-env.js +180 -0
- package/dist/vendor/devkit/signing-tree.js +92 -0
- package/dist/vendor/devkit/target-seams.js +142 -0
- package/dist/vendor/devkit/target-secrets.js +235 -50
- package/dist/vendor/devkit/test/esm-only-fixture.js +48 -0
- package/dist/vendor/devkit/test/fixtures/esm-only-package/browser.js +19 -0
- package/dist/vendor/devkit/test/fixtures/esm-only-package/index.js +20 -0
- package/dist/vendor/devkit/test/fixtures/esm-only-package/package.json +13 -0
- package/dist/vendor/monitoring/env.js +20 -10
- package/dist/vendor/monitoring/main.js +1 -1
- package/dist/vendor/monitoring/preload.js +1 -1
- package/dist/vendor/monitoring/renderer.js +1 -1
- package/docs/analytics.md +1 -1
- package/docs/auto-updater.md +5 -5
- package/docs/boot-sequence.md +1 -1
- package/docs/build-system.md +15 -7
- package/docs/client-bridge.md +9 -7
- package/docs/config-schema.md +4 -4
- package/docs/css.md +8 -2
- package/docs/deep-link.md +12 -4
- package/docs/environment-detection.md +32 -24
- package/docs/hooks.md +3 -1
- package/docs/icons.md +7 -7
- package/docs/index.md +61 -23
- package/docs/installer-options.md +24 -21
- package/docs/logging.md +5 -5
- package/docs/releasing.md +25 -17
- package/docs/runner.md +40 -5
- package/docs/shared/brands.md +12 -6
- package/docs/shared/breaking-changes.md +375 -21
- package/docs/shared/config.md +757 -199
- package/docs/shared/deploys.md +194 -91
- package/docs/shared/icons.md +18 -0
- package/docs/shared/local-dev.md +24 -6
- package/docs/shared/logging.md +9 -6
- package/docs/shared/monitoring.md +27 -13
- package/docs/shared/publishing.md +3 -3
- package/docs/shared/rulings.md +2 -2
- package/docs/shared/testing.md +1 -1
- package/docs/shared/theming.md +26 -1
- package/docs/shared/translation.md +49 -7
- package/docs/shared/updates.md +1 -1
- package/docs/signing.md +59 -33
- package/docs/test-framework.md +10 -5
- package/docs/themes.md +15 -1
- package/package.json +18 -12
- package/bin/omega-desktop +0 -2
- package/dist/commands/push-secrets.js +0 -141
- package/dist/test/suites/build/deliver-certs.test.js +0 -95
- package/dist/test/suites/build/derive-signing-env.test.js +0 -122
- package/dist/test/suites/build/push-secrets.test.js +0 -226
- package/dist/test/suites/build/resolve-signing-cert.test.js +0 -342
- package/dist/utils/deliver-certs.js +0 -69
- package/dist/utils/derive-signing-env.js +0 -56
- package/dist/utils/resolve-signing-cert.js +0 -175
- package/dist/vendor/config/desktop-artifacts.js +0 -110
- package/dist/vendor/config/instances.js +0 -208
- /package/dist/defaults/config/icons/{macos → mac}/dmg.png +0 -0
- /package/dist/defaults/config/icons/{macos → mac}/icon.png +0 -0
- /package/dist/defaults/config/icons/{macos → mac}/tray.png +0 -0
package/docs/shared/icons.md
CHANGED
|
@@ -22,6 +22,24 @@ overdraw their viewBox).
|
|
|
22
22
|
|
|
23
23
|
**Emojis are text**, not icons: type the character. Nothing to build.
|
|
24
24
|
|
|
25
|
+
**A DATA key that carries an icon carries the same string**: every chrome
|
|
26
|
+
`icon` (nav, sidebar, topbar, page header, account dropdown, account section
|
|
27
|
+
header, footer) is the full class string (`icon: 'fa-brands fa-github'`), never
|
|
28
|
+
a bare name a template wraps
|
|
29
|
+
([#903](https://github.com/Omega-JS-Stack/omega/issues/903)). One shape to
|
|
30
|
+
author, and every family the brand's set carries is reachable from data.
|
|
31
|
+
|
|
32
|
+
The same string is what a SECTION arg, a page-layout arg and the feature
|
|
33
|
+
catalog's `icon` carry
|
|
34
|
+
([#929](https://github.com/Omega-JS-Stack/omega/issues/929)): `{% section
|
|
35
|
+
"marketing/stats" %}` takes `icon: 'fa-brands fa-figma'`, and every template
|
|
36
|
+
and runtime builder emits the value verbatim, adding only its own size and
|
|
37
|
+
spacing classes. One key, one shape, wherever it lives. The two keys that name
|
|
38
|
+
a PLATFORM rather than an icon (the footer's `socials` block and a team
|
|
39
|
+
member's link `id`) stay platform keys: a social profile is always a brand
|
|
40
|
+
mark, so the family is derived at the one site that knows it and a brand never
|
|
41
|
+
types a class for a platform it only named.
|
|
42
|
+
|
|
25
43
|
## The two halves
|
|
26
44
|
|
|
27
45
|
| Half | When | What happens |
|
package/docs/shared/local-dev.md
CHANGED
|
@@ -35,12 +35,12 @@ omega dev --full # boot on the WHOLE manage walk, not just the boo
|
|
|
35
35
|
- **The boot cycle never waits on a human** ([#228](https://github.com/Omega-JS-Stack/omega/issues/228)): it runs non-interactive, so any step that needs a person — a console confirm, a consent flow, a secret paste — steps aside into the run summary's ⚑ pending list, each item naming its `npm run manage -- --service=<name>` rerun. The dev legs boot regardless of what is pending; only real errors (broken config, an unloadable brand) stop the boot. A never-setup brand and a fully setup one behave identically here — the difference shows up as a longer pending list, not as a stalled terminal. A dead Google grant is pending too, not an error: the service warns into the same list and the walk carries on. One consequence on a `--full` boot: its web build uses the committed translation cache only (`--cached-only`, the same determinism law the pipeline and deploys follow), so new strings translate on the next interactive manage or build.
|
|
36
36
|
- **Default set = `web` + `backend`** — the local web loop. GUI/watcher targets (desktop opens an Electron window; extension runs a build watcher) never boot unless named via `--target=`/`--all` ([#780](https://github.com/Omega-JS-Stack/omega/issues/780)). The default also adapts: a web-only brand boots just web, no warning.
|
|
37
37
|
- **Legs**: web → the target's `npm start` (`omega dev`, :4000); backend → `npm run emulator` (auth/firestore/functions/database/hosting + seeded personas). Backend boots first so its port map is published before web reads it, and the order is optional either way ([#346](https://github.com/Omega-JS-Stack/omega/issues/346)): the web dev server rewrites each page's port map into the response as it serves it, so a backend that publishes later reaches the browser on the next request instead of never.
|
|
38
|
-
- **
|
|
38
|
+
- **Sibling web ports offset deterministically** ([#886](https://github.com/Omega-JS-Stack/omega/issues/886)): each web target wants the classic base + its position among the brand's `web`-type targets (targets/web → :4000, targets/admin → :4001), so they dev side-by-side from their own target dirs; the N7 allocator still bumps if the offset port happens to be taken, and pins (`--port` / config `ports.website`) win verbatim. A brand with one web target stays on :4000 exactly as before.
|
|
39
39
|
- **Per-target Node**: each leg spawns under its target's own `.nvmrc` major (web and backend pin different ones).
|
|
40
40
|
- **A leg targets the `https` port, never `hosting`** ([#795](https://github.com/Omega-JS-Stack/omega/issues/795)): the ports file publishes both, and only `https` is the public origin under the local certificate; `hosting` is the internal plain-http port the mkcert proxy forwards to, so a consumer process aimed there is talking to the proxy's back door instead of the address every other surface uses. Every leg `omega dev` spawns carries `NODE_EXTRA_CA_CERTS=<mkcert -CAROOT>/rootCA.pem` (a shell-set value wins verbatim; a host without mkcert gets no key at all), so a brand's own Node process VERIFIES that certificate rather than dying on it. A leg that never speaks TLS ignores the variable, and since this is verification and not a bypass, Node prints no warning. The emulator's and `omega serve`'s own children take the same variable in place of the old `NODE_TLS_REJECT_UNAUTHORIZED=0`, whose boot warning is gone with it; that bypass survives in exactly one place, a host whose mkcert root vanished under certificates already on disk.
|
|
41
|
-
- **One terminal covers FRAMEWORK edits too** ([#587](https://github.com/Omega-JS-Stack/omega/issues/587)): when the brand's `@omega.js/*` deps RESOLVE into a monorepo checkout, the boot starts that monorepo's watch as a session child
|
|
41
|
+
- **One terminal covers FRAMEWORK edits too** ([#587](https://github.com/Omega-JS-Stack/omega/issues/587)): when the brand's `@omega.js/*` deps RESOLVE into a monorepo checkout, the boot starts that monorepo's watch as a session child: no flag, no second terminal, so editing a framework's `src/` rebuilds its `dist/` while the stack runs. Resolution answers the question, never the manifest (a `file:` spec can be stale, and workspace hoisting puts the copy at the brand root): `resolveLinkedMonorepo(brandRoot)`. Lock-aware: a watch already running (root `npm start`, or another brand's session) is REUSED, never doubled, session-scoped, so it dies with the stack, and its output rides the `[watch]` tag into `logs/dev.log`. A registry-installed brand has nothing to watch and says so in one line. It starts AFTER the freshness sweep on purpose: the sweep's verdict depends on whether a watch holds the lock ([#281](https://github.com/Omega-JS-Stack/omega/issues/281)/[#398](https://github.com/Omega-JS-Stack/omega/issues/398)), so starting one first would change the answer it just gave. A FRESH watch's initial prepare rewrites every package's `dist/` as it runs, so the boot WAITS for that pass to land ([#670](https://github.com/Omega-JS-Stack/omega/issues/670)): the helper's `ready` promise resolves once every watched package has printed its `Ready for changes!` line (or the moment the watch child exits without reporting, or after 120s with one warning naming the stragglers), and only then do the legs boot, so nothing loads a CLI out from under the rewrite. **An ALREADY-RUNNING watch gates the same way** ([#622](https://github.com/Omega-JS-Stack/omega/issues/622)): the branch a linked brand normally takes, since the root `npm start` is usually already up: with no child stdout to read, the boot tails that watch's own `.temp/logs/watch-all.log` (believed only when its pid header IS the lock owner's) through the same tracker, and also waits out a vendor-propagation pass holding `.omega/vendor-propagation.lock`. A settled watch answers off the file with no wait at all; a watch that dies mid-wait settles it at once. Same helper as the web target's `--local` prelude: one implementation, two callers.
|
|
42
42
|
- **Every seeded persona is a FULL account** ([#327](https://github.com/Omega-JS-Stack/omega/issues/327)): identical in shape AND in substance to a real user — a name, a place, a phone, a company, a birthday, and the device and IP it signed up from — so a persona renders like a customer on every surface that shows a person. The profile is DERIVED from the persona key (`packages/backend/src/test/test-accounts.js` `seededProfile`), so it is the same on every boot and a new persona is born complete; anything a persona names for itself wins. Paid personas carry the provider record a real purchase leaves (provider, resource, order, term start, the event that last wrote it), which is what payment-gated surfaces — the billing card's save offer — read before they show anything. Established personas also carry the two lists an account accumulates ([#343](https://github.com/Omega-JS-Stack/omega/issues/343)): the REFERRALS an affiliate link earned (`{ uid, timestamp }`, exactly as a signup appends them, and naming other personas — so whether a referral converted is the referred account's own subscription state) — carried by the DEDICATED `referrer` persona and nothing else ([#363](https://github.com/Omega-JS-Stack/omega/issues/363)), because a persona demonstrates exactly its own scenario — and the ACTIVE SESSIONS of the two or three devices they are signed in on (Realtime Database records under `sessions/app`, seeded on boot and restored by "Reset to seed", because they live outside the user doc). Demo-safe by construction: documentation-range IPs, fictional 555 numbers, invented companies.
|
|
43
|
-
- **The dev palette** (the DEV pull-tab the web framework renders in development): one-click sign-in as the seeded personas, including the four billing-journey accounts ([#215](https://github.com/Omega-JS-Stack/omega/issues/215)), and a "Reset to seed" button on any signed-in test account
|
|
43
|
+
- **The dev palette** (the DEV pull-tab the web framework renders in development): one-click sign-in as the seeded personas, including the four billing-journey accounts ([#215](https://github.com/Omega-JS-Stack/omega/issues/215)), and a "Reset to seed" button on any signed-in test account, a development-only backend route rebuilds the account from its canonical seed shape. The switcher's roster is the SEED's own ([#400](https://github.com/Omega-JS-Stack/omega/issues/400)): the backend labels each human-facing persona (`palette: '<Label>'` in `packages/backend/src/test/test-accounts.js`) and serves that list, in declaration order, at `GET /omega/test/roster`; the palette fetches it on build and keeps no copy, so a persona seeded today is switchable today and the machinery an automated suite drives never appears. The WHOLE seed is read, both halves ([#712](https://github.com/Omega-JS-Stack/omega/issues/712)): a project's own personas from its `test/_init.js` carry the same label and are offered after the framework's, so a consumer persona is switchable the moment it is seeded. The address the palette signs in on is the brand's HOST, and so is the one the seeder creates ([#708](https://github.com/Omega-JS-Stack/omega/issues/708)): ONE derivation, `@omega.js/config`'s `resolvedBrandHost` (a target's own `url`, else `brand.url`), because a brand answering support mail on the apex while the site sits on a subdomain used to seed accounts the palette could never sign in as. There is no fallback list: with no emulator up the dropdown holds its placeholder alone and the "Signed in as" line carries the reason on a second line, under whoever you are signed in as (that readout is composed, so an auth state settling after the failure lands beside it rather than on top of it). A page opened while the emulator is still booting does not stay stuck there ([#402](https://github.com/Omega-JS-Stack/omega/issues/402)): a spinner and a "Backend starting…" line sit at the top of the panel and the roster is fetched again every two seconds, forever, until it answers; the attempt that lands fills the dropdown, preselects the signed-in persona, and clears both the indicator and the explanation, so no reload is needed. A built-in **Storage** section ([#390](https://github.com/Omega-JS-Stack/omega/issues/390)) covers the client blob: a target dropdown ("All" first, then every top-level key, re-derived from the LIVE blob each time the panel opens) with Log and Clear buttons acting on the selected target: Log prints the parsed value into the console, Clear removes it, and nothing asks you to confirm. Source: `packages/web/core/js/core/dev-palette.js`. Pages contribute their own controls via `registerDevSection` (`core/js/core/dev-sections.js`, [#234](https://github.com/Omega-JS-Stack/omega/issues/234)): sections render on open and merge by id: the checkout page's controls (product, frequency, pre-delay, trial, card provider, reCAPTCHA, the decline toggle) live in the palette's Checkout section, and every one of them applies the same way: Apply & reload navigates with its param set, the decline arm included (`_dev_decline`, which stays armed until you apply it away); the page's old gear dropdown is gone.
|
|
44
44
|
- **The palette is the ONLY dev-testing surface** (Ian's ruling, [#342](https://github.com/Omega-JS-Stack/omega/issues/342), extending [#329](https://github.com/Omega-JS-Stack/omega/issues/329)): no client-side test personas as code objects, no helper hung on `window`, no dev switch you can only reach by already knowing its name — hidden functions get forgotten in six months. Alongside Checkout the panel now carries **Tools** (log opening tags, toggle theme), **Icons** (re-run the missing-icon audit), **Download** (open the onboarding walkthrough for a platform), **Extension** (fire a browser's install click) and **OAuth** (rehearse a returning provider redirect: returning user, new user, credential conflict). The account page carries NO control of its own: its referrals and sessions lists were the last client-side fixtures (`?_dev_prefill`), and the personas carry both now ([#343](https://github.com/Omega-JS-Stack/omega/issues/343)) — switching persona IS the affordance. Every one of them is a `@dev-only` block, so a production build ships neither the control nor what it unlocks. The rule outlives the sweep as a guard: `packages/web/test/dev-hooks-guard.test.js` fails on a new `_dev_*` hook or `window.<helper>` in client code, on a listed hook no palette section actually offers, and on any hook read outside a `@dev-only` block.
|
|
45
45
|
- **Google/OAuth signin uses the redirect flow here, same as production** ([#156](https://github.com/Omega-JS-Stack/omega/issues/156)): the auth emulator returns its credential through storage on the origin it is served from, so `omega dev` proxies the emulator under the SITE origin and the return leg survives the browser's storage partitioning. Details in [docs/web/index.md](../web/index.md).
|
|
46
46
|
- Output is line-prefixed per target (`[backend] …`, `[web] …`); one Ctrl-C stops everything; a leg dying alone is announced and its siblings stay up.
|
|
@@ -86,7 +86,11 @@ Unchanged contract for consumers, now monorepo-backed: `mgr i local` (web, deskt
|
|
|
86
86
|
|
|
87
87
|
**The brand root itself is part of the tree (cp195):** onboard scaffolds `@omega.js/manager` into the brand root's devDependencies — the omega-bin dispatcher resolves brand-level verbs (`omega dev`, manage, the scaffolded `start`/`manage` scripts) FROM the brand root, and without the declaration nothing installs the manager outside the monorepo (inside it, workspace hoisting masked the gap). `linkLocalPackages()` links it like any target dep (`discoverTargets` already includes the brand root).
|
|
88
88
|
|
|
89
|
-
**Outside brands may COMMIT relative `file:` specs — the real brand
|
|
89
|
+
**Outside brands may COMMIT relative `file:` specs — the real brand did in the local era (cp229):** `../omega-omega` declared every `@omega.js/*` dep as `file:../../../omega/packages/<name>` (brand root: `file:../omega/packages/manager`), the same pattern the in-repo brands still use at their own depth. Clone the two repos side by side and a plain `npm install` links the whole tree with zero linker involvement; `linkLocalPackages()` all-skips because the specs already resolve into the monorepo. Since the first publish (0.50.0) the real brand pins the exact registry version instead; the in-repo brands stay on `file:` specs by ruling (2026-09-10).
|
|
90
|
+
|
|
91
|
+
**A linked brand reaches CI as TARBALLS, not as a checkout** ([#872](https://github.com/Omega-JS-Stack/omega/issues/872)): a runner has nothing at the path `file:` specs name, so `omega deploy` packs every linked package into the brand's `omega_modules/` and pushes that snapshot to the brand repo, and the runner installs it with a plain `npm install`. Nothing is asked of the consumer or of the CI tool, and nothing framework-aware runs on the box. The lane, the pack step and the two hops: [deploys.md](deploys.md).
|
|
92
|
+
|
|
93
|
+
**`npx omega` is only ever run inside an installed target** ([#881](https://github.com/Omega-JS-Stack/omega/issues/881)): with no local bin npx fetches a stranger's package named `omega` from the registry, and the plugin's npx hook refuses that in agent shells.
|
|
90
94
|
|
|
91
95
|
## Vendoring vs runtime deps (what ships where)
|
|
92
96
|
|
|
@@ -124,9 +128,14 @@ Every framework CLI boot (web/backend/desktop/extension/manager — `freshnessBo
|
|
|
124
128
|
|
|
125
129
|
**With the watch DOWN, the boot heals the link itself** ([#398](https://github.com/Omega-JS-Stack/omega/issues/398), Ian's call 2026-08-20). The stop is right only while something else owns the rebuild; with no watch running it is pure friction — the guard already knows the watch is down (the `.omega/dev-watch.lock` pid probe it warns from), so a stale linked dist takes the ordinary heal: one `npm run prepare` in place under the package's heal lock, `rebuilt` by `self`, then the boot's re-exec. The hazard #281 named is narrowed, not dismissed: the heal lock still serializes the CLIs booting on that package, and the largest concurrent writer is by definition not running. The once-per-process watch-down warning STAYS on this path — a stale linked dist is healed once at boot, and a framework edit made during the session still needs `npm start` for live rebuilds. **And a heal that FAILS is a loud stop, not a shrug**: the outcome is `heal-failed`, and the boot exits 1 naming the package, the staleness, the prepare's exit status and the `npm run prepare` to run by hand in that checkout. A plain checkout keeps the old warn-and-continue (its dist is the developer's own, and nothing shared hangs on this boot), but a monorepo link has no watch coming to land the build, so continuing would serve code nobody built — the silent fallback #281 forbids. `omega dev`'s hoisted sweep returns those entries as `healFailed` and stops the fan-out before any leg spawns, exactly as it does for `staleLinked`.
|
|
126
130
|
|
|
127
|
-
**The INSTALL path is guarded at the prepare script** ([#350](https://github.com/Omega-JS-Stack/omega/issues/350)). npm runs a `file:`-linked dependency's `prepare` INSIDE the linked checkout, so `omega i local`, `omega dev --local` and any plain `npm install` in a linked brand rebuilt a monorepo package in place through the one door a CLI guard cannot see
|
|
131
|
+
**The INSTALL path is guarded at the prepare script** ([#350](https://github.com/Omega-JS-Stack/omega/issues/350)). The gate is required by a RELATIVE path (`../devkit/tools/prepare-guard`) and borrows nothing from the rest of devkit, because a linked brand's install reifies its `file:` links, and so runs this prepare, before there is any `node_modules/@omega.js/devkit` link to resolve through; and a checkout with no root `node_modules` at all skips its prepare outright, there being nothing to build with ([#868](https://github.com/Omega-JS-Stack/omega/issues/868)). npm runs a `file:`-linked dependency's `prepare` INSIDE the linked checkout, so `omega i local`, `omega dev --local` and any plain `npm install` in a linked brand rebuilt a monorepo package in place through the one door a CLI guard cannot see: npm invokes prepare, devkit never gets a say. Every dist-building package's prepare IS devkit's gate: `node -e "require('../devkit/tools/prepare-guard').run()"` (`packages/devkit/tools/prepare-guard.js`), which runs the decision and then prepare-package itself. When npm's install root (`npm_config_local_prefix`, `INIT_CWD` as the fallback) lies OUTSIDE the monorepo that contains the package, the build is skipped (prepare-package is never even loaded, exit 0, so the consumer's install completes normally) with one stderr line naming the package, the install that reached in, and the watch that owns the dist. It fires for every TREE-TOUCHING command from outside: `install`, `ci`, `update`, `rebuild`, `dedupe`, the five npm reports in `npm_command` that re-run a linked package's prepare (npm 11.12.1), and for nothing else: the monorepo's own root install, workspace installs (`-w packages/web`), an install typed inside a package or an in-repo app, `npm run prepare`, and the `npm pack`/`npm publish` prepare lane all build exactly as before, so a published tarball still carries a freshly built dist. npm buffers lifecycle output, so the notice surfaces under `--foreground-scripts`.
|
|
132
|
+
|
|
133
|
+
**The gate keeps itself wired, even when the prepare fails** ([#870](https://github.com/Omega-JS-Stack/omega/issues/870)). prepare-package OWNS `scripts.prepare`: every full build rewrites the manifest with its own canonical one-liner, which would silently drop the gate on the monorepo's next prepare. Two things put it back, both through the one `ensureGuarded()`/`rewire()` pair in `prepare-guard.js`, so no lane carries a copy of the gated string:
|
|
134
|
+
|
|
135
|
+
1. **`rewire()` is the FIRST `preparePackage.hooks.after` command of every package**, ahead of the vendor hook, because the manifest write is the last thing prepare-package does before its hooks. It restores the gated line in prepare-package's own formatting (idempotent and narrow: it writes only when the manifest holds prepare-package's exact string, and never touches a prepare it does not own), and running first is what covers the `prepare:watch` lane, which never goes through `scripts.prepare` at all. Ordering used to be the other way, and a vendor hook that failed (twice: a devkit source string that looked like a package-internal require) stopped the chain before the rewire entry and left the manifest UNGUARDED.
|
|
136
|
+
2. **`run()` calls `ensureGuarded()` in a `finally`**, so the `prepare` lane ends gated whether the build succeeded, a hook exited nonzero or prepare-package itself threw, whatever the hook order says. The failure stays loud: the rejection is returned, so the script still exits nonzero.
|
|
128
137
|
|
|
129
|
-
**
|
|
138
|
+
**And the freshness heal refuses to leave a manifest its prepare stripped**: after its `npm run prepare` the heal calls that same `ensureGuarded()` on the package it prepared (the guard loaded from the devkit beside it), which covers the one case a `finally` cannot reach, a prepare killed outright. Pinned by devkit `test/prepare-guard.test.js` (27 tests: the decision table, the notice, real-npm/real-prepare-package fixture runs including the red baselines, a failing after hook that still ends gated, the heal on a stripped manifest, and a sweep asserting every dist-building `package.json` carries the gate with `rewire()` first).
|
|
130
139
|
|
|
131
140
|
The consequence is deliberate: with that watch running, a linked dist that is missing, unbuilt or stale FAILS the consumer build loudly, before the verb runs, naming the package, the evidence, the checkout it will not touch, and the watch already on the job:
|
|
132
141
|
|
|
@@ -145,3 +154,12 @@ There is no silent fallback and no staging copy: the build runs on a dist the wa
|
|
|
145
154
|
**A live watch buys a bounded grace, not blind trust.** Stale with the root-watch lock held → recheck for ~2s so an in-flight watcher copy can land (dim note, `rebuilt` by `watch` if it does — still a heal, so the boot re-execs onto it), then the verdict: a monorepo link stops the invocation, any other local checkout heals here. **A dead watcher is loud**: a monorepo-linked boot with no live lock prints one stderr line naming the fix (`npm start` in the monorepo) — the boot's own heal ([#398](https://github.com/Omega-JS-Stack/omega/issues/398)) repairs a STALE dist once, at boot, and nothing propagates a src edit made afterwards, so the warning still carries the whole story (it fires on a fresh dist too, so it states that standing deal rather than claiming a heal that may not have happened). Both surfaced from the freshness path, so all five framework CLIs get them for free.
|
|
146
155
|
|
|
147
156
|
**Heals are locked per package** (a local checkout outside this monorepo, a monorepo link with the watch down, and the watch's own prepares): a mkdir-as-mutex at `<package>/.omega/heal.lock` with the owner pid inside (the `withStateLock` idiom from `deploy-record.js`; pid liveness replaces its mtime age because a real prepare holds the lock for minutes). The loser waits, then RE-CHECKS freshness — the winner's build makes it a no-op, so two or ten CLIs booting on the same stale link produce one build. Abandoned locks (owner gone — an EPERM pid is LIVE, never stolen) are stolen; a wait past the deadline proceeds unlocked rather than failing a boot, and lock bookkeeping that cannot be written (read-only fs, full disk) degrades to unlocked instead of throwing out of a heal. **The vendor-propagation watcher takes the same lock** around its own `npm run prepare` spawn (`startVendorPropagation`, held for the child's whole life, awaited async so the watcher keeps serving its other watches) — that spawn is devkit's own, so it locks; only prepare-package's INTERNAL src→dist copying stays unlocked third-party territory, and it converges on the watcher's next change event.
|
|
157
|
+
|
|
158
|
+
## Boot order: freshness, preludes, verb ([#890](https://github.com/Omega-JS-Stack/omega/issues/890))
|
|
159
|
+
|
|
160
|
+
Every framework CLI boot (web/backend/desktop/extension/manager) runs exactly two steps before the verb, in this order, with the identical call on all five:
|
|
161
|
+
|
|
162
|
+
1. **the freshness guard** above: a stale locally-linked `dist/` heals (or stops the boot loudly) and the invocation re-execs, so no verb ever runs stale framework code;
|
|
163
|
+
2. **the boot preludes** (`@omega.js/devkit/preludes`, `runPreludes({ verb: process.argv[2], targetDir: process.cwd() })`): the cheap, non-interactive checks the whole CLI surface has to settle first, each declaring the verbs it targets (`'all'`, one, or a list) and each a no-op on the ordinary. The list, the contract and the preludes that ship are in [devkit/index.md](../devkit/index.md#boot-preludes-890).
|
|
164
|
+
|
|
165
|
+
The order is the point: the preludes run in the process that will run the verb, which only the freshness step can guarantee is the current framework code. First shipped prelude: the `origin` heal, so a brand whose repo moved is pointed at the address GitHub's redirect answers on the next verb, whichever verb that is.
|
package/docs/shared/logging.md
CHANGED
|
@@ -106,7 +106,9 @@ surface attaches it at its entry point.
|
|
|
106
106
|
rotation (the ruled retention, see below).
|
|
107
107
|
- **Stackable.** `createTee()` returns an independent tee; an attach captures the
|
|
108
108
|
CURRENT writers, so tees nest and each detach restores exactly what it found (LIFO).
|
|
109
|
-
The default export is the process-wide singleton, which is what a CLI verb wants
|
|
109
|
+
The default export is the process-wide singleton, which is what a CLI verb wants; two
|
|
110
|
+
attaches of different paths on the singleton stack the same way (a verb run inside
|
|
111
|
+
another verb's process), and its `detach()` pops the newest.
|
|
110
112
|
- **`createChildLog()` for spawned children.** A child's stdout/stderr never pass
|
|
111
113
|
through this process' writers; the caller mirrors each buffer to the terminal —
|
|
112
114
|
which the verb's own tee then catches, making the verb log a SUPERSET of the child
|
|
@@ -120,7 +122,7 @@ surface attaches it at its entry point.
|
|
|
120
122
|
|
|
121
123
|
## Where every log lives
|
|
122
124
|
|
|
123
|
-
`<targetRoot>` is a target dir in a brand (`targets/
|
|
125
|
+
`<targetRoot>` is a target dir in a brand (`targets/web`, `targets/backend`, …);
|
|
124
126
|
`<brandRoot>` is the brand monorepo root.
|
|
125
127
|
|
|
126
128
|
| Surface | File | What's in it |
|
|
@@ -129,23 +131,24 @@ surface attaches it at its entry point.
|
|
|
129
131
|
| `omega dev` (web) · `omega serve` / `omega emulator` (backend) · `npm start` (desktop, extension) | `<targetRoot>/logs/dev.log` | the whole dev run: boot, ports, watcher rebuilds, the crash — plus every child chunk the verb mirrored (see below) |
|
|
130
132
|
| `omega build` (web, backend) · production gulp build (desktop, extension) | `<targetRoot>/logs/build.log` | the whole production build |
|
|
131
133
|
| `omega test` | `<targetRoot>/logs/test.log` | suite names, pass/fail, harness boot lines |
|
|
134
|
+
| `omega deploy` (web, backend, extension, desktop) | `<targetRoot>/logs/deploy.log` | the whole deploy: the scaffold, the precheck and its refusals, the dispatch, then the followed run's job logs and its verdict ([#873](https://github.com/Omega-JS-Stack/omega/issues/873)) |
|
|
132
135
|
| **Backend children** — firebase's own processes, beside firebase-tools' debug logs. The verb mirrors every child chunk to its own terminal, so the `logs/<verb>.log` above is a SUPERSET of these; a child file is the child-ONLY view (and the one that `roll()`s mid-run) | | |
|
|
133
136
|
| the firebase emulator child | `<targetRoot>/dist/emulator.log` | emulator traffic: function invocations, Firestore/auth calls |
|
|
134
137
|
| the `firebase serve` child | `<targetRoot>/dist/dev.log` | serve output; rolls on each reload |
|
|
135
138
|
| the test runner child | `<targetRoot>/dist/test.log` | the runner's own output under `omega test` |
|
|
136
|
-
| `omega deploy` | `<targetRoot>/dist/deploy.log` | the deploy transcript |
|
|
139
|
+
| `omega deploy --direct` (the firebase child) | `<targetRoot>/dist/deploy.log` | the `firebase deploy` transcript (the verb's own record is `logs/deploy.log`, one row up) |
|
|
137
140
|
| `omega logs` | `<targetRoot>/dist/production.log` | the Cloud Logging tail |
|
|
138
141
|
| firebase-tools itself | `<targetRoot>/*-debug.log` | `firestore-debug.log`, `firebase-debug.log`, `ui-debug.log`, … — theirs, never swept by us |
|
|
139
142
|
| **Desktop extras** | | |
|
|
140
143
|
| the running app itself (main + preload + renderer converge) | `<targetRoot>/logs/runtime.log` (dev) · the OS log dir (packaged) | lifecycle, window and updater lines; kept across boots, rotating at 10 MB — `packages/desktop/docs/logging.md` |
|
|
141
144
|
| `npx omega logs [runtime\|dev\|build\|test]` (desktop's own verb — read, not write) | tails whichever of the four `<targetRoot>/logs/` files was named, `runtime` by default | the print/follow/open surface for all of the above; backend's `omega logs` is a different verb (the Cloud Logging tail, one row up) |
|
|
142
|
-
| `npm run release` | `<targetRoot>/logs/
|
|
145
|
+
| `npm run release` (the same dispatch `omega deploy` delegates to) | `<targetRoot>/logs/deploy.log` | the GH Actions release run, streamed locally: one name for every target's deploy ([#873](https://github.com/Omega-JS-Stack/omega/issues/873)), where this was `logs/ci.log` |
|
|
143
146
|
| Windows code-signing | `<targetRoot>/logs/signing.log` | JSONL signing events (local fallback; on CI it lands in the runner home) |
|
|
144
147
|
| **Brand root** — every verb tees to its OWN `logs/<verb>.log` ([#623](https://github.com/Omega-JS-Stack/omega/issues/623)), so one verb never truncates another's record. A FAN-OUT log holds the walk's own verdict — its header, its loud skips, its summary — because `runCommand` spawns each target with stdio inherit, so a target's output goes past the tee into that target's own log above | | |
|
|
145
148
|
| `omega manage` (the service walk) | `<brandRoot>/logs/manage.log` | the whole service walk |
|
|
146
149
|
| `omega dev` (the fan-out) | `<brandRoot>/logs/dev.log` | the boot walk, then every dev leg's prefixed output (consecutive duplicate lines collapse to one ` (repeated N×)` note) |
|
|
147
150
|
| `omega build` / `omega clean` (the fan-outs) | `<brandRoot>/logs/build.log` · `<brandRoot>/logs/clean.log` | the walk order, every loud skip, the per-target summary |
|
|
148
|
-
| `omega deploy` (the fan-out) | `<brandRoot>/logs/deploy.log` | the delivery lane, then which target published in which order and the summary
|
|
151
|
+
| `omega deploy` (the fan-out) | `<brandRoot>/logs/deploy.log` | the delivery lane, then which target published in which order and the summary. Every target additionally keeps its own `<targetRoot>/logs/deploy.log` ([#873](https://github.com/Omega-JS-Stack/omega/issues/873)), and the backend its firebase transcript `targets/backend/dist/deploy.log` |
|
|
149
152
|
| `omega update` (the fan-out) | `<brandRoot>/logs/update.log` | which target was checked and what it reported/applied |
|
|
150
153
|
| `omega test` (the fan-out) | `<brandRoot>/logs/test.log` | which target ran which scope, and the aggregate verdict |
|
|
151
154
|
| `omega pipeline` (the live full-cycle test) | `<brandRoot>/logs/pipeline.log` | the child invocation, the deploy/verify legs, the scorecard and the PASS/FAIL verdict |
|
|
@@ -195,7 +198,7 @@ emulator or watcher belongs to the user: never restart one, and never re-run a s
|
|
|
195
198
|
just to see output.
|
|
196
199
|
|
|
197
200
|
```bash
|
|
198
|
-
tail -50 targets/
|
|
201
|
+
tail -50 targets/web/logs/dev.log # is the dev server up, what did it last build
|
|
199
202
|
grep -i error targets/backend/dist/emulator.log # what the emulator actually served
|
|
200
203
|
grep '^FAIL' .temp/*/steps.log # which e2e step broke
|
|
201
204
|
tail -100 .temp/logs/test-packages.log # what the last lane printed
|
|
@@ -31,7 +31,7 @@ One block, `monitoring`, in omega.json5, with the monitor named as a KEY under `
|
|
|
31
31
|
presence IS the enable signal at runtime — there is no separate runtime `enabled` flag (the same
|
|
32
32
|
convention every other role section follows: a block's credentials are its switch); the role-level
|
|
33
33
|
`enabled: false` is the manager's skip switch for the provisioning service. Per-surface DSNs are
|
|
34
|
-
`targets.<
|
|
34
|
+
`targets.<name>.monitoring.providers.sentry.dsn` overrides.
|
|
35
35
|
|
|
36
36
|
```jsonc
|
|
37
37
|
monitoring: {
|
|
@@ -79,12 +79,19 @@ In the order they win:
|
|
|
79
79
|
| `OMEGA_SENTRY_ENABLED=false` | Kill switch. Nothing reports, ever. |
|
|
80
80
|
| `OMEGA_TEST_RUNNER` | A test run never pollutes a live project. |
|
|
81
81
|
| `OMEGA_SENTRY_FORCE=true` | Report from a non-production run (local proving). |
|
|
82
|
-
|
|
|
83
|
-
|
|
84
|
-
The production signal is the host's to supply
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
process
|
|
82
|
+
| the ONE environment | The default production signal, for a host that passes no runtime one. |
|
|
83
|
+
|
|
84
|
+
The production signal is the host's to supply, and the DEFAULT is the one environment every OMEGA
|
|
85
|
+
target answers from ([#817](https://github.com/Omega-JS-Stack/omega/issues/817)):
|
|
86
|
+
`@omega.js/config/environment`'s `isProduction()`, read off the host the gates were asked for
|
|
87
|
+
(`process.env.OMEGA_ENVIRONMENT` on Node, the host's baked `config.environment` in a browser-ish
|
|
88
|
+
context such as a renderer bundle). `OMEGA_BUILD_MODE` used to be that default, which made it a
|
|
89
|
+
FIFTH production signal with an opinion of its own: a build-mode run of a development artifact
|
|
90
|
+
reported as production, and a packaged production app whose lane did not carry the flag reported as
|
|
91
|
+
development. @omega.js/backend still passes its own answer in (`Manager.isProduction()`, env-derived
|
|
92
|
+
and stable for the life of the process), alongside its own `reportErrorsInDev` option, and a boolean
|
|
93
|
+
a host supplies always wins. A context that names no environment at all throws by name, the same way
|
|
94
|
+
every other read of the one environment does.
|
|
88
95
|
|
|
89
96
|
## Release tags
|
|
90
97
|
|
|
@@ -101,7 +108,7 @@ Each host supplies its own version identity:
|
|
|
101
108
|
| `@omega.js/backend` | the functions package version. The id is `brand.id`, falling back to the project id on a config missing one (which already warns at boot). |
|
|
102
109
|
| `@omega.js/desktop` (main + renderer) | `app.getVersion()` — the packaged app version, with `brand.id` read off the resolved config |
|
|
103
110
|
| `@omega.js/client` in `@omega.js/extension` | the extension target's package version, baked into the build blob as `config.version` |
|
|
104
|
-
| `@omega.js/client` in `@omega.js/web` | the website target's package version, read off the target root's package.json and
|
|
111
|
+
| `@omega.js/client` in `@omega.js/web` | the website target's package version, read off the target root's package.json and baked into the page's `OMEGA_BUILD_JSON.config` as `version` |
|
|
105
112
|
| `@omega.js/client` in the `@omega.js/desktop` renderer | the desktop target's package version, folded into `OMEGA_BUILD_JSON.config` at bake time (the renderer only ever sees `buildJson.config`) |
|
|
106
113
|
|
|
107
114
|
The client reads `config.version` and falls back to `config.buildTime`. Every host above bakes a
|
|
@@ -140,13 +147,20 @@ config: a page never opts its own credentials back into an event ([#661](https:/
|
|
|
140
147
|
|
|
141
148
|
## How the config reaches a browser
|
|
142
149
|
|
|
143
|
-
The client reads a `sentry: { enabled, config }` namespace on its init blob, and
|
|
144
|
-
|
|
150
|
+
The client reads a `sentry: { enabled, config }` namespace on its init blob, and it maps that
|
|
151
|
+
namespace from `monitoring.providers.sentry` ITSELF, once, for every framework
|
|
152
|
+
([#894](https://github.com/Omega-JS-Stack/omega/issues/894)): each browser surface bakes the
|
|
153
|
+
canonical section into `OMEGA_BUILD_JSON.config` and `_canonicalConfiguration()` in
|
|
154
|
+
`packages/client/src/index.js` turns a DSN's presence into the switch. That home outranks a
|
|
155
|
+
stale `client.sentry` blob, which keeps reporting until a brand migrates
|
|
156
|
+
([#485](https://github.com/Omega-JS-Stack/omega/issues/485)); with no canonical DSN the off
|
|
157
|
+
state rides first, so the legacy blob still decides.
|
|
145
158
|
|
|
146
|
-
| Framework | Where |
|
|
159
|
+
| Framework | Where the section is baked |
|
|
147
160
|
|---|---|
|
|
148
|
-
| `@omega.js/web` | the
|
|
149
|
-
| `@omega.js/extension` | `src/gulp/tasks/bundle.js` (`
|
|
161
|
+
| `@omega.js/web` | the engine's per-build snapshot, written as `<outDir>/build.js` (#743) |
|
|
162
|
+
| `@omega.js/extension` | `src/gulp/tasks/bundle.js` (`composeBuildJson`, written as `dist/build.js`) |
|
|
163
|
+
| `@omega.js/desktop` | `src/gulp/tasks/bundle.js` (`composeClientBuildJson`, written as `dist/build.js` for the renderer) |
|
|
150
164
|
|
|
151
165
|
The client's `sentry.config` is the PROVIDER block, flat — nothing role-level ever rides into
|
|
152
166
|
`Sentry.init`. Node/Electron hosts pass the whole `monitoring` section instead and core's
|
|
@@ -121,8 +121,8 @@ phone home).
|
|
|
121
121
|
|---|---|---|---|
|
|
122
122
|
| web | `omega build` (the production build — on the runner for a deploy, locally for a local one) | `site.license`, a build fact beside `site.pricing`/`site.brandTokens` | the footer's "Powered by omegajs.dev" block renders only while `site.license.attribution == 'shown'` (themes/base `_includes/frontend/sections/footer.html`) |
|
|
123
123
|
| backend | `omega deploy`, before the stage — the CLI reads the key from the .env cascade in its own process | `OMEGA_LICENSE_STATUS` in the composed `dist/.env` (the one COMPUTED key there; the KEY itself never rides the upload) | `libraries/payment/license.js` refuses Stripe/PayPal/Chargebee `init()` on `keyless`. The `test` provider is never gated, and an ABSENT status — every local lane, the emulator, a test — behaves exactly as before |
|
|
124
|
-
| desktop | the bundle task, production builds only | `OMEGA_BUILD_JSON.license` (outside `config`, the
|
|
125
|
-
| extension | the bundle task, production builds only (once per build
|
|
124
|
+
| desktop | the bundle task, production builds only | `OMEGA_BUILD_JSON.license` (outside `config`, in the bundles' define and in the renderer's `dist/build.js`) | nothing at runtime: the artifact records what it was packaged as. Neither target has an attribution surface today, and their payments ride the backend's gate |
|
|
125
|
+
| extension | the bundle task, production builds only (once per build: the one snapshot every browser target then copies) | `OMEGA_BUILD_JSON.license` in the artifact's `build.js`, likewise outside `config` | as desktop |
|
|
126
126
|
|
|
127
127
|
**Honesty system** (spec call 6): plain readable checks, no obfuscation and no artifact
|
|
128
128
|
signing. The legal backing is the Elastic License 2.0 below, whose terms forbid
|
|
@@ -163,7 +163,7 @@ circumventing license-key functionality and removing notices.
|
|
|
163
163
|
3. **Verify from the outside**: in an empty temp dir, `npm install @omega.js/web`
|
|
164
164
|
(and one more, e.g. manager) — install + `require.resolve` must succeed with no
|
|
165
165
|
overrides. That is the moment the untested-lane risk is retired.
|
|
166
|
-
4. **Flip omega-
|
|
166
|
+
4. **Flip the real brand (omega-omega) to registry specs**: from any TARGET root (`targets/web`;
|
|
167
167
|
the manager has no `i` verb), `npx omega i live` — tree-wide `file:` → the EXACT
|
|
168
168
|
family pin + one registry install (`restoreRegistrySpecs` writes the linked copy's version with no
|
|
169
169
|
caret, because the family is lockstep; `omega i local` is the way back for
|
package/docs/shared/rulings.md
CHANGED
|
@@ -25,10 +25,10 @@ Ian's durable rulings, migrated verbatim from PROGRESS.md's Rulings lane when th
|
|
|
25
25
|
- Standing: checkpoint discipline — survey → design → implement → tests → sandbox/fixture proof → docs → commit; live checks never touch real ITW resources outside sanctioned paths
|
|
26
26
|
- Ian 2026-07-30: uniformity — commands/surfaces of the same TYPE act the SAME; no split defaults within one family (the CLI read/write emulator split was the offense: every backend CLI subcommand now defaults to the emulator, `--production` the only path to live)
|
|
27
27
|
- Ian 2026-07-30: NO legacy accommodations in the new system — no code path accepting a superseded form; breaking changes get DOCUMENTED (register: #148) and migrated once, manually (playbook: #149); the config-convert input lane is the one sanctioned legacy-reading exception
|
|
28
|
-
- Ian 2026-07-30: company membership is
|
|
28
|
+
- Ian 2026-07-30: company membership is a POINTER, never the directory tree: brands never physically nest inside a company folder, and anything resolving the company follows the pointer (SUPERSEDED in mechanism by #677, 2026-09-12: the pointer is the config key `company: { id }`, resolved through the machine registry, and the `.omega/company.json` stamp is retired; the rule itself stands)
|
|
29
29
|
- Ian 2026-08-06: harmonize at BUILD time, never in a later pass — when a mechanism lands in one framework, its shared home (devkit) and the mirroring evaluation happen in the same work item; "wait for the harmonization pass" is not an accepted answer (first application: the #200 captured-read helper lifted to devkit pre-ship)
|
|
30
30
|
- Ian 2026-08-20: migrations converge by SHAPE, not by version steps — each fix detects its legacy pattern in the doc itself, converged docs are proven no-ops, still-invalid docs surface loudly in the audit; every future doc reshape adds its convergent fix to the migrations pipeline in the SAME work item (register: docs/shared/breaking-changes.md)
|
|
31
31
|
- Ian 2026-08-20: writing real data is OPT-IN for one-off scripts/processes — any standalone script that mutates live data (Firestore docs, mailing lists, provider accounts) previews by default and writes only under an explicit `--execute`; the manage/reconciliation services (own `--dry-run` + convergence) and scripts that only write tracked files (git diff is the review) are out of scope; template: the migrations service (#394)
|
|
32
32
|
|
|
33
|
-
- Ian 2026-09-03: `--target=<
|
|
33
|
+
- Ian 2026-09-03: `--target=<name>[,<name>]` is the ONE target picker on every brand-root fan-out verb (test, deploy, build, clean, dev, update); `--only`/`--except` are retired, not aliased: `--only` collided with Firebase's own `firebase deploy --only hosting` (register: https://github.com/Omega-JS-Stack/omega/issues/780)
|
|
34
34
|
- Ian 2026-09-03: an ORPHANED process of the emulator family (parent gone, this user's uid, a strict command-shape match) is NOBODY's and every emulator boot reaps it, whatever project it names, with no config and no warning-only mode. The family's shapes are named once, where the reap is described: [backend/index.md](../backend/index.md). Supersedes the #293 line that another brand's orphans stay; the #293 lesson survives as the strict family match replacing the loose name regex (register: https://github.com/Omega-JS-Stack/omega/issues/781)
|
package/docs/shared/testing.md
CHANGED
|
@@ -35,7 +35,7 @@ Layer names inside a suite are platform-native on purpose: desktop's `main`/`ren
|
|
|
35
35
|
| 2d — Desktop auth e2e | The **desktop ↔ backend auth boundary in a REAL Electron app** ([scripts/e2e-desktop-auth.js](../../scripts/e2e-desktop-auth.js)): a consumer app staged from @omega.js/desktop's bundled fixture is built and booted by the real boot runner, then a SECOND Electron instance launches carrying `<brand.id>://auth/token?authToken=…` — the OS single-instance lock forwards that argv to the running app, whose real `second-instance` → deep-link → client-bridge chain signs it in. Both sides of the process boundary are asserted: main's client-bridge on the emulator user, and the renderer's own @omega.js/client Firebase on the same uid (it learned only through the real `desktop:auth:sign-in-with-token` broadcast). Offline by construction — a testing run connects main's auth to the emulator and the staged config points the renderer's client at the same ports | `npm run test:e2e-desktop` at the root | Every checkpoint touching desktop auth, the deep-link routes, or the `/user/token` wire; `OMEGA_SKIP_E2E=1` to skip, and no electron binary (or no built @omega.js/desktop `dist/`) → SKIPPED (exit 0, reason printed) |
|
|
36
36
|
| 2e — User flows e2e (real browser) | The **CRUCIAL user flows through the actual UI** ([scripts/e2e-flows.js](../../scripts/e2e-flows.js)): headless Chromium against the playground's full emulator suite (seeded personas) plus the REAL `omega dev` — the auth-emulator proxy the provider redirect leg needs lives only there. Five areas — four per spec item of [#155](https://github.com/Omega-JS-Stack/omega/issues/155), plus the billing journeys of [#209](https://github.com/Omega-JS-Stack/omega/issues/209): **auth** (the Google picker's real redirect leg on /signup and again with `authReturnUrl`, `?authSignout=true` + the account page's kick-out, the empty-return loud failure, and the password FORMS — /signin, /signup, /reset), **checkout** (bound state, armed payment buttons, a `_dev_cardProvider=test` payment landing on /payment/confirmation with its order), **verts** (an unfilled slot laddering no-fill → promo, the card content-sized under its slot ceiling, the UTM set on the promo link and the click forwarded out of the frame), **account** (a signed-in policy page rendering the persona's account state from the emulator), **billing journeys** (one paid lifecycle per DEDICATED seeded persona — upgrade, cancel, a declined renewal, a trial converting — each verdict read off the RENDERED account page; the two end states no UI can reach post a hand-built test webhook at the backend exactly as a provider would). **Hard precondition**: `OMEGA_WEBHOOK_KEY` must be in the playground backend's `.env` cascade — the webhook route authenticates on it, and the lane throws `OMEGA_WEBHOOK_KEY is missing from the playground backend's .env cascade` at startup rather than running a crippled pass. Owns its stack: it HOLDS every classic port so both children bump onto fresh ones, so it never disturbs a live dev boot | `npm run test:flows` at the root | Every checkpoint touching auth pages, checkout, the vert ladder, the account page, or the billing lifecycle; `OMEGA_SKIP_E2E=1` to skip, and no puppeteer Chrome → SKIPPED (exit 0, reason printed) |
|
|
37
37
|
| 2.5 — Wizard journey (outside-monorepo consumer) | The FULL consumer story in a temp brand born OUTSIDE the monorepo: real onboard wizard (flags) → `i local` tree link → `omega dev` boot + branded-homepage probe → headless creds-scrubbed manage (update must build every target) | `npm run test:journey` at the root (also the tail of root `npm test`) | The full sequence, and any change to onboard/linking/boot plumbing |
|
|
38
|
-
| 3 — Playground (live rehearsal) | The 24-service manage pipeline against REAL cloud (Firebase, Cloudflare, SendGrid, …) | `npm run pipeline` in `brands/omega
|
|
38
|
+
| 3 — Playground (live rehearsal) | The 24-service manage pipeline against REAL cloud (Firebase, Cloudflare, SendGrid, …) | `npm run pipeline` in `brands/playground-omega` | SPARINGLY — Ian-authorized (real infra, real cost) |
|
|
39
39
|
| C — Consumer brand e2e | Every OMEGA brand's OWN browser lane, `<brandRoot>/test/e2e/run.js` on [@omega.js/devkit/test/e2e-harness](../../packages/devkit/src/test/e2e-harness.js): the brand's real pages against its real local stack (the backend emulator with its seeded personas plus the real `omega dev`), on allocator ports beside a live dev boot. The brand-root walk, the `--target` picker and the fanned-out flags: [../manager/brand.md](../manager/brand.md) ([#775](https://github.com/Omega-JS-Stack/omega/issues/775)) | `npx omega test` at the brand root, after every target | Every brand checkpoint. Tier 2a IS this lane, run by the sandbox brand |
|
|
40
40
|
|
|
41
41
|
**Opt-in lanes are not a tier and never join a run by accident.** A lane is a set of suites that exist only for the real external thing — credentials, the network, a vendor CLI — plus a GATE deciding whether they may run at all. It is reached exactly one way, `npx omega test --lane=<name>`, and a gate that cannot be satisfied prints ONE skip line and exits clean; the lane's own `test/<lane>/` directory is excluded from discovery unless its gate opened it, so no default run, no CI tier and no path filter can pull it in. Today there is one: backend's `--lane=stripe-live`, which forwards REAL Stripe test-mode webhooks into the local emulator and refuses to open on anything that is not an `sk_test_` secret ([packages/backend/docs/test-framework.md](../../packages/backend/docs/test-framework.md#opt-in-lanes---lane)). Distinct from `--extended`, which is a *mode* letting the same suites make real calls.
|
package/docs/shared/theming.md
CHANGED
|
@@ -77,7 +77,7 @@ platform rail).
|
|
|
77
77
|
`omega.json5 → brand.color` is an optional hex string (`#RGB` / `#RRGGBB`,
|
|
78
78
|
schema-validated since [#272](https://github.com/Omega-JS-Stack/omega/issues/272);
|
|
79
79
|
unset leaves the token sheet's neutral placeholder standing) and it drives
|
|
80
|
-
`composeBrandTokens()` (`packages/
|
|
80
|
+
`composeBrandTokens()` (`packages/devkit/src/brand-tokens.js`): a light ramp plus a **dark-mode variant**
|
|
81
81
|
(darker brands lift into a legible lightness band for the charcoal ground;
|
|
82
82
|
already-light brands pass through). `core/_includes/core/head.html` emits both
|
|
83
83
|
as inline `:root` blocks AFTER the css bundles — same three-stamp plumbing as
|
|
@@ -86,6 +86,23 @@ the token sheet — so the ramp wins the cascade everywhere, including
|
|
|
86
86
|
`.progress-bar`, and `.text-primary`/`.bg-primary` (classy re-points those at
|
|
87
87
|
the tokens).
|
|
88
88
|
|
|
89
|
+
ONE hex, three surfaces ([#912](https://github.com/Omega-JS-Stack/omega/issues/912)).
|
|
90
|
+
Desktop and the extension have no `<head>` of their own to inline into, so their
|
|
91
|
+
sass tasks write the SAME ramp to a generated partial before every compile:
|
|
92
|
+
`<dist>/assets/scss/_brand.scss` on desktop, `<dist>/assets/css/_brand.scss` on
|
|
93
|
+
the extension, both rendered by `renderBrandScss()` beside the ramp math. The
|
|
94
|
+
partial carries `$primary` (the compile-time accent Bootstrap's color ramp
|
|
95
|
+
derives from) plus a `ramp` mixin holding the runtime `--omega-accent` family,
|
|
96
|
+
and the scaffold's `main.scss` reads both: `@use 'brand'` above the framework
|
|
97
|
+
import for the variable, `@include brand.ramp;` below it for the css. The mixin
|
|
98
|
+
is why the include sits below: a used module's css is emitted at its LOAD
|
|
99
|
+
position, which is ahead of the token sheet and theme it has to beat, so a
|
|
100
|
+
root-level rule in the partial would lose to the very placeholders it replaces.
|
|
101
|
+
A brand that WANTS a different accent from `brand.color` puts a literal back in
|
|
102
|
+
the `with (...)` block, in place of `brand.$primary`. No `brand.color` at all,
|
|
103
|
+
and the renderer's own fallback (`#2563EB`, the hex the classy theme declares
|
|
104
|
+
with `!default`) is what compiles.
|
|
105
|
+
|
|
89
106
|
## Consumer customization (tier 1 — main.scss)
|
|
90
107
|
|
|
91
108
|
- **Discovery**: `omega customize --list` prints the layered override map —
|
|
@@ -594,6 +611,14 @@ the page no longer carries,
|
|
|
594
611
|
[#740](https://github.com/Omega-JS-Stack/omega/issues/740)), and
|
|
595
612
|
`theme.topbar.enabled: false` drops the topbar.
|
|
596
613
|
|
|
614
|
+
A link's `icon` carries the FULL Font Awesome class string
|
|
615
|
+
([#903](https://github.com/Omega-JS-Stack/omega/issues/903)): `icon: 'fa-brands
|
|
616
|
+
fa-github'`, rendered exactly as authored, so the whole chrome spells one key one
|
|
617
|
+
way, the nav, the sidebar, the topbar (its notifications bell included), the page
|
|
618
|
+
header (its title's `theme.header.title.icon` included), the account dropdown,
|
|
619
|
+
the account section header and the footer, and any family the set carries is
|
|
620
|
+
reachable. The mechanism behind the markup: [icons.md](icons.md).
|
|
621
|
+
|
|
597
622
|
## Stable-API line (don't churn once consumers exist)
|
|
598
623
|
|
|
599
624
|
Token NAMES · `_config.scss` variable names · `.omega-shell` markup contract
|
|
@@ -16,7 +16,7 @@ translation: {
|
|
|
16
16
|
languages: ['es', 'fr'],// target codes — EMPTY/ABSENT = translation off
|
|
17
17
|
providers: { claude: {} },// the engine is a KEY (#425): claude | chatgpt. Absent block = claude
|
|
18
18
|
model: null, // optional override for the chosen engine (claude → 'sonnet' alias, chatgpt → 'gpt-5.4-nano')
|
|
19
|
-
|
|
19
|
+
include: ['**', '!blog/**'], // web only: globs over BRAND page routes, `!` negates; this is the framework default, a brand list replaces it (#858; the framework's own default pages are excluded on their own, #605)
|
|
20
20
|
}
|
|
21
21
|
```
|
|
22
22
|
|
|
@@ -112,7 +112,13 @@ string. Committed to git — that's the whole point:
|
|
|
112
112
|
re-translation. Everything else is a cache hit (zero provider calls).
|
|
113
113
|
- **Survives clones/CI**: a warm cache builds a fully-translated site with NO
|
|
114
114
|
AI credentials (kills the BXM parked finding where fresh clones burned live
|
|
115
|
-
Claude calls).
|
|
115
|
+
Claude calls). No AI key is delivered to CI by default
|
|
116
|
+
([#819](https://github.com/Omega-JS-Stack/omega/issues/819), Ian 2026-09-13):
|
|
117
|
+
translation runs on the developer's machine and a runner reads the committed
|
|
118
|
+
cache, which is why `OPENAI_API_KEY` is an `env` delivery on every target that
|
|
119
|
+
names it and no workflow carries a line for it
|
|
120
|
+
([#905](https://github.com/Omega-JS-Stack/omega/issues/905) owns the one
|
|
121
|
+
system, cloud translation included).
|
|
116
122
|
- **Human-overridable**: hand-edit a translation VALUE in the cache file and
|
|
117
123
|
it sticks for as long as the source is unchanged (the value is the
|
|
118
124
|
translation; the key only changes when the SOURCE changes).
|
|
@@ -172,10 +178,44 @@ The list is DERIVED from the packaged defaults tree
|
|
|
172
178
|
never typed out, so a default page that moves or arrives cannot drift out of it,
|
|
173
179
|
and each excluded route guards its subtree too. On top of that: socials
|
|
174
180
|
redirects (config `socials` keys), the `admin`/`test`/`team`/`updates` folders,
|
|
175
|
-
every known language-code folder
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
181
|
+
every known language-code folder.
|
|
182
|
+
|
|
183
|
+
**Which of the BRAND's own pages are translated is `translation.include`**
|
|
184
|
+
([#858](https://github.com/Omega-JS-Stack/omega/issues/858), Ian 2026-09-13,
|
|
185
|
+
the same-name ruling): a list of route GLOBS read like a `.gitignore`, where
|
|
186
|
+
`!` negates and the LAST pattern that matches a route decides it. A route no
|
|
187
|
+
pattern matches is not translated, so an empty list translates nothing. A
|
|
188
|
+
folder pattern covers the folder itself as well as its contents, so
|
|
189
|
+
`!blog/**` takes `/blog` out along with every post under it. The framework
|
|
190
|
+
default lives in the DEFAULTS layer of the merge chain (the schema's own
|
|
191
|
+
`default:`, resolution-only so no brand file carries a copy of it):
|
|
192
|
+
|
|
193
|
+
```json5
|
|
194
|
+
translation: { include: ['**', '!blog/**'] } // the default: the whole site except the blog
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
A brand list **REPLACES** it outright rather than adding to it (arrays replace
|
|
198
|
+
at every level of the merge chain), so a brand that writes `['docs/**']` gets
|
|
199
|
+
docs and nothing else. It is for the brand's own pages only: the framework's
|
|
200
|
+
derived exclusions above are not in its hands, and a brand that names `signin`
|
|
201
|
+
or `account` is naming something already skipped.
|
|
202
|
+
|
|
203
|
+
**A page overrides the list for itself**, under the same key name one level
|
|
204
|
+
down: `translation: { include: true }` in its frontmatter translates a page the
|
|
205
|
+
list left out, `false` takes one out that the list would have covered. The
|
|
206
|
+
build stamps that answer on `<html data-omega-translate>` (the seam #355's base
|
|
207
|
+
path already uses), because the pass runs post-build over `dist/` and
|
|
208
|
+
`omega translate` runs with no build in reach. `include` is the only key a page
|
|
209
|
+
may write under a bare `translation:`; anything else is a config section
|
|
210
|
+
restated bare and fails the build.
|
|
211
|
+
|
|
212
|
+
**`translation.exclude` is RETIRED** with it. There is no dual-read: a config
|
|
213
|
+
still carrying it fails validation naming its replacement, and
|
|
214
|
+
`omega migrate` at the brand root CONVERTS the list (`exclude: ['docs']`
|
|
215
|
+
becomes `include: ['**', '!docs']`, which keeps translating exactly what the
|
|
216
|
+
brand was translating before) and deletes the old key in the same run.
|
|
217
|
+
|
|
218
|
+
Element opt-out: `data-omega-no-translate`, unchanged. Collector fixes vs UJM:
|
|
179
219
|
`aria-describedby`/`aria-labelledby` are NOT collected (ID refs), `value`
|
|
180
220
|
only on button-type inputs (hidden-input tokens stay intact).
|
|
181
221
|
|
|
@@ -213,7 +253,9 @@ alike, since it never touches a provider:
|
|
|
213
253
|
`terms`/`privacy`/`cookies` are deliberately not generated.
|
|
214
254
|
- A configured language the package does not ship is one log line for the whole
|
|
215
255
|
run, not an error — those routes stay in the source language.
|
|
216
|
-
- A
|
|
256
|
+
- A brand's `translation.include` list never touches the framework's default
|
|
257
|
+
pages: it scopes the brand's OWN pages, and the framework's chrome is
|
|
258
|
+
translated once, on the framework side.
|
|
217
259
|
|
|
218
260
|
**Shipped set: `es`, `fa`.** Regenerating, or extending the set, is one command
|
|
219
261
|
in `packages/web` (the ONLY place the framework's own pages ever reach a
|
package/docs/shared/updates.md
CHANGED
|
@@ -54,7 +54,7 @@ the same exact pin ([local-dev.md](local-dev.md) § API surface).
|
|
|
54
54
|
|
|
55
55
|
## Brand root
|
|
56
56
|
|
|
57
|
-
`omega update` at a brand root (manager) fans out over the brand's targets
|
|
57
|
+
`omega update` at a brand root (manager) fans out over the brand's targets, cp251's deploy fan-out shape: same target discovery, same `--target=<name>[,<name>]` picker ([#780](https://github.com/Omega-JS-Stack/omega/issues/780)), every other flag forwarded verbatim, each target answering through its own framework's `update` verb. Unlike deploy, targets are **independent**: one failing target never blocks the rest (any failure still exits 1). The brand-root shell `package.json` rides the walk as its LAST leg ([#794](https://github.com/Omega-JS-Stack/omega/issues/794)), scoped to the one `@omega.js/*` dependency it carries (`@omega.js/manager`) and run in-process through the same devkit implementation (there is no framework bin at the root to spawn; it would dispatch straight back into this command). A brand's own root tooling is never touched, and a picked run (`--target=`) skips the root, because the picker names targets. Without that leg a manager-behind brand could never heal itself: the boot check would refuse every verb, and the fix it names would move every target except the one that was wrong.
|
|
58
58
|
|
|
59
59
|
## Testing
|
|
60
60
|
|