castrum 0.9.1 → 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.
- package/README.md +1 -1
- package/castrum.linux-x64-gnu.node +0 -0
- package/dist/index.d.ts +239 -5
- package/dist/index.js +3852 -3375
- package/docs/ARCHITECTURE.md +11 -9
- package/docs/BENCHMARKS.md +70 -38
- package/docs/CASE_STUDY.md +10 -7
- package/docs/ENVIRONMENT.md +16 -1
- package/docs/FFI_BUN_GUIDE.md +18 -10
- package/docs/GETTING_STARTED.md +5 -4
- package/docs/HOW_TO_ADD_AN_OP.md +180 -0
- package/docs/INGRESS-ROUTER.md +3 -2
- package/docs/INGRESS.md +6 -3
- package/docs/NATIVE-ROUTE.md +28 -4
- package/docs/REPO_MAP.md +60 -30
- package/docs/adr/0001-two-wire-formats.md +1 -1
- package/docs/ai/LOCAL_DEV.md +81 -0
- package/docs/ai/TREE.md +1070 -0
- package/package.json +24 -23
- package/src/ingress/decode/result-base.ts +10 -2
- package/src/ingress/handlers.ts +45 -290
- package/src/ingress/headers/security.ts +41 -0
- package/src/ingress/index.ts +12 -148
- package/src/ingress/native-route.ts +182 -0
- package/src/ingress/packing/gather-raw-headers.ts +26 -2
- package/src/ingress/packing/route-wire.ts +197 -0
- package/src/ingress/packing/select-headers.ts +8 -1
- package/src/ingress/path-matcher.ts +115 -0
- package/src/ingress/response/baked-response.ts +302 -0
- package/src/ingress/router.ts +42 -2
- package/src/ingress/routes/common.ts +9 -1
- package/src/ingress/routes/json-write.ts +21 -18
- package/src/ingress/routes/native.ts +130 -0
- package/src/ingress/server-node.ts +1 -1
- package/src/ingress/server.ts +38 -99
- package/src/ingress/sync.ts +151 -0
- package/src/ingress/types.ts +9 -0
- package/src/native/ffi/build/codecs.ts +736 -0
- package/src/native/ffi/build/compress.ts +248 -0
- package/src/native/ffi/build/instances.ts +598 -0
- package/src/native/ffi/build/parse.ts +539 -0
- package/src/native/ffi/build/util.ts +140 -0
- package/src/native/ffi/build.ts +94 -0
- package/src/native/ffi/selftest.ts +11 -718
- package/src/native/ffi/types.ts +25 -0
- package/src/native/ffi.ts +36 -1320
- package/src/native/types/instances.ts +5 -0
- package/src/rust-ffi/packed.ts +38 -0
- package/src/rust-ffi/scalar/factories.ts +4 -0
|
@@ -163,6 +163,11 @@ export interface EncodingPrefResult {
|
|
|
163
163
|
export interface AcceptNegotiatorInstance {
|
|
164
164
|
/** Best supported encoding for `header`, or null for identity. */
|
|
165
165
|
negotiate(header: Uint8Array): string | null
|
|
166
|
+
/** Best supported encoding for `header` with SERVER-preference tie-breaking
|
|
167
|
+
* (RFC 7231 server semantics — the supported list's order breaks q-value
|
|
168
|
+
* ties), or null for identity. On the napi fallback this is the projected
|
|
169
|
+
* `negotiate_server_preference` method. */
|
|
170
|
+
negotiateServerPreference(header: Uint8Array): string | null
|
|
166
171
|
/** Opaque handle (bun:ffi fast path) — `castrum_accept_negotiator_negotiate`. */
|
|
167
172
|
innerPtr?(): bigint
|
|
168
173
|
}
|
package/src/rust-ffi/packed.ts
CHANGED
|
@@ -10,15 +10,25 @@ import { asNumber } from './options'
|
|
|
10
10
|
/** Raw packed-wire FFI namespace. */
|
|
11
11
|
export interface RustPacked {
|
|
12
12
|
// ── Sync batch (packed in → packed out) ──
|
|
13
|
+
/** Packed CRC32 batch: packed `[u8[]]` items → packed u32 results. */
|
|
13
14
|
crc32BatchPacked(input: Uint8Array): Uint8Array
|
|
15
|
+
/** Packed JSON-validity batch: packed `[u8[]]` items → packed 0/1 bitset. */
|
|
14
16
|
jsonValidBatchPacked(input: Uint8Array): Uint8Array
|
|
17
|
+
/** Packed email-validator batch: packed `[u8[]]` items → packed 0/1 bitset. */
|
|
15
18
|
validateEmailBatchPacked(input: Uint8Array): Uint8Array
|
|
19
|
+
/** Packed UUID-validator batch: packed `[u8[]]` items → packed 0/1 bitset. */
|
|
16
20
|
validateUuidBatchPacked(input: Uint8Array): Uint8Array
|
|
21
|
+
/** Packed IPv4-validator batch: packed `[u8[]]` items → packed 0/1 bitset. */
|
|
17
22
|
validateIpv4BatchPacked(input: Uint8Array): Uint8Array
|
|
23
|
+
/** Packed IPv6-validator batch: packed `[u8[]]` items → packed 0/1 bitset. */
|
|
18
24
|
validateIpv6BatchPacked(input: Uint8Array): Uint8Array
|
|
25
|
+
/** Packed JSON-sum batch: packed `[{id}]` docs → packed `[ok u8][sum i64 LE]`. */
|
|
19
26
|
jsonSumBatchPacked(input: Uint8Array): Uint8Array
|
|
27
|
+
/** Packed query-string parser batch: packed `[u8[]]` queries → packed pair lists. */
|
|
20
28
|
queryParseBatchPacked(input: Uint8Array): Uint8Array
|
|
29
|
+
/** Packed cookie-header parser batch: packed `[u8[]]` headers → packed pair lists. */
|
|
21
30
|
cookieParseBatchPacked(input: Uint8Array): Uint8Array
|
|
31
|
+
/** Packed HTTP-request parser batch: packed `[u8[]]` requests → packed request sections. */
|
|
22
32
|
httpParseRequestBatchPacked(input: Uint8Array): Uint8Array
|
|
23
33
|
/** Batch RFC 6902 JSON Patch (two packed lists, zipped) → packed results. */
|
|
24
34
|
jsonPatchBatchPacked(docs: Uint8Array, patches: Uint8Array): Uint8Array
|
|
@@ -26,24 +36,39 @@ export interface RustPacked {
|
|
|
26
36
|
fnv1A64BatchPacked(input: Uint8Array): Uint8Array
|
|
27
37
|
/** Packed ETag batch (10 strong / 12 weak bytes per item). */
|
|
28
38
|
etagBatchPacked(input: Uint8Array, weak?: boolean | null): Uint8Array
|
|
39
|
+
/** Packed percent-encoding batch: packed `[u8[]]` items → packed hex-percent bytes. */
|
|
29
40
|
urlEncodeBatchPacked(input: Uint8Array): Uint8Array
|
|
41
|
+
/** Packed percent-decoding batch: packed `[u8[]]` items → packed decoded bytes (string-safe). */
|
|
30
42
|
urlDecodeBatchPacked(input: Uint8Array): Uint8Array
|
|
43
|
+
/** Packed percent-decoding batch returning raw bytes (`%FF` preserved). */
|
|
31
44
|
urlDecodeBytesBatchPacked(input: Uint8Array): Uint8Array
|
|
45
|
+
/** Packed MIME-lookup batch: packed `[u8[]]` extensions → packed media-type strings. */
|
|
32
46
|
mimeFromExtensionBatchPacked(input: Uint8Array): Uint8Array
|
|
47
|
+
/** Packed WebSocket accept-key batch: packed `[u8[]]` keys → packed base64 SHA-1 results. */
|
|
33
48
|
wsAcceptKeyBatchPacked(input: Uint8Array): Uint8Array
|
|
34
49
|
|
|
35
50
|
// ── Batch metadata / counts ──
|
|
51
|
+
/** Valid JSON count in a packed JSON batch (0..n; invalid items not counted). */
|
|
36
52
|
jsonValidBatchCountPacked(input: Uint8Array): number
|
|
53
|
+
/** Valid-email count in a packed email batch. */
|
|
37
54
|
validateEmailBatchCountPacked(input: Uint8Array): number
|
|
55
|
+
/** Valid-UUID count in a packed UUID batch. */
|
|
38
56
|
validateUuidBatchCountPacked(input: Uint8Array): number
|
|
57
|
+
/** Valid-IPv4 count in a packed IPv4 batch. */
|
|
39
58
|
validateIpv4BatchCountPacked(input: Uint8Array): number
|
|
59
|
+
/** Valid-IPv6 count in a packed IPv6 batch. */
|
|
40
60
|
validateIpv6BatchCountPacked(input: Uint8Array): number
|
|
61
|
+
/** Total `id` sum across a packed JSON batch (valid items only). */
|
|
41
62
|
jsonSumBatchTotalPacked(input: Uint8Array): number
|
|
63
|
+
/** Total packed-output length (bytes) a query batch will produce. */
|
|
42
64
|
queryParseBatchTotalLenPacked(input: Uint8Array): number
|
|
65
|
+
/** Total packed-output length (bytes) a cookie batch will produce. */
|
|
43
66
|
cookieParseBatchTotalLenPacked(input: Uint8Array): number
|
|
67
|
+
/** Total packed-output length (bytes) an HTTP-request batch will produce. */
|
|
44
68
|
httpParseRequestBatchTotalLenPacked(input: Uint8Array): number
|
|
45
69
|
|
|
46
70
|
// ── Backend-framework features ──
|
|
71
|
+
/** Packed Argon2id-hash batch: packed `[u8[]]` passwords + shared salt → packed PHC strings. */
|
|
47
72
|
passwordHashBatchPacked(
|
|
48
73
|
input: Uint8Array,
|
|
49
74
|
salt: Uint8Array,
|
|
@@ -53,47 +78,60 @@ export interface RustPacked {
|
|
|
53
78
|
passwordVerifyBatchPacked(passwords: Uint8Array, phcs: Uint8Array): Uint8Array
|
|
54
79
|
/** Packed URL-resolve batch (two packed lists, zipped) → packed results. */
|
|
55
80
|
urlResolveBatchPacked(bases: Uint8Array, references: Uint8Array): Uint8Array
|
|
81
|
+
/** Packed AEAD-encrypt batch (packed inputs + shared key/nonce) → packed ciphertexts. */
|
|
56
82
|
aeadEncryptBatchPacked(
|
|
57
83
|
input: Uint8Array,
|
|
58
84
|
key: Uint8Array,
|
|
59
85
|
nonce: Uint8Array,
|
|
60
86
|
algorithm?: string | null,
|
|
61
87
|
): Uint8Array
|
|
88
|
+
/** Packed AEAD-decrypt batch (packed inputs + shared key/nonce) → packed plaintexts. */
|
|
62
89
|
aeadDecryptBatchPacked(
|
|
63
90
|
input: Uint8Array,
|
|
64
91
|
key: Uint8Array,
|
|
65
92
|
nonce: Uint8Array,
|
|
66
93
|
algorithm?: string | null,
|
|
67
94
|
): Uint8Array
|
|
95
|
+
/** Packed gzip-compress batch: packed `[u8[]]` items → packed gzip streams. */
|
|
68
96
|
gzipCompressBatchPacked(input: Uint8Array, level?: number | null): Uint8Array
|
|
97
|
+
/** Packed gzip-decompress batch (64 MiB cap per item) → packed plaintexts. */
|
|
69
98
|
gzipDecompressBatchPacked(input: Uint8Array): Uint8Array
|
|
99
|
+
/** Packed brotli-compress batch: packed `[u8[]]` items → packed brotli streams. */
|
|
70
100
|
brotliCompressBatchPacked(input: Uint8Array, quality?: number | null): Uint8Array
|
|
101
|
+
/** Packed brotli-decompress batch (64 MiB cap per item) → packed plaintexts. */
|
|
71
102
|
brotliDecompressBatchPacked(input: Uint8Array): Uint8Array
|
|
103
|
+
/** Packed HS256 JWT-sign batch (packed claims + shared secret) → packed tokens. */
|
|
72
104
|
jwtSignBatchPacked(
|
|
73
105
|
input: Uint8Array,
|
|
74
106
|
secret: Uint8Array,
|
|
75
107
|
ttlSeconds: number | null,
|
|
76
108
|
nowSeconds: number,
|
|
77
109
|
): Uint8Array
|
|
110
|
+
/** Packed HS256 JWT-verify batch (packed tokens + shared secret) → packed claims/validity. */
|
|
78
111
|
jwtVerifyBatchPacked(input: Uint8Array, secret: Uint8Array, nowSeconds: number): Uint8Array
|
|
79
112
|
/** Batch HMAC-SHA256 sign (packed in → hex-signature byte results). */
|
|
80
113
|
hmacSha256BatchPacked(input: Uint8Array, key: Uint8Array): Uint8Array
|
|
81
114
|
/** Batch HMAC-SHA256 verify (two packed lists: data + hex sigs, zipped) → bitset. */
|
|
82
115
|
hmacSha256VerifyBatchPacked(input: Uint8Array, sigs: Uint8Array, key: Uint8Array): Uint8Array
|
|
116
|
+
/** Packed multipart/form-data parser batch (packed bodies + shared boundary) → packed parts. */
|
|
83
117
|
multipartParseBatchPacked(input: Uint8Array, boundary: Uint8Array): Uint8Array
|
|
118
|
+
/** Packed minijinja template batch: packed contexts + shared source → packed renders. */
|
|
84
119
|
templateRenderBatchPacked(input: Uint8Array, source: string): Uint8Array
|
|
120
|
+
/** Packed SSE-frame batch: packed data + shared event/id/retry → packed frames. */
|
|
85
121
|
sseEncodeBatchPacked(
|
|
86
122
|
input: Uint8Array,
|
|
87
123
|
event: string | null,
|
|
88
124
|
id: string | null,
|
|
89
125
|
retry: number | null,
|
|
90
126
|
): Uint8Array
|
|
127
|
+
/** Packed WebSocket-frame encode batch: packed payloads + shared opcode/mask/fin → packed frames. */
|
|
91
128
|
wsFrameEncodeBatchPacked(
|
|
92
129
|
input: Uint8Array,
|
|
93
130
|
opcode: number,
|
|
94
131
|
mask: boolean,
|
|
95
132
|
fin: boolean,
|
|
96
133
|
): Uint8Array
|
|
134
|
+
/** Packed WebSocket-frame decode batch: packed frames → packed (fin, opcode, payload) results. */
|
|
97
135
|
wsFrameDecodeBatchPacked(input: Uint8Array): Uint8Array
|
|
98
136
|
}
|
|
99
137
|
|
|
@@ -162,6 +162,10 @@ function ffiAcceptNegotiator(
|
|
|
162
162
|
void keepAlive
|
|
163
163
|
return ffi.acceptNegotiatorNegotiate(inner, header)
|
|
164
164
|
},
|
|
165
|
+
negotiateServerPreference(header) {
|
|
166
|
+
void keepAlive
|
|
167
|
+
return ffi.acceptNegotiatorNegotiateServer(inner, header)
|
|
168
|
+
},
|
|
165
169
|
}
|
|
166
170
|
}
|
|
167
171
|
|