@zintrust/core 0.9.5 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.9.5",
3
+ "version": "1.2.0",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
@@ -73,9 +73,9 @@
73
73
  "axios": "^1.15.0",
74
74
  "@eslint/plugin-kit": "^0.7.1",
75
75
  "follow-redirects": "^1.16.0",
76
- "@tootallnate/once": "^3.0.1",
76
+ "@tootallnate/once": "3.0.1",
77
77
  "node-forge": "^1.4.0",
78
- "fast-xml-parser": "^5.7.1",
78
+ "fast-xml-parser": "5.7.1",
79
79
  "brace-expansion": "^5.0.5",
80
80
  "picomatch": "^4.0.4",
81
81
  "cross-spawn": "^7.0.5",
@@ -84,7 +84,7 @@
84
84
  "rollup": "^4.59.0",
85
85
  "vite": "^8.0.5",
86
86
  "flatted": "^3.4.2",
87
- "uuid": "^14.0.0",
87
+ "uuid": "14.0.0",
88
88
  "@actions/github": {
89
89
  "undici": "^6.24.0"
90
90
  },
@@ -94,24 +94,10 @@
94
94
  "miniflare": {
95
95
  "undici": "^7.24.4"
96
96
  },
97
- "@aws-sdk/xml-builder": {
98
- "fast-xml-parser": "^5.7.1"
99
- },
100
- "@aws-sdk/xml-builder@3.972.18": {
101
- "fast-xml-parser": "^5.7.1"
102
- },
103
- "@google-cloud/storage": {
104
- "uuid": "^14.0.0"
105
- },
106
- "@google-cloud/storage@7.19.0": {
107
- "uuid": "^14.0.0"
108
- },
109
- "gaxios": {
110
- "uuid": "^14.0.0"
111
- },
112
- "teeny-request": {
113
- "uuid": "^14.0.0"
114
- }
97
+ "http-proxy-agent": "7.0.2",
98
+ "retry-request": "8.0.2",
99
+ "gaxios": "7.1.4",
100
+ "teeny-request": "10.1.2"
115
101
  },
116
102
  "bin": {
117
103
  "zintrust": "bin/zintrust.js",
@@ -78,7 +78,7 @@ export const EnvKeyGenerateCommand = Object.freeze({
78
78
  }
79
79
  envContent = upsertEnvValue(envContent, envKey, key);
80
80
  await fs.writeFile(envPath, envContent);
81
- Logger.info(`${envKey} set successfully. [${key}]`);
81
+ Logger.info(`${envKey} set successfully.`);
82
82
  }
83
83
  catch (error) {
84
84
  Logger.error(`Failed to update ${envKey} in .env`, error);
package/src/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @zintrust/core v0.9.5
2
+ * @zintrust/core v1.2.0
3
3
  *
4
4
  * ZinTrust Framework - Production-Grade TypeScript Backend
5
5
  * Built for performance, type safety, and exceptional developer experience
6
6
  *
7
7
  * Build Information:
8
- * Built: 2026-04-23T13:02:57.049Z
8
+ * Built: 2026-04-24T08:45:23.492Z
9
9
  * Node: >=20.0.0
10
10
  * License: MIT
11
11
  *
@@ -21,7 +21,7 @@
21
21
  * Available at runtime for debugging and health checks
22
22
  */
23
23
  export const ZINTRUST_VERSION = '0.1.41';
24
- export const ZINTRUST_BUILD_DATE = '2026-04-23T13:02:57.015Z'; // Replaced during build
24
+ export const ZINTRUST_BUILD_DATE = '2026-04-24T08:45:23.460Z'; // Replaced during build
25
25
  export { Application } from './boot/Application.js';
26
26
  export { AwsSigV4 } from './common/index.js';
27
27
  export { SignedRequest } from './security/SignedRequest.js';
@@ -1,17 +1,6 @@
1
- export type ProxyNoncePutOptions = {
2
- expirationTtl?: number;
3
- };
4
- export type ProxyNonceNamespace = {
5
- get: (key: string) => Promise<string | null>;
6
- put: (key: string, value: string, options?: ProxyNoncePutOptions) => Promise<void>;
7
- };
8
- type SignedRequestOptions = Readonly<{
9
- secretEnvVar: string;
10
- missingSecretStatus: number;
11
- missingSecretMessage: string;
12
- defaultSigningWindowMs: number;
13
- }>;
14
- type ReadAndVerifyJsonOptions = SignedRequestOptions & Readonly<{
1
+ import type { WorkerSigningOptions } from './WorkerSigning';
2
+ export type { ProxyNonceNamespace, ProxyNoncePutOptions, WorkerSigningOptions, } from './WorkerSigning';
3
+ type ReadAndVerifyJsonOptions = WorkerSigningOptions & Readonly<{
15
4
  defaultMaxBodyBytes: number;
16
5
  }>;
17
6
  type ProxyRequestEnv = object;
@@ -34,8 +23,7 @@ export declare const parseOptionalJson: (text: string) => {
34
23
  ok: false;
35
24
  response: Response;
36
25
  };
37
- export declare const verifyNonceKv: (kv: ProxyNonceNamespace, keyId: string, nonce: string, ttlMs: number) => Promise<boolean>;
38
- export declare const verifySignedRequest: (request: Request, env: ProxyRequestEnv, bodyBytes: Uint8Array, options: SignedRequestOptions) => Promise<Response | {
26
+ export declare const verifySignedRequest: (request: Request, env: ProxyRequestEnv, bodyBytes: Uint8Array, options: WorkerSigningOptions) => Promise<Response | {
39
27
  ok: true;
40
28
  }>;
41
29
  export declare const readAndVerifyJson: (request: Request, env: ProxyRequestEnv, options: ReadAndVerifyJsonOptions) => Promise<{
@@ -46,5 +34,4 @@ export declare const readAndVerifyJson: (request: Request, env: ProxyRequestEnv,
46
34
  ok: false;
47
35
  response: Response;
48
36
  }>;
49
- export {};
50
37
  //# sourceMappingURL=CloudflareProxyShared.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CloudflareProxyShared.d.ts","sourceRoot":"","sources":["../../../src/proxy/CloudflareProxyShared.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,oBAAoB,GAAG;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpF,CAAC;AAEF,KAAK,oBAAoB,GAAG,QAAQ,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAAC,CAAC;AAEH,KAAK,wBAAwB,GAAG,oBAAoB,GAClD,QAAQ,CAAC;IACP,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC,CAAC;AAEL,KAAK,eAAe,GAAG,MAAM,CAAC;AAE9B,eAAO,MAAM,IAAI,GAAI,QAAQ,MAAM,EAAE,MAAM,OAAO,KAAG,QAQpD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,EAAE,SAAS,MAAM,KAAG,QAG/E,CAAC;AAMF,eAAO,MAAM,SAAS,GAAI,KAAK,eAAe,EAAE,MAAM,MAAM,EAAE,UAAU,MAAM,KAAG,MAKhF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,IAI9D,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,SAAS,OAAO,EAChB,UAAU,MAAM,KACf,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAY3F,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,KACX;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAezF,CAAC;AAcF,eAAO,MAAM,aAAa,GACxB,IAAI,mBAAmB,EACvB,OAAO,MAAM,EACb,OAAO,MAAM,EACb,OAAO,MAAM,KACZ,OAAO,CAAC,OAAO,CAOjB,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,SAAS,OAAO,EAChB,KAAK,eAAe,EACpB,WAAW,UAAU,EACrB,SAAS,oBAAoB,KAC5B,OAAO,CAAC,QAAQ,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,CA+BjC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,SAAS,OAAO,EAChB,KAAK,eAAe,EACpB,SAAS,wBAAwB,KAChC,OAAO,CACN;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,UAAU,CAAA;CAAE,GAC5E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAapC,CAAC"}
1
+ {"version":3,"file":"CloudflareProxyShared.d.ts","sourceRoot":"","sources":["../../../src/proxy/CloudflareProxyShared.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGjE,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,KAAK,wBAAwB,GAAG,oBAAoB,GAClD,QAAQ,CAAC;IACP,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC,CAAC;AAEL,KAAK,eAAe,GAAG,MAAM,CAAC;AAE9B,eAAO,MAAM,IAAI,GAAI,QAAQ,MAAM,EAAE,MAAM,OAAO,KAAG,QAQpD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,EAAE,SAAS,MAAM,KAAG,QAG/E,CAAC;AAMF,eAAO,MAAM,SAAS,GAAI,KAAK,eAAe,EAAE,MAAM,MAAM,EAAE,UAAU,MAAM,KAAG,MAKhF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,IAI9D,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,SAAS,OAAO,EAChB,UAAU,MAAM,KACf,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAY3F,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,KACX;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAezF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,SAAS,OAAO,EAChB,KAAK,eAAe,EACpB,WAAW,UAAU,EACrB,SAAS,oBAAoB,KAC5B,OAAO,CAAC,QAAQ,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,CAQjC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,SAAS,OAAO,EAChB,KAAK,eAAe,EACpB,SAAS,wBAAwB,KAChC,OAAO,CACN;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,UAAU,CAAA;CAAE,GAC5E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAapC,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { isString } from '../helper/index.js';
2
2
  import { ErrorHandler } from './ErrorHandler.js';
3
3
  import { RequestValidator } from './RequestValidator.js';
4
- import { SigningService } from './SigningService.js';
4
+ import { WorkerSigning } from './WorkerSigning.js';
5
5
  export const json = (status, body) => {
6
6
  return new Response(JSON.stringify(body), {
7
7
  status,
@@ -59,44 +59,8 @@ export const parseOptionalJson = (text) => {
59
59
  }
60
60
  return { ok: true, payload: parsed.value };
61
61
  };
62
- const loadSigningSecret = (env, secretEnvVar) => {
63
- const directValue = getEnvValue(env, secretEnvVar);
64
- const direct = isString(directValue) ? directValue.trim() : '';
65
- if (direct !== '')
66
- return direct;
67
- const fallbackValue = getEnvValue(env, 'APP_KEY');
68
- const fallback = isString(fallbackValue) ? fallbackValue.trim() : '';
69
- if (fallback !== '')
70
- return fallback;
71
- return null;
72
- };
73
- export const verifyNonceKv = async (kv, keyId, nonce, ttlMs) => {
74
- const ttlSeconds = Math.max(1, Math.ceil(ttlMs / 1000));
75
- const storageKey = `nonce:${keyId}:${nonce}`;
76
- const existing = await kv.get(storageKey);
77
- if (existing !== null)
78
- return false;
79
- await kv.put(storageKey, '1', { expirationTtl: ttlSeconds });
80
- return true;
81
- };
82
62
  export const verifySignedRequest = async (request, env, bodyBytes, options) => {
83
- const secret = loadSigningSecret(env, options.secretEnvVar);
84
- if (secret === null) {
85
- return toErrorResponse(options.missingSecretStatus, 'CONFIG_ERROR', options.missingSecretMessage);
86
- }
87
- const windowMs = getEnvInt(env, 'ZT_PROXY_SIGNING_WINDOW_MS', options.defaultSigningWindowMs);
88
- const nonceStore = getEnvValue(env, 'ZT_NONCES');
89
- const verifyResult = await SigningService.verifyWithKeyProvider({
90
- method: request.method,
91
- url: request.url,
92
- body: bodyBytes,
93
- headers: request.headers,
94
- windowMs,
95
- getSecretForKeyId: (_keyId) => secret,
96
- verifyNonce: nonceStore === undefined || nonceStore === null
97
- ? undefined
98
- : async (keyId, nonce, ttlMs) => verifyNonceKv(nonceStore, keyId, nonce, ttlMs),
99
- });
63
+ const verifyResult = await WorkerSigning.verifySignedRequest(request, env, bodyBytes, options);
100
64
  if (!verifyResult.ok) {
101
65
  return toErrorResponse(verifyResult.status, verifyResult.code, verifyResult.message);
102
66
  }
@@ -0,0 +1,33 @@
1
+ export type ProxyNoncePutOptions = {
2
+ expirationTtl?: number;
3
+ };
4
+ export type ProxyNonceNamespace = {
5
+ get: (key: string) => Promise<string | null>;
6
+ put: (key: string, value: string, options?: ProxyNoncePutOptions) => Promise<void>;
7
+ };
8
+ export type WorkerSigningOptions = Readonly<{
9
+ secretEnvVar: string;
10
+ missingSecretStatus: number;
11
+ missingSecretMessage: string;
12
+ defaultSigningWindowMs: number;
13
+ }>;
14
+ type WorkerRequestEnv = object;
15
+ type WorkerSigningResult = {
16
+ ok: true;
17
+ } | {
18
+ ok: false;
19
+ status: number;
20
+ code: string;
21
+ message: string;
22
+ };
23
+ export declare const WorkerSigning: Readonly<{
24
+ verifyNonceKv: (kv: ProxyNonceNamespace, keyId: string, nonce: string, ttlMs: number) => Promise<boolean>;
25
+ verifySignedRequest: (request: Request, env: WorkerRequestEnv, bodyBytes: Uint8Array, options: WorkerSigningOptions) => Promise<WorkerSigningResult | {
26
+ ok: false;
27
+ status: number;
28
+ code: "CONFIG_ERROR";
29
+ message: string;
30
+ }>;
31
+ }>;
32
+ export {};
33
+ //# sourceMappingURL=WorkerSigning.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkerSigning.d.ts","sourceRoot":"","sources":["../../../src/proxy/WorkerSigning.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,oBAAoB,GAAG;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpF,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAAC,CAAC;AAEH,KAAK,gBAAgB,GAAG,MAAM,CAAC;AAE/B,KAAK,mBAAmB,GACpB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAkGjE,eAAO,MAAM,aAAa;wBAlDpB,mBAAmB,SAChB,MAAM,SACN,MAAM,SACN,MAAM,KACZ,OAAO,CAAC,OAAO,CAAC;mCAUR,OAAO,OACX,gBAAgB,aACV,UAAU,WACZ,oBAAoB,KAC5B,OAAO,CACR,mBAAmB,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAC3F;EAiCC,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { isString } from '../helper/index.js';
2
+ import { SignedRequest } from '../security/SignedRequest.js';
3
+ const getEnvValue = (env, name) => {
4
+ return env[name];
5
+ };
6
+ const getEnvInt = (env, name, fallback) => {
7
+ const raw = getEnvValue(env, name);
8
+ if (!isString(raw))
9
+ return fallback;
10
+ const parsed = Number.parseInt(raw, 10);
11
+ return Number.isFinite(parsed) ? parsed : fallback;
12
+ };
13
+ const loadSigningSecret = (env, secretEnvVar) => {
14
+ const directValue = getEnvValue(env, secretEnvVar);
15
+ const direct = isString(directValue) ? directValue.trim() : '';
16
+ if (direct !== '')
17
+ return direct;
18
+ const fallbackValue = getEnvValue(env, 'APP_KEY');
19
+ const fallback = isString(fallbackValue) ? fallbackValue.trim() : '';
20
+ if (fallback !== '')
21
+ return fallback;
22
+ return null;
23
+ };
24
+ const mapVerifyResult = (result) => {
25
+ if (result.ok)
26
+ return { ok: true };
27
+ if (result.code === 'MISSING_HEADER' || result.code === 'INVALID_TIMESTAMP') {
28
+ return { ok: false, status: 401, code: result.code, message: result.message };
29
+ }
30
+ if (result.code === 'EXPIRED') {
31
+ return { ok: false, status: 401, code: result.code, message: result.message };
32
+ }
33
+ if (result.code === 'UNKNOWN_KEY') {
34
+ return { ok: false, status: 403, code: result.code, message: result.message };
35
+ }
36
+ if (result.code === 'REPLAYED') {
37
+ return { ok: false, status: 409, code: result.code, message: result.message };
38
+ }
39
+ return { ok: false, status: 403, code: result.code, message: result.message };
40
+ };
41
+ const verifyNonceKv = async (kv, keyId, nonce, ttlMs) => {
42
+ const ttlSeconds = Math.max(1, Math.ceil(ttlMs / 1000));
43
+ const storageKey = `nonce:${keyId}:${nonce}`;
44
+ const existing = await kv.get(storageKey);
45
+ if (existing !== null)
46
+ return false;
47
+ await kv.put(storageKey, '1', { expirationTtl: ttlSeconds });
48
+ return true;
49
+ };
50
+ const verifySignedRequest = async (request, env, bodyBytes, options) => {
51
+ const secret = loadSigningSecret(env, options.secretEnvVar);
52
+ if (secret === null) {
53
+ return {
54
+ ok: false,
55
+ status: options.missingSecretStatus,
56
+ code: 'CONFIG_ERROR',
57
+ message: options.missingSecretMessage,
58
+ };
59
+ }
60
+ const windowMs = getEnvInt(env, 'ZT_PROXY_SIGNING_WINDOW_MS', options.defaultSigningWindowMs);
61
+ const nonceStore = getEnvValue(env, 'ZT_NONCES');
62
+ return mapVerifyResult(await SignedRequest.verify({
63
+ method: request.method,
64
+ url: request.url,
65
+ body: bodyBytes,
66
+ headers: request.headers,
67
+ windowMs,
68
+ getSecretForKeyId: (_keyId) => secret,
69
+ verifyNonce: nonceStore === undefined || nonceStore === null
70
+ ? undefined
71
+ : async (keyId, nonce, ttlMs) => verifyNonceKv(nonceStore, keyId, nonce, ttlMs),
72
+ }));
73
+ };
74
+ export const WorkerSigning = Object.freeze({
75
+ verifyNonceKv,
76
+ verifySignedRequest,
77
+ });
package/src/proxy.d.ts CHANGED
@@ -1,7 +1,6 @@
1
- export { RemoteSignedJson } from './common/RemoteSignedJson';
2
1
  export { ZintrustD1Proxy } from './proxy/d1/ZintrustD1Proxy';
3
2
  export { ErrorHandler } from './proxy/ErrorHandler';
4
3
  export { ZintrustKvProxy } from './proxy/kv/ZintrustKvProxy';
5
4
  export { RequestValidator } from './proxy/RequestValidator';
6
- export { SigningService } from './proxy/SigningService';
5
+ export { WorkerSigning } from './proxy/WorkerSigning';
7
6
  //# sourceMappingURL=proxy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
package/src/proxy.js CHANGED
@@ -1,6 +1,5 @@
1
- export { RemoteSignedJson } from './common/RemoteSignedJson.js';
2
1
  export { ZintrustD1Proxy } from './proxy/d1/ZintrustD1Proxy.js';
3
2
  export { ErrorHandler } from './proxy/ErrorHandler.js';
4
3
  export { ZintrustKvProxy } from './proxy/kv/ZintrustKvProxy.js';
5
4
  export { RequestValidator } from './proxy/RequestValidator.js';
6
- export { SigningService } from './proxy/SigningService.js';
5
+ export { WorkerSigning } from './proxy/WorkerSigning.js';
@@ -1,5 +1,5 @@
1
1
  export declare const WorkerAdapterImports: Readonly<{
2
- loaded: true;
3
- ready: Promise<void>;
2
+ loaded: boolean;
3
+ ready: void;
4
4
  }>;
5
5
  //# sourceMappingURL=WorkerAdapterImports.d.ts.map
@@ -22,7 +22,7 @@ const tryImportOptional = async () => {
22
22
  await tryImportProjectRuntime();
23
23
  await import('./WorkerProjectPlugins.js');
24
24
  };
25
- const ready = tryImportOptional();
25
+ const ready = await tryImportOptional();
26
26
  export const WorkerAdapterImports = Object.freeze({
27
27
  loaded: true,
28
28
  ready,
@@ -8,6 +8,31 @@ import {
8
8
  } from '@zintrust/core';
9
9
 
10
10
  export function registerStorageRoutes(router: IRouter): void {
11
+ // Public file serving: /storage/<path>
12
+ Router.get(router, '/storage/:path*', async (req, res) => {
13
+ const raw = req.getParam('path') ?? '';
14
+ const key = typeof raw === 'string' ? decodeURIComponent(raw).replaceAll('\\\u005C', '/') : '';
15
+
16
+ if (key.trim() === '') {
17
+ res.setStatus(400).json({ message: 'Missing path' });
18
+ return;
19
+ }
20
+
21
+ // Respect private folder convention: do not expose keys under `private/`
22
+ if (key.startsWith('private/') || key === 'private') {
23
+ res.setStatus(404).json({ message: 'Not Found' });
24
+ return;
25
+ }
26
+
27
+ try {
28
+ const contents = await Storage.get('local', key);
29
+ res.setHeader(HTTP_HEADERS.CONTENT_TYPE, 'application/octet-stream');
30
+ res.setStatus(200).send(contents);
31
+ } catch {
32
+ res.setStatus(404).json({ message: 'Not Found' });
33
+ }
34
+ });
35
+
11
36
  Router.get(router, '/storage/download', async (req, res) => {
12
37
  const tokenRaw = req.getQueryParam('token');
13
38
  const token = typeof tokenRaw === 'string' ? tokenRaw : '';
@@ -1 +1 @@
1
- {"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../../../../src/tools/http/Http.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAElF,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,MAAM,eAAe,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,MAAM,GACN,WAAW,GACX,eAAe,GACf,IAAI,GACJ,QAAQ,GACR,eAAe,CAAC;AAEpB,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,KAAK,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;CAChG,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC;IACtD,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;IACnE,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC;IAChE,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAAC;IACtC,MAAM,IAAI,YAAY,CAAC;IACvB,MAAM,IAAI,YAAY,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,qBAAqB,GAAG,YAAY,CAAC;IACpD,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAC/B,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7B,UAAU,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC1F;AAED;;GAEG;AACH,KAAK,aAAa,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AAuXtD;;GAEG;AACH,eAAO,MAAM,UAAU;IACrB;;OAEG;aACM,MAAM,GAAG,YAAY;IAI9B;;OAEG;cACO,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;IAQ9D;;OAEG;aACM,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;IAQ7D;;OAEG;eACQ,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;IAQ/D;;OAEG;gBACS,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;EAOhE,CAAC;AAEH,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../../../../src/tools/http/Http.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAElF,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,MAAM,eAAe,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,MAAM,GACN,WAAW,GACX,eAAe,GACf,IAAI,GACJ,QAAQ,GACR,eAAe,CAAC;AAEpB,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,KAAK,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;CAChG,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC;IACtD,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;IACnE,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC;IAChE,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAAC;IACtC,MAAM,IAAI,YAAY,CAAC;IACvB,MAAM,IAAI,YAAY,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,qBAAqB,GAAG,YAAY,CAAC;IACpD,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAC/B,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7B,UAAU,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC1F;AAED;;GAEG;AACH,KAAK,aAAa,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AA8dtD;;GAEG;AACH,eAAO,MAAM,UAAU;IACrB;;OAEG;aACM,MAAM,GAAG,YAAY;IAI9B;;OAEG;cACO,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;IAQ9D;;OAEG;aACM,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;IAQ7D;;OAEG;eACQ,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;IAQ/D;;OAEG;gBACS,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;EAOhE,CAAC;AAEH,eAAe,UAAU,CAAC"}
@@ -80,6 +80,56 @@ const normalizeBodyInit = (body) => {
80
80
  }
81
81
  return body;
82
82
  };
83
+ const hasAuthorizationHeader = (headers) => {
84
+ return Object.keys(headers).some((name) => name.toLowerCase() === 'authorization');
85
+ };
86
+ const decodeCredentialComponent = (value) => {
87
+ try {
88
+ return decodeURIComponent(value);
89
+ }
90
+ catch {
91
+ return value;
92
+ }
93
+ };
94
+ const encodeBase64Utf8 = (value) => {
95
+ if (typeof Buffer !== 'undefined') {
96
+ return Buffer.from(value, 'utf8').toString('base64');
97
+ }
98
+ if (typeof globalThis.btoa === 'function') {
99
+ const bytes = new TextEncoder().encode(value);
100
+ let binary = '';
101
+ for (const byte of bytes) {
102
+ binary += String.fromCodePoint(byte);
103
+ }
104
+ return globalThis.btoa(binary);
105
+ }
106
+ throw ErrorFactory.createTryCatchError('HTTP basic auth encoding is unavailable');
107
+ };
108
+ const normalizeCredentialUrl = (url, headers) => {
109
+ let parsed;
110
+ try {
111
+ parsed = new URL(url);
112
+ }
113
+ catch {
114
+ return { url, headers };
115
+ }
116
+ const username = parsed.username;
117
+ const password = parsed.password;
118
+ if (username === '' && password === '') {
119
+ return { url, headers };
120
+ }
121
+ const nextHeaders = { ...headers };
122
+ if (!hasAuthorizationHeader(nextHeaders)) {
123
+ const credentials = encodeBase64Utf8(`${decodeCredentialComponent(username)}:${decodeCredentialComponent(password)}`);
124
+ nextHeaders['Authorization'] = `Basic ${credentials}`;
125
+ }
126
+ parsed.username = '';
127
+ parsed.password = '';
128
+ return {
129
+ url: parsed.toString(),
130
+ headers: nextHeaders,
131
+ };
132
+ };
83
133
  const serializeFormBody = (body) => {
84
134
  if (body === null || body === undefined)
85
135
  return body;
@@ -153,8 +203,8 @@ const captureTraceResponseBody = async (response) => {
153
203
  * Perform the actual request for a given state. Separated to keep the builder small
154
204
  */
155
205
  async function performRequest(state) {
156
- const { response, bodyText, durationMs } = await performRequestRaw(state);
157
- Logger.debug(`HTTP ${state.method} ${state.url}`, {
206
+ const { response, bodyText, durationMs, effectiveState } = await performRequestRaw(state);
207
+ Logger.debug(`HTTP ${effectiveState.method} ${effectiveState.url}`, {
158
208
  status: response.status,
159
209
  duration: `${durationMs}ms`,
160
210
  size: bodyText.length,
@@ -162,31 +212,45 @@ async function performRequest(state) {
162
212
  return createHttpResponse(response, bodyText);
163
213
  }
164
214
  async function performRequestRaw(state) {
165
- const { response, durationMs, requestBody } = await performFetch(state);
215
+ const { response, durationMs, requestBody, effectiveState } = await performFetch(state);
166
216
  const bodyText = await response.text();
167
- emitHttpClientTrace({ state, requestBody, response, responseBody: bodyText, durationMs });
168
- return { response, bodyText, durationMs, requestBody };
217
+ emitHttpClientTrace({
218
+ state: effectiveState,
219
+ requestBody,
220
+ response,
221
+ responseBody: bodyText,
222
+ durationMs,
223
+ });
224
+ return { response, bodyText, durationMs, requestBody, effectiveState };
169
225
  }
170
226
  async function performFetch(state) {
171
227
  const timeout = state.timeout ?? Env.getInt('HTTP_TIMEOUT', 30000);
172
228
  const controller = new AbortController();
229
+ const normalizedTarget = normalizeCredentialUrl(state.url, state.headers);
230
+ const effectiveState = normalizedTarget.url === state.url && normalizedTarget.headers === state.headers
231
+ ? state
232
+ : {
233
+ ...state,
234
+ url: normalizedTarget.url,
235
+ headers: normalizedTarget.headers,
236
+ };
173
237
  let timeoutId;
174
238
  if (timeout > 0) {
175
239
  timeoutId = globalThis.setTimeout(() => controller.abort(), timeout);
176
240
  }
177
241
  const buildInit = () => {
178
242
  if (OpenTelemetry.isEnabled()) {
179
- OpenTelemetry.injectTraceHeaders(state.headers);
243
+ OpenTelemetry.injectTraceHeaders(effectiveState.headers);
180
244
  }
181
- const requestBody = serializeRequestBody(state);
245
+ const requestBody = serializeRequestBody(effectiveState);
182
246
  const init = {
183
- method: state.method,
184
- headers: state.headers,
247
+ method: effectiveState.method,
248
+ headers: effectiveState.headers,
185
249
  signal: controller.signal,
186
250
  };
187
251
  if (requestBody !== undefined &&
188
252
  requestBody !== null &&
189
- ['POST', 'PUT', 'PATCH', 'DELETE'].includes(state.method)) {
253
+ ['POST', 'PUT', 'PATCH', 'DELETE'].includes(effectiveState.method)) {
190
254
  init.body = requestBody;
191
255
  }
192
256
  return { init, requestBody };
@@ -194,28 +258,28 @@ async function performFetch(state) {
194
258
  const startTime = Date.now();
195
259
  try {
196
260
  const { init, requestBody } = buildInit();
197
- const response = await globalThis.fetch(state.url, init);
261
+ const response = await globalThis.fetch(effectiveState.url, init);
198
262
  const duration = Date.now() - startTime;
199
- return { response, durationMs: duration, requestBody };
263
+ return { response, durationMs: duration, requestBody, effectiveState };
200
264
  }
201
265
  catch (error) {
202
266
  const duration = Date.now() - startTime;
203
267
  emitHttpClientTrace({
204
- state,
205
- requestBody: serializeRequestBody(state),
268
+ state: effectiveState,
269
+ requestBody: serializeRequestBody(effectiveState),
206
270
  durationMs: duration,
207
271
  error: error instanceof Error ? error.message : String(error),
208
272
  });
209
273
  if (error instanceof Error && error.name === 'AbortError') {
210
274
  throw ErrorFactory.createConnectionError(`HTTP request timeout after ${timeout}ms`, {
211
- url: state.url,
212
- method: state.method,
275
+ url: effectiveState.url,
276
+ method: effectiveState.method,
213
277
  timeout,
214
278
  });
215
279
  }
216
280
  throw ErrorFactory.createTryCatchError(`HTTP request failed: ${error.message}`, {
217
- url: state.url,
218
- method: state.method,
281
+ url: effectiveState.url,
282
+ method: effectiveState.method,
219
283
  error: error instanceof Error ? error.message : String(error),
220
284
  });
221
285
  }
@@ -225,6 +289,18 @@ async function performFetch(state) {
225
289
  }
226
290
  }
227
291
  }
292
+ async function performFetchWithTrace(state) {
293
+ const result = await performFetch(state);
294
+ const responseBody = await captureTraceResponseBody(result.response);
295
+ emitHttpClientTrace({
296
+ state: result.effectiveState,
297
+ requestBody: result.requestBody,
298
+ response: result.response,
299
+ responseBody,
300
+ durationMs: result.durationMs,
301
+ });
302
+ return result;
303
+ }
228
304
  /**
229
305
  * Create request builder with fluent API
230
306
  */
@@ -251,7 +327,7 @@ function createRequestBuilder(method, url, initialBody) {
251
327
  return self;
252
328
  },
253
329
  withBasicAuth(username, password) {
254
- const credentials = Buffer.from(`${username}:${password}`).toString('base64');
330
+ const credentials = encodeBase64Utf8(`${username}:${password}`);
255
331
  state.headers['Authorization'] = `Basic ${credentials}`;
256
332
  return self;
257
333
  },
@@ -281,15 +357,11 @@ function createRequestBuilder(method, url, initialBody) {
281
357
  return performRequest(state);
282
358
  },
283
359
  async sendRaw() {
284
- const { response, durationMs, requestBody } = await performFetch(state);
285
- const responseBody = await captureTraceResponseBody(response);
286
- emitHttpClientTrace({ state, requestBody, response, responseBody, durationMs });
360
+ const { response } = await performFetchWithTrace(state);
287
361
  return response;
288
362
  },
289
363
  async sendStream() {
290
- const { response, durationMs, requestBody } = await performFetch(state);
291
- const responseBody = await captureTraceResponseBody(response);
292
- emitHttpClientTrace({ state, requestBody, response, responseBody, durationMs });
364
+ const { response } = await performFetchWithTrace(state);
293
365
  return { response, stream: response.body };
294
366
  },
295
367
  };
@@ -1,10 +1,7 @@
1
1
  /**
2
- * ZinTrust plugin auto-imports
3
- *
4
- * In real projects, this file is managed by `zin plugin install` and contains
5
- * side-effect imports (e.g. `@zintrust/db-sqlite/register`) that register
6
- * optional adapters/drivers into core registries.
7
- *
2
+ * Auto-generated fallback module.
3
+ * This file is created by scripts/ensure-worker-plugins.mjs when missing.
4
+ * It allows optional runtime plugin imports to resolve in CI/scaffolded setups.
8
5
  */
9
6
  export type {};
10
7
  export declare const __zintrustGeneratedPluginStub = "zintrust.plugins.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"zintrust.plugins.d.ts","sourceRoot":"","sources":["../../src/zintrust.plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,YAAY,EAAE,CAAC;AAgBf,eAAO,MAAM,6BAA6B,wBAAwB,CAAC;;AACnE,wBAAkB"}
1
+ {"version":3,"file":"zintrust.plugins.d.ts","sourceRoot":"","sources":["../../src/zintrust.plugins.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,YAAY,EAAE,CAAC;AAgBf,eAAO,MAAM,6BAA6B,wBAAwB,CAAC;;AACnE,wBAAkB"}
@@ -1,10 +1,7 @@
1
1
  /**
2
- * ZinTrust plugin auto-imports
3
- *
4
- * In real projects, this file is managed by `zin plugin install` and contains
5
- * side-effect imports (e.g. `@zintrust/db-sqlite/register`) that register
6
- * optional adapters/drivers into core registries.
7
- *
2
+ * Auto-generated fallback module.
3
+ * This file is created by scripts/ensure-worker-plugins.mjs when missing.
4
+ * It allows optional runtime plugin imports to resolve in CI/scaffolded setups.
8
5
  */
9
6
  import * as TraceRuntime from './runtime/plugins/trace-runtime.js';
10
7
  globalThis.__zintrust_system_trace_plugin_requested__ = true;