@forklaunch/core 2.1.1 → 3.0.1
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/bin/gateway-mock/routes/email.mjs +233 -0
- package/bin/gateway-mock/routes/models.mjs +192 -0
- package/bin/gateway-mock/routes/payments.mjs +541 -0
- package/bin/gateway-mock/routes/sms.mjs +209 -0
- package/bin/gateway-mock/routes/voice.mjs +237 -0
- package/bin/gateway-mock/routes/whatsapp.mjs +227 -0
- package/bin/gateway-mock/server.mjs +321 -0
- package/bin/migrate-compliant-fields.mjs +312 -0
- package/bin/model-gateway-mock.mjs +13 -0
- package/lib/http/emailClient.d.ts +102 -0
- package/lib/http/emailClient.d.ts.map +1 -0
- package/lib/http/index.d.ts +7 -0
- package/lib/http/index.d.ts.map +1 -1
- package/lib/http/index.js +850 -4
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +809 -1
- package/lib/http/index.mjs.map +1 -1
- package/lib/http/instanceGateway.d.ts +113 -0
- package/lib/http/instanceGateway.d.ts.map +1 -0
- package/lib/http/modelGatewayClient.d.ts +126 -0
- package/lib/http/modelGatewayClient.d.ts.map +1 -0
- package/lib/http/paymentsClient.d.ts +123 -0
- package/lib/http/paymentsClient.d.ts.map +1 -0
- package/lib/http/smsClient.d.ts +123 -0
- package/lib/http/smsClient.d.ts.map +1 -0
- package/lib/http/voiceClient.d.ts +105 -0
- package/lib/http/voiceClient.d.ts.map +1 -0
- package/lib/http/whatsappClient.d.ts +118 -0
- package/lib/http/whatsappClient.d.ts.map +1 -0
- package/lib/objectstore/interfaces/objectstore.interface.d.ts +45 -0
- package/lib/objectstore/interfaces/objectstore.interface.d.ts.map +1 -1
- package/lib/persistence/compliancePropertyBuilder.d.ts.map +1 -1
- package/lib/persistence/complianceTypes.d.ts +10 -1
- package/lib/persistence/complianceTypes.d.ts.map +1 -1
- package/lib/persistence/compliantField.d.ts +203 -0
- package/lib/persistence/compliantField.d.ts.map +1 -0
- package/lib/persistence/defineComplianceEntity.d.ts.map +1 -1
- package/lib/persistence/encryptedType.d.ts +8 -1
- package/lib/persistence/encryptedType.d.ts.map +1 -1
- package/lib/persistence/fieldEncryptor.d.ts +47 -6
- package/lib/persistence/fieldEncryptor.d.ts.map +1 -1
- package/lib/persistence/index.d.ts +3 -2
- package/lib/persistence/index.d.ts.map +1 -1
- package/lib/persistence/index.js +987 -259
- package/lib/persistence/index.js.map +1 -1
- package/lib/persistence/index.mjs +976 -257
- package/lib/persistence/index.mjs.map +1 -1
- package/lib/persistence/keyRotation.d.ts +5 -0
- package/lib/persistence/keyRotation.d.ts.map +1 -1
- package/lib/services/index.js.map +1 -1
- package/lib/services/index.mjs.map +1 -1
- package/package.json +27 -11
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { type InstanceGatewayOptions, InstanceGatewayRequestError } from './instanceGateway';
|
|
2
|
+
/**
|
|
3
|
+
* Client for WhatsApp through the ForkLaunch instance gateway, used from
|
|
4
|
+
* inside a managed instance.
|
|
5
|
+
*
|
|
6
|
+
* The platform holds the WhatsApp Business Account link (AWS End User
|
|
7
|
+
* Messaging Social) and sends on the instance's behalf from the phone number
|
|
8
|
+
* configured for its product or for this instance. The instance never holds
|
|
9
|
+
* a Meta token: each request is signed with its own HMAC key, and the
|
|
10
|
+
* platform enforces WhatsApp's rules and its own:
|
|
11
|
+
*
|
|
12
|
+
* - Business-initiated messages must use a Meta-approved template
|
|
13
|
+
* (`sendTemplate`).
|
|
14
|
+
* - Free-form text (`sendText`) is allowed only inside the 24-hour
|
|
15
|
+
* customer-service window, opened by the recipient's last inbound
|
|
16
|
+
* message. Outside it the gateway answers 422.
|
|
17
|
+
* - A per-instance rate limit (429 with `retryAfterSeconds`).
|
|
18
|
+
* - HIPAA products cannot send at all (403): WhatsApp is not covered by
|
|
19
|
+
* the AWS BAA and Meta signs none. Never put protected health data in a
|
|
20
|
+
* WhatsApp message.
|
|
21
|
+
* - No phone number configured for the product or instance: 409.
|
|
22
|
+
*
|
|
23
|
+
* Events arrive at `/platform-events/whatsapp` (see `verifyPlatformEvent`):
|
|
24
|
+
* - `whatsapp.received` `{ from, text?, type, receivedAt, messageId }`, an
|
|
25
|
+
* inbound message; it opens the 24-hour window for `from`.
|
|
26
|
+
* - `whatsapp.status` `{ messageId, status, recipient?, timestamp? }`,
|
|
27
|
+
* `status` being Meta's `sent`, `delivered`, `read` or `failed`.
|
|
28
|
+
*
|
|
29
|
+
* Locally, `forklaunch infra add <service> whatsapp` points the service at
|
|
30
|
+
* the gateway mock (`forklaunch-gateway-mock`, routes/whatsapp.mjs), which
|
|
31
|
+
* serves templates, emits these events and applies the same refusals.
|
|
32
|
+
*
|
|
33
|
+
* The shape is channel-neutral on purpose (`ConversationChannelClient`):
|
|
34
|
+
* another conversational channel (for example Apple Messages for Business)
|
|
35
|
+
* would be another channel id behind the same three calls.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const whatsapp = createWhatsAppClient();
|
|
39
|
+
* await whatsapp.sendTemplate({
|
|
40
|
+
* to: '+14155550123',
|
|
41
|
+
* template: 'appointment_reminder',
|
|
42
|
+
* language: 'en_US',
|
|
43
|
+
* components: [{ type: 'body', parameters: [{ type: 'text', text: 'Tuesday 3pm' }] }]
|
|
44
|
+
* });
|
|
45
|
+
*/
|
|
46
|
+
export type WhatsAppClientOptions = InstanceGatewayOptions;
|
|
47
|
+
/** A Meta template component (header, body, button), passed through as is. */
|
|
48
|
+
export interface WhatsAppTemplateComponent {
|
|
49
|
+
type: string;
|
|
50
|
+
parameters?: Record<string, unknown>[];
|
|
51
|
+
[key: string]: unknown;
|
|
52
|
+
}
|
|
53
|
+
export interface SendTemplateRequest {
|
|
54
|
+
/** E.164 recipient, e.g. `+14155550123`. */
|
|
55
|
+
to: string;
|
|
56
|
+
/** The approved template's name. */
|
|
57
|
+
template: string;
|
|
58
|
+
/** The template's language code, e.g. `en_US`. */
|
|
59
|
+
language: string;
|
|
60
|
+
/** Variable values for the template, in Meta's component format. */
|
|
61
|
+
components?: WhatsAppTemplateComponent[];
|
|
62
|
+
}
|
|
63
|
+
export interface SendTextRequest {
|
|
64
|
+
/** E.164 recipient; must have written to this number in the last 24 hours. */
|
|
65
|
+
to: string;
|
|
66
|
+
body: string;
|
|
67
|
+
}
|
|
68
|
+
export interface SentMessage {
|
|
69
|
+
/** Matches `messageId` on later `whatsapp.status` events. */
|
|
70
|
+
messageId: string;
|
|
71
|
+
}
|
|
72
|
+
export interface MessageTemplate {
|
|
73
|
+
name: string;
|
|
74
|
+
language: string;
|
|
75
|
+
/** Meta's review status: `APPROVED`, `PENDING`, `REJECTED`, … */
|
|
76
|
+
status: string;
|
|
77
|
+
category?: string;
|
|
78
|
+
}
|
|
79
|
+
/** The data of a `whatsapp.received` event. */
|
|
80
|
+
export interface WhatsAppReceivedEvent {
|
|
81
|
+
from: string;
|
|
82
|
+
/** Present for `type: 'text'` messages. */
|
|
83
|
+
text?: string;
|
|
84
|
+
type: string;
|
|
85
|
+
receivedAt: string;
|
|
86
|
+
messageId?: string;
|
|
87
|
+
}
|
|
88
|
+
/** The data of a `whatsapp.status` event. */
|
|
89
|
+
export interface WhatsAppStatusEvent {
|
|
90
|
+
messageId: string;
|
|
91
|
+
status: string;
|
|
92
|
+
recipient?: string;
|
|
93
|
+
timestamp?: string;
|
|
94
|
+
}
|
|
95
|
+
/** A refusal or failure from the WhatsApp gateway, with its status. */
|
|
96
|
+
export declare class WhatsAppRequestError extends InstanceGatewayRequestError {
|
|
97
|
+
readonly name: 'WhatsAppRequestError';
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The calls every conversational channel offers. WhatsApp is the only
|
|
101
|
+
* implementation today.
|
|
102
|
+
*/
|
|
103
|
+
export interface ConversationChannelClient {
|
|
104
|
+
/** Business-initiated message from an approved template. */
|
|
105
|
+
sendTemplate(request: SendTemplateRequest): Promise<SentMessage>;
|
|
106
|
+
/** Free-form text, inside the 24-hour customer-service window only. */
|
|
107
|
+
sendText(request: SendTextRequest): Promise<SentMessage>;
|
|
108
|
+
/** The templates the configured account has, with their review status. */
|
|
109
|
+
templates(): Promise<MessageTemplate[]>;
|
|
110
|
+
}
|
|
111
|
+
export type WhatsAppClient = ConversationChannelClient;
|
|
112
|
+
/**
|
|
113
|
+
* A WhatsApp client for this managed instance. Throws when the service is
|
|
114
|
+
* not running in managed mode (`PLATFORM_GATEWAY_URL`, `INSTANCE_ID`,
|
|
115
|
+
* `INSTANCE_HMAC_KEY` unset); run the local gateway mock to develop.
|
|
116
|
+
*/
|
|
117
|
+
export declare function createWhatsAppClient(options?: WhatsAppClientOptions): WhatsAppClient;
|
|
118
|
+
//# sourceMappingURL=whatsappClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whatsappClient.d.ts","sourceRoot":"","sources":["../../src/http/whatsappClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,sBAAsB,EAC3B,2BAA2B,EAC5B,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,MAAM,MAAM,qBAAqB,GAAG,sBAAsB,CAAC;AAE3D,8EAA8E;AAC9E,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACvC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,UAAU,CAAC,EAAE,yBAAyB,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,uEAAuE;AACvE,qBAAa,oBAAqB,SAAQ,2BAA2B;IACnE,SAAkB,IAAI,EAAG,sBAAsB,CAAU;CAC1D;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,4DAA4D;IAC5D,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACjE,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACzD,0EAA0E;IAC1E,SAAS,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CACzC;AAED,MAAM,MAAM,cAAc,GAAG,yBAAyB,CAAC;AA6EvD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,qBAA0B,GAClC,cAAc,CAEhB"}
|
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
import { Readable } from 'stream';
|
|
2
2
|
import type { ComplianceContext } from '../../cache/types/ttlCacheRecord.types';
|
|
3
|
+
/** A file body: bytes, text or a stream. */
|
|
4
|
+
export type ObjectStoreFileBody = Buffer | Uint8Array | string | Readable;
|
|
5
|
+
export interface PutFileOptions {
|
|
6
|
+
contentType: string;
|
|
7
|
+
/** Sets Content-Disposition, so a download saves under this name. */
|
|
8
|
+
filename?: string;
|
|
9
|
+
metadata?: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
export interface PresignUploadOptions {
|
|
12
|
+
/** The only content type the upload may carry. */
|
|
13
|
+
contentType: string;
|
|
14
|
+
/** Largest accepted upload, in bytes; the store rejects anything bigger. */
|
|
15
|
+
maxBytes: number;
|
|
16
|
+
/** Link lifetime in seconds. Default and ceiling: the store's upload cap. */
|
|
17
|
+
expiresIn?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A browser upload grant: a form POST of `fields`, then the file as the last
|
|
21
|
+
* field (named `file`), to `url`.
|
|
22
|
+
*/
|
|
23
|
+
export interface PresignedUpload {
|
|
24
|
+
url: string;
|
|
25
|
+
fields: Record<string, string>;
|
|
26
|
+
/** The key the object will be stored under, relative to the store. */
|
|
27
|
+
key: string;
|
|
28
|
+
expiresAt: Date;
|
|
29
|
+
}
|
|
30
|
+
export interface PresignDownloadOptions {
|
|
31
|
+
/** Link lifetime in seconds. Default and ceiling: the store's download cap. */
|
|
32
|
+
expiresIn?: number;
|
|
33
|
+
/** Serve as an attachment saved under this name. */
|
|
34
|
+
filename?: string;
|
|
35
|
+
}
|
|
3
36
|
/**
|
|
4
37
|
* Interface representing an object store.
|
|
5
38
|
*
|
|
@@ -50,6 +83,18 @@ export interface ObjectStore<Client> {
|
|
|
50
83
|
* Note: Streaming bypasses application-level encryption/decryption.
|
|
51
84
|
*/
|
|
52
85
|
streamDownloadBatchObjects(objectKeys: string[]): Promise<Readable[]>;
|
|
86
|
+
/**
|
|
87
|
+
* Stores a file as-is (not JSON-encoded, not encrypted by the app; the
|
|
88
|
+
* store's own at-rest encryption applies).
|
|
89
|
+
*/
|
|
90
|
+
putFile(objectKey: string, body: ObjectStoreFileBody, options: PutFileOptions): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* A short-lived grant for a browser to upload one file directly, with the
|
|
93
|
+
* size limit and content type enforced by the store.
|
|
94
|
+
*/
|
|
95
|
+
presignUpload(objectKey: string, options: PresignUploadOptions): Promise<PresignedUpload>;
|
|
96
|
+
/** A short-lived link to download one object. */
|
|
97
|
+
presignDownload(objectKey: string, options?: PresignDownloadOptions): Promise<string>;
|
|
53
98
|
/**
|
|
54
99
|
* Gets the underlying objectstore client instance.
|
|
55
100
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objectstore.interface.d.ts","sourceRoot":"","sources":["../../../src/objectstore/interfaces/objectstore.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAEhF;;;;;;GAMG;AACH,MAAM,WAAW,WAAW,CAAC,MAAM;IACjC;;OAEG;IACH,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvE;;OAEG;IACH,eAAe,CAAC,CAAC,EACf,OAAO,EAAE,CAAC,EAAE,EACZ,UAAU,CAAC,EAAE,iBAAiB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;OAEG;IACH,kBAAkB,CAAC,CAAC,EAClB,MAAM,EAAE,CAAC,EACT,UAAU,CAAC,EAAE,iBAAiB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;OAEG;IACH,wBAAwB,CAAC,CAAC,EACxB,OAAO,EAAE,CAAC,EAAE,EACZ,UAAU,CAAC,EAAE,iBAAiB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C;;OAEG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD;;OAEG;IACH,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE7E;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAChB,UAAU,EAAE,MAAM,EAAE,EACpB,UAAU,CAAC,EAAE,iBAAiB,GAC7B,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAEhB;;;OAGG;IACH,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE3D;;;OAGG;IACH,0BAA0B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEtE;;OAEG;IACH,SAAS,IAAI,MAAM,CAAC;CACrB"}
|
|
1
|
+
{"version":3,"file":"objectstore.interface.d.ts","sourceRoot":"","sources":["../../../src/objectstore/interfaces/objectstore.interface.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compliancePropertyBuilder.d.ts","sourceRoot":"","sources":["../../src/persistence/compliancePropertyBuilder.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"compliancePropertyBuilder.d.ts","sourceRoot":"","sources":["../../src/persistence/compliancePropertyBuilder.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AA2QjE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,EAAE,EAAE,gBAsCK,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CompliantField, ComplianceOptions } from './compliantField';
|
|
1
2
|
export declare const ComplianceLevel: {
|
|
2
3
|
readonly pii: 'pii';
|
|
3
4
|
readonly phi: 'phi';
|
|
@@ -6,6 +7,14 @@ export declare const ComplianceLevel: {
|
|
|
6
7
|
};
|
|
7
8
|
export type ComplianceLevel = (typeof ComplianceLevel)[keyof typeof ComplianceLevel];
|
|
8
9
|
export declare const COMPLIANCE_KEY: '~compliance';
|
|
10
|
+
/**
|
|
11
|
+
* The property type a classification produces. `none` leaves the value as
|
|
12
|
+
* it is; pii, phi and pci wrap it in a {@link CompliantField}, keeping
|
|
13
|
+
* `null`/`undefined` outside the wrapper so nullability reads naturally.
|
|
14
|
+
*/
|
|
15
|
+
export type CompliantValue<V, L, O = Record<never, never>> = L extends 'pii' | 'phi' | 'pci' ? [V] extends [null | undefined] ? V : CompliantField<NonNullable<V>, L, O extends {
|
|
16
|
+
readonly queryable: true;
|
|
17
|
+
} ? true : false> | Extract<V, null | undefined> : V;
|
|
9
18
|
export declare function registerEntityCompliance(entityName: string, fields: Map<string, ComplianceLevel>): void;
|
|
10
19
|
export declare function getComplianceMetadata(entityName: string, fieldName: string): ComplianceLevel;
|
|
11
20
|
export declare function getEntityComplianceFields(entityName: string): Map<string, ComplianceLevel> | undefined;
|
|
@@ -66,7 +75,7 @@ declare module '@mikro-orm/core' {
|
|
|
66
75
|
* marker cannot tell them apart. See {@link RequiresEncryptionContext} for
|
|
67
76
|
* why the difference matters at a call site.
|
|
68
77
|
*/
|
|
69
|
-
compliance<const L extends ComplianceLevel
|
|
78
|
+
compliance<const L extends ComplianceLevel, const O extends ComplianceOptions = Record<never, never>>(level: L, options?: L extends EncryptedComplianceLevel ? O : never): Pick<UniversalPropertyOptionsBuilder<CompliantValue<Value, L, O>, Options & {
|
|
70
79
|
readonly '~c': L;
|
|
71
80
|
}, IncludeKeys>, IncludeKeys & keyof UniversalPropertyOptionsBuilder<never, never, never>>;
|
|
72
81
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"complianceTypes.d.ts","sourceRoot":"","sources":["../../src/persistence/complianceTypes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe;aAC1B,GAAG,EAAE,KAAK;aACV,GAAG,EAAE,KAAK;aACV,GAAG,EAAE,KAAK;aACV,IAAI,EAAE,MAAM;CACJ,CAAC;AACX,MAAM,MAAM,eAAe,GACzB,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAEzD,eAAO,MAAM,cAAc,EAAG,aAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"complianceTypes.d.ts","sourceRoot":"","sources":["../../src/persistence/complianceTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { Type, type Platform, type PrimaryKeyProp, type TransformContext } from '@mikro-orm/core';
|
|
2
|
+
import type { EncryptedComplianceLevel } from './complianceTypes';
|
|
3
|
+
/**
|
|
4
|
+
* How a field's `.anon` value is derived. Shaped after the HIPAA Safe Harbor
|
|
5
|
+
* identifiers: identifiers become random tokens, dates keep the year, ZIP
|
|
6
|
+
* codes keep three digits (or `000` for sparsely populated areas), card
|
|
7
|
+
* numbers keep the last four, everything else is redacted.
|
|
8
|
+
*/
|
|
9
|
+
export type AnonStrategy = 'token' | 'year' | 'zip3' | 'last4' | 'redact';
|
|
10
|
+
/** Options accepted by `.compliance(level, options)` for pii, phi and pci. */
|
|
11
|
+
export interface ComplianceOptions {
|
|
12
|
+
/**
|
|
13
|
+
* How `.anon` is derived. Defaults to `token` for strings, `year` for
|
|
14
|
+
* dates and `redact` for everything else.
|
|
15
|
+
*/
|
|
16
|
+
readonly anon?: AnonStrategy;
|
|
17
|
+
/**
|
|
18
|
+
* Allow equality lookups (`where: { field: value }`, `$in`, `$ne`, `$nin`).
|
|
19
|
+
* Adds a `<column>_idx` blind-index column (keyed HMAC) that the query is
|
|
20
|
+
* matched against; the ciphertext stays in the original column.
|
|
21
|
+
*/
|
|
22
|
+
readonly queryable?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* How values are normalized before indexing. `exact` (default) matches
|
|
25
|
+
* byte for byte; `lowercase` trims and lowercases strings first (emails).
|
|
26
|
+
*/
|
|
27
|
+
readonly normalize?: 'exact' | 'lowercase';
|
|
28
|
+
}
|
|
29
|
+
/** @internal what a compliant column type knows about its property. */
|
|
30
|
+
export interface CompliantFieldSpec {
|
|
31
|
+
level: EncryptedComplianceLevel;
|
|
32
|
+
anon: AnonStrategy;
|
|
33
|
+
queryable: boolean;
|
|
34
|
+
normalize: 'exact' | 'lowercase';
|
|
35
|
+
elementRuntimeType: string;
|
|
36
|
+
isArray: boolean;
|
|
37
|
+
enumValues?: readonly unknown[];
|
|
38
|
+
/** `Entity.property`, filled in by defineComplianceEntity. */
|
|
39
|
+
path: string;
|
|
40
|
+
}
|
|
41
|
+
/** Emitted every time a compliant field's plaintext is read via `.deanon`. */
|
|
42
|
+
export interface ComplianceAccessEvent {
|
|
43
|
+
/** `Entity.property` */
|
|
44
|
+
field: string;
|
|
45
|
+
level: EncryptedComplianceLevel;
|
|
46
|
+
tenantId: string;
|
|
47
|
+
}
|
|
48
|
+
export type ComplianceAccessListener = (event: ComplianceAccessEvent) => void;
|
|
49
|
+
/**
|
|
50
|
+
* Register a listener for every `.deanon` read, for access audit logs.
|
|
51
|
+
* Returns a function that removes it.
|
|
52
|
+
*/
|
|
53
|
+
export declare function onComplianceAccess(listener: ComplianceAccessListener): () => void;
|
|
54
|
+
/**
|
|
55
|
+
* Thrown by `.anon` on a value still stored in a pre-v4 envelope under a
|
|
56
|
+
* `token` strategy: there is no stored token yet, and one must never be
|
|
57
|
+
* derived from the value. Run `reencryptEncryptedColumns` once to upgrade.
|
|
58
|
+
*/
|
|
59
|
+
export declare class LegacyCiphertextError extends Error {
|
|
60
|
+
readonly name: 'LegacyCiphertextError';
|
|
61
|
+
}
|
|
62
|
+
/** Thrown when a query targets a compliant field in a way it cannot answer. */
|
|
63
|
+
export declare class CompliantQueryError extends Error {
|
|
64
|
+
readonly name: 'CompliantQueryError';
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A de-identified value, produced only by a compliant field's `.anon`.
|
|
68
|
+
* Anything that must never carry protected data (a message to a provider
|
|
69
|
+
* without a BAA, a log line, an analytics event) can require this type and
|
|
70
|
+
* check it at runtime with {@link isAnon}; a plain string cannot pass.
|
|
71
|
+
*/
|
|
72
|
+
export declare class Anon {
|
|
73
|
+
readonly value: string;
|
|
74
|
+
/** @internal */
|
|
75
|
+
constructor(value: string, key: symbol);
|
|
76
|
+
}
|
|
77
|
+
/** True for values produced by `.anon` (works across duplicate package copies). */
|
|
78
|
+
export declare function isAnon(value: unknown): value is Anon;
|
|
79
|
+
/** @internal */
|
|
80
|
+
export declare function computeAnon(strategy: AnonStrategy, value: unknown): string;
|
|
81
|
+
/** The default strategy for a property's runtime type. */
|
|
82
|
+
export declare function defaultAnonStrategy(elementRuntimeType: string, isArray: boolean, hasEnum: boolean): AnonStrategy;
|
|
83
|
+
/**
|
|
84
|
+
* A pii, phi or pci property of an entity. The only ways to its value are
|
|
85
|
+
* `.anon` (de-identified, safe to share) and `.deanon` (plaintext, reported
|
|
86
|
+
* to {@link onComplianceAccess} listeners). There are deliberately no
|
|
87
|
+
* `toString`, `toJSON` or inspect overloads: interpolating it prints
|
|
88
|
+
* `[object Object]` and serializing it prints `{}`, so nothing leaks by
|
|
89
|
+
* accident and every read is explicit.
|
|
90
|
+
*
|
|
91
|
+
* Plaintext is decrypted lazily, on the first `.deanon`, in the caller's
|
|
92
|
+
* encryption context.
|
|
93
|
+
*
|
|
94
|
+
* Assigning a plain value to the property (directly, through `em.create` or
|
|
95
|
+
* through `em.assign`) wraps it; `where: { property: value }` works for
|
|
96
|
+
* fields declared `queryable`.
|
|
97
|
+
*/
|
|
98
|
+
export declare class CompliantField<V = unknown, L extends EncryptedComplianceLevel = EncryptedComplianceLevel, Q extends boolean = boolean> {
|
|
99
|
+
/** @internal */
|
|
100
|
+
readonly __runtime?: CompliantField<V, L, Q> | V;
|
|
101
|
+
/** @internal */
|
|
102
|
+
readonly __raw?: string;
|
|
103
|
+
/** @internal */
|
|
104
|
+
readonly __serialized?: Record<string, never>;
|
|
105
|
+
/** @internal lets `where` accept a plain value, but only for queryable fields */
|
|
106
|
+
readonly [PrimaryKeyProp]?: Q extends true ? V : never;
|
|
107
|
+
/** @internal carries the level into the type */
|
|
108
|
+
readonly __level?: L;
|
|
109
|
+
private constructor();
|
|
110
|
+
/**
|
|
111
|
+
* @internal Wrap a plaintext value for `spec`. Applications assign plain
|
|
112
|
+
* values to the entity property instead.
|
|
113
|
+
*/
|
|
114
|
+
static fromPlain<V>(value: V, spec: CompliantFieldSpec): CompliantField<V>;
|
|
115
|
+
/** @internal Wrap a stored value (any envelope, or legacy plaintext). */
|
|
116
|
+
static fromStored<V>(stored: string, spec: CompliantFieldSpec, index?: string | null): CompliantField<V>;
|
|
117
|
+
/** @internal A queryable field whose ciphertext column was not selected. */
|
|
118
|
+
static fromIndexOnly<V>(index: string | null, spec: CompliantFieldSpec): CompliantField<V>;
|
|
119
|
+
/** The field's classification. */
|
|
120
|
+
get level(): L;
|
|
121
|
+
/** The de-identified value. Never decrypts for values in a `v4` envelope. */
|
|
122
|
+
get anon(): Anon;
|
|
123
|
+
/** The plaintext. Every read is reported to access listeners. */
|
|
124
|
+
get deanon(): V;
|
|
125
|
+
}
|
|
126
|
+
/** True for compliant field instances (works across duplicate package copies). */
|
|
127
|
+
export declare function isCompliantField(value: unknown): value is CompliantField;
|
|
128
|
+
/** @internal The stored envelope for a field, sealing it on first use. */
|
|
129
|
+
export declare function sealedValueOf(field: CompliantField): string | undefined;
|
|
130
|
+
/** @internal Normalize an already-serialized value for indexing. */
|
|
131
|
+
export declare function normalizeSerializedForIndex(serialized: string, spec: CompliantFieldSpec): string;
|
|
132
|
+
/** @internal Blind index of a raw query value. */
|
|
133
|
+
export declare function blindIndexOfValue(value: unknown, spec: CompliantFieldSpec): string;
|
|
134
|
+
/** @internal The blind index for a field, computing it when missing. */
|
|
135
|
+
export declare function blindIndexOf(field: CompliantField): string | null;
|
|
136
|
+
declare const PENDING: unique symbol;
|
|
137
|
+
/** @internal Placeholder hydrated into a queryable property before its ciphertext is paired with it. */
|
|
138
|
+
export interface PendingIndex {
|
|
139
|
+
readonly [PENDING]: string | null;
|
|
140
|
+
}
|
|
141
|
+
export declare function isPendingIndex(value: unknown): value is PendingIndex;
|
|
142
|
+
export declare function pendingIndexValue(value: PendingIndex): string | null;
|
|
143
|
+
declare abstract class CompliantTypeBase extends Type<unknown, string | null> {
|
|
144
|
+
readonly spec: CompliantFieldSpec;
|
|
145
|
+
constructor(spec: CompliantFieldSpec);
|
|
146
|
+
getColumnType(): string;
|
|
147
|
+
get runtimeType(): string;
|
|
148
|
+
ensureComparable(): boolean;
|
|
149
|
+
compareAsType(): string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Column type of a non-queryable compliant field. The column holds the
|
|
153
|
+
* `v4` envelope; loading yields a {@link CompliantField}.
|
|
154
|
+
*/
|
|
155
|
+
export declare class CompliantType extends CompliantTypeBase {
|
|
156
|
+
convertToDatabaseValue(value: unknown, _platform: Platform, context?: TransformContext): string | null;
|
|
157
|
+
convertToJSValue(value: string | null): unknown;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Column type of a queryable compliant field. The property's own column
|
|
161
|
+
* (`<column>_idx`) holds the blind index, so `where` compiles to an
|
|
162
|
+
* index comparison; the envelope lives in a hidden sibling column.
|
|
163
|
+
*/
|
|
164
|
+
export declare class CompliantIndexType extends CompliantTypeBase {
|
|
165
|
+
convertToDatabaseValue(value: unknown, _platform: Platform, context?: TransformContext): string | null;
|
|
166
|
+
convertToJSValue(value: string | null): unknown;
|
|
167
|
+
}
|
|
168
|
+
/** True for the column types above. */
|
|
169
|
+
export declare function isCompliantType(type: unknown): type is CompliantType | CompliantIndexType;
|
|
170
|
+
/** @internal One compliant property of an entity class. */
|
|
171
|
+
export interface CompliantPropertyBinding {
|
|
172
|
+
property: string;
|
|
173
|
+
spec: CompliantFieldSpec;
|
|
174
|
+
/** Hidden property holding the envelope, for queryable fields. */
|
|
175
|
+
sibling?: string;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Install getter/setter pairs for compliant properties on an entity
|
|
179
|
+
* prototype. Assigning a plain value wraps it in a {@link CompliantField};
|
|
180
|
+
* reading returns the field.
|
|
181
|
+
*/
|
|
182
|
+
export declare function installCompliantAccessors(prototype: object, bindings: readonly CompliantPropertyBinding[]): void;
|
|
183
|
+
/** The value type behind a compliant field (null and undefined pass through). */
|
|
184
|
+
export type Deanon<X> = X extends CompliantField<infer V, EncryptedComplianceLevel, boolean> ? V : X;
|
|
185
|
+
/** An entity's fields with every compliant field replaced by its value. */
|
|
186
|
+
export type Deanonymized<T> = {
|
|
187
|
+
[K in keyof T]: Deanon<T[K]>;
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* A plain copy of an entity with every compliant field replaced by its
|
|
191
|
+
* `.deanon` value: what `{ ...entity }` produced before compliant fields,
|
|
192
|
+
* for first-party responses built by spreading an entity.
|
|
193
|
+
*
|
|
194
|
+
* A spread alone does not work: compliant properties live on the entity's
|
|
195
|
+
* prototype, so `{ ...entity }` would silently leave them out. Every value
|
|
196
|
+
* revealed here is reported to access listeners, like any `.deanon`.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* toDto: async (entity) => ({ ...deanon(entity), customerId: entity.customerId ?? undefined })
|
|
200
|
+
*/
|
|
201
|
+
export declare function deanon<T extends object>(entity: T): Deanonymized<T>;
|
|
202
|
+
export {};
|
|
203
|
+
//# sourceMappingURL=compliantField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compliantField.d.ts","sourceRoot":"","sources":["../../src/persistence/compliantField.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defineComplianceEntity.d.ts","sourceRoot":"","sources":["../../src/persistence/defineComplianceEntity.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"defineComplianceEntity.d.ts","sourceRoot":"","sources":["../../src/persistence/defineComplianceEntity.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,4BAA4B,EACjC,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC/B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,eAAe,EACrB,MAAM,mBAAmB,CAAC;AA6E3B,KAAK,kBAAkB,CAAC,CAAC,IAAI;KAC1B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAChB;QAAE,UAAU,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;SAAE,CAAA;KAAE,GAClD,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,GAC/B,CAAC,CAAC,CAAC,CAAC,GACJ;QAAE,UAAU,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;SAAE,CAAA;KAAE;CACvD,CAAC;AAQF,wBAAgB,sBAAsB,CACpC,KAAK,CAAC,KAAK,SAAS,MAAM,EAC1B,KAAK,CAAC,UAAU,SAAS,MAAM,EAC/B,KAAK,CAAC,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjD,KAAK,CAAC,GAAG,SAAS,CAAC,MAAM,WAAW,CAAC,EAAE,GAAG,SAAS,GAAG,SAAS,EAC/D,KAAK,CAAC,KAAK,GAAG,KAAK,EACnB,KAAK,CAAC,WAAW,GAAG,KAAK,EACzB,KAAK,CAAC,YAAY,SAAS,OAAO,GAAG,KAAK,EAE1C,IAAI,EAAE,4BAA4B,CAChC,KAAK,EACL,UAAU,EACV,WAAW,GAAG,kBAAkB,CAAC,WAAW,CAAC,EAC7C,GAAG,EACH,KAAK,EACL,WAAW,EACX,YAAY,CACb,GAAG;IAAE,SAAS,CAAC,EAAE,eAAe,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD,oBAAoB,CACrB,KAAK,EACL,UAAU,EACV,yBAAyB,CAAC,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,CAAC,EAC7E,KAAK,EACL,WAAW,CACZ,CAwFA"}
|
|
@@ -5,6 +5,8 @@ import type { FieldEncryptor } from './fieldEncryptor';
|
|
|
5
5
|
* Call this once at application bootstrap (e.g., in mikro-orm.config.ts).
|
|
6
6
|
*/
|
|
7
7
|
export declare function registerEncryptor(encryptor: FieldEncryptor): void;
|
|
8
|
+
/** The encryptor registered with {@link registerEncryptor}, if any. */
|
|
9
|
+
export declare function getRegisteredEncryptor(): FieldEncryptor | undefined;
|
|
8
10
|
/**
|
|
9
11
|
* The empty string was offered as a tenant id.
|
|
10
12
|
*
|
|
@@ -96,6 +98,8 @@ export declare function getCurrentTenantId(): string;
|
|
|
96
98
|
* encrypted column, and never a key.
|
|
97
99
|
*/
|
|
98
100
|
export declare function getBoundTenantId(): string | undefined;
|
|
101
|
+
/** The bound tenant, or {@link UnboundTenantError} naming what was attempted. */
|
|
102
|
+
export declare function requireBoundTenantId(operation: string): string;
|
|
99
103
|
/**
|
|
100
104
|
* Resolve a MikroORM type value (string, constructor, or instance) to a
|
|
101
105
|
* Type instance. Returns undefined if unresolvable.
|
|
@@ -133,6 +137,9 @@ export declare class EncryptedType extends Type<unknown, string | null> {
|
|
|
133
137
|
ensureComparable(): boolean;
|
|
134
138
|
private serialize;
|
|
135
139
|
private deserialize;
|
|
136
|
-
private tryJsonParse;
|
|
137
140
|
}
|
|
141
|
+
/** Turn any supported JS value into the string that gets encrypted. */
|
|
142
|
+
export declare function serializeForEncryption(value: unknown): string;
|
|
143
|
+
/** Inverse of {@link serializeForEncryption}, given the property's runtime type. */
|
|
144
|
+
export declare function deserializeFromEncryption(value: string, elementRuntimeType: string, isArray: boolean): unknown;
|
|
138
145
|
//# sourceMappingURL=encryptedType.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encryptedType.d.ts","sourceRoot":"","sources":["../../src/persistence/encryptedType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,QAAQ,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAoBvD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAEjE;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,GAAG,EAAE,MAAM,EAQtB;CACF;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,SAAS,EAAE,MAAM,EAQ5B;CACF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,QAAQ,IAAI,MAAM,CAI5B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAG5D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAGzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAErD;
|
|
1
|
+
{"version":3,"file":"encryptedType.d.ts","sourceRoot":"","sources":["../../src/persistence/encryptedType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,QAAQ,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAoBvD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAEjE;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,IAAI,cAAc,GAAG,SAAS,CAEnE;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,GAAG,EAAE,MAAM,EAQtB;CACF;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,SAAS,EAAE,MAAM,EAQ5B;CACF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,QAAQ,IAAI,MAAM,CAI5B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAG5D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAGzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAErD;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAM9D;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,OAAO,GACZ,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,SAAS,CAWpC;AAwCD;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAc,SAAQ,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAI7D,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;IAE5C;;;;;;OAMG;IACH,YACE,kBAAkB,GAAE,MAAiB,EACrC,OAAO,GAAE,OAAe,EACxB,UAAU,CAAC,EAAE,OAAO,EAAE,EAMvB;IAEQ,sBAAsB,CAC7B,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,QAAQ,EACnB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,MAAM,GAAG,IAAI,CAmCf;IAEQ,gBAAgB,CACvB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,SAAS,EAAE,QAAQ,GAClB,OAAO,CA2BT;IAEQ,aAAa,IAAI,MAAM,CAE/B;IAED,IAAa,WAAW,IAAI,MAAM,CAGjC;IAEQ,gBAAgB,IAAI,OAAO,CAEnC;IAMD,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,WAAW;CAOpB;AAMD,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAO7D;AAUD,oFAAoF;AACpF,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,EACb,kBAAkB,EAAE,MAAM,EAC1B,OAAO,EAAE,OAAO,GACf,OAAO,CAyBT"}
|
|
@@ -11,13 +11,23 @@ export declare class EncryptionRequiredError extends Error {
|
|
|
11
11
|
constructor(message?: string);
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* Ciphertext envelopes the encryptor reads.
|
|
14
|
+
* Ciphertext envelopes the encryptor reads. `v3` and `v4` name their key.
|
|
15
15
|
*
|
|
16
|
-
* v1:{iv}:{tag}:{data}
|
|
17
|
-
* v2:{iv}:{tag}:{data}
|
|
18
|
-
* v3:{keyId}:{iv}:{tag}:{data}
|
|
16
|
+
* v1:{iv}:{tag}:{data} random IV (legacy)
|
|
17
|
+
* v2:{iv}:{tag}:{data} deterministic IV
|
|
18
|
+
* v3:{keyId}:{iv}:{tag}:{data} deterministic IV, stamped with the key fingerprint
|
|
19
|
+
* v4:{keyId}:{anon}:{iv}:{tag}:{data} random IV, stamped, carrying the field's
|
|
20
|
+
* de-identified value (base64url) in clear;
|
|
21
|
+
* written by compliant fields via {@link FieldEncryptor.seal}
|
|
19
22
|
*/
|
|
20
|
-
export declare const ENCRYPTED_PREFIXES: readonly ['v1:', 'v2:', 'v3:'];
|
|
23
|
+
export declare const ENCRYPTED_PREFIXES: readonly ['v1:', 'v2:', 'v3:', 'v4:'];
|
|
24
|
+
/** Prefix of blind-index values: `bi1:{keyId}:{hmac}`. */
|
|
25
|
+
export declare const BLIND_INDEX_PREFIX = "bi1:";
|
|
26
|
+
/**
|
|
27
|
+
* The de-identified value carried by a `v4` envelope, or null for any other
|
|
28
|
+
* envelope. Reading it never decrypts.
|
|
29
|
+
*/
|
|
30
|
+
export declare function sealedAnon(ciphertext: string): string | null;
|
|
21
31
|
/** True when the string carries one of the encryptor's envelopes. */
|
|
22
32
|
export declare function isEncryptedCiphertext(value: unknown): value is string;
|
|
23
33
|
/**
|
|
@@ -78,7 +88,9 @@ export interface OpenedCiphertext {
|
|
|
78
88
|
/** True when the current key opened it. */
|
|
79
89
|
current: boolean;
|
|
80
90
|
/** Envelope the value was stored in. */
|
|
81
|
-
version: 'v1' | 'v2' | 'v3';
|
|
91
|
+
version: 'v1' | 'v2' | 'v3' | 'v4';
|
|
92
|
+
/** The de-identified value a `v4` envelope carries; undefined otherwise. */
|
|
93
|
+
anon?: string;
|
|
82
94
|
/**
|
|
83
95
|
* True when a rewrite would change the stored bytes: the value is under
|
|
84
96
|
* a previous key, or it is unstamped while the encryptor writes `v3`.
|
|
@@ -172,5 +184,34 @@ export declare class FieldEncryptor {
|
|
|
172
184
|
* to detect writes.
|
|
173
185
|
*/
|
|
174
186
|
rotate(ciphertext: string | null, tenantId?: string): string | null;
|
|
187
|
+
/**
|
|
188
|
+
* Encrypt for a compliant field: a fresh random IV every time (equal
|
|
189
|
+
* plaintexts produce unrelated ciphertexts), stamped with the current key,
|
|
190
|
+
* and carrying `anon` — the field's de-identified value — in clear so it
|
|
191
|
+
* can be read without decrypting.
|
|
192
|
+
*
|
|
193
|
+
* Equality lookups do not use the ciphertext; they use {@link blindIndex}.
|
|
194
|
+
*
|
|
195
|
+
* @returns `v4:{keyId}:{anon}:{iv}:{tag}:{data}`
|
|
196
|
+
*/
|
|
197
|
+
seal(plaintext: string, tenantId: string, anon: string): string;
|
|
198
|
+
/**
|
|
199
|
+
* Keyed HMAC of a plaintext for equality lookups, under a key derived
|
|
200
|
+
* from the current master key and the tenant (separate from the
|
|
201
|
+
* encryption key). Deterministic per tenant and key, one-way, and never
|
|
202
|
+
* decryptable.
|
|
203
|
+
*
|
|
204
|
+
* After a master key rotation, rows still indexed under the previous key
|
|
205
|
+
* do not match until `reencryptEncryptedColumns` re-indexes them; see
|
|
206
|
+
* {@link blindIndexes} for a lookup that spans the ring.
|
|
207
|
+
*
|
|
208
|
+
* @returns `bi1:{keyId}:{hmac base64url}`
|
|
209
|
+
*/
|
|
210
|
+
blindIndex(plaintext: string, tenantId: string): string;
|
|
211
|
+
/** {@link blindIndex} under every key in the ring, current first. */
|
|
212
|
+
blindIndexes(plaintext: string, tenantId: string): string[];
|
|
213
|
+
/** True when a blind index was computed under a previous key. */
|
|
214
|
+
isStaleBlindIndex(index: string): boolean;
|
|
215
|
+
private blindIndexFor;
|
|
175
216
|
}
|
|
176
217
|
//# sourceMappingURL=fieldEncryptor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fieldEncryptor.d.ts","sourceRoot":"","sources":["../../src/persistence/fieldEncryptor.ts"],"names":[],"mappings":"AAMA,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,EAAG,2BAA2B,CAAU;IACrD,YAAY,OAAO,SAA2C,EAE7D;CACF;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAG,iBAAiB,CAAU;IAC3C,YACE,OAAO,SAAyE,EAGjF;CACF;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAG,yBAAyB,CAAU;IACnD,YACE,OAAO,SAAmE,EAG3E;CACF;
|
|
1
|
+
{"version":3,"file":"fieldEncryptor.d.ts","sourceRoot":"","sources":["../../src/persistence/fieldEncryptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
export { ComplianceLevel, type ComplianceLevel as ComplianceLevelType, getComplianceMetadata, getEntityComplianceFields, entityHasEncryptedFields, RetentionAction, type RetentionAction as RetentionActionType, type RetentionPolicy, RetentionDuration, parseDuration, subtractDuration, type ParsedDuration, getEntityRetention, getAllRetentionPolicies, getEntityUserIdField, getAllUserIdFields, type EncryptedComplianceLevel, type EncryptedKeysOf, type RequiresEncryptionContext, type SelectionAvoidsEncryptedColumns } from './complianceTypes';
|
|
1
|
+
export { ComplianceLevel, type ComplianceLevel as ComplianceLevelType, getComplianceMetadata, getEntityComplianceFields, entityHasEncryptedFields, RetentionAction, type RetentionAction as RetentionActionType, type RetentionPolicy, RetentionDuration, parseDuration, subtractDuration, type ParsedDuration, getEntityRetention, getAllRetentionPolicies, getEntityUserIdField, getAllUserIdFields, type CompliantValue, type EncryptedComplianceLevel, type EncryptedKeysOf, type RequiresEncryptionContext, type SelectionAvoidsEncryptedColumns } from './complianceTypes';
|
|
2
2
|
export { wrapEmWithForgivingDecryption, type ForgivingDecryptionLogger } from './forgivingDecryptionEm';
|
|
3
3
|
export { asEncryptionSafe, type ContextFreeKeysOfSchema, type ContextFreeReadOptions, type DecryptingReadOptions, type EncryptedKeysOfSchema, type EncryptionAwareReadOptions, type EncryptionSafeEntityManager, type HydratingReadMethod, type PropertiesOfSchema, type SchemaRequiresEncryptionContext } from './encryptionSafeEm';
|
|
4
|
+
export { Anon, CompliantField, CompliantIndexType, CompliantQueryError, CompliantType, LegacyCiphertextError, deanon, isAnon, isCompliantField, onComplianceAccess, type AnonStrategy, type ComplianceAccessEvent, type ComplianceAccessListener, type ComplianceOptions, type Deanon, type Deanonymized } from './compliantField';
|
|
4
5
|
export { fp } from './compliancePropertyBuilder';
|
|
5
6
|
export { defineComplianceEntity } from './defineComplianceEntity';
|
|
6
7
|
export { wrapEmWithNativeQueryBlocking } from './complianceEventSubscriber';
|
|
7
8
|
export { EncryptedType, registerEncryptor, setEncryptionTenantId, withEncryptionContext, getCurrentTenantId, getBoundTenantId, assertBindableTenantId, EmptyTenantError, UnboundTenantError } from './encryptedType';
|
|
8
|
-
export { FieldEncryptor, MissingEncryptionKeyError, DecryptionError, EncryptionRequiredError, parseEncryptionKeyList, encryptionKeyId, stampedKeyId, stampedPrefix, isEncryptedCiphertext, ENCRYPTED_PREFIXES, ENCRYPTION_FORMAT_ENV, ENCRYPTION_KEY_ENV, LEGACY_ENCRYPTION_KEYS_ENV, LEGACY_ENCRYPTION_KEY_ENV, type FieldEncryptorOptions, type OpenedCiphertext, type CiphertextFormat } from './fieldEncryptor';
|
|
9
|
+
export { FieldEncryptor, MissingEncryptionKeyError, DecryptionError, EncryptionRequiredError, parseEncryptionKeyList, encryptionKeyId, stampedKeyId, stampedPrefix, isEncryptedCiphertext, sealedAnon, BLIND_INDEX_PREFIX, ENCRYPTED_PREFIXES, ENCRYPTION_FORMAT_ENV, ENCRYPTION_KEY_ENV, LEGACY_ENCRYPTION_KEYS_ENV, LEGACY_ENCRYPTION_KEY_ENV, type FieldEncryptorOptions, type OpenedCiphertext, type CiphertextFormat } from './fieldEncryptor';
|
|
9
10
|
export { reencryptEncryptedColumns, classifyEncryptedValue, collectFallbackTenantIds, defaultTenantIdsFor, entityMetadataList, rotationTotals, countValuesByKeyId, isEncryptedValue, type ReencryptOptions, type RotationOutcome, type RotationTableReport, type SqlExecute, type EntityMetadataLike } from './keyRotation';
|
|
10
11
|
export { setupTenantFilter, getSuperAdminContext, createTenantFilterDef, TENANT_FILTER_NAME } from './tenantFilter';
|
|
11
12
|
export { setupRls, RlsEventSubscriber, type RlsConfig } from './rls';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/persistence/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,KAAK,eAAe,IAAI,mBAAmB,EAC3C,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EAExB,eAAe,EACf,KAAK,eAAe,IAAI,mBAAmB,EAC3C,KAAK,eAAe,EACpB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC9B,KAAK,+BAA+B,EACrC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,6BAA6B,EAC7B,KAAK,yBAAyB,EAC/B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,+BAA+B,EACrC,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/persistence/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,KAAK,eAAe,IAAI,mBAAmB,EAC3C,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EAExB,eAAe,EACf,KAAK,eAAe,IAAI,mBAAmB,EAC3C,KAAK,eAAe,EACpB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC9B,KAAK,+BAA+B,EACrC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,6BAA6B,EAC7B,KAAK,yBAAyB,EAC/B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,+BAA+B,EACrC,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EACL,IAAI,EACJ,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,MAAM,EACN,MAAM,EACN,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,MAAM,EACX,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AAGjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAG5E,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,eAAe,EACf,uBAAuB,EACvB,sBAAsB,EACtB,eAAe,EACf,YAAY,EACZ,aAAa,EACb,qBAAqB,EACrB,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,wBAAwB,EACxB,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAErE,YAAY,EACV,WAAW,EACX,cAAc,EACd,gBAAgB,EACjB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC"}
|