@omega.js/desktop 0.53.0 → 0.54.1
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 +38 -38
- package/dist/cli-run.js +4 -1
- package/dist/cli.js +2 -2
- package/dist/commands/cdp/client.js +1 -1
- package/dist/commands/cdp.js +1 -1
- package/dist/commands/clean.js +2 -3
- package/dist/commands/dev.js +25 -0
- package/dist/commands/lib/ensure-target.js +12 -17
- package/dist/commands/lib/migrate.js +17 -0
- package/dist/commands/logs.js +1 -1
- package/dist/commands/release.js +1 -1
- package/dist/commands/test.js +4 -4
- package/dist/commands/update.js +5 -4
- package/dist/defaults/.github/workflows/build.yml +18 -18
- package/dist/defaults/_.gitignore +0 -2
- package/dist/defaults/_mas/README.md +3 -3
- package/dist/defaults/config/certs/README.md +1 -1
- package/dist/defaults/config/omega.json5 +36 -36
- package/dist/defaults/docs/README.md +3 -3
- package/dist/defaults/gulpfile.js +1 -1
- package/dist/defaults/hooks/build/post.js +1 -1
- package/dist/defaults/hooks/build/pre.js +1 -1
- package/dist/defaults/hooks/notarize/post.js +2 -2
- package/dist/defaults/hooks/release/post.js +1 -1
- package/dist/defaults/hooks/release/pre.js +1 -1
- package/dist/defaults/src/assets/scss/pages/about.scss +1 -1
- package/dist/defaults/src/assets/scss/pages/main.scss +1 -1
- package/dist/defaults/src/assets/scss/pages/settings.scss +1 -1
- package/dist/defaults/src/integrations/context-menu/index.js +11 -11
- package/dist/defaults/src/integrations/menu/index.js +5 -5
- package/dist/defaults/src/integrations/tray/index.js +9 -9
- package/dist/defaults/src/main.js +2 -2
- package/dist/defaults/src/preload.js +1 -1
- package/dist/defaults/test/README.md +3 -3
- package/dist/defaults/test/_init.js +1 -1
- package/dist/gulp/tasks/audit.js +5 -8
- package/dist/lib/restart-manager/index.js +1 -1
- package/dist/lib/restart-manager/install.js +1 -1
- package/dist/lib/restart-manager/protocol.js +1 -1
- package/dist/main.js +4 -3
- package/dist/preload.js +1 -1
- package/dist/test/suites/build/audit.test.js +20 -7
- package/dist/test/suites/build/build-workflow-jobs.test.js +2 -2
- package/dist/test/suites/build/cli.test.js +28 -0
- package/dist/test/suites/build/defaults-em-dash.test.js +22 -0
- package/dist/test/suites/build/defaults-scaffold.test.js +19 -5
- package/dist/test/suites/build/deploy-direct.test.js +7 -5
- package/dist/test/suites/build/deploy-dispatch.test.js +2 -1
- package/dist/test/suites/build/deploy-hook.test.js +4 -2
- package/dist/test/suites/build/dev-verb.test.js +67 -0
- package/dist/test/suites/build/ensure-target.test.js +11 -3
- package/dist/test/suites/build/merge-line-files.test.js +6 -6
- package/dist/test/suites/build/migrate.test.js +29 -0
- package/dist/test/suites/build/project-scripts-deps.test.js +6 -10
- package/dist/test/suites/build/runner-env-write.test.js +73 -0
- package/dist/test/suites/build/runner.test.js +9 -8
- package/dist/test/suites/build/setup-scripts.test.js +27 -0
- package/dist/test/suites/build/validate-config.test.js +13 -2
- package/dist/test/suites/build/verb-logs.test.js +20 -0
- package/dist/test/suites/renderer/window-desktop-surface.test.js +1 -1
- package/dist/utils/build-pipeline.js +4 -4
- package/dist/utils/runner-env.js +13 -28
- package/dist/vendor/config/company.js +46 -14
- package/dist/vendor/config/defaults.js +30 -7
- package/dist/vendor/config/edit.js +25 -3
- package/dist/vendor/config/env-delivery.js +1 -1
- package/dist/vendor/config/env-schema.js +3 -6
- package/dist/vendor/config/env.js +34 -22
- package/dist/vendor/config/index.js +13 -17
- package/dist/vendor/config/load.js +15 -7
- package/dist/vendor/config/repo.js +10 -27
- package/dist/vendor/config/schema-client.js +64 -0
- package/dist/vendor/config/schema-cloud.js +38 -0
- package/dist/vendor/config/schema-manager.js +118 -0
- package/dist/vendor/config/schema-overrides.js +68 -0
- package/dist/vendor/config/schema.js +99 -152
- package/dist/vendor/config/validate.js +97 -77
- package/dist/vendor/devkit/agents-md.js +233 -0
- package/dist/vendor/devkit/attach-log-file.js +15 -1
- package/dist/vendor/devkit/ci-workflows.js +30 -30
- package/dist/vendor/devkit/cli-router.js +13 -7
- package/dist/vendor/devkit/defaults-engine.js +9 -43
- package/dist/vendor/devkit/deploy-snapshot.js +44 -9
- package/dist/vendor/devkit/env-lines.js +183 -0
- package/dist/vendor/devkit/local.js +62 -10
- package/dist/vendor/devkit/lockfile.js +32 -13
- package/dist/vendor/devkit/logger.js +7 -2
- package/dist/vendor/devkit/merge-line-files.js +219 -176
- package/dist/vendor/devkit/omega-bin.js +208 -111
- package/dist/vendor/devkit/preludes/docs-sync.js +52 -0
- package/dist/vendor/devkit/preludes/index.js +1 -0
- package/dist/vendor/devkit/target-picker.js +45 -0
- package/dist/vendor/devkit/test/dashed-files.js +37 -0
- package/dist/vendor/devkit/test/run-verb-under-tee.js +71 -0
- package/dist/vendor/devkit/update.js +15 -15
- package/dist/vendor/devkit/verb-scripts.js +40 -0
- package/dist/vendor/devkit/verbs.js +170 -0
- package/package.json +18 -24
- package/dist/commands/install.js +0 -37
- package/dist/defaults/AGENTS.md +0 -119
- package/dist/defaults/CLAUDE.md +0 -1
- package/dist/vendor/config/env-retired.js +0 -137
- package/dist/vendor/config/retired-keys.js +0 -635
- package/docs/analytics.md +0 -140
- package/docs/app-state.md +0 -92
- package/docs/audit.md +0 -69
- package/docs/auth.md +0 -284
- package/docs/auto-updater.md +0 -243
- package/docs/boot-sequence.md +0 -44
- package/docs/build-system.md +0 -169
- package/docs/cdp-debugging.md +0 -169
- package/docs/common-mistakes.md +0 -21
- package/docs/config-schema.md +0 -120
- package/docs/context-menu.md +0 -112
- package/docs/context.md +0 -81
- package/docs/css.md +0 -84
- package/docs/deep-link.md +0 -186
- package/docs/environment-detection.md +0 -112
- package/docs/fontawesome.md +0 -109
- package/docs/hooks.md +0 -89
- package/docs/icons.md +0 -79
- package/docs/index.md +0 -328
- package/docs/installer-options.md +0 -165
- package/docs/ipc.md +0 -61
- package/docs/lib-modules.md +0 -53
- package/docs/logging.md +0 -227
- package/docs/menu.md +0 -160
- package/docs/releasing.md +0 -239
- package/docs/remote-config.md +0 -118
- package/docs/remote-scripts.md +0 -144
- package/docs/restart-manager.md +0 -144
- package/docs/runner.md +0 -290
- package/docs/sentry.md +0 -97
- package/docs/shared/agent-docs.md +0 -89
- package/docs/shared/analytics.md +0 -612
- package/docs/shared/brands.md +0 -57
- package/docs/shared/breaking-changes.md +0 -917
- package/docs/shared/config.md +0 -1948
- package/docs/shared/deploys.md +0 -341
- package/docs/shared/icons.md +0 -219
- package/docs/shared/local-dev.md +0 -167
- package/docs/shared/logging.md +0 -205
- package/docs/shared/monitoring.md +0 -167
- package/docs/shared/publishing.md +0 -187
- package/docs/shared/rulings.md +0 -34
- package/docs/shared/testing.md +0 -147
- package/docs/shared/theming.md +0 -629
- package/docs/shared/translation.md +0 -342
- package/docs/shared/updates.md +0 -61
- package/docs/signing.md +0 -293
- package/docs/startup.md +0 -142
- package/docs/storage.md +0 -59
- package/docs/templating.md +0 -101
- package/docs/test-boot-layer.md +0 -157
- package/docs/test-framework.md +0 -362
- package/docs/themes.md +0 -149
- package/docs/tooltips.md +0 -99
- package/docs/tray.md +0 -164
- package/docs/usage.md +0 -58
- package/docs/verts.md +0 -62
- package/docs/windows.md +0 -149
package/docs/shared/logging.md
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
# Logging — the tag contract and the file contract
|
|
2
|
-
|
|
3
|
-
Two contracts live here. **What a line says**: every log line carries one identity tag.
|
|
4
|
-
**Where a line lands**: every dev server, build, test runner, emulator and watcher tees
|
|
5
|
-
its whole run to a greppable file ([#197](https://github.com/Omega-JS-Stack/omega/issues/197)).
|
|
6
|
-
The tag contract first, the file contract from [The file tee](#the-file-tee) down.
|
|
7
|
-
|
|
8
|
-
## The tag contract
|
|
9
|
-
|
|
10
|
-
Every log line in the ecosystem carries ONE identity tag: `[@omega.js/<package>:<module>]`.
|
|
11
|
-
The module segment is the file's identity (`push`, `watcher`, `auth:sync` — sub-modules
|
|
12
|
-
join with `:`). Ratified 2026-07-29 ([#12](https://github.com/Omega-JS-Stack/omega/issues/12)).
|
|
13
|
-
|
|
14
|
-
### The debug level (`OMEGA_DEBUG`)
|
|
15
|
-
|
|
16
|
-
`debug` is the ONE opt-in level ([#230](https://github.com/Omega-JS-Stack/omega/issues/230)): a
|
|
17
|
-
backend `ctx.debug(...)` line is dropped whole — console AND the log file — unless
|
|
18
|
-
`OMEGA_DEBUG` is set (truthy STRING semantics, the house's `TEST_EXTENDED_MODE` idiom:
|
|
19
|
-
`OMEGA_DEBUG=0` reads as on; read live per line). Fat payloads belong there: full user
|
|
20
|
-
records, raw webhook bodies. Two related quieting rules from the same issue: boot-time
|
|
21
|
-
environment notes (the TEST banner, the resolved-mode line) are suppressed under the
|
|
22
|
-
emulator (`FUNCTIONS_EMULATOR`) and latched once-per-process everywhere else, and the
|
|
23
|
-
`omega dev` leg output collapses consecutive duplicate lines into one plus a
|
|
24
|
-
`(repeated N×)` note.
|
|
25
|
-
|
|
26
|
-
### PII and secrets
|
|
27
|
-
|
|
28
|
-
**A log line names a user by address or uid, never by serializing the document.** A user
|
|
29
|
-
document carries `api.privateKey`, the consent records, the signup IP and the attribution,
|
|
30
|
-
and a backend line lands in Cloud Logging for the whole retention window — one
|
|
31
|
-
`JSON.stringify(user)` stores a live credential there in plain text
|
|
32
|
-
([#632](https://github.com/Omega-JS-Stack/omega/issues/632)). The rule covers every object
|
|
33
|
-
a caller hands in, not just user docs: log the identifier, not the payload — a payload's
|
|
34
|
-
SHAPE (its top-level key names, a count) is fair game when the line needs it. A secret that
|
|
35
|
-
has to be acknowledged at all renders through backend's `redactSecret()`
|
|
36
|
-
(`***<last 4> (<n> chars)`), and a fat payload worth having while debugging goes to the
|
|
37
|
-
`debug` level above, never to `log`.
|
|
38
|
-
|
|
39
|
-
**A third party's credential is a credential.** An OAuth token exchange response holds the
|
|
40
|
-
access, refresh and id tokens; the identity a provider answers with is the user's PII. Both
|
|
41
|
-
used to ride `ctx.log` on every connection link
|
|
42
|
-
([#641](https://github.com/Omega-JS-Stack/omega/issues/641)) — a line names the provider,
|
|
43
|
-
the uid and whether the exchange succeeded, and nothing else. The same rule reaches an
|
|
44
|
-
HTTP helper's own switches: `wonderful-fetch`'s `log: true` prints its whole configuration,
|
|
45
|
-
headers included, so it never rides a request carrying ANY credential header — an
|
|
46
|
-
`authorization` token, or the `omega-admin-key` an internal call authenticates with
|
|
47
|
-
([#702](https://github.com/Omega-JS-Stack/omega/issues/702)). Backend's
|
|
48
|
-
`test/security/fetch-log-secrets.test.js` scans the source and fails that pairing.
|
|
49
|
-
|
|
50
|
-
### The two surfaces
|
|
51
|
-
|
|
52
|
-
- **Build-time** (CLI, gulp, tests, the manager's services): the devkit logger prints a
|
|
53
|
-
timestamp bracket first — `[HH:MM:SS] [@omega.js/web:watcher] message`. Construction
|
|
54
|
-
stays `new Logger('watcher')`; the package segment derives at construction from the
|
|
55
|
-
constructing file's nearest `package.json` (stack-based, cached, non-throwing —
|
|
56
|
-
fallback `@omega.js/devkit`). Home: `packages/devkit/src/logger.js`.
|
|
57
|
-
- **Runtime** (browser, electron renderer/main, extension): NO timestamp — devtools
|
|
58
|
-
stamps lines. Each runtime surface has its own logger emitting its own package
|
|
59
|
-
segment: client `createLogger()` (`packages/client/src/modules/logger.js`), web
|
|
60
|
-
core/js `createLogger()` (`packages/web/core/js/libs/logger.js`), and the
|
|
61
|
-
desktop/extension `logger-lite` lineage.
|
|
62
|
-
- **Backend** (Cloud Functions) is server-side runtime: in PRODUCTION Cloud Logging
|
|
63
|
-
stamps every entry, so every level emits the tag ALONE —
|
|
64
|
-
`[@omega.js/backend:<module>] <invocation-id>[ <logPrefix>]: message`. Outside
|
|
65
|
-
production (the emulator's `>` prefix carries no time; plain local runs have
|
|
66
|
-
nothing at all) the same `[HH:MM:SS]` bracket the build-time logger prints opens
|
|
67
|
-
the line ([#130](https://github.com/Omega-JS-Stack/omega/issues/130)). The module
|
|
68
|
-
segment is the invocation's function name, which the context already knows
|
|
69
|
-
(`options.functionName || FUNCTION_TARGET`). Home:
|
|
70
|
-
`packages/backend/src/omega/context/logging.js`. A shared backend module
|
|
71
|
-
that logs outside a ctx carries its own file identity.
|
|
72
|
-
|
|
73
|
-
### Markers and exemptions
|
|
74
|
-
|
|
75
|
-
- `[DRY RUN]` survives as a MARKER after the tag, never as an identity tag (casing
|
|
76
|
-
unified; the lowercase form is retired).
|
|
77
|
-
- The manager's reconciliation report is product output, not logging — it stays
|
|
78
|
-
untagged by design (ruling 2026-07-29). That covers ALL its rows: the indented
|
|
79
|
-
`✓ / ~ / +` lines AND the `[DRY RUN]` rows printed through the same report
|
|
80
|
-
(there the marker may open the line, since the report carries no tags at all).
|
|
81
|
-
- Backend's record classifiers (`skip`, `expire`, `authenticated`, `test-mode`, …)
|
|
82
|
-
classify one function's records, not modules. They survive as leading WORDS, never
|
|
83
|
-
brackets (`ctx.log('local: Clearing...')`) — a bracket there would read as a second
|
|
84
|
-
identity tag ([#121](https://github.com/Omega-JS-Stack/omega/issues/121)).
|
|
85
|
-
- Test harnesses and fixtures are exempt; web's `core/js/pages/test/` demo pages are
|
|
86
|
-
NOT (they ship).
|
|
87
|
-
|
|
88
|
-
### Enforcement
|
|
89
|
-
|
|
90
|
-
`scripts/log-tags.test.js` (runs in root `test:packages`) scans `packages/*/src` and
|
|
91
|
-
`packages/web/core/js` for any log call whose message starts with a static bracket tag
|
|
92
|
-
that is not `@omega.js/…` or the dry-run marker. It self-tests its own red path. New
|
|
93
|
-
code uses the surface's shared logger — never a hand-written bracket prefix.
|
|
94
|
-
|
|
95
|
-
## The file tee
|
|
96
|
-
|
|
97
|
-
Nothing an OMEGA surface prints is terminal-only. ONE abstraction does it —
|
|
98
|
-
`packages/devkit/src/attach-log-file.js`, vendored into every framework — and every
|
|
99
|
-
surface attaches it at its entry point.
|
|
100
|
-
|
|
101
|
-
- **Both sinks, always.** A chunk reaches the terminal exactly as written (colors
|
|
102
|
-
intact) and the file with ANSI escapes stripped, so `grep` and `tail -f` read clean.
|
|
103
|
-
- **Synchronous fd writes.** A stream's buffer dies with the process, dropping exactly
|
|
104
|
-
the lines that describe a crash. The per-write syscall buys the crash tail.
|
|
105
|
-
- **Truncate on attach.** A new launch clears the previous run's log — no history, no
|
|
106
|
-
rotation (the ruled retention, see below).
|
|
107
|
-
- **Stackable.** `createTee()` returns an independent tee; an attach captures the
|
|
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; 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.
|
|
112
|
-
- **`createChildLog()` for spawned children.** A child's stdout/stderr never pass
|
|
113
|
-
through this process' writers; the caller mirrors each buffer to the terminal —
|
|
114
|
-
which the verb's own tee then catches, making the verb log a SUPERSET of the child
|
|
115
|
-
file — and hands it to a child log, which adds the one thing the tee has no use for — a
|
|
116
|
-
mid-run `roll()`, requested by touching a reset sentinel, so a days-long emulator
|
|
117
|
-
log can be freshened without restarting it.
|
|
118
|
-
- **CI is a no-op.** Under `CI=true` / `GITHUB_ACTIONS=true` the tee declines: the
|
|
119
|
-
runner captures its own output and no `logs/` is left in the workspace.
|
|
120
|
-
- **A log it cannot open is a lost log, never a lost process.** The tee warns once and
|
|
121
|
-
the run continues untouched.
|
|
122
|
-
|
|
123
|
-
## Where every log lives
|
|
124
|
-
|
|
125
|
-
`<targetRoot>` is a target dir in a brand (`targets/web`, `targets/backend`, …);
|
|
126
|
-
`<brandRoot>` is the brand monorepo root.
|
|
127
|
-
|
|
128
|
-
| Surface | File | What's in it |
|
|
129
|
-
|---|---|---|
|
|
130
|
-
| **Per target** — every framework, same three names | | |
|
|
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) |
|
|
132
|
-
| `omega build` (web, backend) · production gulp build (desktop, extension) | `<targetRoot>/logs/build.log` | the whole production build |
|
|
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)) |
|
|
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) | | |
|
|
136
|
-
| the firebase emulator child | `<targetRoot>/dist/emulator.log` | emulator traffic: function invocations, Firestore/auth calls |
|
|
137
|
-
| the `firebase serve` child | `<targetRoot>/dist/dev.log` | serve output; rolls on each reload |
|
|
138
|
-
| the test runner child | `<targetRoot>/dist/test.log` | the runner's own output under `omega test` |
|
|
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) |
|
|
140
|
-
| `omega logs` | `<targetRoot>/dist/production.log` | the Cloud Logging tail |
|
|
141
|
-
| firebase-tools itself | `<targetRoot>/*-debug.log` | `firestore-debug.log`, `firebase-debug.log`, `ui-debug.log`, … — theirs, never swept by us |
|
|
142
|
-
| **Desktop extras** | | |
|
|
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` |
|
|
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) |
|
|
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` |
|
|
146
|
-
| Windows code-signing | `<targetRoot>/logs/signing.log` | JSONL signing events (local fallback; on CI it lands in the runner home) |
|
|
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 | | |
|
|
148
|
-
| `omega manage` (the service walk) | `<brandRoot>/logs/manage.log` | the whole service walk |
|
|
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) |
|
|
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 |
|
|
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` |
|
|
152
|
-
| `omega update` (the fan-out) | `<brandRoot>/logs/update.log` | which target was checked and what it reported/applied |
|
|
153
|
-
| `omega test` (the fan-out) | `<brandRoot>/logs/test.log` | which target ran which scope, and the aggregate verdict |
|
|
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 |
|
|
155
|
-
| the brand's cross-stack e2e (`@omega.js/devkit/test/e2e-harness`) | `<brandRoot>/test/e2e/.logs/` | `steps.log` (one `PASS` / `FAIL` per step — see below), `emulator.log`, `dev.log`, `page.log` |
|
|
156
|
-
| **This monorepo** | | |
|
|
157
|
-
| every root test lane (`npm test`, `npm run test:packages`, …) | `.temp/logs/<lane>.log` | the lane's own lines plus every child command's output — `test:packages` → `.temp/logs/test-packages.log` |
|
|
158
|
-
| `npm start` (the watcher) | `.temp/logs/watch-all.log` | is it alive, did it respawn, what did it rebuild |
|
|
159
|
-
| every e2e runner's per-step verdicts | `.temp/<lane>/steps.log` | one `PASS` / `FAIL` line per step — see below |
|
|
160
|
-
| every e2e runner's environment | `.temp/<lane>/` | `emulator.log`, `page.log`, `sw.log`, `screenshots/`, the journey's numbered stage logs |
|
|
161
|
-
|
|
162
|
-
The e2e lane dirs are `.temp/flows-e2e/`, `.temp/auth-token-e2e/`, `.temp/verts-e2e/`,
|
|
163
|
-
`.temp/desktop-auth-e2e/`, `.temp/extension-auth-e2e/`, and `.temp/journey/`.
|
|
164
|
-
|
|
165
|
-
### steps.log — which step failed
|
|
166
|
-
|
|
167
|
-
Every e2e runner writes its verdicts incrementally
|
|
168
|
-
(`packages/devkit/src/test/steps-log.js`, re-exported for the root runners as
|
|
169
|
-
`scripts/steps-log.js`, and used by the journey harness and the brand e2e
|
|
170
|
-
harness alike), so a SIGKILLed lane still names the step it died on:
|
|
171
|
-
|
|
172
|
-
```
|
|
173
|
-
PASS the playground emulator boots (hosting :5002, auth :9099)
|
|
174
|
-
FAIL the popup reaches the background SW — timed out after 30s
|
|
175
|
-
FAIL preflight — a playground emulator stack is already running (hosting :5002)
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
`preflight` is the runner dying before or outside any step — the live-stack guard, a
|
|
179
|
-
harness throw on the way up. One line, same shape, so one grep finds every failure:
|
|
180
|
-
|
|
181
|
-
```bash
|
|
182
|
-
grep '^FAIL' .temp/*/steps.log brands/*/e2e/.logs/steps.log
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Retention (ruled 2026-08-05)
|
|
186
|
-
|
|
187
|
-
**Clear on launch, sweep what is stale.** Every log truncates when its surface starts;
|
|
188
|
-
nothing rotates and no history is kept — the question a log answers is "what did the
|
|
189
|
-
run that just happened do?". The backend additionally sweeps its own stale `dist/*.log`
|
|
190
|
-
files and reset sentinels at every verb start, and deliberately leaves firebase-tools'
|
|
191
|
-
`*-debug.log` files alone (a crashed run is diagnosed from them). `logs/` is gitignored
|
|
192
|
-
everywhere, scaffolded brands included.
|
|
193
|
-
|
|
194
|
-
### Grep the logs — do not re-run the process
|
|
195
|
-
|
|
196
|
-
The whole point of the tee is that the answer is already on disk. A running dev server,
|
|
197
|
-
emulator or watcher belongs to the user: never restart one, and never re-run a suite,
|
|
198
|
-
just to see output.
|
|
199
|
-
|
|
200
|
-
```bash
|
|
201
|
-
tail -50 targets/web/logs/dev.log # is the dev server up, what did it last build
|
|
202
|
-
grep -i error targets/backend/dist/emulator.log # what the emulator actually served
|
|
203
|
-
grep '^FAIL' .temp/*/steps.log # which e2e step broke
|
|
204
|
-
tail -100 .temp/logs/test-packages.log # what the last lane printed
|
|
205
|
-
```
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
# Monitoring — the one error-reporting contract
|
|
2
|
-
|
|
3
|
-
`@omega.js/monitoring` is the ONE home of error-reporting policy across every OMEGA target
|
|
4
|
-
([#380](https://github.com/Omega-JS-Stack/omega/issues/380)). Private workspace package, CJS,
|
|
5
|
-
vendored into the frameworks at prepare time — the same deal `@omega.js/analytics` gets.
|
|
6
|
-
|
|
7
|
-
Before it, three surfaces each carried their own copy of "should we report, what release is this,
|
|
8
|
-
what may we send": @omega.js/client's `modules/sentry.js`, @omega.js/backend's hand-rolled
|
|
9
|
-
`Sentry.init`, and @omega.js/desktop's `lib/sentry/` split. They disagreed — on the release format,
|
|
10
|
-
on whether an email rides, on whether a dev build reports. Now they share one core and each host
|
|
11
|
-
supplies only what it alone can know.
|
|
12
|
-
|
|
13
|
-
## The doctrine (Ian, 2026-08-20)
|
|
14
|
-
|
|
15
|
-
- **Server and framework errors ALWAYS report.** Backend routes, cron, event triggers, desktop main,
|
|
16
|
-
extension background: our code, our fault, no filter.
|
|
17
|
-
- **Client-side, only OUR framework code reports.** A web page shares its global with user-land
|
|
18
|
-
scripts, ad and chat widgets, and whatever browser extension a visitor installed. None of it is
|
|
19
|
-
ours to answer for, so a browser event reports only when an `@omega.js` bundle is on its stack.
|
|
20
|
-
- **Capture lives at SEAMS**, never in scattered try/catch: process hooks, the route error handler
|
|
21
|
-
(`ctx.report()`), the event-trigger catch, the SDK's own global handlers.
|
|
22
|
-
- **PII is scrubbed by default.** The uid rides (it is the join key to the account); the email is
|
|
23
|
-
OFF unless a config explicitly opts in.
|
|
24
|
-
- **Everything is OFF when the DSN is unset** — and when it is off, the SDK is never `require()`d
|
|
25
|
-
or imported at all.
|
|
26
|
-
|
|
27
|
-
## Config
|
|
28
|
-
|
|
29
|
-
One block, `monitoring`, in omega.json5, with the monitor named as a KEY under `providers`
|
|
30
|
-
([#425](https://github.com/Omega-JS-Stack/omega/issues/425) — the same shape every role uses). DSN
|
|
31
|
-
presence IS the enable signal at runtime — there is no separate runtime `enabled` flag (the same
|
|
32
|
-
convention every other role section follows: a block's credentials are its switch); the role-level
|
|
33
|
-
`enabled: false` is the manager's skip switch for the provisioning service. Per-surface DSNs are
|
|
34
|
-
`targets.<name>.monitoring.providers.sentry.dsn` overrides.
|
|
35
|
-
|
|
36
|
-
```jsonc
|
|
37
|
-
monitoring: {
|
|
38
|
-
enabled: true, // role-level, optional — false skips the monitoring service
|
|
39
|
-
providers: {
|
|
40
|
-
sentry: { // presence picks the monitor; no entry = none chosen
|
|
41
|
-
org: 'acme', // provisioning only (the manager's monitoring service writes it)
|
|
42
|
-
dsn: 'https://…@o1.ingest.sentry.io/1',
|
|
43
|
-
environment: null, // null = the host's gate names it ('production' / 'development')
|
|
44
|
-
sampleRate: 1, // error events kept, 0..1 — the sampling knob
|
|
45
|
-
tracesSampleRate: 0.1,
|
|
46
|
-
replaysSessionSampleRate: 0, // browser only — session replay is opt-IN (0 = off, and off is the default)
|
|
47
|
-
replaysOnErrorSampleRate: 0, // browser only — replay of an ERRORING session; either rate above 0 loads the integration
|
|
48
|
-
scrubEmail: true, // set false to opt IN to sending emails
|
|
49
|
-
attachScreenshot: false, // desktop only
|
|
50
|
-
bundlePatterns: ['/assets/js/'], // browser only — the URLs that identify our bundles
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Full schema: [config.md](config.md).
|
|
57
|
-
|
|
58
|
-
## The entries
|
|
59
|
-
|
|
60
|
-
| Entry | Who requires it | What it does |
|
|
61
|
-
|---|---|---|
|
|
62
|
-
| `./core` | everything | Pure policy: config resolution, release tag, user scrub, the bundle filter. No `process`, no SDK, no DOM — it is safe inside a page bundle. |
|
|
63
|
-
| `./env` | Node/Electron hosts | The `process.env` half of core's gate seam: the four switches below. |
|
|
64
|
-
| `./node` | `@omega.js/backend` | Boots `@sentry/node` and hands the module back (or `null`). |
|
|
65
|
-
| `./browser` | `@omega.js/client` | Builds the `@sentry/browser` init options — integrations plus the ONE `beforeSend` that decides what leaves a page. |
|
|
66
|
-
| `./main` `./renderer` `./preload` | `@omega.js/desktop` | The `@sentry/electron` per-context wrappers. |
|
|
67
|
-
| `.` | `@omega.js/desktop` | The Electron context delegator: `process.type === 'renderer'` picks the renderer module, anything else the main one. |
|
|
68
|
-
|
|
69
|
-
Core is pure ON PURPOSE. The browser bundle imports it, so an env read there would be a
|
|
70
|
-
ReferenceError on a live page — every environment signal is passed IN as a gate, and `env.js` is
|
|
71
|
-
where the reads live for hosts that have a process. A package test pins this.
|
|
72
|
-
|
|
73
|
-
## The switches
|
|
74
|
-
|
|
75
|
-
In the order they win:
|
|
76
|
-
|
|
77
|
-
| Env var | Effect |
|
|
78
|
-
|---|---|
|
|
79
|
-
| `OMEGA_SENTRY_ENABLED=false` | Kill switch. Nothing reports, ever. |
|
|
80
|
-
| `OMEGA_TEST_RUNNER` | A test run never pollutes a live project. |
|
|
81
|
-
| `OMEGA_SENTRY_FORCE=true` | Report from a non-production run (local proving). |
|
|
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 (`omega.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.
|
|
95
|
-
|
|
96
|
-
## Release tags
|
|
97
|
-
|
|
98
|
-
**ONE format on every target (Ian, 2026-08-20): `<brand.id>@<version>`.** A Sentry release is only
|
|
99
|
-
comparable across the backend, the desktop app and the browser bundles when all three spell it the
|
|
100
|
-
same way, so `core.releaseTag({ id, version })` builds that shape and nothing else — miss either
|
|
101
|
-
half and there is NO tag (a bare version is not a second format). `brand.id` is required config, so
|
|
102
|
-
a missing id is a config hole, not a supported case.
|
|
103
|
-
|
|
104
|
-
Each host supplies its own version identity:
|
|
105
|
-
|
|
106
|
-
| Host | Version source |
|
|
107
|
-
|---|---|
|
|
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). |
|
|
109
|
-
| `@omega.js/desktop` (main + renderer) | `app.getVersion()` — the packaged app version, with `brand.id` read off the resolved config |
|
|
110
|
-
| `@omega.js/client` in `@omega.js/extension` | the extension target's package version, baked into the build blob as `config.version` |
|
|
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` |
|
|
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`) |
|
|
113
|
-
|
|
114
|
-
The client reads `config.version` and falls back to `config.buildTime`. Every host above bakes a
|
|
115
|
-
version now, so the fallback covers only a blob that carries none — a surface embedding the client
|
|
116
|
-
by hand. Nothing tags a build stamp by design.
|
|
117
|
-
|
|
118
|
-
## Where capture happens
|
|
119
|
-
|
|
120
|
-
| Surface | Seam |
|
|
121
|
-
|---|---|
|
|
122
|
-
| Backend routes | `ctx.report()`: 5xx captures automatically, 4xx never ([backend guide](../backend/index.md)) |
|
|
123
|
-
| Backend event triggers | `omega/events.js`: a handler that throws, or a handler file that will not load, goes through the SAME `report()` door. A deliberate block (an `HttpsError`, or an explicit numeric 4xx code) is the trigger's 4xx and never captures; a string `.code` (`ENOENT`, `messaging/invalid-token`) is a system error, not a block, and reports. |
|
|
124
|
-
| Backend payment webhooks | the REFUSAL family's shared seam (`acknowledgeRefusal()` in `events/firestore/payments-webhooks/on-write.js`) captures ONE `warning` per refused event, tagged with the reason and the provider. A refusal is a decision, not a fault, so it never reports as an exception; a processed event reports nothing; and only IDS ride — the refusal stamp's own fields plus the event's ([#550](https://github.com/Omega-JS-Stack/omega/issues/550)). |
|
|
125
|
-
| Desktop main | `@sentry/electron/main`'s own `OnUncaughtException` + `onUnhandledRejection` integrations. Desktop's process handlers log to `runtime.log` and are ADDITIVE — never a second capture. |
|
|
126
|
-
| Desktop renderer | the SDK's window `error` / `unhandledrejection` handlers |
|
|
127
|
-
| Browser (web, extension) | the SDK's global handlers, filtered by `beforeSend` to our bundles |
|
|
128
|
-
|
|
129
|
-
## The browser filter
|
|
130
|
-
|
|
131
|
-
`core.createBundleFilter(patterns)` checks every stack-frame filename an event carries against the
|
|
132
|
-
configured URL fragments. Default: `/assets/js/`, which is where both @omega.js/web and
|
|
133
|
-
@omega.js/extension serve every framework bundle (the client runtime included).
|
|
134
|
-
|
|
135
|
-
An event with **no matching frame is dropped**, and that includes an event with no frames at all — a
|
|
136
|
-
cross-origin `Script error.` is exactly the third-party noise this exists to kill. Deliberate
|
|
137
|
-
`omega.sentry.captureException(…)` calls are unaffected: they are thrown from page bundles, which
|
|
138
|
-
ARE our bundles. The corollary: a deliberate capture must pass an Error CONSTRUCTED in framework
|
|
139
|
-
code — hand it a frameless one (a bare cross-browser `fetch` TypeError, say, which some engines
|
|
140
|
-
raise with no usable stack) and the filter drops it, by design.
|
|
141
|
-
|
|
142
|
-
What survives the filter is scrubbed of credential-bearing auth params: `browser.scrubAuthParams()`
|
|
143
|
-
strips `?authPrivateKey` and `?authCustomToken` from every navigation breadcrumb (`data.from`/`data.to`,
|
|
144
|
-
which the SDK records around `history.replaceState` — including the strip that removes the key) and
|
|
145
|
-
from `event.request.url` (which `httpContext` attaches at capture time). A module constant, not
|
|
146
|
-
config: a page never opts its own credentials back into an event ([#661](https://github.com/Omega-JS-Stack/omega/issues/661)).
|
|
147
|
-
|
|
148
|
-
## How the config reaches a browser
|
|
149
|
-
|
|
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.
|
|
158
|
-
|
|
159
|
-
| Framework | Where the section is baked |
|
|
160
|
-
|---|---|
|
|
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) |
|
|
164
|
-
|
|
165
|
-
The client's `sentry.config` is the PROVIDER block, flat — nothing role-level ever rides into
|
|
166
|
-
`Sentry.init`. Node/Electron hosts pass the whole `monitoring` section instead and core's
|
|
167
|
-
`providerOptions()` reaches in for them: one home for the nesting, on the runtime side.
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
# Publishing — the runbook
|
|
2
|
-
|
|
3
|
-
> The publish-proving checkpoint's script, run for real on 2026-09-09: the seven
|
|
4
|
-
> publishables are on the registry ([#25](https://github.com/Omega-JS-Stack/omega/issues/25)) at 0.50.0, the
|
|
5
|
-
> monorepo's own number (0.1.0 went out first that night and is deprecated: the family
|
|
6
|
-
> carries ONE version, the root package.json's, by ruling 2026-09-10),
|
|
7
|
-
> each with `publishConfig.access: public`, and published is the new normal. The unlatch
|
|
8
|
-
> step below is history; versions move by changesets from here.
|
|
9
|
-
|
|
10
|
-
## What publishes, what never does
|
|
11
|
-
|
|
12
|
-
| Publishes (seven) | Never publishes (vendored at prepare, six) |
|
|
13
|
-
|---|---|
|
|
14
|
-
| `@omega.js/backend`, `@omega.js/client`, `@omega.js/desktop`, `@omega.js/extension`, `@omega.js/manager`, `@omega.js/mcp-router`, `@omega.js/web` | `@omega.js/devkit`, `@omega.js/config`, `@omega.js/account`, `@omega.js/template-kit`, `@omega.js/analytics`, `@omega.js/monitoring` |
|
|
15
|
-
|
|
16
|
-
The private six are `VENDORABLE_PACKAGES` in [packages/devkit/tools/vendor.js](../../packages/devkit/tools/vendor.js),
|
|
17
|
-
which is the SSOT: the vendor tool throws on a dist reference to any `@omega.js`
|
|
18
|
-
package not on that list, so read the count from there rather than from this page.
|
|
19
|
-
|
|
20
|
-
`@omega.js/mcp-router` joined the set (Ian 2026-07-30, [#144](https://github.com/Omega-JS-Stack/omega/issues/144)):
|
|
21
|
-
the manager's vendored Claude plugin declares the router, so the router has to be
|
|
22
|
-
installable beside it — a real dependency, never vendored. It ships no docs tree
|
|
23
|
-
(it is not in the vendor lane's `DOCUMENTED_PACKAGES`) and no `exports` map, so the
|
|
24
|
-
plugin's launcher can deep-resolve `@omega.js/mcp-router/bin/mcp-router.js`.
|
|
25
|
-
|
|
26
|
-
Registry-real internal ranges (everything else is workspace `*`): `@omega.js/client`
|
|
27
|
-
in backend/web/desktop/extension; `@omega.js/backend` and `@omega.js/mcp-router` in
|
|
28
|
-
manager — the EXACT family version (0.50.0 today), not carets, because the family is
|
|
29
|
-
lockstep (below).
|
|
30
|
-
|
|
31
|
-
## Lockstep — the family ships ONE version ([#794](https://github.com/Omega-JS-Stack/omega/issues/794))
|
|
32
|
-
|
|
33
|
-
Changesets carries the seven publishables as a single `fixed` group
|
|
34
|
-
(`.changeset/config.json`; `scripts/changeset-config.test.js` holds that group
|
|
35
|
-
and `release-check.js`'s `PUBLISHABLES` in parity, and release-check itself
|
|
36
|
-
prints a `one version across the family` check). A bump on any one bumps all
|
|
37
|
-
seven to the same number, and packages with no code change republish anyway.
|
|
38
|
-
|
|
39
|
-
Why, in two sentences: ONE number for the family means a brand can never
|
|
40
|
-
install a backend from one release beside a client from another — "everything
|
|
41
|
-
is 0.5.x" is the whole compatibility contract, readable by a human and
|
|
42
|
-
checkable in one comparison. The private internals are VENDORED copies inside
|
|
43
|
-
each framework, so a config-schema change already forces every framework to
|
|
44
|
-
republish; independent numbers only hid that, and let one omega.json5 be
|
|
45
|
-
validated by two validators.
|
|
46
|
-
|
|
47
|
-
`updateInternalDependencies` stays `patch`, so the exact ranges above move
|
|
48
|
-
with the group on every release. In a brand, the same number lands as an exact
|
|
49
|
-
PIN per target ([updates.md](updates.md)) and the manager's boot check refuses
|
|
50
|
-
a brand that ever drifts ([../manager/brand.md](../manager/brand.md)).
|
|
51
|
-
|
|
52
|
-
## What prepare vendors into a tarball
|
|
53
|
-
|
|
54
|
-
Every publishable's prepare `after` hook runs the devkit vendor lane, which
|
|
55
|
-
ships two payloads: the private packages' MODULES into `dist/vendor/`
|
|
56
|
-
(`tools/vendor.js`), and the DOCS into the package root (`tools/vendor-docs.js`
|
|
57
|
-
— the package's guide as `docs/index.md` plus `docs/shared/`, and for
|
|
58
|
-
`@omega.js/manager` also the repo-root map as `docs/AGENTS.md` (links
|
|
59
|
-
retargeted) and `claude-plugin/` + `.claude-plugin/marketplace.json`, the
|
|
60
|
-
plugin a consumer brand enables from its node_modules, `.mcp.json` included —
|
|
61
|
-
its launcher resolves `@omega.js/mcp-router` from the install
|
|
62
|
-
([#144](https://github.com/Omega-JS-Stack/omega/issues/144))). All of it is
|
|
63
|
-
generated and gitignored; `node --test scripts/vendor-docs.test.js` packs the
|
|
64
|
-
six documented packages for real and asserts the tarball listings. A vendor
|
|
65
|
-
failure ABORTS the prepare: every publishable sets `preparePackage.hooks.afterBlocking: true`
|
|
66
|
-
(prepare-package 2.2.0, [#38](https://github.com/Omega-JS-Stack/omega/issues/38)),
|
|
67
|
-
so a tarball can never build missing its vendored internals. Contract:
|
|
68
|
-
[agent-docs.md](agent-docs.md).
|
|
69
|
-
|
|
70
|
-
The MODULE payload is closed over itself ([#739](https://github.com/Omega-JS-Stack/omega/issues/739)): a vendored file's own cross-package requires are rewritten to the sibling vendored copy, and any vendorable only a vendored file needs is vendored too, so the raw-private-reference grep below reads `dist/vendor/` as strictly as the rest of the tree.
|
|
71
|
-
|
|
72
|
-
## The license check ([#320](https://github.com/Omega-JS-Stack/omega/issues/320))
|
|
73
|
-
|
|
74
|
-
A published install needs a LICENSE to enable the payment system and remove the omega
|
|
75
|
-
attribution. A license is a subscription bought on omegajs.dev and the key is that
|
|
76
|
-
account's API key — `OMEGA_LICENSE_KEY` in the brand `.env`, never in omega.json5
|
|
77
|
-
(secret-shape rule). One key per ACCOUNT, unlimited brands for now.
|
|
78
|
-
|
|
79
|
-
**When it runs**: at DEPLOY time, per target, once — `resolveLicenseVerdict({ config, env, transport })`
|
|
80
|
-
in [`@omega.js/devkit/license`](../../packages/devkit/src/license.js). Each target's
|
|
81
|
-
deploy asks and bakes the answer into that artifact; runtime never phones home and the
|
|
82
|
-
payment call stays pure, so a cancelled key holds until the next deploy (accepted — a
|
|
83
|
-
boot or periodic re-check is additive later).
|
|
84
|
-
|
|
85
|
-
| Verdict | When | `payments` | `attribution` |
|
|
86
|
-
|---|---|---|---|
|
|
87
|
-
| licensed | the key resolves an omegajs.dev account whose subscription plan is not the reserved `basic` free sentinel | `live` | `removed` |
|
|
88
|
-
| keyless | no key, an empty key, a `demo-*` project, or a key whose account has no active subscription | `gated` | `shown` |
|
|
89
|
-
|
|
90
|
-
**Loud failure**: a key IS present but the server is unreachable, answers non-2xx, or
|
|
91
|
-
resolves no account → the resolver THROWS. A typo'd or dead key must never quietly ship a
|
|
92
|
-
gated artifact for a brand that is paying.
|
|
93
|
-
|
|
94
|
-
**The keyless-dev carve-out**: a `demo-*` (emulator-only) project short-circuits before
|
|
95
|
-
the network call, key present or not — local dev and the test brands run keyless forever,
|
|
96
|
-
payments in test mode, attribution shown.
|
|
97
|
-
|
|
98
|
-
**The wire**: `GET https://api.omegajs.dev/omega/user?apiKey=<key>&brandId=<brand.id>`.
|
|
99
|
-
The host is a CONSTANT, not config: every other api base in OMEGA derives from a brand's
|
|
100
|
-
own `brand.url` (`api.<host>`) because it belongs to that brand, and this one is the
|
|
101
|
-
PRODUCT's license server — the same host for every brand that installs OMEGA. Server side
|
|
102
|
-
it is the ordinary `GET /user` route resolving an API key (`users` where
|
|
103
|
-
`api.privateKey ==` it), and the plan comes from `@omega.js/account`'s
|
|
104
|
-
`resolveSubscription`, the same derivation the backend and the client run. `brandId` rides
|
|
105
|
-
along and the server ignores it today, so a future per-key brand limit is a server-side
|
|
106
|
-
change alone. `transport` is the injected fetch, so the tests run fully offline.
|
|
107
|
-
|
|
108
|
-
**Delivery**: the env schema declares `OMEGA_LICENSE_KEY` as `ci` for web, desktop and
|
|
109
|
-
extension — their deploys build on Actions runners, so the check runs where the build runs
|
|
110
|
-
— and declares NOTHING for the backend, which deploys straight from the CLI and reads the
|
|
111
|
-
key out of the `.env` cascade in its own process. It never bakes: a baked license key is a
|
|
112
|
-
license key anyone who unpacks the app can copy.
|
|
113
|
-
|
|
114
|
-
**What each target does with the verdict**: the resolver's answer becomes ONE stamp —
|
|
115
|
-
`resolveLicenseStamp({ config, production })` in the same module, which returns
|
|
116
|
-
`{ status: 'licensed'|'keyless', payments, attribution }` and short-circuits to the keyless
|
|
117
|
-
stamp for any build that is not a production one (so a dev build, a watch and a test never
|
|
118
|
-
phone home).
|
|
119
|
-
|
|
120
|
-
| Target | Where the check runs | What the artifact carries | What changes |
|
|
121
|
-
|---|---|---|---|
|
|
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
|
-
| 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`, 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
|
-
|
|
127
|
-
**Honesty system** (spec call 6): plain readable checks, no obfuscation and no artifact
|
|
128
|
-
signing. The legal backing is the Elastic License 2.0 below, whose terms forbid
|
|
129
|
-
circumventing license-key functionality and removing notices.
|
|
130
|
-
|
|
131
|
-
## Pre-flight (any day, no GO needed)
|
|
132
|
-
|
|
133
|
-
1. `npm run release:check` — packs all seven through their real prepare (vendoring
|
|
134
|
-
included), scratch-installs each tarball with local-tarball overrides, resolves,
|
|
135
|
-
and greps the shipped trees for raw private references. **Must be 7/7 green.**
|
|
136
|
-
This is the laptop mirror of CI's pack-smoke.
|
|
137
|
-
2. Full battery green: root `npm test` (packages → corpus → sandbox e2e → journey).
|
|
138
|
-
3. npm auth sanity: `npm whoami` (expected `itwcw2000`). Known parked mystery: `npm org ls omega.js`
|
|
139
|
-
403s on the empty org — the first real publish is the definitive test. If IT 403s,
|
|
140
|
-
the org-owning account must grant publish rights for the `@omega.js` scope.
|
|
141
|
-
4. **License check** ([#349](https://github.com/Omega-JS-Stack/omega/issues/349)): every
|
|
142
|
-
`packages/*/package.json` reads `"license": "Elastic-2.0"`, every publishable carries a
|
|
143
|
-
root `LICENSE` naming the Elastic License 2.0 (npm ships it into the tarball regardless
|
|
144
|
-
of `files`), and no MIT text survives anywhere:
|
|
145
|
-
`grep -rL "Elastic License 2.0" packages/*/LICENSE` must print nothing and
|
|
146
|
-
`grep -ril "MIT License" packages/ --include=LICENSE*` must be empty. A tarball that
|
|
147
|
-
publishes under the wrong license cannot be recalled from the registry, so this runs
|
|
148
|
-
before the unlatch, not after.
|
|
149
|
-
|
|
150
|
-
## Publish day (Ian's GO)
|
|
151
|
-
|
|
152
|
-
1. **Unlatch**: remove `"private": true` from the seven publishables' package.json,
|
|
153
|
-
and ONLY those seven (the six vendorable privates keep theirs forever:
|
|
154
|
-
`VENDORABLE_PACKAGES` in [packages/devkit/tools/vendor.js](../../packages/devkit/tools/vendor.js)
|
|
155
|
-
names them, so the list is never re-typed here).
|
|
156
|
-
2. **Publish** each (changesets is configured lockstep + `access: public`, so the
|
|
157
|
-
seven go out at ONE number; the direct form per package is equally fine):
|
|
158
|
-
`npm publish --workspace=packages/<name>` — order matters only where a dependent
|
|
159
|
-
waits on a dependency: **client and backend before their dependents**
|
|
160
|
-
(web/desktop/extension need client on the registry; manager needs backend and
|
|
161
|
-
mcp-router). Safe order: client → backend → mcp-router → extension → desktop →
|
|
162
|
-
web → manager.
|
|
163
|
-
3. **Verify from the outside**: in an empty temp dir, `npm install @omega.js/web`
|
|
164
|
-
(and one more, e.g. manager) — install + `require.resolve` must succeed with no
|
|
165
|
-
overrides. That is the moment the untested-lane risk is retired.
|
|
166
|
-
4. **Flip the real brand (omega-omega) to registry specs**: from any TARGET root (`targets/web`;
|
|
167
|
-
the manager has no `i` verb), `npx omega i live` — tree-wide `file:` → the EXACT
|
|
168
|
-
family pin + one registry install (`restoreRegistrySpecs` writes the linked copy's version with no
|
|
169
|
-
caret, because the family is lockstep; `omega i local` is the way back for
|
|
170
|
-
local-era work). Commit the brand's manifest+lock change.
|
|
171
|
-
5. **Brand proof**: brand `npm run manage` (manage cycle) + a website build — the brand
|
|
172
|
-
now runs on registry packages; CI-dispatch web deploys become buildable (the
|
|
173
|
-
deploy guard stops refusing once no `file:` specs remain).
|
|
174
|
-
6. Record: CHANGELOG entry + close the tracking issue; re-latch nothing — published is the
|
|
175
|
-
new normal, versions move by changesets from here.
|
|
176
|
-
|
|
177
|
-
## After the first publish
|
|
178
|
-
|
|
179
|
-
- 0.x caret ranges float patch-only (npm's conservative 0.x behavior) — breaking
|
|
180
|
-
changes bump minor and consumers move deliberately. A BRAND floats nothing: the
|
|
181
|
-
manager pins every target exactly, so `omega update` is the one thing that moves
|
|
182
|
-
a brand, and it moves the whole family ([updates.md](updates.md)).
|
|
183
|
-
- **1.0.0 is NEVER published without Ian's explicit word** (ruling 2026-09-10): it is the
|
|
184
|
-
official release, and it waits until OMEGA has survived on its own with Ian's brands.
|
|
185
|
-
Every number below it is free to publish whenever he wants.
|
|
186
|
-
- The publish is also the brand-CI-build unlock: no tarball vendoring exists by
|
|
187
|
-
design — the registry is the lane CI installs from.
|
package/docs/shared/rulings.md
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# Standing rulings
|
|
2
|
-
|
|
3
|
-
Ian's durable rulings, migrated verbatim from PROGRESS.md's Rulings lane when the board retired (v4 migration, 2026-07-27). These bind all work in this monorepo; new rulings land here (or in AGENTS.md when they are architecture). Per-item decisions live on their issues.
|
|
4
|
-
|
|
5
|
-
- Ian 2026-09-09: same-name rule for global + specific values: wherever a site-wide default and a specific override describe the same thing (config default vs page frontmatter, brand vs target, company vs brand, shared vs instance), they share ONE name and ONE shape at every level, the specific level overrides, and a differently named pair is a defect (`seo.index` vs `meta.index` was the case; #564 folds it into `meta.index`). Applies to every config item, never only page-vs-site.
|
|
6
|
-
- Ian 2026-07-21: adblock-safe naming — the ad system speaks vert EVERYWHERE (paths, DOM, collection, API, modules); only ads.txt, Google's own ad* tokens, `advertising` config key say ad
|
|
7
|
-
- Ian 2026-07-21: "DO NOT USE EM DASHES… REWRITE EVERYTHING TO MAKE SENSE WITHUT IT" — site/brand copy never uses em dashes; manual rewrites, not deletions. Operating home with scope + exemptions: docs/shared/theming.md § Copy register (2026-08-15)
|
|
8
|
-
- Ian 2026-07-10: continuous mode — iterate/build/test autonomously, checkpoint after checkpoint; stop only for serious errors or genuinely-Ian decisions
|
|
9
|
-
- Ian 2026-07-19: "I refuse to run a single command — wrap it in npm start, self healing idempotent" — absorb, never hand back; blocked one-offs = framework gaps; wrapped verbs only
|
|
10
|
-
- Ian 2026-07-20: mirrored-implementation rule — same feature, same shape, every framework (cp242 deploys enforced it)
|
|
11
|
-
- Ian 2026-07-20: local-omega-in-production is a SUPPORTED feature — deploys auto-detect linked local frameworks and take local-artifact lanes
|
|
12
|
-
- Ian 2026-07-18: "still use local … until we are fully locked on all decisions that may result in breaking changes" — the local era (file: specs) holds until then
|
|
13
|
-
- Ian 2026-07-19: 0.x until live publishes are proven; 1.0.0 is a later deliberate graduation; zero npm publishes + zero GH releases until GO (old names ship from legacy repos)
|
|
14
|
-
- Ian 2026-07-12: website target = GH Pages ALWAYS; Firebase hosting is the backend/api surface only; GH Pages DNS defaults correct as-is
|
|
15
|
-
- Ian 2026-07-12: FA Pro = local folder route via OMEGA_FONTAWESOME_ROOT (no npm token); skins design within solid/regular/brands
|
|
16
|
-
- Ian 2026-07-11/12: playground = live test infra (Blaze/break/delete); payment+adjacent gated; deploys sparing + named; other brands deploy ONLY on explicit ask
|
|
17
|
-
- Ian 2026-07-13/14: ad-hoc writes to real ITW resources stay gated — manage services' own convergence paths are the sanctioned route (2b mints included)
|
|
18
|
-
- Ian 2026-07-18: credential copies from existing ITW brands SANCTIONED (brand .envs + omega-manager/.brands); new brands mint fresh identity keys; classifier-blocked copies fall to Ian
|
|
19
|
-
- Ian 2026-07-12 (final): NO ITW CLI login — cached browser-OAuth + normal CLI login cover all; never suggest firebase/gcloud login as ITW; npm start = the blessed form *(command superseded 2026-08-13 by [#227](https://github.com/Omega-JS-Stack/omega/issues/227): the blessed reconcile form is now `npm run manage`; `npm start` boots the dev stack)*
|
|
20
|
-
- Ian 2026-07-10: data-shape preservation — Firestore shapes + route semantics presumed good; breaking changes needing migration = flag with plan, don't build
|
|
21
|
-
- Ian 2026-07-06: no backwards compat (dual-read cancelled) — new way only
|
|
22
|
-
- Ian 2026-07-09: legacy repos READ-ONLY (omega-manager, all framework + consumer repos); migrators/verifiers/B5 verify/audit port PINNED; MAM parked
|
|
23
|
-
- Ian 2026-07-20: per-target docs retire in brand context — the brand root is the ONE home (AGENTS.md chain + one README/docs/CHANGELOG)
|
|
24
|
-
- Standing: secrets never in omega.json5 (.env only; config hard-fails); npu never raw npm/npx; explicit `git -C`; commit-and-continue; de-ITW to config = standard scope
|
|
25
|
-
- Standing: checkpoint discipline — survey → design → implement → tests → sandbox/fixture proof → docs → commit; live checks never touch real ITW resources outside sanctioned paths
|
|
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
|
-
- 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 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
|
-
- 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
|
-
- 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
|
-
- 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
|
-
|
|
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
|
-
- 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)
|