@clef-sh/core 0.1.17 → 0.1.19
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/dist/artifact/guards.d.ts +40 -0
- package/dist/artifact/guards.d.ts.map +1 -0
- package/dist/artifact/packer.d.ts.map +1 -1
- package/dist/artifact/types.d.ts +11 -2
- package/dist/artifact/types.d.ts.map +1 -1
- package/dist/compliance/generator.d.ts.map +1 -1
- package/dist/compliance/run.d.ts +19 -0
- package/dist/compliance/run.d.ts.map +1 -1
- package/dist/git/integration.d.ts +8 -5
- package/dist/git/integration.d.ts.map +1 -1
- package/dist/hsm/bundled.d.ts +10 -0
- package/dist/hsm/bundled.d.ts.map +1 -0
- package/dist/hsm/index.d.ts +4 -0
- package/dist/hsm/index.d.ts.map +1 -0
- package/dist/hsm/keyservice.d.ts +36 -0
- package/dist/hsm/keyservice.d.ts.map +1 -0
- package/dist/hsm/resolver.d.ts +22 -0
- package/dist/hsm/resolver.d.ts.map +1 -0
- package/dist/import/index.d.ts +7 -0
- package/dist/import/index.d.ts.map +1 -1
- package/dist/index.d.mts +14 -4
- package/dist/index.d.ts +14 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1129 -385
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +1107 -381
- package/dist/index.mjs.map +4 -4
- package/dist/lint/runner.d.ts +7 -0
- package/dist/lint/runner.d.ts.map +1 -1
- package/dist/manifest/parser.d.ts.map +1 -1
- package/dist/merge/metadata-driver.d.ts +17 -0
- package/dist/merge/metadata-driver.d.ts.map +1 -0
- package/dist/migration/backend.d.ts.map +1 -1
- package/dist/pack/backends/json-envelope.d.ts +33 -0
- package/dist/pack/backends/json-envelope.d.ts.map +1 -0
- package/dist/pack/registry.d.ts +27 -0
- package/dist/pack/registry.d.ts.map +1 -0
- package/dist/pack/types.d.ts +78 -0
- package/dist/pack/types.d.ts.map +1 -0
- package/dist/pending/metadata.d.ts +40 -15
- package/dist/pending/metadata.d.ts.map +1 -1
- package/dist/policy/evaluator.d.ts +19 -9
- package/dist/policy/evaluator.d.ts.map +1 -1
- package/dist/policy/types.d.ts +40 -9
- package/dist/policy/types.d.ts.map +1 -1
- package/dist/scanner/index.d.ts +9 -1
- package/dist/scanner/index.d.ts.map +1 -1
- package/dist/scanner/patterns.d.ts +12 -0
- package/dist/scanner/patterns.d.ts.map +1 -1
- package/dist/sops/client.d.ts +11 -1
- package/dist/sops/client.d.ts.map +1 -1
- package/dist/sops/hsm-arn.d.ts +51 -0
- package/dist/sops/hsm-arn.d.ts.map +1 -0
- package/dist/types/index.d.ts +18 -2
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/lint/runner.d.ts
CHANGED
|
@@ -24,6 +24,13 @@ export declare class LintRunner {
|
|
|
24
24
|
* @param repoRoot - Absolute path to the repository root.
|
|
25
25
|
*/
|
|
26
26
|
run(manifest: ClefManifest, repoRoot: string): Promise<LintResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Cross-reference `.clef-meta.yaml` against the cipher's plaintext key
|
|
29
|
+
* names for each existing cell. Reports orphan rotation records and
|
|
30
|
+
* dual-state (pending + rotation) inconsistencies. Uses
|
|
31
|
+
* {@link readSopsKeyNames} (plaintext YAML parse) — no decryption.
|
|
32
|
+
*/
|
|
33
|
+
private lintMetadataConsistency;
|
|
27
34
|
/**
|
|
28
35
|
* Lint service identity configurations for drift issues.
|
|
29
36
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lint/runner.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EAEZ,UAAU,EAIX,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lint/runner.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EAEZ,UAAU,EAIX,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAI7C;;;;;;;;GAQG;AACH,qBAAa,UAAU;IAEnB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAFV,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,eAAe,EAChC,UAAU,EAAE,iBAAiB;IAGhD;;;;;;OAMG;IACG,GAAG,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAmOxE;;;;;OAKG;YACW,uBAAuB;IAgDrC;;OAEG;YACW,qBAAqB;IAoGnC;;;;;OAKG;IACG,GAAG,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAWzE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/manifest/parser.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,YAAY,EAKb,MAAM,UAAU,CAAC;AAGlB;;;GAGG;AACH,eAAO,MAAM,sBAAsB,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/manifest/parser.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,YAAY,EAKb,MAAM,UAAU,CAAC;AAGlB;;;GAGG;AACH,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAuBlD;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACzB;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY;IAsBrC;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY;IA+lBtC;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI;CAchF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge two `.clef-meta.yaml` contents (as strings). Does not read the
|
|
3
|
+
* base revision — the timestamp-ordered merge is associative without one,
|
|
4
|
+
* which is the whole reason we can auto-resolve. The caller is
|
|
5
|
+
* responsible for reading / writing from disk.
|
|
6
|
+
*
|
|
7
|
+
* Returns the merged YAML content with the standard Clef header comment.
|
|
8
|
+
*/
|
|
9
|
+
export declare function mergeMetadataContents(oursContent: string, theirsContent: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Filesystem wrapper around {@link mergeMetadataContents}. Reads ours and
|
|
12
|
+
* theirs, writes the merged result back to `oursPath` (the conventional
|
|
13
|
+
* destination git passes as `%A`). Does not read `basePath` — see the
|
|
14
|
+
* merge algorithm's docstring for why a base revision is not needed.
|
|
15
|
+
*/
|
|
16
|
+
export declare function mergeMetadataFiles(_basePath: string, oursPath: string, theirsPath: string): void;
|
|
17
|
+
//# sourceMappingURL=metadata-driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata-driver.d.ts","sourceRoot":"","sources":["../../src/merge/metadata-driver.ts"],"names":[],"mappings":"AAgNA;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAQxF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAKhG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/migration/backend.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EAGxB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAE3C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAID;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,uBAAuB,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/migration/backend.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EAGxB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAE3C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAID;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,uBAAuB,GAAG,SAAS,CAO7F,CAAC;AAMF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,uBAAuB,CAOzB;AAUD,qBAAa,eAAe;IAcxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,EAAE;IAdrB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoB;IACnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoB;IAEnD;;;;;;;OAOG;gBAED,UAAU,EAAE,iBAAiB,EACZ,aAAa,EAAE,aAAa,EAC5B,EAAE,EAAE,kBAAkB,EACvC,gBAAgB,CAAC,EAAE,iBAAiB;IAMhC,OAAO,CACX,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,gBAAgB,EACzB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,GACnD,OAAO,CAAC,eAAe,CAAC;IAoL3B,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,yBAAyB;CAmBlC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { PackOutput } from "../../artifact/types";
|
|
2
|
+
import type { BackendPackResult, PackBackend, PackRequest } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Options specific to the {@link JsonEnvelopeBackend}. At least one of
|
|
5
|
+
* `outputPath` or `output` must be provided; `signingKey` and
|
|
6
|
+
* `signingKmsKeyId` are mutually exclusive.
|
|
7
|
+
*/
|
|
8
|
+
export interface JsonEnvelopeOptions {
|
|
9
|
+
/** Local file path for the artifact JSON. Used when `output` is not provided. */
|
|
10
|
+
outputPath?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Pre-constructed output backend. Takes precedence over `outputPath`.
|
|
13
|
+
* Used by `clef serve` with {@link MemoryPackOutput} to avoid disk I/O.
|
|
14
|
+
*/
|
|
15
|
+
output?: PackOutput;
|
|
16
|
+
/** Ed25519 private key for artifact signing (base64 DER PKCS8). */
|
|
17
|
+
signingKey?: string;
|
|
18
|
+
/** KMS asymmetric signing key ARN/ID (ECDSA_SHA_256). Mutually exclusive with signingKey. */
|
|
19
|
+
signingKmsKeyId?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Default pack backend. Produces the canonical Clef JSON artifact
|
|
23
|
+
* envelope (age-encrypted for age identities, AES-256-GCM with
|
|
24
|
+
* KMS-wrapped DEK for KMS-envelope identities) and writes it to
|
|
25
|
+
* a file or a provided output adapter.
|
|
26
|
+
*/
|
|
27
|
+
export declare class JsonEnvelopeBackend implements PackBackend {
|
|
28
|
+
readonly id = "json-envelope";
|
|
29
|
+
readonly description = "Write the Clef JSON artifact envelope to a local file (default).";
|
|
30
|
+
validateOptions(raw: Record<string, unknown>): void;
|
|
31
|
+
pack(req: PackRequest): Promise<BackendPackResult>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=json-envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-envelope.d.ts","sourceRoot":"","sources":["../../../src/pack/backends/json-envelope.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5E;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6FAA6F;IAC7F,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,YAAW,WAAW;IACrD,QAAQ,CAAC,EAAE,mBAAmB;IAC9B,QAAQ,CAAC,WAAW,sEAAsE;IAE1F,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAY7C,IAAI,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC;CA8BzD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PackBackend, PackBackendFactory } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Registry of pack backends. The CLI registers `clef-native` eagerly and
|
|
4
|
+
* may register additional backends discovered via optional plugin packages
|
|
5
|
+
* (e.g. `@clef-sh/pack-vault`). Embedders (tests, IaC synth hooks) may
|
|
6
|
+
* construct a registry directly and register only the backends they need.
|
|
7
|
+
*/
|
|
8
|
+
export declare class PackBackendRegistry {
|
|
9
|
+
private readonly factories;
|
|
10
|
+
/**
|
|
11
|
+
* Register a backend factory under the given id. Throws if a backend
|
|
12
|
+
* with the same id is already registered — collisions surface as a clear
|
|
13
|
+
* error rather than a silent overwrite.
|
|
14
|
+
*/
|
|
15
|
+
register(id: string, factory: PackBackendFactory): void;
|
|
16
|
+
/** Whether a backend with the given id has been registered. */
|
|
17
|
+
has(id: string): boolean;
|
|
18
|
+
/** Registered backend ids, in registration order. */
|
|
19
|
+
list(): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Resolve a backend by id. Throws if unknown. Factories may be async so
|
|
22
|
+
* a plugin package can defer construction (e.g. loading a heavy SDK only
|
|
23
|
+
* when the backend is actually used).
|
|
24
|
+
*/
|
|
25
|
+
resolve(id: string): Promise<PackBackend>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/pack/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE/D;;;;;GAKG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyC;IAEnE;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAOvD,+DAA+D;IAC/D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB,qDAAqD;IACrD,IAAI,IAAI,MAAM,EAAE;IAIhB;;;;OAIG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAQhD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ClefManifest, EncryptionBackend, SubprocessRunner } from "../types";
|
|
2
|
+
import type { KmsProvider } from "../kms";
|
|
3
|
+
import type { PackResult } from "../artifact/types";
|
|
4
|
+
/**
|
|
5
|
+
* Shared services a PackBackend may use. A backend is free to ignore any
|
|
6
|
+
* field it does not need.
|
|
7
|
+
*/
|
|
8
|
+
export interface PackServices {
|
|
9
|
+
/** Decryption/encryption of SOPS source files in the matrix. */
|
|
10
|
+
encryption: EncryptionBackend;
|
|
11
|
+
/** KMS provider, already constructed. Undefined when the manifest does not require one. */
|
|
12
|
+
kms?: KmsProvider;
|
|
13
|
+
/** For subprocess access (git, external CLIs). Prefer this over child_process. */
|
|
14
|
+
runner: SubprocessRunner;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Input to `PackBackend.pack`. Fields are the intersection of what all
|
|
18
|
+
* conceivable backends need; anything backend-specific lives in
|
|
19
|
+
* `backendOptions` and is typed and validated by the backend itself.
|
|
20
|
+
*
|
|
21
|
+
* Implementations must not read `process.env`, log decrypted values, or
|
|
22
|
+
* call `process.exit` — a `PackRequest` may be constructed by any caller
|
|
23
|
+
* (CLI, IaC synth-time hook, test), not just the `clef pack` command.
|
|
24
|
+
*/
|
|
25
|
+
export interface PackRequest {
|
|
26
|
+
/** Service identity name from the manifest. */
|
|
27
|
+
identity: string;
|
|
28
|
+
/** Target environment name. */
|
|
29
|
+
environment: string;
|
|
30
|
+
/** Parsed manifest. */
|
|
31
|
+
manifest: ClefManifest;
|
|
32
|
+
/** Absolute path to the clef repo root. */
|
|
33
|
+
repoRoot: string;
|
|
34
|
+
/** Shared services the backend may use. */
|
|
35
|
+
services: PackServices;
|
|
36
|
+
/** Optional TTL in seconds. Backends that do not support it should ignore. */
|
|
37
|
+
ttl?: number;
|
|
38
|
+
/** Backend-specific options; shape is the backend's private concern. */
|
|
39
|
+
backendOptions: Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Result of a `PackBackend.pack` call. Extends the existing `PackResult`
|
|
43
|
+
* with the backend identifier and a freeform details map for per-backend
|
|
44
|
+
* diagnostics.
|
|
45
|
+
*/
|
|
46
|
+
export interface BackendPackResult extends PackResult {
|
|
47
|
+
/** Identifier of the backend that produced this result (e.g. `"clef-native"`). */
|
|
48
|
+
backend: string;
|
|
49
|
+
/**
|
|
50
|
+
* Freeform per-backend diagnostic detail (e.g. secret ARN, bucket key,
|
|
51
|
+
* commit SHA). Values must be JSON-serializable.
|
|
52
|
+
*/
|
|
53
|
+
details?: Record<string, string | number | boolean | null>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Contract for a pack destination. A backend turns a (identity, environment)
|
|
57
|
+
* pair into whatever its target system requires — a local JSON file for
|
|
58
|
+
* `clef-native`, a Vault KV write for a future vault backend, and so on.
|
|
59
|
+
*/
|
|
60
|
+
export interface PackBackend {
|
|
61
|
+
/** Stable backend identifier (e.g. `"clef-native"`, `"aws-secrets"`, `"vault"`). */
|
|
62
|
+
readonly id: string;
|
|
63
|
+
/** Short human description, used by `clef pack --help` and diagnostics. */
|
|
64
|
+
readonly description: string;
|
|
65
|
+
/**
|
|
66
|
+
* Validate and normalize backend-specific options. Throw with a precise
|
|
67
|
+
* error message on invalid input. Called before `pack`.
|
|
68
|
+
*/
|
|
69
|
+
validateOptions?(raw: Record<string, unknown>): void;
|
|
70
|
+
/**
|
|
71
|
+
* Perform the pack. Must not log plaintext secrets, must not write
|
|
72
|
+
* plaintext to disk, and must not depend on process-global state.
|
|
73
|
+
*/
|
|
74
|
+
pack(req: PackRequest): Promise<BackendPackResult>;
|
|
75
|
+
}
|
|
76
|
+
/** Factory signature used by `PackBackendRegistry.register`. */
|
|
77
|
+
export type PackBackendFactory = () => PackBackend | Promise<PackBackend>;
|
|
78
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/pack/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,UAAU,EAAE,iBAAiB,CAAC;IAC9B,2FAA2F;IAC3F,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,kFAAkF;IAClF,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,QAAQ,EAAE,YAAY,CAAC;IACvB,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;CAC5D;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,eAAe,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACrD;;;OAGG;IACH,IAAI,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACpD;AAED,gEAAgE;AAChE,MAAM,MAAM,kBAAkB,GAAG,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC"}
|
|
@@ -3,26 +3,38 @@ interface PendingKey {
|
|
|
3
3
|
since: Date;
|
|
4
4
|
setBy: string;
|
|
5
5
|
}
|
|
6
|
-
interface
|
|
6
|
+
interface RotationRecord {
|
|
7
|
+
key: string;
|
|
8
|
+
lastRotatedAt: Date;
|
|
9
|
+
rotatedBy: string;
|
|
10
|
+
rotationCount: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Parsed contents of a `.clef-meta.yaml` sidecar.
|
|
14
|
+
*
|
|
15
|
+
* Both `pending` and `rotations` may be empty arrays — they represent two
|
|
16
|
+
* independent per-key state sections. A fresh cell with no sidecar file
|
|
17
|
+
* on disk is represented as `{ version: 1, pending: [], rotations: [] }`.
|
|
18
|
+
*/
|
|
19
|
+
interface CellMetadata {
|
|
7
20
|
version: 1;
|
|
8
21
|
pending: PendingKey[];
|
|
22
|
+
rotations: RotationRecord[];
|
|
9
23
|
}
|
|
24
|
+
/** @deprecated Use {@link CellMetadata}. Retained for external import compatibility. */
|
|
25
|
+
type PendingMetadata = CellMetadata;
|
|
10
26
|
/**
|
|
11
27
|
* Derive the `.clef-meta.yaml` path from an `.enc.yaml` path.
|
|
12
28
|
* Example: `database/dev.enc.yaml` → `database/dev.clef-meta.yaml`
|
|
13
29
|
*/
|
|
14
30
|
declare function metadataPath(encryptedFilePath: string): string;
|
|
15
|
-
/** Load
|
|
16
|
-
declare function loadMetadata(filePath: string): Promise<
|
|
17
|
-
/** Write
|
|
18
|
-
declare function saveMetadata(filePath: string, metadata:
|
|
31
|
+
/** Load metadata for an encrypted file. Returns empty metadata if the file is missing or unreadable. */
|
|
32
|
+
declare function loadMetadata(filePath: string): Promise<CellMetadata>;
|
|
33
|
+
/** Write metadata to disk. Creates parent directories if needed. */
|
|
34
|
+
declare function saveMetadata(filePath: string, metadata: CellMetadata): Promise<void>;
|
|
19
35
|
/**
|
|
20
36
|
* Mark one or more keys as pending (placeholder value) for an encrypted file.
|
|
21
37
|
* If a key is already pending, its timestamp and `setBy` are updated.
|
|
22
|
-
*
|
|
23
|
-
* @param filePath - Path to the encrypted file.
|
|
24
|
-
* @param keys - Key names to mark as pending.
|
|
25
|
-
* @param setBy - Identifier of the actor setting these keys (e.g. a username or CI job).
|
|
26
38
|
*/
|
|
27
39
|
declare function markPending(filePath: string, keys: string[], setBy: string): Promise<void>;
|
|
28
40
|
/** Remove keys from the pending list after they have received real values. */
|
|
@@ -31,16 +43,29 @@ declare function markResolved(filePath: string, keys: string[]): Promise<void>;
|
|
|
31
43
|
declare function getPendingKeys(filePath: string): Promise<string[]>;
|
|
32
44
|
/** Check whether a single key is currently pending for the given encrypted file. */
|
|
33
45
|
declare function isPending(filePath: string, key: string): Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Record a rotation for one or more keys. Creates a new record when the key
|
|
48
|
+
* has never rotated before (rotation_count: 1), or upserts an existing record
|
|
49
|
+
* by bumping rotation_count and updating last_rotated_at + rotated_by.
|
|
50
|
+
*
|
|
51
|
+
* Also removes the corresponding `pending` entry if present — a rotation is
|
|
52
|
+
* the resolution of a pending placeholder, so the two states are mutually
|
|
53
|
+
* exclusive.
|
|
54
|
+
*/
|
|
55
|
+
declare function recordRotation(filePath: string, keys: string[], rotatedBy: string, now?: Date): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Remove rotation records for the given keys. Called when a key is deleted
|
|
58
|
+
* from the cell via `clef delete` — leaving a stale record would mislead
|
|
59
|
+
* policy evaluation.
|
|
60
|
+
*/
|
|
61
|
+
declare function removeRotation(filePath: string, keys: string[]): Promise<void>;
|
|
62
|
+
/** Return the rotation records currently recorded for the given encrypted file. */
|
|
63
|
+
declare function getRotations(filePath: string): Promise<RotationRecord[]>;
|
|
34
64
|
/** Generate a cryptographically random 64-character hex string for use as a placeholder value. */
|
|
35
65
|
declare function generateRandomValue(): string;
|
|
36
66
|
/**
|
|
37
67
|
* Same as {@link markPending} but retries once after `retryDelayMs` on transient failure.
|
|
38
|
-
*
|
|
39
|
-
* @param filePath - Path to the encrypted file.
|
|
40
|
-
* @param keys - Key names to mark as pending.
|
|
41
|
-
* @param setBy - Identifier of the actor setting these keys.
|
|
42
|
-
* @param retryDelayMs - Delay in milliseconds before the single retry (default: 200).
|
|
43
68
|
*/
|
|
44
69
|
declare function markPendingWithRetry(filePath: string, keys: string[], setBy: string, retryDelayMs?: number): Promise<void>;
|
|
45
|
-
export { PendingKey, PendingMetadata, metadataPath, loadMetadata, saveMetadata, markPending, markPendingWithRetry, markResolved, getPendingKeys, isPending, generateRandomValue, };
|
|
70
|
+
export { PendingKey, RotationRecord, CellMetadata, PendingMetadata, metadataPath, loadMetadata, saveMetadata, markPending, markPendingWithRetry, markResolved, getPendingKeys, isPending, recordRotation, removeRotation, getRotations, generateRandomValue, };
|
|
46
71
|
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/pending/metadata.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/pending/metadata.ts"],"names":[],"mappings":"AAoCA,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,IAAI,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,cAAc;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,UAAU,YAAY;IACpB,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,yFAAyF;AACzF,KAAK,eAAe,GAAG,YAAY,CAAC;AAEpC;;;GAGG;AACH,iBAAS,YAAY,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAIvD;AAQD,yGAAyG;AACzG,iBAAe,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAiDnE;AAED,qEAAqE;AACrE,iBAAe,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBnF;AAED;;;GAGG;AACH,iBAAe,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYzF;AAED,8EAA8E;AAC9E,iBAAe,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3E;AAED,wFAAwF;AACxF,iBAAe,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGjE;AAED,oFAAoF;AACpF,iBAAe,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGxE;AAED;;;;;;;;GAQG;AACH,iBAAe,cAAc,CAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,IAAiB,GACrB,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;;;GAIG;AACH,iBAAe,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7E;AAED,mFAAmF;AACnF,iBAAe,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAGvE;AAED,kGAAkG;AAClG,iBAAS,mBAAmB,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,iBAAe,oBAAoB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,MAAM,EACb,YAAY,SAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,SAAS,EACT,cAAc,EACd,cAAc,EACd,YAAY,EACZ,mBAAmB,GACpB,CAAC"}
|
|
@@ -13,27 +13,37 @@
|
|
|
13
13
|
* See docs/contributing/testing.md for the rationale.
|
|
14
14
|
*/
|
|
15
15
|
import { SopsMetadata } from "../types";
|
|
16
|
+
import { RotationRecord } from "../pending/metadata";
|
|
16
17
|
import { FileRotationStatus, PolicyDocument } from "./types";
|
|
17
18
|
/**
|
|
18
|
-
* Evaluates
|
|
19
|
+
* Evaluates per-key rotation state against a {@link PolicyDocument}.
|
|
19
20
|
*
|
|
20
21
|
* The evaluator is intentionally pure — it never reads the filesystem and
|
|
21
|
-
* never decrypts. All inputs
|
|
22
|
+
* never decrypts. All inputs (file metadata, key names, rotation records)
|
|
23
|
+
* come from the caller.
|
|
22
24
|
*/
|
|
23
25
|
export declare class PolicyEvaluator {
|
|
24
26
|
private readonly policy;
|
|
25
27
|
constructor(policy: PolicyDocument);
|
|
26
28
|
/**
|
|
27
|
-
* Evaluate a single encrypted file's rotation state.
|
|
29
|
+
* Evaluate a single encrypted file's per-key rotation state.
|
|
28
30
|
*
|
|
29
31
|
* @param filePath Repo-relative or absolute path to the encrypted file.
|
|
30
|
-
* @param environment Environment name
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
32
|
+
* @param environment Environment name; selects per-env overrides.
|
|
33
|
+
* @param metadata SOPS metadata for the file (carries last_modified,
|
|
34
|
+
* backend, recipients). The evaluator does not read
|
|
35
|
+
* `last_modified` for the policy gate — it is echoed
|
|
36
|
+
* into the output for audit consumers only.
|
|
37
|
+
* @param keys Plaintext key names present in the cipher, enumerated
|
|
38
|
+
* from the unencrypted YAML top-level keys (no decrypt
|
|
39
|
+
* required since SOPS stores key names in plaintext).
|
|
40
|
+
* @param rotations Rotation records from `.clef-meta.yaml`. Records for
|
|
41
|
+
* keys not in `keys` are ignored (those are orphans;
|
|
42
|
+
* lint surfaces them as a warning).
|
|
43
|
+
* @param now Reference time. Inject for deterministic tests.
|
|
35
44
|
*/
|
|
36
|
-
evaluateFile(filePath: string, environment: string, metadata: SopsMetadata, now?: Date): FileRotationStatus;
|
|
45
|
+
evaluateFile(filePath: string, environment: string, metadata: SopsMetadata, keys: string[], rotations: RotationRecord[], now?: Date): FileRotationStatus;
|
|
46
|
+
private evaluateKey;
|
|
37
47
|
private resolveMaxAgeDays;
|
|
38
48
|
}
|
|
39
49
|
//# sourceMappingURL=evaluator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/policy/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/policy/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAqB,cAAc,EAAE,MAAM,SAAS,CAAC;AAMhF;;;;;;GAMG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,cAAc;IAEnD;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CACV,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,EAAE,cAAc,EAAE,EAC3B,GAAG,GAAE,IAAiB,GACrB,kBAAkB;IAsBrB,OAAO,CAAC,WAAW;IA0CnB,OAAO,CAAC,iBAAiB;CAK1B"}
|
package/dist/policy/types.d.ts
CHANGED
|
@@ -29,11 +29,46 @@ export interface PolicyDocument {
|
|
|
29
29
|
version: 1;
|
|
30
30
|
rotation?: PolicyRotationConfig;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Per-key rotation verdict inside a {@link FileRotationStatus}. Each entry
|
|
34
|
+
* corresponds to one plaintext key present in the encrypted file.
|
|
35
|
+
*
|
|
36
|
+
* The authoritative signal is `last_rotated_at` from `.clef-meta.yaml`
|
|
37
|
+
* (recorded by `clef set` / `clef import` when a value actually changes).
|
|
38
|
+
* When no record exists, `last_rotated_known: false` and `compliant: false` —
|
|
39
|
+
* unknown rotation state is treated as a policy violation by design.
|
|
40
|
+
*/
|
|
41
|
+
export interface KeyRotationStatus {
|
|
42
|
+
/** Key name as it appears in the cipher (plaintext). */
|
|
43
|
+
key: string;
|
|
44
|
+
/** ISO 8601 of the last recorded rotation, or `null` when unknown. */
|
|
45
|
+
last_rotated_at: string | null;
|
|
46
|
+
/** Whether `.clef-meta.yaml` had a rotation record for this key. */
|
|
47
|
+
last_rotated_known: boolean;
|
|
48
|
+
/** Git identity that performed the last rotation, or `null` when unknown. */
|
|
49
|
+
rotated_by: string | null;
|
|
50
|
+
/** Monotonically increasing counter across rotations, or `0` when unknown. */
|
|
51
|
+
rotation_count: number;
|
|
52
|
+
/** `last_rotated_at + max_age_days`. `null` when `last_rotated_known: false`. */
|
|
53
|
+
rotation_due: string | null;
|
|
54
|
+
/** `true` iff the rotation is known and past due. */
|
|
55
|
+
rotation_overdue: boolean;
|
|
56
|
+
/** `0` when not overdue or unknown. */
|
|
57
|
+
days_overdue: number;
|
|
58
|
+
/** `true` iff `last_rotated_known && !rotation_overdue`. */
|
|
59
|
+
compliant: boolean;
|
|
60
|
+
}
|
|
32
61
|
/**
|
|
33
62
|
* Result of evaluating a single encrypted file against a {@link PolicyDocument}.
|
|
34
63
|
*
|
|
35
64
|
* Field names are part of the public compliance artifact contract — see the
|
|
36
65
|
* notice at the top of this file.
|
|
66
|
+
*
|
|
67
|
+
* The policy gate is driven by per-key rotation state (`keys[*].compliant`).
|
|
68
|
+
* `compliant` on this struct is the AND of the per-key verdicts. File-level
|
|
69
|
+
* rotation fields are intentionally absent — `sops.lastmodified` is a file
|
|
70
|
+
* freshness signal, not a value-rotation signal, and the two answer different
|
|
71
|
+
* questions (see the rotation policy docs for rationale).
|
|
37
72
|
*/
|
|
38
73
|
export interface FileRotationStatus {
|
|
39
74
|
/** Repo-relative or absolute path the evaluator was given. */
|
|
@@ -46,17 +81,13 @@ export interface FileRotationStatus {
|
|
|
46
81
|
last_modified: string;
|
|
47
82
|
/**
|
|
48
83
|
* Whether the underlying SOPS file actually carried a `lastmodified` field.
|
|
49
|
-
* `false` means `last_modified` is a synthetic fallback
|
|
50
|
-
*
|
|
51
|
-
* distinctly from a normal "compliant" verdict).
|
|
84
|
+
* `false` means `last_modified` is a synthetic fallback. Kept as a raw
|
|
85
|
+
* signal for audit consumers; does not gate policy.
|
|
52
86
|
*/
|
|
53
87
|
last_modified_known: boolean;
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
/** `0` when not overdue. */
|
|
58
|
-
days_overdue: number;
|
|
59
|
-
/** `false` if `rotation_overdue`; `true` otherwise. */
|
|
88
|
+
/** Per-key rotation verdicts. Empty array only for cells that have no keys. */
|
|
89
|
+
keys: KeyRotationStatus[];
|
|
90
|
+
/** AND of `keys[*].compliant`. `true` only when every key is compliant. */
|
|
60
91
|
compliant: boolean;
|
|
61
92
|
}
|
|
62
93
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/policy/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,6EAA6E;AAC7E,MAAM,WAAW,yBAAyB;IACxC,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,uDAAuD;AACvD,MAAM,WAAW,oBAAoB;IACnC,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;CAC1D;AAED,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/policy/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,6EAA6E;AAC7E,MAAM,WAAW,yBAAyB;IACxC,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,uDAAuD;AACvD,MAAM,WAAW,oBAAoB;IACnC,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;CAC1D;AAED,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oEAAoE;IACpE,kBAAkB,EAAE,OAAO,CAAC;IAC5B,6EAA6E;IAC7E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,8EAA8E;IAC9E,cAAc,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,qDAAqD;IACrD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uCAAuC;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IACjC,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,mBAAmB,EAAE,OAAO,CAAC;IAC7B,gFAAgF;IAChF,IAAI,EAAE,iBAAiB,EAAE,CAAC;IAC1B,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,cAGT,CAAC"}
|
package/dist/scanner/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ClefManifest, SubprocessRunner } from "../types";
|
|
|
2
2
|
import { ScanMatch } from "./patterns";
|
|
3
3
|
export type { ScanMatch } from "./patterns";
|
|
4
4
|
export type { ClefIgnoreRules } from "./ignore";
|
|
5
|
-
export { shannonEntropy, isHighEntropy, matchPatterns, redactValue } from "./patterns";
|
|
5
|
+
export { shannonEntropy, isHighEntropy, matchPatterns, matchPublicPrefix, redactValue, } from "./patterns";
|
|
6
6
|
export { loadIgnoreRules, shouldIgnoreFile, shouldIgnoreMatch, parseIgnoreContent } from "./ignore";
|
|
7
7
|
export interface ScanResult {
|
|
8
8
|
matches: ScanMatch[];
|
|
@@ -15,6 +15,14 @@ export interface ScanOptions {
|
|
|
15
15
|
stagedOnly?: boolean;
|
|
16
16
|
paths?: string[];
|
|
17
17
|
severity?: "all" | "high";
|
|
18
|
+
/**
|
|
19
|
+
* When `true` (default) the entropy detector skips values that match known
|
|
20
|
+
* public-by-design credential shapes — reCAPTCHA site keys, Stripe
|
|
21
|
+
* publishable keys, etc. Set to `false` (via `--no-public-allowlist`) to
|
|
22
|
+
* report every high-entropy value regardless of shape. Pattern matches
|
|
23
|
+
* are unaffected — a leaked AWS/Stripe secret key is still flagged.
|
|
24
|
+
*/
|
|
25
|
+
publicAllowlist?: boolean;
|
|
18
26
|
}
|
|
19
27
|
/**
|
|
20
28
|
* Scans repository files for plaintext secrets using pattern matching and entropy detection.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAML,SAAS,EACV,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EACL,cAAc,EACd,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEpG,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAUD;;;;;;;;GAQG;AACH,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,gBAAgB;IAErD;;;;;;;;OAQG;IACG,IAAI,CACR,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,YAAY,EACtB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC;IA+GtB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,QAAQ;IAehB,OAAO,CAAC,aAAa;YAkCP,cAAc;YAUd,eAAe;YAef,kBAAkB;IAShC,OAAO,CAAC,OAAO;CAqBhB"}
|
|
@@ -19,6 +19,18 @@ export interface ScanMatch {
|
|
|
19
19
|
entropy?: number;
|
|
20
20
|
preview: string;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Returns a matching public-prefix definition if the value is a known
|
|
24
|
+
* client-facing credential shape (reCAPTCHA site key, Stripe publishable
|
|
25
|
+
* key, etc.). `null` when the value is not recognized as public.
|
|
26
|
+
*
|
|
27
|
+
* Used by the entropy detector to avoid false positives on strings that are
|
|
28
|
+
* public by design. The check is intentionally conservative — patterns are
|
|
29
|
+
* anchored (`^...$`) so partial matches do not qualify.
|
|
30
|
+
*/
|
|
31
|
+
export declare function matchPublicPrefix(value: string): {
|
|
32
|
+
name: string;
|
|
33
|
+
} | null;
|
|
22
34
|
/**
|
|
23
35
|
* Calculate Shannon entropy (bits per character) of a string.
|
|
24
36
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/scanner/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/scanner/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AA4CD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAKxE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYlD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAM,EAAE,SAAS,SAAK,GAAG,OAAO,CAErF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,CAgB7F"}
|
package/dist/sops/client.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export declare class SopsClient implements EncryptionBackend {
|
|
|
14
14
|
private readonly ageKeyFile?;
|
|
15
15
|
private readonly ageKey?;
|
|
16
16
|
private readonly sopsCommand;
|
|
17
|
+
private readonly keyserviceArgs;
|
|
17
18
|
/**
|
|
18
19
|
* @param runner - Subprocess runner used to invoke the `sops` binary.
|
|
19
20
|
* @param ageKeyFile - Optional path to an age private key file. Passed as
|
|
@@ -22,8 +23,17 @@ export declare class SopsClient implements EncryptionBackend {
|
|
|
22
23
|
* to the subprocess environment.
|
|
23
24
|
* @param sopsPath - Optional explicit path to the sops binary. When omitted,
|
|
24
25
|
* resolved automatically via {@link resolveSopsPath}.
|
|
26
|
+
* @param keyserviceAddr - Optional address of an external SOPS KeyService
|
|
27
|
+
* sidecar (e.g. `tcp://127.0.0.1:12345`). When set, every SOPS invocation
|
|
28
|
+
* includes `--enable-local-keyservice=false --keyservice <addr>` so KMS
|
|
29
|
+
* wrap/unwrap is routed to the sidecar (used for the HSM backend, where
|
|
30
|
+
* the sidecar is `clef-keyservice` talking PKCS#11 to the HSM).
|
|
31
|
+
*
|
|
32
|
+
* The flags are inserted **after** the SOPS subcommand — placing them
|
|
33
|
+
* before is silently ignored by SOPS (a footgun discovered the first
|
|
34
|
+
* time we shipped this).
|
|
25
35
|
*/
|
|
26
|
-
constructor(runner: SubprocessRunner, ageKeyFile?: string | undefined, ageKey?: string | undefined, sopsPath?: string);
|
|
36
|
+
constructor(runner: SubprocessRunner, ageKeyFile?: string | undefined, ageKey?: string | undefined, sopsPath?: string, keyserviceAddr?: string);
|
|
27
37
|
private buildSopsEnv;
|
|
28
38
|
/**
|
|
29
39
|
* Decrypt a SOPS-encrypted file and return its values and metadata.
|
|
@@ -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;
|
|
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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TIER 1 MODULE — Security and correctness critical.
|
|
3
|
+
*
|
|
4
|
+
* Wraps and unwraps PKCS#11 URIs as synthetic AWS KMS ARNs so they pass
|
|
5
|
+
* through SOPS's `--kms` validation regex. Every encrypted file with
|
|
6
|
+
* backend `hsm` stores its key identifier as a Clef-shaped ARN; the
|
|
7
|
+
* clef-keyservice side decodes it back to a pkcs11 URI before handing
|
|
8
|
+
* the DEK wrap/unwrap to the HSM.
|
|
9
|
+
*
|
|
10
|
+
* Contract v1 — frozen with the clef-keyservice team:
|
|
11
|
+
*
|
|
12
|
+
* arn:aws:kms:us-east-1:000000000000:alias/clef-hsm/v1/<BASE64URL(pkcs11-uri)>
|
|
13
|
+
*
|
|
14
|
+
* - Region / account are placeholders. SOPS never dials AWS because
|
|
15
|
+
* `--enable-local-keyservice=false` routes every KMS op to the
|
|
16
|
+
* keyservice sidecar.
|
|
17
|
+
* - Payload is RFC 4648 §5 base64url, no padding. Alphabet is
|
|
18
|
+
* `[A-Za-z0-9_-]`, which is why the regex below ends with `+$`
|
|
19
|
+
* over that exact class.
|
|
20
|
+
* - Version marker lets us evolve the encoding if RFC 7512 extensions
|
|
21
|
+
* push us to a different format — bump to `v2` on both sides.
|
|
22
|
+
*
|
|
23
|
+
* Coverage threshold: 95% lines/functions, 90% branches.
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Wrap a pkcs11 URI in a Clef HSM synthetic ARN.
|
|
27
|
+
*
|
|
28
|
+
* @param uri - A pkcs11 URI (e.g. `pkcs11:slot=0;label=clef-dek-wrapper`).
|
|
29
|
+
* @returns An ARN that passes SOPS's `--kms` regex and carries the URI as payload.
|
|
30
|
+
* @throws If `uri` does not start with `pkcs11:`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function pkcs11UriToSyntheticArn(uri: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Decode a Clef HSM synthetic ARN back to its pkcs11 URI.
|
|
35
|
+
*
|
|
36
|
+
* @param arn - A string that may or may not be a Clef HSM ARN.
|
|
37
|
+
* @returns The pkcs11 URI if `arn` matches the contract; `null` otherwise.
|
|
38
|
+
* Returning `null` (rather than throwing) lets callers branch cleanly
|
|
39
|
+
* between "this is a Clef HSM ARN" and "this is some other KMS ARN".
|
|
40
|
+
* Callers that require a valid decode should throw themselves.
|
|
41
|
+
*/
|
|
42
|
+
export declare function syntheticArnToPkcs11Uri(arn: string): string | null;
|
|
43
|
+
/**
|
|
44
|
+
* Check whether a string is a Clef HSM synthetic ARN (regardless of
|
|
45
|
+
* whether its payload decodes cleanly).
|
|
46
|
+
*
|
|
47
|
+
* Used by {@link SopsClient.detectBackend} to classify entries in
|
|
48
|
+
* `sops.kms[]` as `hsm` rather than `awskms`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function isClefHsmArn(arn: string): boolean;
|
|
51
|
+
//# sourceMappingURL=hsm-arn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hsm-arn.d.ts","sourceRoot":"","sources":["../../src/sops/hsm-arn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAWH;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAY3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAalE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEjD"}
|