@ultimat3/core 29.4.0 → 30.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.
Files changed (89) hide show
  1. package/CLAUDE.md +45 -81
  2. package/README.md +137 -10
  3. package/package.json +19 -3
  4. package/src/address-class.ts +53 -12
  5. package/src/aws-sigv4.ts +104 -8
  6. package/src/breaker.ts +177 -0
  7. package/src/client-dispatch.ts +76 -17
  8. package/src/client-flight.ts +4 -4
  9. package/src/client-paths-pins.ts +92 -0
  10. package/src/client-problem.ts +25 -1
  11. package/src/client-scope.ts +3 -1
  12. package/src/client-stream.ts +106 -0
  13. package/src/client-transport.ts +16 -2
  14. package/src/config-assets.ts +64 -0
  15. package/src/config-client-errors.ts +132 -0
  16. package/src/config-defaults.ts +18 -4
  17. package/src/config-failure-capture.ts +70 -0
  18. package/src/config-health.ts +8 -0
  19. package/src/config-islands.ts +1 -1
  20. package/src/config-keys.ts +2 -0
  21. package/src/config-site.ts +16 -0
  22. package/src/config-time.ts +40 -0
  23. package/src/config.ts +37 -26
  24. package/src/context.ts +92 -10
  25. package/src/core-error-codes.ts +19 -0
  26. package/src/cursor.ts +7 -3
  27. package/src/deadline-signal.ts +57 -0
  28. package/src/declared-errors-openapi.ts +70 -0
  29. package/src/declared-errors-scan.ts +79 -0
  30. package/src/declared-errors.ts +185 -0
  31. package/src/define-error.ts +200 -0
  32. package/src/deprecation.ts +14 -3
  33. package/src/drain-deadline.ts +22 -0
  34. package/src/env.ts +8 -3
  35. package/src/error-fingerprint.ts +95 -0
  36. package/src/error-reporter-chain.ts +45 -0
  37. package/src/error-reporter-sentry.ts +4 -0
  38. package/src/error-reporter.ts +14 -1
  39. package/src/error-status-declared.ts +82 -0
  40. package/src/exercise-errors.ts +41 -0
  41. package/src/exercise-run.ts +176 -0
  42. package/src/exports/error-contract.ts +7 -0
  43. package/src/exports/observability.ts +26 -0
  44. package/src/failure-capture-flush.ts +93 -0
  45. package/src/failure-capture-mask.ts +54 -0
  46. package/src/failure-capture.ts +205 -0
  47. package/src/fill-wire.ts +30 -0
  48. package/src/finite-option.ts +7 -0
  49. package/src/health-disclosure.ts +2 -2
  50. package/src/hmac.ts +47 -0
  51. package/src/index.ts +172 -9
  52. package/src/json-storable.ts +21 -0
  53. package/src/keyed-fingerprint.ts +3 -7
  54. package/src/lifecycle.ts +5 -1
  55. package/src/logger.ts +1 -1
  56. package/src/otlp-metric-exporter.ts +7 -1
  57. package/src/otlp-post.ts +147 -0
  58. package/src/otlp-span-exporter.ts +7 -1
  59. package/src/otlp.ts +4 -37
  60. package/src/outbound-attempt.ts +235 -0
  61. package/src/outbound-dial.ts +103 -0
  62. package/src/outbound-errors.ts +193 -0
  63. package/src/outbound-hops.ts +135 -0
  64. package/src/outbound-read.ts +103 -0
  65. package/src/outbound-subpath.ts +26 -0
  66. package/src/outbound-types.ts +108 -0
  67. package/src/outbound.ts +223 -0
  68. package/src/page-meta.ts +8 -0
  69. package/src/page.ts +9 -0
  70. package/src/record-envelope-openapi.ts +6 -0
  71. package/src/record-envelope.ts +33 -9
  72. package/src/record-sink.ts +13 -0
  73. package/src/redis-client.ts +78 -0
  74. package/src/registrar.ts +11 -0
  75. package/src/render-node.ts +13 -0
  76. package/src/render-nodes.ts +137 -0
  77. package/src/retry-loop.ts +197 -0
  78. package/src/retry.ts +47 -145
  79. package/src/roles.ts +2 -2
  80. package/src/route-path-merge.ts +55 -0
  81. package/src/route-path-template.ts +124 -0
  82. package/src/runtime-metrics.ts +16 -1
  83. package/src/same-origin.ts +18 -2
  84. package/src/session-lost.ts +115 -0
  85. package/src/single-flight.ts +75 -40
  86. package/src/source-mask.ts +36 -2
  87. package/src/tool-description.ts +29 -0
  88. package/src/visible-interval.ts +153 -0
  89. package/src/webhook-signature.ts +9 -11
package/CLAUDE.md CHANGED
@@ -7,7 +7,7 @@ change to every package.
7
7
  | Rule | |
8
8
  |---|---|
9
9
  | Deps | `@ultimat3/schema` only (`bun-types`: types) |
10
- | Errors | subclass `UltimateError`; never `throw new Error` |
10
+ | Errors | never `throw new Error`. A FRAMEWORK code: `bun run new-error-code` (a class, `CORE_CODE_TITLES` or the package's `errors.ts`, a `--status`/`--off-socket` decision, a wiki row). An APP code: `defineError()` (`define-error.ts`), which registers title, status and retry in one call and needs no wiki row; its own module, so an `UltimateError`-only chunk never retains it (`define-error-bytes.test.ts`) |
11
11
  | Values in a message | `renderCauseValue()` / `renderFixLiteral()`; never raw `JSON.stringify`, `String()` or `${…}` on an `unknown` |
12
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
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`) |
@@ -19,7 +19,7 @@ change to every package.
19
19
  | Time | take a `Clock`; `Date.now()` / `new Date()` only inside `clock.ts` |
20
20
  | Context | never thread `ctx` as a parameter — `useContext()` |
21
21
  | A value ambient across an `await` | `asyncContext<T>(subject)` from `async-context.ts`, in **every** package — never `new AsyncLocalStorage` |
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
+ | Exports | explicit in `src/index.ts`; no `export *`. FIVE public subpaths (`./page`, `./outbound`, `./redis`, `./render-node`, `./render-nodes`), one INTERNAL (`./internal/error-status`); nothing that constructs an error joins `./page` (`page-bundle.test.ts`, 1.5 kB). Full rule: `docs/history/core.md` |
23
23
  | Files | < 200 LOC, 500 hard ceiling, one responsibility, `kebab-case.ts`, test beside source |
24
24
  | Type claims | `type-pins.ts`, never a `.test.ts` — `tsconfig.json` excludes tests |
25
25
 
@@ -59,23 +59,28 @@ top-level `UltimateError` use in `error-codes.ts`.
59
59
  | Concept | Owner | Note |
60
60
  |---|---|---|
61
61
  | which deploy this is | `environment.ts` (`ULTIMATE_ENV`) | the twin of `ROLE`; never a second env var |
62
- | one-home helpers | `store-mode` `html-escape` `cookie` `fnv1a` `pg-executor` `deprecation` `aws-sigv4` | never copied (`X_HELPER_COPY`) |
62
+ | one-home helpers | `store-mode` `html-escape` `cookie` `fnv1a` `pg-executor` `deprecation` `aws-sigv4` | never copied (`X_HELPER_COPY`). Full rule: `docs/history/core.md` |
63
+ | the ONE keyed hash | `hmac.ts` (`hmac(alg, key, data, encoding?)`) | `node:crypto`'s `createHmac`: a keyed `Bun.CryptoHasher` throws a stale failed-EC-import error (Bun 1.4.4). `bun run keyed-hasher` (`X_KEYED_HASHER`). Full rule: `docs/history/core.md` |
63
64
  | what this process does | `roles.ts` (`ROLE`) | |
64
65
  | 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 |
65
- | which of two route patterns wins a pathname | `route-rank.ts` (`routeRank`) | the request router's order as one integer: segment by segment, literal 3 > `:param` 2 > `*catch-all` 1, ENDED 4, packed base 5 over 22 segments. Read by `@ultimat3/render`'s `compilePattern` and `@ultimat3/pwa`'s rule order — both tier 4, so the one copy lives here. `@ultimat3/http`'s trie encodes the same order by its walk, not by this number. Never a sum: 100/10/1 ranked `/:a/b/c` above `/a/:x/:y` |
66
+ | which of two route patterns wins a pathname | `route-rank.ts` (`routeRank`) | the request router's order as one integer: segment by segment, literal 3 > `:param` 2 > `*catch-all` 1, ENDED 4, packed base 5 over 22 segments. Full rule: `docs/history/core.md` |
67
+ | an `http.path` template (`/orders/:id`) | `route-path-template.ts` (pure, also on `./page`) + `route-path-merge.ts` (`mergePathParams`, `X_HTTP_PATH_INPUT_CONFLICT`) | `action` and `query` both pin one and share a tier; never a copy in either |
68
+ | `errors:` | `declared-errors.ts`, `-openapi.ts`, `-scan.ts` | ONE copy for `action` and `query`. The HTTP status is passed in (`ErrorStatusOf`): http is above core. The scan is test-time only |
69
+ | a session's loss, an island's poll | `session-lost.ts` (`noteRefusal`, called by `client-dispatch.ts`; a cell on the page handle, cleared by `rescope()`), `visible-interval.ts` (the ONE poll an island takes) | both on `./page`, pinned by `page-bundle.test.ts` |
66
70
  | which rungs a cache ladder has | `cache-vocabulary.ts` (`CACHE_TIERS`) | `@ultimat3/cache`'s read order, imported (no `TIER_ORDER` alias). `isr` is a `RenderMode`, never a tier |
67
71
  | which build of the APP this is | `app-version.ts` (`APP_VERSION`) | one reader, `dev` by default |
68
72
  | the values | `env.ts` | `checkEnv().values` holds REAL secrets — printing goes through `maskedEnvValues()` |
69
73
  | `.env.example` | `env-example.ts` | a projection of the schema, never hand-maintained |
70
74
  | loading `.env` | **Bun**, not us | `envFileCandidates()` documents the measured order; there is no `.env.staging` |
71
- | 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 |
72
- | N callers on one key | `single-flight.ts` | identity-checked eviction, optional injected deadline |
75
+ | how long to wait, and whether to wait at all | `backoff.ts` + `retry-loop.ts` + `retry.ts` | one curve, one loop (no context, for `client-flight.ts`), one executor over it that reads the ambient signal and deadline: the ONE place a loop meets its caller's lifetime, `runToCompletion` the one way out; `jitter` is REQUIRED on a retry policy and defaults to `none` on the arithmetic. `attempt` is 1-based |
76
+ | N callers on one key | `single-flight.ts` | identity-checked eviction, optional injected deadline, optional injected `signal`: a live joiner re-leads after its leader's abort. Reads no context |
73
77
  | how many at once | `flight-gate.ts` | hand-over on release, refusal past `maxQueued`, injectable `overflow:` refusal |
74
78
  | whether an answer still applies | `generation-fence.ts` | `X_SUPERSEDED` / `isSuperseded` |
75
79
  | which HTTP statuses are worth repeating | `retryable-status.ts` | `>= 500` plus 408, 409, 425, 429 |
76
80
  | 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` |
77
81
  | 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. A gate slot per ATTEMPT; the wait holds none, ends on `bump()` or the caller's abort |
78
- | the browser's one HTTP function, records envelope, per-tab handle and principal fence | `client-transport.ts`, `client-dispatch.ts`, `client-problem.ts`, `client-retry-after.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 `clientFlight` 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). `actionPath(name)` with no `style` reads the document's `<meta name="ultimate-path-style">` (`renderedActionPathStyle()`; `CLIENT_PATH_STYLE_META` in `page-meta.ts`) and falls back to `'resource'`. A refusal's `Retry-After` and body `title` are read HERE (`client-retry-after.ts`, `remoteTitleOf`). Bytes: `page-bundle.test.ts`; `rpc`'s and `queryClient`'s in `action`'s and `query`'s CLAUDE.md |
82
+ | a stream-declaring action, read in the browser | `client-stream.ts` | `clientStream`: `POST` with `accept: text/event-stream` through `client-dispatch.ts`'s `dispatchStream` (the ONE browser `fetch`; body handed back unread), never `EventSource` (cannot POST, skips the credentials rule); `clientTransport`'s credentials, headers, caller's signal, session fence and problem decode; a `chunk` frame yields, `done` returns, `error` throws its problem at its own status. A JSON answer is `clientTransport`'s `settleAnswer` (envelope, records, dates), so `stream()` and `call()` agree. Never retried |
83
+ | the browser's one HTTP function, records envelope, per-tab handle and principal fence | `client-transport.ts`, `client-dispatch.ts`, `client-problem.ts`, `client-retry-after.ts`, `client-paths.ts`, `record-envelope.ts`, `record-sink.ts`, `client-scope.ts` | `pageClient()` is the ONE `globalThis` write (`Symbol.for('ultimate.client')`); `clientTransport` never value-imports `clientFlight` or `traceHeaders()` (the OUTBOUND SLOT, `outbound-headers.ts`). A write never dedupes. Full rule: `docs/history/core.md` |
79
84
  | 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 |
80
85
  | which row survives a conflict | `conflict-policy.ts` (`ConflictPolicy`, `resolveConflict`, `Row`) | read by `action`'s mutator and `realtime`'s rebase |
81
86
  | where a visitor's light/dark choice is stored | `theme-storage.ts` (`THEME_STORAGE_KEY`, also on `./page`) | render's boot script reads it, ui's toggle writes it — both tier 4, so the one literal lives here. Persisted in browsers: never respelled |
@@ -85,32 +90,23 @@ top-level `UltimateError` use in `error-codes.ts`.
85
90
  | may a caller read this 5xx `cause`? | `public-cause.ts` (`hasPublicCause`) | one table for http, mcp, ai. `registerPublicCause` is `@ultimat3/http`'s `registerProblemMeta` writing it — never an app's door |
86
91
  | is this field a credential? | `logger.ts` (`isRedactedKey`) | exact keys + `CREDENTIAL_NAME`; a bare `token` suffix is NOT one (`idempotencyToken`, `maxTokens`). Log line, monitor envelope and `action`'s audit ask it |
87
92
  | a value that must not be printed | `secret.ts` | redacted by VALUE; `revealSecret()` is the one, greppable, way out |
88
- | 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` |
93
+ | 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. |
89
94
  | the text direction of a locale | `locale-direction.ts` (`directionOf`, `isRtl`, `Direction`) | import from here, never `@ultimat3/i18n`; here so `@ultimat3/ui` skips the i18n barrel |
90
95
  | 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()` |
91
96
  | ONE sealed value | `seal.ts` (`seal`, `open`, `openText`, `sealAll`) + `seal-keys.ts` (the ring) + `seal-errors.ts` | the framework's one AES call above the envelope: `entity`'s sealed column and `scraping`'s stored session call it, never WebCrypto. `purpose` is required and is AAD |
97
+ | one outbound HTTP call | `outbound.ts` + `outbound-attempt.ts` / `-hops.ts` / `-read.ts` / `-dial.ts` / `-errors.ts` / `-types.ts`, entry `outbound-subpath.ts` | never on the barrel (`outbound-subpath.test.ts`). `retry()` owns the clamp to `ctx`, so no second clamp. Its ten codes register their retry class in `outbound-errors.ts`, NOT `error-retry.ts`'s table, which rides every page. `screenDial` holds the framework's one `Bun.dns.lookup` |
98
+ | is a dependency down | `breaker.ts` | the machine only; the trigger is `classify` or a hand-called `failed()`. Every settle takes the `admit()` ticket. `X_BREAKER_OPEN` registers its class here |
99
+ | what an element carries, for a test | `render-nodes.ts` (`renderNodes`, `nodesOf`, selectors) + `render-node.ts` (`JSX_NODE`, `ISLAND_NODE`, `HOLE_NODE`) | the one walker: `ui`, `admin` and apps import the subpath, never a copy. Islands and holes are branded ARRAYS, tested before `Array.isArray`; a hole is walked as `fallback` and `error`, never its deferred `children` |
92
100
 
93
101
  - **`installSecrets()` is the ONLY path from `secrets.enc.json` to an app value**, landing in
94
102
  `process.env` before `defineEnv` reads it. The real environment always wins.
95
103
  - **`intl-cache.ts`'s bound and canonical key are two halves of one rule** and live in one file:
96
104
  validating and keying are one `getCanonicalLocales` call. Never build an `Intl` formatter on a
97
105
  caller string without both.
98
- - **`secrets-errors.ts`'s command lines are screened**: paths through `renderFixShellArg`; a
99
- variable name must match `/^[A-Z_][A-Z0-9_]*$/` or the line degrades to prose;
100
- `X_SECRETS_KEY_MISMATCH`'s command carries no key id (it is read from a file). Its seven codes
101
- register through `registerErrorCodes()`, so `resetErrorCodes()` drops them — take
102
- `errorCodeSnapshot()` first. The envelope's `kid` lets *wrong key* and *edited file* be two codes.
103
- - **`seal.ts` adds no variable for the CURRENT key** — `findMasterKey()`, the same call
104
- `installSecrets()` makes. Retired keys are `ULTIMATE_SECRETS_RETIRED_KEYS`, written into
105
- `secrets.enc.json` by `x secrets rotate`; the ring memo is keyed by its source strings, never by
106
- time. Constants, `parseMasterKey`, `masterKeyId`, `importKey` and the base64 codec are
107
- `secrets.ts`'s — no second set. `seal-errors.ts` runs nothing at import: its titles are in
108
- `CORE_CODE_TITLES` and its retry class in `CORE_ERROR_RETRY`, so it is no `sideEffects` anchor.
109
- The wire form `x1.<keyId>.<iv>.<ciphertext+tag>` and the AAD string are persisted data: a change
110
- is `x2`, never an edit.
106
+ - **`secrets-errors.ts`'s command lines are screened** (`renderFixShellArg`; a bad variable name degrades to prose). Full rule: `docs/history/core.md`.
107
+ - **`seal.ts` adds no variable for the CURRENT key** (`findMasterKey()`). The wire form `x1.<keyId>.<iv>.<ciphertext+tag>` and the AAD string are persisted data: a change is `x2`, never an edit. Full rule: `docs/history/core.md`.
111
108
  - **`schema-error-codes.ts` registers `@ultimat3/schema`'s codes** (schema cannot call core), and
112
109
  derives their retry classification from the same set. It is a `SIDE_EFFECTS_ANCHORS` entry.
113
- - `timing-safe-equal.ts` is the one constant-time comparison (`auth`, `storage`).
114
110
  - **`canonical-json.ts`: `canonicalJson` is INJECTIVE and `fingerprint` is SHA-256/16 of it** — the
115
111
  hash every in-memory sharing key is taken over (`query`'s `queryHash`, `realtime`'s `qid`).
116
112
  `NaN`, `±Infinity` and `-0` are bare tokens; `Date`, `Map` and `Set` are TAGGED. Never a
@@ -121,26 +117,14 @@ top-level `UltimateError` use in `error-codes.ts`.
121
117
  - **`decimal-order.ts`'s `compareDecimalText` answers `undefined` for a non-decimal**, and only a
122
118
  caller that knows the column's kind may ask (`@ultimat3/entity`'s `compareByKind`) — never
123
119
  `@ultimat3/query`, whose `OrderKey` has no kind.
124
- - **`format-bytes.ts`: one `formatBytes(bytes)`, 1024-base, `b|kb|mb|gb`** for byte counts in error
125
- messages. Not `@ultimat3/ui`'s locale-formatted decimal one. Unmechanised: review catches a third.
126
- - **The flight layer** (`backoff.ts`, `retry.ts`, `single-flight.ts`, `flight-gate.ts`,
120
+ - **The flight layer** (`backoff.ts`, `retry-loop.ts`, `retry.ts`, `single-flight.ts`, `flight-gate.ts`,
127
121
  `generation-fence.ts`, `retryable-status.ts`, `client-flight.ts`, `client-wire.ts`) imports
128
122
  nothing but this package, runs nothing at import, and injects every source of non-determinism
129
123
  (roll, sleep, clock, timer). `classifyThrown` / `statedDelayMs` live beside `error-retry.ts`'s table.
130
- - **`backoffDelay` REFUSES a non-finite bound**: `attempt`, `base`, `max` and `factor` go through
131
- `finiteOption` before the clamps. The trailing `return 0` is reachable only by `factor` overflow.
132
- It clamps to `max` **before** jitter.
133
124
  - **`finiteOption` / `finiteCount` (`finite-option.ts`) are the framework's ONE screen for a numeric
134
125
  option.** `finiteCount(subject, option, value, min)` takes `min: 0 | 1` because only the caller
135
126
  knows what zero means. `bun run finite-bounds` recognises a repair by the call's shape, so a
136
127
  package screen carries `Finite` in its name.
137
- - **`flightGate` HANDS its slot to a waiter** rather than releasing it. `X_FLIGHT_GATE_OVERLOADED`
138
- is core's own code (tier 0 cannot borrow http's `X_OVERLOADED`); `overflow:` lets a caller throw its own.
139
- - **`client-flight.ts` INVERTS `retryDecision`'s unclassified default** through its `transient:`
140
- predicate: a bare `TypeError` (dead network) and an `AbortError` (the caller's cancellation) are
141
- indistinguishable by class. Never "simplify" it back.
142
- - **`ClientFlight` stays `import type`-only in `action`'s and `query`'s `client.ts`** — a value import
143
- pulls the whole flight layer into every caller's chunk.
144
128
  - **`mcp-exposure.ts`'s `isMcpExposed` is the ONE answer to "did this opt into MCP?"**, read by
145
129
  `action`, `query`, `mcp`, `ai`, `manifest`. `@ultimat3/cli`'s `mcp-exposure-pin.test.ts` checks
146
130
  it; `@ultimat3/admin`'s own catalog is the one opt-OUT exception (`mcp-tools.ts`).
@@ -160,6 +144,7 @@ server-only, never on `page.ts`. One call site per recorder; a second is the bug
160
144
  | `recordQueueDepth` | `@ultimat3/jobs` `worker.ts`, throttled inside `tick()` |
161
145
  | `recordJob` | `@ultimat3/jobs` `worker.ts`, the outcome branch inside `tick()` (`JOB_OUTCOME_LABELS` drops `suspended`) |
162
146
  | `recordLeaseLost` | `@ultimat3/jobs` `heartbeat.ts`, once per lapsed lease |
147
+ | `recordBreakerTransition` | `breaker.ts`, on every state change |
163
148
 
164
149
  - Tracing is three files: `telemetry.ts` builds spans, `sampler.ts` decides, `otlp*.ts` exports.
165
150
  `span.end()` returns early when `traceFlags & 1` is 0. The default sampler reads
@@ -169,45 +154,42 @@ server-only, never on `page.ts`. One call site per recorder; a second is the bug
169
154
  - The OTLP exporters are built, not wrapped ([`docs/idea/18-build-vs-wrap.md`](../../docs/idea/18-build-vs-wrap.md)).
170
155
  `otlpTraceRequest` / `otlpMetricsRequest` are pure. **gRPC (`:4317`) is out of scope**:
171
156
  `X_OTLP_PROTOCOL_UNSUPPORTED` names `:4318`; a boot that must not throw asks `tryOtlpEndpoint(signal)`.
157
+ - **`postOtlp` (`otlp-post.ts`) retries `OTLP_RETRY_STATUSES` and a transport failure only**, never `isRetryableStatus`. Full rule: `docs/history/core.md`.
158
+ - **`errorFingerprint` (`error-fingerprint.ts`) is a function, never an `ErrorReport` field**:
159
+ `code`, `source`, `scope.operation`, plus the top app frame for `X_INTERNAL` only. Never `cause`,
160
+ `meta`, ids or `release`. Total over hostile getters; the Sentry envelope's `fingerprint`.
161
+ - **Failure capture is OFF by default** (`config-failure-capture.ts`, `failureCapture.enabled`;
162
+ `x dev` forces it on): with no `FailureStore` installed nothing allocates. The OUTER
163
+ `invoke`/`runQuery` opens one buffer (`withFailureCapture`, `failure-capture.ts`); seams record
164
+ into it (`recordFailureFact`: entity reads, flag answers), masked and path-listed by
165
+ `captureValue` (`failure-capture-mask.ts`). A 5xx HOLDS the buffer on the thrown value, a 4xx
166
+ never; `reportError` releases it keyed by `errorFingerprint` over the same report
167
+ (`failure-capture-flush.ts`). Caps: `perHour` 5 per fingerprint per process, `maxRows` 50,
168
+ `maxBytes` 64 KiB — past one, stored `truncated`. A refused save is a log line, never awaited.
172
169
  - **Three OTLP variables, three codes** — `X_OTLP_ENDPOINT_INVALID`, `X_OTLP_HEADERS_INVALID`,
173
170
  `X_OTLP_PROTOCOL_UNSUPPORTED`. A header KEY is in the cause/fix/meta; its VALUE never is.
174
- - `error-reporter.ts`: `ErrorReporter`, no-op default, memory reporter for tests, Sentry transport
175
- (`error-reporter-sentry.ts`, optional export). `reportError` never throws, never awaits. Callers:
176
- `@ultimat3/http` `stages.ts` (`status >= 500`), `@ultimat3/jobs` `execute.ts`, `@ultimat3/realtime`
177
- `sync-node.ts` and `sync-upgrade.ts`, `@ultimat3/flags` `runtime.ts`. `configureErrorReporting({
178
- release })` takes the build id `serve.ts` computed. Trace and span resolve as a PAIR.
171
+ - `error-reporter.ts`: `ErrorReporter`, no-op default, memory reporter for tests, Sentry transport (`error-reporter-sentry.ts`, optional export). Full rule: `docs/history/core.md`. `'browser'`: only cli's `client-errors-routes.ts`, one `X_CLIENT_ERROR` per report.
179
172
  - `METRICS_PATH` is served by `@ultimat3/cli`'s `metrics-endpoint.ts` on `METRICS_PORT` (9090), never
180
173
  the role's HTTP port; every role opens it.
181
174
 
182
175
  ## Lifecycle and readiness
183
176
 
184
- - `markReady()` means **bound**; readiness means **usable** — `registerReadinessCheck(name, check)`.
185
- `/readyz` is ready when the state is `ready` AND every check passes. `HealthReport.registered` is
186
- the count (an empty registry is still `ready`, deliberately). `readinessChecks()` builds through
187
- `Object.fromEntries` (a check named `__proto__`). Checks are **synchronous**; liveness ignores
188
- them. The registration returns its unregister; `readinessCheckCount()` is the leak probe.
177
+ - `markReady()` means **bound**; readiness means **usable** — `registerReadinessCheck(name, check)`. Full rule: `docs/history/core.md`.
189
178
  - **`drain()`'s memo is published BEFORE the first hook runs** — a hook may re-enter `drain()`
190
179
  (`@ultimat3/http`'s `handle.stop()`), and `settleWithin` invokes hooks synchronously.
191
- - **The drain deadline is enforced**: `runPhase` races each hook against the time left before
192
- `deadlineAt` (`lifecycle-deadline.ts`'s `settleWithin`) and ABANDONS an overrun, logging it
193
- (`X_SHUTDOWN_TIMEOUT`, whose `fix:` names `configureLifecycle({ deadlineMs })`). The budget is the
194
- WHOLE drain's; `DEFAULT_DEADLINE_MS` (25 s) always applies; it is real monotonic time
195
- (`systemClock`), never the injected `clock`. `drainDeadlineMs()` is the one decision point.
196
- `settleWithin` attaches a rejection handler unconditionally.
180
+ - **The drain deadline is enforced** (`lifecycle-deadline.ts`): a hook overrunning the whole drain's budget is abandoned and logged (`X_SHUTDOWN_TIMEOUT`); real monotonic time, never the injected `clock`. Full rule: `docs/history/core.md`.
181
+ - **`close` hooks run last-registered first; the other phases as registered** (`runPhase`). No fourth phase.
197
182
  - **Who a health endpoint tells what is ONE rule, here** (`health-disclosure.ts`): `healthBody` +
198
183
  `healthPeerListed`, called by http and by realtime's sync listener. Never a second copy.
199
- - **A readiness grace runs before the `accept` phase** (`lifecycle-grace.ts`): `/readyz` answers 503
200
- with the socket still open for `drain.readinessGraceMs`, ADDED to `deadlineMs` (a chart's
201
- `terminationGracePeriodSeconds` must exceed the sum — 5 s + 25 s by default). Unset: 0 in
202
- development/test, 5000 everywhere else including a process naming no environment (fail closed).
184
+ - **An address answers two questions** (`address-class.ts`): `classifyAddress` is where a DIAL lands
185
+ and reads through every embedded IPv4; `peerAddressClass` is what a CALLER or a local name may be
186
+ trusted as, and a transit form (`2002:7f00:1::`, `64:ff9b::7f00:1`) is never loopback there. A
187
+ check that grants something asks the second. Unmechanised: review catches a new `=== 'loopback'`.
188
+ - **A readiness grace runs before the `accept` phase** (`lifecycle-grace.ts`), ADDED to `deadlineMs`. Full rule: `docs/history/core.md`.
189
+ - **`abandonment()`: a branded abort reason refuses writes** (`@ultimat3/db`); **`runToCompletion(fn)` is the one escape**, built by `derivedContext`. `run-to-completion.test.ts`.
203
190
  - `impersonate(actor, reason, fn)` is the ONE door through `withChildContext({ actor })`; it stamps
204
191
  `Actor.onBehalfOf` so `actorLabel` renders `service:eng-7→user:cust-99@org-3`. No second path.
205
- - Every `UltimateError` carries `retry` (`terminal | retryable | retry-after`), **defaulting to
206
- `terminal`**. `registerErrorRetry()` is the one registration path and refuses to reclassify a
207
- core code. Two readers: `retryFor(code)` (what to do, fails closed) and
208
- `declaredErrorRetry(code)` (what was declared, `undefined` otherwise) — a caller deciding whether
209
- to STOP work in flight (`@ultimat3/jobs`' executor) reads the second. An instance `retry` on an
210
- unregistered code reads as unclassified.
192
+ - Every `UltimateError` carries `retry` (`terminal | retryable | retry-after`), **defaulting to `terminal`**. Full rule: `docs/history/core.md`.
211
193
  - `PRIMITIVE_KINDS` is the executable eight-primitive rule; `PrimitiveKind` derives from it and
212
194
  `registrar.test.ts` fails on a ninth. `PRIMITIVE_FACTORIES` lists the factories.
213
195
 
@@ -219,25 +201,7 @@ bun run typecheck
219
201
  The root is load-bearing: Bun reads `bunfig.toml` (its preload installs `@ultimat3/testing`'s
220
202
  matchers) from the cwd.
221
203
 
222
- Gotchas:
223
- - `exactOptionalPropertyTypes` is on — declare optional fields as `x?: T | undefined`.
224
- - `noPropertyAccessFromIndexSignature` is on — `ctx.services['mail']`, not `.mail`.
225
- - `Ctx` carries a string index signature so apps can augment `CtxServices`; the cost is that
226
- `ctx.anything` type-checks as `unknown`. Deleting it is a breaking change, measured to compile
227
- core clean; land it alone, with a full `bun run verify`.
228
- - **`Ctx extends CtxFacts, CtxServices`, and `ctxOf` holds the framework's ONE irreducible
229
- `as Ctx`.** `CtxFacts` is what the framework sets (and what a `ServiceFactory` receives); an
230
- augmentation's named members are required of every `Ctx`, and no framework function can obtain
231
- them. `@ultimat3/http`'s `requestContext` composes `ctxOf()` and has no assertion.
232
- Refused alternatives: the file header. The repair is a major, with the index-signature deletion.
233
- - Tests that touch the registry, the lifecycle or the listener table call `resetErrorCodes()` /
234
- `resetLifecycle()` / `resetListeners()` — and a registry reset takes `errorCodeSnapshot()` first
235
- and restores it in `afterAll`, or every earlier package's titles render humanised for the run.
236
- - `onShutdown`'s return value is the unregister, owned by every caller that can start twice
237
- (`@ultimat3/http`'s `server.ts`, `@ultimat3/realtime`'s `listenSyncNode`, `@ultimat3/jobs`' worker,
238
- `@ultimat3/cli`'s `hold.ts`). `shutdownHookCount()` is the leak probe.
239
- - Tests calling `configureCursorSigning()` restore the previous secret or call
240
- `resetCursorSigning()`. The secret is read inside `sign()`, never at module scope; new secrets
241
- follow the same call-time rule.
204
+ Gotchas (`exactOptionalPropertyTypes`, `Ctx`'s index signature, registry resets, `onShutdown`'s unregister, cursor-secret restore): [`docs/history/core.md`](../../docs/history/core.md#moved-out-2026-11-03-plan-101-wave-3-the-claudemd-ceiling).
242
205
 
243
206
  Why each rule above is shaped the way it is: [`docs/history/core.md`](../../docs/history/core.md).
207
+ - `drain-deadline.ts` also owns `WORKER_RETIRE_DEFAULT_MS` and `workerRetireIssue`.
package/README.md CHANGED
@@ -3,12 +3,24 @@
3
3
  Tier 0. The foundation every other Ultimate package imports and none of them may bypass.
4
4
  Zero dependencies, zero `@ultimat3/*` imports.
5
5
 
6
+ `bun add @ultimat3/core` · guide: [Configuration](https://github.com/developerz-ai/ultimate/wiki/Configuration)
7
+
8
+ ```ts
9
+ import { secret } from '@ultimat3/core';
10
+
11
+ const dsn = secret('postgres://app:hunter2@db/app', 'DATABASE_URL');
12
+ JSON.stringify({ dsn }); // the value never prints: a Secret redacts by value, at any depth
13
+ ```
14
+
6
15
  | Owns | Module |
7
16
  |---|---|
8
17
  | `UltimateError`, the 3-line rendering, `--json` shape | `errors.ts` |
9
18
  | rendering an app's value into a `cause` / `fix` without throwing | `error-render.ts` |
10
19
  | a thrown value's stack, its `name: message` line restored when Bun dropped it — `failureStack` | `error-stack.ts` |
11
20
  | code → `{ title, docs }` registry, `registerErrorCodes()` | `error-codes.ts` |
21
+ | an APP code's one declaration — title, HTTP status, retry and class — `defineError()` | `define-error.ts` |
22
+ | an action's or a query's `errors:` — `checkDeclaredErrors` (the list), `judgeThrown` / `enforceDeclared` / `withDeclaredErrors` (a throw out of a handler; `X_ERROR_UNDECLARED` in test and dev, `undeclared_errors_total` in production), `describeDeclaredErrors` (a tool's description); the OpenAPI half `withDeclaredResponses`; the contract's source scan `scanHandlerSource` + `definedErrorClassCodes` (test-time). The status is passed in: `@ultimat3/http` is above this package | `declared-errors.ts`, `declared-errors-openapi.ts`, `declared-errors-scan.ts` |
23
+ | the app's half of the HTTP status table, written by `defineError` and `@ultimat3/http`'s `registerErrorStatus` — internal, on `@ultimat3/core/internal/error-status` only | `error-status-declared.ts` |
12
24
  | the one lazy `AsyncLocalStorage`, every ambient scope in the framework | `async-context.ts` |
13
25
  | request context on that seam | `context.ts` |
14
26
  | `Actor` (`user \| service \| agent \| anonymous`) | `actor.ts` |
@@ -16,7 +28,8 @@ Zero dependencies, zero `@ultimat3/*` imports.
16
28
  | acting as another actor, with an origin and a reason | `impersonate.ts` |
17
29
  | is an error worth retrying? one classification per code | `error-retry.ts` |
18
30
  | how long to wait before the next attempt — one curve, one jitter table | `backoff.ts` |
19
- | the retry executor and the pure decision behind it | `retry.ts` |
31
+ | the retry executor, bound to its caller's lifetime | `retry.ts` |
32
+ | the retry loop and the pure decision behind it, no context | `retry-loop.ts` |
20
33
  | which HTTP statuses are worth repeating | `retryable-status.ts` |
21
34
  | N callers on one key are ONE run | `single-flight.ts` |
22
35
  | how many may run at once, and how many may wait | `flight-gate.ts` |
@@ -28,6 +41,8 @@ Zero dependencies, zero `@ultimat3/*` imports.
28
41
  | the records envelope an answer carries behind `x-ultimate-records: 1` | `record-envelope.ts` |
29
42
  | the per-tab page handle (`globalThis[Symbol.for('ultimate.client')]`) records land in | `record-sink.ts` |
30
43
  | which principal the page acts for, and the epoch that moves when it changes | `client-scope.ts` |
44
+ | whether the page's session is lost — the first `X_UNAUTHENTICATED` / `X_SESSION_EXPIRED` on a page rendered for a principal, said once (`onSessionLost`, `sessionIsLost`), cleared by `rescope()`; on `./page` | `session-lost.ts` |
45
+ | a poll a hidden tab and a lost session stop — `visibleInterval(run, ms, { maxMs? })`: no call while hidden, one when shown, a failed run doubling the wait up to `maxMs` (jittered) and a success resetting it, an idempotent disposer; on `./page` (6,045 B alone, `page-bundle.test.ts`) | `visible-interval.ts` |
31
46
  | which row survives a conflict — `server-wins`, `last-write-wins`, `custom` | `conflict-policy.ts` |
32
47
  | the four shapes an async region can be in | `async-state.ts` |
33
48
  | the audit seam `action` and `query` share — `AuditRecord` (`name`, `primitive`, `surface`, `outcome`, the parsed `input`; `action` is a deprecated alias of `name` until 25.0.0), `AuditSink`, the ONE installed sink (`setAuditSink` / `getAuditSink` / `resetAuditSink`, re-exported by `@ultimat3/action`), and `AUDIT_RECORD_FIELDS`, the field list both primitives' tests pin their records to | `audit.ts` |
@@ -49,6 +64,7 @@ Zero dependencies, zero `@ultimat3/*` imports.
49
64
  | the shape screens that run before any rule reads a value — section, list, boolean, closed set, path | `config-shape.ts` |
50
65
  | the keys a major deleted (`locales`, `defaultLocale`, `defaultTimeZone`, `defaultCurrency`, `theme.tokens` in 25.0.0; `jobs.driver`, deleted in 5.0.0 and refused since 25.0.0) — each REFUSED by name with `X_CONFIG_INVALID` and its replacement, never ignored | `config-removed.ts` |
51
66
  | the `pwa` block — what an install needs, and the boot refusal when it is not there | `config-pwa.ts` |
67
+ | the `assets` block — `retain: { disk, builds }`, earlier builds' hashed files kept across a deploy (`AssetsConfig`, `AssetsRetainConfig`, `AssetsSection`, `AssetsSectionInput`) | `config-assets.ts` |
52
68
  | `isSameOriginPath(value)` — a path on THIS origin as a browser resolves it: refuses `//host`, `/\host`, a C0 control or DEL (`/\t/evil.example` parses to `//evil.example`) and a dot segment leaving a `//` pathname. The one predicate for every URL precached as an offline answer, `@ultimat3/pwa`'s build included | `config-pwa.ts` |
53
69
  | the closed route vocabulary every renderer names | `route-vocabulary.ts` |
54
70
  | which of two route patterns wins a pathname (`routeRank`) | `route-rank.ts` |
@@ -60,11 +76,13 @@ Zero dependencies, zero `@ultimat3/*` imports.
60
76
  | OTel-shaped spans, always on, no-op by default | `telemetry.ts` |
61
77
  | the sampling decision, and `OTEL_TRACES_SAMPLER*` | `sampler.ts` |
62
78
  | OTLP/HTTP JSON: endpoint, headers, value encoding | `otlp.ts` |
79
+ | one OTLP POST, retried on the specification's transient answers | `otlp-post.ts` |
63
80
  | `SpanExporter` on the wire, batched | `otlp-span-exporter.ts` |
64
81
  | `MetricExporter` on the wire | `otlp-metric-exporter.ts` |
65
82
  | may a caller read this 5xx code's `cause`? `hasPublicCause(code)` — one predicate for the HTTP problem document, MCP error data and an agent `tool_result` | `public-cause.ts` |
66
83
  | `reportError` + the `ErrorReporter` seam, no-op by default | `error-reporter.ts` |
67
84
  | that seam on the wire, Sentry's envelope and DSN | `error-reporter-sentry.ts` |
85
+ | which reports are one fault (`errorFingerprint`) | `error-fingerprint.ts` |
68
86
  | OTel-shaped counter / gauge / histogram, same seam | `metrics.ts` |
69
87
  | the `/metrics` scrape body | `metrics-text.ts` |
70
88
  | the series every process emits, incl. what the chart scales on | `runtime-metrics.ts` |
@@ -72,11 +90,11 @@ Zero dependencies, zero `@ultimat3/*` imports.
72
90
  | graceful drain, `/healthz`, `/readyz` | `lifecycle.ts` |
73
91
  | what a health endpoint tells whom — `healthBody(report, role, detailed)`, `healthPeerListed(peers, address)`, `DEFAULT_HEALTH_DETAIL_PEERS`; the one rule `@ultimat3/http` and the sync node's own listener both call | `health-disclosure.ts` |
74
92
  | the readiness grace between `/readyz` → 503 and the listener closing (`drain.readinessGraceMs`) | `lifecycle-grace.ts` |
75
- | the drain budget's default and domain (`drain.deadlineMs`, 25 s, 1–3600000 ms; the worker's optional `drain.workerDeadlineMs`, 1–86400000 ms) — `DRAIN_DEADLINE_DEFAULT_MS`, `DRAIN_DEADLINE_MAX_MS`, `WORKER_DRAIN_DEADLINE_MAX_MS` | `drain-deadline.ts` |
93
+ | the drain budget's default and domain (`drain.deadlineMs`, 25 s, 1–3600000 ms; the worker's optional `drain.workerDeadlineMs`, 1–86400000 ms; its `drain.workerRetireMs`, an hour, 0–86400000 ms) — `DRAIN_DEADLINE_DEFAULT_MS`, `DRAIN_DEADLINE_MAX_MS`, `WORKER_DRAIN_DEADLINE_MAX_MS`, `WORKER_RETIRE_DEFAULT_MS` | `drain-deadline.ts` |
76
94
  | `jobs.concurrency`'s default and domain — one slot count for every queue a worker serves, or a table per queue (`{ banks: 4, 'banks-long': 2 }`; a queue the table does not name runs at the default). `JOBS_CONCURRENCY_DEFAULT` (8), `type JobsConcurrency` | `config-jobs.ts` |
77
95
  | SIGTERM/SIGINT → the one drain; on Windows also SIGHUP (console close) and SIGBREAK (Ctrl-Break) — `drainSignals(platform)` | `lifecycle-signals.ts` |
78
96
  | is this directory inside a `bun build --compile` binary? `isCompiledBundle(import.meta.dir)` — `/$bunfs/` and Windows' `B:\~BUN\` | `bunfs.ts` |
79
- | which network an IP literal belongs to — `classifyAddress`, for SSRF screens | `address-class.ts` |
97
+ | which network an IP literal belongs to — `classifyAddress`, for SSRF screens; `peerAddressClass`, for a check that trusts a caller or a local name | `address-class.ts` |
80
98
  | the network a caller's address keys a per-caller budget on — `addressNetwork`: IPv4 exact, IPv4-mapped as IPv4, IPv6 as its /64 | `address-class.ts` |
81
99
  | the sockets this process opened, so a self-request is not egress | `listeners.ts` |
82
100
  | `defineService('orgs', …)` → `ctx.orgs`, rebuilt per actor | `service.ts` |
@@ -86,10 +104,10 @@ Zero dependencies, zero `@ultimat3/*` imports.
86
104
  | the one HTML character table — `escapeHtml`, text and attributes alike (`& < > " '`) | `html-escape.ts` |
87
105
  | the one `Cookie:` reader — `readCookie(header, name)`, `null` when absent, never a throw | `cookie.ts` |
88
106
  | the one `Set-Cookie` writer — `serializeSetCookie(name, value, options?)`; defaults `Path=/; HttpOnly; Secure; SameSite=Lax`, the value percent-encoded so `readCookie` returns it exactly, `X_COOKIE_INVALID` for a non-token name, a pair over 4096 octets, `SameSite=None`/`Partitioned` without `Secure`, a broken `__Secure-`/`__Host-` prefix rule, or an injectable `Path`/`Domain`. `Expires` is an IMF-fixdate in UTC | `cookie.ts` |
89
- | the one AWS Signature V4 signer — `signAwsRequest({ method, url, headers?, payload?, credentials, region, service, clock? })` → the URL, every header to send (`authorization`, `x-amz-date`, `x-amz-security-token`, `x-amz-content-sha256` by default on `s3`), the canonical request and string-to-sign. `payload`: `{ body }`, a pre-taken `{ sha256Hex }`, or `UNSIGNED_PAYLOAD`. S3 encodes the path once, every other service twice. Web Crypto, no SDK; proven on the aws-c-auth SigV4 suite and S3's worked examples. Shared by `storage`'s s3 disk and `mail`'s SES driver | `aws-sigv4.ts` |
107
+ | the one AWS Signature V4 signer — `signAwsRequest({ method, url, headers?, payload?, credentials, region, service, clock? })` → the URL, every header to send (`authorization`, `x-amz-date`, `x-amz-security-token`, `x-amz-content-sha256` by default on `s3`), the canonical request and string-to-sign. `payload`: `{ body }`, a pre-taken `{ sha256Hex }`, or `UNSIGNED_PAYLOAD`. S3 encodes the path once, every other service twice. Web Crypto, no SDK; proven on the aws-c-auth SigV4 suite and S3's worked examples. Shared by `storage`'s s3 disk and `mail`'s SES driver. `presignAwsUrl({ method, url, expiresInSeconds, headers?, credentials, region, service, clock? })` is the same signature in the query, for a holder with no credentials: `headers` are signed, so a signed `content-length` binds a browser's PUT to that size. Equal to `Bun.S3Client`'s presign byte for byte where Bun can express it | `aws-sigv4.ts` |
90
108
  | 32-bit FNV-1a — a BUCKET (rollouts, factory seeds), never a sharing key (`fingerprint` is) | `fnv1a.ts` |
91
109
  | `PgExecutor` — the structural `query(text, values)` seam every Postgres store takes | `pg-executor.ts` |
92
- | a declared retirement as headers — `renderDeprecation` (RFC 9745 `Deprecation`, RFC 8594 `Sunset`, the `successor-version` link) and `recordDeprecatedCall` on the one `deprecated_calls_total`; `action` and `query` both project through it | `deprecation.ts` |
110
+ | a declared retirement as headers — `renderDeprecation` (RFC 9745 `Deprecation`, RFC 8594 `Sunset`, the `successor-version` link, also `successorLink` / `successorPathOf` for a door that re-serves the route) and `recordDeprecatedCall` on the one `deprecated_calls_total`; `action` and `query` both project through it | `deprecation.ts` |
93
111
 
94
112
  Each of the five, and `fingerprint`, `storeMode` and render's `contentHash`, has ONE implementation:
95
113
  `bun run flight-copies` refuses a second by its shape (`X_HELPER_COPY`), whatever it is named.
@@ -147,6 +165,37 @@ Your package declares its own codes in `src/errors.ts` and registers them once:
147
165
  `registerErrorCodes({ X_DB_DRIFT: { title: 'schema differs from migrations' } })`.
148
166
  Registering a code twice throws `X_ERROR_CODE_DUPLICATE`.
149
167
 
168
+ ### An app's own codes: `defineError`
169
+
170
+ A framework package registers codes as above, through `bun run new-error-code`. An APP declares
171
+ each of its codes once, and gets the class back:
172
+
173
+ ```ts
174
+ import { defineError } from '@ultimat3/core';
175
+
176
+ export const PostNotFound = defineError<{ readonly ref: string }>({
177
+ code: 'X_POST_NOT_FOUND',
178
+ title: "no such post in the actor's organisation",
179
+ status: 404, // or offSocket: true, for a code no response carries — exactly one of the two
180
+ cause: (p) => `no post ${p.ref} in the actor's organisation`,
181
+ fix: 'x queries list --json, then pass an id the post read returns',
182
+ });
183
+
184
+ const error = new PostNotFound({ ref: 'hello' }, { sourceError: undefined });
185
+ PostNotFound.is(error); // the brand plus the code, never `instanceof`
186
+ ```
187
+
188
+ The one call registers the title (`registerErrorCodes`), the status (read by `@ultimat3/http`'s
189
+ `statusFor`, framework table first, so no app declaration moves a framework code) and, when given,
190
+ `retry` (`registerErrorRetry`). The same declaration twice is a no-op — a module re-evaluated
191
+ under `x dev`; a different title or status is `X_ERROR_CODE_DUPLICATE`. A malformed one — both or
192
+ neither of `status`/`offSocket`, a status outside 100-599, a code that is not `X_SCREAMING_SNAKE` —
193
+ is `X_ERROR_DECLARATION_INVALID`. A code some package already registered — a framework code,
194
+ under its own title or not — is `X_ERROR_CODE_DUPLICATE`: its status is not the app's to give. The
195
+ table itself is INTERNAL (`@ultimat3/core/internal/error-status`, read by `@ultimat3/http`): an app
196
+ declares through `defineError`, and a re-raised library code through `registerErrorStatus`. A
197
+ scaffolded app's `guards/error-declared.ts` refuses a handwritten `UltimateError` subclass.
198
+
150
199
  `isUltimateError()` is duck-typed on `Symbol.for('ultimate.error')`, not `instanceof` — that is
151
200
  how `@ultimat3/schema` (tier 0, cannot import core) still produces matching errors.
152
201
 
@@ -236,6 +285,7 @@ a job boundary the class is gone and the `code` is what survives — match on th
236
285
  | `SecretsPlaintextInvalidError` | `X_SECRETS_PLAINTEXT_INVALID` | `src/secrets-errors.ts` |
237
286
  | `SecretsTamperedError` | `X_SECRETS_TAMPERED` | `src/secrets-errors.ts` |
238
287
  | `UltimateError` | any registered code — every class in the framework extends it | `src/errors.ts` |
288
+ | what `defineError()` returns | the code it declared — `.code`, `.status`, `.is()` | `src/define-error.ts` |
239
289
 
240
290
  ## Context
241
291
 
@@ -263,6 +313,24 @@ because it closes over the ctx (actor, clock, tz) it was built for. `withChildCo
263
313
  factory-managed name from what it carries forward on purpose: only an ad hoc service nobody
264
314
  registered survives an actor swap unrebuilt.
265
315
 
316
+ `As of 2026-11-02`, a scope that was abandoned stops writing. `abandonment()` answers the ambient
317
+ signal's reason when it was aborted with a coded one (the request deadline's `X_TIMEOUT`, a job's
318
+ cancellation), the same object, and `undefined` for a client hang-up, which is uncoded: nobody was
319
+ told anything. `@ultimat3/db` and `@ultimat3/entity` refuse on it. `runToCompletion(fn)` is the one
320
+ escape: same request id and actor, a fresh signal, no deadline, managed services rebuilt over it.
321
+
322
+ ```ts
323
+ import { runToCompletion } from '@ultimat3/core';
324
+ import { withTransaction } from '@ultimat3/db';
325
+
326
+ declare function recordCharge(): Promise<void>;
327
+
328
+ await runToCompletion(() => withTransaction(() => recordCharge())); // lands, past the deadline
329
+ ```
330
+
331
+ Nothing in that scope bounds `fn`: the caller owns a ceiling, as `withIdempotency` and `onSettled`
332
+ do. Wrap the whole transaction, as above: a statement wrapped inside one still has its COMMIT refused.
333
+
266
334
  ## Actor facts — the app's own authz vocabulary, on the framework's actor
267
335
 
268
336
  Roles and an org id answer a columnar question ("same tenant?"). They cannot answer a relational
@@ -479,10 +547,13 @@ match with `sealAll()`; uniqueness cannot be held across keys.
479
547
  `tryOtlpEndpoint('traces')` answers `undefined` when nobody configured one, so a boot can skip
480
548
  the exporter instead of throwing. **gRPC (`:4317`) is out of scope** and says so with
481
549
  `X_OTLP_PROTOCOL_UNSUPPORTED`.
550
+ - **A transient export is sent again** (`postOtlp`, `otlp-post.ts`): 429, 502, 503, 504 or a
551
+ transport failure, `OTLP_RETRY_STATUSES`, on core's retry loop (3 attempts, full jitter,
552
+ `Retry-After` honoured) inside `timeoutMs`, which is the whole export. One log line per batch.
482
553
  - Metrics are the same shape one signal over: `counter()`, `gauge()`, `histogram()`, aggregated
483
554
  in process, free until `configureMetrics({ exporter })`. See below.
484
555
  - `onShutdown(name, hook, { phase })` with phases `accept → inflight → close` under one
485
- deadline; `readyzPayload()` flips to 503 the moment draining starts, `healthzPayload()` stays
556
+ deadline, `close` running last-registered first; `readyzPayload()` flips to 503 the moment draining starts, `healthzPayload()` stays
486
557
  200 until stopped. It **returns an unregister**, and a caller that starts and stops more than
487
558
  once has to keep it: a discarded one is a hook per `start()`, each retaining the resource it
488
559
  was going to drain, and the next drain runs every one of them against a torn-down copy.
@@ -547,7 +618,7 @@ process cannot drift apart:
547
618
  |---|---|---|
548
619
  | `rps` | `http_requests_total` | counter; `rps` is a **rate** the adapter derives (`rate(http_requests_total[1m])`), never a stored number |
549
620
  | `ws-connections` | `connections` | gauge, `+1`/`-1` |
550
- | `queue-depth` | `queue_depth` | gauge, by `queue` label |
621
+ | `queue-demand` | `queue_demand` | gauge, by `queue` label, `@ultimat3/jobs`'s. `queue_depth` stays, for the backlog alert: it reads 0 while a fleet holds every job it has |
551
622
 
552
623
  `As of 2026-08` all three are emitted and scraped. One call site per package — `recordRequest`
553
624
  from `@ultimat3/http`'s pipeline, `recordConnection` from `@ultimat3/realtime`'s socket table,
@@ -591,8 +662,11 @@ reportError(failure, { source: 'http', severity: 'error', scope: { operation: 'P
591
662
  | `ErrorReport` | `code` `title` `cause` `fix` `docs` + `meta` `stack` `resource` `environment` `release` `scope`, and the thrown value under `error` |
592
663
  | `configureErrorReporting({ reporter, clock, release, environment, enabled })` | the one install point; `resetErrorReporting()` puts the no-op back |
593
664
  | Reporters | `noopErrorReporter` (default), `memoryErrorReporter()` (`.events`, `.reset()`), `sentryErrorReporter({ dsn, fetch?, clientName? })` |
665
+ | Several at once | `chainErrorReporters(...reporters)` — one reporter handing each report to every member in order; a member that throws is logged and costs only itself; chains flatten, a member listed twice reports once, none is the no-op. `errorReportersOf(reporter)` reads the members back; `installedErrorReporter()` the one installed now. The container chains its `SENTRY_DSN` transport after what the app installed (`As of 2026-11`) |
594
666
  | Wire, testable alone | `parseSentryDsn(dsn)` → `{ publicKey, envelopeUrl, … }`, `sentryEnvelope(report, { dsn, eventId })` → the envelope body. Pure, exactly as `otlpTraceRequest` is |
595
667
  | `errorReport(error, options)` | the normalisation on its own, for a transport's test or a surface that enriches before sending |
668
+ | `errorFingerprint(report)` | 16 hex, which reports are one fault: `code`, `source`, `scope.operation`, and for `X_INTERNAL` the top application frame (function and root-relative path, no line). Never `cause`, `meta`, an id or `release`. Total; the Sentry envelope sends it as `fingerprint` |
669
+ | `setFailureStore(store)` / `withFailureCapture(primitive, name, statusOf, run)` / `recordFailureFact(fact)` | the 5xx bundle `x repro` replays (`failureCapture` in `app.config.ts`). No store, no buffer. A 5xx is held on the thrown value and stored at `reportError` under its `errorFingerprint`; masked input listed in `masked` |
596
670
 
597
671
  `As of 2026-08` four packages call `reportError`, seven call sites in all: `@ultimat3/http`'s
598
672
  `stages.ts` (`status >= 500` only), `@ultimat3/jobs`' `executeJob` — the one frame still holding the
@@ -626,7 +700,7 @@ never a silently wrong page.
626
700
  | Also keys | `keyedFingerprint(value, purpose)` — `h1:<key id>:<HMAC>` over `canonicalJson`, under a per-purpose key derived from this secret; the fingerprint to PERSIST (`@ultimat3/action`'s idempotency `requestHash`). `compareFingerprint` answers `match` / `mismatch` / `unverifiable` (other key), and still checks a legacy bare `fingerprint()` exactly. Rotating the secret makes in-window stored fingerprints `unverifiable` |
627
701
  | Signed, not encrypted | the client already has these rows; what it must not do is *invent* a position |
628
702
  | `usesDevCursorSecret({ env? })` | true while the shipped dev key is in use — this process, or the table `env` as signing would read it (empty and the published key count as unset) |
629
- | `CURSOR_SECRET_KEY` / `CURSOR_SECRET_FIX` | `'ULTIMATE_CURSOR_SECRET'` and the one `fix:` for `X_CURSOR_SECRET_DEV` (`export ULTIMATE_CURSOR_SECRET="$(openssl rand -hex 32)"`) — the boot refusal and `@ultimat3/cli`'s deploy contract (`.env.example`, `x env check`, `x doctor`) read both |
703
+ | `CURSOR_SECRET_KEY` / `CURSOR_SECRET_FIX` | `'ULTIMATE_CURSOR_SECRET'` and the one `fix:` for `X_CURSOR_SECRET_DEV` (`openssl rand -hex 32 # put the output in this deploy's secret store as ULTIMATE_CURSOR_SECRET; …`) — the boot refusal and `@ultimat3/cli`'s deploy contract (`.env.example`, `x env check`, `x doctor`) read both |
630
704
  | `devSecretsRefused({ env? })` | THE rule for refusing a shipped dev secret: anything but `development`/`test`, and no named environment counts as production. The boot (`assertNoDevSecretsOutsideLocal`), `@ultimat3/storage`'s disk and the CLI's diagnostics all ask it |
631
705
  | `resetCursorSigning()` | test seam: forget `configureCursorSigning` and fall back to the environment |
632
706
 
@@ -732,17 +806,18 @@ nothing consulted it before deciding to try again. `As of 2026-08-23`.
732
806
  | Export | The one answer | The question it settles |
733
807
  |---|---|---|
734
808
  | `backoffDelay({ attempt, base, max, factor?, curve?, jitter?, random? })` | one curve — `exponential \| linear \| fixed`, `full \| equal \| none` — 1-based `attempt`, clamped to `max` **before** jitter, rounded, and `0` rather than `NaN` | how long to wait. `random` is injectable, so a schedule is a unit test rather than a range |
735
- | `singleFlight({ deadlineMs?, schedule? })` → `run(key, work, join?)`, `size`, `keys()`, `evict(key)` | N callers on one key are ONE run | who pays for a miss. Eviction is identity-checked, so a load that settles late never drops the load that replaced it; `deadlineMs` frees the KEY a wedged load would hold forever — it never cancels the work and never rejects a joiner. `evict(key)` does the same on demand, for a caller that learns the load in flight began before a write its result must reflect |
809
+ | `singleFlight({ deadlineMs?, schedule?, signal?, released? })` → `run(key, work, join?)`, `size`, `keys()`, `evict(key)` | N callers on one key are ONE run | who pays for a miss. With `signal`, a live joiner re-leads when its leader was aborted, rather than sharing that rejection. `released(key)` fires each time a key stops being held. Eviction is identity-checked, so a load that settles late never drops the load that replaced it; `deadlineMs` frees the KEY a wedged load would hold forever — it never cancels the work and never rejects a joiner. `evict(key)` does the same on demand, for a caller that learns the load in flight began before a write its result must reflect |
736
810
  | `flightGate({ maxConcurrent, maxQueued }, { subject?, overflow? })` | one bound, one queue, one refusal | how many at once. Past the queue the answer is `X_FLIGHT_GATE_OVERLOADED` (503) and never a longer queue; the slot is HANDED to a waiter, never released and re-acquired. Both limits are screened at construction (`finiteCount`, 0 allowed); a width of 0 refuses every caller rather than queueing for a slot that never frees. `run(work, signal?)`: an abort while QUEUED removes the waiter and rejects with the abort's reason |
737
811
  | `generationFence(subject)` → `generation()`, `bump()`, `guard(issued)` | whether an answer still applies | `X_SUPERSEDED` (499) and `isSuperseded(error)` — the piece nothing in the tree had. `guard` compares `!==`, never `<` |
738
812
  | `isRetryableStatus(status)`, `RETRYABLE_STATUSES` | `>= 500`, plus 408, 409, 425, 429 | which HTTP answers are worth repeating |
739
813
  | `jitterStatedDelay(waitMs, capMs, random?)` | the ONE rule for a delay a responder named | the stated wait as a FLOOR plus a spread in `[0, min(wait / 2, cap))`, so a burst told `Retry-After: 1` does not replay in lockstep. `retryDecision`'s `retry-after` path (floor clamped to `max`; `jitter: 'none'` gets the bare floor) and `@ultimat3/jobs`' rate-limit deferral and webhook throttle all take it |
740
- | `retry(work, policy, { sleep, now?, random? })`, `retryDecision(policy, attempt, error, random?)` | the executor and the pure decision behind the classification | whether to try again at all. `clientFlight` is its one caller in the framework; `jobs`, `ai` and `db` each keep their own loop and delegate only the arithmetic and the classification |
814
+ | `retry(work, policy, { sleep?, now?, random? }?)`, `retryDecision(policy, attempt, error, random?)` | the executor and the pure decision behind the classification | whether to try again at all. `retry` stops on the ambient `ctx.signal` and clamps its budget to `ctx.deadlineAt`, with no opt-out: `runToCompletion(fn)` is the way to outlive a caller. `clientFlight` runs the same loop with no context (`retry-loop.ts`), so a page pays for no ambient request; `jobs`, `ai` and `db` each keep their own loop and delegate only the arithmetic and the classification |
741
815
  | `clientFlight({ principal?, retry?, deadlineMs?, limit?, … })` → `run(plan)`, `keyFor(url, opts?)`, `bump()`, `generation()` | the five above composed into one typed-client call | dedup, supersession, retry, one wall-clock deadline and a concurrency ceiling, for a call whose dispatch the caller supplies. `@ultimat3/action` and `@ultimat3/query` import it from here and re-export only its types — one file, because both are tier 3 and neither may import the other |
742
816
  | `isTransientFailure(error)` | what a CLIENT may send again | a declared `retryable`/`retry-after`, plus a dispatch that produced no response at all. It **inverts** `retryDecision`'s unclassified default on purpose: a caller's own `AbortError` and a foreign `TypeError` are terminal |
743
817
  | `traceHeaders()`, `problemOf(text)`, `retryForStatus(code, status, retryAfterSeconds?)`, `FRAMEWORK_CODE` | what a typed client puts on the wire and reads back off it | the W3C header (nothing at all when the span context is incomplete), a total `problem+json` read, and the classification a STATUS is allowed to give when nobody declared one for the code — `retry-after` for a 429 or 503 that stated a delay, unless the code is declared `terminal` |
744
818
  | `retryAfterSecondsOf(header, date)`, `MAX_RETRY_AFTER_SECONDS` | the one `Retry-After` reader | delta-seconds, or an IMF-fixdate measured against the same response's `Date` header (never the client's clock), capped at a day; `0`, a date already past and anything else `undefined` — only a positive delay is a statement (`retryAfterOf`'s outbound rule), so unstated falls back to the jittered curve. `clientTransport` passes it to `problemError` and to a caller's `decodeError(status, text, retryAfterSeconds)`, which carry it as `meta.retryAfterSeconds` for `statedDelayMs` |
745
819
  | `withStatedDelay(meta, retryAfterSeconds)` | a remote error's `meta`, for both decoders (`problemError`, `@ultimat3/action`'s `RemoteActionError`) | the copied wire keys minus any `retryAfterSeconds` — the server never writes one in a body, framework meta being operator-only — plus the header's value when there was one. A body can never drive the wait |
820
+ | `withRequestId(meta, requestId)` | a remote error's `meta`, for both decoders | the copied wire keys minus any `requestId`, plus the document's root member when it is a non-empty string under 128 chars. A server's `meta` key cannot pose as the id |
746
821
  | `remoteTitleOf(value)`, `MAX_REMOTE_TITLE_LENGTH` | a problem document's `title`, as untrusted display text | a non-blank string cut at 120 characters, or nothing. Handed to `UltimateError` as `remoteTitle`, used only when this realm registered no title for the code |
747
822
 
748
823
  `retry`'s `policy.jitter` is **required** where `backoffDelay`'s defaults to `none`: a loop retrying
@@ -753,12 +828,42 @@ cause and a runnable `fix:` with the fact that something was retried, which no r
753
828
  `classifyThrown` and `statedDelayMs` live in `error-retry.ts`, one import away from the table they
754
829
  read; `@ultimat3/jobs` re-exports both rather than keeping a second pair.
755
830
 
831
+ ## One outbound HTTP call, and the breaker in front of it
832
+
833
+ Server-only, on its own subpath: `import { outbound, screenDial } from '@ultimat3/core/outbound'`
834
+ (the barrel exports neither, `outbound-subpath.test.ts`). `breaker` is on the barrel. Full page:
835
+ [Outbound HTTP](https://github.com/developerz-ai/ultimate/wiki/Outbound-HTTP).
836
+
837
+ | Export | The one answer | The question it settles |
838
+ |---|---|---|
839
+ | `outbound({ url, vendor, dial, deadlineMs, method?, headers?, body?, idleMs?, maxBytes?, redirect?, retry?, idempotent?, read?, breaker? }, deps?)` | a vendor call | a whole-call deadline clamped by the ambient request, `ctx.signal` (its reason unchanged), core's `retry()` for safe methods only (`X_OUTBOUND_RETRY_UNSAFE`), `Retry-After`, an idle watchdog and a byte cap on the body, `redirect: 'error'` by default, and ten `X_OUTBOUND_*` codes whose causes carry no query and no header. `deps` injects `fetch`, `resolve`, `sleep`, `now`, `random`, `timer`, `env` |
840
+ | `screenDial(url, { resolve?, allowPrivate? })` → `{ pin } \| { refused } \| { unresolved }` | where a dial may land | every resolved address classified by `classifyAddress`, the connection pinned with `tls.serverName`. The framework's one `Bun.dns.lookup` (`resolveDialHost`); `@ultimat3/jobs`' webhook target and `@ultimat3/scraping` call it and keep their own codes |
841
+ | `deadlineSignal(ms, outer?, timer?)` | one attempt's signal | a deadline plus the caller's signal, undone on dispose (no listener left on `outer`, no timer armed) |
842
+ | `breaker({ name, failures, cooldownMs, classify?, clock? })` → `admit`, `succeeded`, `failed`, `released`, `state`, `failures`, `judge`, `refusal`, `run` | is a dependency down | one state machine, the trigger stays the caller's. One probe in `half-open`, lapsing after `cooldownMs`; `X_BREAKER_OPEN` names `retryAfterSeconds`; `breaker_transitions_total{name,to}`. Per process |
843
+
844
+ ## One Redis client
845
+
846
+ Server-only, on its own subpath: `import { redisClient } from '@ultimat3/core/redis'` (the barrel
847
+ exports none of it, `redis-subpath.test.ts`). The cache's shared tier and the Redis job driver both
848
+ take it; never `Bun.redis`, whose defaults turned an outage into a hang and a restart into a dead
849
+ client. `As of 2026-11`.
850
+
851
+ | Export | The one answer | The question it settles |
852
+ |---|---|---|
853
+ | `redisClient(url?)` → `RedisClient` | one client per process per URL | `enableOfflineQueue: false` (a command while down is refused at once, not queued — a stopped server cost 30,916 ms per first read), `maxRetries: 2_147_483_647` (the default gave up after ~31 s and never reconnected), `connectionTimeout: 1_000`. Connects in the background: the caller never waits, and a command before the first connect is refused like any other while down |
854
+ | `redisUrl(env?)` | which server | `REDIS_URL`, then `VALKEY_URL`, then `redis://localhost:6379`; blank is unset |
855
+ | `REDIS_CLIENT_OPTIONS` | the three options above, frozen | each carries its measured `why` in `redis-client.ts` |
856
+
857
+ A refusal is Bun's `ERR_REDIS_CONNECTION_CLOSED`, untyped here: the job driver types it
858
+ `X_DRIVER_UNAVAILABLE`, the cache tier reads it as a miss. `close()` closes it for every holder in the process.
859
+
756
860
  ## One browser seam — transport, records, page handle, principal fence
757
861
 
758
862
  | Export | The one answer | The question it settles |
759
863
  |---|---|---|
760
864
  | `clientTransport({ method, url, body?, rawBody?, headers?, signal?, idempotencyKey?, flight?, fresh?, retry?, responseType?, onResponse?, decodeError?, onEnvelope?, fetchImpl? })` | every browser request | `credentials: 'same-origin'`, JSON in and out, the `idempotency-key` header, a non-2xx `problem+json` back into the server's code (`meta.origin: 'remote'`) unless `decodeError` answers first, a network `TypeError` into `X_CLIENT_TRANSPORT_FAILED`. A GET is abortable on `rescope()` and deduped only when a `flight` is passed (`fresh` refuses to join); any other method is never deduped and never aborted by the fence. `rawBody` goes out verbatim with no default header and resolves `undefined` (the body as a string with `responseType: 'text'`). `responseType: 'text'` resolves a 2xx body as a string (typed `Promise<string>`), sends `accept: */*` unless `headers` names one, and adopts no envelope — for an HTML fragment or a CSV; a non-2xx is still decoded as a refusal. About 10.7 kB minified (4.6 kB gzipped) through `@ultimat3/core/page`, no titles table — pinned in `page-bundle.test.ts`. `onResponse` sees headers before the body is read. `onEnvelope` sees the decoded records envelope after adoption — the one way to learn the order of `records[type]`. `fetchImpl` defaults to `globalThis.fetch`, read at call time |
761
865
  | `actionPath(name)`, `actionRoute(name)`, `queryPath(name)`, `QUERY_PATH_PREFIX`, `splitWords`, `pluralize` | the one URL rule | `publishPost` → `/api/posts/publish`, `liveFeed` → `/_x/query/live-feed`. Tier 0 so `action`, `query` and `realtime` derive one URL with no sideways import |
866
+ | `templateParams`, `fillTemplate`, `pathTemplateProblem`, `templateKeyProblem`, `toOpenApiPath` (`route-path-template.ts`; the first two also on `./page`) · `mergePathParams`, `HttpPathInputConflictError` (`route-path-merge.ts`) | the one `http.path` template rule | an action's and a query's pin (`/orders/:id/refund`): lowercase static segments and `:param`s, each a required string input key; filled with each value one encoded segment; `{id}` in OpenAPI; the URL's values merged into the input, a disagreeing key `X_HTTP_PATH_INPUT_CONFLICT` (400). Tier 0 because `action` and `query` share a tier |
762
867
  | `actionPath(name)` with no `style`, `renderedActionPathStyle()`, `CLIENT_PATH_STYLE_META` | the style nobody restates | `actionPath(name)` reads the document's `<meta name="ultimate-path-style">` stamp, so a browser caller derives under the style the server serves (`defineApi({ http: { pathStyle } })`). No document, no stamp or an unknown value is `'resource'` — a `'resource'` server writes no stamp. A named `style` is never overridden |
763
868
  | `RECORDS_HEADER`, `encodeRecordEnvelope`, `decodeRecordEnvelope`, `RecordRows` | `{ data, records?: { [type]: { [key]: Row } }, removed?: { [type]: key[] } }`, only behind `x-ultimate-records: 1` | how an answer carries entity rows without changing the wire of an answer that has none. A malformed envelope is `X_CLIENT_RECORD_ENVELOPE_INVALID` |
764
869
  | `pageClient()` → `{ store, socket, scope }`, `RecordSink` | one handle per TAB, not per module copy | every island bundle carries its own core; the handle lives on `globalThis` under one `Symbol.for` key so all of them resolve the same store. No store installed = records dropped |
@@ -770,6 +875,18 @@ read; `@ultimat3/jobs` re-exports both rather than keeping a second pair.
770
875
  are in its file header. A server-side caller that propagates a trace passes `traceHeaders()` in
771
876
  `headers` itself.
772
877
 
878
+ ## A component's node tree, for a test — two subpaths, off the barrel
879
+
880
+ | Export | Subpath | What |
881
+ |---|---|---|
882
+ | `JSX_NODE`, `ISLAND_NODE`, `HOLE_NODE` | `@ultimat3/core/render-node` | the render node brands, one `Symbol.for` each; a leaf with no import. `@ultimat3/render` imports and re-exports all three |
883
+ | `renderNodes(component, props?, { components? })`, `nodesOf(value, { components? })` | `@ultimat3/core/render-nodes` | every node in the tree, depth first: `'expand'` (default) calls components and keeps host nodes, `'keep'` keeps component nodes beside their output, `'stop'` calls none. Thunks are called; an island's server shell and a hole's `fallback`/`error` are walked, a hole's deferred `children` never called; a value no factory built is nothing |
884
+ | `byTag`, `byComponent`, `withAttr`, `one`, `attachRef`, `fire`, `isRenderNode`, `RenderNode`, `RenderComponent`, `ComponentMode`, `NodesOfOptions` | `@ultimat3/core/render-nodes` | selectors over those nodes. `one()` refuses zero and two, `attachRef`/`fire` a missing prop, all `X_INVARIANT` naming what was sought |
885
+
886
+ `render-nodes` is imported by tests only, pinned by `render-nodes-subpath.test.ts` with the barrel
887
+ holding none of these names. `renderView` (`@ultimat3/testing`) answers what a reader sees; this
888
+ answers what an element carries.
889
+
773
890
  ## One image pipeline, everywhere
774
891
 
775
892
  ```ts
@@ -826,3 +943,13 @@ hand-rolled JPEG and PNG codecs is what put it there.
826
943
 
827
944
  `image/image-fixture.ts` is byte-exact output from Pillow and ffmpeg on purpose: a codec that only round
828
945
  trips against itself proves nothing. Never regenerate a fixture with our own encoder.
946
+
947
+ ## Supporting exports
948
+
949
+ `As of 2026-11-02`.
950
+
951
+ | Name | What |
952
+ |---|---|
953
+ | `CompletionBound` | what bounds a `runToCompletion` scope, when its caller owns a ceiling |
954
+ | `MAX_TIMER_MS` | the longest delay a timer holds, 2,147,483,647 ms: past it `setTimeout` arms ~1 ms |
955
+ | `jsonbRefusal(text)` | why `jsonb` would refuse this `JSON.stringify` output, or `undefined`. Names the class of thing, never the text |