@voyantjs/utils 0.1.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/LICENSE +109 -0
- package/README.md +42 -0
- package/dist/accounting-countries.d.ts +12 -0
- package/dist/accounting-countries.d.ts.map +1 -0
- package/dist/accounting-countries.js +307 -0
- package/dist/accounting-countries.js.map +1 -0
- package/dist/accounting-regions.d.ts +103 -0
- package/dist/accounting-regions.d.ts.map +1 -0
- package/dist/accounting-regions.js +38 -0
- package/dist/accounting-regions.js.map +1 -0
- package/dist/airlines.d.ts +960 -0
- package/dist/airlines.d.ts.map +1 -0
- package/dist/airlines.js +989 -0
- package/dist/airlines.js.map +1 -0
- package/dist/analytics/api-key-events.d.ts +89 -0
- package/dist/analytics/api-key-events.d.ts.map +1 -0
- package/dist/analytics/api-key-events.js +99 -0
- package/dist/analytics/api-key-events.js.map +1 -0
- package/dist/api-keys-client.d.ts +40 -0
- package/dist/api-keys-client.d.ts.map +1 -0
- package/dist/api-keys-client.js +63 -0
- package/dist/api-keys-client.js.map +1 -0
- package/dist/api-keys.d.ts +48 -0
- package/dist/api-keys.d.ts.map +1 -0
- package/dist/api-keys.js +108 -0
- package/dist/api-keys.js.map +1 -0
- package/dist/cache.d.ts +123 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +182 -0
- package/dist/cache.js.map +1 -0
- package/dist/checkout-signature.d.ts +15 -0
- package/dist/checkout-signature.d.ts.map +1 -0
- package/dist/checkout-signature.js +64 -0
- package/dist/checkout-signature.js.map +1 -0
- package/dist/conditions.d.ts +36 -0
- package/dist/conditions.d.ts.map +1 -0
- package/dist/conditions.js +396 -0
- package/dist/conditions.js.map +1 -0
- package/dist/countries.d.ts +5 -0
- package/dist/countries.d.ts.map +1 -0
- package/dist/countries.js +251 -0
- package/dist/countries.js.map +1 -0
- package/dist/currencies.d.ts +1011 -0
- package/dist/currencies.d.ts.map +1 -0
- package/dist/currencies.js +1011 -0
- package/dist/currencies.js.map +1 -0
- package/dist/email/send.d.ts +20 -0
- package/dist/email/send.d.ts.map +1 -0
- package/dist/email/send.js +53 -0
- package/dist/email/send.js.map +1 -0
- package/dist/form-runtime.d.ts +38 -0
- package/dist/form-runtime.d.ts.map +1 -0
- package/dist/form-runtime.js +174 -0
- package/dist/form-runtime.js.map +1 -0
- package/dist/gcs/storage.d.ts +23 -0
- package/dist/gcs/storage.d.ts.map +1 -0
- package/dist/gcs/storage.js +25 -0
- package/dist/gcs/storage.js.map +1 -0
- package/dist/geo.d.ts +85 -0
- package/dist/geo.d.ts.map +1 -0
- package/dist/geo.js +141 -0
- package/dist/geo.js.map +1 -0
- package/dist/geographic-regions.d.ts +66 -0
- package/dist/geographic-regions.d.ts.map +1 -0
- package/dist/geographic-regions.js +326 -0
- package/dist/geographic-regions.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/kms-aws.d.ts +26 -0
- package/dist/kms-aws.d.ts.map +1 -0
- package/dist/kms-aws.js +133 -0
- package/dist/kms-aws.js.map +1 -0
- package/dist/kms-crypto.d.ts +20 -0
- package/dist/kms-crypto.d.ts.map +1 -0
- package/dist/kms-crypto.js +108 -0
- package/dist/kms-crypto.js.map +1 -0
- package/dist/kms-env.d.ts +13 -0
- package/dist/kms-env.d.ts.map +1 -0
- package/dist/kms-env.js +13 -0
- package/dist/kms-env.js.map +1 -0
- package/dist/kms-gcp.d.ts +32 -0
- package/dist/kms-gcp.d.ts.map +1 -0
- package/dist/kms-gcp.js +116 -0
- package/dist/kms-gcp.js.map +1 -0
- package/dist/kms-local.d.ts +13 -0
- package/dist/kms-local.d.ts.map +1 -0
- package/dist/kms-local.js +13 -0
- package/dist/kms-local.js.map +1 -0
- package/dist/kms-symmetric.d.ts +14 -0
- package/dist/kms-symmetric.d.ts.map +1 -0
- package/dist/kms-symmetric.js +67 -0
- package/dist/kms-symmetric.js.map +1 -0
- package/dist/kms.d.ts +66 -0
- package/dist/kms.d.ts.map +1 -0
- package/dist/kms.js +169 -0
- package/dist/kms.js.map +1 -0
- package/dist/kv-codecs.d.ts +6 -0
- package/dist/kv-codecs.d.ts.map +1 -0
- package/dist/kv-codecs.js +4 -0
- package/dist/kv-codecs.js.map +1 -0
- package/dist/kv.d.ts +10 -0
- package/dist/kv.d.ts.map +1 -0
- package/dist/kv.js +18 -0
- package/dist/kv.js.map +1 -0
- package/dist/languages.d.ts +187 -0
- package/dist/languages.d.ts.map +1 -0
- package/dist/languages.js +187 -0
- package/dist/languages.js.map +1 -0
- package/dist/localized-countries-regions.d.ts +15 -0
- package/dist/localized-countries-regions.d.ts.map +1 -0
- package/dist/localized-countries-regions.js +674 -0
- package/dist/localized-countries-regions.js.map +1 -0
- package/dist/localized-regions.d.ts +33 -0
- package/dist/localized-regions.d.ts.map +1 -0
- package/dist/localized-regions.js +63 -0
- package/dist/localized-regions.js.map +1 -0
- package/dist/price/resolve.d.ts +91 -0
- package/dist/price/resolve.d.ts.map +1 -0
- package/dist/price/resolve.js +227 -0
- package/dist/price/resolve.js.map +1 -0
- package/dist/rate-limits.d.ts +39 -0
- package/dist/rate-limits.d.ts.map +1 -0
- package/dist/rate-limits.js +86 -0
- package/dist/rate-limits.js.map +1 -0
- package/dist/redis.d.ts +13 -0
- package/dist/redis.d.ts.map +1 -0
- package/dist/redis.js +16 -0
- package/dist/redis.js.map +1 -0
- package/dist/region-only.d.ts +11 -0
- package/dist/region-only.d.ts.map +1 -0
- package/dist/region-only.js +49 -0
- package/dist/region-only.js.map +1 -0
- package/dist/region.d.ts +11 -0
- package/dist/region.d.ts.map +1 -0
- package/dist/region.js +47 -0
- package/dist/region.js.map +1 -0
- package/dist/romania-bucharest-sectors.d.ts +6 -0
- package/dist/romania-bucharest-sectors.d.ts.map +1 -0
- package/dist/romania-bucharest-sectors.js +27 -0
- package/dist/romania-bucharest-sectors.js.map +1 -0
- package/dist/romania-counties.d.ts +6 -0
- package/dist/romania-counties.d.ts.map +1 -0
- package/dist/romania-counties.js +171 -0
- package/dist/romania-counties.js.map +1 -0
- package/dist/session-claims.d.ts +40 -0
- package/dist/session-claims.d.ts.map +1 -0
- package/dist/session-claims.js +184 -0
- package/dist/session-claims.js.map +1 -0
- package/dist/sms/provider.d.ts +28 -0
- package/dist/sms/provider.d.ts.map +1 -0
- package/dist/sms/provider.js +50 -0
- package/dist/sms/provider.js.map +1 -0
- package/dist/sms/segments.d.ts +3 -0
- package/dist/sms/segments.d.ts.map +1 -0
- package/dist/sms/segments.js +33 -0
- package/dist/sms/segments.js.map +1 -0
- package/dist/temporal.d.ts +2 -0
- package/dist/temporal.d.ts.map +1 -0
- package/dist/temporal.js +6 -0
- package/dist/temporal.js.map +1 -0
- package/dist/timezones.d.ts +9 -0
- package/dist/timezones.d.ts.map +1 -0
- package/dist/timezones.js +1217 -0
- package/dist/timezones.js.map +1 -0
- package/dist/twilio/client.d.ts +13 -0
- package/dist/twilio/client.d.ts.map +1 -0
- package/dist/twilio/client.js +26 -0
- package/dist/twilio/client.js.map +1 -0
- package/dist/usage/index.d.ts +34 -0
- package/dist/usage/index.d.ts.map +1 -0
- package/dist/usage/index.js +18 -0
- package/dist/usage/index.js.map +1 -0
- package/dist/usage/policy.d.ts +27 -0
- package/dist/usage/policy.d.ts.map +1 -0
- package/dist/usage/policy.js +17 -0
- package/dist/usage/policy.js.map +1 -0
- package/dist/validation/log.d.ts +10 -0
- package/dist/validation/log.d.ts.map +1 -0
- package/dist/validation/log.js +37 -0
- package/dist/validation/log.js.map +1 -0
- package/dist/with-timeout.d.ts +2 -0
- package/dist/with-timeout.d.ts.map +1 -0
- package/dist/with-timeout.js +15 -0
- package/dist/with-timeout.js.map +1 -0
- package/dist/zod-form-builder.d.ts +45 -0
- package/dist/zod-form-builder.d.ts.map +1 -0
- package/dist/zod-form-builder.js +216 -0
- package/dist/zod-form-builder.js.map +1 -0
- package/package.json +92 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge-compatible GCP KMS encryption/decryption using Web Crypto API.
|
|
3
|
+
* No Node.js dependencies — works in Cloudflare Workers.
|
|
4
|
+
*/
|
|
5
|
+
// ---------- GCP Access Token (module-level cache) ----------
|
|
6
|
+
let cachedToken = null;
|
|
7
|
+
function base64UrlEncode(data) {
|
|
8
|
+
let binary = "";
|
|
9
|
+
for (const byte of data) {
|
|
10
|
+
binary += String.fromCharCode(byte);
|
|
11
|
+
}
|
|
12
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
13
|
+
}
|
|
14
|
+
function base64UrlEncodeString(str) {
|
|
15
|
+
return base64UrlEncode(new TextEncoder().encode(str));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Import a PEM-encoded RSA private key for signing JWTs.
|
|
19
|
+
*/
|
|
20
|
+
async function importPrivateKey(pem) {
|
|
21
|
+
const pemBody = pem
|
|
22
|
+
.replace(/-----BEGIN (?:RSA )?PRIVATE KEY-----/g, "")
|
|
23
|
+
.replace(/-----END (?:RSA )?PRIVATE KEY-----/g, "")
|
|
24
|
+
.replace(/[\n\r\s]/g, "");
|
|
25
|
+
const binaryString = atob(pemBody);
|
|
26
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
27
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
28
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
29
|
+
}
|
|
30
|
+
return crypto.subtle.importKey("pkcs8", bytes, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["sign"]);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Creates a signed JWT assertion and exchanges it at Google's OAuth2 endpoint
|
|
34
|
+
* for a short-lived access token. Caches the token at module level.
|
|
35
|
+
*/
|
|
36
|
+
export async function getGcpAccessToken(email, privateKeyPem) {
|
|
37
|
+
const now = Math.floor(Date.now() / 1000);
|
|
38
|
+
if (cachedToken && cachedToken.expiresAt > now + 60) {
|
|
39
|
+
return cachedToken.token;
|
|
40
|
+
}
|
|
41
|
+
const header = base64UrlEncodeString(JSON.stringify({ alg: "RS256", typ: "JWT" }));
|
|
42
|
+
const exp = now + 3600;
|
|
43
|
+
const payload = base64UrlEncodeString(JSON.stringify({
|
|
44
|
+
iss: email,
|
|
45
|
+
scope: "https://www.googleapis.com/auth/cloudkms",
|
|
46
|
+
aud: "https://oauth2.googleapis.com/token",
|
|
47
|
+
iat: now,
|
|
48
|
+
exp,
|
|
49
|
+
}));
|
|
50
|
+
const signingInput = `${header}.${payload}`;
|
|
51
|
+
const key = await importPrivateKey(privateKeyPem);
|
|
52
|
+
const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", key, new TextEncoder().encode(signingInput));
|
|
53
|
+
const jwt = `${signingInput}.${base64UrlEncode(new Uint8Array(signature))}`;
|
|
54
|
+
const res = await fetch("https://oauth2.googleapis.com/token", {
|
|
55
|
+
method: "POST",
|
|
56
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
57
|
+
body: `grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=${jwt}`,
|
|
58
|
+
});
|
|
59
|
+
if (!res.ok) {
|
|
60
|
+
const body = await res.text();
|
|
61
|
+
throw new Error(`GCP token exchange failed (${res.status}): ${body}`);
|
|
62
|
+
}
|
|
63
|
+
const data = (await res.json());
|
|
64
|
+
cachedToken = { token: data.access_token, expiresAt: now + data.expires_in };
|
|
65
|
+
return data.access_token;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Encrypt plaintext using GCP Cloud KMS.
|
|
69
|
+
* Returns base64 ciphertext string.
|
|
70
|
+
*/
|
|
71
|
+
export async function kmsEncrypt(plaintext, keyName, accessToken) {
|
|
72
|
+
const encoded = btoa(plaintext);
|
|
73
|
+
const res = await fetch(`https://cloudkms.googleapis.com/v1/${keyName}:encrypt`, {
|
|
74
|
+
method: "POST",
|
|
75
|
+
headers: {
|
|
76
|
+
Authorization: `Bearer ${accessToken}`,
|
|
77
|
+
"Content-Type": "application/json",
|
|
78
|
+
},
|
|
79
|
+
body: JSON.stringify({ plaintext: encoded }),
|
|
80
|
+
});
|
|
81
|
+
if (!res.ok) {
|
|
82
|
+
const body = await res.text();
|
|
83
|
+
throw new Error(`KMS encrypt failed (${res.status}): ${body}`);
|
|
84
|
+
}
|
|
85
|
+
const data = (await res.json());
|
|
86
|
+
return data.ciphertext;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Decrypt ciphertext using GCP Cloud KMS.
|
|
90
|
+
* Returns plaintext string.
|
|
91
|
+
*/
|
|
92
|
+
export async function kmsDecrypt(ciphertext, keyName, accessToken) {
|
|
93
|
+
const res = await fetch(`https://cloudkms.googleapis.com/v1/${keyName}:decrypt`, {
|
|
94
|
+
method: "POST",
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `Bearer ${accessToken}`,
|
|
97
|
+
"Content-Type": "application/json",
|
|
98
|
+
},
|
|
99
|
+
body: JSON.stringify({ ciphertext }),
|
|
100
|
+
});
|
|
101
|
+
if (!res.ok) {
|
|
102
|
+
const body = await res.text();
|
|
103
|
+
throw new Error(`KMS decrypt failed (${res.status}): ${body}`);
|
|
104
|
+
}
|
|
105
|
+
const data = (await res.json());
|
|
106
|
+
return atob(data.plaintext);
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=kms-crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms-crypto.js","sourceRoot":"","sources":["../src/kms-crypto.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SymmetricAesGcmKmsProvider } from "./kms-symmetric.js";
|
|
2
|
+
export interface EnvKmsConfig {
|
|
3
|
+
/** Base64-encoded 32-byte master key. */
|
|
4
|
+
key: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function generateEnvKmsKey(): string;
|
|
7
|
+
export declare class EnvKmsProvider extends SymmetricAesGcmKmsProvider {
|
|
8
|
+
readonly name: "env";
|
|
9
|
+
protected readonly prefix = "env:v1:";
|
|
10
|
+
protected readonly label = "EnvKmsProvider";
|
|
11
|
+
constructor(config: EnvKmsConfig);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=kms-env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms-env.d.ts","sourceRoot":"","sources":["../src/kms-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,0BAA0B,EAAE,MAAM,oBAAoB,CAAA;AAExF,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,qBAAa,cAAe,SAAQ,0BAA0B;IAC5D,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAS;IAC9B,SAAS,CAAC,QAAQ,CAAC,MAAM,aAAY;IACrC,SAAS,CAAC,QAAQ,CAAC,KAAK,oBAAmB;gBAE/B,MAAM,EAAE,YAAY;CAGjC"}
|
package/dist/kms-env.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { generateSymmetricKmsKey, SymmetricAesGcmKmsProvider } from "./kms-symmetric.js";
|
|
2
|
+
export function generateEnvKmsKey() {
|
|
3
|
+
return generateSymmetricKmsKey();
|
|
4
|
+
}
|
|
5
|
+
export class EnvKmsProvider extends SymmetricAesGcmKmsProvider {
|
|
6
|
+
name = "env";
|
|
7
|
+
prefix = "env:v1:";
|
|
8
|
+
label = "EnvKmsProvider";
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super(config.key);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=kms-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms-env.js","sourceRoot":"","sources":["../src/kms-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAA;AAOxF,MAAM,UAAU,iBAAiB;IAC/B,OAAO,uBAAuB,EAAE,CAAA;AAClC,CAAC;AAED,MAAM,OAAO,cAAe,SAAQ,0BAA0B;IACnD,IAAI,GAAG,KAAc,CAAA;IACX,MAAM,GAAG,SAAS,CAAA;IAClB,KAAK,GAAG,gBAAgB,CAAA;IAE3C,YAAY,MAAoB;QAC9B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCP Cloud KMS provider.
|
|
3
|
+
*
|
|
4
|
+
* Edge-compatible: uses Web Crypto API for JWT signing and fetch() for GCP API
|
|
5
|
+
* calls. No Node.js dependencies — works in Cloudflare Workers.
|
|
6
|
+
*/
|
|
7
|
+
import type { KeyRef, KmsKeyType, KmsProvider } from "./kms.js";
|
|
8
|
+
export interface GcpKmsConfig {
|
|
9
|
+
projectId: string;
|
|
10
|
+
serviceAccountEmail: string;
|
|
11
|
+
privateKeyPem: string;
|
|
12
|
+
/** GCP keyring name. Keyrings are location-bound — one provider, one keyring. */
|
|
13
|
+
keyRing: string;
|
|
14
|
+
/** GCP location the keyring lives in, e.g. "europe", "us", "global", "europe-west1". */
|
|
15
|
+
location: string;
|
|
16
|
+
cryptoKeyByType: Record<KmsKeyType, string>;
|
|
17
|
+
}
|
|
18
|
+
export declare class GcpKmsProvider implements KmsProvider {
|
|
19
|
+
private readonly config;
|
|
20
|
+
readonly name: "gcp";
|
|
21
|
+
private cachedToken;
|
|
22
|
+
constructor(config: GcpKmsConfig);
|
|
23
|
+
private getKeyName;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a signed JWT assertion and exchanges it at Google's OAuth2
|
|
26
|
+
* endpoint for a short-lived access token. Caches the token per instance.
|
|
27
|
+
*/
|
|
28
|
+
private getAccessToken;
|
|
29
|
+
encrypt(plaintext: string, key: KeyRef): Promise<string>;
|
|
30
|
+
decrypt(ciphertext: string, key: KeyRef): Promise<string>;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=kms-gcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms-gcp.d.ts","sourceRoot":"","sources":["../src/kms-gcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE/D,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,aAAa,EAAE,MAAM,CAAA;IACrB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAA;IACf,wFAAwF;IACxF,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;CAC5C;AAsCD,qBAAa,cAAe,YAAW,WAAW;IAKpC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAS;IAE9B,OAAO,CAAC,WAAW,CAAoD;gBAE1C,MAAM,EAAE,YAAY;IAEjD,OAAO,CAAC,UAAU;IAKlB;;;OAGG;YACW,cAAc;IA4CtB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAuBxD,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAqBhE"}
|
package/dist/kms-gcp.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCP Cloud KMS provider.
|
|
3
|
+
*
|
|
4
|
+
* Edge-compatible: uses Web Crypto API for JWT signing and fetch() for GCP API
|
|
5
|
+
* calls. No Node.js dependencies — works in Cloudflare Workers.
|
|
6
|
+
*/
|
|
7
|
+
function base64UrlEncode(data) {
|
|
8
|
+
let binary = "";
|
|
9
|
+
for (const byte of data) {
|
|
10
|
+
binary += String.fromCharCode(byte);
|
|
11
|
+
}
|
|
12
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
13
|
+
}
|
|
14
|
+
function base64UrlEncodeString(str) {
|
|
15
|
+
return base64UrlEncode(new TextEncoder().encode(str));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Import a PEM-encoded RSA private key for signing JWTs.
|
|
19
|
+
*/
|
|
20
|
+
async function importPrivateKey(pem) {
|
|
21
|
+
const pemBody = pem
|
|
22
|
+
.replace(/-----BEGIN (?:RSA )?PRIVATE KEY-----/g, "")
|
|
23
|
+
.replace(/-----END (?:RSA )?PRIVATE KEY-----/g, "")
|
|
24
|
+
.replace(/[\n\r\s]/g, "");
|
|
25
|
+
const binaryString = atob(pemBody);
|
|
26
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
27
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
28
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
29
|
+
}
|
|
30
|
+
return crypto.subtle.importKey("pkcs8", bytes, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["sign"]);
|
|
31
|
+
}
|
|
32
|
+
export class GcpKmsProvider {
|
|
33
|
+
config;
|
|
34
|
+
name = "gcp";
|
|
35
|
+
cachedToken = null;
|
|
36
|
+
constructor(config) {
|
|
37
|
+
this.config = config;
|
|
38
|
+
}
|
|
39
|
+
getKeyName(key) {
|
|
40
|
+
const cryptoKey = this.config.cryptoKeyByType[key.keyType];
|
|
41
|
+
return `projects/${this.config.projectId}/locations/${this.config.location}/keyRings/${this.config.keyRing}/cryptoKeys/${cryptoKey}`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Creates a signed JWT assertion and exchanges it at Google's OAuth2
|
|
45
|
+
* endpoint for a short-lived access token. Caches the token per instance.
|
|
46
|
+
*/
|
|
47
|
+
async getAccessToken() {
|
|
48
|
+
const now = Math.floor(Date.now() / 1000);
|
|
49
|
+
if (this.cachedToken && this.cachedToken.expiresAt > now + 60) {
|
|
50
|
+
return this.cachedToken.token;
|
|
51
|
+
}
|
|
52
|
+
const header = base64UrlEncodeString(JSON.stringify({ alg: "RS256", typ: "JWT" }));
|
|
53
|
+
const exp = now + 3600;
|
|
54
|
+
const payload = base64UrlEncodeString(JSON.stringify({
|
|
55
|
+
iss: this.config.serviceAccountEmail,
|
|
56
|
+
scope: "https://www.googleapis.com/auth/cloudkms",
|
|
57
|
+
aud: "https://oauth2.googleapis.com/token",
|
|
58
|
+
iat: now,
|
|
59
|
+
exp,
|
|
60
|
+
}));
|
|
61
|
+
const signingInput = `${header}.${payload}`;
|
|
62
|
+
const key = await importPrivateKey(this.config.privateKeyPem);
|
|
63
|
+
const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", key, new TextEncoder().encode(signingInput));
|
|
64
|
+
const jwt = `${signingInput}.${base64UrlEncode(new Uint8Array(signature))}`;
|
|
65
|
+
const res = await fetch("https://oauth2.googleapis.com/token", {
|
|
66
|
+
method: "POST",
|
|
67
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
68
|
+
body: `grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=${jwt}`,
|
|
69
|
+
});
|
|
70
|
+
if (!res.ok) {
|
|
71
|
+
const body = await res.text();
|
|
72
|
+
throw new Error(`GCP token exchange failed (${res.status}): ${body}`);
|
|
73
|
+
}
|
|
74
|
+
const data = (await res.json());
|
|
75
|
+
this.cachedToken = { token: data.access_token, expiresAt: now + data.expires_in };
|
|
76
|
+
return data.access_token;
|
|
77
|
+
}
|
|
78
|
+
async encrypt(plaintext, key) {
|
|
79
|
+
const keyName = this.getKeyName(key);
|
|
80
|
+
const accessToken = await this.getAccessToken();
|
|
81
|
+
const encoded = btoa(plaintext);
|
|
82
|
+
const res = await fetch(`https://cloudkms.googleapis.com/v1/${keyName}:encrypt`, {
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers: {
|
|
85
|
+
Authorization: `Bearer ${accessToken}`,
|
|
86
|
+
"Content-Type": "application/json",
|
|
87
|
+
},
|
|
88
|
+
body: JSON.stringify({ plaintext: encoded }),
|
|
89
|
+
});
|
|
90
|
+
if (!res.ok) {
|
|
91
|
+
const body = await res.text();
|
|
92
|
+
throw new Error(`KMS encrypt failed (${res.status}): ${body}`);
|
|
93
|
+
}
|
|
94
|
+
const data = (await res.json());
|
|
95
|
+
return data.ciphertext;
|
|
96
|
+
}
|
|
97
|
+
async decrypt(ciphertext, key) {
|
|
98
|
+
const keyName = this.getKeyName(key);
|
|
99
|
+
const accessToken = await this.getAccessToken();
|
|
100
|
+
const res = await fetch(`https://cloudkms.googleapis.com/v1/${keyName}:decrypt`, {
|
|
101
|
+
method: "POST",
|
|
102
|
+
headers: {
|
|
103
|
+
Authorization: `Bearer ${accessToken}`,
|
|
104
|
+
"Content-Type": "application/json",
|
|
105
|
+
},
|
|
106
|
+
body: JSON.stringify({ ciphertext }),
|
|
107
|
+
});
|
|
108
|
+
if (!res.ok) {
|
|
109
|
+
const body = await res.text();
|
|
110
|
+
throw new Error(`KMS decrypt failed (${res.status}): ${body}`);
|
|
111
|
+
}
|
|
112
|
+
const data = (await res.json());
|
|
113
|
+
return atob(data.plaintext);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=kms-gcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms-gcp.js","sourceRoot":"","sources":["../src/kms-gcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SymmetricAesGcmKmsProvider } from "./kms-symmetric.js";
|
|
2
|
+
export interface LocalKmsConfig {
|
|
3
|
+
/** Base64-encoded 32-byte master key. */
|
|
4
|
+
key: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function generateLocalKmsKey(): string;
|
|
7
|
+
export declare class LocalKmsProvider extends SymmetricAesGcmKmsProvider {
|
|
8
|
+
readonly name: "local";
|
|
9
|
+
protected readonly prefix = "local:v1:";
|
|
10
|
+
protected readonly label = "LocalKmsProvider";
|
|
11
|
+
constructor(config: LocalKmsConfig);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=kms-local.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms-local.d.ts","sourceRoot":"","sources":["../src/kms-local.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,0BAA0B,EAAE,MAAM,oBAAoB,CAAA;AAExF,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,qBAAa,gBAAiB,SAAQ,0BAA0B;IAC9D,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;IAChC,SAAS,CAAC,QAAQ,CAAC,MAAM,eAAc;IACvC,SAAS,CAAC,QAAQ,CAAC,KAAK,sBAAqB;gBAEjC,MAAM,EAAE,cAAc;CAGnC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { generateSymmetricKmsKey, SymmetricAesGcmKmsProvider } from "./kms-symmetric.js";
|
|
2
|
+
export function generateLocalKmsKey() {
|
|
3
|
+
return generateSymmetricKmsKey();
|
|
4
|
+
}
|
|
5
|
+
export class LocalKmsProvider extends SymmetricAesGcmKmsProvider {
|
|
6
|
+
name = "local";
|
|
7
|
+
prefix = "local:v1:";
|
|
8
|
+
label = "LocalKmsProvider";
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super(config.key);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=kms-local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms-local.js","sourceRoot":"","sources":["../src/kms-local.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAA;AAOxF,MAAM,UAAU,mBAAmB;IACjC,OAAO,uBAAuB,EAAE,CAAA;AAClC,CAAC;AAED,MAAM,OAAO,gBAAiB,SAAQ,0BAA0B;IACrD,IAAI,GAAG,OAAgB,CAAA;IACb,MAAM,GAAG,WAAW,CAAA;IACpB,KAAK,GAAG,kBAAkB,CAAA;IAE7C,YAAY,MAAsB;QAChC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { KeyRef, KmsProvider } from "./kms.js";
|
|
2
|
+
export declare function generateSymmetricKmsKey(): string;
|
|
3
|
+
export declare abstract class SymmetricAesGcmKmsProvider implements KmsProvider {
|
|
4
|
+
private readonly keyB64;
|
|
5
|
+
abstract readonly name: KmsProvider["name"];
|
|
6
|
+
protected abstract readonly prefix: string;
|
|
7
|
+
protected abstract readonly label: string;
|
|
8
|
+
private keyPromise;
|
|
9
|
+
protected constructor(keyB64: string);
|
|
10
|
+
private getKey;
|
|
11
|
+
encrypt(plaintext: string, _key: KeyRef): Promise<string>;
|
|
12
|
+
decrypt(ciphertext: string, _key: KeyRef): Promise<string>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=kms-symmetric.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms-symmetric.d.ts","sourceRoot":"","sources":["../src/kms-symmetric.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AA+BnD,wBAAgB,uBAAuB,IAAI,MAAM,CAIhD;AAED,8BAAsB,0BAA2B,YAAW,WAAW;IAO/C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAN7C,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC3C,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IAC1C,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IAEzC,OAAO,CAAC,UAAU,CAAkC;IAEpD,SAAS,aAA8B,MAAM,EAAE,MAAM;IAErD,OAAO,CAAC,MAAM;IAOR,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiBzD,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAmBjE"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const IV_BYTES = 12;
|
|
2
|
+
function base64ToBytes(b64) {
|
|
3
|
+
const binary = atob(b64);
|
|
4
|
+
const bytes = new Uint8Array(new ArrayBuffer(binary.length));
|
|
5
|
+
for (let i = 0; i < binary.length; i++) {
|
|
6
|
+
bytes[i] = binary.charCodeAt(i);
|
|
7
|
+
}
|
|
8
|
+
return bytes;
|
|
9
|
+
}
|
|
10
|
+
function bytesToBase64(bytes) {
|
|
11
|
+
let binary = "";
|
|
12
|
+
for (const byte of bytes) {
|
|
13
|
+
binary += String.fromCharCode(byte);
|
|
14
|
+
}
|
|
15
|
+
return btoa(binary);
|
|
16
|
+
}
|
|
17
|
+
function importMasterKey(keyB64, label) {
|
|
18
|
+
const raw = base64ToBytes(keyB64);
|
|
19
|
+
if (raw.length !== 32) {
|
|
20
|
+
throw new Error(`${label}: key must decode to 32 bytes (got ${raw.length}). Generate one with: openssl rand -base64 32`);
|
|
21
|
+
}
|
|
22
|
+
return crypto.subtle.importKey("raw", raw, { name: "AES-GCM" }, false, ["encrypt", "decrypt"]);
|
|
23
|
+
}
|
|
24
|
+
export function generateSymmetricKmsKey() {
|
|
25
|
+
const bytes = new Uint8Array(32);
|
|
26
|
+
crypto.getRandomValues(bytes);
|
|
27
|
+
return bytesToBase64(bytes);
|
|
28
|
+
}
|
|
29
|
+
export class SymmetricAesGcmKmsProvider {
|
|
30
|
+
keyB64;
|
|
31
|
+
keyPromise = null;
|
|
32
|
+
constructor(keyB64) {
|
|
33
|
+
this.keyB64 = keyB64;
|
|
34
|
+
}
|
|
35
|
+
getKey() {
|
|
36
|
+
if (!this.keyPromise) {
|
|
37
|
+
this.keyPromise = importMasterKey(this.keyB64, this.label);
|
|
38
|
+
}
|
|
39
|
+
return this.keyPromise;
|
|
40
|
+
}
|
|
41
|
+
async encrypt(plaintext, _key) {
|
|
42
|
+
const masterKey = await this.getKey();
|
|
43
|
+
const iv = new Uint8Array(IV_BYTES);
|
|
44
|
+
crypto.getRandomValues(iv);
|
|
45
|
+
const data = new TextEncoder().encode(plaintext);
|
|
46
|
+
const ciphertext = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv }, masterKey, data));
|
|
47
|
+
const combined = new Uint8Array(IV_BYTES + ciphertext.length);
|
|
48
|
+
combined.set(iv, 0);
|
|
49
|
+
combined.set(ciphertext, IV_BYTES);
|
|
50
|
+
return `${this.prefix}${bytesToBase64(combined)}`;
|
|
51
|
+
}
|
|
52
|
+
async decrypt(ciphertext, _key) {
|
|
53
|
+
if (!ciphertext.startsWith(this.prefix)) {
|
|
54
|
+
throw new Error(`${this.label}: ciphertext missing "${this.prefix}" prefix — was it encrypted by a different provider?`);
|
|
55
|
+
}
|
|
56
|
+
const combined = base64ToBytes(ciphertext.slice(this.prefix.length));
|
|
57
|
+
if (combined.length <= IV_BYTES) {
|
|
58
|
+
throw new Error(`${this.label}: ciphertext is too short to contain IV + data`);
|
|
59
|
+
}
|
|
60
|
+
const iv = combined.slice(0, IV_BYTES);
|
|
61
|
+
const encrypted = combined.slice(IV_BYTES);
|
|
62
|
+
const masterKey = await this.getKey();
|
|
63
|
+
const plaintext = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, masterKey, encrypted);
|
|
64
|
+
return new TextDecoder().decode(plaintext);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=kms-symmetric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms-symmetric.js","sourceRoot":"","sources":["../src/kms-symmetric.ts"],"names":[],"mappings":"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"}
|
package/dist/kms.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KMS provider interface and factory.
|
|
3
|
+
*
|
|
4
|
+
* Callers encrypt/decrypt opaque strings via a `KmsProvider` implementation.
|
|
5
|
+
* The returned ciphertext is paired with the `{ enc: "..." }` envelope from
|
|
6
|
+
* `@voyantjs/types/schemas/kms/envelope` when persisted.
|
|
7
|
+
*/
|
|
8
|
+
import type { KmsEncryptedEnvelope } from "@voyantjs/types/schemas/kms/envelope";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { type AwsKmsConfig, AwsKmsProvider } from "./kms-aws.js";
|
|
11
|
+
import { type EnvKmsConfig, EnvKmsProvider, generateEnvKmsKey } from "./kms-env.js";
|
|
12
|
+
import { type GcpKmsConfig, GcpKmsProvider } from "./kms-gcp.js";
|
|
13
|
+
import { generateLocalKmsKey, type LocalKmsConfig, LocalKmsProvider } from "./kms-local.js";
|
|
14
|
+
export type KmsKeyType = "people" | "integrations";
|
|
15
|
+
export interface KeyRef {
|
|
16
|
+
keyType: KmsKeyType;
|
|
17
|
+
}
|
|
18
|
+
export interface KmsProvider {
|
|
19
|
+
/**
|
|
20
|
+
* Provider identifier. Known values are "gcp", "aws", "env", and "local"; custom providers
|
|
21
|
+
* may use any string (the `(string & {})` pattern keeps autocomplete for the
|
|
22
|
+
* known values without forbidding others).
|
|
23
|
+
*/
|
|
24
|
+
readonly name: "gcp" | "aws" | "env" | "local" | (string & {});
|
|
25
|
+
encrypt(plaintext: string, key: KeyRef): Promise<string>;
|
|
26
|
+
decrypt(ciphertext: string, key: KeyRef): Promise<string>;
|
|
27
|
+
}
|
|
28
|
+
export type KmsConfig = {
|
|
29
|
+
provider: "gcp";
|
|
30
|
+
gcp: GcpKmsConfig;
|
|
31
|
+
} | {
|
|
32
|
+
provider: "aws";
|
|
33
|
+
aws: AwsKmsConfig;
|
|
34
|
+
} | {
|
|
35
|
+
provider: "env";
|
|
36
|
+
env: EnvKmsConfig;
|
|
37
|
+
} | {
|
|
38
|
+
provider: "local";
|
|
39
|
+
local: LocalKmsConfig;
|
|
40
|
+
} | {
|
|
41
|
+
provider: "custom";
|
|
42
|
+
custom: KmsProvider;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Build a provider instance from a validated config object.
|
|
46
|
+
*
|
|
47
|
+
* Supply `{ provider: "custom", custom: <your KmsProvider> }` to plug in an
|
|
48
|
+
* implementation that isn't built in (e.g. AWS KMS, HashiCorp Vault).
|
|
49
|
+
*/
|
|
50
|
+
export declare function createKmsProvider(config: KmsConfig): KmsProvider;
|
|
51
|
+
/**
|
|
52
|
+
* Build a `KmsConfig` from an env-like object. Accepts CF Workers `c.env`,
|
|
53
|
+
* Node `process.env`, or any plain object.
|
|
54
|
+
*
|
|
55
|
+
* Throws with a clear message if `KMS_PROVIDER` is unset/invalid or required
|
|
56
|
+
* provider-specific vars are missing.
|
|
57
|
+
*/
|
|
58
|
+
export declare function kmsConfigFromEnv(env: Record<string, string | undefined>): KmsConfig;
|
|
59
|
+
export declare function createKmsProviderFromEnv(env: Record<string, string | undefined>): KmsProvider;
|
|
60
|
+
export declare function encryptJsonEnvelope<T>(provider: KmsProvider, key: KeyRef, value: T): Promise<KmsEncryptedEnvelope>;
|
|
61
|
+
export declare function decryptJsonEnvelope<T>(provider: KmsProvider, key: KeyRef, envelope: KmsEncryptedEnvelope, schema: z.ZodType<T>): Promise<T>;
|
|
62
|
+
export declare function encryptOptionalJsonEnvelope<T>(provider: KmsProvider, key: KeyRef, value: T | null | undefined): Promise<KmsEncryptedEnvelope | null>;
|
|
63
|
+
export declare function decryptOptionalJsonEnvelope<T>(provider: KmsProvider, key: KeyRef, envelope: KmsEncryptedEnvelope | null | undefined, schema: z.ZodType<T>): Promise<T | null>;
|
|
64
|
+
export type { AwsKmsConfig, EnvKmsConfig, GcpKmsConfig, LocalKmsConfig };
|
|
65
|
+
export { AwsKmsProvider, EnvKmsProvider, GcpKmsProvider, generateEnvKmsKey, generateLocalKmsKey, LocalKmsProvider, };
|
|
66
|
+
//# sourceMappingURL=kms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms.d.ts","sourceRoot":"","sources":["../src/kms.ts"],"names":[],"mappings":"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"}
|