@clef-sh/core 0.1.27 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/dist/artifact/packer.d.ts +4 -3
- package/dist/artifact/packer.d.ts.map +1 -1
- package/dist/artifact/resolve.d.ts +3 -2
- package/dist/artifact/resolve.d.ts.map +1 -1
- package/dist/compliance/run.d.ts.map +1 -1
- package/dist/diff/engine.d.ts +18 -8
- package/dist/diff/engine.d.ts.map +1 -1
- package/dist/import/index.d.ts +5 -5
- package/dist/import/index.d.ts.map +1 -1
- package/dist/index.d.mts +14 -12
- package/dist/index.d.ts +14 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1225 -872
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +1213 -848
- package/dist/index.mjs.map +4 -4
- package/dist/kms/aws-arn.d.ts +29 -0
- package/dist/kms/aws-arn.d.ts.map +1 -0
- package/dist/kms/index.d.ts +2 -0
- package/dist/kms/index.d.ts.map +1 -1
- package/dist/lint/runner.d.ts +7 -7
- package/dist/lint/runner.d.ts.map +1 -1
- package/dist/manifest/io.d.ts +6 -0
- package/dist/manifest/io.d.ts.map +1 -1
- package/dist/manifest/parser.d.ts.map +1 -1
- package/dist/matrix/manager.d.ts +4 -16
- package/dist/matrix/manager.d.ts.map +1 -1
- package/dist/merge/driver.d.ts +2 -2
- package/dist/merge/driver.d.ts.map +1 -1
- package/dist/merge/metadata-driver.d.ts +5 -4
- package/dist/merge/metadata-driver.d.ts.map +1 -1
- package/dist/migration/backend.d.ts +10 -7
- package/dist/migration/backend.d.ts.map +1 -1
- package/dist/pack/backends/json-envelope.d.ts.map +1 -1
- package/dist/pack/types.d.ts +9 -3
- package/dist/pack/types.d.ts.map +1 -1
- package/dist/pending/metadata.d.ts +1 -3
- package/dist/pending/metadata.d.ts.map +1 -1
- package/dist/recipients/index.d.ts +4 -3
- package/dist/recipients/index.d.ts.map +1 -1
- package/dist/report/generator.d.ts +4 -3
- package/dist/report/generator.d.ts.map +1 -1
- package/dist/reset/manager.d.ts +21 -3
- package/dist/reset/manager.d.ts.map +1 -1
- package/dist/service-identity/manager.d.ts +6 -3
- package/dist/service-identity/manager.d.ts.map +1 -1
- package/dist/sops/client.d.ts +80 -55
- package/dist/sops/client.d.ts.map +1 -1
- package/dist/sops/linux-stdin-fifo.d.ts +31 -0
- package/dist/sops/linux-stdin-fifo.d.ts.map +1 -0
- package/dist/source/compose.d.ts +10 -0
- package/dist/source/compose.d.ts.map +1 -0
- package/dist/source/default-bulk.d.ts +12 -0
- package/dist/source/default-bulk.d.ts.map +1 -0
- package/dist/source/encryption-backend.d.ts +85 -0
- package/dist/source/encryption-backend.d.ts.map +1 -0
- package/dist/source/errors.d.ts +19 -0
- package/dist/source/errors.d.ts.map +1 -0
- package/dist/source/filesystem-storage-backend.d.ts +26 -0
- package/dist/source/filesystem-storage-backend.d.ts.map +1 -0
- package/dist/source/guards.d.ts +14 -0
- package/dist/source/guards.d.ts.map +1 -0
- package/dist/source/index.d.ts +10 -0
- package/dist/source/index.d.ts.map +1 -0
- package/dist/source/mock-source.d.ts +89 -0
- package/dist/source/mock-source.d.ts.map +1 -0
- package/dist/source/storage-backend.d.ts +61 -0
- package/dist/source/storage-backend.d.ts.map +1 -0
- package/dist/source/types.d.ts +212 -0
- package/dist/source/types.d.ts.map +1 -0
- package/dist/structure/manager.d.ts +17 -3
- package/dist/structure/manager.d.ts.map +1 -1
- package/dist/sync/manager.d.ts +7 -6
- package/dist/sync/manager.d.ts.map +1 -1
- package/dist/types/index.d.ts +10 -23
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/bulk/ops.d.ts +0 -57
- package/dist/bulk/ops.d.ts.map +0 -1
package/dist/sops/client.d.ts
CHANGED
|
@@ -1,18 +1,39 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DecryptedFile, MergeDecrypter, SopsMetadata, SubprocessRunner } from "../types";
|
|
2
|
+
import type { EncryptionBackend, EncryptionContext, RotateOptions } from "../source/encryption-backend";
|
|
2
3
|
/**
|
|
3
|
-
* Wraps the `sops` binary for encryption, decryption,
|
|
4
|
-
* All
|
|
4
|
+
* Wraps the `sops` binary for encryption, decryption, rotation, and metadata
|
|
5
|
+
* extraction. All blob operations are piped via stdin/stdout — plaintext
|
|
6
|
+
* never touches disk.
|
|
7
|
+
*
|
|
8
|
+
* `SopsClient` implements {@link EncryptionBackend} directly — pass it
|
|
9
|
+
* straight to `composeSecretSource(storage, client, manifest)` without
|
|
10
|
+
* any adapter. The legacy file-path methods (`encrypt(filePath, ...)`,
|
|
11
|
+
* `addRecipient`, `removeRecipient`, `reEncrypt`,
|
|
12
|
+
* `validateEncryption(filePath)`, `getMetadata(filePath)`) were removed
|
|
13
|
+
* in Phase 7. The only remaining file-path entry point is
|
|
14
|
+
* {@link decryptFile}, kept for the merge driver which receives temp
|
|
15
|
+
* file paths from git — the contract for that surface is
|
|
16
|
+
* {@link MergeDecrypter}.
|
|
5
17
|
*
|
|
6
18
|
* @example
|
|
7
19
|
* ```ts
|
|
8
20
|
* const client = new SopsClient(runner, "/home/user/.age/key.txt");
|
|
9
|
-
* const
|
|
21
|
+
* const source = composeSecretSource(
|
|
22
|
+
* new FilesystemStorageBackend(manifest, repoRoot),
|
|
23
|
+
* client,
|
|
24
|
+
* manifest,
|
|
25
|
+
* );
|
|
26
|
+
* const cell = await source.readCell({ namespace: "db", environment: "prod" });
|
|
10
27
|
* ```
|
|
11
28
|
*/
|
|
12
|
-
export declare class SopsClient implements EncryptionBackend {
|
|
29
|
+
export declare class SopsClient implements EncryptionBackend, MergeDecrypter {
|
|
13
30
|
private readonly runner;
|
|
14
31
|
private readonly ageKeyFile?;
|
|
15
32
|
private readonly ageKey?;
|
|
33
|
+
/** {@link EncryptionBackend} identifier. */
|
|
34
|
+
readonly id = "sops";
|
|
35
|
+
/** {@link EncryptionBackend} short description (used by `clef doctor`). */
|
|
36
|
+
readonly description = "SOPS-based encryption via the bundled `sops` binary";
|
|
16
37
|
private readonly sopsCommand;
|
|
17
38
|
private readonly keyserviceArgs;
|
|
18
39
|
/**
|
|
@@ -36,77 +57,81 @@ export declare class SopsClient implements EncryptionBackend {
|
|
|
36
57
|
constructor(runner: SubprocessRunner, ageKeyFile?: string | undefined, ageKey?: string | undefined, sopsPath?: string, keyserviceAddr?: string);
|
|
37
58
|
private buildSopsEnv;
|
|
38
59
|
/**
|
|
39
|
-
* Decrypt a SOPS-encrypted file
|
|
60
|
+
* Decrypt a SOPS-encrypted file by path. The only remaining file-path
|
|
61
|
+
* entry point on this class — kept for the merge driver, which
|
|
62
|
+
* receives temp filesystem paths from git that don't map onto a
|
|
63
|
+
* `CellRef`. Production `SecretSource` consumers should call
|
|
64
|
+
* `source.readCell` instead.
|
|
40
65
|
*
|
|
41
66
|
* @param filePath - Path to the `.enc.yaml` or `.enc.json` file.
|
|
42
67
|
* @returns {@link DecryptedFile} with plaintext values in memory only.
|
|
43
68
|
* @throws {@link SopsKeyNotFoundError} If no matching decryption key is available.
|
|
44
69
|
* @throws {@link SopsDecryptionError} On any other decryption failure.
|
|
45
70
|
*/
|
|
46
|
-
|
|
71
|
+
decryptFile(filePath: string): Promise<DecryptedFile>;
|
|
47
72
|
/**
|
|
48
|
-
*
|
|
73
|
+
* Determine whether a decrypt failure is caused by a missing/mismatched key (vs. some other
|
|
74
|
+
* SOPS error) without relying on stderr message text.
|
|
49
75
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* @param environment - Optional environment name. When provided, per-env backend overrides
|
|
54
|
-
* are resolved from the manifest. When omitted, the global `sops.default_backend` is used.
|
|
55
|
-
* @throws {@link SopsEncryptionError} On encryption or write failure.
|
|
76
|
+
* For age backends: reads the file's recipient list and checks whether any of the configured
|
|
77
|
+
* private keys derive to a matching public key. For non-age backends (pgp, kms) we cannot
|
|
78
|
+
* perform an equivalent check, so those always return "other".
|
|
56
79
|
*/
|
|
57
|
-
|
|
80
|
+
private classifyDecryptError;
|
|
81
|
+
private parseMetadataFromFile;
|
|
58
82
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
83
|
+
* Parse SOPS metadata from a string (no IO). Used by both
|
|
84
|
+
* `parseMetadataFromFile` (after reading from disk) and the blob-shaped
|
|
85
|
+
* `getMetadataFromBlob` (which receives ciphertext directly from a
|
|
86
|
+
* BlobStore). The `label` is woven into error messages so callers can
|
|
87
|
+
* include the file path or cell ref the content came from.
|
|
64
88
|
*/
|
|
65
|
-
|
|
89
|
+
private parseMetadataFromContent;
|
|
90
|
+
private detectBackend;
|
|
91
|
+
private extractRecipients;
|
|
92
|
+
private buildEncryptArgs;
|
|
66
93
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* @param key - age public key to add as a recipient.
|
|
71
|
-
* @throws {@link SopsEncryptionError} On failure.
|
|
94
|
+
* {@link EncryptionBackend.decrypt} — decrypt SOPS-encrypted bytes (e.g.
|
|
95
|
+
* read from a `StorageBackend`) and return plaintext values + metadata.
|
|
96
|
+
* Plaintext lives only in memory.
|
|
72
97
|
*/
|
|
73
|
-
|
|
98
|
+
decrypt(blob: string, ctx: EncryptionContext): Promise<DecryptedFile>;
|
|
74
99
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* @throws {@link SopsEncryptionError} On failure.
|
|
100
|
+
* {@link EncryptionBackend.encrypt} — encrypt plaintext values into a
|
|
101
|
+
* SOPS-formatted ciphertext blob. Returns the bytes as a string;
|
|
102
|
+
* caller (typically a `StorageBackend`) decides where to put them.
|
|
103
|
+
* Plaintext is piped via stdin only.
|
|
80
104
|
*/
|
|
81
|
-
|
|
105
|
+
encrypt(values: Record<string, string>, ctx: EncryptionContext): Promise<string>;
|
|
82
106
|
/**
|
|
83
|
-
*
|
|
107
|
+
* {@link EncryptionBackend.rotate} — add or remove recipients from an
|
|
108
|
+
* encrypted SOPS blob via stdin/stdout. Drops the in-place `-i` flag
|
|
109
|
+
* the deleted file-path-shaped methods used, so SOPS writes the
|
|
110
|
+
* rotated ciphertext to stdout instead of back to a file. Plaintext
|
|
111
|
+
* stays inside the SOPS subprocess; no plaintext window exists in
|
|
112
|
+
* this Node process.
|
|
84
113
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
114
|
+
* Single SOPS invocation can both add and remove recipients
|
|
115
|
+
* simultaneously (matches the CLI flag set).
|
|
87
116
|
*/
|
|
88
|
-
|
|
117
|
+
rotate(blob: string, opts: RotateOptions, ctx: EncryptionContext): Promise<string>;
|
|
89
118
|
/**
|
|
90
|
-
*
|
|
91
|
-
* without decrypting
|
|
92
|
-
*
|
|
93
|
-
* @param filePath - Path to the encrypted file.
|
|
94
|
-
* @returns {@link SopsMetadata} parsed from the file's `sops:` block.
|
|
95
|
-
* @throws {@link SopsDecryptionError} If the file cannot be read or parsed.
|
|
119
|
+
* {@link EncryptionBackend.getMetadata} — extract SOPS metadata from a
|
|
120
|
+
* ciphertext blob without decrypting. Pure parser, no IO, no
|
|
121
|
+
* subprocess.
|
|
96
122
|
*/
|
|
97
|
-
getMetadata(
|
|
123
|
+
getMetadata(content: string): SopsMetadata;
|
|
98
124
|
/**
|
|
99
|
-
*
|
|
100
|
-
* SOPS
|
|
101
|
-
*
|
|
102
|
-
* For age backends: reads the file's recipient list and checks whether any of the configured
|
|
103
|
-
* private keys derive to a matching public key. For non-age backends (pgp, kms) we cannot
|
|
104
|
-
* perform an equivalent check, so those always return "other".
|
|
125
|
+
* {@link EncryptionBackend.validateEncryption} — whether `content` is a
|
|
126
|
+
* valid SOPS-encrypted blob (parses + has the `sops:` metadata
|
|
127
|
+
* block). Never throws.
|
|
105
128
|
*/
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
129
|
+
validateEncryption(content: string): boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Blob-shaped variant of `classifyDecryptError`. Same logic as the
|
|
132
|
+
* file-path version but reads metadata from the in-memory ciphertext
|
|
133
|
+
* instead of disk.
|
|
134
|
+
*/
|
|
135
|
+
private classifyDecryptErrorFromContent;
|
|
111
136
|
}
|
|
112
137
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/sops/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/sops/client.ts"],"names":[],"mappings":"AAgBA,OAAO,EAGL,aAAa,EACb,cAAc,EAId,YAAY,EACZ,gBAAgB,EAGjB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACd,MAAM,8BAA8B,CAAC;AAsEtC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,UAAW,YAAW,iBAAiB,EAAE,cAAc;IA4BhE,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IA7B1B,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,UAAU;IACrB,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,yDAAyD;IAE7E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoB;IAEnD;;;;;;;;;;;;;;;;;OAiBG;gBAEgB,MAAM,EAAE,gBAAgB,EACxB,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,MAAM,CAAC,EAAE,MAAM,YAAA,EAChC,QAAQ,CAAC,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,MAAM;IAQzB,OAAO,CAAC,YAAY;IAWpB;;;;;;;;;;;OAWG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAiD3D;;;;;;;OAOG;YACW,oBAAoB;IAsClC,OAAO,CAAC,qBAAqB;IAa7B;;;;;;OAMG;IACH,OAAO,CAAC,wBAAwB;IA6BhC,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,iBAAiB;IA6CzB,OAAO,CAAC,gBAAgB;IAoExB;;;;OAIG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC;IAmD3E;;;;;OAKG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAwCtF;;;;;;;;;;OAUG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAiDxF;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY;IAI1C;;;;OAIG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAS5C;;;;OAIG;YACW,+BAA+B;CAmC9C"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SubprocessRunner } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* On Linux, libuv creates pipes for child stdio. SOPS (Go) translates
|
|
4
|
+
* `/dev/stdin` through `/proc/self/fd/0` and tries to re-open it by path,
|
|
5
|
+
* which fails with ENXIO ("no such device or address") because pipes
|
|
6
|
+
* cannot be re-opened by path.
|
|
7
|
+
*
|
|
8
|
+
* Workaround: when SopsClient asks the runner to spawn `sops` with
|
|
9
|
+
* `/dev/stdin` in the args AND content piped via the runner's stdin,
|
|
10
|
+
* substitute a Linux FIFO (named pipe). FIFOs are openable by path —
|
|
11
|
+
* the bytes still live in an in-memory kernel buffer (not on disk), so
|
|
12
|
+
* the no-plaintext-to-disk invariant is preserved.
|
|
13
|
+
*
|
|
14
|
+
* Gated on `process.platform === "linux"` and the absence of
|
|
15
|
+
* `JEST_WORKER_ID` — unit tests mock `SubprocessRunner` and never
|
|
16
|
+
* spawn a real SOPS binary, so the FIFO machinery would only add
|
|
17
|
+
* subprocess overhead with no benefit. Callers that genuinely need the
|
|
18
|
+
* workaround inside a Jest-spawned child (e.g. the CDK pack-helper
|
|
19
|
+
* subprocess) must scrub `JEST_WORKER_ID` from the child's env so this
|
|
20
|
+
* gate fires correctly.
|
|
21
|
+
*/
|
|
22
|
+
export declare function shouldUseLinuxStdinFifo(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Wrap a `SubprocessRunner` so that any call carrying both `/dev/stdin`
|
|
25
|
+
* in `args` and a non-empty `opts.stdin` payload is rewritten to use a
|
|
26
|
+
* Linux FIFO. On platforms where the workaround isn't needed (or in
|
|
27
|
+
* unit tests), returns the input runner unchanged so the wrapper costs
|
|
28
|
+
* nothing.
|
|
29
|
+
*/
|
|
30
|
+
export declare function wrapWithLinuxStdinFifo(runner: SubprocessRunner): SubprocessRunner;
|
|
31
|
+
//# sourceMappingURL=linux-stdin-fifo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linux-stdin-fifo.d.ts","sourceRoot":"","sources":["../../src/sops/linux-stdin-fifo.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CAEjD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CA4CjF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ClefManifest } from "../types";
|
|
2
|
+
import type { Bulk, Lintable, Rotatable, SecretSource } from "./types";
|
|
3
|
+
import type { StorageBackend } from "./storage-backend";
|
|
4
|
+
import type { EncryptionBackend } from "./encryption-backend";
|
|
5
|
+
/**
|
|
6
|
+
* Build a `SecretSource & Lintable & Rotatable & Bulk` from the two
|
|
7
|
+
* orthogonal backends and the manifest.
|
|
8
|
+
*/
|
|
9
|
+
export declare function composeSecretSource(storage: StorageBackend, encryption: EncryptionBackend, manifest: ClefManifest): SecretSource & Lintable & Rotatable & Bulk;
|
|
10
|
+
//# sourceMappingURL=compose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/source/compose.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,UAAU,CAAC;AAC3D,OAAO,KAAK,EACV,IAAI,EAIJ,QAAQ,EAER,SAAS,EAET,YAAY,EACb,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAqB,MAAM,sBAAsB,CAAC;AAGjF;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,iBAAiB,EAC7B,QAAQ,EAAE,YAAY,GACrB,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,IAAI,CAE5C"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Bulk, SecretSource } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Wrap a `SecretSource` in a `Bulk` implementation that loops over
|
|
4
|
+
* `readCell` / `writeCell` / `deleteCell`. Sources whose substrate
|
|
5
|
+
* cannot batch — or that simply haven't bothered — get correct
|
|
6
|
+
* behavior for free at the cost of one round-trip per cell.
|
|
7
|
+
*
|
|
8
|
+
* Returned object satisfies `Bulk` only; combine via spread when a
|
|
9
|
+
* caller needs both the source surface and bulk methods.
|
|
10
|
+
*/
|
|
11
|
+
export declare function defaultBulk(source: SecretSource): Bulk;
|
|
12
|
+
//# sourceMappingURL=default-bulk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-bulk.d.ts","sourceRoot":"","sources":["../../src/source/default-bulk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAW,YAAY,EAAE,MAAM,SAAS,CAAC;AAG3D;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CA6CtD"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `EncryptionBackend` is the substrate-agnostic encryption contract — a
|
|
3
|
+
* peer abstraction to `StorageBackend`. It takes plaintext values and
|
|
4
|
+
* produces opaque ciphertext bytes (and the reverse), without ever
|
|
5
|
+
* touching files, paths, or storage substrate.
|
|
6
|
+
*
|
|
7
|
+
* Implementations:
|
|
8
|
+
* - `createSopsEncryptionBackend(sopsClient)` — SOPS via the bundled
|
|
9
|
+
* `sops` binary. The default and only first-party implementation.
|
|
10
|
+
* - Future: any byte-shaped encryption scheme (age-direct, libsodium,
|
|
11
|
+
* BYO). Plugin authors can ship one as `@clef-sh/encryption-<id>`.
|
|
12
|
+
*
|
|
13
|
+
* The pairing with `StorageBackend` is intentionally orthogonal:
|
|
14
|
+
*
|
|
15
|
+
* composeSecretSource(storage: StorageBackend,
|
|
16
|
+
* encryption: EncryptionBackend,
|
|
17
|
+
* manifest: ClefManifest): SecretSource
|
|
18
|
+
*
|
|
19
|
+
* Any combination of (storage, encryption) yields a working source.
|
|
20
|
+
*
|
|
21
|
+
* Plaintext discipline:
|
|
22
|
+
* - `encrypt` and `decrypt` may hold plaintext briefly in process memory
|
|
23
|
+
* while they shell out to the encryption tool. Implementations MUST
|
|
24
|
+
* NOT write plaintext to disk, log it, or transmit it over an
|
|
25
|
+
* untrusted channel.
|
|
26
|
+
* - `rotate` is plaintext-free: it transforms ciphertext to ciphertext
|
|
27
|
+
* (re-wrapping the data encryption key against an updated recipient
|
|
28
|
+
* set) without exposing values to the calling process.
|
|
29
|
+
*/
|
|
30
|
+
import type { ClefManifest, DecryptedFile, SopsMetadata } from "../types";
|
|
31
|
+
/**
|
|
32
|
+
* Per-call context. Carries the manifest (for recipients/backend
|
|
33
|
+
* resolution), the target environment (for per-env overrides), and the
|
|
34
|
+
* format hint forwarded from the `StorageBackend`.
|
|
35
|
+
*/
|
|
36
|
+
export interface EncryptionContext {
|
|
37
|
+
manifest: ClefManifest;
|
|
38
|
+
environment?: string;
|
|
39
|
+
/** Format of the ciphertext bytes — typically passed through verbatim. */
|
|
40
|
+
format: "yaml" | "json";
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Recipient changes applied during a rotation. All fields are optional;
|
|
44
|
+
* a backend may interpret only the keys it understands (e.g. a custom
|
|
45
|
+
* non-SOPS backend that ignores `addAge` if it has no concept of age).
|
|
46
|
+
*/
|
|
47
|
+
export interface RotateOptions {
|
|
48
|
+
addAge?: string;
|
|
49
|
+
rmAge?: string;
|
|
50
|
+
addKms?: string;
|
|
51
|
+
rmKms?: string;
|
|
52
|
+
addGcpKms?: string;
|
|
53
|
+
rmGcpKms?: string;
|
|
54
|
+
addAzureKv?: string;
|
|
55
|
+
rmAzureKv?: string;
|
|
56
|
+
addPgp?: string;
|
|
57
|
+
rmPgp?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface EncryptionBackend {
|
|
60
|
+
/** Stable identifier (e.g. `"sops"`). */
|
|
61
|
+
readonly id: string;
|
|
62
|
+
/** Short human-readable description, used in `clef doctor`. */
|
|
63
|
+
readonly description: string;
|
|
64
|
+
/**
|
|
65
|
+
* Encrypt a plaintext value-map into ciphertext bytes. The recipient
|
|
66
|
+
* set is derived from the manifest (and optional per-env override).
|
|
67
|
+
*/
|
|
68
|
+
encrypt(values: Record<string, string>, ctx: EncryptionContext): Promise<string>;
|
|
69
|
+
/**
|
|
70
|
+
* Decrypt ciphertext bytes back into a plaintext value-map plus
|
|
71
|
+
* encryption metadata (backend, recipients, last-modified, ...).
|
|
72
|
+
*/
|
|
73
|
+
decrypt(blob: string, ctx: EncryptionContext): Promise<DecryptedFile>;
|
|
74
|
+
/**
|
|
75
|
+
* Rotate the data encryption key and/or update the recipient set on
|
|
76
|
+
* an already-encrypted blob. Returns the new ciphertext. Plaintext is
|
|
77
|
+
* not exposed to the calling process.
|
|
78
|
+
*/
|
|
79
|
+
rotate(blob: string, opts: RotateOptions, ctx: EncryptionContext): Promise<string>;
|
|
80
|
+
/** Inspect ciphertext metadata without decrypting. Pure parser. */
|
|
81
|
+
getMetadata(blob: string): SopsMetadata;
|
|
82
|
+
/** Whether `blob` is well-formed encrypted output. Never throws. */
|
|
83
|
+
validateEncryption(blob: string): boolean;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=encryption-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption-backend.d.ts","sourceRoot":"","sources":["../../src/source/encryption-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE1E;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,YAAY,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjF;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEtE;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnF,mEAAmE;IACnE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC;IAExC,oEAAoE;IACpE,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3C"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ClefError } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when a CLI command or UI route requires a capability the
|
|
4
|
+
* configured `SecretSource` does not implement (e.g. running
|
|
5
|
+
* `clef rotate` against a `postgres` source that does not implement
|
|
6
|
+
* `Rotatable`).
|
|
7
|
+
*
|
|
8
|
+
* Surfaces at the command-entry boundary so users see a clean message
|
|
9
|
+
* rather than a deep stack trace from a missing method call. The
|
|
10
|
+
* `capability` field is the trait name in lower-case kebab form
|
|
11
|
+
* (`"rotate"`, `"recipients"`, `"merge"`, etc.) — matching the keys of
|
|
12
|
+
* `SourceCapabilities`.
|
|
13
|
+
*/
|
|
14
|
+
export declare class SourceCapabilityUnsupportedError extends ClefError {
|
|
15
|
+
readonly capability: string;
|
|
16
|
+
readonly sourceId: string;
|
|
17
|
+
constructor(capability: string, sourceId: string);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/source/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC;;;;;;;;;;;GAWG;AACH,qBAAa,gCAAiC,SAAQ,SAAS;aAE3C,UAAU,EAAE,MAAM;aAClB,QAAQ,EAAE,MAAM;gBADhB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM;CAQnC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ClefManifest } from "../types";
|
|
2
|
+
import type { StorageBackend } from "./storage-backend";
|
|
3
|
+
import type { CellRef, CellPendingMetadata } from "./types";
|
|
4
|
+
export declare class FilesystemStorageBackend implements StorageBackend {
|
|
5
|
+
private readonly manifest;
|
|
6
|
+
private readonly repoRoot;
|
|
7
|
+
readonly id = "filesystem";
|
|
8
|
+
readonly description = "Filesystem-backed cell storage (default substrate)";
|
|
9
|
+
constructor(manifest: ClefManifest, repoRoot: string);
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a cell reference to its absolute filesystem path. Public —
|
|
12
|
+
* used by substrate-specific trait implementations.
|
|
13
|
+
*/
|
|
14
|
+
cellPath(cell: CellRef): string;
|
|
15
|
+
/** The repo root, exposed for filesystem-shaped trait implementations. */
|
|
16
|
+
getRepoRoot(): string;
|
|
17
|
+
blobFormat(cell: CellRef): "yaml" | "json";
|
|
18
|
+
readBlob(cell: CellRef): Promise<string>;
|
|
19
|
+
writeBlob(cell: CellRef, blob: string): Promise<void>;
|
|
20
|
+
deleteBlob(cell: CellRef): Promise<void>;
|
|
21
|
+
blobExists(cell: CellRef): Promise<boolean>;
|
|
22
|
+
readPendingMetadata(cell: CellRef): Promise<CellPendingMetadata>;
|
|
23
|
+
writePendingMetadata(cell: CellRef, meta: CellPendingMetadata): Promise<void>;
|
|
24
|
+
private sidecarPath;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=filesystem-storage-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-storage-backend.d.ts","sourceRoot":"","sources":["../../src/source/filesystem-storage-backend.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAG5D,qBAAa,wBAAyB,YAAW,cAAc;IAK3D,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL3B,QAAQ,CAAC,EAAE,gBAAgB;IAC3B,QAAQ,CAAC,WAAW,wDAAwD;gBAGzD,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,MAAM;IAGnC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM;IAO/B,0EAA0E;IAC1E,WAAW,IAAI,MAAM;IAIrB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM;IAIpC,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAKxC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBrD,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxC,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3C,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAIhE,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAInF,OAAO,CAAC,WAAW;CAKpB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Bulk, Lintable, MergeAware, Migratable, RecipientManaged, Rotatable, SecretSource, SourceCapabilities, Structural } from "./types";
|
|
2
|
+
export declare function isLintable(s: SecretSource): s is SecretSource & Lintable;
|
|
3
|
+
export declare function isRotatable(s: SecretSource): s is SecretSource & Rotatable;
|
|
4
|
+
export declare function isRecipientManaged(s: SecretSource): s is SecretSource & RecipientManaged;
|
|
5
|
+
export declare function isMergeAware(s: SecretSource): s is SecretSource & MergeAware;
|
|
6
|
+
export declare function isMigratable(s: SecretSource): s is SecretSource & Migratable;
|
|
7
|
+
export declare function isBulk(s: SecretSource): s is SecretSource & Bulk;
|
|
8
|
+
export declare function isStructural(s: SecretSource): s is SecretSource & Structural;
|
|
9
|
+
/**
|
|
10
|
+
* Build a boolean capability descriptor for the source. Used by the UI
|
|
11
|
+
* server's `GET /api/capabilities` endpoint and by `clef doctor` output.
|
|
12
|
+
*/
|
|
13
|
+
export declare function describeCapabilities(s: SecretSource): SourceCapabilities;
|
|
14
|
+
//# sourceMappingURL=guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/source/guards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACX,MAAM,SAAS,CAAC;AAqBjB,wBAAgB,UAAU,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,IAAI,YAAY,GAAG,QAAQ,CAExE;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,IAAI,YAAY,GAAG,SAAS,CAE1E;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,IAAI,YAAY,GAAG,gBAAgB,CAExF;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,IAAI,YAAY,GAAG,UAAU,CAE5E;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,IAAI,YAAY,GAAG,UAAU,CAE5E;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,IAAI,YAAY,GAAG,IAAI,CAEhE;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,IAAI,YAAY,GAAG,UAAU,CAO5E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,YAAY,GAAG,kBAAkB,CAUxE"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type { AddRecipientRequest, Bulk, CellData, CellPendingMetadata, CellRef, Lintable, MergeAware, Migratable, RecipientDriftResult, RecipientManaged, RemoveRecipientRequest, Rotatable, SecretSource, SourceCapabilities, Structural, } from "./types";
|
|
2
|
+
export { describeCapabilities, isBulk, isLintable, isMergeAware, isMigratable, isRecipientManaged, isRotatable, isStructural, } from "./guards";
|
|
3
|
+
export { defaultBulk } from "./default-bulk";
|
|
4
|
+
export { SourceCapabilityUnsupportedError } from "./errors";
|
|
5
|
+
export { MockSecretSource } from "./mock-source";
|
|
6
|
+
export type { StorageBackend } from "./storage-backend";
|
|
7
|
+
export { FilesystemStorageBackend } from "./filesystem-storage-backend";
|
|
8
|
+
export type { EncryptionBackend, EncryptionContext, RotateOptions } from "./encryption-backend";
|
|
9
|
+
export { composeSecretSource } from "./compose";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/source/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,IAAI,EACJ,QAAQ,EACR,mBAAmB,EACnB,OAAO,EACP,QAAQ,EACR,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,YAAY,EACZ,kBAAkB,EAClB,UAAU,GACX,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,oBAAoB,EACpB,MAAM,EACN,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,YAAY,GACb,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,gCAAgC,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGjD,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory test fixture used by CLI command tests and any future
|
|
3
|
+
* consumer that needs to exercise source-shaped code paths without a
|
|
4
|
+
* real git+SOPS substrate. Production code must NOT depend on this
|
|
5
|
+
* file — it is exported under `@clef-sh/core` solely so workspace
|
|
6
|
+
* tests can import it.
|
|
7
|
+
*
|
|
8
|
+
* Capability dialing: pass `capabilities: { lint: false, ... }` to
|
|
9
|
+
* construct a source missing specific traits, so tests can assert
|
|
10
|
+
* `SourceCapabilityUnsupportedError` paths (Phase 5+).
|
|
11
|
+
*/
|
|
12
|
+
import type { AddNamespaceOptions, AddEnvironmentOptions, AddRecipientRequest, CellPendingMetadata, CellRef, CellData, RecipientDriftResult, RemoveRecipientRequest, RotateOptions, SecretSource } from "./types";
|
|
13
|
+
import type { ClefManifest, SopsMetadata } from "../types";
|
|
14
|
+
import type { Recipient, RecipientsResult } from "../recipients";
|
|
15
|
+
import type { MigrationOptions, MigrationResult, MigrationTarget } from "../migration/backend";
|
|
16
|
+
import type { MergeResult } from "../merge/driver";
|
|
17
|
+
interface MockCapabilityToggles {
|
|
18
|
+
lint?: boolean;
|
|
19
|
+
rotate?: boolean;
|
|
20
|
+
recipients?: boolean;
|
|
21
|
+
merge?: boolean;
|
|
22
|
+
migrate?: boolean;
|
|
23
|
+
bulk?: boolean;
|
|
24
|
+
structural?: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface MockSecretSourceOptions {
|
|
27
|
+
id?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
/** Pre-populated cell values keyed by `${namespace}/${environment}`. */
|
|
30
|
+
cells?: Record<string, Record<string, string>>;
|
|
31
|
+
/** Default recipients populated into every read cell's metadata. */
|
|
32
|
+
recipients?: string[];
|
|
33
|
+
/** Capability toggles (default: all true). */
|
|
34
|
+
capabilities?: MockCapabilityToggles;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* In-memory `SecretSource` implementing every trait by default. Toggle
|
|
38
|
+
* capabilities off via the `capabilities` constructor option to
|
|
39
|
+
* simulate a source that does not support a given feature.
|
|
40
|
+
*
|
|
41
|
+
* The `_disabled*` private fields exist because TypeScript type guards
|
|
42
|
+
* detect trait support by method presence. To "disable" a capability
|
|
43
|
+
* the corresponding methods are simply not defined on the instance —
|
|
44
|
+
* the public class definition declares them, but the constructor
|
|
45
|
+
* deletes them when toggled off.
|
|
46
|
+
*/
|
|
47
|
+
export declare class MockSecretSource implements SecretSource {
|
|
48
|
+
readonly id: string;
|
|
49
|
+
readonly description: string;
|
|
50
|
+
private readonly cells;
|
|
51
|
+
private readonly pending;
|
|
52
|
+
private readonly recipients;
|
|
53
|
+
constructor(options?: MockSecretSourceOptions);
|
|
54
|
+
readCell(cell: CellRef): Promise<CellData>;
|
|
55
|
+
writeCell(cell: CellRef, values: Record<string, string>): Promise<void>;
|
|
56
|
+
deleteCell(cell: CellRef): Promise<void>;
|
|
57
|
+
cellExists(cell: CellRef): Promise<boolean>;
|
|
58
|
+
listKeys(cell: CellRef): Promise<string[]>;
|
|
59
|
+
getCellMetadata(_cell: CellRef): Promise<SopsMetadata>;
|
|
60
|
+
scaffoldCell(cell: CellRef, _manifest: ClefManifest): Promise<void>;
|
|
61
|
+
getPendingMetadata(cell: CellRef): Promise<CellPendingMetadata>;
|
|
62
|
+
markPending(cell: CellRef, keys: string[], setBy: string): Promise<void>;
|
|
63
|
+
markResolved(cell: CellRef, keys: string[]): Promise<void>;
|
|
64
|
+
recordRotation(cell: CellRef, keys: string[], rotatedBy: string): Promise<void>;
|
|
65
|
+
removeRotation(cell: CellRef, keys: string[]): Promise<void>;
|
|
66
|
+
validateEncryption(cell: CellRef): Promise<boolean>;
|
|
67
|
+
checkRecipientDrift(_cell: CellRef, expected: string[]): Promise<RecipientDriftResult>;
|
|
68
|
+
rotate(_cell: CellRef, _opts: RotateOptions): Promise<void>;
|
|
69
|
+
listRecipients(_manifest: ClefManifest, _environment?: string): Promise<Recipient[]>;
|
|
70
|
+
addRecipient(req: AddRecipientRequest): Promise<RecipientsResult>;
|
|
71
|
+
removeRecipient(req: RemoveRecipientRequest): Promise<RecipientsResult>;
|
|
72
|
+
mergeCells(_base: CellRef, _ours: CellRef, _theirs: CellRef): Promise<MergeResult>;
|
|
73
|
+
installMergeDriver(_repoRoot: string): Promise<void>;
|
|
74
|
+
uninstallMergeDriver(_repoRoot: string): Promise<void>;
|
|
75
|
+
installHooks(_repoRoot: string): Promise<void>;
|
|
76
|
+
uninstallHooks(_repoRoot: string): Promise<void>;
|
|
77
|
+
migrateBackend(_target: MigrationTarget, _opts: MigrationOptions): Promise<MigrationResult>;
|
|
78
|
+
bulkSet(namespace: string, key: string, valuesByEnv: Record<string, string>, manifest: ClefManifest): Promise<void>;
|
|
79
|
+
bulkDelete(namespace: string, key: string, manifest: ClefManifest): Promise<void>;
|
|
80
|
+
copyValue(key: string, from: CellRef, to: CellRef, manifest: ClefManifest): Promise<void>;
|
|
81
|
+
addNamespace(_name: string, _opts: AddNamespaceOptions, _manifest: ClefManifest): Promise<void>;
|
|
82
|
+
removeNamespace(name: string, _manifest: ClefManifest): Promise<void>;
|
|
83
|
+
renameNamespace(from: string, to: string, _manifest: ClefManifest): Promise<void>;
|
|
84
|
+
addEnvironment(_name: string, _opts: AddEnvironmentOptions, _manifest: ClefManifest): Promise<void>;
|
|
85
|
+
removeEnvironment(name: string, _manifest: ClefManifest): Promise<void>;
|
|
86
|
+
renameEnvironment(from: string, to: string, _manifest: ClefManifest): Promise<void>;
|
|
87
|
+
}
|
|
88
|
+
export {};
|
|
89
|
+
//# sourceMappingURL=mock-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-source.d.ts","sourceRoot":"","sources":["../../src/source/mock-source.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `StorageBackend` is the substrate-level plugin-author surface for *where*
|
|
3
|
+
* ciphertext bytes live. It is one of two orthogonal abstractions composed
|
|
4
|
+
* into a `SecretSource`:
|
|
5
|
+
*
|
|
6
|
+
* - `StorageBackend` — substrate (filesystem, postgres, S3, ...)
|
|
7
|
+
* - `EncryptionBackend` — encryption (SOPS, age-direct, custom, ...)
|
|
8
|
+
*
|
|
9
|
+
* Both vary independently. Any combination — `(filesystem, sops)`,
|
|
10
|
+
* `(postgres, sops)`, `(filesystem, custom)`, `(postgres, custom)` —
|
|
11
|
+
* produces a working `SecretSource` via `composeSecretSource(storage,
|
|
12
|
+
* encryption, manifest)`.
|
|
13
|
+
*
|
|
14
|
+
* Implementations have **zero** knowledge of encryption, recipients, KMS,
|
|
15
|
+
* or age. They store and retrieve opaque bytes by `CellRef` and a small
|
|
16
|
+
* metadata sidecar; plugin authors never re-implement encryption.
|
|
17
|
+
*
|
|
18
|
+
* Format of the bytes:
|
|
19
|
+
* - Whatever the paired `EncryptionBackend` produces and consumes
|
|
20
|
+
* (SOPS YAML/JSON for `sops`; could be anything for a custom backend).
|
|
21
|
+
* - The `StorageBackend` does not parse the bytes; it stores and
|
|
22
|
+
* retrieves them verbatim.
|
|
23
|
+
*
|
|
24
|
+
* Atomicity:
|
|
25
|
+
* - `writeBlob` MUST be atomic from the caller's perspective. A torn
|
|
26
|
+
* write would leave the cell in an undecryptable state. Filesystem
|
|
27
|
+
* impls use temp-file + rename; database impls use a transaction.
|
|
28
|
+
*/
|
|
29
|
+
import type { CellRef, CellPendingMetadata } from "./types";
|
|
30
|
+
export interface StorageBackend {
|
|
31
|
+
/** Stable identifier for diagnostic output (e.g. `"filesystem"`, `"postgres"`). */
|
|
32
|
+
readonly id: string;
|
|
33
|
+
/** Short human-readable description, used in `clef doctor`. */
|
|
34
|
+
readonly description: string;
|
|
35
|
+
/**
|
|
36
|
+
* Read the cell's ciphertext bytes. Throws if the cell does not exist —
|
|
37
|
+
* callers should use `blobExists` first when absence is a valid state.
|
|
38
|
+
*/
|
|
39
|
+
readBlob(cell: CellRef): Promise<string>;
|
|
40
|
+
/** Atomically replace the cell's ciphertext bytes. Idempotent. */
|
|
41
|
+
writeBlob(cell: CellRef, blob: string): Promise<void>;
|
|
42
|
+
/** Remove the cell's blob. No-op if it does not exist. */
|
|
43
|
+
deleteBlob(cell: CellRef): Promise<void>;
|
|
44
|
+
/** Whether the cell currently has stored ciphertext. */
|
|
45
|
+
blobExists(cell: CellRef): Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Format hint for the cell's bytes. Forwarded to the paired
|
|
48
|
+
* `EncryptionBackend` so it can pick the right input/output type. The
|
|
49
|
+
* filesystem substrate derives this from the file extension; other
|
|
50
|
+
* substrates pick a fixed format.
|
|
51
|
+
*/
|
|
52
|
+
blobFormat(cell: CellRef): "yaml" | "json";
|
|
53
|
+
/**
|
|
54
|
+
* Read pending + rotation metadata for the cell. Returns an empty
|
|
55
|
+
* record when no metadata exists. Never throws on missing.
|
|
56
|
+
*/
|
|
57
|
+
readPendingMetadata(cell: CellRef): Promise<CellPendingMetadata>;
|
|
58
|
+
/** Atomically replace the cell's pending + rotation metadata. */
|
|
59
|
+
writePendingMetadata(cell: CellRef, meta: CellPendingMetadata): Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=storage-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-backend.d.ts","sourceRoot":"","sources":["../../src/source/storage-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzC,kEAAkE;IAClE,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtD,0DAA0D;IAC1D,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC,wDAAwD;IACxD,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE5C;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAE3C;;;OAGG;IACH,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAEjE,iEAAiE;IACjE,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/E"}
|