@penvhq/cli 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +686 -397
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +49 -28
- package/dist/index.d.ts +49 -28
- package/dist/index.js +539 -241
- package/dist/index.js.map +1 -1
- package/package.json +8 -10
package/dist/index.d.cts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import * as citty from 'citty';
|
|
2
|
-
import {
|
|
2
|
+
import { ProjectionProvider, Provider, ParameterRef, Scope, AnyProvider, RotationMechanism, RotationState } from '@penvhq/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A check reports one of four verdicts. `unknown` — a check that ran but could
|
|
6
6
|
* not reach a verdict — is never rendered as a pass: "I looked and found nothing
|
|
7
7
|
* wrong" and "I could not look" are opposite situations with opposite remedies,
|
|
8
|
-
* and a
|
|
8
|
+
* and a value-withholding destination makes most of what doctor can say the
|
|
9
|
+
* second kind.
|
|
9
10
|
*/
|
|
10
11
|
type DoctorSeverity = "pass" | "warning" | "failure" | "unknown";
|
|
11
|
-
type DoctorCheck = "schema" | "missing" | "declared" | "weak" | "unused" | "unscoped-fallback" | "plaintext-secret" | "public-secret" | "encryption" | "rotation-overdue" | "rotation-stuck" | "provider-value-drift" | "provider" | "
|
|
12
|
+
type DoctorCheck = "schema" | "missing" | "declared" | "weak" | "unused" | "unscoped-fallback" | "plaintext-secret" | "public-secret" | "encryption" | "rotation-overdue" | "rotation-stuck" | "provider-value-drift" | "provider" | "projection-unreachable" | "projection-name-drift" | "projection-manual-edit" | "projection-value-drift" | "environment-flag-shadow";
|
|
12
13
|
interface DoctorFinding {
|
|
13
14
|
readonly check: DoctorCheck;
|
|
14
15
|
readonly severity: DoctorSeverity;
|
|
@@ -27,13 +28,15 @@ interface DoctorReport {
|
|
|
27
28
|
interface DoctorOptions {
|
|
28
29
|
readonly cwd: string;
|
|
29
30
|
readonly environment?: string;
|
|
30
|
-
/**
|
|
31
|
-
readonly
|
|
31
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
32
|
+
readonly envFlags?: readonly string[];
|
|
33
|
+
/** Injected in tests: the projection-holding destination to check against. Defaults to the one the config declares. */
|
|
34
|
+
readonly projection?: ProjectionProvider;
|
|
32
35
|
/**
|
|
33
36
|
* Injected in tests: the source-of-truth provider to compare the local tree
|
|
34
37
|
* against. Defaults to the one the config declares (`sourceProviderFor`).
|
|
35
|
-
* Mirrors `
|
|
36
|
-
* a live backend.
|
|
38
|
+
* Mirrors `projection`, for the same reason — the drift checks stay driveable
|
|
39
|
+
* without a live backend.
|
|
37
40
|
*/
|
|
38
41
|
readonly source?: Provider;
|
|
39
42
|
/** Injected in tests: the wall-clock reading the rotation clocks are read against. Defaults to now. */
|
|
@@ -127,6 +130,8 @@ interface FillPrompt {
|
|
|
127
130
|
interface FillOptions {
|
|
128
131
|
readonly cwd: string;
|
|
129
132
|
readonly environment?: string;
|
|
133
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
134
|
+
readonly envFlags?: readonly string[];
|
|
130
135
|
/**
|
|
131
136
|
* How a value is obtained for one prompt. `undefined` or an empty answer skips
|
|
132
137
|
* the parameter — the readline half lives only in the wrapper, so `runFill`
|
|
@@ -176,6 +181,8 @@ declare function renderFill(result: FillResult): string[];
|
|
|
176
181
|
interface GenerateOptions {
|
|
177
182
|
readonly cwd: string;
|
|
178
183
|
readonly environment?: string;
|
|
184
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
185
|
+
readonly envFlags?: readonly string[];
|
|
179
186
|
/** Where to write, absolute or relative to `cwd`. Defaults to `.env` at the project root. */
|
|
180
187
|
readonly out?: string;
|
|
181
188
|
/** Permits sealed values to be written into the artifact as plaintext. */
|
|
@@ -410,6 +417,8 @@ interface ValidateResult {
|
|
|
410
417
|
interface ValidateOptions {
|
|
411
418
|
readonly cwd: string;
|
|
412
419
|
readonly environment?: string;
|
|
420
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
421
|
+
readonly envFlags?: readonly string[];
|
|
413
422
|
}
|
|
414
423
|
declare function runValidate(options: ValidateOptions): Promise<ValidateResult>;
|
|
415
424
|
|
|
@@ -556,26 +565,13 @@ interface MoveResult {
|
|
|
556
565
|
declare function runMove(options: MoveOptions): Promise<MoveResult>;
|
|
557
566
|
declare function renderMove(result: MoveResult): string[];
|
|
558
567
|
|
|
559
|
-
/**
|
|
560
|
-
* `penv pull` — materialise the local `.penv` tree from an environment's
|
|
561
|
-
* source-of-truth provider. It is the inverse of the deploy-time injection most
|
|
562
|
-
* stacks already have: instead of reading the tree to feed a backend, it reads
|
|
563
|
-
* the backend to feed the tree.
|
|
564
|
-
*
|
|
565
|
-
* It only means anything when the environment declares a real backend
|
|
566
|
-
* (`vault`, `mock`): those hold the truth somewhere penv does not edit in place,
|
|
567
|
-
* and pulling copies it down so every other command — which reads the local tree
|
|
568
|
-
* — sees it. An environment with no separate `providers` entry has the local
|
|
569
|
-
* tree *as* its source of truth, so a pull would be the tree copying onto
|
|
570
|
-
* itself; that degenerate case is reported as nothing to do, never a self-copy.
|
|
571
|
-
*
|
|
572
|
-
* Values cross verbatim. They are opaque envelope strings the source holds and
|
|
573
|
-
* penv does not open here — a sealed value stays sealed, byte-for-byte, so the
|
|
574
|
-
* key that opens it never has to be present to pull it.
|
|
575
|
-
*/
|
|
576
568
|
interface PullOptions {
|
|
577
569
|
readonly cwd: string;
|
|
578
570
|
readonly environment?: string;
|
|
571
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
572
|
+
readonly envFlags?: readonly string[];
|
|
573
|
+
/** Injected in tests: the source provider. Defaults to the one the config declares. */
|
|
574
|
+
readonly source?: AnyProvider;
|
|
579
575
|
}
|
|
580
576
|
interface PullResult {
|
|
581
577
|
readonly environment: string;
|
|
@@ -593,6 +589,12 @@ interface PullResult {
|
|
|
593
589
|
readonly meta: number;
|
|
594
590
|
/** Distinct parameters the pull touched, at any scope. */
|
|
595
591
|
readonly refs: number;
|
|
592
|
+
/**
|
|
593
|
+
* True when the source declares `readsValues: false`: names and meta came
|
|
594
|
+
* down, values stayed absent — the destination never returns one, and the
|
|
595
|
+
* pull says so rather than dressing emptiness as freshness.
|
|
596
|
+
*/
|
|
597
|
+
readonly valuesUnreadable?: boolean;
|
|
596
598
|
}
|
|
597
599
|
declare function runPull(options: PullOptions): Promise<PullResult>;
|
|
598
600
|
declare function renderPull(result: PullResult): string[];
|
|
@@ -602,22 +604,41 @@ declare const LAST_PUSHED_KEY = "lastPushedAt";
|
|
|
602
604
|
interface PushOptions {
|
|
603
605
|
readonly cwd: string;
|
|
604
606
|
readonly environment?: string;
|
|
607
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
608
|
+
readonly envFlags?: readonly string[];
|
|
605
609
|
/** Permits sealed values to be decrypted locally and pushed as plaintext for the destination to re-seal. */
|
|
606
610
|
readonly allowDecrypt?: boolean;
|
|
607
|
-
/**
|
|
608
|
-
readonly
|
|
611
|
+
/** One-shot destination override: a provider package name. Nothing is persisted. */
|
|
612
|
+
readonly destination?: string;
|
|
613
|
+
/** The destination-side place, when `destination` needs one — `--location`. */
|
|
614
|
+
readonly location?: string;
|
|
615
|
+
/** Pre-approves creating a missing destination-side target (`--yes`). */
|
|
616
|
+
readonly yes?: boolean;
|
|
617
|
+
/** Injected in tests: the destination provider. Defaults to the one the config (or `--destination`) declares. */
|
|
618
|
+
readonly provider?: AnyProvider;
|
|
619
|
+
/** Injected in tests: answers the create-target question. Defaults to a terminal prompt. */
|
|
620
|
+
readonly confirm?: (question: string) => Promise<boolean>;
|
|
609
621
|
/** Injected in tests: the wall-clock reading recorded in meta. Defaults to now. */
|
|
610
622
|
readonly now?: string;
|
|
611
623
|
}
|
|
612
624
|
interface PushResult {
|
|
613
625
|
readonly environment: string;
|
|
614
|
-
/** The
|
|
615
|
-
readonly
|
|
626
|
+
/** The destination provider's type — its package name. */
|
|
627
|
+
readonly destination: string;
|
|
628
|
+
/** What the destination holds, which decided what crossed. */
|
|
629
|
+
readonly mode: "records" | "projection";
|
|
630
|
+
/** The `location` targeted, when one was declared. */
|
|
631
|
+
readonly location: string | undefined;
|
|
632
|
+
/** Values sent — resolved secrets for a projection, value files for records. */
|
|
616
633
|
readonly pushed: number;
|
|
634
|
+
/** Meta records mirrored. Records mode only. */
|
|
635
|
+
readonly meta: number;
|
|
617
636
|
readonly repositorySecrets: number;
|
|
618
637
|
readonly environmentSecrets: number;
|
|
619
638
|
/** How many were sealed and crossed as plaintext for the destination to re-seal. */
|
|
620
639
|
readonly decrypted: number;
|
|
640
|
+
/** True when the destination-side target was created by this push, on approval. */
|
|
641
|
+
readonly createdTarget: boolean;
|
|
621
642
|
}
|
|
622
643
|
declare function runPush(options: PushOptions): Promise<PushResult>;
|
|
623
644
|
declare function renderPush(result: PushResult): string[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import * as citty from 'citty';
|
|
2
|
-
import {
|
|
2
|
+
import { ProjectionProvider, Provider, ParameterRef, Scope, AnyProvider, RotationMechanism, RotationState } from '@penvhq/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A check reports one of four verdicts. `unknown` — a check that ran but could
|
|
6
6
|
* not reach a verdict — is never rendered as a pass: "I looked and found nothing
|
|
7
7
|
* wrong" and "I could not look" are opposite situations with opposite remedies,
|
|
8
|
-
* and a
|
|
8
|
+
* and a value-withholding destination makes most of what doctor can say the
|
|
9
|
+
* second kind.
|
|
9
10
|
*/
|
|
10
11
|
type DoctorSeverity = "pass" | "warning" | "failure" | "unknown";
|
|
11
|
-
type DoctorCheck = "schema" | "missing" | "declared" | "weak" | "unused" | "unscoped-fallback" | "plaintext-secret" | "public-secret" | "encryption" | "rotation-overdue" | "rotation-stuck" | "provider-value-drift" | "provider" | "
|
|
12
|
+
type DoctorCheck = "schema" | "missing" | "declared" | "weak" | "unused" | "unscoped-fallback" | "plaintext-secret" | "public-secret" | "encryption" | "rotation-overdue" | "rotation-stuck" | "provider-value-drift" | "provider" | "projection-unreachable" | "projection-name-drift" | "projection-manual-edit" | "projection-value-drift" | "environment-flag-shadow";
|
|
12
13
|
interface DoctorFinding {
|
|
13
14
|
readonly check: DoctorCheck;
|
|
14
15
|
readonly severity: DoctorSeverity;
|
|
@@ -27,13 +28,15 @@ interface DoctorReport {
|
|
|
27
28
|
interface DoctorOptions {
|
|
28
29
|
readonly cwd: string;
|
|
29
30
|
readonly environment?: string;
|
|
30
|
-
/**
|
|
31
|
-
readonly
|
|
31
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
32
|
+
readonly envFlags?: readonly string[];
|
|
33
|
+
/** Injected in tests: the projection-holding destination to check against. Defaults to the one the config declares. */
|
|
34
|
+
readonly projection?: ProjectionProvider;
|
|
32
35
|
/**
|
|
33
36
|
* Injected in tests: the source-of-truth provider to compare the local tree
|
|
34
37
|
* against. Defaults to the one the config declares (`sourceProviderFor`).
|
|
35
|
-
* Mirrors `
|
|
36
|
-
* a live backend.
|
|
38
|
+
* Mirrors `projection`, for the same reason — the drift checks stay driveable
|
|
39
|
+
* without a live backend.
|
|
37
40
|
*/
|
|
38
41
|
readonly source?: Provider;
|
|
39
42
|
/** Injected in tests: the wall-clock reading the rotation clocks are read against. Defaults to now. */
|
|
@@ -127,6 +130,8 @@ interface FillPrompt {
|
|
|
127
130
|
interface FillOptions {
|
|
128
131
|
readonly cwd: string;
|
|
129
132
|
readonly environment?: string;
|
|
133
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
134
|
+
readonly envFlags?: readonly string[];
|
|
130
135
|
/**
|
|
131
136
|
* How a value is obtained for one prompt. `undefined` or an empty answer skips
|
|
132
137
|
* the parameter — the readline half lives only in the wrapper, so `runFill`
|
|
@@ -176,6 +181,8 @@ declare function renderFill(result: FillResult): string[];
|
|
|
176
181
|
interface GenerateOptions {
|
|
177
182
|
readonly cwd: string;
|
|
178
183
|
readonly environment?: string;
|
|
184
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
185
|
+
readonly envFlags?: readonly string[];
|
|
179
186
|
/** Where to write, absolute or relative to `cwd`. Defaults to `.env` at the project root. */
|
|
180
187
|
readonly out?: string;
|
|
181
188
|
/** Permits sealed values to be written into the artifact as plaintext. */
|
|
@@ -410,6 +417,8 @@ interface ValidateResult {
|
|
|
410
417
|
interface ValidateOptions {
|
|
411
418
|
readonly cwd: string;
|
|
412
419
|
readonly environment?: string;
|
|
420
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
421
|
+
readonly envFlags?: readonly string[];
|
|
413
422
|
}
|
|
414
423
|
declare function runValidate(options: ValidateOptions): Promise<ValidateResult>;
|
|
415
424
|
|
|
@@ -556,26 +565,13 @@ interface MoveResult {
|
|
|
556
565
|
declare function runMove(options: MoveOptions): Promise<MoveResult>;
|
|
557
566
|
declare function renderMove(result: MoveResult): string[];
|
|
558
567
|
|
|
559
|
-
/**
|
|
560
|
-
* `penv pull` — materialise the local `.penv` tree from an environment's
|
|
561
|
-
* source-of-truth provider. It is the inverse of the deploy-time injection most
|
|
562
|
-
* stacks already have: instead of reading the tree to feed a backend, it reads
|
|
563
|
-
* the backend to feed the tree.
|
|
564
|
-
*
|
|
565
|
-
* It only means anything when the environment declares a real backend
|
|
566
|
-
* (`vault`, `mock`): those hold the truth somewhere penv does not edit in place,
|
|
567
|
-
* and pulling copies it down so every other command — which reads the local tree
|
|
568
|
-
* — sees it. An environment with no separate `providers` entry has the local
|
|
569
|
-
* tree *as* its source of truth, so a pull would be the tree copying onto
|
|
570
|
-
* itself; that degenerate case is reported as nothing to do, never a self-copy.
|
|
571
|
-
*
|
|
572
|
-
* Values cross verbatim. They are opaque envelope strings the source holds and
|
|
573
|
-
* penv does not open here — a sealed value stays sealed, byte-for-byte, so the
|
|
574
|
-
* key that opens it never has to be present to pull it.
|
|
575
|
-
*/
|
|
576
568
|
interface PullOptions {
|
|
577
569
|
readonly cwd: string;
|
|
578
570
|
readonly environment?: string;
|
|
571
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
572
|
+
readonly envFlags?: readonly string[];
|
|
573
|
+
/** Injected in tests: the source provider. Defaults to the one the config declares. */
|
|
574
|
+
readonly source?: AnyProvider;
|
|
579
575
|
}
|
|
580
576
|
interface PullResult {
|
|
581
577
|
readonly environment: string;
|
|
@@ -593,6 +589,12 @@ interface PullResult {
|
|
|
593
589
|
readonly meta: number;
|
|
594
590
|
/** Distinct parameters the pull touched, at any scope. */
|
|
595
591
|
readonly refs: number;
|
|
592
|
+
/**
|
|
593
|
+
* True when the source declares `readsValues: false`: names and meta came
|
|
594
|
+
* down, values stayed absent — the destination never returns one, and the
|
|
595
|
+
* pull says so rather than dressing emptiness as freshness.
|
|
596
|
+
*/
|
|
597
|
+
readonly valuesUnreadable?: boolean;
|
|
596
598
|
}
|
|
597
599
|
declare function runPull(options: PullOptions): Promise<PullResult>;
|
|
598
600
|
declare function renderPull(result: PullResult): string[];
|
|
@@ -602,22 +604,41 @@ declare const LAST_PUSHED_KEY = "lastPushedAt";
|
|
|
602
604
|
interface PushOptions {
|
|
603
605
|
readonly cwd: string;
|
|
604
606
|
readonly environment?: string;
|
|
607
|
+
/** Bare flags the command did not declare — environment shorthands, judged against the whitelist. */
|
|
608
|
+
readonly envFlags?: readonly string[];
|
|
605
609
|
/** Permits sealed values to be decrypted locally and pushed as plaintext for the destination to re-seal. */
|
|
606
610
|
readonly allowDecrypt?: boolean;
|
|
607
|
-
/**
|
|
608
|
-
readonly
|
|
611
|
+
/** One-shot destination override: a provider package name. Nothing is persisted. */
|
|
612
|
+
readonly destination?: string;
|
|
613
|
+
/** The destination-side place, when `destination` needs one — `--location`. */
|
|
614
|
+
readonly location?: string;
|
|
615
|
+
/** Pre-approves creating a missing destination-side target (`--yes`). */
|
|
616
|
+
readonly yes?: boolean;
|
|
617
|
+
/** Injected in tests: the destination provider. Defaults to the one the config (or `--destination`) declares. */
|
|
618
|
+
readonly provider?: AnyProvider;
|
|
619
|
+
/** Injected in tests: answers the create-target question. Defaults to a terminal prompt. */
|
|
620
|
+
readonly confirm?: (question: string) => Promise<boolean>;
|
|
609
621
|
/** Injected in tests: the wall-clock reading recorded in meta. Defaults to now. */
|
|
610
622
|
readonly now?: string;
|
|
611
623
|
}
|
|
612
624
|
interface PushResult {
|
|
613
625
|
readonly environment: string;
|
|
614
|
-
/** The
|
|
615
|
-
readonly
|
|
626
|
+
/** The destination provider's type — its package name. */
|
|
627
|
+
readonly destination: string;
|
|
628
|
+
/** What the destination holds, which decided what crossed. */
|
|
629
|
+
readonly mode: "records" | "projection";
|
|
630
|
+
/** The `location` targeted, when one was declared. */
|
|
631
|
+
readonly location: string | undefined;
|
|
632
|
+
/** Values sent — resolved secrets for a projection, value files for records. */
|
|
616
633
|
readonly pushed: number;
|
|
634
|
+
/** Meta records mirrored. Records mode only. */
|
|
635
|
+
readonly meta: number;
|
|
617
636
|
readonly repositorySecrets: number;
|
|
618
637
|
readonly environmentSecrets: number;
|
|
619
638
|
/** How many were sealed and crossed as plaintext for the destination to re-seal. */
|
|
620
639
|
readonly decrypted: number;
|
|
640
|
+
/** True when the destination-side target was created by this push, on approval. */
|
|
641
|
+
readonly createdTarget: boolean;
|
|
621
642
|
}
|
|
622
643
|
declare function runPush(options: PushOptions): Promise<PushResult>;
|
|
623
644
|
declare function renderPush(result: PushResult): string[];
|