@forklaunch/core 1.5.20 → 1.6.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/lib/persistence/fieldEncryptor.d.ts +137 -9
- package/lib/persistence/fieldEncryptor.d.ts.map +1 -1
- package/lib/persistence/index.d.ts +2 -1
- package/lib/persistence/index.d.ts.map +1 -1
- package/lib/persistence/index.js +409 -26
- package/lib/persistence/index.js.map +1 -1
- package/lib/persistence/index.mjs +391 -26
- package/lib/persistence/index.mjs.map +1 -1
- package/lib/persistence/keyRotation.d.ts +118 -0
- package/lib/persistence/keyRotation.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/core';
|
|
2
|
+
import { isEncryptedCiphertext, type FieldEncryptor } from './fieldEncryptor';
|
|
3
|
+
export declare const isEncryptedValue: typeof isEncryptedCiphertext;
|
|
4
|
+
export type RotationOutcome = {
|
|
5
|
+
kind: 'plaintext';
|
|
6
|
+
} | {
|
|
7
|
+
kind: 'current';
|
|
8
|
+
tenantId: string;
|
|
9
|
+
keyId: string;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'rewritten';
|
|
12
|
+
tenantId: string;
|
|
13
|
+
keyId: string;
|
|
14
|
+
next: string;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'unreadable';
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Classify one stored value against the encryptor's ring. `tenantIds` are
|
|
20
|
+
* the row's likely tenants, most likely first; `fallbackTenantIds` are
|
|
21
|
+
* tried only when none of those open the value with any key.
|
|
22
|
+
*/
|
|
23
|
+
export declare function classifyEncryptedValue(value: unknown, encryptor: FieldEncryptor, tenantIds: readonly string[], fallbackTenantIds?: readonly string[]): RotationOutcome;
|
|
24
|
+
export interface RotationTableReport {
|
|
25
|
+
table: string;
|
|
26
|
+
columns: string[];
|
|
27
|
+
scanned: number;
|
|
28
|
+
plaintext: number;
|
|
29
|
+
current: number;
|
|
30
|
+
rewritten: number;
|
|
31
|
+
unreadable: number;
|
|
32
|
+
/** Row ids (primary key as string) with at least one unreadable value. */
|
|
33
|
+
unreadableIds: string[];
|
|
34
|
+
/** How many values each previous key still held before this pass. */
|
|
35
|
+
byKeyId: Record<string, number>;
|
|
36
|
+
/** Stamped key ids seen on unreadable values: keys that must be added to the ring. */
|
|
37
|
+
missingKeyIds: Record<string, number>;
|
|
38
|
+
}
|
|
39
|
+
export type SqlExecute = (sql: string, params?: unknown[]) => Promise<unknown>;
|
|
40
|
+
export interface ReencryptOptions {
|
|
41
|
+
em: EntityManager;
|
|
42
|
+
/** The ring: current key plus every previous key. */
|
|
43
|
+
encryptor: FieldEncryptor;
|
|
44
|
+
/** Report only; write nothing. */
|
|
45
|
+
dryRun?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Candidate tenant ids for a row, most likely first. The default tries
|
|
48
|
+
* the row's `organization_id` (when the table has one) and then the empty
|
|
49
|
+
* tenant. Modules with other tenant shapes (an organization is its own
|
|
50
|
+
* tenant) extend it.
|
|
51
|
+
*/
|
|
52
|
+
tenantIdsFor?: (entityName: string, row: Record<string, unknown>) => string[];
|
|
53
|
+
/**
|
|
54
|
+
* Tenants to try only when a row's own candidates open nothing. Pass the
|
|
55
|
+
* result of {@link collectFallbackTenantIds} to catch rows written under a
|
|
56
|
+
* mismatched context. Empty by default.
|
|
57
|
+
*/
|
|
58
|
+
fallbackTenantIds?: readonly string[];
|
|
59
|
+
/**
|
|
60
|
+
* How to run SQL. A migration must pass its own `this.execute`: MikroORM
|
|
61
|
+
* applies pending migrations inside one transaction, and a pooled
|
|
62
|
+
* connection cannot see tables that earlier migrations created but have
|
|
63
|
+
* not committed yet. Defaults to the entity manager's connection.
|
|
64
|
+
*/
|
|
65
|
+
execute?: SqlExecute;
|
|
66
|
+
log?: (message: string) => void;
|
|
67
|
+
}
|
|
68
|
+
/** `organization_id` first when the row carries one, then the empty tenant. */
|
|
69
|
+
export declare function defaultTenantIdsFor(_entityName: string, row: Record<string, unknown>): string[];
|
|
70
|
+
/**
|
|
71
|
+
* Every tenant id the database knows: the distinct `organization_id` of
|
|
72
|
+
* every table in the current schema that has one, plus `organization.id`
|
|
73
|
+
* where the module owns organizations. Used as the last-resort tenant list.
|
|
74
|
+
* PostgreSQL only (information_schema + to_regclass).
|
|
75
|
+
*/
|
|
76
|
+
export declare function collectFallbackTenantIds(execute: SqlExecute): Promise<string[]>;
|
|
77
|
+
export interface EntityMetadataLike {
|
|
78
|
+
className: string;
|
|
79
|
+
tableName?: string;
|
|
80
|
+
abstract?: boolean;
|
|
81
|
+
embeddable?: boolean;
|
|
82
|
+
primaryKeys: readonly string[];
|
|
83
|
+
properties: Record<string, {
|
|
84
|
+
fieldNames: string[];
|
|
85
|
+
columnTypes?: string[];
|
|
86
|
+
} | undefined>;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Every entity MikroORM discovered. `getMetadata().getAll()` is a Map in
|
|
90
|
+
* MikroORM 7 and was a plain object before; accept both shapes.
|
|
91
|
+
*/
|
|
92
|
+
export declare function entityMetadataList(em: EntityManager): EntityMetadataLike[];
|
|
93
|
+
/**
|
|
94
|
+
* Walk every registered entity with encrypted compliance fields and rewrite
|
|
95
|
+
* previous-key ciphertexts under the current key. Safe to re-run: every
|
|
96
|
+
* value is classified before anything is written.
|
|
97
|
+
*/
|
|
98
|
+
export declare function reencryptEncryptedColumns(options: ReencryptOptions): Promise<RotationTableReport[]>;
|
|
99
|
+
/**
|
|
100
|
+
* How many values in a column are stamped with each key (`v3`), and how
|
|
101
|
+
* many are unstamped (`v1`/`v2`). Cheap, read-only, no decryption: the
|
|
102
|
+
* answer to "can this key be dropped yet?" once a table is on `v3`.
|
|
103
|
+
*/
|
|
104
|
+
export declare function countValuesByKeyId(execute: SqlExecute, table: string, column: string): Promise<{
|
|
105
|
+
byKeyId: Record<string, number>;
|
|
106
|
+
unstamped: number;
|
|
107
|
+
plaintext: number;
|
|
108
|
+
}>;
|
|
109
|
+
/** Sum a report field across tables. */
|
|
110
|
+
export declare function rotationTotals(reports: readonly RotationTableReport[]): {
|
|
111
|
+
tables: number;
|
|
112
|
+
scanned: number;
|
|
113
|
+
rewritten: number;
|
|
114
|
+
current: number;
|
|
115
|
+
plaintext: number;
|
|
116
|
+
unreadable: number;
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=keyRotation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyRotation.d.ts","sourceRoot":"","sources":["../../src/persistence/keyRotation.ts"],"names":[],"mappings":"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"}
|