speckeeper 0.11.0 → 0.11.1
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/cli.js +190 -1
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,6 @@ import { readFileSync, existsSync, writeFileSync, mkdirSync, readdirSync, statSy
|
|
|
4
4
|
import { dirname, join, resolve, basename, isAbsolute } from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import { Command } from 'commander';
|
|
7
|
-
import { isOptionActive, derivePolicy } from 'cli-contracts/policy';
|
|
8
7
|
import chalk4 from 'chalk';
|
|
9
8
|
import { stringify, parse } from 'yaml';
|
|
10
9
|
import 'crypto';
|
|
@@ -536,6 +535,196 @@ var init_dsl = __esm({
|
|
|
536
535
|
init_workflows();
|
|
537
536
|
}
|
|
538
537
|
});
|
|
538
|
+
|
|
539
|
+
// src/generated/policy-runtime.ts
|
|
540
|
+
var RISK_ORDER = {
|
|
541
|
+
low: 0,
|
|
542
|
+
medium: 1,
|
|
543
|
+
high: 2,
|
|
544
|
+
critical: 3
|
|
545
|
+
};
|
|
546
|
+
function maxRiskLevel(...levels) {
|
|
547
|
+
let max = "low";
|
|
548
|
+
for (const level of levels) {
|
|
549
|
+
if (RISK_ORDER[level] > RISK_ORDER[max]) {
|
|
550
|
+
max = level;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return max;
|
|
554
|
+
}
|
|
555
|
+
function isOptionActive(definition, value, specified) {
|
|
556
|
+
const schemaType = definition.schema?.type;
|
|
557
|
+
if (schemaType === "boolean") {
|
|
558
|
+
return value === true;
|
|
559
|
+
}
|
|
560
|
+
if (definition.repeatable) {
|
|
561
|
+
return specified && Array.isArray(value) && value.length > 0;
|
|
562
|
+
}
|
|
563
|
+
return specified && value != null;
|
|
564
|
+
}
|
|
565
|
+
function derivePolicy(input) {
|
|
566
|
+
const sideEffects = /* @__PURE__ */ new Set();
|
|
567
|
+
const reads = [];
|
|
568
|
+
const writes = [];
|
|
569
|
+
const networkEffects = [];
|
|
570
|
+
const riskLevels = [];
|
|
571
|
+
let executionMode;
|
|
572
|
+
let explicitConfirmation;
|
|
573
|
+
if (input.commandEffects) {
|
|
574
|
+
const ce = input.commandEffects;
|
|
575
|
+
riskLevels.push(ce.riskLevel ?? "low");
|
|
576
|
+
if (ce.writes) {
|
|
577
|
+
sideEffects.add("file_write");
|
|
578
|
+
for (const w of ce.writes) {
|
|
579
|
+
writes.push({
|
|
580
|
+
kind: "semantic",
|
|
581
|
+
target: w.target,
|
|
582
|
+
description: w.description,
|
|
583
|
+
overwrite: w.overwrite,
|
|
584
|
+
destructive: w.destructive,
|
|
585
|
+
...w.idempotent !== void 0 ? { idempotent: w.idempotent } : {},
|
|
586
|
+
...w.idempotencyKey ? { idempotencyKey: w.idempotencyKey } : {},
|
|
587
|
+
...w.idempotentNote ? { idempotentNote: w.idempotentNote } : {},
|
|
588
|
+
source: `command:${input.commandId}`
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
if (ce.reads) {
|
|
593
|
+
for (const r of ce.reads) {
|
|
594
|
+
reads.push({
|
|
595
|
+
kind: "semantic",
|
|
596
|
+
target: r.target,
|
|
597
|
+
description: r.description,
|
|
598
|
+
source: `command:${input.commandId}`
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
if (ce.network) {
|
|
603
|
+
sideEffects.add("network");
|
|
604
|
+
if (typeof ce.network === "object") {
|
|
605
|
+
networkEffects.push({
|
|
606
|
+
...ce.network.description ? { description: ce.network.description } : {},
|
|
607
|
+
...ce.network.domains ? { domains: ce.network.domains } : {},
|
|
608
|
+
...ce.network.idempotent !== void 0 ? { idempotent: ce.network.idempotent } : {},
|
|
609
|
+
...ce.network.idempotencyKey ? { idempotencyKey: ce.network.idempotencyKey } : {},
|
|
610
|
+
...ce.network.idempotentNote ? { idempotentNote: ce.network.idempotentNote } : {},
|
|
611
|
+
source: `command:${input.commandId}`
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
if (ce.executionMode) {
|
|
616
|
+
executionMode = ce.executionMode;
|
|
617
|
+
}
|
|
618
|
+
if (ce.requiresConfirmation !== void 0) {
|
|
619
|
+
explicitConfirmation = ce.requiresConfirmation;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
for (const [optName, optInput] of Object.entries(input.options)) {
|
|
623
|
+
const { definition, value, specified } = optInput;
|
|
624
|
+
const active = isOptionActive(definition, value, specified);
|
|
625
|
+
if (!active) continue;
|
|
626
|
+
if (definition.file) {
|
|
627
|
+
const filePath = typeof value === "string" ? value : void 0;
|
|
628
|
+
const mode = definition.file.mode;
|
|
629
|
+
if (mode === "read" || mode === "readWrite") {
|
|
630
|
+
reads.push({
|
|
631
|
+
kind: "option-file",
|
|
632
|
+
option: optName,
|
|
633
|
+
path: filePath,
|
|
634
|
+
source: `option:${optName}`
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
if (mode === "write" || mode === "append" || mode === "readWrite") {
|
|
638
|
+
sideEffects.add("file_write");
|
|
639
|
+
writes.push({
|
|
640
|
+
kind: "option-file",
|
|
641
|
+
option: optName,
|
|
642
|
+
path: filePath,
|
|
643
|
+
mode,
|
|
644
|
+
source: `option:${optName}`
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
if (definition.effects) {
|
|
649
|
+
const eff = definition.effects;
|
|
650
|
+
riskLevels.push(eff.riskLevel ?? "low");
|
|
651
|
+
if (eff.writes) {
|
|
652
|
+
sideEffects.add("file_write");
|
|
653
|
+
for (const w of eff.writes) {
|
|
654
|
+
writes.push({
|
|
655
|
+
kind: "semantic",
|
|
656
|
+
target: w.target,
|
|
657
|
+
description: w.description,
|
|
658
|
+
overwrite: w.overwrite,
|
|
659
|
+
destructive: w.destructive,
|
|
660
|
+
...w.idempotent !== void 0 ? { idempotent: w.idempotent } : {},
|
|
661
|
+
...w.idempotencyKey ? { idempotencyKey: w.idempotencyKey } : {},
|
|
662
|
+
...w.idempotentNote ? { idempotentNote: w.idempotentNote } : {},
|
|
663
|
+
source: `option:${optName}`
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
if (eff.reads) {
|
|
668
|
+
for (const r of eff.reads) {
|
|
669
|
+
reads.push({
|
|
670
|
+
kind: "semantic",
|
|
671
|
+
target: r.target,
|
|
672
|
+
description: r.description,
|
|
673
|
+
source: `option:${optName}`
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (eff.network) {
|
|
678
|
+
sideEffects.add("network");
|
|
679
|
+
if (typeof eff.network === "object") {
|
|
680
|
+
networkEffects.push({
|
|
681
|
+
...eff.network.description ? { description: eff.network.description } : {},
|
|
682
|
+
...eff.network.domains ? { domains: eff.network.domains } : {},
|
|
683
|
+
...eff.network.idempotent !== void 0 ? { idempotent: eff.network.idempotent } : {},
|
|
684
|
+
...eff.network.idempotencyKey ? { idempotencyKey: eff.network.idempotencyKey } : {},
|
|
685
|
+
...eff.network.idempotentNote ? { idempotentNote: eff.network.idempotentNote } : {},
|
|
686
|
+
source: `option:${optName}`
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
if (eff.executionMode && !executionMode) {
|
|
691
|
+
executionMode = eff.executionMode;
|
|
692
|
+
}
|
|
693
|
+
if (eff.requiresConfirmation !== void 0 && explicitConfirmation === void 0) {
|
|
694
|
+
explicitConfirmation = eff.requiresConfirmation;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
const finalRiskLevel = riskLevels.length > 0 ? maxRiskLevel(...riskLevels) : "low";
|
|
699
|
+
const requiresConfirmation = explicitConfirmation ?? (finalRiskLevel === "high" || finalRiskLevel === "critical");
|
|
700
|
+
let requiresSecrets;
|
|
701
|
+
if (input.env) {
|
|
702
|
+
const secrets = [];
|
|
703
|
+
for (const [envName, envVar] of Object.entries(input.env)) {
|
|
704
|
+
if (envVar.sensitive) {
|
|
705
|
+
secrets.push(envName);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
if (secrets.length > 0) {
|
|
709
|
+
requiresSecrets = secrets;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
const semanticWrites = writes.filter((w) => w.kind === "semantic");
|
|
713
|
+
const idempotent = semanticWrites.every((w) => w.idempotent === true) && networkEffects.every((n) => n.idempotent === true);
|
|
714
|
+
return {
|
|
715
|
+
riskLevel: finalRiskLevel,
|
|
716
|
+
requiresConfirmation,
|
|
717
|
+
idempotent,
|
|
718
|
+
sideEffects: [...sideEffects],
|
|
719
|
+
reads,
|
|
720
|
+
writes,
|
|
721
|
+
...networkEffects.length > 0 ? { network: networkEffects } : {},
|
|
722
|
+
...executionMode ? { executionMode } : {},
|
|
723
|
+
...requiresSecrets ? { requiresSecrets } : {}
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// src/generated/policy.ts
|
|
539
728
|
var commandDefinitions = {
|
|
540
729
|
"init": {
|
|
541
730
|
"effects": {
|