@clef-sh/core 0.1.28 → 0.3.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 (73) 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 +13 -10
  12. package/dist/index.d.ts +13 -10
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1080 -832
  15. package/dist/index.js.map +4 -4
  16. package/dist/index.mjs +1049 -791
  17. package/dist/index.mjs.map +4 -4
  18. package/dist/lint/runner.d.ts +7 -7
  19. package/dist/lint/runner.d.ts.map +1 -1
  20. package/dist/matrix/manager.d.ts +4 -16
  21. package/dist/matrix/manager.d.ts.map +1 -1
  22. package/dist/merge/driver.d.ts +2 -2
  23. package/dist/merge/driver.d.ts.map +1 -1
  24. package/dist/merge/metadata-driver.d.ts +5 -4
  25. package/dist/merge/metadata-driver.d.ts.map +1 -1
  26. package/dist/migration/backend.d.ts +10 -7
  27. package/dist/migration/backend.d.ts.map +1 -1
  28. package/dist/pack/backends/json-envelope.d.ts.map +1 -1
  29. package/dist/pack/types.d.ts +9 -3
  30. package/dist/pack/types.d.ts.map +1 -1
  31. package/dist/pending/metadata.d.ts +1 -3
  32. package/dist/pending/metadata.d.ts.map +1 -1
  33. package/dist/recipients/index.d.ts +4 -3
  34. package/dist/recipients/index.d.ts.map +1 -1
  35. package/dist/report/generator.d.ts +4 -3
  36. package/dist/report/generator.d.ts.map +1 -1
  37. package/dist/reset/manager.d.ts +21 -3
  38. package/dist/reset/manager.d.ts.map +1 -1
  39. package/dist/service-identity/manager.d.ts +6 -3
  40. package/dist/service-identity/manager.d.ts.map +1 -1
  41. package/dist/sops/client.d.ts +80 -55
  42. package/dist/sops/client.d.ts.map +1 -1
  43. package/dist/sops/linux-stdin-fifo.d.ts +31 -0
  44. package/dist/sops/linux-stdin-fifo.d.ts.map +1 -0
  45. package/dist/source/compose.d.ts +10 -0
  46. package/dist/source/compose.d.ts.map +1 -0
  47. package/dist/source/default-bulk.d.ts +12 -0
  48. package/dist/source/default-bulk.d.ts.map +1 -0
  49. package/dist/source/encryption-backend.d.ts +85 -0
  50. package/dist/source/encryption-backend.d.ts.map +1 -0
  51. package/dist/source/errors.d.ts +19 -0
  52. package/dist/source/errors.d.ts.map +1 -0
  53. package/dist/source/filesystem-storage-backend.d.ts +26 -0
  54. package/dist/source/filesystem-storage-backend.d.ts.map +1 -0
  55. package/dist/source/guards.d.ts +14 -0
  56. package/dist/source/guards.d.ts.map +1 -0
  57. package/dist/source/index.d.ts +10 -0
  58. package/dist/source/index.d.ts.map +1 -0
  59. package/dist/source/mock-source.d.ts +89 -0
  60. package/dist/source/mock-source.d.ts.map +1 -0
  61. package/dist/source/storage-backend.d.ts +61 -0
  62. package/dist/source/storage-backend.d.ts.map +1 -0
  63. package/dist/source/types.d.ts +212 -0
  64. package/dist/source/types.d.ts.map +1 -0
  65. package/dist/structure/manager.d.ts +17 -3
  66. package/dist/structure/manager.d.ts.map +1 -1
  67. package/dist/sync/manager.d.ts +7 -6
  68. package/dist/sync/manager.d.ts.map +1 -1
  69. package/dist/types/index.d.ts +10 -23
  70. package/dist/types/index.d.ts.map +1 -1
  71. package/package.json +3 -3
  72. package/dist/bulk/ops.d.ts +0 -57
  73. package/dist/bulk/ops.d.ts.map +0 -1
@@ -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":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EAEnB,mBAAmB,EACnB,OAAO,EACP,QAAQ,EAIR,oBAAoB,EAEpB,sBAAsB,EAEtB,aAAa,EACb,YAAY,EAEb,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC/F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,UAAU,qBAAqB;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,uBAAuB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/C,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,qBAAqB,CAAC;CACtC;AAoBD;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,YAAW,YAAY;IACnD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6C;IACnE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0C;IAClE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;gBAE1B,OAAO,GAAE,uBAA4B;IA2D3C,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQ1C,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxC,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3C,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAK1C,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC;IAItD,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAI/D,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxE,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1D,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB/E,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5D,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAInD,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAQtF,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3D,cAAc,CAAC,SAAS,EAAE,YAAY,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAIpF,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAWjE,eAAe,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAcvE,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAGlF,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACpD,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACtD,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9C,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,cAAc,CAClB,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,eAAe,CAAC;IAYrB,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,IAAI,CAAC;IAGV,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAGjF,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzF,YAAY,CAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,IAAI,CAAC;IACV,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IASjF,cAAc,CAClB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,qBAAqB,EAC5B,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,IAAI,CAAC;IACV,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvE,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAS1F"}
@@ -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"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * `SecretSource` is the high-level cell-storage seam consumed by every
3
+ * non-source-specific consumer (CLI commands, UI server, pack backends).
4
+ * Methods take and return plaintext at this boundary; encryption is a
5
+ * lower-layer concern that does not appear in this contract.
6
+ *
7
+ * Architecture (introduced in Phase 2):
8
+ *
9
+ * ┌─────────────────────────────────────────────────────┐
10
+ * │ SecretSource plaintext cells, what consumers see │
11
+ * ├─────────────────────────────────────────────────────┤
12
+ * │ SopsClient uniform encryption (KMS/age via │
13
+ * │ the SOPS subprocess) │
14
+ * ├─────────────────────────────────────────────────────┤
15
+ * │ BlobStore opaque ciphertext bytes by CellRef │
16
+ * └─────────────────────────────────────────────────────┘
17
+ *
18
+ * The bundled `GitSopsSource` is composed from `FilesystemBlobStore +
19
+ * SopsClient + manifest`. A future third-party source plugs in by
20
+ * implementing `BlobStore` (a small, encryption-free interface) — the
21
+ * encryption layer is provided uniformly by clef. Plugin authors do
22
+ * not implement encryption primitives.
23
+ *
24
+ * The optional capability traits (`Lintable`, `Rotatable`, etc.)
25
+ * declare functionality some sources can offer and others cannot.
26
+ * SOPS-backed traits (lint/rotate/recipients/migrate) are uniform
27
+ * across every source because they live at the SopsClient layer.
28
+ * Substrate-shaped traits (`MergeAware`, `Structural`) are decided by
29
+ * the BlobStore. Consumers use the type guards in `./guards` for
30
+ * runtime detection; CLI commands and UI routes that require an
31
+ * unsupported capability fail fast with
32
+ * `SourceCapabilityUnsupportedError` (see `./errors`).
33
+ */
34
+ import type { ClefManifest, SopsMetadata } from "../types";
35
+ import type { Recipient, RecipientsResult } from "../recipients";
36
+ import type { MigrationOptions, MigrationResult, MigrationTarget } from "../migration/backend";
37
+ import type { MergeResult } from "../merge/driver";
38
+ import type { CellMetadata as PendingCellMetadata } from "../pending/metadata";
39
+ import type { AddNamespaceOptions, AddEnvironmentOptions } from "../structure/manager";
40
+ import type { RotateOptions } from "./encryption-backend";
41
+ export type { RotateOptions };
42
+ /** Identifies a cell in the namespace × environment matrix. */
43
+ export interface CellRef {
44
+ namespace: string;
45
+ environment: string;
46
+ }
47
+ /** Result of decrypting / loading a cell's contents. */
48
+ export interface CellData {
49
+ values: Record<string, string>;
50
+ /**
51
+ * Source-reported metadata. For `git-sops` this carries the SOPS
52
+ * envelope fields (recipients, lastModified, backend, version).
53
+ * Sources with no native equivalent populate sensible defaults.
54
+ */
55
+ metadata: SopsMetadata;
56
+ }
57
+ /**
58
+ * Pending and rotation metadata for a cell. Mirrors the existing
59
+ * `.clef-meta.yaml` data model so the only thing that changes is *where*
60
+ * the metadata lives — file sidecar (git-sops) vs. database row
61
+ * (postgres) etc.
62
+ */
63
+ export type CellPendingMetadata = PendingCellMetadata;
64
+ /**
65
+ * Boolean capability descriptor returned by `describeCapabilities` and
66
+ * surfaced to UI clients via `GET /api/capabilities`. Field names match
67
+ * the trait identifier so adding a new trait means adding one boolean.
68
+ */
69
+ export interface SourceCapabilities {
70
+ lint: boolean;
71
+ rotate: boolean;
72
+ recipients: boolean;
73
+ merge: boolean;
74
+ migrate: boolean;
75
+ bulk: boolean;
76
+ structural: boolean;
77
+ }
78
+ /**
79
+ * Core contract every source must implement. Operations are cell-level
80
+ * — callers never need to know about file paths, table names, or any
81
+ * other substrate detail.
82
+ *
83
+ * Methods throw `ClefError` (or one of its subclasses such as
84
+ * `SopsDecryptionError` / `SopsKeyNotFoundError`) on failure. Sources
85
+ * are expected to translate substrate-specific errors into the Clef
86
+ * hierarchy so CLI/UI consumers can render uniform error messages.
87
+ */
88
+ export interface SecretSource {
89
+ /** Stable source identifier (e.g. `"git-sops"`, `"postgres"`). */
90
+ readonly id: string;
91
+ /** Short human-readable description, used in `clef doctor` output. */
92
+ readonly description: string;
93
+ /** Decrypt / load the cell's values and metadata. */
94
+ readCell(cell: CellRef): Promise<CellData>;
95
+ /**
96
+ * Replace the cell's values atomically. Implementations must ensure
97
+ * a failure mid-write does not leave partial values visible.
98
+ */
99
+ writeCell(cell: CellRef, values: Record<string, string>): Promise<void>;
100
+ /** Remove the cell entirely (or its scaffolded equivalent). */
101
+ deleteCell(cell: CellRef): Promise<void>;
102
+ /** Whether the cell currently has stored data. */
103
+ cellExists(cell: CellRef): Promise<boolean>;
104
+ /**
105
+ * List the keys present in the cell. Sources that can answer this
106
+ * without decrypting (git-sops reads `data.*` keys from the SOPS
107
+ * file) should do so for performance; otherwise a default
108
+ * implementation can decrypt and return `Object.keys`.
109
+ */
110
+ listKeys(cell: CellRef): Promise<string[]>;
111
+ /** Read source-reported metadata without loading values. */
112
+ getCellMetadata(cell: CellRef): Promise<SopsMetadata>;
113
+ /**
114
+ * Create a new (or empty) cell consistent with the manifest's
115
+ * declared recipients/backend for this environment. Idempotent.
116
+ */
117
+ scaffoldCell(cell: CellRef, manifest: ClefManifest): Promise<void>;
118
+ /** Pending + rotation metadata. */
119
+ getPendingMetadata(cell: CellRef): Promise<CellPendingMetadata>;
120
+ markPending(cell: CellRef, keys: string[], setBy: string): Promise<void>;
121
+ markResolved(cell: CellRef, keys: string[]): Promise<void>;
122
+ recordRotation(cell: CellRef, keys: string[], rotatedBy: string): Promise<void>;
123
+ removeRotation(cell: CellRef, keys: string[]): Promise<void>;
124
+ }
125
+ /**
126
+ * Source-specific lint checks. Portable matrix-completeness lint runs
127
+ * over every source via the core interface and is *not* part of this
128
+ * trait — only checks that depend on the substrate (e.g. SOPS envelope
129
+ * integrity, recipient drift) live here.
130
+ */
131
+ export interface Lintable {
132
+ /** Whether the cell has valid encryption envelope metadata. */
133
+ validateEncryption(cell: CellRef): Promise<boolean>;
134
+ /** Compare the cell's actual recipients against the expected set. */
135
+ checkRecipientDrift(cell: CellRef, expected: string[]): Promise<RecipientDriftResult>;
136
+ }
137
+ /** Result of `Lintable.checkRecipientDrift`. */
138
+ export interface RecipientDriftResult {
139
+ /** Recipients expected by the manifest but absent from the cell. */
140
+ missing: string[];
141
+ /** Recipients present on the cell but not in the manifest. */
142
+ unexpected: string[];
143
+ }
144
+ /**
145
+ * Re-key a cell: rotate the data encryption key and/or update the
146
+ * recipient set without exposing plaintext to the calling process. The
147
+ * `RotateOptions` shape mirrors the substrate-level `EncryptionBackend`
148
+ * — at the SOPS layer that means add/remove for any of age, AWS KMS,
149
+ * GCP KMS, Azure KV, PGP. Backends interpret only the keys they
150
+ * understand.
151
+ */
152
+ export interface Rotatable {
153
+ rotate(cell: CellRef, opts: RotateOptions): Promise<void>;
154
+ }
155
+ /**
156
+ * Manifest-level recipient management. `add` and `remove` mutate both
157
+ * the manifest declaration and re-encrypt every affected cell — the
158
+ * trait bundles these because list/add/remove are useless apart.
159
+ */
160
+ export interface RecipientManaged {
161
+ listRecipients(manifest: ClefManifest, environment?: string): Promise<Recipient[]>;
162
+ addRecipient(req: AddRecipientRequest): Promise<RecipientsResult>;
163
+ removeRecipient(req: RemoveRecipientRequest): Promise<RecipientsResult>;
164
+ }
165
+ export interface AddRecipientRequest {
166
+ key: string;
167
+ label?: string;
168
+ environment?: string;
169
+ manifest: ClefManifest;
170
+ }
171
+ export interface RemoveRecipientRequest {
172
+ key: string;
173
+ environment?: string;
174
+ manifest: ClefManifest;
175
+ }
176
+ /** Three-way merge + git driver/hook installation. */
177
+ export interface MergeAware {
178
+ mergeCells(base: CellRef, ours: CellRef, theirs: CellRef): Promise<MergeResult>;
179
+ installMergeDriver(repoRoot: string): Promise<void>;
180
+ uninstallMergeDriver(repoRoot: string): Promise<void>;
181
+ installHooks(repoRoot: string): Promise<void>;
182
+ uninstallHooks(repoRoot: string): Promise<void>;
183
+ }
184
+ /** Re-encrypt every cell to a new SOPS backend (e.g. age → awskms). */
185
+ export interface Migratable {
186
+ migrateBackend(target: MigrationTarget, opts: MigrationOptions): Promise<MigrationResult>;
187
+ }
188
+ /**
189
+ * Batch operations across the matrix. Sources that can do these in a
190
+ * single round-trip (e.g. one SQL transaction) should implement the
191
+ * trait directly; otherwise consumers wrap a `SecretSource` in
192
+ * `defaultBulk` for a correct-but-slow looped fallback.
193
+ */
194
+ export interface Bulk {
195
+ bulkSet(namespace: string, key: string, valuesByEnv: Record<string, string>, manifest: ClefManifest): Promise<void>;
196
+ bulkDelete(namespace: string, key: string, manifest: ClefManifest): Promise<void>;
197
+ copyValue(key: string, from: CellRef, to: CellRef, manifest: ClefManifest): Promise<void>;
198
+ }
199
+ /**
200
+ * Namespace + environment CRUD. On a file-based source this cascades
201
+ * to file/folder renames; on a DB source it's a metadata table update.
202
+ */
203
+ export interface Structural {
204
+ addNamespace(name: string, opts: AddNamespaceOptions, manifest: ClefManifest): Promise<void>;
205
+ removeNamespace(name: string, manifest: ClefManifest): Promise<void>;
206
+ renameNamespace(from: string, to: string, manifest: ClefManifest): Promise<void>;
207
+ addEnvironment(name: string, opts: AddEnvironmentOptions, manifest: ClefManifest): Promise<void>;
208
+ removeEnvironment(name: string, manifest: ClefManifest): Promise<void>;
209
+ renameEnvironment(from: string, to: string, manifest: ClefManifest): Promise<void>;
210
+ }
211
+ export type { AddNamespaceOptions, AddEnvironmentOptions };
212
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/source/types.ts"],"names":[],"mappings":"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"}