castrum 0.9.0 → 0.9.2

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 (120) hide show
  1. package/README.md +153 -630
  2. package/castrum.linux-x64-gnu.node +0 -0
  3. package/dist/index.d.ts +1653 -1817
  4. package/dist/index.js +6172 -4294
  5. package/docs/API.md +337 -0
  6. package/docs/ARCHITECTURE.md +111 -17
  7. package/docs/BENCHMARKS.md +117 -49
  8. package/docs/CASE_STUDY.md +243 -0
  9. package/docs/ENVIRONMENT.md +24 -7
  10. package/docs/FFI_BUN_GUIDE.md +335 -0
  11. package/docs/GETTING_STARTED.md +18 -34
  12. package/docs/HOW_TO_ADD_AN_OP.md +180 -0
  13. package/docs/INGRESS-ROUTER.md +82 -0
  14. package/docs/INGRESS.md +11 -7
  15. package/docs/NATIVE-ROUTE.md +77 -0
  16. package/docs/REPO_MAP.md +103 -53
  17. package/docs/adr/0001-two-wire-formats.md +1 -1
  18. package/docs/adr/0003-bun-builtins-delegation.md +6 -5
  19. package/docs/ai/LOCAL_DEV.md +81 -0
  20. package/docs/ai/TREE.md +1070 -0
  21. package/docs/bun-builtins-decision-matrix.md +25 -18
  22. package/index.ts +9 -16
  23. package/package.json +41 -28
  24. package/src/ingress/body.ts +167 -27
  25. package/src/ingress/decode/result-base.ts +10 -2
  26. package/src/ingress/handlers.ts +116 -285
  27. package/src/ingress/headers/security.ts +41 -0
  28. package/src/ingress/health.ts +1 -0
  29. package/src/ingress/index.ts +45 -169
  30. package/src/ingress/native-route.ts +182 -0
  31. package/src/ingress/packing/gather-raw-headers.ts +110 -22
  32. package/src/ingress/packing/header-packing.ts +5 -5
  33. package/src/ingress/packing/input-packer.ts +17 -3
  34. package/src/ingress/packing/route-wire.ts +197 -0
  35. package/src/ingress/packing/select-headers.ts +20 -7
  36. package/src/ingress/path-matcher.ts +115 -0
  37. package/src/ingress/response/baked-response.ts +302 -0
  38. package/src/ingress/router.ts +277 -0
  39. package/src/ingress/routes/common.ts +50 -1
  40. package/src/ingress/routes/fallback.ts +2 -2
  41. package/src/ingress/routes/head.ts +3 -13
  42. package/src/ingress/routes/index.ts +5 -4
  43. package/src/ingress/routes/json-write.ts +26 -47
  44. package/src/ingress/routes/native.ts +130 -0
  45. package/src/ingress/routes/options.ts +2 -12
  46. package/src/ingress/routes/read.ts +3 -13
  47. package/src/ingress/routes/responder.ts +159 -0
  48. package/src/ingress/server-node.ts +7 -7
  49. package/src/ingress/server.ts +83 -112
  50. package/src/ingress/sync.ts +151 -0
  51. package/src/ingress/types.ts +44 -1
  52. package/src/integration/pipeline.ts +3 -0
  53. package/src/integration/streaming.ts +2 -3
  54. package/src/integration/websocket.ts +4 -3
  55. package/src/loader/batch.ts +4 -0
  56. package/src/loader/cost.ts +1 -0
  57. package/src/loader/index.ts +43 -228
  58. package/src/loader/state.ts +84 -0
  59. package/src/loader/types.ts +145 -0
  60. package/src/native/ffi/build/codecs.ts +736 -0
  61. package/src/native/ffi/build/compress.ts +248 -0
  62. package/src/native/ffi/build/instances.ts +598 -0
  63. package/src/native/ffi/build/parse.ts +539 -0
  64. package/src/native/ffi/build/util.ts +140 -0
  65. package/src/native/ffi/build.ts +94 -0
  66. package/src/native/ffi/constants.ts +58 -0
  67. package/src/native/ffi/selftest.ts +22 -0
  68. package/src/native/ffi/types.ts +499 -0
  69. package/src/native/ffi.ts +307 -1357
  70. package/src/native/loader.ts +52 -6
  71. package/src/native/types/instances.ts +279 -0
  72. package/src/native/types.ts +41 -238
  73. package/src/runtime/builtins.ts +131 -0
  74. package/src/runtime/codec.ts +147 -0
  75. package/src/runtime/detect.ts +36 -0
  76. package/src/runtime/index.ts +28 -0
  77. package/src/runtime/native.ts +35 -0
  78. package/src/runtime/server.ts +31 -0
  79. package/src/runtime/transport.ts +64 -0
  80. package/src/runtime/types.ts +173 -0
  81. package/src/runtime/uuid.ts +45 -0
  82. package/src/runtime/websocket.ts +30 -0
  83. package/src/rust-ffi/addon.ts +1 -1
  84. package/src/rust-ffi/batch/build.ts +155 -0
  85. package/src/rust-ffi/batch/index.ts +8 -0
  86. package/src/rust-ffi/batch/types.ts +92 -0
  87. package/src/rust-ffi/client.ts +5 -6
  88. package/src/rust-ffi/context.ts +39 -10
  89. package/src/rust-ffi/index.ts +28 -17
  90. package/src/rust-ffi/into.ts +21 -0
  91. package/src/rust-ffi/options.ts +1 -1
  92. package/src/rust-ffi/packed.ts +40 -2
  93. package/src/rust-ffi/proven.ts +16 -30
  94. package/src/rust-ffi/scalar/crypto.ts +188 -107
  95. package/src/rust-ffi/scalar/factories.ts +257 -27
  96. package/src/rust-ffi/scalar/hashing.ts +43 -41
  97. package/src/rust-ffi/scalar/http.ts +208 -77
  98. package/src/rust-ffi/scalar/index.ts +3 -3
  99. package/src/rust-ffi/scalar/interface.ts +88 -213
  100. package/src/rust-ffi/scalar/json-packed.ts +175 -0
  101. package/src/rust-ffi/scalar/json.ts +28 -12
  102. package/src/rust-ffi/scalar/payload.ts +159 -42
  103. package/src/rust-ffi/text.ts +31 -5
  104. package/src/selection.ts +27 -31
  105. package/src/shared/adaptive.ts +1 -2
  106. package/src/shared/buffer-pool.ts +72 -17
  107. package/src/shared/bytes.ts +75 -6
  108. package/src/shared/codec.ts +78 -0
  109. package/src/shared/env.ts +4 -4
  110. package/src/shared/log.ts +1 -0
  111. package/src/shared/packed/index.ts +10 -0
  112. package/src/shared/packed/parsers.ts +31 -0
  113. package/src/shared/packed/schema.ts +23 -0
  114. package/src/shared/{packed.ts → packed/wire.ts} +31 -39
  115. package/src/shared/proven.ts +189 -496
  116. package/src/shared/runtime.ts +20 -25
  117. package/src/shared/uuid.ts +12 -28
  118. package/src/data/json-rows.ts +0 -33
  119. package/src/rust-ffi/batch.ts +0 -431
  120. package/src/shared/bench-classify.ts +0 -209
@@ -1,596 +1,289 @@
1
- // src/shared/proven.ts — Performance-proven export registry (SINGLE SOURCE OF TRUTH).
1
+ // src/shared/proven.ts — baked "proven selection" registry (PURE DATA, no addon).
2
2
  //
3
- // Every public `rust.<name>` function is classified by how it performs against
4
- // its JavaScript baseline in the CPU benchmark (`bun run check`, which writes
5
- // `bench/results/cpu/latest.json`):
3
+ // The proven selection answers: "for op X, which implementation is the
4
+ // benchmark-proven winner, and is that what we wire as the default?"
6
5
  //
7
- // - "proven" Rust consistently wins in release/perf builds.
8
- // - "parity" Rust is within ~±15% of the JS baseline (no clear win).
9
- // - "not-competitive" Rust loses to the JS baseline (e.g. DOM + napi
10
- // marshaling costs, or a highly optimized host built-in
11
- // like Bun's JSON.parse).
12
- // - "unmeasured" No direct comparison task exists (infra/config only).
6
+ // - 'native' → the rust addon wins (bun:ffi on Bun / napi on Node)
7
+ // - 'js' → the pure-TS implementation wins
8
+ // - 'bun' → a Bun built-in wins UNDER BUN and is delegated there
9
+ // (see src/runtime/builtins.ts)
13
10
  //
14
- // This module is PURE DATA — it must NOT import the addon or the `rust` client,
15
- // so the audit script (`scripts/check-proven.ts`) can load it without dlopening
16
- // the native addon.
11
+ // This is BAKED (committed), benchmark-derived data — the winners were
12
+ // measured by `scripts/select-native.ts` (the `nativeRatio` in
13
+ // `src/selection.json`) and the Bun built-in decision matrix
14
+ // (`docs/bun-builtins-decision-matrix.md`). It is PURE DATA: no addon import,
15
+ // no dlopen, no live benchmark audit. That live audit was the friction of the
16
+ // old `check:proven`/`check:annotate` machinery (flaky on noisy hosts) — it
17
+ // is intentionally NOT re-added. Instead `test/unit/shared/proven.test.ts`
18
+ // verifies every entry is wired to the impl it claims (`opImpl`, the Bun
19
+ // built-in registry, and the addon's embedded selection.json), so drift is
20
+ // caught deterministically instead of by re-running benchmarks.
21
+ //
22
+ // `typicalRatio` is the addon-vs-pure-TS-baseline ratio (rust faster = >1) for
23
+ // native/js entries, and the Bun-built-in-vs-addon ratio for 'bun' entries
24
+ // (higher = the built-in wins by more).
25
+
26
+ /** The benchmark-proven default implementation for an op. */
27
+ export type ProvenImpl = 'native' | 'js' | 'bun'
17
28
 
18
- export type PerformanceStatus = 'proven' | 'parity' | 'not-competitive' | 'unmeasured'
29
+ /** How decisive the baked winner is. */
30
+ export type ProvenStatus = 'proven' | 'parity' | 'unmeasured'
19
31
 
32
+ /** One entry in the baked proven-selection registry. */
20
33
  export interface ProvenEntry {
21
- /** Public `rust.<name>` method key. */
34
+ /** Selection op name (matches `opImpl(op)` / `src/selection.json` keys). */
22
35
  name: string
23
- /** Benchmark comparison label (see src/bench/comparisons.ts). */
24
- label: string
25
- /** Baseline task name in the CPU report. */
26
- nativeTask: string
27
- /** Rust task name in the CPU report. */
28
- rustTask: string
29
- status: PerformanceStatus
30
- /** Typical rust-vs-baseline ratio from release/perf builds (rust faster = >1). */
36
+ /** The baked default implementation: the benchmark-proven winner. */
37
+ impl: ProvenImpl
38
+ /** `proven` = decisive win, `parity` = borderline, `unmeasured` = pinned by policy. */
39
+ status: ProvenStatus
40
+ /** Measured ratio behind the decision (see module doc for the axis). */
31
41
  typicalRatio?: number
32
42
  /** Why this classification. */
33
43
  note?: string
34
44
  }
35
45
 
36
46
  /**
37
- * Curated registry. Classifications are based on release/perf-build results
38
- * (docs + prior runs); the audit script re-checks them against the latest
39
- * report. Borderline wins are kept as "parity" so the `proven` surface stays
40
- * honest.
41
- *
42
- * `as const satisfies` keeps the literal `name`/`status` types so the
43
- * `ProvenKey` type (below) can be derived at the type level.
47
+ * Baked proven-winner registry. Covering the FULL selection surface
48
+ * (`src/selection.json` ops + every Bun built-in delegation) so nothing can be
49
+ * silently dropped. Classifications are based on release/perf-build results;
50
+ * `test/unit/shared/proven.test.ts` re-checks them against the LIVE wiring.
44
51
  */
45
- export const PROVEN_SURFACE = [
46
- // ── Clear wins (Rust > baseline) ──
47
- {
48
- name: 'fnv1a64',
49
- label: 'FNV-1a 64',
50
- nativeTask: 'native:fnv1a64',
51
- rustTask: 'rust:fnv1a64',
52
- status: 'proven',
53
- typicalRatio: 11,
54
- },
52
+ export const PROVEN_SELECTION: readonly ProvenEntry[] = [
53
+ // ── Bun built-in delegation — 'bun' (wins under Bun; consumer binding = 'js') ──
55
54
  {
56
- name: 'jsonValid',
57
- label: 'JSON valid',
58
- nativeTask: 'native:json_valid',
59
- rustTask: 'rust:json_valid',
60
- status: 'proven',
61
- typicalRatio: 3,
62
- },
63
- {
64
- name: 'jsonSumIds',
65
- label: 'JSON sum',
66
- nativeTask: 'native:json_sum',
67
- rustTask: 'rust:json_sum',
68
- status: 'proven',
69
- typicalRatio: 3,
70
- },
71
- {
72
- name: 'httpParseRequestPacked',
73
- label: 'HTTP parse',
74
- nativeTask: 'native:http_parse',
75
- rustTask: 'rust:http_parse',
76
- status: 'proven',
77
- typicalRatio: 4,
78
- },
79
- {
80
- name: 'queryParsePacked',
81
- label: 'Query parse',
82
- nativeTask: 'native:query_parse',
83
- rustTask: 'rust:query_parse',
55
+ name: 'crc32',
56
+ impl: 'bun',
84
57
  status: 'proven',
85
58
  typicalRatio: 4,
59
+ note: 'Bun.hash.crc32 wins 2.8–8.4×; selection.json records js (0.659)',
86
60
  },
87
61
  {
88
- name: 'cookieParsePacked',
89
- label: 'Cookie parse',
90
- nativeTask: 'native:cookie_parse',
91
- rustTask: 'rust:cookie_parse',
92
- status: 'proven',
93
- typicalRatio: 2.5,
94
- },
95
- {
96
- name: 'wsAcceptKey',
97
- label: 'WebSocket accept',
98
- nativeTask: 'native:ws_accept_key',
99
- rustTask: 'rust:ws_accept_key',
100
- status: 'proven',
101
- typicalRatio: 1.6,
102
- },
103
- {
104
- name: 'jsonPatch',
105
- label: 'JSON Patch',
106
- nativeTask: 'native:json_patch',
107
- rustTask: 'rust:json_patch',
62
+ name: 'xxh3',
63
+ impl: 'bun',
108
64
  status: 'proven',
109
- typicalRatio: 1.2,
110
- note: 'Modest but real win; swings ~0.9-1.5x run-to-run (DOM marshal dominated).',
65
+ typicalRatio: 4.15,
66
+ note: 'Bun.hash.xxHash3 ~4.15×; addon kept as the Node / non-Bun path',
111
67
  },
112
68
  {
113
69
  name: 'hmacSha256',
114
- label: 'HMAC sign',
115
- nativeTask: 'native:hmac_sha256',
116
- rustTask: 'rust:hmac_sha256',
117
- status: 'proven',
118
- typicalRatio: 1.5,
119
- note: 'Classification vs the node:crypto baseline. Under Bun the public rust.hmacSha256 delegates to Bun.CryptoHasher (BUN_WINS — hex re-encoded to the same contract); this row measures the raw addon (see src/bench/raw-native.ts).',
120
- },
121
- {
122
- name: 'hmacSha256Verify',
123
- label: 'HMAC verify',
124
- nativeTask: 'native:hmac_verify',
125
- rustTask: 'rust:hmac_verify',
126
- status: 'proven',
127
- typicalRatio: 2.4,
70
+ impl: 'bun',
71
+ status: 'parity',
72
+ typicalRatio: 1.2,
73
+ note: 'Bun.CryptoHasher mild 1.1–1.4×; the addon still beats the pure-JS baseline (1.212)',
128
74
  },
129
75
  {
130
- name: 'validateEmail',
131
- label: 'Email validation',
132
- nativeTask: 'native:validate_email',
133
- rustTask: 'rust:validate_email',
76
+ name: 'randomToken',
77
+ impl: 'bun',
134
78
  status: 'proven',
135
- typicalRatio: 3,
79
+ typicalRatio: 1.62,
80
+ note: 'Bun.randomUUIDv7 / crypto.getRandomValues for token-sized output',
136
81
  },
137
82
  {
138
- name: 'validateIpv6',
139
- label: 'IPv6 validation',
140
- nativeTask: 'native:validate_ipv6',
141
- rustTask: 'rust:validate_ipv6',
83
+ name: 'gzipCompress',
84
+ impl: 'bun',
142
85
  status: 'proven',
143
- typicalRatio: 1.3,
86
+ typicalRatio: 2.02,
87
+ note: 'Bun.gzipSync ~2×; gzipDecompress deliberately NOT delegated (64 MiB bomb cap)',
144
88
  },
145
89
  {
146
90
  name: 'urlEncode',
147
- label: 'URL encode',
148
- nativeTask: 'native:url_encode',
149
- rustTask: 'rust:url_encode',
150
- status: 'not-competitive',
151
- note: 'Public rust.urlEncode delegates to encodeURIComponent under Bun (BUN_WINS — ~3-4x faster than the FFI crossing; skips the C-ABI call). The rust: column measures the RAW addon (src/bench/raw-native.ts): the small-input FFI crossing loses (~0.58x), but LARGE inputs win (rust:url_encode_large ~1.45x) — the honest report no longer self-compares the built-in. Rust addon remains the Node path. Byte parity pinned by test/unit/features/url.test.ts + test/unit/features/wiring.test.ts.',
152
- },
153
- {
154
- name: 'urlDecode',
155
- label: 'URL decode',
156
- nativeTask: 'native:url_decode',
157
- rustTask: 'rust:url_decode',
158
- status: 'not-competitive',
159
- note: 'Public rust.urlDecode delegates to decodeURIComponent under Bun (BUN_WINS — ~4-8x faster than the FFI crossing; strict UTF-8 semantics match: both throw on malformed/invalid). The rust: column measures the RAW addon (src/bench/raw-native.ts): the small-input FFI crossing loses (~0.55x), but LARGE inputs win (rust:url_decode_large ~3.45x) — the honest report no longer self-compares the built-in. Rust addon remains the Node path and the raw-bytes urlDecodeBytes stays native. Parity pinned by test/unit/features/url.test.ts + test/unit/features/wiring.test.ts.',
160
- },
161
- {
162
- name: 'jwtVerify',
163
- label: 'JWT verify',
164
- nativeTask: 'native:jwt_verify',
165
- rustTask: 'rust:jwt_verify',
166
- status: 'proven',
167
- typicalRatio: 1.4,
168
- },
169
- {
170
- name: 'passwordHash',
171
- label: 'Password hash',
172
- nativeTask: 'native:password_hash',
173
- rustTask: 'rust:password_hash',
91
+ impl: 'bun',
174
92
  status: 'proven',
175
- typicalRatio: 19,
176
- note: 'argon2id vs node:crypto scrypt.',
93
+ typicalRatio: 11.5,
94
+ note: 'encodeURIComponent ~11.5×, zero alloc',
177
95
  },
178
96
  {
179
- name: 'aeadEncrypt',
180
- label: 'AEAD encrypt',
181
- nativeTask: 'native:aead_encrypt',
182
- rustTask: 'rust:aead_encrypt',
97
+ name: 'urlDecode',
98
+ impl: 'bun',
183
99
  status: 'proven',
184
- typicalRatio: 1.6,
100
+ typicalRatio: 6,
101
+ note: 'decodeURIComponent ~4–8×',
185
102
  },
186
103
  {
187
- name: 'aeadDecrypt',
188
- label: 'AEAD decrypt',
189
- nativeTask: 'native:aead_decrypt',
190
- rustTask: 'rust:aead_decrypt',
104
+ name: 'base64Encode',
105
+ impl: 'bun',
191
106
  status: 'proven',
192
107
  typicalRatio: 2,
108
+ note: 'Buffer.toString("base64") ~2×; url-safe / unpadded fall through to native',
193
109
  },
194
110
  {
195
- name: 'gzipDecompress',
196
- label: 'Gzip decompress',
197
- nativeTask: 'native:gzip_decompress',
198
- rustTask: 'rust:gzip_decompress',
199
- status: 'proven',
200
- typicalRatio: 1.4,
201
- note: "zlib-rs vs node zlib; swings 1.0-1.4x run-to-run. Deliberately NOT delegated to Bun.gunzipSync under Bun (NOT in BUN_WINS): Bun's decompressor has no output-size bound, and the native path keeps the 64 MiB decompression-bomb cap.",
202
- },
203
- {
204
- name: 'brotliDecompress',
205
- label: 'Brotli decompress',
206
- nativeTask: 'native:brotli_decompress',
207
- rustTask: 'rust:brotli_decompress',
208
- status: 'proven',
209
- typicalRatio: 1.9,
210
- },
211
- {
212
- name: 'multipartParse',
213
- label: 'Multipart parse',
214
- nativeTask: 'native:multipart_parse',
215
- rustTask: 'rust:multipart_parse',
216
- status: 'proven',
217
- typicalRatio: 2.3,
218
- },
219
- {
220
- name: 'wsFrameEncode',
221
- label: 'WS frame encode',
222
- nativeTask: 'native:ws_frame_encode',
223
- rustTask: 'rust:ws_frame_encode',
224
- status: 'proven',
225
- typicalRatio: 1.8,
226
- },
227
- {
228
- name: 'wsFrameDecode',
229
- label: 'WS frame decode',
230
- nativeTask: 'native:ws_frame_decode',
231
- rustTask: 'rust:ws_frame_decode',
111
+ name: 'base64UrlEncode',
112
+ impl: 'bun',
232
113
  status: 'proven',
233
114
  typicalRatio: 2,
115
+ note: 'Buffer.toString("base64url")',
234
116
  },
235
117
  {
236
- name: 'createSchemaValidator',
237
- label: 'JSON schema validate',
238
- nativeTask: 'native:json_schema_validate',
239
- rustTask: 'rust:json_schema_validate',
240
- status: 'proven',
241
- note: 'Zero-DOM fast path validates raw bytes for the common keyword subset (scalar ~1.2-2.4x, batch ~1.0-1.56x vs ajv); unsupported keywords fall back to the jsonschema crate.',
242
- },
243
-
244
- // ── Parity (no clear win) ──
245
- {
246
- name: 'crc32',
247
- label: 'CRC32',
248
- nativeTask: 'native:crc32',
249
- rustTask: 'rust:crc32',
250
- status: 'not-competitive',
251
- note: 'Raw addon vs the same-engine JS crc-32 loop (~0.23-0.44x across runs). Under Bun the public rust.crc32 delegates to Bun.hash.crc32 (BUN_WINS, ~2.8-8.4x) — this row measures the raw addon (src/bench/raw-native.ts).',
252
- },
253
- {
254
- name: 'xxh3',
255
- label: 'XXH3-64',
256
- nativeTask: 'diag:bun_hash_xxh3',
257
- rustTask: 'diag:xxh3',
258
- status: 'not-competitive',
259
- note: 'Bun.hash.xxHash3 wins ~4x (in-process C++ beats the FFI crossing). The public rust.xxh3 now DELEGATES to Bun.hash.xxHash3 under Bun (BUN_WINS); the addon remains the Node/non-Bun fast path. See docs/bun-builtins-decision-matrix.md.',
260
- },
261
- {
262
- name: 'randomToken',
263
- label: 'Random token',
264
- nativeTask: 'native:random_token',
265
- rustTask: 'rust:random_token',
266
- status: 'parity',
267
- typicalRatio: 1.1,
268
- note: 'Raw addon vs crypto.getRandomValues baseline. Under Bun the public rust.randomToken delegates to crypto.getRandomValues + native hex (BUN_WINS, same 2n-hex format + 16 MiB guard) — this row measures the raw addon (src/bench/raw-native.ts).',
269
- },
270
- {
271
- name: 'validateUuid',
272
- label: 'UUID validation',
273
- nativeTask: 'native:validate_uuid',
274
- rustTask: 'rust:validate_uuid',
275
- status: 'parity',
276
- typicalRatio: 1,
277
- },
278
- {
279
- name: 'validateIpv4',
280
- label: 'IPv4 validation',
281
- nativeTask: 'native:validate_ipv4',
282
- rustTask: 'rust:validate_ipv4',
283
- status: 'parity',
284
- typicalRatio: 1.05,
285
- },
286
- {
287
- name: 'mimeFromExtension',
288
- label: 'MIME lookup',
289
- nativeTask: 'native:mime',
290
- rustTask: 'rust:mime',
291
- status: 'parity',
292
- typicalRatio: 1.4,
293
- note: 'Consistently ~1.38-1.44x rust after the 2026-08-12 marshal reduction (cachedMime no longer per-call slices; text.mimeFromExtension memoizes the decoded string). phf table lookup.',
294
- },
295
- {
296
- name: 'gzipCompress',
297
- label: 'Gzip compress',
298
- nativeTask: 'native:gzip_compress',
299
- rustTask: 'rust:gzip_compress',
300
- status: 'parity',
301
- typicalRatio: 1,
302
- note: 'Raw addon vs node zlib baseline. Under Bun the public rust.gzipCompress delegates to Bun.gzipSync (BUN_WINS, ~2x; decompression-parity with the addon — only the header OS byte differs) — this row measures the raw addon (src/bench/raw-native.ts).',
303
- },
304
- {
305
- name: 'sseEncodeEvent',
306
- label: 'SSE encode',
307
- nativeTask: 'native:sse_encode',
308
- rustTask: 'rust:sse_encode',
309
- status: 'parity',
310
- typicalRatio: 1.1,
311
- },
312
-
313
- // ── New primitives (2026-08-11; measured vs Bun built-ins / node:crypto) ──
314
- {
315
- name: 'passwordHashBcrypt',
316
- label: 'Password hash (bcrypt)',
317
- nativeTask: 'diag:bun_password_bcrypt_hash',
318
- rustTask: 'diag:bcrypt_hash',
319
- status: 'parity',
320
- note: 'Bun.password.bcrypt ~1.24x faster at cost 10 (noisy KDF); rust is self-contained and non-Bun. See docs/bun-builtins-decision-matrix.md.',
321
- },
322
- {
323
- name: 'passwordVerifyBcrypt',
324
- label: 'Password verify (bcrypt)',
325
- nativeTask: 'diag:bun_password_bcrypt_verify',
326
- rustTask: 'diag:bcrypt_verify',
327
- status: 'parity',
328
- note: 'Rust ~1.49x vs Bun.password.verify at cost 10; KDF timings noisy — parity for gate stability.',
329
- },
330
- {
331
- name: 'pbkdf2Sha256',
332
- label: 'PBKDF2-HMAC-SHA256',
333
- nativeTask: 'diag:pbkdf2_sha256',
334
- rustTask: 'diag:pbkdf2_sha256_rust',
335
- status: 'parity',
336
- note: '~1.08x vs node:crypto pbkdf2Sync at 100k rounds (parity); Bun has no synchronous PBKDF2.',
337
- },
338
-
339
- // ── Not competitive (JS baseline wins) ──
340
- {
341
- name: 'jsonParse',
342
- label: 'JSON parse',
343
- nativeTask: 'native:json_parse',
344
- rustTask: 'rust:json_parse',
345
- status: 'not-competitive',
346
- note: "Bun's JSON.parse beats the native DOM + napi marshaling path (~5x).",
347
- },
348
- {
349
- name: 'jwtSign',
350
- label: 'JWT sign',
351
- nativeTask: 'native:jwt_sign',
352
- rustTask: 'rust:jwt_sign',
353
- status: 'not-competitive',
354
- note: 'Base64 + claims DOM marshal overhead. Use jwtSignBytes (claims as JSON bytes) which skips the napi Value marshal and flips to a ~1.07x win.',
355
- },
356
- {
357
- name: 'jwtSignBytes',
358
- label: 'JWT sign (bytes)',
359
- nativeTask: 'native:jwt_sign',
360
- rustTask: 'rust:jwt_sign_bytes',
361
- status: 'parity',
362
- note: 'Byte-JSON claims overload avoids the napi serde_json::Value DOM marshal; flips jwtSign from a ~1.3x loss to ~1.07x (parity).',
363
- },
364
- {
365
- name: 'brotliCompress',
366
- label: 'Brotli compress',
367
- nativeTask: 'native:brotli_compress',
368
- rustTask: 'rust:brotli_compress',
369
- status: 'not-competitive',
370
- note: 'The native brotli baseline wins for small inputs.',
371
- },
372
- {
373
- name: 'templateRender',
374
- label: 'Template render',
375
- nativeTask: 'native:template_render',
376
- rustTask: 'rust:template_render',
377
- status: 'not-competitive',
378
- note: 'The allocating render marshals the context via napi DOM (~1.5x loss). Use TemplateRenderer.renderBytes (JSON-bytes context) which avoids it and wins ~1.37x.',
379
- },
380
-
381
- // ── Framework actions (2026-08-07; release-build numbers) ──
382
- {
383
- name: 'formParsePacked',
384
- label: 'Form parse',
385
- nativeTask: 'native:form_parse',
386
- rustTask: 'rust:form_parse',
118
+ name: 'hexEncode',
119
+ impl: 'bun',
387
120
  status: 'proven',
388
- typicalRatio: 5.8,
389
- note: 'Benchmarked via the FormParser instance (same parser core).',
390
- },
391
- {
392
- name: 'parseMediaType',
393
- label: 'Media type parse',
394
- nativeTask: 'native:media_type_parse',
395
- rustTask: 'rust:media_type_parse',
396
- status: 'not-competitive',
397
- note: 'Consistent ~0.71-0.81x (sub-µs FFI crossing vs the JS baseline); use MediaTypeMatcher (precompiled expected) for the zero-alloc match path.',
398
- },
399
- {
400
- name: 'etag',
401
- label: 'ETag',
402
- nativeTask: 'native:etag',
403
- rustTask: 'rust:etag',
404
- status: 'parity',
405
- typicalRatio: 1.06,
121
+ typicalRatio: 1.35,
122
+ note: 'Buffer.toString("hex")',
406
123
  },
407
124
  {
408
125
  name: 'httpDate',
409
- label: 'HTTP date',
410
- nativeTask: 'native:http_date',
411
- rustTask: 'rust:http_date',
412
- status: 'not-competitive',
413
- note: 'Delegates to Date.toUTCString() under Bun (BUN_WINS — ~3.7x faster than the FFI crossing; byte-identical RFC 1123 for HTTP timestamps, incl. leap years/epoch). Rust addon remains the Node path; pooled httpDateInto stays native.',
414
- },
415
- {
416
- name: 'createConditionalRequest',
417
- label: 'Conditional request',
418
- nativeTask: 'native:conditional',
419
- rustTask: 'rust:conditional',
126
+ impl: 'bun',
420
127
  status: 'proven',
421
- typicalRatio: 1.4,
128
+ typicalRatio: 3.7,
129
+ note: 'Date.toUTCString() ~3.7×',
422
130
  },
131
+
132
+ // ── Native winners — 'native' (addon beats the pure-TS baseline) ──
133
+ { name: 'fnv1a64', impl: 'native', status: 'proven', typicalRatio: 12.603 },
134
+ { name: 'hmacSha256Verify', impl: 'native', status: 'proven', typicalRatio: 9.028 },
135
+ { name: 'signCookie', impl: 'native', status: 'proven', typicalRatio: 3.64 },
136
+ { name: 'verifyCookie', impl: 'native', status: 'proven', typicalRatio: 1.772 },
137
+ { name: 'csrfToken', impl: 'native', status: 'proven', typicalRatio: 12.671 },
138
+ { name: 'csrfVerify', impl: 'native', status: 'proven', typicalRatio: 12.458 },
423
139
  {
424
- name: 'createAcceptNegotiator',
425
- label: 'Accept-Encoding negotiate',
426
- nativeTask: 'native:accept_negotiate',
427
- rustTask: 'rust:accept_negotiate',
140
+ name: 'passwordHash',
141
+ impl: 'native',
428
142
  status: 'proven',
429
- typicalRatio: 4,
143
+ typicalRatio: 1.657,
144
+ note: 'argon2id — rust ~1.83× vs Bun.password at equal cost; never delegate',
430
145
  },
431
146
  {
432
- name: 'base64Encode',
433
- label: 'Base64 encode',
434
- nativeTask: 'native:base64_encode',
435
- rustTask: 'rust:base64_encode',
436
- status: 'not-competitive',
437
- note: 'Delegates to Buffer base64 under Bun for the standard padded, non-url-safe case (BUN_WINS — ~2x faster than the FFI crossing); url-safe/unpadded falls through to native. Rust addon remains the Node path. Parity pinned by test/unit/features/encoding.test.ts.',
438
- },
439
- {
440
- name: 'base64Decode',
441
- label: 'Base64 decode',
442
- nativeTask: 'native:base64_decode',
443
- rustTask: 'rust:base64_decode',
444
- status: 'parity',
445
- typicalRatio: 1.17,
446
- },
447
- {
448
- name: 'hexEncode',
449
- label: 'Hex encode',
450
- nativeTask: 'native:hex_encode',
451
- rustTask: 'rust:hex_encode',
452
- status: 'not-competitive',
453
- note: "Buffer.toString('hex') is native SIMD; pooled hexEncodeInto cuts the loss from ~2.2x to ~1.35x.",
147
+ name: 'passwordVerify',
148
+ impl: 'native',
149
+ status: 'proven',
150
+ typicalRatio: 1.88,
151
+ note: 'argon2id verify — rust wins; no representative pure-TS baseline (pinned)',
454
152
  },
153
+ { name: 'aeadEncrypt', impl: 'native', status: 'proven', typicalRatio: 1.288 },
455
154
  {
456
- name: 'hexDecode',
457
- label: 'Hex decode',
458
- nativeTask: 'native:hex_decode',
459
- rustTask: 'rust:hex_decode',
155
+ name: 'aeadDecrypt',
156
+ impl: 'native',
460
157
  status: 'parity',
461
- typicalRatio: 0.78,
462
- note: 'Slightly slower than Buffer hex decode (~1.3x).',
463
- },
464
- {
465
- name: 'signCookie',
466
- label: 'Cookie sign',
467
- nativeTask: 'native:cookie_sign',
468
- rustTask: 'rust:cookie_sign',
469
- status: 'proven',
470
- typicalRatio: 9,
158
+ typicalRatio: 1.108,
159
+ note: 'borderline — kept native',
471
160
  },
161
+ { name: 'createAcceptNegotiator', impl: 'native', status: 'proven', typicalRatio: 2.01 },
472
162
  {
473
- name: 'verifyCookie',
474
- label: 'Cookie verify',
475
- nativeTask: 'native:cookie_verify',
476
- rustTask: 'rust:cookie_verify',
163
+ name: 'gzipDecompress',
164
+ impl: 'native',
477
165
  status: 'proven',
478
- typicalRatio: 2.1,
166
+ typicalRatio: 61.039,
167
+ note: 'deliberately NOT delegated — Bun.gunzipSync has no bomb cap; native 64 MiB cap kept',
479
168
  },
480
169
  {
481
- name: 'csrfToken',
482
- label: 'CSRF create',
483
- nativeTask: 'native:csrf_create',
484
- rustTask: 'rust:csrf_create',
170
+ name: 'brotliCompress',
171
+ impl: 'native',
485
172
  status: 'proven',
486
- typicalRatio: 13.8,
173
+ typicalRatio: 9.983,
174
+ note: 'no synchronous Bun API',
487
175
  },
488
176
  {
489
- name: 'csrfVerify',
490
- label: 'CSRF verify',
491
- nativeTask: 'native:csrf_verify',
492
- rustTask: 'rust:csrf_verify',
177
+ name: 'brotliDecompress',
178
+ impl: 'native',
493
179
  status: 'proven',
494
- typicalRatio: 2.7,
180
+ typicalRatio: 33.327,
181
+ note: 'no synchronous Bun API',
495
182
  },
496
183
  {
497
- name: 'urlResolve',
498
- label: 'URL resolve',
499
- nativeTask: 'native:url_resolve',
500
- rustTask: 'rust:url_resolve',
501
- status: 'parity',
502
- typicalRatio: 1.11,
503
- note: 'Noisy ~1.5µs op; swings 0.74-1.03x run-to-run. UrlBuilder reuses the parsed base.',
184
+ name: 'jwtSign',
185
+ impl: 'native',
186
+ status: 'unmeasured',
187
+ note: 'pinned native — constant-time canonical (not pure-perf)',
504
188
  },
505
189
  {
506
- name: 'urlEncodeQuery',
507
- label: 'URL query build',
508
- nativeTask: 'native:url_encode_query',
509
- rustTask: 'rust:url_encode_query',
510
- status: 'not-competitive',
511
- note: 'encodeURIComponent baseline wins (~1.2-1.35x).',
190
+ name: 'jwtVerify',
191
+ impl: 'native',
192
+ status: 'unmeasured',
193
+ note: 'pinned native — constant-time canonical',
512
194
  },
513
-
514
- // ── Unmeasured (no direct comparison task) ──
515
195
  {
516
- name: 'passwordVerify',
517
- label: 'Password verify',
518
- nativeTask: '',
519
- rustTask: '',
196
+ name: 'createTemplate',
197
+ impl: 'native',
520
198
  status: 'unmeasured',
521
- note: 'Depends on the hash cost; no standalone comparison.',
199
+ note: 'pinned native — compiled-once instance',
522
200
  },
523
201
  {
524
- name: 'urlDecodeBytes',
525
- label: 'URL decode (bytes)',
526
- nativeTask: '',
527
- rustTask: '',
202
+ name: 'createSchemaValidator',
203
+ impl: 'native',
528
204
  status: 'unmeasured',
205
+ note: 'pinned native — compiled-once instance',
529
206
  },
207
+
208
+ // ── JS winners — 'js' (pure-TS beats the addon) ──
209
+ { name: 'queryPairs', impl: 'js', status: 'proven', typicalRatio: 0.279 },
210
+ { name: 'cookiePairs', impl: 'js', status: 'proven', typicalRatio: 0.105 },
211
+ { name: 'formPairs', impl: 'js', status: 'proven', typicalRatio: 0.328 },
212
+ { name: 'etag', impl: 'js', status: 'proven', typicalRatio: 0.187 },
213
+ { name: 'parseMediaType', impl: 'js', status: 'proven', typicalRatio: 0.378 },
214
+ { name: 'parseAcceptEncoding', impl: 'js', status: 'proven', typicalRatio: 0.367 },
215
+ { name: 'createConditionalRequest', impl: 'js', status: 'proven', typicalRatio: 0.275 },
530
216
  {
531
- name: 'configure',
532
- label: 'configure',
533
- nativeTask: '',
534
- rustTask: '',
217
+ name: 'multipartParse',
218
+ impl: 'js',
535
219
  status: 'unmeasured',
536
- note: 'Config only.',
220
+ note: 'no ratio recorded — JS baseline kept',
537
221
  },
538
222
  {
539
- name: 'initThreadPool',
540
- label: 'initThreadPool',
541
- nativeTask: '',
542
- rustTask: '',
543
- status: 'unmeasured',
544
- note: 'Runtime setup only.',
223
+ name: 'jsonValid',
224
+ impl: 'js',
225
+ status: 'parity',
226
+ typicalRatio: 0.749,
227
+ note: 'borderline — JSON.parse wins',
545
228
  },
546
229
  {
547
- name: 'rayonNumThreads',
548
- label: 'rayonNumThreads',
549
- nativeTask: '',
550
- rustTask: '',
551
- status: 'unmeasured',
552
- note: 'Introspection only.',
230
+ name: 'jsonPatch',
231
+ impl: 'js',
232
+ status: 'proven',
233
+ typicalRatio: 0.014,
234
+ note: 'custom JSON.patch beats the addon at small sizes',
553
235
  },
236
+ { name: 'sseEncode', impl: 'js', status: 'proven', typicalRatio: 0.586 },
237
+ { name: 'wsFrameEncode', impl: 'js', status: 'proven', typicalRatio: 0.152 },
238
+ {
239
+ name: 'wsFrameDecode',
240
+ impl: 'js',
241
+ status: 'parity',
242
+ typicalRatio: 0.988,
243
+ note: 'parity boundary — JS baseline kept',
244
+ },
245
+ { name: 'wsAcceptKey', impl: 'js', status: 'parity', typicalRatio: 0.939 },
246
+ { name: 'validateEmail', impl: 'js', status: 'proven', typicalRatio: 0.007 },
247
+ { name: 'validateUuid', impl: 'js', status: 'proven', typicalRatio: 0.008 },
248
+ { name: 'validateIpv4', impl: 'js', status: 'proven', typicalRatio: 0.012 },
249
+ { name: 'validateIpv6', impl: 'js', status: 'proven', typicalRatio: 0.078 },
250
+ { name: 'createRateLimiter', impl: 'js', status: 'proven', typicalRatio: 0.061 },
251
+ { name: 'renderTemplate', impl: 'js', status: 'proven', typicalRatio: 0.141 },
554
252
  ] as const satisfies readonly ProvenEntry[]
555
253
 
556
- /** An entry of the registry with a specific status (type-level). */
557
- type ProvenEntryOf<S extends PerformanceStatus> = Extract<
558
- (typeof PROVEN_SURFACE)[number],
559
- { status: S }
560
- >
254
+ const INDEX = new Map<string, ProvenEntry>(PROVEN_SELECTION.map((e) => [e.name, e]))
561
255
 
562
256
  /**
563
- * The `rust.<name>` keys whose status is "proven" — the only keys exposed on
564
- * the `proven` surface. Derived from the registry so the type can never drift
565
- * from the data.
257
+ * The baked {@link ProvenEntry} for `op`, or `undefined` for unknown ops.
258
+ * Pure data — never dlopens the addon.
566
259
  */
567
- export type ProvenKey = ProvenEntryOf<'proven'>['name']
260
+ export function provenEntry(op: string): ProvenEntry | undefined {
261
+ return INDEX.get(op)
262
+ }
568
263
 
569
- const byName = new Map<string, ProvenEntry>(PROVEN_SURFACE.map((e) => [e.name, e]))
264
+ /** The baked default implementation for `op` (`native` / `js` / `bun`), or `null`. */
265
+ export function provenImpl(op: string): ProvenImpl | null {
266
+ return INDEX.get(op)?.impl ?? null
267
+ }
570
268
 
571
- /** Look up the status of a public function by its `rust.<name>` key. */
572
- export function provenStatus(name: string): PerformanceStatus | undefined {
573
- return byName.get(name)?.status
269
+ /** The baked status for `op`, or `null` for unknown ops. */
270
+ export function provenStatus(op: string): ProvenStatus | null {
271
+ return INDEX.get(op)?.status ?? null
574
272
  }
575
273
 
576
- /** Whether a function is part of the performance-proven surface. */
577
- export function isProven(name: string): boolean {
578
- return provenStatus(name) === 'proven'
274
+ /** Whether the op's baked winner is a decisive (`proven`) win. */
275
+ export function isProven(op: string): boolean {
276
+ return INDEX.get(op)?.status === 'proven'
579
277
  }
580
278
 
581
- /** The entries that are performance-proven (Rust clearly wins). */
582
- export function provenSurface(): ProvenEntry[] {
583
- return PROVEN_SURFACE.filter((e) => e.status === 'proven')
279
+ /** The full baked registry (same array as {@link PROVEN_SELECTION}). */
280
+ export function provenSurface(): readonly ProvenEntry[] {
281
+ return PROVEN_SELECTION
584
282
  }
585
283
 
586
- /** Aggregate summary of the registry (status → count). */
587
- export function provenSummary(): Record<PerformanceStatus, number> {
588
- const out: Record<PerformanceStatus, number> = {
589
- proven: 0,
590
- parity: 0,
591
- 'not-competitive': 0,
592
- unmeasured: 0,
593
- }
594
- for (const e of PROVEN_SURFACE) out[e.status] += 1
595
- return out
284
+ /** A one-line summary of the baked selection (counts per implementation). */
285
+ export function provenSummary(): string {
286
+ const byImpl = { native: 0, js: 0, bun: 0 }
287
+ for (const e of PROVEN_SELECTION) byImpl[e.impl] += 1
288
+ return `proven selection: ${byImpl.native} native, ${byImpl.js} js, ${byImpl.bun} bun built-in (${PROVEN_SELECTION.length} ops)`
596
289
  }