@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.d.cts CHANGED
@@ -1,14 +1,15 @@
1
1
  import * as citty from 'citty';
2
- import { Sink, Provider, ParameterRef, Scope, RotationMechanism, RotationState } from '@penvhq/core';
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 write-only sink makes most of what doctor can say the second kind.
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" | "sink-unreachable" | "sink-name-drift" | "sink-manual-edit" | "sink-value-drift";
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
- /** Injected in tests: the sink to check against. Defaults to the one the config declares. */
31
- readonly sink?: Sink;
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 `sink`, for the same reason — the drift checks stay driveable without
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
- /** Injected in tests: the sink to push to. Defaults to the one the config declares. */
608
- readonly sink?: Sink;
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 `owner/repo` targeted, when the config named one. */
615
- readonly repo: string | undefined;
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 { Sink, Provider, ParameterRef, Scope, RotationMechanism, RotationState } from '@penvhq/core';
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 write-only sink makes most of what doctor can say the second kind.
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" | "sink-unreachable" | "sink-name-drift" | "sink-manual-edit" | "sink-value-drift";
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
- /** Injected in tests: the sink to check against. Defaults to the one the config declares. */
31
- readonly sink?: Sink;
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 `sink`, for the same reason — the drift checks stay driveable without
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
- /** Injected in tests: the sink to push to. Defaults to the one the config declares. */
608
- readonly sink?: Sink;
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 `owner/repo` targeted, when the config named one. */
615
- readonly repo: string | undefined;
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[];