@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
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* max: Number, // only checked when value present + number
|
|
12
12
|
* match: RegExp, // only checked when value present + string
|
|
13
13
|
* enum: [...], // only checked when value present
|
|
14
|
+
* itemEnum: [...], // an ARRAY value's allowed members
|
|
14
15
|
* default: <value>, // the framework answer — see below
|
|
15
16
|
* description: 'What the field drives.',
|
|
16
17
|
* }
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
* (#527 — the adsense `client` id is the ONE switch, and a materialized
|
|
48
49
|
* advertising block would switch the web build's automatic vert placements on
|
|
49
50
|
* for a brand that configured none). Blocks whose services gate on `enabled`
|
|
50
|
-
* instead
|
|
51
|
+
* instead (cloudflare, searchConsole, slapform, chatsy, replyify)
|
|
51
52
|
* DO carry the default that states the polarity (`enabled: true`, read
|
|
52
53
|
* `!== false`), because presence there picks nothing. Role-level switches
|
|
53
54
|
* beside any providers block (`monitoring.enabled`,
|
|
@@ -73,31 +74,44 @@
|
|
|
73
74
|
// winback.js re-exports it, so every existing import keeps working.
|
|
74
75
|
const WINBACK_DURATIONS = ['once', 'forever'];
|
|
75
76
|
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
77
|
+
// Where a brand hosts its SOURCE, and where a web target is SERVED from
|
|
78
|
+
// ([#883](https://github.com/Omega-JS-Stack/omega/issues/883)). One value each
|
|
79
|
+
// today: a second provider is a new entry here plus that provider's own helper,
|
|
80
|
+
// never a reshape of the config. They live HERE, with the rules that enumerate
|
|
81
|
+
// them, so repo.js can derive without a require cycle (the WINBACK_DURATIONS
|
|
82
|
+
// pattern above); repo.js re-exports both, and every reader takes them there.
|
|
83
|
+
const REPO_PROVIDERS = ['github'];
|
|
84
|
+
const HOSTING_PROVIDERS = ['github'];
|
|
85
|
+
|
|
86
|
+
// The category slugs addons.mozilla.org accepts on a listing (its live set on
|
|
87
|
+
// 2026-09-11). AMO has no utilities or productivity slug, so the framework
|
|
88
|
+
// default is `alerts-updates`, the most generic one that is not `other`
|
|
89
|
+
// ([#884](https://github.com/Omega-JS-Stack/omega/issues/884)). It lives HERE,
|
|
90
|
+
// with the rule that enumerates it (the WINBACK_DURATIONS pattern above), and
|
|
91
|
+
// @omega.js/extension's Firefox lane takes the SAME list from this package when
|
|
92
|
+
// it writes a first publish's `--amo-metadata` file: a slug AMO does not know
|
|
93
|
+
// fails in the build instead of at the store.
|
|
94
|
+
const AMO_CATEGORIES = ['alerts-updates', 'appearance', 'bookmarks', 'download-management', 'feeds-news-blogging', 'games-entertainment', 'language-support', 'photos-music-videos', 'privacy-security', 'search-tools', 'shopping', 'social-communication', 'tabs', 'web-development', 'other'];
|
|
95
|
+
|
|
96
|
+
// Canonical target TYPES: the frameworks a `targets.<name>.type` may name
|
|
97
|
+
// (#886). Key presence in a config's `targets` object = "this brand enables a
|
|
98
|
+
// target by that name" (absorbs the legacy brand-config targets ARRAY).
|
|
79
99
|
const TARGETS = ['web', 'backend', 'desktop', 'extension', 'mobile'];
|
|
80
100
|
|
|
81
101
|
// A brand also runs targets no framework owns — a Render API, a worker, a
|
|
82
|
-
// script (#603). Those
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
// manager is the one that runs them (docs/manager/index.md).
|
|
102
|
+
// script (#603). Those declare `type: 'custom'` like any other target
|
|
103
|
+
// (`targets.api: { type: 'custom' }`), and their verbs come entirely from the
|
|
104
|
+
// target's own package.json scripts; the manager is the one that runs them
|
|
105
|
+
// (docs/manager/index.md).
|
|
87
106
|
const CUSTOM_TARGET_TYPE = 'custom';
|
|
88
107
|
|
|
89
108
|
/**
|
|
90
|
-
* Whether a `targets.<
|
|
91
|
-
* (multi-instance) form is custom only when EVERY instance says so — a mixed
|
|
92
|
-
* array has no honest reading, so the validator fails it.
|
|
109
|
+
* Whether a `targets.<name>` entry declares itself custom.
|
|
93
110
|
*
|
|
94
|
-
* @param {object|
|
|
111
|
+
* @param {object|null|undefined} entry - The raw targets.<name> value.
|
|
95
112
|
* @returns {boolean} True when the entry is a custom target.
|
|
96
113
|
*/
|
|
97
114
|
function isCustomTargetEntry(entry) {
|
|
98
|
-
if (Array.isArray(entry)) {
|
|
99
|
-
return entry.length > 0 && entry.every((instance) => instance?.type === CUSTOM_TARGET_TYPE);
|
|
100
|
-
}
|
|
101
115
|
return entry?.type === CUSTOM_TARGET_TYPE;
|
|
102
116
|
}
|
|
103
117
|
|
|
@@ -125,25 +139,90 @@ function backendProjectType(entry) {
|
|
|
125
139
|
return entry?.projectType === 'custom' ? 'custom' : 'firebase';
|
|
126
140
|
}
|
|
127
141
|
|
|
142
|
+
// The page routes a brand translates when it says nothing
|
|
143
|
+
// ([#858](https://github.com/Omega-JS-Stack/omega/issues/858), Ian 2026-09-13):
|
|
144
|
+
// the whole site except the blog. Named here, beside the rule that defaults to
|
|
145
|
+
// it, because the web build's matcher reads the same constant rather than
|
|
146
|
+
// keeping a second copy of the framework's answer.
|
|
147
|
+
const TRANSLATION_INCLUDE_DEFAULT = ['**', '!blog/**'];
|
|
148
|
+
|
|
128
149
|
// The machine-owned top-level sections identical in every omega.json5 —
|
|
129
150
|
// omega-manager's disperse enumerates THIS list instead of hardcoding
|
|
130
151
|
// per-target mapping blocks. (`targets` itself is the scoping key, not a
|
|
131
152
|
// shared section; `theme` is project-owned but shared-shaped.)
|
|
132
153
|
const SHARED_SECTIONS = ['brand', 'cloud', 'repo', 'edge', 'captcha', 'search', 'forms', 'inbound', 'analytics', 'advertising', 'features', 'payment', 'monitoring', 'connections', 'theme', 'translation'];
|
|
133
154
|
|
|
155
|
+
// Which config sections a BROWSER may see, and how much of each: the ONE
|
|
156
|
+
// declaration behind clientConfig() ([#894](https://github.com/Omega-JS-Stack/omega/issues/894)).
|
|
157
|
+
// Every browser surface bakes its artifact through that function (web's page
|
|
158
|
+
// chrome, desktop's renderer bundle, every extension bundle), so a value goes
|
|
159
|
+
// public by gaining a row HERE, never by a per-framework list. The flag is
|
|
160
|
+
// per SECTION, at the granularity the section's public half needs:
|
|
161
|
+
//
|
|
162
|
+
// `client: true` the whole section rides (its keys are public by design:
|
|
163
|
+
// secrets never live in omega.json5, and the validator
|
|
164
|
+
// hard-fails a secret-shaped key anywhere in the file)
|
|
165
|
+
// `client: [paths]` only these sub-paths ride, for a section whose other
|
|
166
|
+
// keys are provisioning-only (nothing secret, nothing a
|
|
167
|
+
// runtime reads)
|
|
168
|
+
// no row the browser never sees it: cloud/GCP provisioning,
|
|
169
|
+
// the account admins, the repo and edge plumbing, every
|
|
170
|
+
// build-only section (platforms, purgecss, collections…)
|
|
171
|
+
//
|
|
172
|
+
// A new section defaults to INVISIBLE, which fails as a missing feature rather
|
|
173
|
+
// than a leak. The build FACTS a surface composes beside these sections
|
|
174
|
+
// (runtime, version, dev, …) are client-config.js's own list.
|
|
175
|
+
const CLIENT_SECTIONS = {
|
|
176
|
+
advertising: true,
|
|
177
|
+
analytics: true,
|
|
178
|
+
app: true,
|
|
179
|
+
brand: true,
|
|
180
|
+
captcha: true,
|
|
181
|
+
client: true,
|
|
182
|
+
// The Firebase WEB config is public by design (the api key included) and is
|
|
183
|
+
// what boots @omega.js/client on all three surfaces; the GCP account facts
|
|
184
|
+
// beside it (billingAccount, organizationId, apiSubdomain) are provisioning.
|
|
185
|
+
cloud: ['config', 'messaging.vapidKey'],
|
|
186
|
+
company: true,
|
|
187
|
+
connections: true,
|
|
188
|
+
features: true,
|
|
189
|
+
// The contact page's endpoint, and nothing else the slapform service keeps
|
|
190
|
+
// beside it (template ids, plan, update flags).
|
|
191
|
+
forms: ['providers.slapform.formId'],
|
|
192
|
+
// The chat widget's agent and its presentation, same rule.
|
|
193
|
+
inbound: ['chat.providers.chatsy.enabled', 'chat.providers.chatsy.agentId', 'chat.providers.chatsy.settings'],
|
|
194
|
+
listings: true,
|
|
195
|
+
monitoring: true,
|
|
196
|
+
payment: true,
|
|
197
|
+
theme: true,
|
|
198
|
+
};
|
|
199
|
+
|
|
134
200
|
// brand.id's slug rule — the ONE home for the pattern. Anything that gates a
|
|
135
201
|
// caller-supplied brand id (the backend verts routes' normalizeBrandId) imports
|
|
136
202
|
// this instead of copying the regex.
|
|
137
203
|
const BRAND_ID_PATTERN = /^[a-z][a-z0-9+\-.]*$/;
|
|
138
204
|
|
|
139
205
|
const SHARED_SCHEMA = [
|
|
140
|
-
// ── the
|
|
206
|
+
// ── the target's own url ─────────────────────────────────────────────────
|
|
141
207
|
{
|
|
142
208
|
path: 'url',
|
|
143
209
|
type: 'string',
|
|
144
210
|
required: false,
|
|
145
211
|
match: /^https?:\/\//,
|
|
146
|
-
description: "This
|
|
212
|
+
description: "This TARGET's own public URL, and the one key a target entry may set at the top level. A target whose name is not its type derives it from the name (`admin: { type: 'web' }` → https://admin.<host of brand.url>, #588/#886; docs/shared/config.md → Targets); an entry's own `url` overrides it for a custom host. `brand.url` stays the BRAND's url, which is what brand-level facts (authDomain, the persona domain) read.",
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
// ── the target's own type (#886) ─────────────────────────────────────────
|
|
216
|
+
// Declared ONCE, here: every target entry carries it, whatever its
|
|
217
|
+
// framework, and a copy per TARGET_SCHEMAS would be four copies of one
|
|
218
|
+
// contract ([#911](https://github.com/Omega-JS-Stack/omega/issues/911)). It
|
|
219
|
+
// is target-entry machinery like `url`, so it names no config SECTION.
|
|
220
|
+
{
|
|
221
|
+
path: 'type',
|
|
222
|
+
type: 'string',
|
|
223
|
+
required: false,
|
|
224
|
+
enum: [...TARGETS, CUSTOM_TARGET_TYPE],
|
|
225
|
+
description: "The FRAMEWORK that runs this target (#886), or `custom` for a target no framework owns. Key presence in `targets` enables a target by NAME, and this is what says which code runs there, so a target named `admin` with `type: 'web'` is a web build. A resolved target config carries it at the top level like every other key in the entry.",
|
|
147
226
|
},
|
|
148
227
|
|
|
149
228
|
// ── brand ────────────────────────────────────────────────────────────────
|
|
@@ -179,12 +258,6 @@ const SHARED_SCHEMA = [
|
|
|
179
258
|
required: false,
|
|
180
259
|
description: 'Short marketing tagline.',
|
|
181
260
|
},
|
|
182
|
-
{
|
|
183
|
-
path: 'brand.company',
|
|
184
|
-
type: 'string',
|
|
185
|
-
required: false,
|
|
186
|
-
description: 'Parent/legal entity name ("Acme Inc"). Legal documents, receipts; falls back to brand.name.',
|
|
187
|
-
},
|
|
188
261
|
{
|
|
189
262
|
path: 'brand.type',
|
|
190
263
|
type: 'string',
|
|
@@ -266,12 +339,6 @@ const SHARED_SCHEMA = [
|
|
|
266
339
|
required: false,
|
|
267
340
|
description: 'Brand image URLs/paths (wordmark, brandmark, combomark, icon).',
|
|
268
341
|
},
|
|
269
|
-
{
|
|
270
|
-
path: 'brand.images.companyWordmark',
|
|
271
|
-
type: 'string',
|
|
272
|
-
required: false,
|
|
273
|
-
description: 'Parent/legal-entity wordmark (brand.company) rendered in the transactional email footer. Omitted from the footer when unset.',
|
|
274
|
-
},
|
|
275
342
|
|
|
276
343
|
// ── socials ──────────────────────────────────────────────────────────────
|
|
277
344
|
{
|
|
@@ -439,7 +506,7 @@ const SHARED_SCHEMA = [
|
|
|
439
506
|
path: 'advertising.providers.inhouse.source',
|
|
440
507
|
type: 'string',
|
|
441
508
|
required: false,
|
|
442
|
-
description: "In-house ads source: 'self' (this brand's backend serves its own `ads` inventory), 'company' (the parent company's api
|
|
509
|
+
description: "In-house ads source: 'self' (this brand's backend serves its own `ads` inventory), 'company' (the parent company's api, derived from the RESOLVED company.url), or a full base URL used verbatim. Presence-driven, and unset disables house units.",
|
|
443
510
|
},
|
|
444
511
|
{
|
|
445
512
|
path: 'advertising.fallback',
|
|
@@ -454,13 +521,31 @@ const SHARED_SCHEMA = [
|
|
|
454
521
|
description: "This brand's contextual tags (['music', 'audio-tools']) — the targeting match input a house unit sends with its serve request unless the include passes its own. No user tracking.",
|
|
455
522
|
},
|
|
456
523
|
|
|
457
|
-
// ── company
|
|
524
|
+
// ── company (ONE typed key, the rest RESOLVED) ───────────────────────────
|
|
525
|
+
// The brand's relationship to its company lives OUTSIDE `brand` (Ian
|
|
526
|
+
// 2026-09-12: "brand key is for things about this brand, and the
|
|
527
|
+
// parent/company/organization key is OUTSIDE of that"), and the loader fills
|
|
528
|
+
// the SAME key with the company's public facts (#677): `company.name`,
|
|
529
|
+
// `company.url` and `company.images.wordmark` are RESOLVED, never typed, and
|
|
530
|
+
// the loader refuses each of them in an authored file. A brand with no
|
|
531
|
+
// company resolves to its own name and url under a null id, so no reader
|
|
532
|
+
// carries a fallback.
|
|
458
533
|
{
|
|
459
|
-
path: 'company.
|
|
534
|
+
path: 'company.id',
|
|
460
535
|
type: 'string',
|
|
461
536
|
required: false,
|
|
462
|
-
|
|
463
|
-
|
|
537
|
+
description: "The company this brand belongs to, named by the parent's `brand.id` ('itw-creative-works'), or the literal 'self' on the company brand itself. The ONE key that joins a brand to a company: the parent's public facts, its config layer, its `.env`, its hooks and its signing tree all resolve from it (docs/manager/company.md).",
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
path: 'company.webhooks',
|
|
541
|
+
type: 'boolean',
|
|
542
|
+
required: false,
|
|
543
|
+
default: true,
|
|
544
|
+
// Resolution only: an opt-OUT written into every brand file as `true`
|
|
545
|
+
// would be noise, and the fact belongs to the brands that actually share
|
|
546
|
+
// somebody else's provider account.
|
|
547
|
+
materialize: false,
|
|
548
|
+
description: "Whether the manage walk may repoint this company's provider ACCOUNT webhooks (#677). `false` says the SendGrid Event Webhook and the Beehiiv webhook belong to someone else (a shared account whose one account-level webhook points at their production), so the campaigns and newsletter services leave them alone. The successor to the retired top-level `parent: false`.",
|
|
464
549
|
},
|
|
465
550
|
|
|
466
551
|
// ── features (the catalog every product prices) ──────────────────────────
|
|
@@ -468,10 +553,17 @@ const SHARED_SCHEMA = [
|
|
|
468
553
|
path: 'features',
|
|
469
554
|
type: 'object',
|
|
470
555
|
required: false,
|
|
471
|
-
description: "The feature catalog (#647): every feature DEFINED once, keyed by id, in the order every surface renders it. An entry carries name, icon, definition — and, when the feature is METERED, a `usage` block ({ pace: 'daily' | false, mirror: ['<doc kind>'] }); an entry without one is a perk. Products name only the VALUE (payment.products[].features). Key order is row order on the pricing page and the account's usage bars.",
|
|
556
|
+
description: "The feature catalog (#647): every feature DEFINED once, keyed by id, in the order every surface renders it. An entry carries name, icon (the full Font Awesome class string, #929), definition — and, when the feature is METERED, a `usage` block ({ pace: 'daily' | false, mirror: ['<doc kind>'] }); an entry without one is a perk. Products name only the VALUE (payment.products[].features). Key order is row order on the pricing page and the account's usage bars.",
|
|
472
557
|
},
|
|
473
558
|
|
|
474
559
|
// ── payment (role: billing; provider-discriminated) ──────────────────────
|
|
560
|
+
{
|
|
561
|
+
path: 'payment.currency',
|
|
562
|
+
type: 'string',
|
|
563
|
+
required: false,
|
|
564
|
+
default: 'USD',
|
|
565
|
+
description: "The ISO 4217 code every price in payment.products is quoted in (#850). One currency per brand, named wherever a price is shown or recorded: the pricing page's JSON-LD, the checkout, and the backend's order history (GET /user/orders). Defaults to 'USD', the fallback its readers carried before the fact had a home. The successor to the retired targets.web.currency.",
|
|
566
|
+
},
|
|
475
567
|
{
|
|
476
568
|
path: 'payment.providers.stripe.publishableKey',
|
|
477
569
|
type: 'string',
|
|
@@ -555,7 +647,7 @@ const SHARED_SCHEMA = [
|
|
|
555
647
|
type: 'string',
|
|
556
648
|
required: false,
|
|
557
649
|
match: /^https?:\/\//,
|
|
558
|
-
description: 'Sentry DSN (public by design). Per-surface DSNs go in targets.<
|
|
650
|
+
description: 'Sentry DSN (public by design). Per-surface DSNs go in targets.<name>.monitoring.providers.sentry.dsn overrides.',
|
|
559
651
|
},
|
|
560
652
|
{
|
|
561
653
|
path: 'monitoring.providers.sentry.environment',
|
|
@@ -668,39 +760,35 @@ const SHARED_SCHEMA = [
|
|
|
668
760
|
description: "Per-provider user-connection settings, keyed by provider name (`connections: { twitch: {…} }`) — public values only, never client secrets (those are the CONNECTIONS_<PROVIDER>_CLIENT_ID/_SECRET env pair). The set of providers is OPEN (a brand ships its own as `src/connections/<name>.js`), so the section stays free-form; the keys every entry may carry are `enabled` (the packaged providers default to false — set it true to offer one; a brand's own provider is on unless this is false), `scope` (an array that wins over the provider module's default), `name` and `logo` (what the account page's card draws — the CONFIG is the only card list, #793: `logo` is the name of a mark @omega.js/web ships in core/logos/brandmarks/original, rendered inline, or a full URL rendered as an img), and `description` (the line under the card's title). The five packaged providers carry all three by default, so enabling one is one line. packages/backend/docs/connections.md",
|
|
669
761
|
},
|
|
670
762
|
|
|
671
|
-
// ── repo (
|
|
763
|
+
// ── repo (where the brand hosts its source; #883) ───────────────────────
|
|
764
|
+
// Two keys, and block PRESENCE is the switch, exactly as a target's key
|
|
765
|
+
// presence enables that target. Every repo NAME derives from
|
|
766
|
+
// `<brand.id>-<role>` (#809), and visibility is the brand root package.json's
|
|
767
|
+
// `private` field, so neither is configurable here.
|
|
672
768
|
{
|
|
673
|
-
path: 'repo
|
|
674
|
-
type: '
|
|
769
|
+
path: 'repo',
|
|
770
|
+
type: 'object',
|
|
675
771
|
required: false,
|
|
676
|
-
|
|
677
|
-
description: 'false = the repo service skips entirely — no org profile, no repo settings, no GitHub Pages reconciliation; the brand hosts its source somewhere the manager does not touch.',
|
|
772
|
+
description: 'Where the brand hosts its source. Presence enables the repo service; the block is provider + org and nothing else, since every repo name derives from `<brand.id>-<role>` (#883).',
|
|
678
773
|
},
|
|
679
774
|
{
|
|
680
|
-
path: 'repo.
|
|
775
|
+
path: 'repo.provider',
|
|
776
|
+
// NO `default:`, by the presence-gate exclusion (docs/shared/config.md,
|
|
777
|
+
// Defaults & self-healing): the BLOCK's presence is what enables the repo
|
|
778
|
+
// service, so a resolved `repo: { provider: 'github' }` would say a brand
|
|
779
|
+
// hosts its source somewhere when it declared nothing. The value a missing
|
|
780
|
+
// provider reads is repo.js's DEFAULT_REPO_PROVIDER, beside the derivation
|
|
781
|
+
// that reads it.
|
|
681
782
|
type: 'string',
|
|
682
783
|
required: false,
|
|
683
|
-
|
|
784
|
+
enum: REPO_PROVIDERS,
|
|
785
|
+
description: 'Which host serves the brand source (default `github`, the only one built). A second provider is a new row here plus its own helper, never a reshape of this block.',
|
|
684
786
|
},
|
|
685
787
|
{
|
|
686
|
-
path: 'repo.
|
|
788
|
+
path: 'repo.org',
|
|
687
789
|
type: 'string',
|
|
688
790
|
required: false,
|
|
689
|
-
description:
|
|
690
|
-
},
|
|
691
|
-
{
|
|
692
|
-
path: 'repo.providers.github.shared',
|
|
693
|
-
type: 'boolean',
|
|
694
|
-
required: false,
|
|
695
|
-
default: false,
|
|
696
|
-
description: 'true = the org is shared with other brands; org-level reconciliation is skipped.',
|
|
697
|
-
},
|
|
698
|
-
{
|
|
699
|
-
path: 'repo.providers.github.private',
|
|
700
|
-
type: 'boolean',
|
|
701
|
-
required: false,
|
|
702
|
-
default: true,
|
|
703
|
-
description: 'Brand repo visibility (default true).',
|
|
791
|
+
description: "GitHub org/user every repo the brand owns lives in: `<brand.id>-omega` (source), `<brand.id>-releases` (public artifacts), `<brand.id>-<name>` (one per GitHub-hosted web target). No org → the repo service skips and the site's desktop release URLs stay underived.",
|
|
704
792
|
},
|
|
705
793
|
|
|
706
794
|
// ── domain (two roles: registrar + mailbox; provider-keyed, #425) ────────
|
|
@@ -964,6 +1052,14 @@ const SHARED_SCHEMA = [
|
|
|
964
1052
|
description: "Certificate types managed for the Apple Developer account ([{ type, manual }]) — `manual: true` marks the ones Apple's API cannot create, which the Account Holder downloads from the portal. Unset uses the framework set.",
|
|
965
1053
|
},
|
|
966
1054
|
|
|
1055
|
+
// ── publishing (role: ship credentials; no provider) ─────────────────
|
|
1056
|
+
{
|
|
1057
|
+
path: 'publishing.enabled',
|
|
1058
|
+
type: 'boolean',
|
|
1059
|
+
required: false,
|
|
1060
|
+
description: "The manage walk's ship-credential gate ([#867](https://github.com/Omega-JS-Stack/omega/issues/867)): the `publishing` service asks for every developer key and listing id the brand's declared formats need (`targets.<name>.platforms.<platform>.formats`). `false` is the permanent opt-out the gate's Disable lands; absence means ask, and no default is materialized. Dropping ONE store is the declaration's job (`platforms.<store>.formats.store: false`), never this switch.",
|
|
1061
|
+
},
|
|
1062
|
+
|
|
967
1063
|
// ── devlog (role: commit-digest publishing; provider-discriminated) ──────
|
|
968
1064
|
{
|
|
969
1065
|
path: 'devlog',
|
|
@@ -994,28 +1090,12 @@ const SHARED_SCHEMA = [
|
|
|
994
1090
|
description: "Managed Firebase Auth accounts (@omega.js/manager account service): enabled + admins ([{ email, account, marketing }]; '{domain}' templates to the brand domain). Owner-defined — typically set once in the COMPANY omega.json5 (arrays replace, so the company list wins whole). Passwords NEVER live here: per-account OMEGA_ACCOUNT_PASSWORD__* env vars, the config/hooks/account/password.js hook, or the ACCOUNT_PASSWORD_SEED derivation.",
|
|
995
1091
|
},
|
|
996
1092
|
|
|
997
|
-
// ──
|
|
998
|
-
//
|
|
1093
|
+
// ── reviews ──────────────────────────────────────────────────────────────
|
|
1094
|
+
// reviews … dataRequest are brand-level sections the manager reads UNFOLDED
|
|
999
1095
|
// (#277): a website-only brand has no targets.backend to hold them, and
|
|
1000
1096
|
// adding one purely as a config home would falsely enable the target. A
|
|
1001
1097
|
// targets.backend block still overrides any of them: that comes free from
|
|
1002
1098
|
// the merge chain.
|
|
1003
|
-
{
|
|
1004
|
-
path: 'parent',
|
|
1005
|
-
type: 'string|boolean',
|
|
1006
|
-
required: false,
|
|
1007
|
-
description: "Webhook parent topology: 'self' when this brand IS the parent, a parent URL otherwise, or false to deliberately opt out (shared webhook account owned elsewhere).",
|
|
1008
|
-
},
|
|
1009
|
-
|
|
1010
|
-
// ── github ───────────────────────────────────────────────────────────────
|
|
1011
|
-
{
|
|
1012
|
-
path: 'github',
|
|
1013
|
-
type: 'object',
|
|
1014
|
-
required: false,
|
|
1015
|
-
description: 'GitHub identity for the brand (user, website repo URL).',
|
|
1016
|
-
},
|
|
1017
|
-
|
|
1018
|
-
// ── reviews ──────────────────────────────────────────────────────────────
|
|
1019
1099
|
{
|
|
1020
1100
|
path: 'reviews',
|
|
1021
1101
|
type: 'object',
|
|
@@ -1141,7 +1221,7 @@ const SHARED_SCHEMA = [
|
|
|
1141
1221
|
path: 'directory',
|
|
1142
1222
|
type: 'object',
|
|
1143
1223
|
required: false,
|
|
1144
|
-
description: "Directory participation (@omega.js/manager directory service): { enabled }
|
|
1224
|
+
description: "Directory participation (@omega.js/manager directory service): { enabled } opts in to pushing this brand's entry into the parent project's `brands` collection. Absent or false never pushes. Needs `company.id` to name a parent (#677) and DIRECTORY_SERVICE_ACCOUNT in the brand .env.",
|
|
1145
1225
|
},
|
|
1146
1226
|
{
|
|
1147
1227
|
path: 'directory.enabled',
|
|
@@ -1242,10 +1322,15 @@ const SHARED_SCHEMA = [
|
|
|
1242
1322
|
description: "Model override for the chosen provider (defaults: claude → 'sonnet' alias, chatgpt → 'gpt-5.4-nano').",
|
|
1243
1323
|
},
|
|
1244
1324
|
{
|
|
1245
|
-
path: 'translation.
|
|
1325
|
+
path: 'translation.include',
|
|
1246
1326
|
type: 'array',
|
|
1247
1327
|
required: false,
|
|
1248
|
-
|
|
1328
|
+
default: TRANSLATION_INCLUDE_DEFAULT,
|
|
1329
|
+
// Resolution only: the list is the FRAMEWORK's answer to "what is worth
|
|
1330
|
+
// paying a provider for", and a copy in every brand config is a copy that
|
|
1331
|
+
// drifts from it (#793). A brand that wants a different answer writes one.
|
|
1332
|
+
materialize: false,
|
|
1333
|
+
description: "Web only: the page routes to translate, as globs with `!` negation, read in order like a .gitignore: the LAST pattern that matches a route decides it, and a route no pattern matches is not translated. A folder pattern covers the folder itself (`!blog/**` excludes `/blog` and everything under it). The default ['**', '!blog/**'] translates the whole site except the blog, which is where the words (and the cost) pile up. A brand list REPLACES the default outright. A page overrides it for itself with `translation.include: true`/`false` in its own frontmatter, the same key name one level down (docs/web/frontmatter.md). The framework's own default pages carry their own exclusion and are never in this list's hands.",
|
|
1249
1334
|
},
|
|
1250
1335
|
|
|
1251
1336
|
// ── client (the @omega.js/client runtime blob) ───────────────────────────
|
|
@@ -1306,7 +1391,7 @@ const SHARED_SCHEMA = [
|
|
|
1306
1391
|
path: 'targets',
|
|
1307
1392
|
type: 'object',
|
|
1308
1393
|
required: false,
|
|
1309
|
-
description: "Key presence = target enabled;
|
|
1394
|
+
description: "Every key is a target NAME, which is the folder `targets/<name>`, the `--target=<name>` word and the derived-repo suffix (#886). Key presence = target enabled; the value is an object of target-scoped config (any shared key inside overrides it) and MUST declare `type`: web/backend/desktop/extension/mobile, or `custom` (#603) for a target the manager drives entirely through its own package.json scripts. Anything else is an error.",
|
|
1310
1395
|
},
|
|
1311
1396
|
];
|
|
1312
1397
|
|
|
@@ -1316,6 +1401,22 @@ const TARGET_SCHEMAS = {
|
|
|
1316
1401
|
// Grows with @omega.js/web's design: distribute, purgecss safelist,
|
|
1317
1402
|
// workflows land as their features do.
|
|
1318
1403
|
web: [
|
|
1404
|
+
{
|
|
1405
|
+
path: 'hosting',
|
|
1406
|
+
type: 'object',
|
|
1407
|
+
required: false,
|
|
1408
|
+
description: 'Where this web target is SERVED from (#883). Web targets only: a non-web target carrying it is a validation error.',
|
|
1409
|
+
},
|
|
1410
|
+
{
|
|
1411
|
+
path: 'hosting.provider',
|
|
1412
|
+
// No `default:` either, for the same reason as `repo.provider`: the value
|
|
1413
|
+
// is read off the TARGET's own entry (repo.js `hostingProvider`), where a
|
|
1414
|
+
// resolved top-level default never reaches.
|
|
1415
|
+
type: 'string',
|
|
1416
|
+
required: false,
|
|
1417
|
+
enum: HOSTING_PROVIDERS,
|
|
1418
|
+
description: "Who serves the built site. `github` publishes it to the target's own `<brand.id>-<name>` repo and serves it from GitHub Pages at the target's url; a second provider is a new row here plus its own deploy helper.",
|
|
1419
|
+
},
|
|
1319
1420
|
{
|
|
1320
1421
|
path: 'meta',
|
|
1321
1422
|
type: 'object',
|
|
@@ -1387,9 +1488,8 @@ const TARGET_SCHEMAS = {
|
|
|
1387
1488
|
|
|
1388
1489
|
// Seeded from the sandbox brand's real @omega.js/backend config (backend-manager-config.json).
|
|
1389
1490
|
backend: [
|
|
1390
|
-
//
|
|
1391
|
-
//
|
|
1392
|
-
// through the merge chain.
|
|
1491
|
+
// reviews, marketing, blog, dataRequest moved to SHARED_SCHEMA (#277); a
|
|
1492
|
+
// targets.backend block still overrides them through the merge chain.
|
|
1393
1493
|
{
|
|
1394
1494
|
path: 'projectType',
|
|
1395
1495
|
type: 'string',
|
|
@@ -1416,12 +1516,157 @@ const TARGET_SCHEMAS = {
|
|
|
1416
1516
|
enum: ['productivity', 'developer-tools', 'utilities', 'media', 'social', 'network'],
|
|
1417
1517
|
description: 'Generic high-level category. Maps to per-platform UTI + freedesktop strings.',
|
|
1418
1518
|
},
|
|
1519
|
+
// ── the rest of app.* (#911) ─────────────────────────────────────────
|
|
1520
|
+
// The three DERIVED fields carry no schema `default:`: their answer comes
|
|
1521
|
+
// from the brand (the bundle-id policy, brand.name, the year), so a
|
|
1522
|
+
// materialized null would be a brand file restating "derive it".
|
|
1523
|
+
{
|
|
1524
|
+
path: 'app.appId',
|
|
1525
|
+
type: 'string',
|
|
1526
|
+
required: false,
|
|
1527
|
+
description: "The bundle identifier the app is signed and registered under. Unset, it derives as `certificates.providers.apple.bundleIdPrefix` plus `brand.id` with the dashes as dots ([#909](https://github.com/Omega-JS-Stack/omega/issues/909)), the very id the certificates service registers; a brand with no prefix falls back to the reverse-domain of `brand.url`, then `app.<brand.id>`. Set it only to stay on an id already-shipped builds carry.",
|
|
1528
|
+
},
|
|
1529
|
+
{
|
|
1530
|
+
path: 'app.productName',
|
|
1531
|
+
type: 'string',
|
|
1532
|
+
required: false,
|
|
1533
|
+
description: 'The product name the installer, the app menu and the artifact names carry. Unset, it is `brand.name`.',
|
|
1534
|
+
},
|
|
1535
|
+
{
|
|
1536
|
+
path: 'app.copyright',
|
|
1537
|
+
type: 'string',
|
|
1538
|
+
required: false,
|
|
1539
|
+
description: 'The copyright string baked into the mac plist and the Windows version resource. A `{YEAR}` token expands at build time. Unset, it is `© {YEAR}, <brand.name>`.',
|
|
1540
|
+
},
|
|
1541
|
+
{
|
|
1542
|
+
path: 'app.languages',
|
|
1543
|
+
type: 'array',
|
|
1544
|
+
required: false,
|
|
1545
|
+
description: "The languages the mac build ships (electron-builder's `mac.electronLanguages`). Unset reads as ['en'].",
|
|
1546
|
+
},
|
|
1547
|
+
{
|
|
1548
|
+
path: 'app.darkModeSupport',
|
|
1549
|
+
type: 'boolean',
|
|
1550
|
+
required: false,
|
|
1551
|
+
description: 'Whether the mac build declares dark-mode support (NSRequiresAquaSystemAppearance). Unset reads as true; windows and linux ignore it.',
|
|
1552
|
+
},
|
|
1553
|
+
{
|
|
1554
|
+
path: 'omega.authPersistence',
|
|
1555
|
+
type: 'string',
|
|
1556
|
+
required: false,
|
|
1557
|
+
description: "Where @omega.js/client's auth session is kept in the main process: `safeStorage` (the default, the OS keychain through Electron safeStorage), `none` (in-memory, the explicit opt-out), or the name of a strategy the consumer registered before `initialize()`. A test run is always `none`, whatever this says.",
|
|
1558
|
+
},
|
|
1559
|
+
// ── the shipping declaration (#867) ──────────────────────────────────
|
|
1560
|
+
// The SAME shape the extension target declares below: presence is the
|
|
1561
|
+
// switch, every platform and every format defaults ON, and the only thing
|
|
1562
|
+
// that drops one is a literal `false` (the `certificates: false` idiom).
|
|
1563
|
+
// Per-format settings live INSIDE the format. The vocabulary is the
|
|
1564
|
+
// client's (mac, windows, linux), and @omega.js/config's platforms.js is
|
|
1565
|
+
// the format table every reader derives from.
|
|
1566
|
+
{
|
|
1567
|
+
path: 'platforms',
|
|
1568
|
+
type: 'object',
|
|
1569
|
+
required: false,
|
|
1570
|
+
description: "What this desktop target SHIPS, plus each platform's install knobs (#867): `platforms.<mac|windows|linux>.formats.<dmg|nsis|deb|appimage|snap>`. Presence = enabled; drop a default with `false`. The install knobs beside `formats` (arch, the NSIS flags, mac entitlements) map onto the same electron-builder concepts, which @omega.js/desktop owns the target list of.",
|
|
1571
|
+
},
|
|
1572
|
+
{
|
|
1573
|
+
path: 'platforms.mac',
|
|
1574
|
+
type: 'object|boolean',
|
|
1575
|
+
required: false,
|
|
1576
|
+
description: 'The mac leg: `false` ships no mac build at all (no dmg, no auto-update zip).',
|
|
1577
|
+
},
|
|
1578
|
+
{
|
|
1579
|
+
path: 'platforms.mac.formats',
|
|
1580
|
+
type: 'object',
|
|
1581
|
+
required: false,
|
|
1582
|
+
description: 'Which mac formats ship. `dmg` is the only one a brand declares; the auto-update zip is not a format (electron-updater fetches it from the feed and nobody links it).',
|
|
1583
|
+
},
|
|
1584
|
+
{
|
|
1585
|
+
path: 'platforms.mac.formats.dmg',
|
|
1586
|
+
type: 'object|boolean',
|
|
1587
|
+
required: false,
|
|
1588
|
+
description: 'The macOS disk image, and the download `/download/mac/dmg` hands over. `false` drops it.',
|
|
1589
|
+
},
|
|
1590
|
+
{
|
|
1591
|
+
path: 'platforms.windows',
|
|
1592
|
+
type: 'object|boolean',
|
|
1593
|
+
required: false,
|
|
1594
|
+
description: 'The windows leg: `false` ships no windows build and skips the signing jobs with it.',
|
|
1595
|
+
},
|
|
1596
|
+
{
|
|
1597
|
+
path: 'platforms.windows.formats',
|
|
1598
|
+
type: 'object',
|
|
1599
|
+
required: false,
|
|
1600
|
+
description: 'Which windows formats ship. `nsis` is the one installer, and it merges every declared arch into one file.',
|
|
1601
|
+
},
|
|
1419
1602
|
{
|
|
1420
|
-
path: 'platforms.
|
|
1603
|
+
path: 'platforms.windows.formats.nsis',
|
|
1604
|
+
type: 'object|boolean',
|
|
1605
|
+
required: false,
|
|
1606
|
+
description: 'The NSIS installer, and the download `/download/windows/nsis` hands over. `false` drops it. Its installer UX knobs (oneClick, shortcuts, perMachine) sit on `platforms.windows` itself.',
|
|
1607
|
+
},
|
|
1608
|
+
{
|
|
1609
|
+
path: 'platforms.windows.signing.strategy',
|
|
1421
1610
|
type: 'string',
|
|
1422
1611
|
required: false,
|
|
1423
1612
|
enum: ['self-hosted', 'cloud', 'local'],
|
|
1424
|
-
description: 'Windows code-signing path. self-hosted = EV USB token on a runner; cloud = provider CLI; local = developer signs manually.',
|
|
1613
|
+
description: 'Windows code-signing path. self-hosted = EV USB token on a runner; cloud = provider CLI; local = developer signs manually. The env schema gates each signing credential on this value, so the walk only ever asks for the set this strategy uses.',
|
|
1614
|
+
},
|
|
1615
|
+
{
|
|
1616
|
+
path: 'platforms.linux',
|
|
1617
|
+
type: 'object|boolean',
|
|
1618
|
+
required: false,
|
|
1619
|
+
description: 'The linux leg: `false` ships no linux build at all.',
|
|
1620
|
+
},
|
|
1621
|
+
{
|
|
1622
|
+
path: 'platforms.linux.formats',
|
|
1623
|
+
type: 'object',
|
|
1624
|
+
required: false,
|
|
1625
|
+
description: 'Which linux formats ship: `deb` and `appimage` are release assets, `snap` publishes to the Snap Store instead.',
|
|
1626
|
+
},
|
|
1627
|
+
{
|
|
1628
|
+
path: 'platforms.linux.formats.deb',
|
|
1629
|
+
type: 'object|boolean',
|
|
1630
|
+
required: false,
|
|
1631
|
+
description: 'The Debian package, and the download `/download/linux/deb` hands over. It needs `brand.url` and `brand.contact.email` (electron-builder refuses a deb with no homepage or maintainer).',
|
|
1632
|
+
},
|
|
1633
|
+
{
|
|
1634
|
+
path: 'platforms.linux.formats.appimage',
|
|
1635
|
+
type: 'object|boolean',
|
|
1636
|
+
required: false,
|
|
1637
|
+
description: 'The AppImage, and the download `/download/linux/appimage` hands over. `false` drops it.',
|
|
1638
|
+
},
|
|
1639
|
+
{
|
|
1640
|
+
path: 'platforms.linux.formats.snap',
|
|
1641
|
+
type: 'object|boolean',
|
|
1642
|
+
required: false,
|
|
1643
|
+
description: "The Snap Store publish (never a release asset: the store holds the file, and `/download/linux/snap` is the listing). Needs SNAPCRAFT_STORE_CREDENTIALS, which the env schema gates on this very key, so declaring it is what makes the walk ask.",
|
|
1644
|
+
},
|
|
1645
|
+
{
|
|
1646
|
+
path: 'platforms.linux.formats.snap.channels',
|
|
1647
|
+
type: 'array',
|
|
1648
|
+
required: false,
|
|
1649
|
+
description: "Snap Store channels the publish pushes to. Unset, the publish uses ['stable']; ['edge'] is the pre-release lane. No schema `default:` on any of these four: materializing one would declare the snap format on every brand that never mentioned it, and the declaration is what makes its credentials mandatory.",
|
|
1650
|
+
},
|
|
1651
|
+
{
|
|
1652
|
+
path: 'platforms.linux.formats.snap.confinement',
|
|
1653
|
+
type: 'string',
|
|
1654
|
+
required: false,
|
|
1655
|
+
enum: ['strict', 'classic', 'devmode'],
|
|
1656
|
+
description: 'Snap confinement. Unset reads as strict, which is what the store reviews fastest; classic needs manual store approval.',
|
|
1657
|
+
},
|
|
1658
|
+
{
|
|
1659
|
+
path: 'platforms.linux.formats.snap.grade',
|
|
1660
|
+
type: 'string',
|
|
1661
|
+
required: false,
|
|
1662
|
+
enum: ['stable', 'devel'],
|
|
1663
|
+
description: 'Snap grade. Unset reads as stable; a devel snap cannot be released to a stable channel.',
|
|
1664
|
+
},
|
|
1665
|
+
{
|
|
1666
|
+
path: 'platforms.linux.formats.snap.autoStart',
|
|
1667
|
+
type: 'boolean',
|
|
1668
|
+
required: false,
|
|
1669
|
+
description: 'Whether the snap registers the app to start on login. Unset reads as true.',
|
|
1425
1670
|
},
|
|
1426
1671
|
{
|
|
1427
1672
|
path: 'startup.mode',
|
|
@@ -1430,29 +1675,81 @@ const TARGET_SCHEMAS = {
|
|
|
1430
1675
|
enum: ['normal', 'hidden'],
|
|
1431
1676
|
description: 'normal = main window appears at launch; hidden = bakes LSUIElement=true on macOS (no dock, no Cmd+Tab).',
|
|
1432
1677
|
},
|
|
1678
|
+
// ── the OTHER startup knob (#911): what an OS LOGIN launch does ──────
|
|
1433
1679
|
{
|
|
1434
|
-
path: '
|
|
1680
|
+
path: 'startup.openAtLogin.enabled',
|
|
1681
|
+
type: 'boolean',
|
|
1682
|
+
required: false,
|
|
1683
|
+
description: 'Whether the app registers with the OS to auto-launch at login. Unset reads as true.',
|
|
1684
|
+
},
|
|
1685
|
+
{
|
|
1686
|
+
path: 'startup.openAtLogin.mode',
|
|
1435
1687
|
type: 'string',
|
|
1436
1688
|
required: false,
|
|
1437
|
-
|
|
1689
|
+
enum: ['normal', 'hidden'],
|
|
1690
|
+
description: 'How an AT-LOGIN launch behaves, independently of `startup.mode` (which owns user-direct launches). Unset reads as hidden, so a normal app still starts quietly at login and surfaces when the user opens it.',
|
|
1438
1691
|
},
|
|
1692
|
+
// ── the auto-updater block (#911) ────────────────────────────────────
|
|
1693
|
+
// Its runtime answers live in the lib's own DEFAULTS, which every
|
|
1694
|
+
// unset key falls through to; the cadences are two separate timers on
|
|
1695
|
+
// purpose (a feed poll is network, an idle evaluation is arithmetic).
|
|
1439
1696
|
{
|
|
1440
|
-
path: '
|
|
1697
|
+
path: 'autoUpdate.enabled',
|
|
1441
1698
|
type: 'boolean',
|
|
1442
1699
|
required: false,
|
|
1443
|
-
description: 'One switch for the
|
|
1700
|
+
description: 'One switch for the auto-updater. Unset reads as true; `false` leaves the whole lane inert (no feed poll, no idle evaluator, no install).',
|
|
1444
1701
|
},
|
|
1445
1702
|
{
|
|
1446
|
-
path: '
|
|
1447
|
-
type: '
|
|
1703
|
+
path: 'autoUpdate.autoDownload',
|
|
1704
|
+
type: 'boolean',
|
|
1705
|
+
required: false,
|
|
1706
|
+
description: 'Whether a found update downloads on its own. Unset reads as true; false leaves the download to `manager.autoUpdater` being asked for it.',
|
|
1707
|
+
},
|
|
1708
|
+
{
|
|
1709
|
+
path: 'autoUpdate.startupDelayMs',
|
|
1710
|
+
type: 'integer',
|
|
1711
|
+
required: false,
|
|
1712
|
+
min: 0,
|
|
1713
|
+
description: 'How long after the app is ready the FIRST update check fires. Unset reads as 10000 (10s), which keeps the check off the boot path.',
|
|
1714
|
+
},
|
|
1715
|
+
{
|
|
1716
|
+
path: 'autoUpdate.feedCheckIntervalMs',
|
|
1717
|
+
type: 'integer',
|
|
1718
|
+
required: false,
|
|
1719
|
+
min: 0,
|
|
1720
|
+
description: 'How often the update feed is polled. Network-bound, so keep it slow: unset reads as 3600000 (1h), the cadence Discord, Slack and VS Code use.',
|
|
1721
|
+
},
|
|
1722
|
+
{
|
|
1723
|
+
path: 'autoUpdate.idleEvalIntervalMs',
|
|
1724
|
+
type: 'integer',
|
|
1725
|
+
required: false,
|
|
1726
|
+
min: 0,
|
|
1727
|
+
description: 'How often a DOWNLOADED update re-asks "is the user idle enough to install". In-process arithmetic, so it is cheap: unset reads as 60000 (1m).',
|
|
1728
|
+
},
|
|
1729
|
+
{
|
|
1730
|
+
path: 'autoUpdate.maxAgeMs',
|
|
1731
|
+
type: 'integer',
|
|
1448
1732
|
required: false,
|
|
1449
|
-
|
|
1733
|
+
min: 0,
|
|
1734
|
+
description: 'How long a downloaded update may sit pending before the install stops waiting for an idle moment. Unset reads as 2592000000 (30d).',
|
|
1450
1735
|
},
|
|
1451
1736
|
{
|
|
1452
|
-
path: '
|
|
1737
|
+
path: 'cdp.readySignal',
|
|
1453
1738
|
type: 'string',
|
|
1454
1739
|
required: false,
|
|
1455
|
-
description: '
|
|
1740
|
+
description: 'Boot-complete signal for `mgr cdp relaunch`: a URL substring matched against CDP page targets.',
|
|
1741
|
+
},
|
|
1742
|
+
{
|
|
1743
|
+
path: 'releases.enabled',
|
|
1744
|
+
type: 'boolean',
|
|
1745
|
+
required: false,
|
|
1746
|
+
description: 'One switch for the release surface: false suppresses the site\'s derived download links AND desktop publishing (electron-builder publish). Site derivation defaults true only when the releases block exists; desktop publishing defaults true regardless.',
|
|
1747
|
+
},
|
|
1748
|
+
{
|
|
1749
|
+
path: 'releases',
|
|
1750
|
+
type: 'object',
|
|
1751
|
+
required: false,
|
|
1752
|
+
description: "Presence opts the brand into the release surface (the site's download links, desktop publishing). WHICH repo is not configurable: it is the brand's one public `<brand.id>-releases` (#883).",
|
|
1456
1753
|
},
|
|
1457
1754
|
{
|
|
1458
1755
|
path: 'restartManager.enabled',
|
|
@@ -1474,6 +1771,20 @@ const TARGET_SCHEMAS = {
|
|
|
1474
1771
|
match: /^[\w.-]+$/,
|
|
1475
1772
|
description: 'GitHub repo of the RM release feed.',
|
|
1476
1773
|
},
|
|
1774
|
+
// ── hot config (#911): the JSON the app re-reads without a release ───
|
|
1775
|
+
{
|
|
1776
|
+
path: 'remoteConfig.enabled',
|
|
1777
|
+
type: 'boolean',
|
|
1778
|
+
required: false,
|
|
1779
|
+
description: 'The remote-config document, polled at the auto-updater feed cadence so app behavior (a force-update gate, a kill switch) flips without shipping a build. Unset reads as true.',
|
|
1780
|
+
},
|
|
1781
|
+
{
|
|
1782
|
+
path: 'remoteConfig.url',
|
|
1783
|
+
type: 'string',
|
|
1784
|
+
required: false,
|
|
1785
|
+
match: /^https?:\/\//,
|
|
1786
|
+
description: 'Where that document is fetched from. Unset, it derives as `${brand.url}/data/resources/main.json`.',
|
|
1787
|
+
},
|
|
1477
1788
|
{
|
|
1478
1789
|
path: 'remoteScripts.enabled',
|
|
1479
1790
|
type: 'boolean',
|
|
@@ -1499,6 +1810,109 @@ const TARGET_SCHEMAS = {
|
|
|
1499
1810
|
// Store listings ARE the extension page's declaration and the curated
|
|
1500
1811
|
// site.targets.extension view (#85, #610 — no second copy in web config).
|
|
1501
1812
|
extension: [
|
|
1813
|
+
// ── the shipping declaration (#867) ──────────────────────────────────
|
|
1814
|
+
// The SAME shape the desktop target declares above, in the browser half of
|
|
1815
|
+
// the client's vocabulary (chrome, firefox, edge). `edge` ships the CHROME
|
|
1816
|
+
// build: two stores, one chromium artifact.
|
|
1817
|
+
{
|
|
1818
|
+
path: 'platforms',
|
|
1819
|
+
type: 'object',
|
|
1820
|
+
required: false,
|
|
1821
|
+
description: 'What this extension target SHIPS (#867): `platforms.<chrome|firefox|edge>.formats.<zip|store>`. Presence = enabled; drop a default with `false`. The zip is attached to the release, the store is published to, and @omega.js/config\'s platforms.js says which credentials each store cannot ship without.',
|
|
1822
|
+
},
|
|
1823
|
+
{
|
|
1824
|
+
path: 'platforms.chrome',
|
|
1825
|
+
type: 'object|boolean',
|
|
1826
|
+
required: false,
|
|
1827
|
+
description: 'The Chrome leg (the chromium build every Chromium browser installs): `false` ships nothing for it.',
|
|
1828
|
+
},
|
|
1829
|
+
{
|
|
1830
|
+
path: 'platforms.chrome.formats',
|
|
1831
|
+
type: 'object',
|
|
1832
|
+
required: false,
|
|
1833
|
+
description: 'Which chrome formats ship: `zip` (attached to the release) and `store` (published to the Chrome Web Store).',
|
|
1834
|
+
},
|
|
1835
|
+
{
|
|
1836
|
+
path: 'platforms.chrome.formats.zip',
|
|
1837
|
+
type: 'object|boolean',
|
|
1838
|
+
required: false,
|
|
1839
|
+
description: 'The packaged zip, attached to the brand releases repo so anyone can install it unpacked.',
|
|
1840
|
+
},
|
|
1841
|
+
{
|
|
1842
|
+
path: 'platforms.chrome.formats.store',
|
|
1843
|
+
type: 'object|boolean',
|
|
1844
|
+
required: false,
|
|
1845
|
+
description: 'The Chrome Web Store publish. Needs the CHROME_* API credentials plus `listings.chrome.id` (the walk asks for both, #893).',
|
|
1846
|
+
},
|
|
1847
|
+
{
|
|
1848
|
+
path: 'platforms.firefox',
|
|
1849
|
+
type: 'object|boolean',
|
|
1850
|
+
required: false,
|
|
1851
|
+
description: 'The Firefox leg (its own build: scripts instead of a service worker, sidebar_action instead of side_panel).',
|
|
1852
|
+
},
|
|
1853
|
+
{
|
|
1854
|
+
path: 'platforms.firefox.formats',
|
|
1855
|
+
type: 'object',
|
|
1856
|
+
required: false,
|
|
1857
|
+
description: 'Which firefox formats ship: `zip` (attached to the release) and `store` (published to addons.mozilla.org).',
|
|
1858
|
+
},
|
|
1859
|
+
{
|
|
1860
|
+
path: 'platforms.firefox.formats.zip',
|
|
1861
|
+
type: 'object|boolean',
|
|
1862
|
+
required: false,
|
|
1863
|
+
description: 'The packaged zip, attached to the brand releases repo.',
|
|
1864
|
+
},
|
|
1865
|
+
{
|
|
1866
|
+
path: 'platforms.firefox.formats.store',
|
|
1867
|
+
type: 'object|boolean',
|
|
1868
|
+
required: false,
|
|
1869
|
+
description: 'The addons.mozilla.org publish. Needs FIREFOX_API_KEY + FIREFOX_API_SECRET; the add-on id is the manifest gecko id (`listings.firefox.id`), which the local scaffold pins into config when the brand declares none.',
|
|
1870
|
+
},
|
|
1871
|
+
{
|
|
1872
|
+
path: 'platforms.firefox.formats.store.channel',
|
|
1873
|
+
type: 'string',
|
|
1874
|
+
required: false,
|
|
1875
|
+
enum: ['listed', 'unlisted'],
|
|
1876
|
+
description: 'Which AMO channel the publish signs into. Unset reads as listed; `unlisted` self-distributes (signed, never listed on the store). No schema `default:`, for the same reason as the snap options: a materialized default would declare the format on a brand that never asked for it.',
|
|
1877
|
+
},
|
|
1878
|
+
{
|
|
1879
|
+
path: 'platforms.edge',
|
|
1880
|
+
type: 'object|boolean',
|
|
1881
|
+
required: false,
|
|
1882
|
+
description: 'The Edge leg. It ships the CHROME build, so dropping chrome while keeping edge still packages the chromium artifact.',
|
|
1883
|
+
},
|
|
1884
|
+
{
|
|
1885
|
+
path: 'platforms.edge.formats',
|
|
1886
|
+
type: 'object',
|
|
1887
|
+
required: false,
|
|
1888
|
+
description: 'Which edge formats ship: `zip` (attached to the release) and `store` (published to Edge Add-ons).',
|
|
1889
|
+
},
|
|
1890
|
+
{
|
|
1891
|
+
path: 'platforms.edge.formats.zip',
|
|
1892
|
+
type: 'object|boolean',
|
|
1893
|
+
required: false,
|
|
1894
|
+
description: 'The packaged zip, attached to the brand releases repo.',
|
|
1895
|
+
},
|
|
1896
|
+
{
|
|
1897
|
+
path: 'platforms.edge.formats.store',
|
|
1898
|
+
type: 'object|boolean',
|
|
1899
|
+
required: false,
|
|
1900
|
+
description: 'The Edge Add-ons publish. Needs EDGE_CLIENT_ID + EDGE_API_KEY plus `listings.edge.id` (the Partner Center product id, #893).',
|
|
1901
|
+
},
|
|
1902
|
+
{
|
|
1903
|
+
path: 'categories',
|
|
1904
|
+
type: 'array',
|
|
1905
|
+
required: false,
|
|
1906
|
+
itemEnum: AMO_CATEGORIES,
|
|
1907
|
+
default: ['alerts-updates'],
|
|
1908
|
+
description: "The AMO categories a FIRST Firefox publish lists the add-on under (#884): addons.mozilla.org requires them on a new listing, and the Firefox lane writes them into the `--amo-metadata` file it hands `web-ext sign`. Slugs come from AMO's own set; the default is `alerts-updates`, the most generic one that is not `other`. Chrome and Edge pick their category in their own dashboards.",
|
|
1909
|
+
},
|
|
1910
|
+
{
|
|
1911
|
+
path: 'listings.chrome.id',
|
|
1912
|
+
type: 'string',
|
|
1913
|
+
required: false,
|
|
1914
|
+
description: "The Chrome Web Store ITEM ID the publish uploads to, the 32-letter id in the listing URL (#893). Public by design, so it lives here and not in .env; the manage walk asks for it.",
|
|
1915
|
+
},
|
|
1502
1916
|
{
|
|
1503
1917
|
path: 'listings.chrome.url',
|
|
1504
1918
|
type: 'string',
|
|
@@ -1512,6 +1926,12 @@ const TARGET_SCHEMAS = {
|
|
|
1512
1926
|
required: false,
|
|
1513
1927
|
description: 'Listing state note (e.g. live, pending review). Display-safe, informational only.',
|
|
1514
1928
|
},
|
|
1929
|
+
{
|
|
1930
|
+
path: 'listings.firefox.id',
|
|
1931
|
+
type: 'string',
|
|
1932
|
+
required: false,
|
|
1933
|
+
description: "The addons.mozilla.org ADD-ON ID, which IS the manifest's browser_specific_settings.gecko.id (AMO uses it as the add-on guid, #893). Declared here it is authoritative: the firefox package writes it into the manifest. A brand that declares none gets the derived id pinned here by the extension's local scaffold, never by a publish.",
|
|
1934
|
+
},
|
|
1515
1935
|
{
|
|
1516
1936
|
path: 'listings.firefox.url',
|
|
1517
1937
|
type: 'string',
|
|
@@ -1525,6 +1945,12 @@ const TARGET_SCHEMAS = {
|
|
|
1525
1945
|
required: false,
|
|
1526
1946
|
description: 'Listing state note (e.g. live, pending review). Display-safe, informational only.',
|
|
1527
1947
|
},
|
|
1948
|
+
{
|
|
1949
|
+
path: 'listings.edge.id',
|
|
1950
|
+
type: 'string',
|
|
1951
|
+
required: false,
|
|
1952
|
+
description: "The Microsoft Edge Partner Center PRODUCT ID (a GUID) the publish uploads to (#893). Public by design, so it lives here and not in .env; the manage walk asks for it.",
|
|
1953
|
+
},
|
|
1528
1954
|
{
|
|
1529
1955
|
path: 'listings.edge.url',
|
|
1530
1956
|
type: 'string',
|
|
@@ -1584,10 +2010,10 @@ const TARGET_SCHEMAS = {
|
|
|
1584
2010
|
};
|
|
1585
2011
|
|
|
1586
2012
|
// Declared top-level keys that are NOT config sections: `targets` is scoping
|
|
1587
|
-
// machinery, and `url` is this
|
|
2013
|
+
// machinery, and `url` is this target's RESOLVED public url (#588): a value
|
|
1588
2014
|
// the loader derives, carried to templates as the `site.url` build fact, never
|
|
1589
2015
|
// a namespace a page's `config:` block overrides.
|
|
1590
|
-
const NON_SECTION_KEYS = ['targets', 'url'];
|
|
2016
|
+
const NON_SECTION_KEYS = ['targets', 'url', 'type'];
|
|
1591
2017
|
|
|
1592
2018
|
/** The top-level sections a rule array declares (machinery keys excluded). */
|
|
1593
2019
|
const sectionsOf = (rules) => [...new Set(rules.map((rule) => rule.path.split('.')[0]))].filter((section) => !NON_SECTION_KEYS.includes(section));
|
|
@@ -1607,4 +2033,4 @@ function configSections(target) {
|
|
|
1607
2033
|
return [...new Set([...sectionsOf(SHARED_SCHEMA), ...sectionsOf(TARGET_SCHEMAS[target] || [])])].sort();
|
|
1608
2034
|
}
|
|
1609
2035
|
|
|
1610
|
-
module.exports = { TARGETS, CUSTOM_TARGET_TYPE, isCustomTargetEntry, BACKEND_PROJECT_TYPES, backendProjectType, SHARED_SECTIONS, SHARED_SCHEMA, TARGET_SCHEMAS, BRAND_ID_PATTERN, WINBACK_DURATIONS, configSections };
|
|
2036
|
+
module.exports = { TRANSLATION_INCLUDE_DEFAULT, TARGETS, CUSTOM_TARGET_TYPE, isCustomTargetEntry, BACKEND_PROJECT_TYPES, backendProjectType, SHARED_SECTIONS, CLIENT_SECTIONS, SHARED_SCHEMA, TARGET_SCHEMAS, BRAND_ID_PATTERN, WINBACK_DURATIONS, REPO_PROVIDERS, HOSTING_PROVIDERS, AMO_CATEGORIES, configSections };
|