@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.
Files changed (80) hide show
  1. package/README.md +1 -2
  2. package/dist/artifact/packer.d.ts +4 -3
  3. package/dist/artifact/packer.d.ts.map +1 -1
  4. package/dist/artifact/resolve.d.ts +3 -2
  5. package/dist/artifact/resolve.d.ts.map +1 -1
  6. package/dist/compliance/run.d.ts.map +1 -1
  7. package/dist/diff/engine.d.ts +18 -8
  8. package/dist/diff/engine.d.ts.map +1 -1
  9. package/dist/import/index.d.ts +5 -5
  10. package/dist/import/index.d.ts.map +1 -1
  11. package/dist/index.d.mts +14 -12
  12. package/dist/index.d.ts +14 -12
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1225 -872
  15. package/dist/index.js.map +4 -4
  16. package/dist/index.mjs +1213 -848
  17. package/dist/index.mjs.map +4 -4
  18. package/dist/kms/aws-arn.d.ts +29 -0
  19. package/dist/kms/aws-arn.d.ts.map +1 -0
  20. package/dist/kms/index.d.ts +2 -0
  21. package/dist/kms/index.d.ts.map +1 -1
  22. package/dist/lint/runner.d.ts +7 -7
  23. package/dist/lint/runner.d.ts.map +1 -1
  24. package/dist/manifest/io.d.ts +6 -0
  25. package/dist/manifest/io.d.ts.map +1 -1
  26. package/dist/manifest/parser.d.ts.map +1 -1
  27. package/dist/matrix/manager.d.ts +4 -16
  28. package/dist/matrix/manager.d.ts.map +1 -1
  29. package/dist/merge/driver.d.ts +2 -2
  30. package/dist/merge/driver.d.ts.map +1 -1
  31. package/dist/merge/metadata-driver.d.ts +5 -4
  32. package/dist/merge/metadata-driver.d.ts.map +1 -1
  33. package/dist/migration/backend.d.ts +10 -7
  34. package/dist/migration/backend.d.ts.map +1 -1
  35. package/dist/pack/backends/json-envelope.d.ts.map +1 -1
  36. package/dist/pack/types.d.ts +9 -3
  37. package/dist/pack/types.d.ts.map +1 -1
  38. package/dist/pending/metadata.d.ts +1 -3
  39. package/dist/pending/metadata.d.ts.map +1 -1
  40. package/dist/recipients/index.d.ts +4 -3
  41. package/dist/recipients/index.d.ts.map +1 -1
  42. package/dist/report/generator.d.ts +4 -3
  43. package/dist/report/generator.d.ts.map +1 -1
  44. package/dist/reset/manager.d.ts +21 -3
  45. package/dist/reset/manager.d.ts.map +1 -1
  46. package/dist/service-identity/manager.d.ts +6 -3
  47. package/dist/service-identity/manager.d.ts.map +1 -1
  48. package/dist/sops/client.d.ts +80 -55
  49. package/dist/sops/client.d.ts.map +1 -1
  50. package/dist/sops/linux-stdin-fifo.d.ts +31 -0
  51. package/dist/sops/linux-stdin-fifo.d.ts.map +1 -0
  52. package/dist/source/compose.d.ts +10 -0
  53. package/dist/source/compose.d.ts.map +1 -0
  54. package/dist/source/default-bulk.d.ts +12 -0
  55. package/dist/source/default-bulk.d.ts.map +1 -0
  56. package/dist/source/encryption-backend.d.ts +85 -0
  57. package/dist/source/encryption-backend.d.ts.map +1 -0
  58. package/dist/source/errors.d.ts +19 -0
  59. package/dist/source/errors.d.ts.map +1 -0
  60. package/dist/source/filesystem-storage-backend.d.ts +26 -0
  61. package/dist/source/filesystem-storage-backend.d.ts.map +1 -0
  62. package/dist/source/guards.d.ts +14 -0
  63. package/dist/source/guards.d.ts.map +1 -0
  64. package/dist/source/index.d.ts +10 -0
  65. package/dist/source/index.d.ts.map +1 -0
  66. package/dist/source/mock-source.d.ts +89 -0
  67. package/dist/source/mock-source.d.ts.map +1 -0
  68. package/dist/source/storage-backend.d.ts +61 -0
  69. package/dist/source/storage-backend.d.ts.map +1 -0
  70. package/dist/source/types.d.ts +212 -0
  71. package/dist/source/types.d.ts.map +1 -0
  72. package/dist/structure/manager.d.ts +17 -3
  73. package/dist/structure/manager.d.ts.map +1 -1
  74. package/dist/sync/manager.d.ts +7 -6
  75. package/dist/sync/manager.d.ts.map +1 -1
  76. package/dist/types/index.d.ts +10 -23
  77. package/dist/types/index.d.ts.map +1 -1
  78. package/package.json +3 -3
  79. package/dist/bulk/ops.d.ts +0 -57
  80. package/dist/bulk/ops.d.ts.map +0 -1
@@ -1,18 +1,39 @@
1
- import { ClefManifest, DecryptedFile, EncryptionBackend, SopsMetadata, SubprocessRunner } from "../types";
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, re-encryption, and metadata extraction.
4
- * All decrypt/encrypt operations are piped via stdin/stdout — plaintext never touches disk.
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 decrypted = await client.decrypt("secrets/production.enc.yaml");
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 and return its values and metadata.
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
- decrypt(filePath: string): Promise<DecryptedFile>;
71
+ decryptFile(filePath: string): Promise<DecryptedFile>;
47
72
  /**
48
- * Encrypt a key/value map and write it to an encrypted SOPS file.
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
- * @param filePath - Destination path for the encrypted file.
51
- * @param values - Flat key/value map to encrypt.
52
- * @param manifest - Manifest used to determine the encryption backend and key configuration.
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
- encrypt(filePath: string, values: Record<string, string>, manifest: ClefManifest, environment?: string): Promise<void>;
80
+ private classifyDecryptError;
81
+ private parseMetadataFromFile;
58
82
  /**
59
- * Rotate encryption by adding a new age recipient key to an existing SOPS file.
60
- *
61
- * @param filePath - Path to the encrypted file to re-encrypt.
62
- * @param newKey - New age public key to add as a recipient.
63
- * @throws {@link SopsEncryptionError} On failure.
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
- reEncrypt(filePath: string, newKey: string): Promise<void>;
89
+ private parseMetadataFromContent;
90
+ private detectBackend;
91
+ private extractRecipients;
92
+ private buildEncryptArgs;
66
93
  /**
67
- * Add an age recipient to an existing SOPS file.
68
- *
69
- * @param filePath - Path to the encrypted file.
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
- addRecipient(filePath: string, key: string): Promise<void>;
98
+ decrypt(blob: string, ctx: EncryptionContext): Promise<DecryptedFile>;
74
99
  /**
75
- * Remove an age recipient from an existing SOPS file.
76
- *
77
- * @param filePath - Path to the encrypted file.
78
- * @param key - age public key to remove.
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
- removeRecipient(filePath: string, key: string): Promise<void>;
105
+ encrypt(values: Record<string, string>, ctx: EncryptionContext): Promise<string>;
82
106
  /**
83
- * Check whether a file contains valid SOPS encryption metadata.
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
- * @param filePath - Path to the file to check.
86
- * @returns `true` if valid SOPS metadata is present; `false` otherwise. Never throws.
114
+ * Single SOPS invocation can both add and remove recipients
115
+ * simultaneously (matches the CLI flag set).
87
116
  */
88
- validateEncryption(filePath: string): Promise<boolean>;
117
+ rotate(blob: string, opts: RotateOptions, ctx: EncryptionContext): Promise<string>;
89
118
  /**
90
- * Extract SOPS metadata (backend, recipients, last-modified timestamp) from an encrypted file
91
- * without decrypting its values.
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(filePath: string): Promise<SopsMetadata>;
123
+ getMetadata(content: string): SopsMetadata;
98
124
  /**
99
- * Determine whether a decrypt failure is caused by a missing/mismatched key (vs. some other
100
- * SOPS error) without relying on stderr message text.
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
- private classifyDecryptError;
107
- private parseMetadataFromFile;
108
- private detectBackend;
109
- private extractRecipients;
110
- private buildEncryptArgs;
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":"AAiBA,OAAO,EAEL,YAAY,EACZ,aAAa,EACb,iBAAiB,EAIjB,YAAY,EACZ,gBAAgB,EAGjB,MAAM,UAAU,CAAC;AA0ClB;;;;;;;;;GASG;AACH,qBAAa,UAAW,YAAW,iBAAiB;IAuBhD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAxB1B,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;;;;;;;OAOG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA6CvD;;;;;;;;;OASG;IACG,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,QAAQ,EAAE,YAAY,EACtB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC;IAuEhB;;;;;;OAMG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE;;;;;;OAMG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBhE;;;;;;OAMG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBnE;;;;;OAKG;IACG,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU5D;;;;;;;OAOG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAgB1D;;;;;;;OAOG;YACW,oBAAoB;IAsClC,OAAO,CAAC,qBAAqB;IAuC7B,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,iBAAiB;IA6CzB,OAAO,CAAC,gBAAgB;CA+DzB"}
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"}