@ultimat3/core 20.2.1 → 22.0.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/CLAUDE.md +189 -523
- package/README.md +62 -1
- package/package.json +6 -3
- package/src/actor.ts +14 -0
- package/src/address-class.ts +143 -0
- package/src/async-state.ts +19 -0
- package/src/canonical-json.ts +24 -1
- package/src/client-dispatch.ts +163 -0
- package/src/client-flight.ts +22 -3
- package/src/client-paths.ts +79 -0
- package/src/client-problem.ts +94 -0
- package/src/client-scope-error.ts +18 -0
- package/src/client-scope.ts +59 -0
- package/src/client-transport.ts +86 -0
- package/src/config-count.ts +19 -0
- package/src/config-fixes.ts +23 -0
- package/src/config-merge.ts +36 -0
- package/src/config.ts +122 -65
- package/src/conflict-policy.ts +48 -0
- package/src/context.ts +12 -1
- package/src/core-error-codes.ts +78 -0
- package/src/dev-secrets.ts +45 -0
- package/src/error-codes.ts +17 -66
- package/src/error-retry.ts +3 -0
- package/src/exports/error-contract.ts +2 -2
- package/src/exports/secrets.ts +1 -0
- package/src/generation-fence.ts +9 -2
- package/src/host-rules.ts +71 -0
- package/src/image/exif-orientation.ts +40 -0
- package/src/image/probe.ts +13 -1
- package/src/in-process-fetch.ts +39 -0
- package/src/index.ts +80 -30
- package/src/iso-date.ts +5 -0
- package/src/lifecycle-grace.ts +44 -0
- package/src/lifecycle-signals.ts +35 -0
- package/src/lifecycle.ts +44 -36
- package/src/logger.ts +22 -3
- package/src/measurement-actor.ts +52 -0
- package/src/metrics-text.ts +10 -2
- package/src/otlp-metric-exporter.ts +39 -12
- package/src/otlp-span-exporter.ts +38 -15
- package/src/outbound-headers.ts +16 -0
- package/src/outbox-drain.ts +14 -0
- package/src/page-meta.ts +41 -0
- package/src/page.ts +52 -0
- package/src/pending-records.ts +58 -0
- package/src/record-envelope-openapi.ts +41 -0
- package/src/record-envelope.ts +98 -0
- package/src/record-sink.ts +129 -0
- package/src/schema-error-codes.ts +1 -1
- package/src/secrets-errors.ts +1 -1
- package/src/secrets-store.ts +51 -5
- package/src/service.ts +9 -0
- package/src/source-mask.ts +30 -0
- package/src/telemetry.ts +3 -0
- package/src/type-pins.ts +9 -0
- package/src/write-digest.ts +29 -0
- package/src/write-origin.ts +31 -0
- package/src/result.ts +0 -78
package/CLAUDE.md
CHANGED
|
@@ -1,556 +1,222 @@
|
|
|
1
1
|
# @ultimat3/core — agent notes
|
|
2
2
|
|
|
3
|
-
Tier 0. **Imports no `@ultimat3/*` package
|
|
4
|
-
|
|
3
|
+
Tier 0. **Imports no `@ultimat3/*` package except `@ultimat3/schema`** (the declared `core → schema`
|
|
4
|
+
edge; `schema → core` stays forbidden). Everything else depends on this, so a change here is a
|
|
5
|
+
change to every package.
|
|
5
6
|
|
|
6
7
|
| Rule | |
|
|
7
8
|
|---|---|
|
|
8
|
-
| Deps |
|
|
9
|
+
| Deps | `@ultimat3/schema` only (`bun-types` for types) |
|
|
9
10
|
| Errors | subclass `UltimateError`; never `throw new Error` |
|
|
10
11
|
| Values in a message | `renderCauseValue()` / `renderFixLiteral()`; never raw `JSON.stringify`, `String()` or `${…}` on an `unknown` |
|
|
11
|
-
| A value in a `fix:` a shell READS | `renderFixShellArg(value, placeholder)` — `renderFixLiteral`
|
|
12
|
-
| Whether that value TRAVELS | `isFixShellSafe(value)
|
|
13
|
-
| Rendering the 3-line format | nothing to remember — `UltimateError`'s CONSTRUCTOR escapes `code`, `title`, `cause`, `fix` and `docs` with `singleLine()`. Call it yourself only
|
|
12
|
+
| A value in a `fix:` a shell READS | `renderFixShellArg(value, placeholder)` — `renderFixLiteral`'s double quotes leave `$(…)`, `` ` `` and `${…}` live. An ordinary path or URL passes through; anything a shell would read becomes the placeholder |
|
|
13
|
+
| Whether that value TRAVELS | `isFixShellSafe(value)`, the predicate `renderFixShellArg` is built on. A placeholder is not a runnable command, so a `fix:` whose value sits mid-command asks this first and emits PROSE when the answer is no (`@ultimat3/auth`'s `jwks.ts`, `@ultimat3/scraping`'s `profileLocked`) |
|
|
14
|
+
| Rendering the 3-line format | nothing to remember — `UltimateError`'s CONSTRUCTOR escapes `code`, `title`, `cause`, `fix` and `docs` with `singleLine()`. Call it yourself only for a shape this class never built (a `Finding`) |
|
|
14
15
|
| A value a CALLER supplied | `describeValue()` — shape, never content. `renderCauseValue` is safe against throwing, not against leaking |
|
|
15
|
-
| Reading a caught value | `renderThrowable()` / `isThrownError()` / `stringField()`; never `error.message`, `
|
|
16
|
-
| New code | add to `CORE_CODE_TITLES` in `error-codes.ts
|
|
17
|
-
| Where an error points | `ERROR_DOCS_URL` — one constant, never a per-code URL. `docs:` is omitted at
|
|
16
|
+
| Reading a caught value | `renderThrowable()` / `isThrownError()` / `stringField()`; never `error.message`, `instanceof Error` or `typeof error.code === 'string'` |
|
|
17
|
+
| New code | add to `CORE_CODE_TITLES` in `core-error-codes.ts` — a side-effect anchor the barrel bare-imports, so `UltimateError` alone never carries the table |
|
|
18
|
+
| Where an error points | `ERROR_DOCS_URL` — one constant, never a per-code URL. `docs:` is omitted at construction and resolved from the registry |
|
|
18
19
|
| Time | take a `Clock`; `Date.now()` / `new Date()` only inside `clock.ts` |
|
|
19
20
|
| Context | never thread `ctx` as a parameter — `useContext()` |
|
|
20
21
|
| A value ambient across an `await` | `asyncContext<T>(subject)` from `async-context.ts`, in **every** package — never `new AsyncLocalStorage` |
|
|
21
|
-
| Exports |
|
|
22
|
+
| Exports | explicit in `src/index.ts`; no `export *`. ONE subpath, `@ultimat3/core/page` (`src/page.ts`): the page handle, the principal fence and the page's shared names, because any barrel import retains the error registry (~7.6 kB). `page-bundle.test.ts` pins the retained module set and a 1.5 kB ceiling; nothing that constructs an error may join it. `src/exports/` groups three subjects; every name is still written out in `index.ts` |
|
|
22
23
|
| Files | < 200 LOC, 500 hard ceiling, one responsibility, `kebab-case.ts`, test beside source |
|
|
23
|
-
| Type claims | `type-pins.ts`, never a `.test.ts` — `tsconfig.json` excludes tests
|
|
24
|
-
|
|
25
|
-
Deliberate
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
`
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
through a local helper first (`packages/ui/src/components/ErrorState.tsx` builds a `message`
|
|
56
|
-
const, then assigns it).
|
|
57
|
-
|
|
58
|
-
`singleLine` is the escape that keeps the 3-line contract to three lines, and it exists because
|
|
59
|
-
`scripts/error-render.ts` **cannot see this class**. That gate refuses a parameter typed
|
|
60
|
-
`unknown`/`any` reaching a `cause:`; a value that is already a `string` renders without throwing, so
|
|
61
|
-
there is nothing for it to object to — while a newline in one adds a line to a format that is
|
|
62
|
-
line-oriented in the terminal, in CI logs and inside the dev overlay's `<pre>`. Three holes shipped
|
|
63
|
-
in `@ultimat3/auth` under a green check, the worst reachable by an unauthenticated stranger with one
|
|
64
|
-
crafted OIDC token (issue #97).
|
|
65
|
-
|
|
66
|
-
**It is applied in the CONSTRUCTOR, `As of 2026-08-20` — not at the renderers, which is where it
|
|
67
|
-
went first and could not stay.** Escaping at each renderer was six call sites, and six is a number
|
|
68
|
-
that only goes up: a seventh in this repo, and every renderer an APP writes, would each have had to
|
|
69
|
-
remember. `format()` is also not the only reader — an uncaught throw prints `.message`, a log line
|
|
70
|
-
takes `.cause`, `--json` takes `toJSON()` — so a per-renderer escape left three of four doors open.
|
|
71
|
-
One constructor covers all of them, and `singleLine` is idempotent, so a call site that already
|
|
72
|
-
escaped (`@ultimat3/auth` renders `claims.iss` at its source, quotes and all) is unharmed. `format()`
|
|
73
|
-
therefore interpolates the fields bare: a second pass would be a second place that has to be right.
|
|
74
|
-
The four renderers that still call it — `renderErrorLines` in `@ultimat3/http`,
|
|
75
|
-
`renderFrameworkError` in `@ultimat3/mcp`, `renderFinding` / `detailLines` in `@ultimat3/cli` — take
|
|
76
|
-
shapes this class never built (a `Finding`, a catalog entry), which is the one case left.
|
|
77
|
-
|
|
78
|
-
It is not a general sanitiser: a cause is prose and keeps its quotes,
|
|
79
|
-
its backslashes and its percent signs — only the control range is touched. Line breaks are the
|
|
80
|
-
structural half; the rest of C0 and DEL ride along because a terminal reads a raw `\u001b` as an ANSI
|
|
81
|
-
escape, so a cause could repaint the screen or hide the line above it. `@ultimat3/schema` carries a
|
|
82
|
-
deliberate duplicate — `schema -> core` stays forbidden, so that direction cannot be collapsed —
|
|
83
|
-
pinned behaviourally by `single-line-pin.test.ts`, which lives HERE `As of 2026-08-27`, at the tier
|
|
84
|
-
the invariant belongs to, and pins `ERROR_DOCS_URL` and the brand key beside it.
|
|
85
|
-
|
|
86
|
-
**`core -> schema` is a declared edge `As of 2026-08-27`, and FIVE copies went with it.**
|
|
87
|
-
`describeValue`, `charCount`, `CURRENCY_CODE_PATTERN`, `SCHEMA_ERROR_CODES` and `isIanaZoneName`
|
|
88
|
-
were all restated here because both packages are tier 0 and neither could import the other; they
|
|
89
|
-
were held equal by 394 lines of pin test in `@ultimat3/cli`, a TIER-5 package pinning a tier-0
|
|
90
|
-
invariant that no rule required to exist. `describeValue` is the one that made it urgent — it
|
|
91
|
-
prints INSTEAD of a rejected password, so the safety property of the framework's most
|
|
92
|
-
security-sensitive renderer rested on a 63-line behavioural pin at tier 5. `error-render.ts`
|
|
93
|
-
re-exports schema's now, and the four pin files are deleted.
|
|
94
|
-
|
|
95
|
-
The edge cost was MEASURED before it was declared, because axiom 6 makes it a measurement and not
|
|
96
|
-
an argument — `docs/architecture/01-package-map.md` carries the table. Short version: the edge
|
|
97
|
-
alone TRIPLED a core-only browser chunk (6,362 → 19,018 B), because importing schema's barrel with
|
|
98
|
-
no `sideEffects` field forces a bundler to keep every module it reaches; `@ultimat3/schema` now
|
|
99
|
-
declares `sideEffects: false`, which `bun run side-effects` had already measured as true of it, and
|
|
100
|
-
the cost drops to ~1 kB — while `moneyText` from `@ultimat3/ui`, which always carried schema, comes
|
|
101
|
-
out 7.8 kB SMALLER.
|
|
102
|
-
|
|
103
|
-
**A string's length is CODE POINTS, `As of 2026-08-22`**
|
|
104
|
-
— `validators.ts` rejects in that unit and `json-schema.ts` publishes `minLength` in it, so
|
|
105
|
-
`.length` made `t.string.min(3).safeParse('👍a')` say "at least 3 chars, received a string of 3
|
|
106
|
-
characters". The rule it enforces: a `cause` reaches the log index AND the
|
|
107
|
-
HTTP problem document, redaction is by log FIELD key, and a value baked into a message string has
|
|
108
|
-
no key left to redact — so `parseId`/`uuidTimestamp` describe a rejected id and never echo it.
|
|
109
|
-
|
|
110
|
-
`logger.ts` must not import `context.ts`. `context.ts` injects the ids via
|
|
111
|
-
`setLoggerContextFields()`. It **does** import `secret.ts`, one way only: `secret.ts` owns
|
|
112
|
-
`REDACTED` so a `Secret` can render it without importing the logger, and `logger.ts` re-exports
|
|
113
|
-
the constant so there is still one definition and one public path.
|
|
114
|
-
|
|
115
|
-
`ActorFacts` is the app's extension point on `Actor` — module augmentation, the same trick as
|
|
116
|
-
`CtxServices` and `PermissionRegistry`. Core declares the seam and **never a fact**: augmenting
|
|
117
|
-
`ActorFacts` inside the framework would declare that fact for every app. Every fact reads as
|
|
118
|
-
`T | undefined` through `actorFact()` on purpose — an unresolved fact must deny, and a job, a
|
|
119
|
-
test and an MCP token exchange all mint actors that resolved nothing. `type-pins.ts` pins that
|
|
120
|
-
shape against a locally declared sample interface for exactly that reason.
|
|
24
|
+
| Type claims | `type-pins.ts`, never a `.test.ts` — `tsconfig.json` excludes tests |
|
|
25
|
+
|
|
26
|
+
Deliberate cycle (safe — nothing referenced at module evaluation): `errors.ts ⇄ error-codes.ts`. No
|
|
27
|
+
top-level `UltimateError` use in `error-codes.ts`.
|
|
28
|
+
|
|
29
|
+
## Invariants
|
|
30
|
+
|
|
31
|
+
- **`async-context.ts` is the framework's ONE `AsyncLocalStorage`.** Construction is deferred to
|
|
32
|
+
the first `get()`/`run()`, so a browser bundle can evaluate the module; reads degrade to
|
|
33
|
+
`undefined`, writes throw `X_ASYNC_CONTEXT_UNAVAILABLE`. `scripts/async-context-guard.ts` refuses a
|
|
34
|
+
`new AsyncLocalStorage` or an import of the class anywhere else; `scripts/browser-barrel.test.ts`
|
|
35
|
+
covers `await import('node:async_hooks')`.
|
|
36
|
+
- **`error-render.ts` imports nothing** except schema's re-exports (`describeValue`, `charCount`) —
|
|
37
|
+
an error factory that dies formatting its own message is the failure it exists to prevent.
|
|
38
|
+
`scripts/error-render.ts` (`X_ERROR_RENDER_UNSAFE`) cannot see a value laundered through a local
|
|
39
|
+
helper.
|
|
40
|
+
- **`singleLine` keeps the 3-line contract to three lines, applied in the CONSTRUCTOR** so every
|
|
41
|
+
door (`format()`, `.message`, `.cause`, `toJSON()`) is covered once. It touches only C0 controls
|
|
42
|
+
and DEL — a cause keeps its quotes and backslashes. `@ultimat3/schema` carries a deliberate
|
|
43
|
+
duplicate, pinned by `single-line-pin.test.ts` HERE, with `ERROR_DOCS_URL` and the brand key.
|
|
44
|
+
- **`core → schema` is declared, and the five former copies are gone** (`describeValue`,
|
|
45
|
+
`charCount`, `CURRENCY_CODE_PATTERN`, `SCHEMA_ERROR_CODES`, `isIanaZoneName`). Its bundle cost is
|
|
46
|
+
measured in `docs/architecture/01-package-map.md`; it depends on `@ultimat3/schema` keeping
|
|
47
|
+
`sideEffects: false`.
|
|
48
|
+
- **A string's length is CODE POINTS** — `validators.ts` rejects in that unit and
|
|
49
|
+
`json-schema.ts` publishes `minLength` in it. `parseId`/`uuidTimestamp` describe a rejected id and
|
|
50
|
+
never echo it: a value baked into a message has no log field key to redact.
|
|
51
|
+
- `logger.ts` must not import `context.ts` (`context.ts` injects ids via `setLoggerContextFields()`).
|
|
52
|
+
It imports `secret.ts` one way only: `secret.ts` owns `REDACTED`, `logger.ts` re-exports it.
|
|
53
|
+
- **`ActorFacts` is the app's extension point on `Actor`** (module augmentation). Core never declares
|
|
54
|
+
a fact; every fact reads `T | undefined` through `actorFact()` so an unresolved fact denies.
|
|
55
|
+
`type-pins.ts` pins the shape against a local sample.
|
|
121
56
|
|
|
122
57
|
| Concept | Owner | Note |
|
|
123
58
|
|---|---|---|
|
|
124
|
-
| which deploy this is | `environment.ts` (`ULTIMATE_ENV`) | the twin of `ROLE`; never
|
|
59
|
+
| which deploy this is | `environment.ts` (`ULTIMATE_ENV`) | the twin of `ROLE`; never a second env var |
|
|
125
60
|
| what this process does | `roles.ts` (`ROLE`) | |
|
|
126
|
-
| how a route renders, caches offline and hydrates | `route-vocabulary.ts` (`RENDER_MODES`, `OFFLINE_STRATEGIES`, `HYDRATE_STRATEGIES`) |
|
|
127
|
-
| which rungs a cache ladder has | `cache-vocabulary.ts` (`CACHE_TIERS`) |
|
|
128
|
-
| which build of the APP this is | `app-version.ts` (`APP_VERSION`) | one reader, `dev` by default
|
|
129
|
-
| the values | `env.ts` | `checkEnv().values` holds REAL secrets —
|
|
61
|
+
| how a route renders, caches offline and hydrates | `route-vocabulary.ts` (`RENDER_MODES`, `OFFLINE_STRATEGIES`, `HYDRATE_STRATEGIES`) | every union is `(typeof ARRAY)[number]`, pinned in `type-pins.ts`; `scripts/render-modes.test.ts` refuses a second declaration. Re-export it, never restate it |
|
|
62
|
+
| which rungs a cache ladder has | `cache-vocabulary.ts` (`CACHE_TIERS`) | `@ultimat3/cache`'s `TIER_ORDER` IS this array. `isr` is a `RenderMode`, never a tier |
|
|
63
|
+
| which build of the APP this is | `app-version.ts` (`APP_VERSION`) | one reader, `dev` by default |
|
|
64
|
+
| the values | `env.ts` | `checkEnv().values` holds REAL secrets — printing goes through `maskedEnvValues()` |
|
|
130
65
|
| `.env.example` | `env-example.ts` | a projection of the schema, never hand-maintained |
|
|
131
66
|
| loading `.env` | **Bun**, not us | `envFileCandidates()` documents the measured order; there is no `.env.staging` |
|
|
132
|
-
| how long to wait, and whether to wait at all | `backoff.ts` + `retry.ts` | one curve
|
|
133
|
-
| N callers on one key | `single-flight.ts` | identity-checked eviction, optional injected deadline
|
|
67
|
+
| how long to wait, and whether to wait at all | `backoff.ts` + `retry.ts` | one curve, one executor; `jitter` is REQUIRED on a retry policy and defaults to `none` on the arithmetic. `attempt` is 1-based |
|
|
68
|
+
| N callers on one key | `single-flight.ts` | identity-checked eviction, optional injected deadline |
|
|
134
69
|
| how many at once | `flight-gate.ts` | hand-over on release, refusal past `maxQueued`, injectable `overflow:` refusal |
|
|
135
|
-
| whether an answer still applies | `generation-fence.ts` | `X_SUPERSEDED` / `isSuperseded
|
|
136
|
-
| which HTTP statuses are worth repeating | `retryable-status.ts` | `>= 500` plus 408, 409, 425, 429
|
|
137
|
-
| how long this request has left | `request-budget.ts` (`Ctx.deadlineAt`, `REQUEST_TIMEOUT_HEADER`) | `@ultimat3/http`'s `startDeadline` is the one
|
|
138
|
-
| the
|
|
139
|
-
|
|
|
140
|
-
| a
|
|
141
|
-
|
|
|
142
|
-
| the
|
|
70
|
+
| whether an answer still applies | `generation-fence.ts` | `X_SUPERSEDED` / `isSuperseded` |
|
|
71
|
+
| which HTTP statuses are worth repeating | `retryable-status.ts` | `>= 500` plus 408, 409, 425, 429 |
|
|
72
|
+
| how long this request has left | `request-budget.ts` (`Ctx.deadlineAt`, `REQUEST_TIMEOUT_HEADER`) | `@ultimat3/http`'s `startDeadline` is the one writer of the instant; `traceHeaders()` the one writer of the header. A spent budget sends nothing, never `0` |
|
|
73
|
+
| the above, composed into one typed-client call | `client-flight.ts` + `client-wire.ts` | shared by `@ultimat3/action` and `@ultimat3/query` (both tier 3), re-exported by both. Declares no code of its own |
|
|
74
|
+
| the browser's one HTTP function, records envelope, per-tab handle and principal fence | `client-transport.ts`, `client-dispatch.ts`, `client-problem.ts`, `client-paths.ts`, `record-envelope.ts`, `record-sink.ts`, `client-scope.ts` | `pageClient()` is the ONE `globalThis` write (`Symbol.for('ultimate.client')`); the scope's listeners live ON the handle. `clientTransport` never value-imports `createClientFlight` or `traceHeaders()`: trace/budget headers reach it through the page handle's OUTBOUND SLOT (`outbound-headers.ts`). `isSuperseded` answers both `X_SUPERSEDED` and `X_CLIENT_SCOPE_CHANGED`. The fence never `bump()`s a caller's flight. A write never dedupes; a read dedupes only with a caller's `flight`. `pageClient()` reads `<meta name="ultimate-scope">` (`CLIENT_SCOPE_META`) once: content = principal, empty = anonymous (`null`), absent = UNSCOPED (`undefined`, nothing persisted). Byte figures (`As of 2026-09-23`): `clientTransport` 14,405 B, `pageClient` 8,853 B through the barrel, 332 B from its own module; `rpc`'s live in `packages/action/CLAUDE.md`, `queryClient`'s in `packages/query/CLAUDE.md` |
|
|
75
|
+
| a write's public name | `write-digest.ts` (`writeDigest`, `isWriteDigest`, also on `./page`) + `write-origin.ts` (`withWriteOrigin`, `currentWriteOrigin`, `WRITE_ORIGIN_WAL_PREFIX`, server-only) | SHA-256 of an idempotency key, 32 hex; carried action → entity → WAL → realtime `records` frame. A malformed value runs the work unnamed: a label, never a gate |
|
|
76
|
+
| which row survives a conflict | `conflict-policy.ts` (`ConflictPolicy`, `resolveConflict`, `Row`) | read by `action`'s mutator and `realtime`'s rebase |
|
|
77
|
+
| the four shapes of an async region | `async-state.ts` (`AsyncState`) | `realtime` returns it, `ui` renders it. `bun run render-modes` refuses a second status union sharing three members |
|
|
78
|
+
| is this `unknown` a keyed record? | `json-object.ts` (`isJsonObject`) | narrows a shape; does not certify provenance |
|
|
79
|
+
| a value that must not be printed | `secret.ts` | redacted by VALUE; `revealSecret()` is the one, greppable, way out |
|
|
80
|
+
| an `Intl` formatter cache, and the screen in front of it | `intl-cache.ts` (`cachedFormatter`, `canonicalLocale`, `assertLocale`, `MAX_CACHED_FORMATTERS`, `MAX_LOCALE_EXCERPT`) | a locale arrives from a header: refuse a non-tag (`X_LOCALE_INVALID`), key canonically AND bound the cache — never a copy of any of the three. The cause quotes at most `MAX_LOCALE_EXCERPT` (35) code points; the whole tag rides in `meta.locale` |
|
|
81
|
+
| the text direction of a locale | `locale-direction.ts` (`directionOf`, `isRtl`, `Direction`) | re-exported by `@ultimat3/i18n`; lives here so `@ultimat3/ui` need not reach the i18n barrel |
|
|
143
82
|
| the committed encrypted values | `secrets.ts` (envelope) + `secrets-store.ts` (files, `installSecrets`) | plaintext is a flat map of ENV NAMES; there is no `secrets.get()` |
|
|
144
83
|
|
|
145
|
-
|
|
146
|
-
`process.env` before `defineEnv` reads it
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
`
|
|
155
|
-
`
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
`
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
`
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
`
|
|
185
|
-
the
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
`
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
`timing-safe-equal.ts` holds the one constant-time string comparison `@ultimat3/auth` and
|
|
199
|
-
`@ultimat3/storage` both need — core is the lowest tier both can reach, so the shared code lives
|
|
200
|
-
here rather than in either package copying the other's file.
|
|
201
|
-
|
|
202
|
-
`canonical-json.ts` is the same shape for the hash every SHARING key in the framework is taken
|
|
203
|
-
over, `As of 2026-08`. `canonicalJson` is an INJECTIVE canonical form and `fingerprint` is
|
|
204
|
-
SHA-256/16 of it, and three tier-3 packages needed exactly this while none may import another:
|
|
205
|
-
`@ultimat3/action`'s `requestHash` and job dedupe key, `@ultimat3/query`'s `queryHash` (a
|
|
206
|
-
read-cache entry, a cursor scope, a live query id) and `@ultimat3/realtime`'s `qid`. Each kept its
|
|
207
|
-
own copy and the copies had **diverged in a way that leaked**: query's had no `Date` branch, so
|
|
208
|
-
`Object.keys(date)` was `[]`, every date rendered `{}`, and one cache key, one cursor scope and one
|
|
209
|
-
live window answered for every date window of a read — reachable straight off a query string, since
|
|
210
|
-
`coerceQuery` turns a `t.date` member into a real `Date`. Injective is the whole requirement, not a
|
|
211
|
-
formatting preference: every one of those keys decides which of two callers is served the other's
|
|
212
|
-
answer. So `NaN`, `±Infinity` and `-0` are bare tokens the quoting `string` branch cannot spell,
|
|
213
|
-
and a `Date`, a `Map` and a `Set` — the three values with no own enumerable key — are TAGGED. Never
|
|
214
|
-
add a fourth copy, and never make it parseable: `@ultimat3/action`'s `stableStringify` is the
|
|
215
|
-
DOCUMENT form for that (it publishes `openapi.json`), and it is a different function on purpose.
|
|
216
|
-
|
|
217
|
-
`decimal-order.ts` is the third instance of the same rule, over a value rather than a shape.
|
|
218
|
-
`compareDecimalText` is the exact ordering of two decimals however long the digits run — the order
|
|
219
|
-
Postgres gives a `numeric` or an `int8` over the TEXT `@ultimat3/entity`'s `bigint()` and
|
|
220
|
-
`decimal()` hand back, where `String(left) < String(right)` answers `["10","100","2","9"]` for
|
|
221
|
-
`["2","9","10","100"]` and cuts a keyset page where the database does not. It answers **`undefined`**
|
|
222
|
-
when either side is not a plain decimal, and that is the contract, not a convenience: a caller that
|
|
223
|
-
knows the column's declared kind asks (`@ultimat3/entity`'s `compareByKind`), and a caller that does
|
|
224
|
-
NOT — `@ultimat3/query`, whose `OrderKey` is a name and a direction — must never, because Postgres
|
|
225
|
-
orders a `text` column of digits lexically and a comparator guessing would trade one disagreement
|
|
226
|
-
with the SQL it printed for another.
|
|
227
|
-
|
|
228
|
-
`format-bytes.ts` is the same rule at its smallest, `As of 2026-08-22`: one `formatBytes(bytes)`,
|
|
229
|
-
1024-base, `b|kb|mb|gb`, for the byte count an error message carries. `@ultimat3/render` (t4) and
|
|
230
|
-
`@ultimat3/pwa` (t4) each had one and they had diverged — render's stopped at `kb`, so a 5 MiB route
|
|
231
|
-
read `5120kb` in `X_BUDGET_EXCEEDED` and `5mb` in the precache warning about the same bytes, and
|
|
232
|
-
`@ultimat3/cli`'s budget error imported render's. Deliberately NOT
|
|
233
|
-
`@ultimat3/ui`'s `formatBytes(bytes, locale)`, which is a different function and stays: that one is
|
|
234
|
-
`Intl`-formatted and DECIMAL (kB = 1000 B, which is what `Intl`'s unit means), for a human reading a
|
|
235
|
-
file picker, where this one must line up with a bundler's own KiB figures and must not move with the
|
|
236
|
-
reader's locale. **Not mechanised** — no gate refuses a third copy, unlike `render-modes.ts` for the
|
|
237
|
-
route vocabulary; a `formatBytes` reappearing in `packages/*/src` is caught by review only.
|
|
238
|
-
|
|
239
|
-
The **flight layer** is the same rule over control flow rather than over a value, `As of
|
|
240
|
-
2026-08-23`: `backoff.ts`, `retry.ts`, `single-flight.ts`, `flight-gate.ts`, `generation-fence.ts`
|
|
241
|
-
and `retryable-status.ts` — plus `client-flight.ts` and `client-wire.ts`, which compose them into
|
|
242
|
-
one typed-client call and arrived the same way the layer itself did, as two identical copies in two
|
|
243
|
-
packages that may not import each other. Measured before it existed — FOUR backoff curves
|
|
244
|
-
(`@ultimat3/jobs` equal-jitter, `@ultimat3/ai` full-jitter with `Math.random` inline and therefore
|
|
245
|
-
untestable, `@ultimat3/realtime` 0-based-attempt full-jitter, `@ultimat3/db` none at all), FIVE
|
|
246
|
-
retryability tables of which `packages/cache/src/purge-http.ts:19` and
|
|
247
|
-
`packages/mail/src/driver-resend.ts:27` were byte-identical in two packages that cannot import
|
|
248
|
-
each other, FOUR bounded pools and FOUR dedupers. `error-retry.ts` had declared the vocabulary and
|
|
249
|
-
**nothing consulted it before retrying**; `retry()` is the executor it never had, and
|
|
250
|
-
`classifyThrown` / `statedDelayMs` moved down here beside the table they read (`@ultimat3/jobs`'
|
|
251
|
-
`retry-classification.ts` is that pair one tier up and can delegate to it unchanged). Nothing in
|
|
252
|
-
the layer imports anything but this package, nothing runs at import time, and every source of
|
|
253
|
-
non-determinism — the roll, the sleep, the clock, the timer — is injected, because a schedule
|
|
254
|
-
provable only by waiting is a schedule no test pins.
|
|
255
|
-
|
|
256
|
-
**`backoffDelay` REFUSES a non-finite bound, `As of 2026-08-26`, and that is a behaviour change.**
|
|
257
|
-
It used to answer `0`, on the argument that 0 is "wrong loudly". It is not: measured,
|
|
258
|
-
`retry({ attempts: 5, max: NaN })` slept `[0, 0, 0, 0]` and `factor: NaN` slept `[1000, 0, 0, 0]` —
|
|
259
|
-
a retry loop with no wait at all, which is the failure backoff exists to prevent, on the tree's ONE
|
|
260
|
-
curve (`bun run flight-copies`), reaching every retry in the framework. `attempt`, `base`, `max`
|
|
261
|
-
and `factor` each go through `finiteOption` before the clamps, because `Math.max`, `Math.min` and
|
|
262
|
-
`Math.trunc` propagate rather than validate and `Math.min(raw, Infinity)` is `Infinity`. The
|
|
263
|
-
`return 0` below them stays and is still reachable, by exactly one route: `factor ** (step - 1)`
|
|
264
|
-
overflows around attempt 1030 and `0 * Infinity` is `NaN` — a zero base is a caller asking for no
|
|
265
|
-
wait, which is the answer it gets.
|
|
266
|
-
|
|
267
|
-
**`finiteOption` / `finiteCount` (`finite-option.ts`) are the framework's ONE screen for a numeric
|
|
268
|
-
option, `As of 2026-08-26`.** They landed here because `@ultimat3/jobs`, `@ultimat3/realtime` and
|
|
269
|
-
`@ultimat3/query` each held a byte-identical copy; all three were deleted and now import these.
|
|
270
|
-
`finiteCount(subject, option, value, min)` takes `min: 0 | 1` as a DEFAULT PARAMETER rather than
|
|
271
|
-
shipping a third `finitePositive`, because only the caller knows what zero means —
|
|
272
|
-
`requestTimeoutMs: 0` is "no deadline", a pool `max: 0` is a pool nothing can run on.
|
|
273
|
-
`bun run finite-bounds` is the ratchet, and it recognises a repair by the SHAPE OF THE CALL: a
|
|
274
|
-
package screen that does not carry `Finite` in its name is invisible to it, which is why
|
|
275
|
-
`assertFiniteImageQuality`, `assertFiniteOtlpBound` and their siblings in five other packages are
|
|
276
|
-
spelled that way.
|
|
277
|
-
|
|
278
|
-
Two rules that are not preferences. `backoffDelay` clamps to `max` **before** jitter: capping after
|
|
279
|
-
turns `full` into a distribution whose upper half is a single value at `max`, which is the
|
|
280
|
-
correlation jitter exists to remove. `createFlightGate` **hands** its slot to a waiter rather than
|
|
281
|
-
releasing it: decrementing first lets a caller arriving in the same tick past the ceiling while the
|
|
282
|
-
waiter's continuation is still a queued microtask — `@ultimat3/auth`'s `createKdfGate` states the
|
|
283
|
-
same rule, and `overflow:` is the seam that lets it keep throwing its own `X_OVERLOADED` while
|
|
284
|
-
delegating the mechanism. `X_FLIGHT_GATE_OVERLOADED` is core's own code and not auth's borrowed
|
|
285
|
-
one: `X_OVERLOADED` belongs to `@ultimat3/http` (tier 2), and tier 0 may not borrow upward.
|
|
286
|
-
|
|
287
|
-
**`client-flight.ts` INVERTS `retryDecision`'s unclassified default, and that inversion is the
|
|
288
|
-
point of it having a `transient:` parameter at all.** `retry.ts` sends a throw nobody classified
|
|
289
|
-
again until the attempts run out, which is right for a job and wrong for a client: `fetch` rejects
|
|
290
|
-
with a bare `TypeError` for a dead network and a `DOMException` named `AbortError` for the caller's
|
|
291
|
-
own cancellation, and nothing can tell them apart from the class alone — so inheriting the default
|
|
292
|
-
retries a caller's own abort. `@ultimat3/ai` and `@ultimat3/db` each declined the executor outright
|
|
293
|
-
over it; this is the third refusal, and the one that keeps the executor by supplying a predicate.
|
|
294
|
-
Never "simplify" it back to the default.
|
|
295
|
-
|
|
296
|
-
**`ClientFlight` must stay `import type`-only in both packages' `client.ts`, and that erasure is
|
|
297
|
-
the whole tree-shaking story.** `import { rpc } from '@ultimat3/action'` is 14,759 B minified for
|
|
298
|
-
the browser and 20,292 B with `createClientFlight` beside it; `queryClient` is 12,755 B against
|
|
299
|
-
17,912 B. A value import from `client.ts` would put `retry.ts`, `single-flight.ts`,
|
|
300
|
-
`generation-fence.ts`, `flight-gate.ts` and `backoff.ts` into every caller's chunk. Measure through
|
|
301
|
-
the PUBLIC specifier — `Bun.build`, `target: 'browser'`, `minify: true` — and expect ±376 B run to
|
|
302
|
-
run: `Bun.build` 1.4.0 drops this package's `schema-error-codes.ts` from some builds even though
|
|
303
|
-
`sideEffects` names it (issue #273), which is exactly the size of the schema error titles.
|
|
304
|
-
|
|
305
|
-
`mcp-exposure.ts` is the same shape for a declaration rather than an algorithm: `isMcpExposed` is
|
|
306
|
-
the ONE answer to "did this primitive opt into being an MCP tool?", asked by `action`, `query`
|
|
307
|
-
(t3), `mcp`, `ai`, `manifest` (t4) — five packages that cannot import each other, so core is the
|
|
308
|
-
only tier all of them reach. Three spellings of the same question shipped before it (`=== true`,
|
|
309
|
-
`!== false`, `?? true`), which published tools in `openapi.json` and `x.manifest.json` that no
|
|
310
|
-
surface would serve. Never add a second reader: `@ultimat3/cli`'s `mcp-exposure-pin.test.ts` is
|
|
311
|
-
what makes "one predicate" checkable, since no single package below tier 5 can. The one deliberate
|
|
312
|
-
exception is `@ultimat3/admin`'s own catalog, which is opt-OUT and says why in `mcp-tools.ts`.
|
|
313
|
-
|
|
314
|
-
Metrics mirror tracing exactly — `metrics.ts` is to `telemetry.ts` what a counter is to a span:
|
|
315
|
-
always on, no-op exporter by default, driver on the wire. `runtime-metrics.ts` is the only place
|
|
316
|
-
that names a series the deploy chart reads (`http_requests_total`, `connections`, `queue_depth`);
|
|
317
|
-
`SCALING_METRICS` keys them by `ScalingSignal` so `roles.ts` and `docker/helm` cannot drift.
|
|
318
|
-
Core declares the instruments and never calls them for another package's events. `As of 2026-08`
|
|
319
|
-
the recorders are wired, and there is exactly one call site per package — a second one anywhere is
|
|
320
|
-
the bug:
|
|
321
|
-
|
|
322
|
-
| Recorder | The one caller | Why that seam |
|
|
323
|
-
|---|---|---|
|
|
324
|
-
| `recordRequest` | `@ultimat3/http` `pipeline.ts`, the `finally` around `execute` | every request passes it once, error paths included |
|
|
325
|
-
| `recordConnection` | `@ultimat3/realtime` `socket.ts`, `SocketRegistry.add`/`remove` | the only definition of a live connection; close, idle sweep and drain all pass through it, so the gauge cannot leak |
|
|
326
|
-
| `recordQueueDepth` | `@ultimat3/jobs` `worker.ts`, throttled inside `tick()` | the worker is the only process that reads its own queue |
|
|
327
|
-
| `recordJob` | `@ultimat3/jobs` `worker.ts`, the outcome branch inside `tick()` | the loop is where the queue name is in scope; `JOB_OUTCOME_LABELS` maps the four outcomes onto three labels and drops `suspended`, because parking a run is control flow |
|
|
328
|
-
| `recordLeaseLost` | `@ultimat3/jobs` `heartbeat.ts`, once per lease that lapsed | the lease heartbeat is the only thing that knows a renewal stopped landing; deliberately not an `outcome` on `jobs_total`, because nothing failed and nothing finished — the queue simply re-delivered a job this process was still running |
|
|
329
|
-
|
|
330
|
-
Tracing has three parts and they are three files on purpose: `telemetry.ts` builds spans,
|
|
331
|
-
`sampler.ts` decides whether a trace is worth exporting, and `otlp*.ts` puts it on the wire.
|
|
332
|
-
`span.end()` returns early when `traceFlags & 1` is 0 — the bit is obeyed, not merely forwarded,
|
|
333
|
-
which is what stops an exporter from turning 40k rps into 40k rps of spans. `configureTelemetry`
|
|
334
|
-
takes a `Sampler`; the default reads `OTEL_TRACES_SAMPLER*` **at the first span, never at module
|
|
335
|
-
scope** (same call-time rule as `cursor.ts`'s secret). `resetTelemetry()` drops both.
|
|
336
|
-
|
|
337
|
-
**An empty `spanId` means "no inbound decision", and every reader must honour it, `As of
|
|
338
|
-
2026-08-22`.** `currentSpanContext()` synthesises `{ traceId, spanId: '', traceFlags: 1 }` from the
|
|
339
|
-
request context — a trace id this process minted, plus the header it would send onward. Handing
|
|
340
|
-
that to `Sampler.shouldSample` as a parent made `parentBasedRatioSampler` inherit a bit nobody sent,
|
|
341
|
-
so at ratio 0 a root span outside a request exported 0 and one inside exported 1 — and
|
|
342
|
-
`@ultimat3/http`'s `pipeline.ts` is `runWithContext` then `withSpan`, so **every HTTP root span was
|
|
343
|
-
exported at every ratio**. `startSpan` now narrows through `inboundParent()`: the trace id is
|
|
344
|
-
carried, the decision is not. It is the same discriminator `end()` already used to drop a synthetic
|
|
345
|
-
`parentSpanId`.
|
|
346
|
-
|
|
347
|
-
The OTLP exporters are built, not wrapped, and the case is in
|
|
348
|
-
[`docs/idea/18-build-vs-wrap.md`](../../docs/idea/18-build-vs-wrap.md): OTLP/HTTP JSON is `fetch`
|
|
349
|
-
plus `JSON.stringify`, while `@opentelemetry/api` would put a SECOND `Span` type in the framework
|
|
350
|
-
(axiom 1) and `sdk-node` would fight `context.ts` for the AsyncLocalStorage. `otlpTraceRequest` /
|
|
351
|
-
`otlpMetricsRequest` are pure so the wire format is a unit test, exactly as `sentryEnvelope` is.
|
|
352
|
-
**gRPC (`:4317`) is out of scope** — it needs HTTP/2 and protobuf, and both the `:4317` port and a
|
|
353
|
-
non-`http/json` `OTEL_EXPORTER_OTLP_PROTOCOL` throw `X_OTLP_PROTOCOL_UNSUPPORTED` naming `:4318`.
|
|
354
|
-
A boot that must not throw asks `tryOtlpEndpoint(signal)` first.
|
|
355
|
-
|
|
356
|
-
**Three OTLP variables, three codes, `As of 2026-08-22`** — `X_OTLP_ENDPOINT_INVALID`,
|
|
357
|
-
`X_OTLP_HEADERS_INVALID`, `X_OTLP_PROTOCOL_UNSUPPORTED`, one per variable an operator sets. The
|
|
358
|
-
headers one is not a duplicate of the endpoint one: `otlpHeaders` percent-decodes, so `%zz` in
|
|
359
|
-
`OTEL_EXPORTER_OTLP_HEADERS` used to take the process down with a bare `URIError` at exporter
|
|
360
|
-
construction, and raising the ENDPOINT code instead would send the first reader of
|
|
361
|
-
`x errors explain` to inspect a variable that is fine. A title is what an agent reads first, and an
|
|
362
|
-
accurate `cause:` does not rescue one that misdirects. The header **key** is in the cause, the fix
|
|
363
|
-
and `meta`; the **value** is in none of them — it is the collector's credential.
|
|
364
|
-
|
|
365
|
-
`error-reporter.ts` is the same shape a third time: `ErrorReporter`, a no-op default, a memory
|
|
366
|
-
reporter for tests, and a transport on the wire (`error-reporter-sentry.ts`, an optional separate
|
|
367
|
-
export — the DSN is the app's typed env, never a constant here). `reportError` never throws and
|
|
368
|
-
never awaits. **Four packages call it, seven call sites, `As of 2026-08`** — and unlike the
|
|
369
|
-
recorders it is not one per package, because `realtime` has two files that can see a throw:
|
|
370
|
-
|
|
371
|
-
| Package | Call site |
|
|
84
|
+
- **`installSecrets()` is the ONLY path from `secrets.enc.json` to an app value**, landing in
|
|
85
|
+
`process.env` before `defineEnv` reads it. The real environment always wins.
|
|
86
|
+
- **`intl-cache.ts`'s bound and canonical key are two halves of one rule** and live in one file:
|
|
87
|
+
validating and keying are one `getCanonicalLocales` call. Never build an `Intl` formatter on a
|
|
88
|
+
caller string without both.
|
|
89
|
+
- **`secrets-errors.ts`'s command lines are screened**: paths through `renderFixShellArg`; a
|
|
90
|
+
variable name must match `/^[A-Z_][A-Z0-9_]*$/` or the line degrades to prose;
|
|
91
|
+
`X_SECRETS_KEY_MISMATCH`'s command carries no key id (it is read from a file). Its seven codes
|
|
92
|
+
register through `registerErrorCodes()`, so `resetErrorCodes()` drops them — take
|
|
93
|
+
`errorCodeSnapshot()` first. The envelope's `kid` lets *wrong key* and *edited file* be two codes.
|
|
94
|
+
- **`schema-error-codes.ts` registers `@ultimat3/schema`'s codes** (schema cannot call core), and
|
|
95
|
+
derives their retry classification from the same set. It is a `SIDE_EFFECTS_ANCHORS` entry.
|
|
96
|
+
- `timing-safe-equal.ts` is the one constant-time comparison (`@ultimat3/auth`, `@ultimat3/storage`).
|
|
97
|
+
- **`canonical-json.ts`: `canonicalJson` is INJECTIVE and `fingerprint` is SHA-256/16 of it** — the
|
|
98
|
+
hash every sharing key is taken over (`action`'s `requestHash`, `query`'s `queryHash`, `realtime`'s
|
|
99
|
+
`qid`). `NaN`, `±Infinity` and `-0` are bare tokens; `Date`, `Map` and `Set` are TAGGED. Never a
|
|
100
|
+
fourth copy, never parseable (`@ultimat3/action`'s `stableStringify` is the document form).
|
|
101
|
+
- **`decimal-order.ts`'s `compareDecimalText` answers `undefined` for a non-decimal**, and only a
|
|
102
|
+
caller that knows the column's kind may ask (`@ultimat3/entity`'s `compareByKind`) — never
|
|
103
|
+
`@ultimat3/query`, whose `OrderKey` has no kind.
|
|
104
|
+
- **`format-bytes.ts`: one `formatBytes(bytes)`, 1024-base, `b|kb|mb|gb`** for byte counts in error
|
|
105
|
+
messages. Not `@ultimat3/ui`'s locale-formatted decimal one. Not mechanised — review catches a
|
|
106
|
+
third copy.
|
|
107
|
+
- **The flight layer** (`backoff.ts`, `retry.ts`, `single-flight.ts`, `flight-gate.ts`,
|
|
108
|
+
`generation-fence.ts`, `retryable-status.ts`, `client-flight.ts`, `client-wire.ts`) imports
|
|
109
|
+
nothing but this package, runs nothing at import, and injects every source of non-determinism
|
|
110
|
+
(roll, sleep, clock, timer). `classifyThrown` / `statedDelayMs` live beside `error-retry.ts`'s table.
|
|
111
|
+
- **`backoffDelay` REFUSES a non-finite bound**: `attempt`, `base`, `max` and `factor` go through
|
|
112
|
+
`finiteOption` before the clamps. The trailing `return 0` is reachable only by `factor` overflow.
|
|
113
|
+
It clamps to `max` **before** jitter.
|
|
114
|
+
- **`finiteOption` / `finiteCount` (`finite-option.ts`) are the framework's ONE screen for a numeric
|
|
115
|
+
option.** `finiteCount(subject, option, value, min)` takes `min: 0 | 1` because only the caller
|
|
116
|
+
knows what zero means. `bun run finite-bounds` recognises a repair by the call's shape, so a
|
|
117
|
+
package screen carries `Finite` in its name.
|
|
118
|
+
- **`createFlightGate` HANDS its slot to a waiter** rather than releasing it. `X_FLIGHT_GATE_OVERLOADED`
|
|
119
|
+
is core's own code (tier 0 cannot borrow http's `X_OVERLOADED`); `overflow:` lets a caller throw its own.
|
|
120
|
+
- **`client-flight.ts` INVERTS `retryDecision`'s unclassified default** through its `transient:`
|
|
121
|
+
predicate: a bare `TypeError` (dead network) and an `AbortError` (the caller's cancellation) are
|
|
122
|
+
indistinguishable by class. Never "simplify" it back.
|
|
123
|
+
- **`ClientFlight` stays `import type`-only in `action`'s and `query`'s `client.ts`** — a value import
|
|
124
|
+
pulls the whole flight layer into every caller's chunk.
|
|
125
|
+
- **`mcp-exposure.ts`'s `isMcpExposed` is the ONE answer to "did this opt into MCP?"**, read by
|
|
126
|
+
`action`, `query`, `mcp`, `ai`, `manifest`. `@ultimat3/cli`'s `mcp-exposure-pin.test.ts` checks
|
|
127
|
+
it; `@ultimat3/admin`'s own catalog is the one opt-OUT exception (`mcp-tools.ts`).
|
|
128
|
+
|
|
129
|
+
## Metrics, tracing, reporting
|
|
130
|
+
|
|
131
|
+
`metrics.ts` is to `telemetry.ts` what a counter is to a span: always on, no-op exporter by
|
|
132
|
+
default. `runtime-metrics.ts` is the only place that names a series the chart reads
|
|
133
|
+
(`http_requests_total`, `connections`, `queue_depth`), keyed by `ScalingSignal` in
|
|
134
|
+
`SCALING_METRICS`. One call site per package; a second is the bug:
|
|
135
|
+
|
|
136
|
+
| Recorder | The one caller |
|
|
372
137
|
|---|---|
|
|
373
|
-
| `@ultimat3/http`
|
|
374
|
-
| `@ultimat3/
|
|
375
|
-
| `@ultimat3/
|
|
376
|
-
| `@ultimat3/
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
`
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
138
|
+
| `recordRequest` | `@ultimat3/http` `pipeline.ts`, the `finally` around `execute` |
|
|
139
|
+
| `recordConnection` | `@ultimat3/realtime` `socket.ts`, `SocketRegistry.add`/`remove` |
|
|
140
|
+
| `recordQueueDepth` | `@ultimat3/jobs` `worker.ts`, throttled inside `tick()` |
|
|
141
|
+
| `recordJob` | `@ultimat3/jobs` `worker.ts`, the outcome branch inside `tick()` (`JOB_OUTCOME_LABELS` drops `suspended`) |
|
|
142
|
+
| `recordLeaseLost` | `@ultimat3/jobs` `heartbeat.ts`, once per lapsed lease |
|
|
143
|
+
|
|
144
|
+
- Tracing is three files: `telemetry.ts` builds spans, `sampler.ts` decides, `otlp*.ts` exports.
|
|
145
|
+
`span.end()` returns early when `traceFlags & 1` is 0. The default sampler reads
|
|
146
|
+
`OTEL_TRACES_SAMPLER*` at the first span, never at module scope. `resetTelemetry()` drops both.
|
|
147
|
+
- **An empty `spanId` means "no inbound decision"** — `startSpan` narrows through
|
|
148
|
+
`inboundParent()`, carrying the trace id and never the synthesised sampling bit.
|
|
149
|
+
- The OTLP exporters are built, not wrapped ([`docs/idea/18-build-vs-wrap.md`](../../docs/idea/18-build-vs-wrap.md)).
|
|
150
|
+
`otlpTraceRequest` / `otlpMetricsRequest` are pure. **gRPC (`:4317`) is out of scope**:
|
|
151
|
+
`X_OTLP_PROTOCOL_UNSUPPORTED` names `:4318`; a boot that must not throw asks `tryOtlpEndpoint(signal)`.
|
|
152
|
+
- **Three OTLP variables, three codes** — `X_OTLP_ENDPOINT_INVALID`, `X_OTLP_HEADERS_INVALID`,
|
|
153
|
+
`X_OTLP_PROTOCOL_UNSUPPORTED`. A header KEY is in the cause/fix/meta; its VALUE never is.
|
|
154
|
+
- `error-reporter.ts`: `ErrorReporter`, no-op default, memory reporter for tests, Sentry transport
|
|
155
|
+
(`error-reporter-sentry.ts`, optional export). `reportError` never throws, never awaits. Callers:
|
|
156
|
+
`@ultimat3/http` `stages.ts` (`status >= 500`), `@ultimat3/jobs` `execute.ts`, `@ultimat3/realtime`
|
|
157
|
+
`sync-node.ts` and `sync-upgrade.ts`, `@ultimat3/flags` `runtime.ts`. `configureErrorReporting({
|
|
158
|
+
release })` takes the build id `serve.ts` computed. Trace and span resolve as a PAIR.
|
|
159
|
+
- `METRICS_PATH` is served by `@ultimat3/cli`'s `metrics-endpoint.ts` on `METRICS_PORT` (9090), never
|
|
160
|
+
the role's HTTP port; every role opens it.
|
|
161
|
+
|
|
162
|
+
## Lifecycle and readiness
|
|
163
|
+
|
|
164
|
+
- `markReady()` means **bound**; readiness means **usable** — `registerReadinessCheck(name, check)`.
|
|
165
|
+
`/readyz` is ready when the state is `ready` AND every check passes. `HealthReport.registered` is
|
|
166
|
+
the count (an empty registry is still `ready`, deliberately). `readinessChecks()` builds through
|
|
167
|
+
`Object.fromEntries` (a check named `__proto__`). Checks are **synchronous**; liveness ignores
|
|
168
|
+
them. The registration returns its unregister; `readinessCheckCount()` is the leak probe.
|
|
169
|
+
- **`drain()`'s memo is published BEFORE the first hook runs** — a hook may re-enter `drain()`
|
|
170
|
+
(`@ultimat3/http`'s `handle.stop()`), and `settleWithin` invokes hooks synchronously.
|
|
171
|
+
- **The drain deadline is enforced**: `runPhase` races each hook against the time left before
|
|
172
|
+
`deadlineAt` (`lifecycle-deadline.ts`'s `settleWithin`) and ABANDONS an overrun, logging it
|
|
173
|
+
(`X_SHUTDOWN_TIMEOUT`, whose `fix:` names `configureLifecycle({ deadlineMs })`). The budget is the
|
|
174
|
+
WHOLE drain's; `DEFAULT_DEADLINE_MS` (25 s) always applies; it is real monotonic time
|
|
175
|
+
(`systemClock`), never the injected `clock`. `drainDeadlineMs()` is the one decision point.
|
|
176
|
+
`settleWithin` attaches a rejection handler unconditionally.
|
|
177
|
+
- **A readiness grace runs before the `accept` phase** (`lifecycle-grace.ts`): `/readyz` answers 503
|
|
178
|
+
with the socket still open for `drain.readinessGraceMs`, ADDED to `deadlineMs` (a chart's
|
|
179
|
+
`terminationGracePeriodSeconds` must exceed the sum — 5 s + 25 s by default). Unset: 0 in
|
|
180
|
+
development/test, 5000 everywhere else including a process naming no environment (fail closed).
|
|
181
|
+
- `impersonate(actor, reason, fn)` is the ONE door through `withChildContext({ actor })`; it stamps
|
|
182
|
+
`Actor.onBehalfOf` so `actorLabel` renders `service:eng-7→user:cust-99@org-3`. No second path.
|
|
183
|
+
- Every `UltimateError` carries `retry` (`terminal | retryable | retry-after`), **defaulting to
|
|
184
|
+
`terminal`**. `registerErrorRetry()` is the one registration path and refuses to reclassify a
|
|
185
|
+
core code. Two readers: `retryFor(code)` (what to do, fails closed) and
|
|
186
|
+
`declaredErrorRetry(code)` (what was declared, `undefined` otherwise) — a caller deciding whether
|
|
187
|
+
to STOP work in flight (`@ultimat3/jobs`' executor) reads the second. An instance `retry` on an
|
|
188
|
+
unregistered code reads as unclassified.
|
|
189
|
+
- `PRIMITIVE_KINDS` is the executable eight-primitive rule; `PrimitiveKind` derives from it and
|
|
190
|
+
`registrar.test.ts` fails on a ninth. `PRIMITIVE_FACTORIES` lists the factories.
|
|
387
191
|
|
|
388
192
|
```bash
|
|
389
193
|
bun test packages/core/src # from the REPO ROOT, never from packages/core
|
|
390
194
|
bun run typecheck
|
|
391
195
|
```
|
|
392
196
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
run inside `packages/core` loads no preload and 17 tests in `secrets.test.ts` die on
|
|
396
|
-
`expect(...).rejects.toBeUltimateError is not a function`, which reads as this package's failure
|
|
397
|
-
and is the shell's. `.github/workflows/ci.yml`'s `package` job spawns `bun test packages/<pkg>`
|
|
398
|
-
with `cwd` at the root for the same reason (`scripts/coverage-gate.ts`).
|
|
399
|
-
|
|
400
|
-
`markReady()` means **bound**, and readiness means **usable** — two different facts since
|
|
401
|
-
`registerReadinessCheck(name, check)`. `/readyz` is ready only when the state is `ready` AND every
|
|
402
|
-
named check passes, and `HealthReport.checks` carries them by name because "alert on check
|
|
403
|
-
failures by check name" is not writable against a boolean. `HealthReport.registered` carries the
|
|
404
|
-
COUNT beside it, `As of 2026-08-22`: `checks: {}` reads identically for "every check passed" and
|
|
405
|
-
"nobody registered one", and only the second is a `/readyz` meaning no more than "the socket is
|
|
406
|
-
bound". Reported, never enforced — **an empty registry is still `ready`, and `/readyz` still
|
|
407
|
-
answers 200**: `Object.values({}).every(…)` is vacuously true, and that is deliberate so a role
|
|
408
|
-
with no dependency does not have to invent a check to boot. `registered` is the field a caller
|
|
409
|
-
reads to tell "all checks passed" from "there were none".
|
|
410
|
-
|
|
411
|
-
`readinessChecks()` builds its record through `Object.fromEntries`, never by assigning
|
|
412
|
-
`results[name]` — assignment to the one name `__proto__` sets the PROTOTYPE rather than adding a
|
|
413
|
-
key, so a check by that name disappeared from the report and a `failing` one answered 200. Checks are **synchronous** on purpose:
|
|
414
|
-
a probe that awaits a network call turns a slow dependency into a wedged endpoint and a restart
|
|
415
|
-
loop, so the owner of the dependency keeps a boolean fresh and this reads it. Liveness ignores
|
|
416
|
-
them — a database outage that failed `/healthz` would restart the whole fleet into the same
|
|
417
|
-
outage. The registration returns its unregister, same shape and same ownership rule as
|
|
418
|
-
`onShutdown`; `readinessCheckCount()` is the leak probe.
|
|
419
|
-
|
|
420
|
-
**`drain()`'s memo is published BEFORE the first hook runs, `As of 2026-08-22`, and that ordering
|
|
421
|
-
is the whole of the function.** A hook may call back into `drain()` and one does — `handle.stop()`
|
|
422
|
-
in `@ultimat3/http` is `drain('manual')`, and an `accept` hook is exactly where a server stops
|
|
423
|
-
listening — while `settleWithin` invokes a hook SYNCHRONOUSLY. `drainPromise = (async () => …)()`
|
|
424
|
-
had therefore not assigned when the first hook ran: the re-entrant call read `undefined`, started a
|
|
425
|
-
second whole drain and recursed **~4,700 deep** until the stack ran out, every level swallowed by
|
|
426
|
-
`settleWithin` as `shutdown hook failed`. The guard and the registration are now one synchronous
|
|
427
|
-
step (`jobs`' `worker.ts` states the same rule), with the phases in `runDrain`.
|
|
428
|
-
|
|
429
|
-
**The drain deadline is enforced, not merely computed, and there is no unbounded state.**
|
|
430
|
-
`ShutdownReason.deadlineAt` was always handed to every hook and **no hook has ever read it** —
|
|
431
|
-
`jobs`' worker awaits every in-flight job and `driver.close()`, `jobs`' scheduler awaits its round,
|
|
432
|
-
`realtime`'s `listenSyncNode` awaits `node.drain()`'s own grace, `http`'s `server.ts` awaits
|
|
433
|
-
`server.stop()` — so before 2026-08 `configureLifecycle({ deadlineMs: 100 })` bounded nothing:
|
|
434
|
-
measured, one 5-second `accept` hook drained in **5053ms**, state pinned at `draining`. `runPhase`
|
|
435
|
-
now races each hook against the time left before `deadlineAt` (`lifecycle-deadline.ts`'s
|
|
436
|
-
`settleWithin`, split out so the race cannot reach this file's state) and an overrun is
|
|
437
|
-
**ABANDONED** — the drain resolves, the later phases still run, and `installSignalHandlers` reaches
|
|
438
|
-
`process.exit(0)`. Merely logging would leave the kubelet to SIGKILL at the grace period, which is
|
|
439
|
-
the every-deploy job duplicate draining exists to prevent; the abandoned hook keeps running with
|
|
440
|
-
nobody reading it, and that cost is named in the log line rather than hidden. `settleWithin`
|
|
441
|
-
attaches a rejection handler unconditionally: an abandoned hook that rejects later has nobody left
|
|
442
|
-
awaiting it, and the unhandled rejection would kill the process the drain is ending cleanly.
|
|
443
|
-
|
|
444
|
-
Three rules follow and none is optional. **The budget is the WHOLE drain's**, read per hook off
|
|
445
|
-
`deadlineAt`, so a hook that spends it leaves none for the ones behind — the sum of the phases is
|
|
446
|
-
bounded, not each phase separately, which is what `terminationGracePeriodSeconds` means. A budget
|
|
447
|
-
already spent still lets a *synchronous* hook finish (a resolved promise settles on a microtask,
|
|
448
|
-
the 0ms timer on a macrotask), so closing a pool costs nothing it does not already have.
|
|
449
|
-
**`DEFAULT_DEADLINE_MS` (25s) applies whether or not an app sets one** — an opt-in deadline would
|
|
450
|
-
have left `worker`, `scheduler` and `sync` unbounded, i.e. a mechanism claiming more than it
|
|
451
|
-
enforces; abandoned at 25s a worker exits clean, its row's visibility lease lapses and another
|
|
452
|
-
worker re-claims it, which is what at-least-once already promises, and the alternative is the same
|
|
453
|
-
duplicate delivered by SIGKILL with no line naming what overran. The lever is a **larger** value —
|
|
454
|
-
`configureLifecycle({ deadlineMs: 600_000 })` for a 10-minute job — and the `X_SHUTDOWN_TIMEOUT`
|
|
455
|
-
`fix:` says so, because whoever reads it at 3am learns the knob from the line. **The budget is real
|
|
456
|
-
monotonic time (`systemClock`), never the injected `clock`**: `waitForIdle` sleeps on a real
|
|
457
|
-
`setTimeout`, so a frozen clock advanced an hour handed the drain a 16-minute grace period the
|
|
458
|
-
kubelet would never honour. `clock` still owns `uptimeMs`. `drainDeadlineMs()` is the one place the
|
|
459
|
-
budget is decided and the only thing a test can pin — 25s is above any drain a test can wait out.
|
|
460
|
-
|
|
461
|
-
`impersonate(actor, reason, fn)` is the ONE door through `withChildContext({ actor })`. It stamps
|
|
462
|
-
the caller onto the child as `Actor.onBehalfOf`, so `actorLabel` renders
|
|
463
|
-
`service:eng-7→user:cust-99@org-3` and a refund issued during a support session can never read as
|
|
464
|
-
the customer's. The non-blank-reason assert is `@ultimat3/entity`'s `crossTenant()` template
|
|
465
|
-
verbatim — two escapes from the framework's default posture should not look like two things. Do
|
|
466
|
-
not add a second impersonation path.
|
|
467
|
-
|
|
468
|
-
**`ERROR_DOCS_URL` replaced `ERROR_DOCS_BASE` + `errorDocsUrl(code)` `As of 2026-08-23`, and it is
|
|
469
|
-
a breaking change** — it lands in the next major, not in the released line. `https://ultimate.dev/errors/<code>` answered **404**, host included, on every error the
|
|
470
|
-
framework has ever thrown — including the first line a new agent reads (`x --json` →
|
|
471
|
-
`"docs":"https://ultimate.dev/errors/X_CLI_UNKNOWN_COMMAND"`). A dead link in every error is a
|
|
472
|
-
defect under axiom 4, and it is not "not built yet": `wiki/` is the only public documentation
|
|
473
|
-
surface there is. There is no per-code URL because there is no per-code ANCHOR — codes live in
|
|
474
|
-
`wiki/Error-Codes.md` as TABLE ROWS, and a `#X_DB_DRIFT` fragment would be a second dead
|
|
475
|
-
declaration rather than a fix for the first. So the function is gone rather than kept with an
|
|
476
|
-
ignored parameter, and `descriptor()` lost its `code` parameter with it. A package constructing an
|
|
477
|
-
`UltimateError` now OMITS `docs:` entirely and lets the constructor resolve the registered
|
|
478
|
-
descriptor — one URL, one place, instead of the fifteen packages that each spelled the base out.
|
|
479
|
-
|
|
480
|
-
Every `UltimateError` carries `retry` (`terminal | retryable | retry-after`), **defaulting to
|
|
481
|
-
`terminal`** — fail closed, because a client retrying on `status >= 500` hammers `X_DB_DRIFT` and
|
|
482
|
-
`X_TENANCY_UNSCOPED`, which are permanent config faults. `registerErrorRetry()` is the one
|
|
483
|
-
registration path and it refuses to reclassify a core code, the same way `registerErrorStatus`
|
|
484
|
-
refuses to remap one. A new code in any package should be classified beside its declaration.
|
|
485
|
-
|
|
486
|
-
Two readers of that table, and picking the wrong one is a live defect. `retryFor(code)` answers
|
|
487
|
-
*what to do* and fails closed; `declaredErrorRetry(code)` answers *what somebody declared* and is
|
|
488
|
-
`undefined` when nobody did. `retry` on the instance is `init.retry ?? retryFor(code)`, so every
|
|
489
|
-
unclassified error already reads `terminal` — a caller deciding whether to STOP work in flight
|
|
490
|
-
(`@ultimat3/jobs`' executor) must read `declaredErrorRetry`, or it dead-letters attempt 1 of every
|
|
491
|
-
job in every app whose codes nobody classified. An instance `retry: 'terminal'` on an **unregistered**
|
|
492
|
-
code is indistinguishable from the default and is therefore read as unclassified; registering the
|
|
493
|
-
code is the one way to have it honoured.
|
|
197
|
+
The root is not a preference: `bunfig.toml`'s preload installs `@ultimat3/testing`'s matchers, and
|
|
198
|
+
Bun reads `bunfig.toml` from the cwd (`scripts/coverage-gate.ts` runs from the root for the same reason).
|
|
494
199
|
|
|
495
200
|
Gotchas:
|
|
496
201
|
- `exactOptionalPropertyTypes` is on — declare optional fields as `x?: T | undefined`.
|
|
497
202
|
- `noPropertyAccessFromIndexSignature` is on — `ctx.services['mail']`, not `.mail`.
|
|
498
|
-
- `Ctx` carries a string index signature so apps can augment `CtxServices
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
shipped `ctx.storage.ensureBucket()` against a method no package has). Deleting the signature
|
|
502
|
-
is the fix and a breaking change; until then `ctx.services['mail']` is the honest late-bound
|
|
503
|
-
path and a declared augmentation is the only typed one. **Measured 2026-08:** deleting the
|
|
504
|
-
signature compiles core clean on its own, and the augmentation seam survives untouched — an
|
|
505
|
-
augmentation adds NAMED members and `Ctx extends CtxServices` picks them up with no index
|
|
506
|
-
signature at all. What is unmeasured is the rest of the tree: the change is only a build error
|
|
507
|
-
where an app reads an undeclared service, which is the point, but `examples/dummy` ships one
|
|
508
|
-
such read and it would land on the app gate's ratchet. Land it as its own change, alone, with a
|
|
509
|
-
full `bun run verify` — never folded into another branch.
|
|
203
|
+
- `Ctx` carries a string index signature so apps can augment `CtxServices`; the cost is that
|
|
204
|
+
`ctx.anything` type-checks as `unknown`. Deleting it is a breaking change, measured to compile
|
|
205
|
+
core clean; land it alone, with a full `bun run verify`.
|
|
510
206
|
- **`Ctx extends CtxFacts, CtxServices`, and `createContext` holds the framework's ONE irreducible
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
`
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
**One `as Ctx` remains and four alternatives were built and measured before it was kept.**
|
|
528
|
-
`Partial<CtxServices>` removes it and makes `ctx.posts` `PostRepo | undefined` for every app —
|
|
529
|
-
true, and a breaking change to the documented seam. Typing `CtxInit.services` as `CtxServices`
|
|
530
|
-
moves the proof to the caller and breaks every internal `createContext()` in an app's program,
|
|
531
|
-
because an app typechecks this tree's sources through its project references. A generic
|
|
532
|
-
`createContext<S>` returns a context no framework caller can pass where a `Ctx` is wanted. An
|
|
533
|
-
overload whose implementation signature returns the looser type compiles only through
|
|
534
|
-
TypeScript's documented bivariance hole — the same assertion, laundered. The file header carries
|
|
535
|
-
this list; the structural repair is a major and belongs with the index-signature deletion above.
|
|
536
|
-
- Tests that touch the registry, the lifecycle or the listener table must call
|
|
537
|
-
`resetErrorCodes()` / `resetLifecycle()` / `resetListeners()`.
|
|
538
|
-
- `onShutdown`'s return value is the unregister, and every caller that can be started twice owns
|
|
539
|
-
it — `@ultimat3/http`'s `server.ts`, `@ultimat3/realtime`'s `listenSyncNode`, `@ultimat3/jobs`'
|
|
540
|
-
worker, `@ultimat3/cli`'s `hold.ts`. `shutdownHookCount()` is the test-only probe, the same
|
|
541
|
-
shape as `idleWaiterCount()`: a count that climbs across a start/stop cycle is a leak.
|
|
542
|
-
- The error-code registry is process-global and every package fills it once, at import time. A
|
|
543
|
-
test that resets it must take `errorCodeSnapshot()` first and call the returned undo in
|
|
544
|
-
`afterAll` — a reset that is not handed back strips the titles of every package imported before
|
|
545
|
-
that file, and their errors render the humanised fallback (`X_DB_DRIFT: db drift`) for the rest
|
|
546
|
-
of the run. That is a load-order flake: green locally, red on whichever CI ordering hits it.
|
|
547
|
-
- Tests that call `configureCursorSigning()` must restore the previous secret, or call
|
|
548
|
-
`resetCursorSigning()` — the only way back to "unconfigured", which restoring a literal cannot
|
|
549
|
-
express. The secret itself is read inside `sign()`, never at module scope: `openSecrets()` runs
|
|
550
|
-
during boot, so a module-scope read signed a whole process's cursors with the dev key while
|
|
551
|
-
`ULTIMATE_CURSOR_SECRET` was set and `x doctor` merely warned. Same call-time rule as
|
|
552
|
-
`@ultimat3/auth`'s `oauth-cookie.ts` / `oauth-exchange.ts`; new secrets follow it.
|
|
553
|
-
- `PRIMITIVE_KINDS` is the executable copy of the eight-primitive rule — `PrimitiveKind` derives
|
|
554
|
-
from it, so the list and the type cannot drift. A ninth entry fails `registrar.test.ts`, which
|
|
555
|
-
is the point: a new capability arrives as a factory over an existing primitive (`llm()` returns
|
|
556
|
-
an `action`), never as a new kind.
|
|
207
|
+
`as Ctx`.** `CtxFacts` is what the framework sets (and what a `ServiceFactory` receives); an
|
|
208
|
+
augmentation's named members are required of every `Ctx`, and no framework function can obtain
|
|
209
|
+
them. `@ultimat3/http`'s `createRequestContext` composes `createContext()` and has no assertion.
|
|
210
|
+
Four alternatives were measured and refused (listed in the file header); the structural repair is
|
|
211
|
+
a major, alongside the index-signature deletion.
|
|
212
|
+
- Tests that touch the registry, the lifecycle or the listener table call `resetErrorCodes()` /
|
|
213
|
+
`resetLifecycle()` / `resetListeners()` — and a registry reset takes `errorCodeSnapshot()` first
|
|
214
|
+
and restores it in `afterAll`, or every earlier package's titles render humanised for the run.
|
|
215
|
+
- `onShutdown`'s return value is the unregister, owned by every caller that can start twice
|
|
216
|
+
(`@ultimat3/http`'s `server.ts`, `@ultimat3/realtime`'s `listenSyncNode`, `@ultimat3/jobs`' worker,
|
|
217
|
+
`@ultimat3/cli`'s `hold.ts`). `shutdownHookCount()` is the leak probe.
|
|
218
|
+
- Tests calling `configureCursorSigning()` restore the previous secret or call
|
|
219
|
+
`resetCursorSigning()`. The secret is read inside `sign()`, never at module scope; new secrets
|
|
220
|
+
follow the same call-time rule.
|
|
221
|
+
|
|
222
|
+
Why each rule above is shaped the way it is: [`docs/history/core.md`](../../docs/history/core.md).
|