castrum 0.9.3 → 0.9.6

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 (206) hide show
  1. package/Cargo.lock +2242 -0
  2. package/Cargo.toml +155 -0
  3. package/README.md +14 -6
  4. package/build.rs +5 -0
  5. package/castrum.darwin-arm64.node +0 -0
  6. package/castrum.darwin-x64.node +0 -0
  7. package/castrum.linux-arm64-gnu.node +0 -0
  8. package/castrum.linux-arm64-musl.node +0 -0
  9. package/castrum.linux-x64-gnu.node +0 -0
  10. package/castrum.linux-x64-musl.node +0 -0
  11. package/castrum.linux-x64-v3-gnu.node +0 -0
  12. package/castrum.win32-x64-msvc.node +0 -0
  13. package/dist/index.d.ts +1508 -1291
  14. package/dist/index.js +3391 -2069
  15. package/docs/API.md +2 -1
  16. package/docs/ARCHITECTURE.md +3 -2
  17. package/docs/CASE_STUDY.md +5 -3
  18. package/docs/ENVIRONMENT.md +25 -2
  19. package/docs/FFI_BUN_GUIDE.md +242 -14
  20. package/docs/HOW_TO_ADD_AN_OP.md +10 -0
  21. package/docs/REPO_MAP.md +17 -6
  22. package/docs/RND-CONCURRENCY.md +772 -0
  23. package/docs/bun-builtins-decision-matrix.md +4 -1
  24. package/index.ts +24 -25
  25. package/package.json +173 -156
  26. package/rust/crypto/aead.rs +378 -0
  27. package/rust/crypto/argon2.rs +265 -0
  28. package/rust/crypto/base64.rs +420 -0
  29. package/rust/crypto/bcrypt.rs +89 -0
  30. package/rust/crypto/cookie_sign.rs +169 -0
  31. package/rust/crypto/csrf.rs +106 -0
  32. package/rust/crypto/ed25519.rs +215 -0
  33. package/rust/crypto/hashing.rs +140 -0
  34. package/rust/crypto/hmac_sha256.rs +88 -0
  35. package/rust/crypto/jwt/api.rs +286 -0
  36. package/rust/crypto/jwt/mod.rs +22 -0
  37. package/rust/crypto/jwt/tests.rs +312 -0
  38. package/rust/crypto/jwt/token.rs +360 -0
  39. package/rust/crypto/mod.rs +27 -0
  40. package/rust/crypto/pbkdf2.rs +105 -0
  41. package/rust/crypto/random_token.rs +85 -0
  42. package/rust/crypto/session.rs +222 -0
  43. package/rust/ffi/crypto.rs +708 -0
  44. package/rust/ffi/hashing.rs +285 -0
  45. package/rust/ffi/http.rs +752 -0
  46. package/rust/ffi/ingress.rs +303 -0
  47. package/rust/ffi/json.rs +517 -0
  48. package/rust/ffi/jwt.rs +419 -0
  49. package/rust/ffi/metrics.rs +373 -0
  50. package/rust/ffi/mod.rs +69 -0
  51. package/rust/ffi/payload.rs +275 -0
  52. package/rust/ffi/probe.rs +60 -0
  53. package/rust/ffi/rate_limit.rs +77 -0
  54. package/rust/ffi/route.rs +85 -0
  55. package/rust/ffi/task.rs +172 -0
  56. package/rust/ffi/tests.rs +2333 -0
  57. package/rust/ffi/util.rs +152 -0
  58. package/rust/ffi/validators.rs +123 -0
  59. package/rust/http/accept.rs +606 -0
  60. package/rust/http/cookie_parser.rs +140 -0
  61. package/rust/http/etag.rs +289 -0
  62. package/rust/http/form.rs +136 -0
  63. package/rust/http/headers.rs +267 -0
  64. package/rust/http/http_date.rs +286 -0
  65. package/rust/http/http_parser.rs +252 -0
  66. package/rust/http/media_type.rs +355 -0
  67. package/rust/http/method.rs +200 -0
  68. package/rust/http/mime_lookup.rs +130 -0
  69. package/rust/http/mod.rs +32 -0
  70. package/rust/http/multipart.rs +685 -0
  71. package/rust/http/query_parser.rs +211 -0
  72. package/rust/http/url_codec.rs +296 -0
  73. package/rust/http/url_join.rs +324 -0
  74. package/rust/ingress/api.rs +355 -0
  75. package/rust/ingress/cors.rs +403 -0
  76. package/rust/ingress/ingress_constants.rs +209 -0
  77. package/rust/ingress/ip_trust.rs +312 -0
  78. package/rust/ingress/mod.rs +48 -0
  79. package/rust/ingress/native_route.rs +770 -0
  80. package/rust/ingress/options.rs +176 -0
  81. package/rust/ingress/output.rs +406 -0
  82. package/rust/ingress/packed.rs +191 -0
  83. package/rust/ingress/pipeline.rs +534 -0
  84. package/rust/ingress/proxy.rs +138 -0
  85. package/rust/ingress/rate_limit.rs +538 -0
  86. package/rust/ingress/terminal.rs +114 -0
  87. package/rust/ingress/tests.rs +567 -0
  88. package/rust/ingress/time.rs +70 -0
  89. package/rust/json/fast_schema/capture.rs +336 -0
  90. package/rust/json/fast_schema/compile.rs +556 -0
  91. package/rust/json/fast_schema/cursor.rs +368 -0
  92. package/rust/json/fast_schema/email.rs +282 -0
  93. package/rust/json/fast_schema/errors.rs +247 -0
  94. package/rust/json/fast_schema/mod.rs +57 -0
  95. package/rust/json/fast_schema/tests.rs +1143 -0
  96. package/rust/json/fast_schema/types.rs +140 -0
  97. package/rust/json/fast_schema/validate.rs +931 -0
  98. package/rust/json/json_ops.rs +121 -0
  99. package/rust/json/json_schema.rs +837 -0
  100. package/rust/json/json_ser.rs +883 -0
  101. package/rust/json/mod.rs +19 -0
  102. package/rust/json/napi_marshal.rs +318 -0
  103. package/rust/json/patch/api.rs +60 -0
  104. package/rust/json/patch/engine.rs +153 -0
  105. package/rust/json/patch/mod.rs +47 -0
  106. package/rust/json/patch/ops.rs +270 -0
  107. package/rust/json/patch/pointer.rs +49 -0
  108. package/rust/json/patch/tests.rs +499 -0
  109. package/rust/lib.rs +73 -0
  110. package/rust/metrics/api.rs +148 -0
  111. package/rust/metrics/mod.rs +21 -0
  112. package/rust/metrics/registry.rs +961 -0
  113. package/rust/panic_safety.rs +40 -0
  114. package/rust/payload/compress.rs +512 -0
  115. package/rust/payload/mod.rs +13 -0
  116. package/rust/payload/sse.rs +214 -0
  117. package/rust/payload/template.rs +253 -0
  118. package/rust/payload/websocket.rs +69 -0
  119. package/rust/payload/ws_frames.rs +354 -0
  120. package/rust/proptest_suite.rs +139 -0
  121. package/rust/selection.rs +95 -0
  122. package/rust/src/bin/native-bench.rs +495 -0
  123. package/rust/task/completion.rs +119 -0
  124. package/rust/task/mod.rs +65 -0
  125. package/rust/task/ops.rs +503 -0
  126. package/rust/task/runtime.rs +220 -0
  127. package/rust/task/tests.rs +231 -0
  128. package/rust/test_support.rs +71 -0
  129. package/rust/util/batch/api.rs +266 -0
  130. package/rust/util/batch/core.rs +473 -0
  131. package/rust/util/batch/mod.rs +23 -0
  132. package/rust/util/batch/tests.rs +445 -0
  133. package/rust/util/batch_core.rs +184 -0
  134. package/rust/util/bytes.rs +594 -0
  135. package/rust/util/mod.rs +34 -0
  136. package/rust/util/packed.rs +473 -0
  137. package/rust/util/text.rs +130 -0
  138. package/rust/util/threadpool.rs +128 -0
  139. package/rust/util/validation.rs +419 -0
  140. package/rust-toolchain.toml +17 -0
  141. package/scripts/postinstall.mjs +199 -0
  142. package/src/ingress/constants.ts +1 -1
  143. package/src/ingress/context.ts +2 -2
  144. package/src/ingress/decode/baked-result.ts +13 -13
  145. package/src/ingress/decode/fast-result.ts +17 -17
  146. package/src/ingress/errors.ts +7 -7
  147. package/src/ingress/headers/baked-templates.ts +1 -1
  148. package/src/ingress/headers/fast-templates.ts +3 -3
  149. package/src/ingress/health.ts +1 -2
  150. package/src/ingress/index.ts +1 -1
  151. package/src/ingress/native-route.ts +9 -5
  152. package/src/ingress/options.ts +1 -1
  153. package/src/ingress/packing/gather-raw-headers.ts +1 -1
  154. package/src/ingress/packing/route-wire.ts +1 -5
  155. package/src/ingress/response/error-bodies.ts +5 -5
  156. package/src/ingress/response/terminal.ts +1 -1
  157. package/src/ingress/routes/echo.ts +4 -4
  158. package/src/ingress/routes/fallback.ts +2 -2
  159. package/src/ingress/routes/head.ts +2 -2
  160. package/src/ingress/routes/native.ts +2 -1
  161. package/src/ingress/routes/options.ts +1 -1
  162. package/src/ingress/routes/read.ts +2 -2
  163. package/src/ingress/server.ts +10 -6
  164. package/src/ingress/status.ts +7 -7
  165. package/src/integration/batch.ts +1 -1
  166. package/src/integration/index.ts +9 -9
  167. package/src/integration/pipeline.ts +6 -6
  168. package/src/integration/websocket.ts +2 -2
  169. package/src/loader/index.ts +1 -5
  170. package/src/loader/ops.ts +1 -1
  171. package/src/native/ffi/build/codecs.ts +130 -12
  172. package/src/native/ffi/build/compress.ts +22 -10
  173. package/src/native/ffi/build/instances.ts +46 -4
  174. package/src/native/ffi/build/metrics.ts +247 -0
  175. package/src/native/ffi/build/parse.ts +59 -23
  176. package/src/native/ffi/build/task.ts +79 -0
  177. package/src/native/ffi/build/util.ts +32 -1
  178. package/src/native/ffi/build.ts +4 -0
  179. package/src/native/ffi/selftest.ts +12 -3
  180. package/src/native/ffi/types.ts +151 -9
  181. package/src/native/ffi.ts +160 -15
  182. package/src/native/index.ts +1 -1
  183. package/src/native/loader.ts +55 -5
  184. package/src/native/types/instances.ts +34 -0
  185. package/src/native/types.ts +11 -0
  186. package/src/runtime/codec.ts +53 -9
  187. package/src/runtime/types.ts +7 -0
  188. package/src/rust-ffi/batch/build.ts +16 -9
  189. package/src/rust-ffi/index.ts +7 -6
  190. package/src/rust-ffi/options.ts +1 -3
  191. package/src/rust-ffi/proven.ts +3 -3
  192. package/src/rust-ffi/scalar/crypto.ts +1 -1
  193. package/src/rust-ffi/scalar/factories.ts +73 -0
  194. package/src/rust-ffi/scalar/hashing.ts +1 -1
  195. package/src/rust-ffi/scalar/http.ts +71 -27
  196. package/src/rust-ffi/scalar/index.ts +2 -0
  197. package/src/rust-ffi/scalar/interface.ts +20 -0
  198. package/src/rust-ffi/scalar/payload.ts +11 -3
  199. package/src/rust-ffi/scalar/validation.ts +121 -0
  200. package/src/rust-ffi/text.ts +25 -3
  201. package/src/selection.ts +1 -1
  202. package/src/shared/bytes.ts +24 -4
  203. package/src/shared/codec.ts +18 -3
  204. package/src/task/index.ts +24 -0
  205. package/src/task/op.ts +171 -0
  206. package/src/task/runtime.ts +568 -0
package/Cargo.toml ADDED
@@ -0,0 +1,155 @@
1
+ [package]
2
+ name = "castrum"
3
+ # Keep in sync with package.json "version" (single source of truth: the npm package).
4
+ version = "0.9.6"
5
+ edition = "2021"
6
+ # Keep in sync with package.json "license" (cargo-deny rejects a crate with no
7
+ # license expression).
8
+ license = "MIT"
9
+
10
+ [lib]
11
+ name = "castrum"
12
+ crate-type = ["cdylib", "rlib"]
13
+ path = "rust/lib.rs"
14
+
15
+ # Native-only benchmark binary: times the pure-Rust cores (crc32, hashing,
16
+ # hex/base64/url, validators, packed parsers, gzip/brotli, ...) with NO JS / FFI
17
+ # boundary, so bench/ffi-margin.ts can compare them against the same ops called
18
+ # through bun:ffi and pinpoint exactly where the crossing cost is. Diagnostic
19
+ # only — never shipped; NOT part of the addon surface.
20
+ [[bin]]
21
+ name = "native-bench"
22
+ path = "rust/src/bin/native-bench.rs"
23
+ required-features = ["native-bench"]
24
+
25
+ [dependencies]
26
+ napi = { version = "3", features = ["napi10", "serde-json"] }
27
+ napi-derive = "3"
28
+
29
+ serde = { version = "1", features = ["derive"] }
30
+ # preserve_order: IndexMap for serde_json::Value objects -> faster DOM build + O(1)
31
+ # object lookups during jsonschema validation (BTreeMap default is O(log n)).
32
+ # Key order becomes insertion order; correctness checks are order-insensitive.
33
+ serde_json = { version = "1", features = ["preserve_order"] }
34
+ # sort_keys: sonic's owned `Value` object backs mutable objects with
35
+ # AHashMap (non-deterministic iteration order) unless `sort_keys` is enabled,
36
+ # which swaps the owned map to BTreeMap → DETERMINISTIC sorted serialization.
37
+ # Determinism is a hard wire-format requirement: JWT sign (iat/exp injection)
38
+ # and the RFC 6902 patch engine must emit byte-identical output across the
39
+ # FFI/napi/scalar/bulk transports. Parsed (unmutated) values keep the shared
40
+ # Vec representation (insertion order) — only mutation switches to the map.
41
+ sonic-rs = { version = "0.5", features = ["sort_keys"] }
42
+
43
+ # default-features=false: drop resolve-http + tls-aws-lc-rs which pull in
44
+ # reqwest -> hyper/h2/tokio/rustls (large binary, attack surface). Format
45
+ # validators (email etc.) are built-in and NOT feature-gated in 0.48.
46
+ jsonschema = { version = "0.49", default-features = false, features = ["resolve-file"] }
47
+ aws-lc-rs = "1"
48
+ # NOTE: base64 0.23 enables SIMD (SSE/AVX) by default via the `simd-unsafe`
49
+ # feature (part of `default`); no explicit feature is needed.
50
+ base64 = "0.23"
51
+ crc32fast = "1"
52
+ httparse = "1"
53
+ mime_guess = "2"
54
+ phf = { version = "0.14", features = ["macros"] }
55
+ getrandom = "0.4"
56
+ memchr = "2"
57
+ simdutf8 = "0.1"
58
+ email_address = "0.2"
59
+ fast_chemail = { version = "0.9", optional = true }
60
+ # Replicate jsonschema 0.48.5's format:"email" hostname validation (punycode
61
+ # A-labels + RFC 5892 PVALID/contextual rules) on the zero-DOM fast path. Same
62
+ # crates/versions the jsonschema crate uses, so the fast path stays byte-parity.
63
+ idna = "1"
64
+ unicode-general-category = "1"
65
+ rayon = "1"
66
+ # mimalloc is set as the Rust #[global_allocator] (see rust/lib.rs). We DELIBERATELY
67
+ # do NOT enable the "override" feature: it interposes libc malloc/free at the
68
+ # process level, which is an embedding hazard when this cdylib is dlopen'd into
69
+ # Bun (which itself embeds mimalloc -> symbol clashes). The Rust-level global
70
+ # allocator keeps most of the allocation win without replacing the host malloc.
71
+ mimalloc = { version = "0.1", features = ["local_dynamic_tls"] }
72
+ core_affinity = "0.8"
73
+
74
+ parking_lot = "0.12"
75
+ xxhash-rust = { version = "0.8", features = ["xxh3"] }
76
+ ipnet = "2"
77
+ # 0.18.2+ carries the RUSTSEC-2026-0253 fix (0.16.x is affected); keep this
78
+ # requirement at or above the fixed release so `cargo deny` / OSV stay green.
79
+ lru = "0.18.2"
80
+ # Zero-cost hashing for fast_schema object-key lookups (default SipHash is slow
81
+ # on short keys). Already a transitive dep, so no new download.
82
+ rustc-hash = "2"
83
+ # fast_schema extended-keyword parity: fancy-regex is the SAME regex engine the
84
+ # jsonschema crate uses for `pattern`/`patternProperties` (ECMA-262 semantics incl.
85
+ # lookahead/backrefs); fraction::BigFraction is the SAME exact-rational type used
86
+ # for `multipleOf` divisibility. Both are already transitive deps, so no new
87
+ # downloads — but they become direct deps so fast_schema can use them.
88
+ fancy-regex = "0.19"
89
+ fraction = "0.15"
90
+ # Exact cross-type number equality for enum/const/uniqueItems (same semantics
91
+ # jsonschema uses via jsonschema-value's cmp::equal). Already transitive.
92
+ num-cmp = "0.1"
93
+
94
+ # Backend-framework feature additions (Phase A/B/C)
95
+ # argon2id password hashing (password-hash/rand features are default-on).
96
+ argon2 = "0.5"
97
+ # bcrypt password hashing (pure-Rust, Blowfish-based).
98
+ bcrypt = "0.16"
99
+ # PBKDF2-HMAC-SHA256 (RustCrypto) — pure-Rust KDF.
100
+ pbkdf2 = "0.12"
101
+ # sha2 is consumed ONLY by pbkdf2 (digest 0.10). Do NOT bump to 0.11: that
102
+ # moves `Sha256` to digest 0.11 while pbkdf2 0.12 still requires digest 0.10,
103
+ # so `pbkdf2_hmac::<Sha256>` stops compiling (E0277 CoreProxy). Revisit only
104
+ # together with a pbkdf2 release that depends on digest 0.11.
105
+ sha2 = "0.10"
106
+ # HTML templating (fast, safe, no eval).
107
+ minijinja = "2"
108
+ # gzip via the memory-safe zlib-rs backend (pure Rust, no C).
109
+ flate2 = { version = "1", default-features = false, features = ["zlib-rs"] }
110
+ # brotli compression (pure Rust port).
111
+ brotli = "8"
112
+
113
+ [build-dependencies]
114
+ napi-build = "2"
115
+
116
+ [dev-dependencies]
117
+ # Property-based testing for the security-sensitive wire parsers (fuzz-style
118
+ # with automatic shrinking) — complements the deterministic xorshift corpus in
119
+ # rust/test_support.rs. Runs under `cargo test`; not part of the shipped addon.
120
+ proptest = "1"
121
+
122
+ [features]
123
+ default = ["fast-email"]
124
+ fast-email = ["dep:fast_chemail"]
125
+ # Diagnostic-only gate for the `native-bench` binary (see the [[bin]] below):
126
+ # without this feature the bin is not a default target, so `napi build` — and
127
+ # therefore every shipped cross-compiled artifact — never links it. The napi
128
+ # cross toolchains cannot resolve the aws-lc-sys C symbols an executable needs
129
+ # (`undefined reference to __isoc23_sscanf`), while a cdylib tolerates them.
130
+ # Run it with: cargo run --release --features native-bench --bin native-bench
131
+ native-bench = []
132
+
133
+ # Codify the CI clippy gate (`cargo clippy --all-targets -- -D warnings`) so a
134
+ # bare local `cargo clippy` fails on the same lints — no flag drift between
135
+ # laptop and CI. Clippy-only lints: normal `cargo build`/`test` are unaffected.
136
+ [lints.clippy]
137
+ all = "deny"
138
+
139
+ [profile.release]
140
+ opt-level = 3
141
+ lto = "fat"
142
+ codegen-units = 1
143
+ strip = "symbols"
144
+ debug = 0
145
+ incremental = false
146
+ # Safety: this is an embedded cdylib loaded into the Bun process. panic = "unwind"
147
+ # (the default) lets napi's catch_unwind convert Rust panics into JS exceptions
148
+ # instead of aborting the host process. overflow-checks = true catches integer
149
+ # overflow in release; the cost is negligible relative to the safety gain.
150
+ overflow-checks = true
151
+ debug-assertions = false
152
+
153
+ [profile.release.package."*"]
154
+ opt-level = 3
155
+ codegen-units = 1
package/README.md CHANGED
@@ -34,6 +34,12 @@ bun install
34
34
  bun run build # compile the Rust addon (release)
35
35
  ```
36
36
 
37
+ > **Cross-platform install**: prebuilt addons ship for linux (x64/arm64,
38
+ > glibc + musl), macOS (x64/arm64), and Windows (x64 msvc) — built by CI on
39
+ > every push/PR and published on a `v*` tag. When no prebuilt matches your
40
+ > platform, the package `postinstall` hook compiles the addon from source in
41
+ > your `node_modules` (`cargo build --release`, needs a Rust toolchain).
42
+
37
43
  ### 2. Start a server
38
44
 
39
45
  ```ts
@@ -181,17 +187,19 @@ For coverage floors, the typecheck/test configs, and the full test matrix, see
181
187
  ## Publishing
182
188
 
183
189
  The package ships **all platform addons in a single tarball**. Push a `v*` tag
184
- and CI builds + publishes every platform to npm; or use `bun run publish:manual`
190
+ and CI builds + publishes every platform to npm; or use `bun run release:manual`
185
191
  for a quick single-platform release:
186
192
 
187
193
  ```bash
188
- bun run publish:manual -- --increment minor # bump + tag + build + publish
189
- bun run publish:manual:dry # print the plan, change nothing
194
+ bun run release minor # bump + verify + commit + tag (CI publishes)
195
+ bun run release:manual # same, but also builds + publishes locally
196
+ bun run release:dry # print the plan, change nothing
190
197
  ```
191
198
 
192
- Run `bun run check:version` before tagging (it verifies `package.json`,
193
- `Cargo.toml`, and `CHANGELOG.md` agree). See [`docs/REPO_MAP.md`](./docs/REPO_MAP.md)
194
- §6 for the full flow.
199
+ `bun run release` uses the shared canonical flow (`scripts/release.ts` +
200
+ `.release.json`), syncing `package.json`, `Cargo.toml`, `Cargo.lock`, and
201
+ `CHANGELOG.md`. Run `bun run check:version` before tagging (it verifies they
202
+ agree). See [`docs/REPO_MAP.md`](./docs/REPO_MAP.md) §6 for the full flow.
195
203
 
196
204
  ## Documentation
197
205
 
package/build.rs ADDED
@@ -0,0 +1,5 @@
1
+ extern crate napi_build;
2
+
3
+ fn main() {
4
+ napi_build::setup();
5
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file