@prisma-next/extension-cipherstash 0.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/README.md +153 -0
- package/dist/call-classes-CSvD7w8U.mjs +206 -0
- package/dist/call-classes-CSvD7w8U.mjs.map +1 -0
- package/dist/column-types.d.mts +33 -0
- package/dist/column-types.d.mts.map +1 -0
- package/dist/column-types.mjs +42 -0
- package/dist/column-types.mjs.map +1 -0
- package/dist/constants-BDxL9Pe3.d.mts +22 -0
- package/dist/constants-BDxL9Pe3.d.mts.map +1 -0
- package/dist/constants-B_2TNvUi.mjs +46 -0
- package/dist/constants-B_2TNvUi.mjs.map +1 -0
- package/dist/control.d.mts +7 -0
- package/dist/control.d.mts.map +1 -0
- package/dist/control.mjs +430 -0
- package/dist/control.mjs.map +1 -0
- package/dist/descriptor-meta-BgQfZTAF.mjs +129 -0
- package/dist/descriptor-meta-BgQfZTAF.mjs.map +1 -0
- package/dist/envelope-P9BxfJNr.mjs +271 -0
- package/dist/envelope-P9BxfJNr.mjs.map +1 -0
- package/dist/middleware.d.mts +13 -0
- package/dist/middleware.d.mts.map +1 -0
- package/dist/middleware.mjs +129 -0
- package/dist/middleware.mjs.map +1 -0
- package/dist/migration.d.mts +141 -0
- package/dist/migration.d.mts.map +1 -0
- package/dist/migration.mjs +2 -0
- package/dist/operation-types.d.mts +49 -0
- package/dist/operation-types.d.mts.map +1 -0
- package/dist/operation-types.mjs +1 -0
- package/dist/pack.d.mts +86 -0
- package/dist/pack.d.mts.map +1 -0
- package/dist/pack.mjs +2 -0
- package/dist/runtime.d.mts +207 -0
- package/dist/runtime.d.mts.map +1 -0
- package/dist/runtime.mjs +429 -0
- package/dist/runtime.mjs.map +1 -0
- package/dist/sdk-D5FTGyzp.d.mts +67 -0
- package/dist/sdk-D5FTGyzp.d.mts.map +1 -0
- package/package.json +69 -0
- package/src/contract/authoring.ts +62 -0
- package/src/contract/contract.d.ts +149 -0
- package/src/contract/contract.json +104 -0
- package/src/contract/contract.prisma +46 -0
- package/src/execution/abort.ts +143 -0
- package/src/execution/codec-runtime.ts +209 -0
- package/src/execution/decrypt-all.ts +217 -0
- package/src/execution/envelope.ts +263 -0
- package/src/execution/operators.ts +211 -0
- package/src/execution/parameterized.ts +71 -0
- package/src/execution/routing.ts +93 -0
- package/src/execution/sdk.ts +68 -0
- package/src/exports/column-types.ts +62 -0
- package/src/exports/contract-space-typing.ts +86 -0
- package/src/exports/control.ts +120 -0
- package/src/exports/middleware.ts +24 -0
- package/src/exports/migration.ts +43 -0
- package/src/exports/operation-types.ts +16 -0
- package/src/exports/pack.ts +13 -0
- package/src/exports/runtime.ts +110 -0
- package/src/extension-metadata/codec-metadata.ts +81 -0
- package/src/extension-metadata/constants.ts +70 -0
- package/src/extension-metadata/descriptor-meta.ts +76 -0
- package/src/middleware/bulk-encrypt.ts +192 -0
- package/src/migration/call-classes.ts +350 -0
- package/src/migration/cipherstash-codec.ts +157 -0
- package/src/migration/eql-bundle.ts +29 -0
- package/src/migration/eql-install.generated.ts +5751 -0
- package/src/types/operation-types.ts +81 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.mjs","names":[],"sources":["../src/execution/routing.ts","../src/middleware/bulk-encrypt.ts"],"sourcesContent":["/**\n * Routing-key derivation for cipherstash bulk operations.\n *\n * The routing key is derived from the envelope handle's\n * `(table, column)` — there is no per-column override surface. Every\n * cipherstash envelope passing through `bulkEncryptMiddleware` (and\n * `decryptAll`) carries `(table, column)` on its handle, populated by\n * the middleware's AST walk before the bulk-encrypt phase begins.\n *\n * `groupByRoutingKey` produces one homogeneous group per\n * `(table, column)` pair so each `bulkEncrypt` call serves a single\n * routing key — matching the SDK's\n * `bulkEncrypt({ routingKey, values, signal })` shape. Heterogeneous\n * batching is a future optimization.\n */\n\nimport type { EncryptedString } from './envelope';\nimport type { CipherstashRoutingKey } from './sdk';\n\n/**\n * Per-target context the bulk-encrypt middleware accumulates while\n * walking `params.entries()`. Each target carries the envelope, its\n * routing key (derived from the handle), the plaintext to encrypt, and\n * the param-ref handle the mutator yielded so the post-encrypt\n * `replaceValues` write-back can find the slot.\n */\nexport interface BulkEncryptTarget<TRef = unknown> {\n readonly ref: TRef;\n readonly plaintext: string;\n readonly envelope: EncryptedString;\n readonly routingKey: CipherstashRoutingKey;\n}\n\n/**\n * Stable string key used to group targets by their `(table, column)`\n * routing key. Exported for tests; not part of the package's public\n * surface. Uses a NUL byte as the separator so the id never collides\n * across pairs whose names happen to share a literal concatenation\n * (e.g. `(a, bc)` vs `(ab, c)`).\n */\nexport function routingKeyId(routingKey: CipherstashRoutingKey): string {\n return `${routingKey.table}\\u0000${routingKey.column}`;\n}\n\n/**\n * Read the routing key from an envelope's internal handle. Throws if\n * the handle's `(table, column)` slots are unset — which happens when\n * the bulk-encrypt middleware's AST walk did not see this envelope\n * (typical cause: the envelope was passed in a context the AST walk\n * does not yet handle, e.g. a raw-SQL plan with no `InsertAst` /\n * `UpdateAst` arm). The throw matches the codec's\n * \"missing ciphertext\" diagnostic shape: it points at the workflow that\n * should have populated the slot.\n */\nexport function getRoutingKey(envelope: EncryptedString): CipherstashRoutingKey {\n const handle = envelope.expose();\n if (handle.table === undefined || handle.column === undefined) {\n throw new Error(\n 'cipherstash bulk-encrypt: envelope has no (table, column) routing context. ' +\n 'The bulk-encrypt middleware stamps routing context from the lowered AST ' +\n '(insert/update); raw-SQL plans embedding cipherstash envelopes must stamp ' +\n 'routing context explicitly before execute.',\n );\n }\n return { table: handle.table, column: handle.column };\n}\n\n/**\n * Group bulk-encrypt targets by `(table, column)` routing key. Each\n * `Map` entry yields one homogeneous batch suitable for a single\n * `sdk.bulkEncrypt({ routingKey, values, signal })` call.\n *\n * Order preservation: within each group, targets keep the order they\n * were collected from `params.entries()` — which is the canonical\n * ParamRef order the renderer's `$N` index map and the encode-side walk\n * both consume. Iteration order across groups follows the order each\n * routing key was first observed in the input.\n */\nexport function groupByRoutingKey<TRef>(\n targets: ReadonlyArray<BulkEncryptTarget<TRef>>,\n): Map<string, BulkEncryptTarget<TRef>[]> {\n const groups = new Map<string, BulkEncryptTarget<TRef>[]>();\n for (const target of targets) {\n const id = routingKeyId(target.routingKey);\n let group = groups.get(id);\n if (!group) {\n group = [];\n groups.set(id, group);\n }\n group.push(target);\n }\n return groups;\n}\n","/**\n * Bulk-encrypt middleware for cipherstash envelopes.\n *\n * The middleware sits in the SQL runtime's `beforeExecute` chain and:\n *\n * 1. Walks the lowered query AST (`InsertAst` / `UpdateAst`) and stamps\n * `(table, column)` routing context onto every `EncryptedString`\n * envelope embedded in a `ParamRef`. The handle's `(table, column)`\n * slots are the canonical input to {@link groupByRoutingKey}; this\n * walk is the single place the AST's structural column metadata gets\n * attached to the envelopes the SDK will see.\n *\n * 2. Iterates `params.entries()` to collect every cipherstash-codec'd\n * `ParamRef` whose value is an `EncryptedString`, groups them by\n * routing key, and issues exactly one `sdk.bulkEncrypt(...)` call\n * per group. Routing-key derivation is `(table, column)` —\n * homogeneous batches only.\n *\n * 3. Stamps each returned ciphertext onto the envelope's handle via\n * `setHandleCiphertext` and writes the envelope back through\n * `params.replaceValues` so the runtime's `currentParams()` view\n * reflects the post-mutation slot. The handle's `plaintext` slot\n * is **retained** — `envelope.decrypt()` continues to return the\n * plaintext synchronously without consulting the SDK.\n *\n * Cancellation: `ctx.signal` is forwarded by identity to every\n * `bulkEncrypt` call via `ifDefined`; the SDK is responsible for\n * honoring it. The awaiting middleware also races the SDK promise\n * against `ctx.signal` via `raceCipherstashAbort` so a caller-side\n * abort surfaces a `RUNTIME.ABORTED { phase: 'bulk-encrypt' }`\n * envelope promptly even when the SDK body itself ignores the signal.\n * A pre-flight `checkCipherstashAborted` short-circuits before any\n * SDK round-trip is scheduled when the signal is already aborted at\n * entry.\n */\n\nimport type {\n AnyQueryAst,\n ColumnRef,\n DefaultValueExpr,\n InsertAst,\n ParamRef,\n UpdateAst,\n} from '@prisma-next/sql-relational-core/ast';\nimport type {\n ParamRefHandle,\n SqlParamRefMutator,\n} from '@prisma-next/sql-relational-core/middleware';\nimport type { SqlMiddleware } from '@prisma-next/sql-runtime';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { checkCipherstashAborted, raceCipherstashAbort } from '../execution/abort';\nimport { EncryptedString, setHandleCiphertext, setHandleRoutingKey } from '../execution/envelope';\nimport { type BulkEncryptTarget, groupByRoutingKey } from '../execution/routing';\nimport type { CipherstashSdk } from '../execution/sdk';\nimport { CIPHERSTASH_STRING_CODEC_ID } from '../extension-metadata/constants';\n\n/**\n * Construct the bulk-encrypt middleware. The returned middleware is\n * stateless aside from the captured `sdk` reference; one instance per\n * runtime extension is the expected pattern.\n */\nexport function bulkEncryptMiddleware(sdk: CipherstashSdk): SqlMiddleware {\n return {\n name: 'cipherstash.bulk-encrypt',\n familyId: 'sql',\n async beforeExecute(plan, ctx, params) {\n if (!params) {\n return;\n }\n\n stampRoutingKeysFromAst(plan.ast);\n\n const targets = collectTargets(params);\n if (targets.length === 0) {\n return;\n }\n\n const groups = groupByRoutingKey(targets);\n for (const [groupKey, group] of groups) {\n const first = group[0];\n if (!first) continue;\n const routingKey = first.routingKey;\n\n checkCipherstashAborted(ctx.signal, 'bulk-encrypt');\n const ciphertexts = await raceCipherstashAbort(\n sdk.bulkEncrypt({\n routingKey,\n values: group.map((t) => t.plaintext),\n ...ifDefined('signal', ctx.signal),\n }),\n ctx.signal,\n 'bulk-encrypt',\n );\n\n if (ciphertexts.length !== group.length) {\n throw new Error(\n `cipherstash bulk-encrypt: SDK returned ${ciphertexts.length} ciphertexts ` +\n `for routing key ${groupKey} but ${group.length} were requested.`,\n );\n }\n\n params.replaceValues(\n group.map((t, i) => {\n const ciphertext = ciphertexts[i];\n setHandleCiphertext(t.envelope, ciphertext);\n return { ref: t.ref, newValue: t.envelope };\n }),\n );\n }\n },\n };\n}\n\nfunction collectTargets(\n params: SqlParamRefMutator,\n): BulkEncryptTarget<ParamRefHandle<string | undefined>>[] {\n const targets: BulkEncryptTarget<ParamRefHandle<string | undefined>>[] = [];\n for (const entry of params.entries()) {\n if (entry.codecId !== CIPHERSTASH_STRING_CODEC_ID) continue;\n const value = entry.value;\n if (!(value instanceof EncryptedString)) continue;\n const handle = value.expose();\n if (handle.plaintext === undefined) {\n throw new Error(\n 'cipherstash bulk-encrypt: encountered an envelope with no plaintext on the write path. ' +\n 'Use `EncryptedString.from(plaintext)` to construct write-side envelopes.',\n );\n }\n if (handle.table === undefined || handle.column === undefined) {\n throw new Error(\n 'cipherstash bulk-encrypt: envelope reached the bulk-encrypt phase without a (table, column) ' +\n \"routing context. The middleware's AST walk only handles `InsertAst` and `UpdateAst`; \" +\n 'cipherstash envelopes embedded in other plan shapes (e.g. raw SQL) must stamp routing ' +\n 'context explicitly via `setHandleRoutingKey` before execute.',\n );\n }\n targets.push({\n ref: entry.ref,\n plaintext: handle.plaintext,\n envelope: value,\n routingKey: { table: handle.table, column: handle.column },\n });\n }\n return targets;\n}\n\nfunction stampRoutingKeysFromAst(ast: AnyQueryAst | undefined): void {\n if (!ast) return;\n switch (ast.kind) {\n case 'insert':\n stampInsert(ast);\n return;\n case 'update':\n stampUpdate(ast);\n return;\n default:\n return;\n }\n}\n\nfunction stampInsert(ast: InsertAst): void {\n const tableName = ast.table.name;\n for (const row of ast.rows) {\n for (const [column, value] of Object.entries(row)) {\n stampParamRefIfEnvelope(value, tableName, column);\n }\n }\n if (ast.onConflict?.action.kind === 'do-update-set') {\n for (const [column, value] of Object.entries(ast.onConflict.action.set)) {\n stampParamRefIfEnvelope(value, tableName, column);\n }\n }\n}\n\nfunction stampUpdate(ast: UpdateAst): void {\n const tableName = ast.table.name;\n for (const [column, value] of Object.entries(ast.set)) {\n stampParamRefIfEnvelope(value, tableName, column);\n }\n}\n\nfunction stampParamRefIfEnvelope(\n value: ColumnRef | ParamRef | DefaultValueExpr,\n table: string,\n column: string,\n): void {\n if (value.kind !== 'param-ref') return;\n const inner = value.value;\n if (inner instanceof EncryptedString) {\n setHandleRoutingKey(inner, table, column);\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { ImportRequirement, TsExpression } from "@prisma-next/ts-render";
|
|
2
|
+
import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
|
|
3
|
+
import { MigrationOperationClass, OpFactoryCall } from "@prisma-next/framework-components/control";
|
|
4
|
+
|
|
5
|
+
//#region src/migration/call-classes.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Two-valued enumeration matching the EQL search-config indices the
|
|
8
|
+
* cipherstash codec emits — one per enabled flag in
|
|
9
|
+
* `Encrypted<string>`'s `typeParams`:
|
|
10
|
+
*
|
|
11
|
+
* - `equality: true` → `'unique'` index
|
|
12
|
+
* - `freeTextSearch: true` → `'match'` index
|
|
13
|
+
*/
|
|
14
|
+
type CipherstashSearchIndex = 'unique' | 'match';
|
|
15
|
+
/**
|
|
16
|
+
* Args shape accepted by the public `cipherstashAddSearchConfig` /
|
|
17
|
+
* `cipherstashRemoveSearchConfig` factory functions.
|
|
18
|
+
*
|
|
19
|
+
* `castAs` defaults to `'text'` — matches the cipherstash codec hook's
|
|
20
|
+
* canonical output and the EQL bundle's expected cast for
|
|
21
|
+
* `eql_v2_encrypted` columns. Override only if you know the runtime
|
|
22
|
+
* cast for your column differs.
|
|
23
|
+
*/
|
|
24
|
+
interface CipherstashSearchConfigArgs {
|
|
25
|
+
readonly table: string;
|
|
26
|
+
readonly column: string;
|
|
27
|
+
readonly index: CipherstashSearchIndex;
|
|
28
|
+
readonly castAs?: string;
|
|
29
|
+
}
|
|
30
|
+
type CipherstashOp = SqlMigrationPlanOperation<unknown>;
|
|
31
|
+
type OpStep = CipherstashOp['execute'][number];
|
|
32
|
+
/**
|
|
33
|
+
* Base class for cipherstash migration IR nodes.
|
|
34
|
+
*
|
|
35
|
+
* Each instance is *both* an `OpFactoryCall` (renderable to TypeScript,
|
|
36
|
+
* lowerable to a runtime op via `toOp()`) and a structurally-valid
|
|
37
|
+
* {@link CipherstashOp} — `id`, `label`, `operationClass`,
|
|
38
|
+
* `invariantId`, `target`, `precheck`, `execute`, `postcheck` are
|
|
39
|
+
* stored as enumerable own properties, populated in the concrete
|
|
40
|
+
* subclass constructors. So when the planner-rendered `migration.ts`
|
|
41
|
+
* runs and the user's `operations` getter returns Call instances
|
|
42
|
+
* directly, both `MigrationOpSchema` validation (which checks `id` /
|
|
43
|
+
* `label` / `operationClass`) and `JSON.stringify` (which writes
|
|
44
|
+
* `ops.json`) see the runtime op shape unchanged.
|
|
45
|
+
*
|
|
46
|
+
* The cipherstash-specific identity fields (`factoryName`, `table`,
|
|
47
|
+
* `column`, `index`, `castAs`) live on the subclass prototype as
|
|
48
|
+
* accessor getters and on a per-instance backing record kept in a
|
|
49
|
+
* private slot (`#args`). Accessor properties on the class are
|
|
50
|
+
* non-enumerable, and the backing record is a private field, so
|
|
51
|
+
* `Object.keys(call)` and `canonicalizeJson(...)` see only the op
|
|
52
|
+
* fields — `ops.json` and `migrationHash` stay byte-stable.
|
|
53
|
+
*/
|
|
54
|
+
declare abstract class CipherstashOpFactoryCallNode extends TsExpression implements OpFactoryCall {
|
|
55
|
+
abstract get factoryName(): string;
|
|
56
|
+
abstract readonly operationClass: MigrationOperationClass;
|
|
57
|
+
abstract readonly label: string;
|
|
58
|
+
abstract readonly id: string;
|
|
59
|
+
abstract readonly invariantId: string;
|
|
60
|
+
abstract readonly target: {
|
|
61
|
+
readonly id: string;
|
|
62
|
+
};
|
|
63
|
+
abstract readonly precheck: readonly OpStep[];
|
|
64
|
+
abstract readonly execute: readonly OpStep[];
|
|
65
|
+
abstract readonly postcheck: readonly OpStep[];
|
|
66
|
+
importRequirements(): readonly ImportRequirement[];
|
|
67
|
+
/**
|
|
68
|
+
* Re-expose the runtime op view for callers that prefer to lower
|
|
69
|
+
* Calls explicitly (notably {@link renderOps} on the postgres lane).
|
|
70
|
+
* The returned object is a plain copy of this Call's op-shaped
|
|
71
|
+
* fields.
|
|
72
|
+
*/
|
|
73
|
+
toOp(): CipherstashOp;
|
|
74
|
+
protected freeze(): void;
|
|
75
|
+
}
|
|
76
|
+
declare class CipherstashAddSearchConfigCall extends CipherstashOpFactoryCallNode {
|
|
77
|
+
#private;
|
|
78
|
+
readonly id: string;
|
|
79
|
+
readonly label: string;
|
|
80
|
+
readonly operationClass: 'additive';
|
|
81
|
+
readonly invariantId: string;
|
|
82
|
+
readonly target: {
|
|
83
|
+
readonly id: string;
|
|
84
|
+
};
|
|
85
|
+
readonly precheck: readonly OpStep[];
|
|
86
|
+
readonly execute: readonly OpStep[];
|
|
87
|
+
readonly postcheck: readonly OpStep[];
|
|
88
|
+
constructor(table: string, column: string, index: CipherstashSearchIndex, castAs?: string);
|
|
89
|
+
get factoryName(): 'cipherstashAddSearchConfig';
|
|
90
|
+
get table(): string;
|
|
91
|
+
get column(): string;
|
|
92
|
+
get index(): CipherstashSearchIndex;
|
|
93
|
+
get castAs(): string;
|
|
94
|
+
renderTypeScript(): string;
|
|
95
|
+
}
|
|
96
|
+
declare class CipherstashRemoveSearchConfigCall extends CipherstashOpFactoryCallNode {
|
|
97
|
+
#private;
|
|
98
|
+
readonly id: string;
|
|
99
|
+
readonly label: string;
|
|
100
|
+
readonly operationClass: 'destructive';
|
|
101
|
+
readonly invariantId: string;
|
|
102
|
+
readonly target: {
|
|
103
|
+
readonly id: string;
|
|
104
|
+
};
|
|
105
|
+
readonly precheck: readonly OpStep[];
|
|
106
|
+
readonly execute: readonly OpStep[];
|
|
107
|
+
readonly postcheck: readonly OpStep[];
|
|
108
|
+
constructor(table: string, column: string, index: CipherstashSearchIndex);
|
|
109
|
+
get factoryName(): 'cipherstashRemoveSearchConfig';
|
|
110
|
+
get table(): string;
|
|
111
|
+
get column(): string;
|
|
112
|
+
get index(): CipherstashSearchIndex;
|
|
113
|
+
renderTypeScript(): string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Public factory: register a cipherstash search-config row.
|
|
117
|
+
*
|
|
118
|
+
* Use from a hand-written migration when you need to wire EQL
|
|
119
|
+
* search-config alongside a `createTable` / `addColumn`. The
|
|
120
|
+
* `Encrypted<string>` codec hook calls this factory automatically when
|
|
121
|
+
* planning a contract diff that adds a `searchable: true` column.
|
|
122
|
+
*
|
|
123
|
+
* Returns the {@link CipherstashAddSearchConfigCall} IR node, which
|
|
124
|
+
* implements `OpFactoryCall` and is itself a `SqlMigrationPlanOperation`
|
|
125
|
+
* (its readonly op-shaped fields are populated in the constructor) — so
|
|
126
|
+
* the same value flows through both the renderer (planner-time IR) and
|
|
127
|
+
* the runtime ops list (`Migration.operations`) without an extra
|
|
128
|
+
* lowering step at the call site.
|
|
129
|
+
*/
|
|
130
|
+
declare function cipherstashAddSearchConfig(args: CipherstashSearchConfigArgs): CipherstashAddSearchConfigCall;
|
|
131
|
+
/**
|
|
132
|
+
* Public factory: invert {@link cipherstashAddSearchConfig} for the
|
|
133
|
+
* same (table, column, index) tuple.
|
|
134
|
+
*
|
|
135
|
+
* Returns the {@link CipherstashRemoveSearchConfigCall} IR node — see
|
|
136
|
+
* {@link cipherstashAddSearchConfig} for the rationale.
|
|
137
|
+
*/
|
|
138
|
+
declare function cipherstashRemoveSearchConfig(args: CipherstashSearchConfigArgs): CipherstashRemoveSearchConfigCall;
|
|
139
|
+
//#endregion
|
|
140
|
+
export { type CipherstashSearchConfigArgs, type CipherstashSearchIndex, cipherstashAddSearchConfig, cipherstashRemoveSearchConfig };
|
|
141
|
+
//# sourceMappingURL=migration.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.d.mts","names":[],"sources":["../src/migration/call-classes.ts"],"mappings":";;;;;;;;;;;;;KAmDY,sBAAA;;;;;;;;;;UAWK,2BAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,KAAA,EAAO,sBAAA;EAAA,SACP,MAAA;AAAA;AAAA,KAGN,aAAA,GAAgB,yBAAA;AAAA,KAChB,MAAA,GAAS,aAAA;;;;;;;;;;AA+Fd;;;;;;;;;;;;;uBApDe,4BAAA,SAAqC,YAAA,YAAwB,aAAA;EAAA,aAC7D,WAAA,CAAA;EAAA,kBACK,cAAA,EAAgB,uBAAA;EAAA,kBAChB,KAAA;EAAA,kBACA,EAAA;EAAA,kBACA,WAAA;EAAA,kBACA,MAAA;IAAA,SAAmB,EAAA;EAAA;EAAA,kBACnB,QAAA,WAAmB,MAAA;EAAA,kBACnB,OAAA,WAAkB,MAAA;EAAA,kBAClB,SAAA,WAAoB,MAAA;EAEtC,kBAAA,CAAA,YAA+B,iBAAA;EA0D7B;;;;;;EAhDF,IAAA,CAAA,GAAQ,aAAA;EAAA,UAaE,MAAA,CAAA;AAAA;AAAA,cAkBC,8BAAA,SAAuC,4BAAA;EAAA;WACzC,EAAA;EAAA,SACA,KAAA;EAAA,SACA,cAAA;EAAA,SACA,WAAA;EAAA,SACA,MAAA;IAAA,SAAmB,EAAA;EAAA;EAAA,SACnB,QAAA,WAAmB,MAAA;EAAA,SACnB,OAAA,WAAkB,MAAA;EAAA,SAClB,SAAA,WAAoB,MAAA;cAS3B,KAAA,UACA,MAAA,UACA,KAAA,EAAO,sBAAA,EACP,MAAA;EAAA,IAwBE,WAAA,CAAA;EAAA,IAIA,KAAA,CAAA;EAAA,IAIA,MAAA,CAAA;EAAA,IAIA,KAAA,CAAA,GAAS,sBAAA;EAAA,IAIT,MAAA,CAAA;EAIJ,gBAAA,CAAA;AAAA;AAAA,cA2BW,iCAAA,SAA0C,4BAAA;EAAA;WAC5C,EAAA;EAAA,SACA,KAAA;EAAA,SACA,cAAA;EAAA,SACA,WAAA;EAAA,SACA,MAAA;IAAA,SAAmB,EAAA;EAAA;EAAA,SACnB,QAAA,WAAmB,MAAA;EAAA,SACnB,OAAA,WAAkB,MAAA;EAAA,SAClB,SAAA,WAAoB,MAAA;cAIjB,KAAA,UAAe,MAAA,UAAgB,KAAA,EAAO,sBAAA;EAAA,IAmB9C,WAAA,CAAA;EAAA,IAIA,KAAA,CAAA;EAAA,IAIA,MAAA,CAAA;EAAA,IAIA,KAAA,CAAA,GAAS,sBAAA;EAIb,gBAAA,CAAA;AAAA;;;;;AAwBF;;;;;;;;;AAkBA;;iBAlBgB,0BAAA,CACd,IAAA,EAAM,2BAAA,GACL,8BAAA;;;;;;;;iBAgBa,6BAAA,CACd,IAAA,EAAM,2BAAA,GACL,iCAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CodecExpression, Expression } from "@prisma-next/sql-relational-core/expression";
|
|
2
|
+
import { SqlQueryOperationTypes } from "@prisma-next/sql-contract/types";
|
|
3
|
+
|
|
4
|
+
//#region src/types/operation-types.d.ts
|
|
5
|
+
type CodecTypesBase = Record<string, {
|
|
6
|
+
readonly input: unknown;
|
|
7
|
+
readonly output: unknown;
|
|
8
|
+
}>;
|
|
9
|
+
declare const CIPHERSTASH_STRING_CODEC = "cipherstash/string@1";
|
|
10
|
+
type CipherstashStringCodec = typeof CIPHERSTASH_STRING_CODEC;
|
|
11
|
+
/**
|
|
12
|
+
* Flat operation signatures consumed by the SQL query builder. Read
|
|
13
|
+
* via the `queryOperations` slot on the runtime context to project
|
|
14
|
+
* `t.email.cipherstashEq(...)` onto `cipherstash/string@1` column
|
|
15
|
+
* accessors inside `sql(t).where(...)` callbacks.
|
|
16
|
+
*
|
|
17
|
+
* Both operators take an encrypted-string `self` and a plaintext-or-
|
|
18
|
+
* envelope `other`/`pattern`; the runtime implementation
|
|
19
|
+
* (`eqlOperator` in `../execution/operators.ts`) wraps the user-supplied
|
|
20
|
+
* second argument in an `EncryptedString` envelope, stamps the
|
|
21
|
+
* column's routing context, and lowers to `eql_v2.eq` / `eql_v2.ilike`.
|
|
22
|
+
*
|
|
23
|
+
* Return type is the postgres `pg/bool@1` codec — that's the codec
|
|
24
|
+
* the framework's predicate machinery looks at via the `'boolean'`
|
|
25
|
+
* trait to decide a value is suitable for a WHERE clause.
|
|
26
|
+
*/
|
|
27
|
+
type QueryOperationTypes<CT extends CodecTypesBase> = SqlQueryOperationTypes<CT, {
|
|
28
|
+
readonly cipherstashEq: {
|
|
29
|
+
readonly self: {
|
|
30
|
+
readonly codecId: CipherstashStringCodec;
|
|
31
|
+
};
|
|
32
|
+
readonly impl: (self: CodecExpression<CipherstashStringCodec, boolean, CT>, other: CodecExpression<'pg/text@1', boolean, CT>) => Expression<{
|
|
33
|
+
codecId: 'pg/bool@1';
|
|
34
|
+
nullable: false;
|
|
35
|
+
}>;
|
|
36
|
+
};
|
|
37
|
+
readonly cipherstashIlike: {
|
|
38
|
+
readonly self: {
|
|
39
|
+
readonly codecId: CipherstashStringCodec;
|
|
40
|
+
};
|
|
41
|
+
readonly impl: (self: CodecExpression<CipherstashStringCodec, boolean, CT>, pattern: CodecExpression<'pg/text@1', boolean, CT>) => Expression<{
|
|
42
|
+
codecId: 'pg/bool@1';
|
|
43
|
+
nullable: false;
|
|
44
|
+
}>;
|
|
45
|
+
};
|
|
46
|
+
}>;
|
|
47
|
+
//#endregion
|
|
48
|
+
export { type QueryOperationTypes };
|
|
49
|
+
//# sourceMappingURL=operation-types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation-types.d.mts","names":[],"sources":["../src/types/operation-types.ts"],"mappings":";;;;KAyBK,cAAA,GAAiB,MAAA;EAAA,SAA0B,KAAA;EAAA,SAAyB,MAAA;AAAA;AAAA,cAEnE,wBAAA;AAAA,KACD,sBAAA,UAAgC,wBAAA;;;;;;;;;;;;;;;;;KAkBzB,mBAAA,YAA+B,cAAA,IAAkB,sBAAA,CAC3D,EAAA;EAAA,SAEW,aAAA;IAAA,SACE,IAAA;MAAA,SAAiB,OAAA,EAAS,sBAAA;IAAA;IAAA,SAC1B,IAAA,GACP,IAAA,EAAM,eAAA,CAAgB,sBAAA,WAAiC,EAAA,GAavD,KAAA,EAAO,eAAA,uBAAsC,EAAA,MAC1C,UAAA;MAAa,OAAA;MAAsB,QAAA;IAAA;EAAA;EAAA,SAEjC,gBAAA;IAAA,SACE,IAAA;MAAA,SAAiB,OAAA,EAAS,sBAAA;IAAA;IAAA,SAC1B,IAAA,GACP,IAAA,EAAM,eAAA,CAAgB,sBAAA,WAAiC,EAAA,GAKvD,OAAA,EAAS,eAAA,uBAAsC,EAAA,MAC5C,UAAA;MAAa,OAAA;MAAsB,QAAA;IAAA;EAAA;AAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/pack.d.mts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as _$_prisma_next_framework_components_codec0 from "@prisma-next/framework-components/codec";
|
|
2
|
+
import * as _$_prisma_next_contract_types0 from "@prisma-next/contract/types";
|
|
3
|
+
|
|
4
|
+
//#region src/extension-metadata/descriptor-meta.d.ts
|
|
5
|
+
declare const cipherstashPackMeta: {
|
|
6
|
+
readonly kind: "extension";
|
|
7
|
+
readonly id: "cipherstash";
|
|
8
|
+
readonly familyId: "sql";
|
|
9
|
+
readonly targetId: "postgres";
|
|
10
|
+
readonly version: "0.0.1";
|
|
11
|
+
readonly authoring: {
|
|
12
|
+
readonly type: {
|
|
13
|
+
readonly cipherstash: {
|
|
14
|
+
readonly EncryptedString: {
|
|
15
|
+
readonly kind: "typeConstructor";
|
|
16
|
+
readonly args: readonly [{
|
|
17
|
+
readonly kind: "object";
|
|
18
|
+
readonly name: "options";
|
|
19
|
+
readonly optional: true;
|
|
20
|
+
readonly properties: {
|
|
21
|
+
readonly equality: {
|
|
22
|
+
readonly kind: "boolean";
|
|
23
|
+
readonly optional: true;
|
|
24
|
+
};
|
|
25
|
+
readonly freeTextSearch: {
|
|
26
|
+
readonly kind: "boolean";
|
|
27
|
+
readonly optional: true;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
}];
|
|
31
|
+
readonly output: {
|
|
32
|
+
readonly codecId: "cipherstash/string@1";
|
|
33
|
+
readonly nativeType: "eql_v2_encrypted";
|
|
34
|
+
readonly typeParams: {
|
|
35
|
+
readonly equality: {
|
|
36
|
+
readonly kind: "arg";
|
|
37
|
+
readonly index: 0;
|
|
38
|
+
readonly path: readonly ["equality"];
|
|
39
|
+
readonly default: true;
|
|
40
|
+
};
|
|
41
|
+
readonly freeTextSearch: {
|
|
42
|
+
readonly kind: "arg";
|
|
43
|
+
readonly index: 0;
|
|
44
|
+
readonly path: readonly ["freeTextSearch"];
|
|
45
|
+
readonly default: true;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
readonly types: {
|
|
54
|
+
readonly codecTypes: {
|
|
55
|
+
readonly codecInstances: readonly [{
|
|
56
|
+
encode(): Promise<unknown>;
|
|
57
|
+
decode(): Promise<unknown>;
|
|
58
|
+
encodeJson(): _$_prisma_next_contract_types0.JsonValue;
|
|
59
|
+
decodeJson(): unknown;
|
|
60
|
+
readonly descriptor: _$_prisma_next_framework_components_codec0.CodecDescriptor<any>;
|
|
61
|
+
get id(): "cipherstash/string@1";
|
|
62
|
+
}];
|
|
63
|
+
readonly typeImports: readonly [{
|
|
64
|
+
readonly package: "@prisma-next/extension-cipherstash/runtime";
|
|
65
|
+
readonly named: "EncryptedString";
|
|
66
|
+
readonly alias: "EncryptedString";
|
|
67
|
+
}];
|
|
68
|
+
};
|
|
69
|
+
readonly queryOperationTypes: {
|
|
70
|
+
readonly import: {
|
|
71
|
+
readonly package: "@prisma-next/extension-cipherstash/operation-types";
|
|
72
|
+
readonly named: "QueryOperationTypes";
|
|
73
|
+
readonly alias: "CipherstashQueryOperationTypes";
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
readonly storage: readonly [{
|
|
77
|
+
readonly typeId: "cipherstash/string@1";
|
|
78
|
+
readonly familyId: "sql";
|
|
79
|
+
readonly targetId: "postgres";
|
|
80
|
+
readonly nativeType: "eql_v2_encrypted";
|
|
81
|
+
}];
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
//#endregion
|
|
85
|
+
export { cipherstashPackMeta as default };
|
|
86
|
+
//# sourceMappingURL=pack.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack.d.mts","names":[],"sources":["../src/extension-metadata/descriptor-meta.ts"],"mappings":";;;;cAkCa,mBAAA;EAAA"}
|
package/dist/pack.mjs
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { n as CIPHERSTASH_STRING_CODEC_ID, t as CIPHERSTASH_EXTENSION_VERSION } from "./constants-BDxL9Pe3.mjs";
|
|
2
|
+
import { a as CipherstashSingleDecryptArgs, i as CipherstashSdk, n as CipherstashBulkEncryptArgs, r as CipherstashRoutingKey, t as CipherstashBulkDecryptArgs } from "./sdk-D5FTGyzp.mjs";
|
|
3
|
+
import { AnyCodecDescriptor, CodecImpl } from "@prisma-next/framework-components/codec";
|
|
4
|
+
import { Codec, SqlCodecCallContext } from "@prisma-next/sql-relational-core/ast";
|
|
5
|
+
import { RuntimeParameterizedCodecDescriptor, SqlRuntimeExtensionDescriptor } from "@prisma-next/sql-runtime";
|
|
6
|
+
import { JsonValue } from "@prisma-next/contract/types";
|
|
7
|
+
import * as _$arktype_internal_variants_object_ts0 from "arktype/internal/variants/object.ts";
|
|
8
|
+
|
|
9
|
+
//#region src/execution/envelope.d.ts
|
|
10
|
+
/**
|
|
11
|
+
* The mutable state of an `EncryptedString` — exposed by `expose()` for
|
|
12
|
+
* callers that explicitly opt in. Mutating these slots from outside the
|
|
13
|
+
* package is supported (we don't stop you) but unusual; the framework's
|
|
14
|
+
* own lifecycle mutators (`setHandleCiphertext`, `setHandleRoutingKey`,
|
|
15
|
+
* etc.) are the conventional path.
|
|
16
|
+
*/
|
|
17
|
+
interface EncryptedStringHandle {
|
|
18
|
+
plaintext: string | undefined;
|
|
19
|
+
ciphertext: unknown;
|
|
20
|
+
table: string | undefined;
|
|
21
|
+
column: string | undefined;
|
|
22
|
+
sdk: CipherstashSdk | undefined;
|
|
23
|
+
}
|
|
24
|
+
interface EncryptedStringFromInternalArgs {
|
|
25
|
+
readonly ciphertext: unknown;
|
|
26
|
+
readonly table: string;
|
|
27
|
+
readonly column: string;
|
|
28
|
+
readonly sdk: CipherstashSdk;
|
|
29
|
+
}
|
|
30
|
+
declare class EncryptedString {
|
|
31
|
+
#private;
|
|
32
|
+
private constructor();
|
|
33
|
+
/**
|
|
34
|
+
* Construct a write-side envelope from plaintext. Bulk-encrypt
|
|
35
|
+
* middleware populates the handle's ciphertext slot before the codec
|
|
36
|
+
* encodes the envelope to wire format.
|
|
37
|
+
*/
|
|
38
|
+
static from(plaintext: string): EncryptedString;
|
|
39
|
+
/**
|
|
40
|
+
* Construct a read-side envelope from a wire ciphertext + the column
|
|
41
|
+
* identity + the SDK used to decrypt the cell. Called from the codec
|
|
42
|
+
* `decode` body.
|
|
43
|
+
*/
|
|
44
|
+
static fromInternal(args: EncryptedStringFromInternalArgs): EncryptedString;
|
|
45
|
+
/**
|
|
46
|
+
* Explicitly retrieve the wrapped handle. Modelled on Rust `secrecy`'s
|
|
47
|
+
* `SecretBox<T>::expose_secret`: the handle is reachable, but you have
|
|
48
|
+
* to ask for it by name. Callers reach for `expose()` when they need
|
|
49
|
+
* to inspect or transport the ciphertext envelope, debug lifecycle
|
|
50
|
+
* state, or wire ad-hoc tooling around the SDK reference.
|
|
51
|
+
*
|
|
52
|
+
* Mutating the returned handle is supported but unusual — the
|
|
53
|
+
* framework's lifecycle mutators (`setHandleCiphertext`,
|
|
54
|
+
* `setHandleRoutingKey`, etc.) are the conventional path during
|
|
55
|
+
* encrypt / decrypt flow.
|
|
56
|
+
*/
|
|
57
|
+
expose(): EncryptedStringHandle;
|
|
58
|
+
/**
|
|
59
|
+
* Decrypt and return the plaintext.
|
|
60
|
+
*
|
|
61
|
+
* - If the handle's `plaintext` slot is already populated (write-side
|
|
62
|
+
* envelopes from `from(plaintext)`, or read-side envelopes already
|
|
63
|
+
* materialized by `decryptAll(...)` or a prior `decrypt()`), returns
|
|
64
|
+
* the cached plaintext synchronously without consulting the SDK.
|
|
65
|
+
* - Otherwise (read-side handle without a cached plaintext), invokes
|
|
66
|
+
* the SDK's single-cell `decrypt` with the handle's routing context.
|
|
67
|
+
* The caller-supplied `signal` is forwarded to the SDK by identity
|
|
68
|
+
* per the umbrella cancellation contract; the SDK promise is also
|
|
69
|
+
* raced against the signal so an abort surfaces a `RUNTIME.ABORTED
|
|
70
|
+
* { phase: 'decrypt' }` envelope promptly even if the SDK body
|
|
71
|
+
* ignores the signal. The cached-plaintext fast path returns
|
|
72
|
+
* synchronously without consulting the signal — no IO, no abort
|
|
73
|
+
* observation point.
|
|
74
|
+
*/
|
|
75
|
+
decrypt(opts?: {
|
|
76
|
+
signal?: AbortSignal;
|
|
77
|
+
}): Promise<string>;
|
|
78
|
+
toJSON(): string;
|
|
79
|
+
toString(): string;
|
|
80
|
+
valueOf(): string;
|
|
81
|
+
[Symbol.toPrimitive](): string;
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/execution/codec-runtime.d.ts
|
|
85
|
+
declare const CIPHERSTASH_STRING_TRAITS: readonly [];
|
|
86
|
+
declare class CipherstashStringCodec extends CodecImpl<typeof CIPHERSTASH_STRING_CODEC_ID, typeof CIPHERSTASH_STRING_TRAITS, unknown, EncryptedString> implements Codec<typeof CIPHERSTASH_STRING_CODEC_ID, typeof CIPHERSTASH_STRING_TRAITS, unknown, EncryptedString> {
|
|
87
|
+
readonly sdk: CipherstashSdk | undefined;
|
|
88
|
+
constructor(descriptor: AnyCodecDescriptor, sdk: CipherstashSdk | undefined);
|
|
89
|
+
encode(value: EncryptedString, _ctx: SqlCodecCallContext): Promise<unknown>;
|
|
90
|
+
decode(wire: unknown, ctx: SqlCodecCallContext): Promise<EncryptedString>;
|
|
91
|
+
encodeJson(_value: EncryptedString): JsonValue;
|
|
92
|
+
decodeJson(_json: JsonValue): EncryptedString;
|
|
93
|
+
}
|
|
94
|
+
declare function createCipherstashStringCodec(sdk: CipherstashSdk): CipherstashStringCodec;
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/execution/decrypt-all.d.ts
|
|
97
|
+
/**
|
|
98
|
+
* `decryptAll` — read-side bulk-decrypt walker.
|
|
99
|
+
*
|
|
100
|
+
* Public utility users invoke after `findMany` (or any other read
|
|
101
|
+
* surface) to materialize the plaintext for every `EncryptedString`
|
|
102
|
+
* envelope reachable from the result set in a fixed number of bulk SDK
|
|
103
|
+
* round-trips:
|
|
104
|
+
*
|
|
105
|
+
* const rows = await db.select(...).from(User).execute();
|
|
106
|
+
* await decryptAll(rows);
|
|
107
|
+
* // every envelope's `decrypt()` now returns plaintext synchronously.
|
|
108
|
+
*
|
|
109
|
+
* Why a separate utility (rather than middleware that auto-decrypts on
|
|
110
|
+
* every read): the framework`s streaming-read path cannot bulk-amortize
|
|
111
|
+
* decryption across rows it`s yielding incrementally — by the time row
|
|
112
|
+
* N is yielded, rows 1..N-1 have already been delivered to the caller.
|
|
113
|
+
* The `decryptAll` shape lets the caller buffer the result set
|
|
114
|
+
* explicitly (with `await stream.toArray()`) and then opt into bulk
|
|
115
|
+
* decryption in one round-trip per `(table, column)` group. The runtime
|
|
116
|
+
* descriptor wrapper deliberately does NOT register an implicit-decrypt
|
|
117
|
+
* middleware for this reason.
|
|
118
|
+
*
|
|
119
|
+
* **Walker shape**.
|
|
120
|
+
*
|
|
121
|
+
* - Recursive on plain objects + plain arrays only. Date / Map / Set /
|
|
122
|
+
* typed arrays / Buffer / function / etc. are not recursed into:
|
|
123
|
+
* cipherstash envelopes are user data and would not normally embed
|
|
124
|
+
* inside these host containers; if a future caller needs to bulk-
|
|
125
|
+
* decrypt envelopes inside such a container they extract them into a
|
|
126
|
+
* plain row first. The narrow scope keeps the walker`s behavior
|
|
127
|
+
* trivially predictable and avoids the cycle / iterator / lazy-eval
|
|
128
|
+
* surface those exotic types bring.
|
|
129
|
+
* - Cycle-safe via a `WeakSet` of visited objects/arrays; the same
|
|
130
|
+
* envelope appearing in N positions is collected once.
|
|
131
|
+
* - Skips envelopes whose plaintext slot is already populated
|
|
132
|
+
* (write-side envelopes from `EncryptedString.from(plaintext)`, or
|
|
133
|
+
* read-side envelopes already materialized by a prior
|
|
134
|
+
* `decrypt()` / `decryptAll(...)`). The skip means a re-run is a
|
|
135
|
+
* no-op and a mixed write/read row tree only round-trips for the
|
|
136
|
+
* envelopes that need it.
|
|
137
|
+
*
|
|
138
|
+
* **Grouping**. Envelopes are grouped by `(sdk, table, column)` —
|
|
139
|
+
* routing key plus the envelope handle`s SDK reference. The SDK split
|
|
140
|
+
* preserves the per-tenant SDK isolation `runtime.ts`'s docblock spells
|
|
141
|
+
* out: each tenant constructs its own runtime descriptor with its own
|
|
142
|
+
* SDK so per-tenant key material never crosses runtimes. Envelopes from
|
|
143
|
+
* different tenants happening to share `(table, column)` therefore
|
|
144
|
+
* still receive separate `bulkDecrypt` calls.
|
|
145
|
+
*
|
|
146
|
+
* **Cancellation**. `opts.signal` is forwarded by identity to every
|
|
147
|
+
* `bulkDecrypt` call via `ifDefined` — the same shape the bulk-encrypt
|
|
148
|
+
* middleware and `EncryptedString.decrypt({ signal? })` use. The
|
|
149
|
+
* walker also races each SDK promise against `opts.signal` via
|
|
150
|
+
* `raceCipherstashAbort` so an abort surfaces `RUNTIME.ABORTED
|
|
151
|
+
* { phase: 'decrypt-all' }` promptly even when the SDK body itself
|
|
152
|
+
* ignores the signal. A pre-check before the first SDK round-trip
|
|
153
|
+
* short-circuits when the signal is already aborted at entry; the
|
|
154
|
+
* no-envelopes-reachable fast path returns immediately without
|
|
155
|
+
* observing the signal.
|
|
156
|
+
*/
|
|
157
|
+
interface DecryptAllOptions {
|
|
158
|
+
readonly signal?: AbortSignal;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Walk a result set and bulk-decrypt every `EncryptedString` envelope
|
|
162
|
+
* reachable from it. After the returned promise resolves, every touched
|
|
163
|
+
* envelope's `decrypt()` returns the cached plaintext synchronously
|
|
164
|
+
* without consulting the SDK.
|
|
165
|
+
*
|
|
166
|
+
* The walker is a no-op when no envelopes are reachable (returns
|
|
167
|
+
* without making any SDK call), so it is cheap to call defensively
|
|
168
|
+
* after queries that may or may not contain encrypted columns.
|
|
169
|
+
*/
|
|
170
|
+
declare function decryptAll(rows: unknown, opts?: DecryptAllOptions): Promise<void>;
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region src/execution/parameterized.d.ts
|
|
173
|
+
interface CipherstashStringParams {
|
|
174
|
+
readonly equality: boolean;
|
|
175
|
+
readonly freeTextSearch: boolean;
|
|
176
|
+
}
|
|
177
|
+
declare const encryptedStringParamsSchema: _$arktype_internal_variants_object_ts0.ObjectType<{
|
|
178
|
+
equality: boolean;
|
|
179
|
+
freeTextSearch: boolean;
|
|
180
|
+
}, {}>;
|
|
181
|
+
declare function renderEncryptedStringOutputType(_params: CipherstashStringParams): string;
|
|
182
|
+
declare function createParameterizedCodecDescriptors(sdk: CipherstashSdk): ReadonlyArray<RuntimeParameterizedCodecDescriptor<CipherstashStringParams>>;
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/exports/runtime.d.ts
|
|
185
|
+
interface CreateCipherstashRuntimeDescriptorOptions {
|
|
186
|
+
readonly sdk: CipherstashSdk;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Compose the SDK-bound codec runtime + parameterized codec descriptors
|
|
190
|
+
* + runtime-plane codec-instances metadata into a single
|
|
191
|
+
* `SqlRuntimeExtensionDescriptor<'postgres'>`.
|
|
192
|
+
*
|
|
193
|
+
* The descriptor is per-SDK: cipherstash's codec captures the SDK at
|
|
194
|
+
* `decode` time (read-side single-cell `decrypt`) and the bulk-encrypt
|
|
195
|
+
* middleware captures it at `beforeExecute` time (write-side bulk
|
|
196
|
+
* round-trip). Multi-tenant deployments construct one descriptor per
|
|
197
|
+
* tenant SDK so per-tenant key material never crosses runtimes.
|
|
198
|
+
*
|
|
199
|
+
* Mirrors `packages/3-extensions/pgvector/src/exports/runtime.ts` —
|
|
200
|
+
* pgvector's vectorRuntimeDescriptor is a static default-export because
|
|
201
|
+
* its codec is fully stateless; cipherstash needs the factory wrapper
|
|
202
|
+
* because the codec depends on `sdk`.
|
|
203
|
+
*/
|
|
204
|
+
declare function createCipherstashRuntimeDescriptor(opts: CreateCipherstashRuntimeDescriptorOptions): SqlRuntimeExtensionDescriptor<'postgres'>;
|
|
205
|
+
//#endregion
|
|
206
|
+
export { CIPHERSTASH_EXTENSION_VERSION, CIPHERSTASH_STRING_CODEC_ID, type CipherstashBulkDecryptArgs, type CipherstashBulkEncryptArgs, type CipherstashRoutingKey, type CipherstashSdk, type CipherstashSingleDecryptArgs, type CipherstashStringCodec, type CipherstashStringParams, CreateCipherstashRuntimeDescriptorOptions, type DecryptAllOptions, EncryptedString, type EncryptedStringFromInternalArgs, type EncryptedStringHandle, createCipherstashRuntimeDescriptor, createCipherstashStringCodec, createParameterizedCodecDescriptors, decryptAll, encryptedStringParamsSchema, renderEncryptedStringOutputType };
|
|
207
|
+
//# sourceMappingURL=runtime.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/execution/envelope.ts","../src/execution/codec-runtime.ts","../src/execution/decrypt-all.ts","../src/execution/parameterized.ts","../src/exports/runtime.ts"],"mappings":";;;;;;;;;;;;;;;;UA8DiB,qBAAA;EACf,SAAA;EACA,UAAA;EACA,KAAA;EACA,MAAA;EACA,GAAA,EAAK,cAAA;AAAA;AAAA,UAKU,+BAAA;EAAA,SACN,UAAA;EAAA,SACA,KAAA;EAAA,SACA,MAAA;EAAA,SACA,GAAA,EAAK,cAAA;AAAA;AAAA,cAGH,eAAA;EAAA;UAGJ,WAAA,CAAA;ECtBoC;AAkD7C;;;;EAlD6C,OD+BpC,IAAA,CAAK,SAAA,WAAoB,eAAA;ECwB9B;;;;;EAAA,ODTK,YAAA,CAAa,IAAA,EAAM,+BAAA,GAAkC,eAAA;ECqBX;;;;;;;;;;;;EDCjD,MAAA,CAAA,GAAU,qBAAA;ECVH;;;;;;;;;;;;;;;;;ED+BD,OAAA,CAAQ,IAAA;IAAS,MAAA,GAAS,WAAA;EAAA,IAAgB,OAAA;EA6BhD,MAAA,CAAA;EAIA,QAAA,CAAA;EAIA,OAAA,CAAA;EAAA,CAIC,MAAA,CAAO,WAAA;AAAA;;;cClIJ,yBAAA;AAAA,cAkDO,sBAAA,SACH,SAAA,QACC,2BAAA,SACA,yBAAA,WAEP,eAAA,aAGA,KAAA,QACS,2BAAA,SACA,yBAAA,WAEP,eAAA;EAAA,SAGK,GAAA,EAAK,cAAA;cAEF,UAAA,EAAY,kBAAA,EAAoB,GAAA,EAAK,cAAA;EAK3C,MAAA,CAAO,KAAA,EAAO,eAAA,EAAiB,IAAA,EAAM,mBAAA,GAAsB,OAAA;EAW3D,MAAA,CAAO,IAAA,WAAe,GAAA,EAAK,mBAAA,GAAsB,OAAA,CAAQ,eAAA;EAsB/D,UAAA,CAAW,MAAA,EAAQ,eAAA,GAAkB,SAAA;EAIrC,UAAA,CAAW,KAAA,EAAO,SAAA,GAAY,eAAA;AAAA;AAAA,iBAmChB,4BAAA,CAA6B,GAAA,EAAK,cAAA,GAAiB,sBAAA;;;;;;;;;;;;AD9InE;;;;;;;;;;;;AAUA;;;;;;;;;;;AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;UEbiB,iBAAA;EAAA,SACN,MAAA,GAAS,WAAA;AAAA;;;;;;;;AD7BwB;;;iBCiDtB,UAAA,CAAW,IAAA,WAAe,IAAA,GAAO,iBAAA,GAAoB,OAAA;;;UCzD1D,uBAAA;EAAA,SACN,QAAA;EAAA,SACA,cAAA;AAAA;AAAA,cAGE,2BAAA,EAGX,sCAAA,CAHsC,UAAA;;;;iBAKxB,+BAAA,CAAgC,OAAA,EAAS,uBAAA;AAAA,iBAIzC,mCAAA,CACd,GAAA,EAAK,cAAA,GACJ,aAAA,CAAc,mCAAA,CAAoC,uBAAA;;;UCiBpC,yCAAA;EAAA,SACN,GAAA,EAAK,cAAA;AAAA;;;;;;;;;;;;;;;;;iBAmBA,kCAAA,CACd,IAAA,EAAM,yCAAA,GACL,6BAAA"}
|