@gjermundgaraba/upup 0.5.1 → 0.5.2
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/README.md +2 -0
- package/dist/{Tui-DV_6wbrQ.mjs → Tui-Ri-yz-Sx.mjs} +58 -25
- package/dist/grep-worker.mjs +3 -16
- package/dist/{io-ns6xhFdF.mjs → io-Dgi-IiVu.mjs} +11 -1
- package/dist/main.mjs +489 -511
- package/native/dist/upup-sparkle.json +1 -1
- package/native/dist/upup-sparkle.zip +0 -0
- package/package.json +1 -1
package/dist/main.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as
|
|
2
|
+
import { i as reason, n as decodeUtf8, r as openFlags, t as byName } from "./io-Dgi-IiVu.mjs";
|
|
3
3
|
import { findPackageJSON } from "node:module";
|
|
4
4
|
import { NodeRuntime, NodeServices, NodeStdio } from "@effect/platform-node";
|
|
5
5
|
import { Cause, Clock, Config, Context, Data, Deferred, Duration, Effect, Equal, Exit, Fiber, FiberHandle, FiberSet, FileSystem, Layer, Option, Predicate, Queue, Ref, Result, Schedule, Schema, Semaphore, Stream, SubscriptionRef, identity } from "effect";
|
|
@@ -19,6 +19,7 @@ import lockfile from "proper-lockfile";
|
|
|
19
19
|
import { BACKGROUND_CONTEXT, withAbortSignal } from "@earendil-works/chord/context";
|
|
20
20
|
import { GenerationTask, Harness, LiveDoc, ROOT_CONVERSATION_ID, ToolTask, createRegistry, defineDoc, defineExtension, defineTool, hook, section } from "@earendil-works/pi-durable";
|
|
21
21
|
import { openNodeSqliteStorage } from "@earendil-works/pi-durable/storage/sqlite/node";
|
|
22
|
+
import { absurd, constVoid } from "effect/Function";
|
|
22
23
|
import { ChildProcess, ChildProcessSpawner, CommandLine } from "effect/process";
|
|
23
24
|
import { Worker } from "node:worker_threads";
|
|
24
25
|
import semver from "semver";
|
|
@@ -33,7 +34,6 @@ import { bundleFromJSON, isBundleWithDsseEnvelope } from "@sigstore/bundle";
|
|
|
33
34
|
import { getTrustedRoot } from "@sigstore/tuf";
|
|
34
35
|
import { Verifier, toSignedEntity, toTrustMaterial } from "@sigstore/verify";
|
|
35
36
|
import { isDeepStrictEqual } from "node:util";
|
|
36
|
-
import { constVoid } from "effect/Function";
|
|
37
37
|
import { applyEdits, modify, parse as parse$1 } from "jsonc-parser";
|
|
38
38
|
import { getStaticTOMLValue, parseTOML, traverseNodes } from "toml-eslint-parser";
|
|
39
39
|
import { XMLParser } from "fast-xml-parser";
|
|
@@ -41,7 +41,7 @@ import * as ActionMcp from "@gjermundgaraba/effect-actions/ActionMcp";
|
|
|
41
41
|
import * as Action from "@gjermundgaraba/effect-actions/Action";
|
|
42
42
|
import { setup, types } from "xstate/fsm";
|
|
43
43
|
// package.json
|
|
44
|
-
var version$1 = "0.5.
|
|
44
|
+
var version$1 = "0.5.2";
|
|
45
45
|
// src/ai/Setup.ts
|
|
46
46
|
const Thinking = Schema.Literals([
|
|
47
47
|
"off",
|
|
@@ -427,13 +427,15 @@ const withTarget = (pkg, target) => ({
|
|
|
427
427
|
const isUnaudited = Schema.is(UnauditedEcosystem);
|
|
428
428
|
const isApp$1 = Schema.is(AppEcosystem);
|
|
429
429
|
const isRuntime = Schema.is(RuntimeEcosystem);
|
|
430
|
+
const isOs = Schema.is(OsEcosystem);
|
|
430
431
|
const isUnauditedUpdate = (pkg) => isUnaudited(pkg.ecosystem);
|
|
431
432
|
const isAppUpdate = (pkg) => isApp$1(pkg.ecosystem);
|
|
432
|
-
const
|
|
433
|
-
if (isApp$1(
|
|
434
|
-
if (isRuntime(
|
|
435
|
-
|
|
433
|
+
const ecosystemKind = (ecosystem) => {
|
|
434
|
+
if (isApp$1(ecosystem)) return "app";
|
|
435
|
+
if (isRuntime(ecosystem)) return "runtime";
|
|
436
|
+
return isOs(ecosystem) ? "os" : absurd(ecosystem);
|
|
436
437
|
};
|
|
438
|
+
const unauditedKind = (pkg) => isUnaudited(pkg.ecosystem) ? ecosystemKind(pkg.ecosystem) : void 0;
|
|
437
439
|
// src/inventory/Provider.ts
|
|
438
440
|
var OutputMalformed = class extends Schema.TaggedError()("OutputMalformed", {
|
|
439
441
|
command: Schema.String,
|
|
@@ -559,7 +561,8 @@ const layer$6 = Layer.effect(Exec, Effect.gen(function* () {
|
|
|
559
561
|
const nodeLayer = layer$6.pipe(Layer.provide(NodeServices.layer));
|
|
560
562
|
// src/brew/Brew.ts
|
|
561
563
|
const caskPrefix = "cask:";
|
|
562
|
-
const
|
|
564
|
+
const Kind = Schema.Literals(["formula", "cask"]);
|
|
565
|
+
const kindOf$2 = (pkg) => pkg.id.startsWith(caskPrefix) ? "cask" : "formula";
|
|
563
566
|
const Keg = Schema.Struct({
|
|
564
567
|
version: Schema.String,
|
|
565
568
|
installed_on_request: Schema.Boolean,
|
|
@@ -603,13 +606,12 @@ const Outdated$1 = Schema.Struct({
|
|
|
603
606
|
formulae: Schema.Array(OutdatedEntry),
|
|
604
607
|
casks: Schema.Array(OutdatedEntry)
|
|
605
608
|
});
|
|
606
|
-
const brew
|
|
609
|
+
const brew = (args, refreshMetadata = false) => ({
|
|
607
610
|
command: "brew",
|
|
608
611
|
args,
|
|
609
612
|
cwd: "/",
|
|
610
613
|
env: refreshMetadata ? {} : { HOMEBREW_NO_AUTO_UPDATE: "1" }
|
|
611
614
|
});
|
|
612
|
-
const kindOf$2 = (pkg) => pkg.id.startsWith("cask:") ? "cask" : "formula";
|
|
613
615
|
const activeKeg = (formula) => formula.installed.find((keg) => keg.version === formula.linked_keg) ?? formula.installed.at(-1);
|
|
614
616
|
const describedAs = (desc) => desc === void 0 || desc === null || desc === "" ? {} : { description: desc };
|
|
615
617
|
const packages = (installed, outdated) => {
|
|
@@ -656,19 +658,19 @@ const make$14 = Effect.gen(function* () {
|
|
|
656
658
|
const exec = yield* Exec;
|
|
657
659
|
const json = (schema, invocation) => exec.stdout(invocation).pipe(Effect.flatMap(decodeJson(schema, commandLine(invocation))));
|
|
658
660
|
const list = Effect.gen(function* () {
|
|
659
|
-
const installed = yield* json(Installed, brew
|
|
661
|
+
const installed = yield* json(Installed, brew([
|
|
660
662
|
"info",
|
|
661
663
|
"--json=v2",
|
|
662
664
|
"--installed"
|
|
663
665
|
]));
|
|
664
|
-
const outdated = yield* json(Outdated$1, brew
|
|
666
|
+
const outdated = yield* json(Outdated$1, brew(["outdated", "--json=v2"], true));
|
|
665
667
|
return {
|
|
666
668
|
packages: packages(installed, outdated),
|
|
667
669
|
notices: []
|
|
668
670
|
};
|
|
669
671
|
}).pipe(Effect.withSpan("Brew.list"));
|
|
670
672
|
const observe = Effect.fn("Brew.observe")(function* (pkg) {
|
|
671
|
-
const installed = yield* json(Installed, brew
|
|
673
|
+
const installed = yield* json(Installed, brew([
|
|
672
674
|
"info",
|
|
673
675
|
"--json=v2",
|
|
674
676
|
`--${kindOf$2(pkg)}`,
|
|
@@ -681,7 +683,7 @@ const make$14 = Effect.gen(function* () {
|
|
|
681
683
|
return Option.fromUndefinedOr(observed.find((candidate) => candidate.id === pkg.id));
|
|
682
684
|
});
|
|
683
685
|
const offered = Effect.fn("Brew.offered")(function* (pkg) {
|
|
684
|
-
const invocation = brew
|
|
686
|
+
const invocation = brew([
|
|
685
687
|
"outdated",
|
|
686
688
|
"--json=v2",
|
|
687
689
|
`--${kindOf$2(pkg)}`,
|
|
@@ -709,14 +711,14 @@ const make$14 = Effect.gen(function* () {
|
|
|
709
711
|
expected: target,
|
|
710
712
|
...now === void 0 ? {} : { offered: now }
|
|
711
713
|
});
|
|
712
|
-
yield* exec.stdout(brew
|
|
714
|
+
yield* exec.stdout(brew([
|
|
713
715
|
"upgrade",
|
|
714
716
|
`--${kindOf$2(pkg)}`,
|
|
715
717
|
pkg.name
|
|
716
718
|
]));
|
|
717
719
|
}),
|
|
718
720
|
uninstall: Effect.fn("Brew.uninstall")(function* (pkg) {
|
|
719
|
-
yield* exec.stdout(brew
|
|
721
|
+
yield* exec.stdout(brew([
|
|
720
722
|
"uninstall",
|
|
721
723
|
`--${kindOf$2(pkg)}`,
|
|
722
724
|
pkg.name
|
|
@@ -761,65 +763,88 @@ const Report = Schema.Struct({
|
|
|
761
763
|
findings: Schema.Array(Finding),
|
|
762
764
|
unverified: Schema.Array(Schema.String).annotate({ description: "Each thing you could not verify." })
|
|
763
765
|
});
|
|
766
|
+
const Context$1 = Schema.TaggedUnion({
|
|
767
|
+
None: {},
|
|
768
|
+
Brew: { kind: Kind },
|
|
769
|
+
Python: { python: Schema.String },
|
|
770
|
+
Revision: { revision: Schema.String }
|
|
771
|
+
});
|
|
772
|
+
const sameContext = Schema.toEquivalence(Context$1);
|
|
764
773
|
Schema.Struct({
|
|
765
774
|
mode: Mode,
|
|
766
775
|
delta: Delta,
|
|
767
|
-
context:
|
|
776
|
+
context: Context$1
|
|
768
777
|
});
|
|
769
778
|
var ChangesUnavailable = class extends Schema.TaggedError()("ChangesUnavailable", { issue: Schema.String }) {};
|
|
770
779
|
const isRegistry = Schema.is(RegistryEcosystem);
|
|
771
|
-
const deltaOf = (pkg) => pkg.target === void 0 || !isRegistry(pkg.ecosystem) ? void 0 : {
|
|
772
|
-
ecosystem: pkg.ecosystem,
|
|
773
|
-
artifact: pkg.artifact,
|
|
774
|
-
from: pkg.current,
|
|
775
|
-
to: pkg.target
|
|
776
|
-
};
|
|
777
780
|
const contextOf = (pkg) => {
|
|
778
|
-
if (pkg.ecosystem === "brew") return {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
781
|
+
if (pkg.ecosystem === "brew") return {
|
|
782
|
+
_tag: "Brew",
|
|
783
|
+
kind: kindOf$2(pkg)
|
|
784
|
+
};
|
|
785
|
+
if (pkg.ecosystem === "pypi" && pkg.runtime !== void 0) return {
|
|
786
|
+
_tag: "Python",
|
|
787
|
+
python: pkg.runtime
|
|
788
|
+
};
|
|
789
|
+
if (pkg.ecosystem === "github-actions" && pkg.revision !== void 0) return {
|
|
790
|
+
_tag: "Revision",
|
|
791
|
+
revision: pkg.revision
|
|
792
|
+
};
|
|
793
|
+
return { _tag: "None" };
|
|
782
794
|
};
|
|
783
|
-
const
|
|
795
|
+
const unauditedReasons = {
|
|
796
|
+
app: "an app update",
|
|
797
|
+
runtime: "a Node.js runtime version",
|
|
798
|
+
os: "an operating-system update"
|
|
799
|
+
};
|
|
800
|
+
const registryOf = (pkg) => {
|
|
801
|
+
if (!isRegistry(pkg.ecosystem)) return Result.fail(`it is ${unauditedReasons[ecosystemKind(pkg.ecosystem)]}, which upup does not audit`);
|
|
802
|
+
return pkg.privateRegistry === void 0 ? Result.succeed(pkg.ecosystem) : Result.fail(`it comes from the private registry ${pkg.privateRegistry}, which upup does not audit`);
|
|
803
|
+
};
|
|
804
|
+
const deltaOf = (pkg) => {
|
|
805
|
+
const { target } = pkg;
|
|
806
|
+
return target === void 0 ? Result.fail("no update is offered") : Result.map(registryOf(pkg), (ecosystem) => ({
|
|
807
|
+
ecosystem,
|
|
808
|
+
artifact: pkg.artifact,
|
|
809
|
+
from: pkg.current,
|
|
810
|
+
to: target
|
|
811
|
+
}));
|
|
812
|
+
};
|
|
813
|
+
const auditOf = (pkg, mode) => Result.map(deltaOf(pkg), (delta) => ({
|
|
814
|
+
mode,
|
|
815
|
+
delta,
|
|
816
|
+
context: contextOf(pkg)
|
|
817
|
+
}));
|
|
818
|
+
const identityOf = (pkg, mode) => Result.getOrUndefined(auditOf(pkg, mode));
|
|
819
|
+
const unauditable = (pkg) => Result.getOrUndefined(Result.flip(deltaOf(pkg)));
|
|
820
|
+
const landingOf = (pkg, mode) => Result.getOrUndefined(Result.map(registryOf(pkg), (ecosystem) => ({
|
|
784
821
|
mode,
|
|
785
|
-
ecosystem
|
|
822
|
+
ecosystem,
|
|
786
823
|
artifact: pkg.artifact,
|
|
787
824
|
version: pkg.current,
|
|
788
825
|
context: contextOf(pkg)
|
|
789
|
-
}
|
|
826
|
+
})));
|
|
827
|
+
const landingAt = (identity) => ({
|
|
828
|
+
mode: identity.mode,
|
|
829
|
+
ecosystem: identity.delta.ecosystem,
|
|
830
|
+
artifact: identity.delta.artifact,
|
|
831
|
+
version: identity.delta.to,
|
|
832
|
+
context: identity.context
|
|
833
|
+
});
|
|
790
834
|
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
|
|
791
835
|
const landingKey = (landing) => sha256(JSON.stringify([
|
|
792
836
|
landing.ecosystem,
|
|
793
837
|
landing.artifact,
|
|
794
838
|
landing.version,
|
|
795
|
-
|
|
839
|
+
landing.context
|
|
796
840
|
]));
|
|
797
|
-
const unauditedReasons = {
|
|
798
|
-
app: "an app update",
|
|
799
|
-
runtime: "a Node.js runtime version",
|
|
800
|
-
os: "an operating-system update"
|
|
801
|
-
};
|
|
802
|
-
const unauditable = (pkg) => {
|
|
803
|
-
if (pkg.target === void 0) return "no update is offered";
|
|
804
|
-
const kind = unauditedKind(pkg);
|
|
805
|
-
if (kind !== void 0) return `it is ${unauditedReasons[kind]}, which upup does not audit`;
|
|
806
|
-
return pkg.privateRegistry === void 0 ? void 0 : `it comes from the private registry ${pkg.privateRegistry}, which upup does not audit`;
|
|
807
|
-
};
|
|
808
|
-
const identityOf = (pkg, mode) => {
|
|
809
|
-
const delta = deltaOf(pkg);
|
|
810
|
-
return delta === void 0 || pkg.privateRegistry !== void 0 ? void 0 : {
|
|
811
|
-
mode,
|
|
812
|
-
delta,
|
|
813
|
-
context: contextOf(pkg)
|
|
814
|
-
};
|
|
815
|
-
};
|
|
816
841
|
const deltaKey = (delta) => sha256(JSON.stringify([
|
|
817
842
|
delta.ecosystem,
|
|
818
843
|
delta.artifact,
|
|
819
844
|
delta.from,
|
|
820
845
|
delta.to
|
|
821
846
|
]));
|
|
822
|
-
const workspaceKey = (identity) => sha256(JSON.stringify([deltaKey(identity.delta),
|
|
847
|
+
const workspaceKey = (identity) => sha256(JSON.stringify([deltaKey(identity.delta), identity.context]));
|
|
823
848
|
// src/audit/tools.ts
|
|
824
849
|
const limits$1 = {
|
|
825
850
|
resultBytes: 262144,
|
|
@@ -832,16 +857,6 @@ const limits$1 = {
|
|
|
832
857
|
longLineMatches: 1025
|
|
833
858
|
};
|
|
834
859
|
const grepTimeoutMs = 3e4;
|
|
835
|
-
const names$1 = {
|
|
836
|
-
read: "read",
|
|
837
|
-
grep: "grep",
|
|
838
|
-
list: "list"
|
|
839
|
-
};
|
|
840
|
-
const descriptions = {
|
|
841
|
-
read: "Read a bounded byte range from one regular UTF-8 file.",
|
|
842
|
-
grep: "Find a JavaScript regular expression in UTF-8 regular files below a path. Each line is matched whole. Lines over 1 KiB show a bounded window around each match with its file byte offset; a file stops at a line over 16 MiB.",
|
|
843
|
-
list: "List workspace entries below a directory to a bounded depth."
|
|
844
|
-
};
|
|
845
860
|
const count$1 = (maximum) => Schema.Number.pipe(Schema.check(Schema.isInt(), Schema.isBetween({
|
|
846
861
|
minimum: 1,
|
|
847
862
|
maximum
|
|
@@ -894,7 +909,6 @@ const respond = async (signal, run) => {
|
|
|
894
909
|
const checkPath = (name) => {
|
|
895
910
|
if (!(name === "." || name !== "" && !name.includes("\\") && !name.includes("\0") && name.split("/").every((segment) => segment !== "" && segment !== "." && segment !== ".."))) fail$1(`path ${JSON.stringify(name)} is not workspace-relative`);
|
|
896
911
|
};
|
|
897
|
-
const isCount = (value, min, max) => Number.isSafeInteger(value) && value >= min && value <= max;
|
|
898
912
|
const kindOf$1 = (info) => {
|
|
899
913
|
if (info.isFile()) return "file";
|
|
900
914
|
return info.isDirectory() ? "directory" : "other";
|
|
@@ -930,20 +944,9 @@ const trimIncompleteUtf8 = (data) => {
|
|
|
930
944
|
return data;
|
|
931
945
|
}
|
|
932
946
|
};
|
|
933
|
-
const decodeUtf8 = (data) => {
|
|
934
|
-
try {
|
|
935
|
-
return new TextDecoder("utf-8", {
|
|
936
|
-
fatal: true,
|
|
937
|
-
ignoreBOM: true
|
|
938
|
-
}).decode(data);
|
|
939
|
-
} catch {
|
|
940
|
-
return;
|
|
941
|
-
}
|
|
942
|
-
};
|
|
943
947
|
const read$2 = async (workspace, args, signal) => await respond(signal, async () => {
|
|
944
948
|
const name = args.path;
|
|
945
949
|
checkPath(name);
|
|
946
|
-
if (!isCount(args.offset, 0, Number.MAX_SAFE_INTEGER) || !isCount(args.limit, 1, limits$1.readBytes)) fail$1("offset or limit is outside the allowed range");
|
|
947
950
|
const located = await locate$4(workspace, name, `open ${name}`);
|
|
948
951
|
if (located.kind !== "file") fail$1("path is not a regular file");
|
|
949
952
|
signal?.throwIfAborted();
|
|
@@ -977,7 +980,6 @@ const read$2 = async (workspace, args, signal) => await respond(signal, async ()
|
|
|
977
980
|
});
|
|
978
981
|
const list = async (workspace, args, signal) => await respond(signal, async () => {
|
|
979
982
|
checkPath(args.path);
|
|
980
|
-
if (!isCount(args.depth, 1, limits$1.listDepth)) fail$1("depth is outside the allowed range");
|
|
981
983
|
const located = await locate$4(workspace, args.path, `list workspace: walk ${args.path}`);
|
|
982
984
|
if (located.kind !== "directory") return "no entries";
|
|
983
985
|
let result = "";
|
|
@@ -1062,15 +1064,29 @@ const ends = (offset, limit) => {
|
|
|
1062
1064
|
const [from, to] = [span(offset), span(offset + limit)];
|
|
1063
1065
|
return from === to ? `${from} +${span(limit)}` : `${from}–${to}`;
|
|
1064
1066
|
};
|
|
1067
|
+
const tool = (description, Args, run, detail) => {
|
|
1068
|
+
const decode = Schema.decodeUnknownSync(Args);
|
|
1069
|
+
return {
|
|
1070
|
+
description,
|
|
1071
|
+
Args,
|
|
1072
|
+
call: async (workspace, args, signal) => await run(workspace, decode(args), signal),
|
|
1073
|
+
detail
|
|
1074
|
+
};
|
|
1075
|
+
};
|
|
1076
|
+
const tools$3 = {
|
|
1077
|
+
read: tool("Read a bounded byte range from one regular UTF-8 file.", ReadArgs, read$2, ({ path: shown, range }) => `${shown}${range}`),
|
|
1078
|
+
grep: tool("Find a JavaScript regular expression in UTF-8 regular files below a path. Each line is matched whole. Lines over 1 KiB show a bounded window around each match with its file byte offset; a file stops at a line over 16 MiB.", GrepArgs, async (workspace, args, signal) => await grep(workspace, args, signal === void 0 ? {} : { signal }), ({ path: shown, pattern }) => `${pattern} ${shown}`),
|
|
1079
|
+
list: tool("List workspace entries below a directory to a bounded depth.", ListArgs, list, ({ path: shown }) => shown)
|
|
1080
|
+
};
|
|
1081
|
+
const isTool = (name) => Object.hasOwn(tools$3, name);
|
|
1065
1082
|
const describeCall = (name, args) => {
|
|
1066
|
-
if (!Predicate.isObject(args)) return name;
|
|
1083
|
+
if (!Predicate.isObject(args) || !isTool(name)) return name;
|
|
1067
1084
|
const { path: target, pattern, offset, limit } = args;
|
|
1068
|
-
const
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
else if (name === names$1.grep) detail = `${Predicate.isString(pattern) ? pattern : ""} ${shownPath}`;
|
|
1085
|
+
const detail = tools$3[name].detail({
|
|
1086
|
+
path: Predicate.isString(target) ? target : "",
|
|
1087
|
+
pattern: Predicate.isString(pattern) ? pattern : "",
|
|
1088
|
+
range: Predicate.isNumber(offset) && Predicate.isNumber(limit) ? ` bytes ${ends(offset, limit)}` : ""
|
|
1089
|
+
});
|
|
1074
1090
|
return detail === "" ? name : `${name} ${detail}`;
|
|
1075
1091
|
};
|
|
1076
1092
|
// src/audit/hashed-names.ts
|
|
@@ -1728,7 +1744,7 @@ const Meta = Schema.Struct({
|
|
|
1728
1744
|
ecosystem: Delta.fields.ecosystem,
|
|
1729
1745
|
from: Schema.String,
|
|
1730
1746
|
to: Schema.String,
|
|
1731
|
-
context:
|
|
1747
|
+
context: Context$1,
|
|
1732
1748
|
evidence: Grade,
|
|
1733
1749
|
evidence_detail: Schema.String,
|
|
1734
1750
|
preparation_key: Schema.String
|
|
@@ -1739,7 +1755,7 @@ const failed$1 = (workspace) => (cause) => new WorkspaceFailed({
|
|
|
1739
1755
|
issue: cause instanceof Error ? cause.message : String(cause)
|
|
1740
1756
|
});
|
|
1741
1757
|
const listed$2 = async (workspace, name) => await readFile(path.join(workspace, name), "utf-8").catch(() => void 0);
|
|
1742
|
-
const write = (workspace, identity, diff, evidence, detail, preparationKey) => Effect.tryPromise({
|
|
1758
|
+
const write = (workspace, identity, { diff, evidence, detail }, preparationKey) => Effect.tryPromise({
|
|
1743
1759
|
try: async () => {
|
|
1744
1760
|
await writeFile(path.join(workspace, files.diff), diff, { mode: 384 });
|
|
1745
1761
|
await writeFile(path.join(workspace, files.index), buildIndex(diff), { mode: 384 });
|
|
@@ -1762,7 +1778,6 @@ const readMeta = (workspace) => Effect.tryPromise({
|
|
|
1762
1778
|
try: async () => await readFile(path.join(workspace, files.meta), "utf-8"),
|
|
1763
1779
|
catch: failed$1(workspace)
|
|
1764
1780
|
}).pipe(Effect.flatMap((text) => Schema.decodeEffect(MetaJson)(text).pipe(Effect.mapError(failed$1(workspace)))));
|
|
1765
|
-
const sameContext = (left, right) => JSON.stringify(Object.entries(left).toSorted(([a], [b]) => a.localeCompare(b))) === JSON.stringify(Object.entries(right).toSorted(([a], [b]) => a.localeCompare(b)));
|
|
1766
1781
|
const describes = (meta, identity) => meta.name === identity.delta.artifact && meta.ecosystem === identity.delta.ecosystem && meta.from === identity.delta.from && meta.to === identity.delta.to && sameContext(meta.context, identity.context);
|
|
1767
1782
|
const readable = (workspace, identity) => readMeta(workspace).pipe(Effect.flatMap((meta) => describes(meta, identity) ? Effect.promise(async () => await stat(path.join(workspace, files.diff)).then(() => true, () => false)) : Effect.succeed(false)), Effect.orElseSucceed(() => false));
|
|
1768
1783
|
const prune = (workspace) => Effect.promise(async () => {
|
|
@@ -1906,7 +1921,7 @@ const Brief = Schema.Struct({
|
|
|
1906
1921
|
artifact: Schema.String,
|
|
1907
1922
|
from: Schema.String,
|
|
1908
1923
|
to: Schema.String,
|
|
1909
|
-
context:
|
|
1924
|
+
context: Context$1,
|
|
1910
1925
|
workspace: Schema.String,
|
|
1911
1926
|
evidence: Grade,
|
|
1912
1927
|
evidenceDetail: Schema.String,
|
|
@@ -1927,9 +1942,6 @@ const BriefDoc = defineDoc({
|
|
|
1927
1942
|
checkpointWhen: () => false
|
|
1928
1943
|
});
|
|
1929
1944
|
const parameters = (schema) => Schema.toJsonSchemaDocument(schema).schema;
|
|
1930
|
-
const decodeRead = Schema.decodeUnknownSync(ReadArgs);
|
|
1931
|
-
const decodeGrep = Schema.decodeUnknownSync(GrepArgs);
|
|
1932
|
-
const decodeList = Schema.decodeUnknownSync(ListArgs);
|
|
1933
1945
|
const decodeSubmitted = Schema.decodeUnknownSync(Report);
|
|
1934
1946
|
const encodeReport = (submitted) => ({
|
|
1935
1947
|
...submitted,
|
|
@@ -1959,27 +1971,13 @@ const answer = (result) => {
|
|
|
1959
1971
|
const auditExtension = (workspace) => {
|
|
1960
1972
|
let steps = 0;
|
|
1961
1973
|
let nudged = false;
|
|
1962
|
-
const
|
|
1963
|
-
name
|
|
1964
|
-
description:
|
|
1965
|
-
replay: "safe",
|
|
1966
|
-
parameters: parameters(ReadArgs),
|
|
1967
|
-
execute: async (args, _api, invocation) => answer(await read$2(workspace, decodeRead(args), invocation.abortSignal))
|
|
1968
|
-
});
|
|
1969
|
-
const grep$1 = defineTool({
|
|
1970
|
-
name: "grep",
|
|
1971
|
-
description: descriptions.grep,
|
|
1972
|
-
replay: "safe",
|
|
1973
|
-
parameters: parameters(GrepArgs),
|
|
1974
|
-
execute: async (args, _api, invocation) => answer(await grep(workspace, decodeGrep(args), invocation.abortSignal === void 0 ? {} : { signal: invocation.abortSignal }))
|
|
1975
|
-
});
|
|
1976
|
-
const list$1 = defineTool({
|
|
1977
|
-
name: "list",
|
|
1978
|
-
description: descriptions.list,
|
|
1974
|
+
const investigate = Object.entries(tools$3).map(([name, tool]) => defineTool({
|
|
1975
|
+
name,
|
|
1976
|
+
description: tool.description,
|
|
1979
1977
|
replay: "safe",
|
|
1980
|
-
parameters: parameters(
|
|
1981
|
-
execute: async (args, _api, invocation) => answer(await
|
|
1982
|
-
});
|
|
1978
|
+
parameters: parameters(tool.Args),
|
|
1979
|
+
execute: async (args, _api, invocation) => answer(await tool.call(workspace, args, invocation.abortSignal))
|
|
1980
|
+
}));
|
|
1983
1981
|
const submit = defineTool({
|
|
1984
1982
|
name: "submit_report",
|
|
1985
1983
|
description: "Submit the audit report. Call exactly once, when the investigation is done; the audit ends.",
|
|
@@ -1999,12 +1997,7 @@ const auditExtension = (workspace) => {
|
|
|
1999
1997
|
});
|
|
2000
1998
|
return defineExtension({
|
|
2001
1999
|
name: "upup.audit",
|
|
2002
|
-
tools: [
|
|
2003
|
-
read,
|
|
2004
|
-
grep$1,
|
|
2005
|
-
list$1,
|
|
2006
|
-
submit
|
|
2007
|
-
],
|
|
2000
|
+
tools: [...investigate, submit],
|
|
2008
2001
|
sections: [section("audit", () => instructions$1)],
|
|
2009
2002
|
hooks: [hook(GenerationTask, {
|
|
2010
2003
|
beforeRequest: (request) => {
|
|
@@ -2035,17 +2028,15 @@ const policyKey = (prompt, setup) => sha256(JSON.stringify([
|
|
|
2035
2028
|
setup.modelId,
|
|
2036
2029
|
setup.thinking
|
|
2037
2030
|
]));
|
|
2031
|
+
const said = (kind, content) => content.trim() === "" ? [] : [{
|
|
2032
|
+
kind,
|
|
2033
|
+
text: content
|
|
2034
|
+
}];
|
|
2038
2035
|
const entriesOf$1 = (message) => {
|
|
2039
2036
|
if (message.role === "assistant") {
|
|
2040
2037
|
const blocks = message.content.flatMap((block) => {
|
|
2041
|
-
if (block.type === "thinking") return block.thinking
|
|
2042
|
-
|
|
2043
|
-
text: block.thinking
|
|
2044
|
-
}];
|
|
2045
|
-
if (block.type === "text") return block.text.trim() === "" ? [] : [{
|
|
2046
|
-
kind: "text",
|
|
2047
|
-
text: block.text
|
|
2048
|
-
}];
|
|
2038
|
+
if (block.type === "thinking") return said("thinking", block.thinking);
|
|
2039
|
+
if (block.type === "text") return said("text", block.text);
|
|
2049
2040
|
return [{
|
|
2050
2041
|
kind: "tool",
|
|
2051
2042
|
text: describeCall(block.name, block.arguments)
|
|
@@ -2081,14 +2072,8 @@ const decodeLive = Schema.decodeUnknownOption(Schema.Struct({ generation: Schema
|
|
|
2081
2072
|
retry: Schema.optional(Schema.Struct({ error: Schema.String }))
|
|
2082
2073
|
})) }));
|
|
2083
2074
|
const streamed = (block) => {
|
|
2084
|
-
if (isThinkingBlock(block)) return block.thinking
|
|
2085
|
-
|
|
2086
|
-
text: block.thinking
|
|
2087
|
-
}];
|
|
2088
|
-
if (isTextBlock(block)) return block.text.trim() === "" ? [] : [{
|
|
2089
|
-
kind: "text",
|
|
2090
|
-
text: block.text
|
|
2091
|
-
}];
|
|
2075
|
+
if (isThinkingBlock(block)) return said("thinking", block.thinking);
|
|
2076
|
+
if (isTextBlock(block)) return said("text", block.text);
|
|
2092
2077
|
return [];
|
|
2093
2078
|
};
|
|
2094
2079
|
var Transcript = class {
|
|
@@ -2359,6 +2344,42 @@ const lookup$5 = Effect.fn("go.lookup")(function* (client, wanted) {
|
|
|
2359
2344
|
withdrawn: {}
|
|
2360
2345
|
};
|
|
2361
2346
|
});
|
|
2347
|
+
// src/registry/npm.ts
|
|
2348
|
+
const Version = Schema.Struct({ deprecated: Schema.optionalKey(Schema.Unknown) });
|
|
2349
|
+
const Packument$1 = Schema.Struct({
|
|
2350
|
+
description: Schema.optionalKey(Schema.String),
|
|
2351
|
+
homepage: Schema.optionalKey(Schema.String),
|
|
2352
|
+
repository: Schema.optionalKey(Schema.Union([Schema.String, Schema.Struct({ url: Schema.optionalKey(Schema.String) })])),
|
|
2353
|
+
"dist-tags": Schema.optionalKey(Schema.Struct({ latest: Schema.optionalKey(Schema.String) })),
|
|
2354
|
+
time: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
|
|
2355
|
+
versions: Schema.optionalKey(Schema.Record(Schema.String, Version))
|
|
2356
|
+
});
|
|
2357
|
+
const Downloads = Schema.Struct({ downloads: Schema.Finite });
|
|
2358
|
+
const message$2 = (version) => {
|
|
2359
|
+
const deprecated = version?.deprecated;
|
|
2360
|
+
return Predicate.isString(deprecated) && deprecated !== "" ? Option.some(deprecated) : Option.none();
|
|
2361
|
+
};
|
|
2362
|
+
const npmRegistry = "https://registry.npmjs.org";
|
|
2363
|
+
const npmPath = (segment) => encodeURIComponent(segment).replaceAll(/%(?:24|26|2B|3A|3D|40)/gu, (escaped) => decodeURIComponent(escaped));
|
|
2364
|
+
const lookup$4 = Effect.fn("npm.lookup")(function* (client, wanted) {
|
|
2365
|
+
const [packument, downloads] = yield* Effect.all([getJson(client, `${npmRegistry}/${npmPath(wanted.name)}`, Packument$1), getJson(client, `https://api.npmjs.org/downloads/point/last-week/${wanted.name}`, Downloads).pipe(Effect.option)], { concurrency: "unbounded" });
|
|
2366
|
+
const versions = packument.versions ?? {};
|
|
2367
|
+
const latest = packument["dist-tags"]?.latest;
|
|
2368
|
+
const repository = Predicate.isString(packument.repository) ? packument.repository : packument.repository?.url;
|
|
2369
|
+
const deprecated = latest === void 0 ? Option.none() : message$2(versions[latest]);
|
|
2370
|
+
return {
|
|
2371
|
+
...packument.description === void 0 ? {} : { description: packument.description },
|
|
2372
|
+
...packument.homepage === void 0 ? {} : { homepage: packument.homepage },
|
|
2373
|
+
...repository === void 0 ? {} : { repository: repositoryUrl(repository) },
|
|
2374
|
+
...Option.isSome(downloads) ? { popularity: `${count(downloads.value.downloads)} downloads last week` } : {},
|
|
2375
|
+
...Option.isSome(deprecated) ? { deprecated: deprecated.value } : {},
|
|
2376
|
+
released: pick$1(packument.time ?? {}, wanted.versions),
|
|
2377
|
+
withdrawn: Object.fromEntries(wanted.versions.flatMap((version) => Option.match(message$2(versions[version]), {
|
|
2378
|
+
onNone: () => [],
|
|
2379
|
+
onSome: (reason) => [[version, reason]]
|
|
2380
|
+
})))
|
|
2381
|
+
};
|
|
2382
|
+
});
|
|
2362
2383
|
// src/audit/binary.ts
|
|
2363
2384
|
const startsWith$1 = (prefix, magic) => magic.every((byte, index) => prefix[index] === byte);
|
|
2364
2385
|
const binaryKind = (prefix) => {
|
|
@@ -4273,11 +4294,11 @@ var EvidenceUnavailable = class extends Schema.TaggedError()("EvidenceUnavailabl
|
|
|
4273
4294
|
reason: Schema.optionalKey(Schema.Literals(["gone", "mismatch"]))
|
|
4274
4295
|
}) {};
|
|
4275
4296
|
const maxDownloadBytes = 8 * 1024 ** 3;
|
|
4276
|
-
const message$
|
|
4297
|
+
const message$1 = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
4277
4298
|
const download = Effect.fn("evidence.download")(function* (client, url, limit = maxDownloadBytes, stall) {
|
|
4278
4299
|
const unavailable = (cause) => new EvidenceUnavailable({
|
|
4279
4300
|
source: url,
|
|
4280
|
-
issue: message$
|
|
4301
|
+
issue: message$1(cause)
|
|
4281
4302
|
});
|
|
4282
4303
|
const stalled = (after) => unavailable(`sent nothing for ${Duration.format(after)}, so upup gave up`);
|
|
4283
4304
|
const directory = yield* Effect.acquireRelease(Effect.tryPromise({
|
|
@@ -4323,7 +4344,7 @@ const download = Effect.fn("evidence.download")(function* (client, url, limit =
|
|
|
4323
4344
|
sha256: hash.digest("hex")
|
|
4324
4345
|
};
|
|
4325
4346
|
});
|
|
4326
|
-
const canonicalSha256
|
|
4347
|
+
const canonicalSha256 = (raw) => {
|
|
4327
4348
|
const value = raw.trim().toLowerCase();
|
|
4328
4349
|
return /^[0-9a-f]{64}$/u.test(value) ? value : void 0;
|
|
4329
4350
|
};
|
|
@@ -4345,7 +4366,7 @@ const crate = Effect.fn("evidence.crate")(function* (client, name, version) {
|
|
|
4345
4366
|
source,
|
|
4346
4367
|
issue: `no crates index entry for ${name} ${version}`
|
|
4347
4368
|
});
|
|
4348
|
-
const sum = canonicalSha256
|
|
4369
|
+
const sum = canonicalSha256(entry.cksum);
|
|
4349
4370
|
if (sum === void 0) return yield* new EvidenceUnavailable({
|
|
4350
4371
|
source,
|
|
4351
4372
|
issue: `crates index publishes an invalid checksum for ${name} ${version}`
|
|
@@ -4399,8 +4420,6 @@ const NpmVersion = Schema.Struct({
|
|
|
4399
4420
|
shasum: Schema.optionalKey(Schema.String)
|
|
4400
4421
|
}))
|
|
4401
4422
|
});
|
|
4402
|
-
const npmRegistry = "https://registry.npmjs.org";
|
|
4403
|
-
const npmPath = (segment) => encodeURIComponent(segment).replaceAll(/%(?:24|26|2B|3A|3D|40)/gu, (escaped) => decodeURIComponent(escaped));
|
|
4404
4423
|
const strictBase64 = (value) => {
|
|
4405
4424
|
const decoded = Buffer.from(value, "base64");
|
|
4406
4425
|
return decoded.toString("base64") === value ? decoded : void 0;
|
|
@@ -4451,7 +4470,7 @@ const npmPlan = Effect.fn("evidence.npmPlan")(function* (name, version, metadata
|
|
|
4451
4470
|
try: () => npmDigest(dist.integrity ?? "", dist.shasum ?? ""),
|
|
4452
4471
|
catch: (error) => new EvidenceUnavailable({
|
|
4453
4472
|
source,
|
|
4454
|
-
issue: `npm ${name}@${version}: ${message$
|
|
4473
|
+
issue: `npm ${name}@${version}: ${message$1(error)}`
|
|
4455
4474
|
})
|
|
4456
4475
|
})
|
|
4457
4476
|
};
|
|
@@ -4514,7 +4533,7 @@ const fetchVerified = Effect.fn("evidence.fetchVerified")(function* (client, url
|
|
|
4514
4533
|
try: async () => await computedDigest(digest, downloaded),
|
|
4515
4534
|
catch: (error) => new EvidenceUnavailable({
|
|
4516
4535
|
source: url,
|
|
4517
|
-
issue: message$
|
|
4536
|
+
issue: message$1(error)
|
|
4518
4537
|
})
|
|
4519
4538
|
});
|
|
4520
4539
|
if (computed === void 0) return yield* new EvidenceUnavailable({
|
|
@@ -4567,6 +4586,10 @@ const preparationPlan = (subject, evidence) => {
|
|
|
4567
4586
|
plan: `${JSON.stringify(plan, null, 2)}\n`
|
|
4568
4587
|
};
|
|
4569
4588
|
};
|
|
4589
|
+
const prepareWorkspace = Effect.fn("evidence.prepareWorkspace")(function* (workspace, subject, preparation) {
|
|
4590
|
+
const prepared = yield* preparation.materialize(workspace);
|
|
4591
|
+
return yield* write(workspace, subject, prepared, preparation.key);
|
|
4592
|
+
});
|
|
4570
4593
|
// src/registry/github.ts
|
|
4571
4594
|
const githubApi = "https://api.github.com";
|
|
4572
4595
|
const githubRepository = (name) => `https://github.com/${name}.git`;
|
|
@@ -4629,18 +4652,11 @@ const sourceOf$1 = (entry) => ({
|
|
|
4629
4652
|
tapGitHead: entry.tap_git_head ?? "",
|
|
4630
4653
|
rubySourceChecksum: entry.ruby_source_checksum?.sha256 ?? ""
|
|
4631
4654
|
});
|
|
4632
|
-
const brew = (args) => ({
|
|
4633
|
-
command: "brew",
|
|
4634
|
-
args,
|
|
4635
|
-
cwd: "/",
|
|
4636
|
-
env: { HOMEBREW_NO_AUTO_UPDATE: "1" }
|
|
4637
|
-
});
|
|
4638
4655
|
const unavailable$2 = (source, issue) => new EvidenceUnavailable({
|
|
4639
4656
|
source,
|
|
4640
4657
|
issue
|
|
4641
4658
|
});
|
|
4642
4659
|
const query = Effect.fn("brew.query")(function* (kind, name) {
|
|
4643
|
-
if (kind !== "formula" && kind !== "cask") return yield* unavailable$2("brew", `unsupported brew package variant ${JSON.stringify(kind)}`);
|
|
4644
4660
|
const raw = yield* (yield* Exec).stdout(brew([
|
|
4645
4661
|
"info",
|
|
4646
4662
|
"--json=v2",
|
|
@@ -4790,9 +4806,7 @@ const nextPage = (current, link) => {
|
|
|
4790
4806
|
const githubGet = (client, url, token) => Effect.gen(function* () {
|
|
4791
4807
|
const headers = {
|
|
4792
4808
|
"user-agent": userAgent,
|
|
4793
|
-
|
|
4794
|
-
"x-github-api-version": "2022-11-28",
|
|
4795
|
-
...token !== void 0 && url.startsWith(`https://api.github.com/`) ? { authorization: `Bearer ${token}` } : {}
|
|
4809
|
+
...githubHeaders(url.startsWith(`https://api.github.com/`) ? token : void 0)
|
|
4796
4810
|
};
|
|
4797
4811
|
const response = yield* get(client, url, headers);
|
|
4798
4812
|
const fail = (issue) => Effect.fail(new EvidenceUnavailable({
|
|
@@ -6098,17 +6112,17 @@ const provenanceSource = (statement, integrity) => {
|
|
|
6098
6112
|
commit
|
|
6099
6113
|
};
|
|
6100
6114
|
};
|
|
6101
|
-
const message
|
|
6115
|
+
const message = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
6102
6116
|
const sigstoreVerifier = Effect.gen(function* () {
|
|
6103
|
-
const cachePath = path.join(yield* cacheDir.pipe(Effect.mapError((error) => `no cache directory: ${message
|
|
6117
|
+
const cachePath = path.join(yield* cacheDir.pipe(Effect.mapError((error) => `no cache directory: ${message(error)}`)), "sigstore");
|
|
6104
6118
|
const root = yield* Effect.tryPromise({
|
|
6105
6119
|
try: async () => await getTrustedRoot({ cachePath }),
|
|
6106
|
-
catch: (error) => `the Sigstore trust root could not be loaded: ${message
|
|
6120
|
+
catch: (error) => `the Sigstore trust root could not be loaded: ${message(error)}`
|
|
6107
6121
|
});
|
|
6108
6122
|
const verifier = new Verifier(toTrustMaterial(root));
|
|
6109
6123
|
return (bundle) => Effect.try({
|
|
6110
6124
|
try: () => verifier.verify(toSignedEntity(bundle), {}),
|
|
6111
|
-
catch: (error) => `its Sigstore verification failed: ${message
|
|
6125
|
+
catch: (error) => `its Sigstore verification failed: ${message(error)}`
|
|
6112
6126
|
});
|
|
6113
6127
|
});
|
|
6114
6128
|
const sourceRepositoryUri = "1.3.6.1.4.1.57264.1.12";
|
|
@@ -6343,7 +6357,7 @@ const sourceEvidence = Effect.fn("brew.sourceEvidence")(function* (client, works
|
|
|
6343
6357
|
detail: ["Checksum-verified publisher source archive Delta is included.", partial("source archive", source.omitted)].filter((sentence) => sentence !== "").join(" ")
|
|
6344
6358
|
};
|
|
6345
6359
|
});
|
|
6346
|
-
const materialize$1 = Effect.fn("brew.materialize")(function* (client, workspace, identity, plan
|
|
6360
|
+
const materialize$1 = Effect.fn("brew.materialize")(function* (client, workspace, identity, plan) {
|
|
6347
6361
|
const [formula, source, payload] = yield* Effect.all([
|
|
6348
6362
|
materializeFormula(workspace, plan.formula),
|
|
6349
6363
|
sourceEvidence(client, workspace, archives(plan.formula), plan.sourceGap),
|
|
@@ -6359,17 +6373,26 @@ const materialize$1 = Effect.fn("brew.materialize")(function* (client, workspace
|
|
|
6359
6373
|
goSource?.detail ?? "",
|
|
6360
6374
|
repository?.detail ?? ""
|
|
6361
6375
|
].filter((sentence) => sentence !== "").join(" ");
|
|
6362
|
-
return
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6376
|
+
return {
|
|
6377
|
+
diff: Buffer.concat([
|
|
6378
|
+
formula,
|
|
6379
|
+
source.diff,
|
|
6380
|
+
payload.diff,
|
|
6381
|
+
goSource?.diff ?? Buffer.alloc(0),
|
|
6382
|
+
repository?.diff ?? Buffer.alloc(0)
|
|
6383
|
+
]),
|
|
6384
|
+
evidence,
|
|
6385
|
+
detail: plan.formula.fromGap === "" ? detail : `The installed version's formula snapshot is unavailable: ${plan.formula.fromGap}. ${detail}`
|
|
6386
|
+
};
|
|
6369
6387
|
});
|
|
6370
6388
|
const resolve$2 = Effect.fn("brew.resolve")(function* (client, identity) {
|
|
6371
6389
|
const { artifact, from, to } = identity.delta;
|
|
6372
|
-
const
|
|
6390
|
+
const { context } = identity;
|
|
6391
|
+
if (context._tag !== "Brew") return yield* new EvidenceUnavailable({
|
|
6392
|
+
source: "brew",
|
|
6393
|
+
issue: `a brew package's audit needs its kind, not ${context._tag}`
|
|
6394
|
+
});
|
|
6395
|
+
const { kind } = context;
|
|
6373
6396
|
const { source, formula: info } = yield* query(kind, artifact);
|
|
6374
6397
|
const formula = yield* resolveFormula(client, source, from, to);
|
|
6375
6398
|
const formulaGap = formula.fromGap === "" ? archiveUnavailableReason(archives(formula)) : "the installed version's formula snapshot is unavailable";
|
|
@@ -6388,25 +6411,21 @@ const resolve$2 = Effect.fn("brew.resolve")(function* (client, identity) {
|
|
|
6388
6411
|
...repository === void 0 ? {} : { repository }
|
|
6389
6412
|
};
|
|
6390
6413
|
});
|
|
6391
|
-
const prepareBrewWith = (exec) => (client, identity) => resolve$2(client, identity).pipe(Effect.provide(exec), Effect.map((plan) => {
|
|
6392
|
-
|
|
6414
|
+
const prepareBrewWith = (exec) => (client, identity) => resolve$2(client, identity).pipe(Effect.provide(exec), Effect.map((plan) => ({
|
|
6415
|
+
...preparationPlan(identity, {
|
|
6393
6416
|
kind: "brew",
|
|
6394
6417
|
plan: planKey(plan)
|
|
6395
|
-
})
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
artifacts: artifactsOf(plan),
|
|
6400
|
-
materialize: (workspace) => materialize$1(client, workspace, identity, plan, key).pipe(Effect.provide(exec))
|
|
6401
|
-
};
|
|
6402
|
-
}));
|
|
6418
|
+
}),
|
|
6419
|
+
artifacts: artifactsOf(plan),
|
|
6420
|
+
materialize: (workspace) => materialize$1(client, workspace, identity, plan).pipe(Effect.provide(exec))
|
|
6421
|
+
})));
|
|
6403
6422
|
const prepareBrew = prepareBrewWith(nodeLayer);
|
|
6404
6423
|
// src/audit/github-actions.ts
|
|
6405
6424
|
const unavailable$1 = (error) => new EvidenceUnavailable({
|
|
6406
6425
|
source: error.repository,
|
|
6407
6426
|
issue: error.issue
|
|
6408
6427
|
});
|
|
6409
|
-
const workspaceOf
|
|
6428
|
+
const workspaceOf = Effect.fn("githubActions.workspace")(function* (workspace, identity, repository, commits, options) {
|
|
6410
6429
|
const trees = {
|
|
6411
6430
|
from: path.join(workspace, files.actionFrom),
|
|
6412
6431
|
to: path.join(workspace, files.actionTo)
|
|
@@ -6431,17 +6450,25 @@ const workspaceOf$1 = Effect.fn("githubActions.workspace")(function* (workspace,
|
|
|
6431
6450
|
const { from, to } = identity.delta;
|
|
6432
6451
|
const commitsSentence = `In ${repository}, ${from} is ${commits.from} and ${to} is ${commits.to}.`;
|
|
6433
6452
|
const modes = yield* writeFileDiff(workspace, files.actionModesFrom, files.actionModesTo, json(Object.fromEntries(changed.modes.map((change) => [change.path, change.from]))), json(Object.fromEntries(changed.modes.map((change) => [change.path, change.to]))));
|
|
6434
|
-
if (changed.omitted !== "") return
|
|
6453
|
+
if (changed.omitted !== "") return {
|
|
6454
|
+
diff: modes,
|
|
6455
|
+
evidence: "metadata-only",
|
|
6456
|
+
detail: `${commitsSentence} The changed files were not fetched: ${changed.omitted}.`
|
|
6457
|
+
};
|
|
6435
6458
|
const { diff, omitted } = yield* treeDiff(workspace, files.actionFrom, files.actionTo);
|
|
6436
6459
|
const submodules = changed.modes.flatMap((change) => change.submodule ? [change.path] : []);
|
|
6437
6460
|
const gaps = [partial("action", omitted), submodules.length === 0 ? "" : `Submodules changed, and their contents were not fetched: ${submodules.join(", ")}.`].filter((sentence) => sentence !== "");
|
|
6438
|
-
return
|
|
6461
|
+
return {
|
|
6462
|
+
diff: Buffer.concat([diff, modes]),
|
|
6463
|
+
evidence: gaps.length === 0 ? "full" : "partial",
|
|
6464
|
+
detail: [commitsSentence, ...gaps].join(" ")
|
|
6465
|
+
};
|
|
6439
6466
|
});
|
|
6440
6467
|
const githubActionPreparer = (repositoryOf, options = {}) => Effect.fn("githubActions.prepare")(function* (_client, identity) {
|
|
6441
6468
|
const { artifact, from, to } = identity.delta;
|
|
6442
6469
|
const repository = repositoryOf(artifact);
|
|
6443
6470
|
const [fromCommit, toCommit] = yield* Effect.all([tagCommit(repository, from, options), tagCommit(repository, to, options)], { concurrency: "unbounded" }).pipe(Effect.mapError(unavailable$1));
|
|
6444
|
-
const listed = identity.context
|
|
6471
|
+
const listed = identity.context._tag === "Revision" ? identity.context.revision : void 0;
|
|
6445
6472
|
if (listed !== toCommit) return yield* new EvidenceUnavailable({
|
|
6446
6473
|
source: repository,
|
|
6447
6474
|
issue: listed === void 0 ? `upup listed no commit for ${to}; refresh` : `${to} now points at ${toCommit}, not the ${listed} upup listed; refresh`,
|
|
@@ -6451,16 +6478,14 @@ const githubActionPreparer = (repositoryOf, options = {}) => Effect.fn("githubAc
|
|
|
6451
6478
|
from: fromCommit,
|
|
6452
6479
|
to: toCommit
|
|
6453
6480
|
};
|
|
6454
|
-
const { key, plan } = preparationPlan(identity, {
|
|
6455
|
-
kind: "github-actions",
|
|
6456
|
-
repository,
|
|
6457
|
-
commits
|
|
6458
|
-
});
|
|
6459
6481
|
return {
|
|
6460
|
-
|
|
6461
|
-
|
|
6482
|
+
...preparationPlan(identity, {
|
|
6483
|
+
kind: "github-actions",
|
|
6484
|
+
repository,
|
|
6485
|
+
commits
|
|
6486
|
+
}),
|
|
6462
6487
|
artifacts: [`from ${fromCommit}`, `to ${toCommit}`],
|
|
6463
|
-
materialize: (workspace) => workspaceOf
|
|
6488
|
+
materialize: (workspace) => workspaceOf(workspace, identity, repository, commits, options)
|
|
6464
6489
|
};
|
|
6465
6490
|
});
|
|
6466
6491
|
const prepareGitHubAction = githubActionPreparer(githubRepository);
|
|
@@ -6474,10 +6499,6 @@ const Release$2 = Schema.Struct({ urls: optional(Schema.Array(Schema.Struct({
|
|
|
6474
6499
|
digests: optional(Schema.Struct({ sha256: optional(Schema.String) }))
|
|
6475
6500
|
}))) });
|
|
6476
6501
|
const releaseUrl = (name, version) => `https://pypi.org/pypi/${encodeURIComponent(name)}/${encodeURIComponent(version)}/json`;
|
|
6477
|
-
const canonicalSha256 = (raw) => {
|
|
6478
|
-
const value = raw.trim().toLowerCase();
|
|
6479
|
-
return /^[0-9a-f]{64}$/u.test(value) ? value : void 0;
|
|
6480
|
-
};
|
|
6481
6502
|
const formatOf = (url) => {
|
|
6482
6503
|
try {
|
|
6483
6504
|
return formatOf$1(url);
|
|
@@ -6626,7 +6647,7 @@ const trees = [
|
|
|
6626
6647
|
files.wheelFrom,
|
|
6627
6648
|
files.wheelTo
|
|
6628
6649
|
];
|
|
6629
|
-
const pypiWorkspace = Effect.fn("pypi.workspace")(function* (client, workspace,
|
|
6650
|
+
const pypiWorkspace = Effect.fn("pypi.workspace")(function* (client, workspace, plans) {
|
|
6630
6651
|
yield* Effect.tryPromise({
|
|
6631
6652
|
try: async () => await Promise.all(trees.map(async (tree) => await mkdir(path.join(workspace, tree), {
|
|
6632
6653
|
recursive: true,
|
|
@@ -6646,38 +6667,40 @@ const pypiWorkspace = Effect.fn("pypi.workspace")(function* (client, workspace,
|
|
|
6646
6667
|
writeFileDiff(workspace, files.binaryWheelFrom, files.binaryWheelTo, json(binarySummaries(from.compatible_universal_wheel?.archive_manifest)), json(binarySummaries(to.compatible_universal_wheel?.archive_manifest)))
|
|
6647
6668
|
], { concurrency: "unbounded" });
|
|
6648
6669
|
const detail = `Checksum-verified PyPI publisher artifacts; ${pairedDetail("source distributions", from.publisher_sdist, to.publisher_sdist)}; ${pairedDetail("compatible universal wheel candidates", from.compatible_universal_wheel, to.compatible_universal_wheel)}; the installer’s exact resolver selection is not known.`;
|
|
6649
|
-
return
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
partial
|
|
6658
|
-
|
|
6659
|
-
|
|
6670
|
+
return {
|
|
6671
|
+
diff: Buffer.concat([
|
|
6672
|
+
sources.diff,
|
|
6673
|
+
records,
|
|
6674
|
+
sourceBinaries,
|
|
6675
|
+
wheels.diff,
|
|
6676
|
+
wheelBinaries
|
|
6677
|
+
]),
|
|
6678
|
+
evidence: "partial",
|
|
6679
|
+
detail: [
|
|
6680
|
+
detail,
|
|
6681
|
+
partial("source distribution", sources.omitted),
|
|
6682
|
+
partial("wheel", wheels.omitted)
|
|
6683
|
+
].filter((sentence) => sentence !== "").join(" ")
|
|
6684
|
+
};
|
|
6660
6685
|
});
|
|
6661
6686
|
const preparePyPI = Effect.fn("pypi.prepare")(function* (client, identity) {
|
|
6662
6687
|
const { artifact, from, to } = identity.delta;
|
|
6663
|
-
const python = identity.context
|
|
6688
|
+
const python = identity.context._tag === "Python" ? identity.context.python : "";
|
|
6664
6689
|
const [fromPlan, toPlan] = yield* Effect.all([resolve$1(client, artifact, from, python), resolve$1(client, artifact, to, python)], { concurrency: "unbounded" });
|
|
6665
6690
|
const plans = {
|
|
6666
6691
|
from: fromPlan,
|
|
6667
6692
|
to: toPlan
|
|
6668
6693
|
};
|
|
6669
|
-
const { key, plan } = preparationPlan(identity, {
|
|
6670
|
-
kind: "pypi",
|
|
6671
|
-
...plans
|
|
6672
|
-
});
|
|
6673
6694
|
return {
|
|
6674
|
-
|
|
6675
|
-
|
|
6695
|
+
...preparationPlan(identity, {
|
|
6696
|
+
kind: "pypi",
|
|
6697
|
+
...plans
|
|
6698
|
+
}),
|
|
6676
6699
|
artifacts: ["from", "to"].flatMap((side) => [plans[side].publisher_sdist, plans[side].compatible_universal_wheel].map((selected) => `${side} ${selected === null ? "none" : `sha256:${selected.sha256}`}`)),
|
|
6677
|
-
materialize: (workspace) => pypiWorkspace(client, workspace,
|
|
6700
|
+
materialize: (workspace) => pypiWorkspace(client, workspace, plans)
|
|
6678
6701
|
};
|
|
6679
6702
|
});
|
|
6680
|
-
const Packument
|
|
6703
|
+
const Packument = Schema.Struct({
|
|
6681
6704
|
"dist-tags": Schema.optionalKey(Schema.NullOr(Schema.Record(Schema.String, Schema.String))),
|
|
6682
6705
|
versions: Schema.Record(Schema.String, Schema.Unknown)
|
|
6683
6706
|
});
|
|
@@ -6709,7 +6732,7 @@ const resolveSide = (client, host, name, declared, options = {}) => Effect.gen(f
|
|
|
6709
6732
|
issue: `declares ${JSON.stringify(declared.spec)}, which is not a registry version range`
|
|
6710
6733
|
});
|
|
6711
6734
|
const source = `${npmRegistry}/${npmPath(name)}`;
|
|
6712
|
-
const packument = yield* getJson(client, source, Packument
|
|
6735
|
+
const packument = yield* getJson(client, source, Packument, { accept: "application/vnd.npm.install-v1+json" }).pipe(Effect.mapError((error) => new EvidenceUnavailable({
|
|
6713
6736
|
source,
|
|
6714
6737
|
issue: error.issue
|
|
6715
6738
|
})));
|
|
@@ -6902,87 +6925,102 @@ const materializeDependencies = Effect.fn("npmDependencies.materialize")(functio
|
|
|
6902
6925
|
});
|
|
6903
6926
|
// src/audit/registry-evidence.ts
|
|
6904
6927
|
const registryDetail = "Both published packages were downloaded and their checksums verified. File types and modes, and any native binaries, are summarised without running them.";
|
|
6905
|
-
const
|
|
6928
|
+
const sentences = (parts) => parts.filter((sentence) => sentence !== "").join(" ");
|
|
6929
|
+
const artifactEvidence = Effect.fn("evidence.artifactEvidence")(function* (client, workspace, plans) {
|
|
6906
6930
|
const [from, to] = yield* Effect.all([materialize$2(client, plans.from, path.join(workspace, files.from)), materialize$2(client, plans.to, path.join(workspace, files.to))], { concurrency: "unbounded" });
|
|
6907
6931
|
const [artifacts, trees, binaries] = yield* Effect.all([
|
|
6908
6932
|
writeFileDiff(workspace, files.artifactFrom, files.artifactTo, manifestJson(from), manifestJson(to)),
|
|
6909
6933
|
treeDiff(workspace, files.from, files.to),
|
|
6910
6934
|
writeFileDiff(workspace, files.binaryFrom, files.binaryTo, json(binarySummaries(from)), json(binarySummaries(to)))
|
|
6911
6935
|
], { concurrency: "unbounded" });
|
|
6912
|
-
const treeDetail = [registryDetail, partial("artifact", trees.omitted)].filter((sentence) => sentence !== "").join(" ");
|
|
6913
|
-
if (npm === void 0) return yield* write(workspace, identity, Buffer.concat([
|
|
6914
|
-
artifacts,
|
|
6915
|
-
trees.diff,
|
|
6916
|
-
binaries
|
|
6917
|
-
]), trees.omitted === "" ? "full" : "partial", treeDetail, key);
|
|
6918
|
-
const changed = yield* materializeDependencies(client, workspace, npm.dependencies);
|
|
6919
|
-
const linked = yield* Effect.forEach(changed.binaries, (binary) => releaseAssetSources(client, binary.repository, [binary.from, binary.to]).pipe(Effect.map(([fromRelease, toRelease]) => ({
|
|
6920
|
-
label: binary.label,
|
|
6921
|
-
from: fromRelease ?? { gap: "no release lookup" },
|
|
6922
|
-
to: toRelease ?? { gap: "no release lookup" }
|
|
6923
|
-
}))), { concurrency: 2 });
|
|
6924
|
-
const source = yield* materializeSources(workspace, [npm.source, ...linked]);
|
|
6925
|
-
return yield* write(workspace, identity, Buffer.concat([
|
|
6926
|
-
artifacts,
|
|
6927
|
-
trees.diff,
|
|
6928
|
-
binaries,
|
|
6929
|
-
changed.diff,
|
|
6930
|
-
source.diff
|
|
6931
|
-
]), "partial", [
|
|
6932
|
-
treeDetail,
|
|
6933
|
-
changed.detail,
|
|
6934
|
-
source.detail
|
|
6935
|
-
].filter((sentence) => sentence !== "").join(" "), key);
|
|
6936
|
-
});
|
|
6937
|
-
const npmExtras = Effect.fn("evidence.npmExtras")(function* (client, name, from, to, manifests) {
|
|
6938
|
-
const fromManifest = manifests.from;
|
|
6939
|
-
const toManifest = manifests.to;
|
|
6940
|
-
const dependencies = yield* resolveDependencies(client, manifests, {
|
|
6941
|
-
os: process.platform,
|
|
6942
|
-
cpu: process.arch
|
|
6943
|
-
});
|
|
6944
|
-
const verifier = yield* Effect.cached(sigstoreVerifier);
|
|
6945
|
-
const [fromSource, toSource] = yield* Effect.all([npmSource(client, name, from, fromManifest, verifier), npmSource(client, name, to, toManifest, verifier)], { concurrency: "unbounded" });
|
|
6946
|
-
const { directory } = npmRepository(toManifest);
|
|
6947
6936
|
return {
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6937
|
+
diff: Buffer.concat([
|
|
6938
|
+
artifacts,
|
|
6939
|
+
trees.diff,
|
|
6940
|
+
binaries
|
|
6941
|
+
]),
|
|
6942
|
+
evidence: trees.omitted === "" ? "full" : "partial",
|
|
6943
|
+
detail: sentences([registryDetail, partial("artifact", trees.omitted)])
|
|
6955
6944
|
};
|
|
6956
6945
|
});
|
|
6946
|
+
const digests = (plans) => [`from ${plans.from.published_digest}`, `to ${plans.to.published_digest}`];
|
|
6957
6947
|
const prepareRegistry = Effect.fn("evidence.prepareRegistry")(function* (client, identity) {
|
|
6958
6948
|
const { ecosystem, artifact, from, to } = identity.delta;
|
|
6959
|
-
const
|
|
6960
|
-
from: npmVersion(client, artifact, from),
|
|
6961
|
-
to: npmVersion(client, artifact, to)
|
|
6962
|
-
}, { concurrency: "unbounded" }) : void 0;
|
|
6963
|
-
const [fromPlan, toPlan] = yield* Effect.all(manifests === void 0 ? [resolve$3(client, ecosystem, artifact, from), resolve$3(client, ecosystem, artifact, to)] : [npmPlan(artifact, from, manifests.from), npmPlan(artifact, to, manifests.to)], { concurrency: "unbounded" });
|
|
6949
|
+
const [fromPlan, toPlan] = yield* Effect.all([resolve$3(client, ecosystem, artifact, from), resolve$3(client, ecosystem, artifact, to)], { concurrency: "unbounded" });
|
|
6964
6950
|
const plans = {
|
|
6965
6951
|
from: fromPlan,
|
|
6966
6952
|
to: toPlan
|
|
6967
6953
|
};
|
|
6968
|
-
const npm = manifests === void 0 ? void 0 : yield* npmExtras(client, artifact, from, to, manifests);
|
|
6969
|
-
const { key, plan } = preparationPlan(identity, {
|
|
6970
|
-
kind: "registry",
|
|
6971
|
-
...plans,
|
|
6972
|
-
...npm
|
|
6973
|
-
});
|
|
6974
6954
|
return {
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6955
|
+
...preparationPlan(identity, {
|
|
6956
|
+
kind: "registry",
|
|
6957
|
+
...plans
|
|
6958
|
+
}),
|
|
6959
|
+
artifacts: digests(plans),
|
|
6960
|
+
materialize: (workspace) => artifactEvidence(client, workspace, plans)
|
|
6979
6961
|
};
|
|
6980
6962
|
});
|
|
6981
6963
|
// src/audit/prepare.ts
|
|
6982
6964
|
const preparers = {
|
|
6983
6965
|
crates: prepareRegistry,
|
|
6984
6966
|
go: prepareRegistry,
|
|
6985
|
-
npm:
|
|
6967
|
+
npm: Effect.fn("evidence.prepareNpm")(function* (client, identity) {
|
|
6968
|
+
const { artifact, from, to } = identity.delta;
|
|
6969
|
+
const manifests = yield* Effect.all({
|
|
6970
|
+
from: npmVersion(client, artifact, from),
|
|
6971
|
+
to: npmVersion(client, artifact, to)
|
|
6972
|
+
}, { concurrency: "unbounded" });
|
|
6973
|
+
const [fromPlan, toPlan] = yield* Effect.all([npmPlan(artifact, from, manifests.from), npmPlan(artifact, to, manifests.to)], { concurrency: "unbounded" });
|
|
6974
|
+
const dependencies = yield* resolveDependencies(client, manifests, {
|
|
6975
|
+
os: process.platform,
|
|
6976
|
+
cpu: process.arch
|
|
6977
|
+
});
|
|
6978
|
+
const verifier = yield* Effect.cached(sigstoreVerifier);
|
|
6979
|
+
const [fromSource, toSource] = yield* Effect.all([npmSource(client, artifact, from, manifests.from, verifier), npmSource(client, artifact, to, manifests.to, verifier)], { concurrency: "unbounded" });
|
|
6980
|
+
const { directory } = npmRepository(manifests.to);
|
|
6981
|
+
const source = {
|
|
6982
|
+
label: artifact,
|
|
6983
|
+
...directory === void 0 ? {} : { directory },
|
|
6984
|
+
from: fromSource,
|
|
6985
|
+
to: toSource
|
|
6986
|
+
};
|
|
6987
|
+
const plans = {
|
|
6988
|
+
from: fromPlan,
|
|
6989
|
+
to: toPlan
|
|
6990
|
+
};
|
|
6991
|
+
return {
|
|
6992
|
+
...preparationPlan(identity, {
|
|
6993
|
+
kind: "npm",
|
|
6994
|
+
...plans,
|
|
6995
|
+
dependencies,
|
|
6996
|
+
source
|
|
6997
|
+
}),
|
|
6998
|
+
artifacts: digests(plans),
|
|
6999
|
+
materialize: (workspace) => Effect.gen(function* () {
|
|
7000
|
+
const artifacts = yield* artifactEvidence(client, workspace, plans);
|
|
7001
|
+
const changed = yield* materializeDependencies(client, workspace, dependencies);
|
|
7002
|
+
const linked = yield* Effect.forEach(changed.binaries, (binary) => releaseAssetSources(client, binary.repository, [binary.from, binary.to]).pipe(Effect.map(([fromRelease, toRelease]) => ({
|
|
7003
|
+
label: binary.label,
|
|
7004
|
+
from: fromRelease ?? { gap: "no release lookup" },
|
|
7005
|
+
to: toRelease ?? { gap: "no release lookup" }
|
|
7006
|
+
}))), { concurrency: 2 });
|
|
7007
|
+
const sources = yield* materializeSources(workspace, [source, ...linked]);
|
|
7008
|
+
return {
|
|
7009
|
+
diff: Buffer.concat([
|
|
7010
|
+
artifacts.diff,
|
|
7011
|
+
changed.diff,
|
|
7012
|
+
sources.diff
|
|
7013
|
+
]),
|
|
7014
|
+
evidence: "partial",
|
|
7015
|
+
detail: sentences([
|
|
7016
|
+
artifacts.detail,
|
|
7017
|
+
changed.detail,
|
|
7018
|
+
sources.detail
|
|
7019
|
+
])
|
|
7020
|
+
};
|
|
7021
|
+
})
|
|
7022
|
+
};
|
|
7023
|
+
}),
|
|
6986
7024
|
pypi: preparePyPI,
|
|
6987
7025
|
brew: prepareBrew,
|
|
6988
7026
|
"github-actions": prepareGitHubAction
|
|
@@ -7068,7 +7106,7 @@ const within = (effect, what) => effect.pipe(Effect.timeoutOrElse({
|
|
|
7068
7106
|
issue: `evidence preparation timed out after 15 minutes`
|
|
7069
7107
|
}))
|
|
7070
7108
|
}));
|
|
7071
|
-
const ensure = (workspace, preparation) => Effect.gen(function* () {
|
|
7109
|
+
const ensure = (workspace, identity, preparation) => Effect.gen(function* () {
|
|
7072
7110
|
yield* Effect.tryPromise({
|
|
7073
7111
|
try: async () => {
|
|
7074
7112
|
await rm(workspace, {
|
|
@@ -7086,23 +7124,21 @@ const ensure = (workspace, preparation) => Effect.gen(function* () {
|
|
|
7086
7124
|
issue: issueOf$1(error)
|
|
7087
7125
|
})
|
|
7088
7126
|
});
|
|
7089
|
-
yield* within(
|
|
7127
|
+
yield* within(prepareWorkspace(workspace, identity, preparation), "prepare workspace").pipe(Effect.onError(() => Effect.promise(async () => {
|
|
7090
7128
|
await rm(workspace, {
|
|
7091
7129
|
recursive: true,
|
|
7092
7130
|
force: true
|
|
7093
7131
|
});
|
|
7094
7132
|
})));
|
|
7095
7133
|
});
|
|
7096
|
-
const workspaceOf = (file) => path.join(path.dirname(path.dirname(path.dirname(file))), "workspaces", path.basename(path.dirname(file)));
|
|
7097
7134
|
const sameArtifacts = (left, right) => left.length === right.length && left.every((artifact, index) => artifact === right[index]);
|
|
7098
|
-
const reportedFrom = (
|
|
7135
|
+
const reportedFrom = (paths, stored) => Option.isSome(stored.report) && Option.isSome(stored.brief) ? Option.some({
|
|
7099
7136
|
_tag: "Reported",
|
|
7100
7137
|
report: stored.report.value,
|
|
7101
7138
|
evidence: stored.brief.value.evidence,
|
|
7102
7139
|
detail: stored.brief.value.evidenceDetail,
|
|
7103
7140
|
model: `${stored.brief.value.provider}/${stored.brief.value.modelId}`,
|
|
7104
|
-
|
|
7105
|
-
workspace: workspaceOf(file)
|
|
7141
|
+
...paths
|
|
7106
7142
|
}) : Option.none();
|
|
7107
7143
|
const audits$1 = (stored, artifacts) => Option.isSome(stored.brief) && sameArtifacts(stored.brief.value.artifacts, artifacts);
|
|
7108
7144
|
const children = (directory) => Effect.promise(async () => await readdir(directory).catch(() => []));
|
|
@@ -7143,13 +7179,7 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
|
|
|
7143
7179
|
});
|
|
7144
7180
|
const landingFile = (landing) => path.join(root, "landed", landing.mode, `${landingKey(landing)}.json`);
|
|
7145
7181
|
const land = (identity) => Effect.tryPromise(async () => {
|
|
7146
|
-
const file = landingFile(
|
|
7147
|
-
mode: identity.mode,
|
|
7148
|
-
ecosystem: identity.delta.ecosystem,
|
|
7149
|
-
artifact: identity.delta.artifact,
|
|
7150
|
-
version: identity.delta.to,
|
|
7151
|
-
context: identity.context
|
|
7152
|
-
});
|
|
7182
|
+
const file = landingFile(landingAt(identity));
|
|
7153
7183
|
await mkdir(path.dirname(file), {
|
|
7154
7184
|
recursive: true,
|
|
7155
7185
|
mode: 448
|
|
@@ -7163,10 +7193,15 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
|
|
|
7163
7193
|
const note = JSON.parse(text);
|
|
7164
7194
|
return Predicate.hasProperty(note, "from") && Predicate.hasProperty(note, "to") && Predicate.isString(note.from) && note.to === landing.version ? Option.some(note.from) : Option.none();
|
|
7165
7195
|
}, () => Option.none()));
|
|
7166
|
-
const
|
|
7167
|
-
const
|
|
7168
|
-
|
|
7169
|
-
|
|
7196
|
+
const workspaces = path.join(root, "workspaces");
|
|
7197
|
+
const workspaceFor = (identity) => path.join(workspaces, workspaceKey(identity));
|
|
7198
|
+
const pathsOf = (identity, policyKey) => ({
|
|
7199
|
+
file: path.join(root, identity.mode, workspaceKey(identity), `${policyKey}.sqlite`),
|
|
7200
|
+
workspace: workspaceFor(identity)
|
|
7201
|
+
});
|
|
7202
|
+
const storedIn = (paths) => Effect.scoped(Effect.gen(function* () {
|
|
7203
|
+
if (!(yield* tryHold(paths.workspace))) return Option.none();
|
|
7204
|
+
return Option.some(yield* stored(paths.file, ai.models));
|
|
7170
7205
|
})).pipe(Effect.orElseSucceed(() => Option.none()));
|
|
7171
7206
|
const attempt = Effect.fn("Audits.attempt")(function* (identity, options) {
|
|
7172
7207
|
let transcript = [];
|
|
@@ -7185,8 +7220,8 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
|
|
|
7185
7220
|
const prompt = promptFor(identity.mode);
|
|
7186
7221
|
const policyKey$1 = policyKey(prompt, setup.value);
|
|
7187
7222
|
const preparation = yield* within(prepare(client, identity), "resolve evidence");
|
|
7188
|
-
const
|
|
7189
|
-
const workspace =
|
|
7223
|
+
const paths = pathsOf(identity, policyKey$1);
|
|
7224
|
+
const { file, workspace } = paths;
|
|
7190
7225
|
yield* hold(workspace);
|
|
7191
7226
|
const model = `${setup.value.provider}/${setup.value.modelId}`;
|
|
7192
7227
|
if (existsSync(file)) {
|
|
@@ -7194,7 +7229,7 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
|
|
|
7194
7229
|
brief: Option.none(),
|
|
7195
7230
|
report: Option.none()
|
|
7196
7231
|
})));
|
|
7197
|
-
const found = reportedFrom(
|
|
7232
|
+
const found = reportedFrom(paths, stored$1);
|
|
7198
7233
|
if (!options.force && Option.isSome(found) && audits$1(stored$1, preparation.artifacts)) {
|
|
7199
7234
|
yield* land(identity);
|
|
7200
7235
|
return found.value;
|
|
@@ -7208,7 +7243,7 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
|
|
|
7208
7243
|
}, file);
|
|
7209
7244
|
}
|
|
7210
7245
|
yield* Effect.addFinalizer(() => prune(workspace));
|
|
7211
|
-
yield* ensure(workspace, preparation);
|
|
7246
|
+
yield* ensure(workspace, identity, preparation);
|
|
7212
7247
|
const meta = yield* readMeta(workspace);
|
|
7213
7248
|
yield* Effect.tryPromise({
|
|
7214
7249
|
try: async () => await mkdir(path.dirname(file), {
|
|
@@ -7273,8 +7308,7 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
|
|
|
7273
7308
|
evidence: meta.evidence,
|
|
7274
7309
|
detail: meta.evidence_detail,
|
|
7275
7310
|
model,
|
|
7276
|
-
|
|
7277
|
-
workspace
|
|
7311
|
+
...paths
|
|
7278
7312
|
};
|
|
7279
7313
|
});
|
|
7280
7314
|
const audit = (identity, options) => Effect.sync(() => {
|
|
@@ -7293,8 +7327,8 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
|
|
|
7293
7327
|
const recall = Effect.fn("Audits.recall")(function* (identity) {
|
|
7294
7328
|
const setup = yield* ai.setup;
|
|
7295
7329
|
if (Option.isNone(setup)) return Option.none();
|
|
7296
|
-
const
|
|
7297
|
-
const found = Option.flatMap(yield* storedIn(
|
|
7330
|
+
const paths = pathsOf(identity, policyKey(promptFor(identity.mode), setup.value));
|
|
7331
|
+
const found = Option.flatMap(yield* storedIn(paths), (stored) => reportedFrom(paths, stored));
|
|
7298
7332
|
if (Option.isSome(found)) yield* land(identity);
|
|
7299
7333
|
return found;
|
|
7300
7334
|
});
|
|
@@ -7302,26 +7336,26 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
|
|
|
7302
7336
|
const setup = yield* ai.setup;
|
|
7303
7337
|
if (Option.isNone(setup)) return Option.none();
|
|
7304
7338
|
const preparation = yield* within(prepare(client, identity), "resolve evidence");
|
|
7305
|
-
const
|
|
7306
|
-
return Option.filter(yield* storedIn(
|
|
7339
|
+
const paths = pathsOf(identity, policyKey(promptFor(identity.mode), setup.value));
|
|
7340
|
+
return Option.filter(yield* storedIn(paths), (stored) => audits$1(stored, preparation.artifacts)).pipe(Option.flatMap((stored) => reportedFrom(paths, stored)));
|
|
7307
7341
|
}).pipe(Effect.catch((error) => Effect.succeedSome({
|
|
7308
7342
|
_tag: "Failed",
|
|
7309
7343
|
issue: `the update's artifacts could not be resolved: ${issueOf$1(error)}`,
|
|
7310
7344
|
transcript: []
|
|
7311
7345
|
})));
|
|
7312
7346
|
const changes = (identity) => Effect.scoped(Effect.gen(function* () {
|
|
7313
|
-
const workspace =
|
|
7347
|
+
const workspace = workspaceFor(identity);
|
|
7314
7348
|
const held = yield* tryHold(workspace);
|
|
7315
7349
|
if (yield* readable(workspace, identity)) return yield* read$1(workspace);
|
|
7316
7350
|
if (!held) return yield* new ChangesUnavailable({ issue: "A running Audit is preparing this evidence." });
|
|
7317
7351
|
const preparation = yield* within(prepare(client, identity), "resolve evidence");
|
|
7318
|
-
yield* ensure(workspace, preparation);
|
|
7352
|
+
yield* ensure(workspace, identity, preparation);
|
|
7319
7353
|
const view = yield* read$1(workspace);
|
|
7320
7354
|
yield* prune(workspace);
|
|
7321
7355
|
return view;
|
|
7322
7356
|
})).pipe(Effect.mapError((error) => new ChangesUnavailable({ issue: issueOf$1(error) })));
|
|
7323
7357
|
const majors = (identity) => Effect.gen(function* () {
|
|
7324
|
-
const workspace =
|
|
7358
|
+
const workspace = workspaceFor(identity);
|
|
7325
7359
|
if (!(yield* readable(workspace, identity))) return [];
|
|
7326
7360
|
return yield* readMajors(workspace);
|
|
7327
7361
|
}).pipe(Effect.orElseSucceed(() => []));
|
|
@@ -7334,9 +7368,8 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
|
|
|
7334
7368
|
mode: 448
|
|
7335
7369
|
}));
|
|
7336
7370
|
const started = yield* Clock.currentTimeMillis;
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
const workspace = path.join(base, name);
|
|
7371
|
+
yield* Effect.forEach((yield* children(workspaces)).filter((name) => !name.endsWith(".lock")), (name) => {
|
|
7372
|
+
const workspace = path.join(workspaces, name);
|
|
7340
7373
|
return Effect.scoped(Effect.gen(function* () {
|
|
7341
7374
|
if (!(yield* tryHold(workspace))) return;
|
|
7342
7375
|
const prepared = yield* Effect.promise(async () => await stat(path.join(workspace, files.meta)).then((info) => info.mtimeMs, () => 0));
|
|
@@ -7367,8 +7400,8 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
|
|
|
7367
7400
|
changes,
|
|
7368
7401
|
majors,
|
|
7369
7402
|
landed,
|
|
7370
|
-
transcript: (file) => Effect.scoped(Effect.gen(function* () {
|
|
7371
|
-
if (!(yield* tryHold(
|
|
7403
|
+
transcript: ({ file, workspace }) => Effect.scoped(Effect.gen(function* () {
|
|
7404
|
+
if (!(yield* tryHold(workspace))) return yield* new AgentFailed({ issue: "the Audit is running" });
|
|
7372
7405
|
return yield* transcript(file, ai.models);
|
|
7373
7406
|
}))
|
|
7374
7407
|
}));
|
|
@@ -7384,6 +7417,18 @@ const replaceText = Effect.fn("replaceText")(function* (file, text) {
|
|
|
7384
7417
|
yield* fs.writeFileString(temporary, text, { mode }).pipe(Effect.mapError(fileFailed("write", temporary)));
|
|
7385
7418
|
yield* fs.rename(temporary, file).pipe(Effect.mapError(fileFailed("replace", file)));
|
|
7386
7419
|
});
|
|
7420
|
+
const editFiles = Effect.fn("editFiles")(function* (root, edits) {
|
|
7421
|
+
const edited = /* @__PURE__ */ new Map();
|
|
7422
|
+
for (const { file, edit } of edits) {
|
|
7423
|
+
const next = edit(edited.get(file) ?? (yield* readText(path.join(root, file))));
|
|
7424
|
+
if (Result.isFailure(next)) return yield* new EditRefused({
|
|
7425
|
+
manifest: file,
|
|
7426
|
+
issue: next.failure
|
|
7427
|
+
});
|
|
7428
|
+
edited.set(file, next.success);
|
|
7429
|
+
}
|
|
7430
|
+
for (const [file, text] of edited) yield* replaceText(path.join(root, file), text);
|
|
7431
|
+
});
|
|
7387
7432
|
// src/project/find-up.ts
|
|
7388
7433
|
const findUp = Effect.fn("findUp")(function* (start, name) {
|
|
7389
7434
|
const fs = yield* FileSystem.FileSystem;
|
|
@@ -7781,7 +7826,6 @@ const publicTags = (url) => tags(url, { timeout: lsRemoteTimeout }).pipe(Effect.
|
|
|
7781
7826
|
const make$13 = (root, origin, readPublic = publicTags) => Effect.gen(function* () {
|
|
7782
7827
|
const exec = yield* Exec;
|
|
7783
7828
|
const fs = yield* FileSystem.FileSystem;
|
|
7784
|
-
const read = (file) => readText(file).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
7785
7829
|
const scanned = Effect.gen(function* () {
|
|
7786
7830
|
const files = yield* workflowFiles(root).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
7787
7831
|
return {
|
|
@@ -7868,17 +7912,10 @@ const make$13 = (root, origin, readPublic = publicTags) => Effect.gen(function*
|
|
|
7868
7912
|
expected: pinned && pkg.revision !== void 0 ? `${target} at ${short(pkg.revision)}` : target,
|
|
7869
7913
|
...sha === void 0 ? {} : { offered: `${target} at ${short(sha)}` }
|
|
7870
7914
|
});
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
|
|
7875
|
-
if (Result.isFailure(next)) return yield* new EditRefused({
|
|
7876
|
-
manifest: use.file,
|
|
7877
|
-
issue: next.failure
|
|
7878
|
-
});
|
|
7879
|
-
edited.set(use.file, next.success);
|
|
7880
|
-
}
|
|
7881
|
-
for (const [file, text] of edited) yield* replaceText(path.join(root, file), text).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
7915
|
+
yield* editFiles(root, group.uses.map((use) => ({
|
|
7916
|
+
file: use.file,
|
|
7917
|
+
edit: (text) => pinned ? editYamlScalar(text, use.path, `${use.name}@${sha}`, movedComment(use.comment, target)) : editYamlScalar(text, use.path, `${use.name}@${target}`)
|
|
7918
|
+
}))).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
7882
7919
|
});
|
|
7883
7920
|
return {
|
|
7884
7921
|
name: providerName$1,
|
|
@@ -9019,7 +9056,7 @@ const versionsOf = (kind, installed, offer) => {
|
|
|
9019
9056
|
target: withBuild(offer.short, offer.version)
|
|
9020
9057
|
};
|
|
9021
9058
|
};
|
|
9022
|
-
const caskInfo = brew
|
|
9059
|
+
const caskInfo = brew([
|
|
9023
9060
|
"info",
|
|
9024
9061
|
"--json=v2",
|
|
9025
9062
|
"--installed",
|
|
@@ -9281,7 +9318,7 @@ const makeWith = (options) => Effect.gen(function* () {
|
|
|
9281
9318
|
const queue = yield* Ref.make([]);
|
|
9282
9319
|
const using = options.tools ?? tools$2;
|
|
9283
9320
|
const helper = options.sparkle === void 0 ? locate$3.pipe(Effect.provideService(FileSystem.FileSystem, fs)) : Effect.succeed(options.sparkle);
|
|
9284
|
-
const
|
|
9321
|
+
const sparkleHelper = (pkg, install) => {
|
|
9285
9322
|
const refused = (reason) => new InstallRefused({
|
|
9286
9323
|
package: pkg.name,
|
|
9287
9324
|
reason
|
|
@@ -9292,10 +9329,8 @@ const makeWith = (options) => Effect.gen(function* () {
|
|
|
9292
9329
|
if (Option.isNone(found)) return yield* refused("this copy of upup has no upup-sparkle, which installs Sparkle apps' updates; build it with `vp run sparkle`");
|
|
9293
9330
|
if (install.installationType === "package" && found.value.team === null) return yield* refused("its update is an installer package, which Sparkle installs only through an upup-sparkle signed with a Developer ID, and this copy of upup's is signed ad hoc");
|
|
9294
9331
|
return {
|
|
9295
|
-
|
|
9296
|
-
helper: found.value
|
|
9297
|
-
build,
|
|
9298
|
-
feed: install.feed
|
|
9332
|
+
...install,
|
|
9333
|
+
helper: found.value
|
|
9299
9334
|
};
|
|
9300
9335
|
});
|
|
9301
9336
|
};
|
|
@@ -9320,21 +9355,23 @@ const makeWith = (options) => Effect.gen(function* () {
|
|
|
9320
9355
|
const inside = yield* hosts.pipe(Effect.mapError((error) => refused(`upup could not tell which app it runs in, so it risks none: ${describeError(error)}`)));
|
|
9321
9356
|
if (inside.paths.has(pkg.id) || inside.ids.has(bundle.bundleId)) return yield* refused(`upup is running inside ${pkg.name}; update it from another terminal app`);
|
|
9322
9357
|
yield* unchanged$1(pkg, plist);
|
|
9323
|
-
const planned = install.kind === "sparkle" ? yield*
|
|
9358
|
+
const planned = install.kind === "sparkle" ? yield* sparkleHelper(pkg, install) : install;
|
|
9324
9359
|
const writable = yield* Effect.isSuccess(Effect.all([fs.access(pkg.id, { writable: true }), fs.access(path.dirname(pkg.id), { writable: true })]));
|
|
9325
|
-
const ownsApp = install.kind === "sparkle" && (yield* owned(pkg.id));
|
|
9326
9360
|
const quitAllowed = permission?.quitApps === true;
|
|
9327
9361
|
yield* gate(pkg, bundle.bundleId, quitAllowed);
|
|
9328
9362
|
const team = yield* teamOf(pkg.id);
|
|
9329
9363
|
if (team === void 0) return yield* refused("it is not signed by a developer team, so upup cannot check its update");
|
|
9330
|
-
const version = {
|
|
9331
|
-
key: install.kind === "sparkle" ? "CFBundleVersion" : "CFBundleShortVersionString",
|
|
9332
|
-
value: offer.version
|
|
9333
|
-
};
|
|
9334
9364
|
const prepared = planned.kind === "sparkle" ? {
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9365
|
+
update: {
|
|
9366
|
+
kind: "sparkle",
|
|
9367
|
+
helper: planned.helper,
|
|
9368
|
+
build: offer.version,
|
|
9369
|
+
feed: planned.feed,
|
|
9370
|
+
requirement: requirement(bundle.bundleId, team)
|
|
9371
|
+
},
|
|
9372
|
+
dir: yield* room(pkg.name),
|
|
9373
|
+
root: !writable || planned.installationType === "package" || !(yield* owned(pkg.id))
|
|
9374
|
+
} : yield* Effect.map(stage(client, {
|
|
9338
9375
|
name: pkg.name,
|
|
9339
9376
|
url: planned.url,
|
|
9340
9377
|
...planned.size === void 0 ? {} : { size: planned.size },
|
|
@@ -9343,18 +9380,19 @@ const makeWith = (options) => Effect.gen(function* () {
|
|
|
9343
9380
|
team,
|
|
9344
9381
|
arch: listing.here.arch,
|
|
9345
9382
|
version: offer.version
|
|
9346
|
-
})
|
|
9347
|
-
|
|
9383
|
+
}), (staged) => ({
|
|
9384
|
+
update: staged,
|
|
9385
|
+
dir: staged.dir,
|
|
9386
|
+
root: !writable
|
|
9387
|
+
}));
|
|
9348
9388
|
yield* Ref.update(queue, (all) => [...all, {
|
|
9349
9389
|
pkg,
|
|
9350
9390
|
bundleId: bundle.bundleId,
|
|
9351
9391
|
executable: path.join("Contents", "MacOS", bundle.executable ?? pkg.name),
|
|
9352
9392
|
installed: plist,
|
|
9353
|
-
|
|
9354
|
-
dir,
|
|
9393
|
+
...prepared,
|
|
9355
9394
|
quitAllowed,
|
|
9356
|
-
|
|
9357
|
-
version,
|
|
9395
|
+
version: offer.version,
|
|
9358
9396
|
team
|
|
9359
9397
|
}]);
|
|
9360
9398
|
}, provide);
|
|
@@ -9364,9 +9402,10 @@ const makeWith = (options) => Effect.gen(function* () {
|
|
|
9364
9402
|
if (now.value === item.installed) return replaceable(now.value);
|
|
9365
9403
|
const { info, digest } = yield* readInfoStable(item.pkg.id);
|
|
9366
9404
|
if (Option.isNone(info) || digest !== now.value || info.value.CFBundleIdentifier !== item.bundleId || (yield* teamOf(item.pkg.id)) !== item.team) return changed;
|
|
9367
|
-
const
|
|
9368
|
-
|
|
9369
|
-
|
|
9405
|
+
const sparkle = item.update.kind === "sparkle";
|
|
9406
|
+
const version = sparkle ? info.value.CFBundleVersion : info.value.CFBundleShortVersionString;
|
|
9407
|
+
if (version === item.version) return alreadyUpdated;
|
|
9408
|
+
return version !== void 0 && (sparkle ? isNewer(item.version, version) : isNewerRelease(item.version, version)) ? replaceable(now.value) : changed;
|
|
9370
9409
|
}).pipe(Effect.orElseSucceed(() => changed));
|
|
9371
9410
|
const ready = (item) => Effect.gen(function* () {
|
|
9372
9411
|
const now = yield* installedNow(item);
|
|
@@ -9471,7 +9510,7 @@ const makeWith = (options) => Effect.gen(function* () {
|
|
|
9471
9510
|
uninstall: Effect.fn("Apps.uninstall")(function* (pkg) {
|
|
9472
9511
|
const token = (yield* Ref.get(memory))?.rows.get(pkg.id)?.cask;
|
|
9473
9512
|
if (token === void 0) return yield* new Unsupported({ reason: unremovable$1 });
|
|
9474
|
-
yield* exec.stdout(brew
|
|
9513
|
+
yield* exec.stdout(brew([
|
|
9475
9514
|
"uninstall",
|
|
9476
9515
|
"--cask",
|
|
9477
9516
|
token
|
|
@@ -9925,6 +9964,11 @@ const matchesGoPattern = (pattern, path) => {
|
|
|
9925
9964
|
const prefix = segments.slice(0, parts.length).join("/");
|
|
9926
9965
|
return new RegExp(`^${parts.map((part) => RegExp.escape(part).replaceAll("\\*", "[^/]*").replaceAll("\\?", "[^/]")).join("/")}$`, "u").test(prefix);
|
|
9927
9966
|
};
|
|
9967
|
+
const GoProxyEnv = Schema.Struct({
|
|
9968
|
+
GOPROXY: Schema.optionalKey(Schema.String),
|
|
9969
|
+
GOPRIVATE: Schema.optionalKey(Schema.String),
|
|
9970
|
+
GONOPROXY: Schema.optionalKey(Schema.String)
|
|
9971
|
+
});
|
|
9928
9972
|
const privateGoModule = (env, path) => {
|
|
9929
9973
|
if (goPatterns(env.GONOPROXY === void 0 || env.GONOPROXY === "" ? env.GOPRIVATE ?? "" : env.GONOPROXY).some((pattern) => matchesGoPattern(pattern, path))) return "a GOPRIVATE module";
|
|
9930
9974
|
const [proxy] = goPatterns((env.GOPROXY ?? "https://proxy.golang.org,direct").replaceAll("|", ","));
|
|
@@ -9942,7 +9986,21 @@ const privatePypiIndex = (env = process.env) => {
|
|
|
9942
9986
|
const index = env["UV_DEFAULT_INDEX"] ?? env["UV_INDEX_URL"] ?? env["PIP_INDEX_URL"];
|
|
9943
9987
|
return index === void 0 || index === "" || publicPypi.has(trailing(index)) ? void 0 : index;
|
|
9944
9988
|
};
|
|
9989
|
+
const withPypiOrigin = (index) => (pkg) => index === void 0 ? pkg : {
|
|
9990
|
+
...pkg,
|
|
9991
|
+
privateRegistry: index
|
|
9992
|
+
};
|
|
9945
9993
|
// src/go/go-json.ts
|
|
9994
|
+
const go = (cwd, args, env = {}) => ({
|
|
9995
|
+
command: "go",
|
|
9996
|
+
args,
|
|
9997
|
+
cwd,
|
|
9998
|
+
env: {
|
|
9999
|
+
GOWORK: "off",
|
|
10000
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
10001
|
+
...env
|
|
10002
|
+
}
|
|
10003
|
+
});
|
|
9946
10004
|
const decodeGoJson = (schema, command) => decodeJson(Schema.toCodecGoJson(schema), command);
|
|
9947
10005
|
const jsonObjects = (text) => {
|
|
9948
10006
|
const objects = [];
|
|
@@ -9971,22 +10029,14 @@ const jsonObjects = (text) => {
|
|
|
9971
10029
|
const GoEnv = Schema.Struct({
|
|
9972
10030
|
GOBIN: Schema.String,
|
|
9973
10031
|
GOPATH: Schema.String,
|
|
9974
|
-
|
|
9975
|
-
GOPRIVATE: Schema.optionalKey(Schema.String),
|
|
9976
|
-
GONOPROXY: Schema.optionalKey(Schema.String)
|
|
10032
|
+
...GoProxyEnv.fields
|
|
9977
10033
|
});
|
|
9978
|
-
const envKeys =
|
|
9979
|
-
"GOBIN",
|
|
9980
|
-
"GOPATH",
|
|
9981
|
-
"GOPROXY",
|
|
9982
|
-
"GOPRIVATE",
|
|
9983
|
-
"GONOPROXY"
|
|
9984
|
-
];
|
|
10034
|
+
const envKeys = Object.keys(GoEnv.fields);
|
|
9985
10035
|
const BuildInfo = Schema.Struct({
|
|
9986
|
-
Path: Schema.String,
|
|
10036
|
+
Path: Schema.optionalKey(Schema.String),
|
|
9987
10037
|
Main: Schema.Struct({
|
|
9988
|
-
Path: Schema.String,
|
|
9989
|
-
Version: Schema.String,
|
|
10038
|
+
Path: Schema.optionalKey(Schema.String),
|
|
10039
|
+
Version: Schema.optionalKey(Schema.String),
|
|
9990
10040
|
Sum: Schema.optionalKey(Schema.String),
|
|
9991
10041
|
Replace: Schema.optionalKey(Schema.Unknown)
|
|
9992
10042
|
})
|
|
@@ -9996,36 +10046,27 @@ const ModuleQuery = Schema.Struct({
|
|
|
9996
10046
|
Version: Schema.String,
|
|
9997
10047
|
Error: Schema.optionalKey(Schema.Struct({ Err: Schema.String }))
|
|
9998
10048
|
});
|
|
9999
|
-
const go = (args, env = {}) => ({
|
|
10000
|
-
command: "go",
|
|
10001
|
-
args,
|
|
10002
|
-
cwd: "/",
|
|
10003
|
-
env: {
|
|
10004
|
-
GOWORK: "off",
|
|
10005
|
-
GIT_TERMINAL_PROMPT: "0",
|
|
10006
|
-
...env
|
|
10007
|
-
}
|
|
10008
|
-
});
|
|
10009
10049
|
const executableName = (importPath) => {
|
|
10010
10050
|
const elements = importPath.split("/");
|
|
10011
10051
|
const last = elements.at(-1) ?? importPath;
|
|
10012
10052
|
return /^v\d+$/u.test(last) && elements.length > 1 ? elements.at(-2) ?? last : last;
|
|
10013
10053
|
};
|
|
10014
10054
|
const fromBuildInfo = (info, file) => {
|
|
10015
|
-
const { Main: main } = info;
|
|
10016
|
-
|
|
10055
|
+
const { Path: importPath, Main: main } = info;
|
|
10056
|
+
const { Path: module, Version: version } = main;
|
|
10057
|
+
return importPath !== void 0 && module !== void 0 && version !== void 0 && main.Sum !== void 0 && main.Replace === void 0 && semver.valid(version) !== null && (importPath === module || importPath.startsWith(`${module}/`)) && executableName(importPath) === file ? Option.some({
|
|
10017
10058
|
provider: "go-install",
|
|
10018
|
-
id:
|
|
10059
|
+
id: importPath,
|
|
10019
10060
|
name: file,
|
|
10020
10061
|
ecosystem: "go",
|
|
10021
|
-
artifact:
|
|
10022
|
-
current:
|
|
10062
|
+
artifact: module,
|
|
10063
|
+
current: version
|
|
10023
10064
|
}) : Option.none();
|
|
10024
10065
|
};
|
|
10025
10066
|
const make$8 = Effect.gen(function* () {
|
|
10026
10067
|
const exec = yield* Exec;
|
|
10027
10068
|
const fs = yield* FileSystem.FileSystem;
|
|
10028
|
-
const envInvocation = go([
|
|
10069
|
+
const envInvocation = go("/", [
|
|
10029
10070
|
"env",
|
|
10030
10071
|
"-json",
|
|
10031
10072
|
...envKeys
|
|
@@ -10033,7 +10074,7 @@ const make$8 = Effect.gen(function* () {
|
|
|
10033
10074
|
const goEnv = yield* Effect.cached(exec.stdout(envInvocation).pipe(Effect.flatMap(decodeGoJson(GoEnv, commandLine(envInvocation)))));
|
|
10034
10075
|
const binDir = goEnv.pipe(Effect.map((env) => env.GOBIN || path.join(env.GOPATH.split(":")[0] ?? env.GOPATH, "bin")));
|
|
10035
10076
|
const inspect = Effect.fn("GoInstall.inspect")(function* (dir, file) {
|
|
10036
|
-
const invocation = go([
|
|
10077
|
+
const invocation = go("/", [
|
|
10037
10078
|
"version",
|
|
10038
10079
|
"-m",
|
|
10039
10080
|
"-json",
|
|
@@ -10055,7 +10096,7 @@ const make$8 = Effect.gen(function* () {
|
|
|
10055
10096
|
});
|
|
10056
10097
|
const latest = Effect.fn("GoInstall.latest")(function* (modules) {
|
|
10057
10098
|
if (modules.length === 0) return /* @__PURE__ */ new Map();
|
|
10058
|
-
const invocation = go([
|
|
10099
|
+
const invocation = go("/", [
|
|
10059
10100
|
"list",
|
|
10060
10101
|
"-m",
|
|
10061
10102
|
"-e",
|
|
@@ -10105,7 +10146,7 @@ const make$8 = Effect.gen(function* () {
|
|
|
10105
10146
|
}),
|
|
10106
10147
|
update: Effect.fn("GoInstall.update")(function* (pkg, target) {
|
|
10107
10148
|
const dir = yield* binDir;
|
|
10108
|
-
yield* exec.stdout(go([
|
|
10149
|
+
yield* exec.stdout(go("/", [
|
|
10109
10150
|
"install",
|
|
10110
10151
|
"--",
|
|
10111
10152
|
`${pkg.id}@${target}`
|
|
@@ -10138,27 +10179,12 @@ const WorkFile = Schema.Struct({
|
|
|
10138
10179
|
Use: Schema.optionalKey(Schema.Array(Schema.Struct({ DiskPath: Schema.String }))),
|
|
10139
10180
|
Replace: Schema.optionalKey(Schema.Array(Schema.Struct({ Old: Schema.Struct({ Path: Schema.String }) })))
|
|
10140
10181
|
});
|
|
10141
|
-
const goEnv = {
|
|
10142
|
-
GOWORK: "off",
|
|
10143
|
-
GIT_TERMINAL_PROMPT: "0"
|
|
10144
|
-
};
|
|
10145
|
-
const GoProxyEnv = Schema.Struct({
|
|
10146
|
-
GOPROXY: Schema.optionalKey(Schema.String),
|
|
10147
|
-
GOPRIVATE: Schema.optionalKey(Schema.String),
|
|
10148
|
-
GONOPROXY: Schema.optionalKey(Schema.String)
|
|
10149
|
-
});
|
|
10150
10182
|
const directRequirements = (mod, local) => {
|
|
10151
10183
|
const replaced = new Set((mod.Replace ?? []).map((replace) => replace.Old.Path));
|
|
10152
10184
|
return (mod.Require ?? []).filter((requirement) => requirement.Indirect !== true && !replaced.has(requirement.Path) && !local.has(requirement.Path));
|
|
10153
10185
|
};
|
|
10154
|
-
const goIn = (cwd, args) => ({
|
|
10155
|
-
command: "go",
|
|
10156
|
-
args,
|
|
10157
|
-
cwd,
|
|
10158
|
-
env: goEnv
|
|
10159
|
-
});
|
|
10160
10186
|
const readModFile = (exec, cwd) => {
|
|
10161
|
-
const edit =
|
|
10187
|
+
const edit = go(cwd, [
|
|
10162
10188
|
"mod",
|
|
10163
10189
|
"edit",
|
|
10164
10190
|
"-json"
|
|
@@ -10168,13 +10194,13 @@ const readModFile = (exec, cwd) => {
|
|
|
10168
10194
|
const make$7 = (root, moduleDir, place = "", local = /* @__PURE__ */ new Set()) => Effect.gen(function* () {
|
|
10169
10195
|
const exec = yield* Exec;
|
|
10170
10196
|
const manifest = path.join(place, path.relative(root, path.join(moduleDir, "go.mod")));
|
|
10171
|
-
const
|
|
10197
|
+
const inModule = (args) => go(moduleDir, args);
|
|
10172
10198
|
const requirements = Effect.gen(function* () {
|
|
10173
10199
|
return directRequirements(yield* readModFile(exec, moduleDir), local);
|
|
10174
10200
|
});
|
|
10175
10201
|
const selected = Effect.fn("GoModule.selected")(function* (paths, withUpdates) {
|
|
10176
10202
|
if (paths.length === 0) return /* @__PURE__ */ new Map();
|
|
10177
|
-
const list =
|
|
10203
|
+
const list = inModule([
|
|
10178
10204
|
"list",
|
|
10179
10205
|
"-m",
|
|
10180
10206
|
...withUpdates ? ["-u"] : [],
|
|
@@ -10200,12 +10226,10 @@ const make$7 = (root, moduleDir, place = "", local = /* @__PURE__ */ new Set())
|
|
|
10200
10226
|
selector: requirement.Version
|
|
10201
10227
|
}
|
|
10202
10228
|
});
|
|
10203
|
-
const env =
|
|
10229
|
+
const env = inModule([
|
|
10204
10230
|
"env",
|
|
10205
10231
|
"-json",
|
|
10206
|
-
|
|
10207
|
-
"GOPRIVATE",
|
|
10208
|
-
"GONOPROXY"
|
|
10232
|
+
...Object.keys(GoProxyEnv.fields)
|
|
10209
10233
|
]);
|
|
10210
10234
|
const origin = exec.stdout(env).pipe(Effect.flatMap(decodeGoJson(GoProxyEnv, commandLine(env))), Effect.map(withGoOrigin));
|
|
10211
10235
|
const list = Effect.gen(function* () {
|
|
@@ -10236,16 +10260,16 @@ const make$7 = (root, moduleDir, place = "", local = /* @__PURE__ */ new Set())
|
|
|
10236
10260
|
return Option.some(toPackage(requirement, entries.get(requirement.Path)));
|
|
10237
10261
|
});
|
|
10238
10262
|
const update = Effect.fn("GoModule.update")(function* (pkg, target) {
|
|
10239
|
-
yield* exec.stdout(
|
|
10263
|
+
yield* exec.stdout(inModule(["get", `${pkg.id}@${target}`]));
|
|
10240
10264
|
});
|
|
10241
10265
|
const uninstall = Effect.fn("GoModule.uninstall")(function* (pkg) {
|
|
10242
|
-
yield* exec.stdout(
|
|
10266
|
+
yield* exec.stdout(inModule([
|
|
10243
10267
|
"mod",
|
|
10244
10268
|
"edit",
|
|
10245
10269
|
`-droprequire=${pkg.id}`
|
|
10246
10270
|
]));
|
|
10247
10271
|
});
|
|
10248
|
-
const reconcile = () => exec.stdout(
|
|
10272
|
+
const reconcile = () => exec.stdout(inModule(["mod", "tidy"])).pipe(Effect.as(void 0));
|
|
10249
10273
|
return {
|
|
10250
10274
|
name: manifest,
|
|
10251
10275
|
mode: "project",
|
|
@@ -10661,7 +10685,6 @@ const makeVp = makeGlobal({
|
|
|
10661
10685
|
list: [
|
|
10662
10686
|
"list",
|
|
10663
10687
|
"-g",
|
|
10664
|
-
"--depth=0",
|
|
10665
10688
|
"--json"
|
|
10666
10689
|
],
|
|
10667
10690
|
outdated: [
|
|
@@ -10794,7 +10817,6 @@ const make$6 = (root, dir = root, nested = []) => Effect.gen(function* () {
|
|
|
10794
10817
|
const client = yield* HttpClient.HttpClient;
|
|
10795
10818
|
const context = yield* Effect.context();
|
|
10796
10819
|
const scanned = scan(root, dir, nested).pipe(Effect.provideContext(context));
|
|
10797
|
-
const read = (file) => readText(path.join(root, file)).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
10798
10820
|
const list = Effect.gen(function* () {
|
|
10799
10821
|
const pins = yield* scanned;
|
|
10800
10822
|
const notices = [];
|
|
@@ -10833,19 +10855,15 @@ const make$6 = (root, dir = root, nested = []) => Effect.gen(function* () {
|
|
|
10833
10855
|
manifest: pkg.declaration?.manifest ?? "",
|
|
10834
10856
|
issue: `Node.js ${pkg.current} is no longer pinned there`
|
|
10835
10857
|
});
|
|
10836
|
-
|
|
10837
|
-
|
|
10838
|
-
|
|
10839
|
-
|
|
10840
|
-
|
|
10841
|
-
|
|
10842
|
-
|
|
10843
|
-
|
|
10844
|
-
|
|
10845
|
-
});
|
|
10846
|
-
edited.set(pin.file, moved.success);
|
|
10847
|
-
}
|
|
10848
|
-
for (const [file, text] of edited) yield* replaceText(path.join(root, file), text).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
10858
|
+
yield* editFiles(root, group.map((pin) => ({
|
|
10859
|
+
file: pin.file,
|
|
10860
|
+
edit: (text) => {
|
|
10861
|
+
const next = `${pin.prefix}${target}`;
|
|
10862
|
+
if (pin.path !== void 0) return editYamlScalar(text, pin.path, next);
|
|
10863
|
+
const { parts, at } = versionLine(text);
|
|
10864
|
+
return Result.succeed(parts.map((part, index) => index === at ? part.replace(`${pin.prefix}${pin.version}`, next) : part).join(""));
|
|
10865
|
+
}
|
|
10866
|
+
}))).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
10849
10867
|
});
|
|
10850
10868
|
return {
|
|
10851
10869
|
name: providerName,
|
|
@@ -11156,7 +11174,7 @@ const make$5 = (root, manager, place = "", claimed = []) => Effect.gen(function*
|
|
|
11156
11174
|
message: line.failure
|
|
11157
11175
|
});
|
|
11158
11176
|
const target = Result.getOrUndefined(line);
|
|
11159
|
-
if (target === void 0
|
|
11177
|
+
if (target === void 0) return pkg;
|
|
11160
11178
|
const selector = parseSelector(pkg.name, pkg.declaration?.selector ?? "");
|
|
11161
11179
|
if (selector === void 0 || moveTo(selector, target) === void 0) {
|
|
11162
11180
|
notices.push({
|
|
@@ -11827,13 +11845,10 @@ const make = Effect.gen(function* () {
|
|
|
11827
11845
|
"--show-python"
|
|
11828
11846
|
])).pipe(Effect.map(parseTools))], { concurrency: "unbounded" });
|
|
11829
11847
|
const targets = new Map(outdated.flatMap((tool) => tool.fromPyPI && tool.latest !== void 0 ? [[tool.pkg.id, tool.latest]] : []));
|
|
11830
|
-
const
|
|
11848
|
+
const origin = withPypiOrigin(privatePypiIndex());
|
|
11831
11849
|
return {
|
|
11832
11850
|
packages: packages.map((listed) => {
|
|
11833
|
-
const pkg =
|
|
11834
|
-
...listed,
|
|
11835
|
-
privateRegistry: index
|
|
11836
|
-
};
|
|
11851
|
+
const pkg = origin(listed);
|
|
11837
11852
|
const target = targets.get(pkg.id);
|
|
11838
11853
|
return target === void 0 ? pkg : withTarget(pkg, target);
|
|
11839
11854
|
}),
|
|
@@ -11925,12 +11940,12 @@ const deprecationOf = (formula) => {
|
|
|
11925
11940
|
if (formula.disabled) return `Homebrew disabled it (${formula.disable_reason ?? "no reason given"})`;
|
|
11926
11941
|
if (formula.deprecated) return formula.deprecation_reason ?? "no reason given";
|
|
11927
11942
|
};
|
|
11928
|
-
const lookup$
|
|
11943
|
+
const lookup$3 = Effect.fn("brew.lookup")(function* (client, wanted) {
|
|
11929
11944
|
if (wanted.name.includes("/")) return yield* new MetadataUnavailable({
|
|
11930
11945
|
source: wanted.name,
|
|
11931
11946
|
issue: "Homebrew's API only describes formulae and casks from the core taps"
|
|
11932
11947
|
});
|
|
11933
|
-
const kind = wanted.kind
|
|
11948
|
+
const kind = wanted.kind ?? "formula";
|
|
11934
11949
|
const formula = yield* getJson(client, `https://formulae.brew.sh/api/${kind}/${wanted.name}.json`, Formula);
|
|
11935
11950
|
const installs = formula.analytics?.install["30d"][wanted.name];
|
|
11936
11951
|
const deprecated = deprecationOf(formula);
|
|
@@ -11958,7 +11973,7 @@ const Crate = Schema.Struct({
|
|
|
11958
11973
|
yank_message: Schema.NullOr(Schema.String)
|
|
11959
11974
|
}))
|
|
11960
11975
|
});
|
|
11961
|
-
const lookup$
|
|
11976
|
+
const lookup$2 = Effect.fn("crates.lookup")(function* (client, wanted) {
|
|
11962
11977
|
const { crate, versions } = yield* getJson(client, `https://crates.io/api/v1/crates/${wanted.name}`, Crate);
|
|
11963
11978
|
const relevant = versions.filter((version) => wanted.versions.includes(version.num));
|
|
11964
11979
|
return {
|
|
@@ -11979,7 +11994,7 @@ const Repository = Schema.Struct({
|
|
|
11979
11994
|
archived: Schema.Boolean
|
|
11980
11995
|
});
|
|
11981
11996
|
const Release = Schema.Struct({ published_at: Schema.NullOr(Schema.String) });
|
|
11982
|
-
const lookup$
|
|
11997
|
+
const lookup$1 = Effect.fn("githubActions.lookup")(function* (client, wanted) {
|
|
11983
11998
|
const token = yield* githubToken.pipe(Effect.provide(nodeLayer));
|
|
11984
11999
|
const headers = githubHeaders(token);
|
|
11985
12000
|
const base = `${githubApi}/repos/${wanted.name}`;
|
|
@@ -11995,41 +12010,6 @@ const lookup$2 = Effect.fn("githubActions.lookup")(function* (client, wanted) {
|
|
|
11995
12010
|
withdrawn: {}
|
|
11996
12011
|
};
|
|
11997
12012
|
});
|
|
11998
|
-
// src/registry/npm.ts
|
|
11999
|
-
const Version = Schema.Struct({ deprecated: Schema.optionalKey(Schema.Unknown) });
|
|
12000
|
-
const Packument = Schema.Struct({
|
|
12001
|
-
description: Schema.optionalKey(Schema.String),
|
|
12002
|
-
homepage: Schema.optionalKey(Schema.String),
|
|
12003
|
-
repository: Schema.optionalKey(Schema.Union([Schema.String, Schema.Struct({ url: Schema.optionalKey(Schema.String) })])),
|
|
12004
|
-
"dist-tags": Schema.optionalKey(Schema.Struct({ latest: Schema.optionalKey(Schema.String) })),
|
|
12005
|
-
time: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
|
|
12006
|
-
versions: Schema.optionalKey(Schema.Record(Schema.String, Version))
|
|
12007
|
-
});
|
|
12008
|
-
const Downloads = Schema.Struct({ downloads: Schema.Finite });
|
|
12009
|
-
const message = (version) => {
|
|
12010
|
-
const deprecated = version?.deprecated;
|
|
12011
|
-
return Predicate.isString(deprecated) && deprecated !== "" ? Option.some(deprecated) : Option.none();
|
|
12012
|
-
};
|
|
12013
|
-
const lookup$1 = Effect.fn("npm.lookup")(function* (client, wanted) {
|
|
12014
|
-
const path = wanted.name.replace("/", "%2F");
|
|
12015
|
-
const [packument, downloads] = yield* Effect.all([getJson(client, `https://registry.npmjs.org/${path}`, Packument), getJson(client, `https://api.npmjs.org/downloads/point/last-week/${wanted.name}`, Downloads).pipe(Effect.option)], { concurrency: "unbounded" });
|
|
12016
|
-
const versions = packument.versions ?? {};
|
|
12017
|
-
const latest = packument["dist-tags"]?.latest;
|
|
12018
|
-
const repository = Predicate.isString(packument.repository) ? packument.repository : packument.repository?.url;
|
|
12019
|
-
const deprecated = latest === void 0 ? Option.none() : message(versions[latest]);
|
|
12020
|
-
return {
|
|
12021
|
-
...packument.description === void 0 ? {} : { description: packument.description },
|
|
12022
|
-
...packument.homepage === void 0 ? {} : { homepage: packument.homepage },
|
|
12023
|
-
...repository === void 0 ? {} : { repository: repositoryUrl(repository) },
|
|
12024
|
-
...Option.isSome(downloads) ? { popularity: `${count(downloads.value.downloads)} downloads last week` } : {},
|
|
12025
|
-
...Option.isSome(deprecated) ? { deprecated: deprecated.value } : {},
|
|
12026
|
-
released: pick$1(packument.time ?? {}, wanted.versions),
|
|
12027
|
-
withdrawn: Object.fromEntries(wanted.versions.flatMap((version) => Option.match(message(versions[version]), {
|
|
12028
|
-
onNone: () => [],
|
|
12029
|
-
onSome: (reason) => [[version, reason]]
|
|
12030
|
-
})))
|
|
12031
|
-
};
|
|
12032
|
-
});
|
|
12033
12013
|
// src/registry/pypi.ts
|
|
12034
12014
|
const Project = Schema.Struct({
|
|
12035
12015
|
info: Schema.Struct({
|
|
@@ -12079,12 +12059,12 @@ const vendor = (source, issue) => (_, wanted) => Effect.fail(new MetadataUnavail
|
|
|
12079
12059
|
issue: `${wanted.name} ${issue}`
|
|
12080
12060
|
}));
|
|
12081
12061
|
const sources = {
|
|
12082
|
-
brew: lookup$
|
|
12083
|
-
npm: lookup$
|
|
12084
|
-
crates: lookup$
|
|
12062
|
+
brew: lookup$3,
|
|
12063
|
+
npm: lookup$4,
|
|
12064
|
+
crates: lookup$2,
|
|
12085
12065
|
go: lookup$5,
|
|
12086
12066
|
pypi: lookup,
|
|
12087
|
-
"github-actions": lookup$
|
|
12067
|
+
"github-actions": lookup$1,
|
|
12088
12068
|
macos: vendor("Software Update", "comes from Apple's Software Update, which has no registry"),
|
|
12089
12069
|
apt: vendor("apt", "comes from your distribution's apt repositories, which upup does not read"),
|
|
12090
12070
|
sparkle: vendor("Sparkle", "updates from its own Sparkle feed, which has no registry"),
|
|
@@ -12101,7 +12081,7 @@ const freshFor = 864e5;
|
|
|
12101
12081
|
const wanted = (pkg) => ({
|
|
12102
12082
|
name: pkg.artifact,
|
|
12103
12083
|
versions: [pkg.current, ...pkg.target === void 0 ? [] : [pkg.target]],
|
|
12104
|
-
...
|
|
12084
|
+
...kindOf$2(pkg) === "cask" ? { kind: "cask" } : {}
|
|
12105
12085
|
});
|
|
12106
12086
|
const layer$2 = (cacheDir) => Layer.effect(Registry, Effect.gen(function* () {
|
|
12107
12087
|
const client = yield* HttpClient.HttpClient;
|
|
@@ -12438,15 +12418,16 @@ const auditTools = (home) => Action.implement(AuditActions, Effect.gen(function*
|
|
|
12438
12418
|
const audits = yield* Audits;
|
|
12439
12419
|
const ai = yield* Ai;
|
|
12440
12420
|
const status = (pkg, mode) => Effect.gen(function* () {
|
|
12441
|
-
const
|
|
12442
|
-
if (
|
|
12443
|
-
const reason =
|
|
12421
|
+
const audit = auditOf(pkg, mode);
|
|
12422
|
+
if (Result.isFailure(audit)) {
|
|
12423
|
+
const reason = audit.failure;
|
|
12444
12424
|
return {
|
|
12445
12425
|
key: rowKey(pkg),
|
|
12446
12426
|
status: "not-auditable",
|
|
12447
12427
|
reason: `${reason.charAt(0).toUpperCase()}${reason.slice(1)}.`
|
|
12448
12428
|
};
|
|
12449
12429
|
}
|
|
12430
|
+
const identity = audit.success;
|
|
12450
12431
|
const job = (yield* audits.jobs)[jobKey(identity)];
|
|
12451
12432
|
if (job?._tag === "Running") return {
|
|
12452
12433
|
key: rowKey(pkg),
|
|
@@ -12479,17 +12460,17 @@ const auditTools = (home) => Action.implement(AuditActions, Effect.gen(function*
|
|
|
12479
12460
|
}),
|
|
12480
12461
|
package_changes: ({ key, path, ...where }) => Effect.gen(function* () {
|
|
12481
12462
|
const { scope, pkg } = yield* resolve.one(where, key);
|
|
12482
|
-
const
|
|
12483
|
-
if (
|
|
12463
|
+
const audit = auditOf(pkg, scope.mode);
|
|
12464
|
+
if (Result.isFailure(audit)) {
|
|
12484
12465
|
if (pkg.target === void 0) return yield* new ChangesUnavailable({ issue: "No update is offered." });
|
|
12485
|
-
if (pkg.notes === void 0) return yield* new ChangesUnavailable({ issue: `Nothing to compare: ${
|
|
12466
|
+
if (pkg.notes === void 0) return yield* new ChangesUnavailable({ issue: `Nothing to compare: ${audit.failure}${isAppUpdate(pkg) ? ", and its feed has no release notes" : ""}.` });
|
|
12486
12467
|
if (path !== void 0) return yield* new ChangesUnavailable({ issue: `${pkg.name}'s update has release notes but no files to diff; leave out path.` });
|
|
12487
12468
|
return {
|
|
12488
12469
|
...versions(pkg),
|
|
12489
12470
|
notes: pkg.notes
|
|
12490
12471
|
};
|
|
12491
12472
|
}
|
|
12492
|
-
const view = yield* audits.changes(
|
|
12473
|
+
const view = yield* audits.changes(audit.success);
|
|
12493
12474
|
const files = view.sections.map((section) => ({
|
|
12494
12475
|
path: sectionPath(section),
|
|
12495
12476
|
...changedLines(section),
|
|
@@ -12794,33 +12775,34 @@ const reasonFor = (result) => Option.match(result, {
|
|
|
12794
12775
|
onNone: () => "it has no finished audit of these exact artifacts",
|
|
12795
12776
|
onSome: (found) => found._tag === "Failed" ? `its audit failed: ${found.issue}` : `its audit found ${found.report.verdict}`
|
|
12796
12777
|
});
|
|
12778
|
+
const approves = (result) => Option.isSome(result) && result.value._tag === "Reported" && result.value.report.verdict === "ok";
|
|
12797
12779
|
const screen = (targets, mode, resultOf) => Effect.gen(function* () {
|
|
12798
|
-
const identities = /* @__PURE__ */ new Map();
|
|
12799
|
-
for (const target of targets) {
|
|
12800
|
-
const identity = identityOf(target.pkg, mode);
|
|
12801
|
-
if (identity !== void 0) identities.set(workspaceKey(identity), identity);
|
|
12802
|
-
}
|
|
12803
|
-
const results = new Map(yield* Effect.forEach(identities, ([key, identity]) => Effect.map(resultOf(identity), (result) => [key, result]), { concurrency: 4 }));
|
|
12804
|
-
const approved = [];
|
|
12805
12780
|
const refused = {};
|
|
12781
|
+
const groups = /* @__PURE__ */ new Map();
|
|
12806
12782
|
for (const target of targets) {
|
|
12807
|
-
if (isUnauditedUpdate(target.pkg))
|
|
12808
|
-
|
|
12783
|
+
if (isUnauditedUpdate(target.pkg)) continue;
|
|
12784
|
+
const audit = auditOf(target.pkg, mode);
|
|
12785
|
+
if (Result.isFailure(audit)) {
|
|
12786
|
+
refused[rowKey(target.pkg)] = Outcome.Excluded({ reason: audit.failure });
|
|
12809
12787
|
continue;
|
|
12810
12788
|
}
|
|
12811
|
-
const
|
|
12812
|
-
const
|
|
12813
|
-
|
|
12814
|
-
|
|
12815
|
-
|
|
12816
|
-
|
|
12817
|
-
|
|
12818
|
-
}
|
|
12819
|
-
}
|
|
12820
|
-
refused[rowKey(target.pkg)] = Outcome.Excluded({ reason: result === void 0 ? unauditable(target.pkg) ?? "it has no exact update to audit" : reasonFor(result) });
|
|
12789
|
+
const key = workspaceKey(audit.success);
|
|
12790
|
+
const group = groups.get(key) ?? {
|
|
12791
|
+
identity: audit.success,
|
|
12792
|
+
members: []
|
|
12793
|
+
};
|
|
12794
|
+
group.members.push(target);
|
|
12795
|
+
groups.set(key, group);
|
|
12821
12796
|
}
|
|
12797
|
+
yield* Effect.forEach(groups.values(), ({ identity, members }) => Effect.map(resultOf(identity), (found) => {
|
|
12798
|
+
if (approves(found)) return;
|
|
12799
|
+
for (const target of members) refused[rowKey(target.pkg)] = Outcome.Excluded({ reason: reasonFor(found) });
|
|
12800
|
+
}), {
|
|
12801
|
+
concurrency: 4,
|
|
12802
|
+
discard: true
|
|
12803
|
+
});
|
|
12822
12804
|
return {
|
|
12823
|
-
approved,
|
|
12805
|
+
approved: targets.filter((target) => !Object.hasOwn(refused, rowKey(target.pkg))),
|
|
12824
12806
|
refused
|
|
12825
12807
|
};
|
|
12826
12808
|
});
|
|
@@ -13163,8 +13145,7 @@ const initial = (mode, scope, preferences, audits = {}, settingsIssue) => ({
|
|
|
13163
13145
|
selected: [],
|
|
13164
13146
|
operation: machine$1.initialState,
|
|
13165
13147
|
activity: {},
|
|
13166
|
-
|
|
13167
|
-
actions: {},
|
|
13148
|
+
ran: {},
|
|
13168
13149
|
installed: {},
|
|
13169
13150
|
removed: {},
|
|
13170
13151
|
password: void 0,
|
|
@@ -13457,8 +13438,7 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
13457
13438
|
const reset = (mode, scope) => SubscriptionRef.update(state, (current) => {
|
|
13458
13439
|
places.set(`${current.mode}:${current.scope}`, {
|
|
13459
13440
|
selected: current.selected,
|
|
13460
|
-
|
|
13461
|
-
actions: current.actions,
|
|
13441
|
+
ran: current.ran,
|
|
13462
13442
|
installed: current.installed,
|
|
13463
13443
|
removed: current.removed
|
|
13464
13444
|
});
|
|
@@ -13529,13 +13509,12 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
13529
13509
|
const confirmed = targets.filter((target) => accepted.includes(rowKey(target.pkg)));
|
|
13530
13510
|
const chosen = vetting ? vet(targets.filter((target) => !accepted.includes(rowKey(target.pkg))), current.mode).pipe(Effect.flatMap(({ approved, refused }) => update((latest) => ({
|
|
13531
13511
|
...latest,
|
|
13532
|
-
|
|
13533
|
-
...latest.
|
|
13534
|
-
...refused
|
|
13535
|
-
|
|
13536
|
-
|
|
13537
|
-
|
|
13538
|
-
...Object.fromEntries(Object.keys(refused).map((key) => [key, action]))
|
|
13512
|
+
ran: {
|
|
13513
|
+
...latest.ran,
|
|
13514
|
+
...Object.fromEntries(Object.entries(refused).map(([key, outcome]) => [key, {
|
|
13515
|
+
action,
|
|
13516
|
+
outcome
|
|
13517
|
+
}]))
|
|
13539
13518
|
}
|
|
13540
13519
|
})).pipe(Effect.as([...confirmed, ...approved])))) : Effect.succeed(targets);
|
|
13541
13520
|
yield* FiberHandle.run(operation, chosen.pipe(Effect.tap((approved) => update((latest) => ({
|
|
@@ -13553,13 +13532,12 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
13553
13532
|
} : {
|
|
13554
13533
|
...latest,
|
|
13555
13534
|
activity: without(latest.activity, event.key),
|
|
13556
|
-
|
|
13557
|
-
...latest.
|
|
13558
|
-
[event.key]:
|
|
13559
|
-
|
|
13560
|
-
|
|
13561
|
-
|
|
13562
|
-
[event.key]: action
|
|
13535
|
+
ran: {
|
|
13536
|
+
...latest.ran,
|
|
13537
|
+
[event.key]: {
|
|
13538
|
+
action,
|
|
13539
|
+
outcome: event.outcome
|
|
13540
|
+
}
|
|
13563
13541
|
},
|
|
13564
13542
|
installed: installedAfter(latest.installed, approved, event),
|
|
13565
13543
|
removed: removedAfter(latest.removed, approved, event),
|
|
@@ -13585,10 +13563,10 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
13585
13563
|
if ((yield* SubscriptionRef.get(state)).about[key] !== void 0) return;
|
|
13586
13564
|
yield* about.load(key, registry.lookup(pkg));
|
|
13587
13565
|
});
|
|
13588
|
-
const readTranscript = Effect.fn("Session.readTranscript")(function* (
|
|
13589
|
-
const known = (yield* SubscriptionRef.get(state)).transcripts[file];
|
|
13566
|
+
const readTranscript = Effect.fn("Session.readTranscript")(function* (paths) {
|
|
13567
|
+
const known = (yield* SubscriptionRef.get(state)).transcripts[paths.file];
|
|
13590
13568
|
if (known !== void 0 && known._tag !== "Unavailable") return;
|
|
13591
|
-
yield* transcripts.load(file, audits.transcript(
|
|
13569
|
+
yield* transcripts.load(paths.file, audits.transcript(paths));
|
|
13592
13570
|
});
|
|
13593
13571
|
const readChanges = Effect.fn("Session.readChanges")(function* (pkg) {
|
|
13594
13572
|
const current = yield* SubscriptionRef.get(state);
|
|
@@ -13749,7 +13727,7 @@ const silenceNodeWarningsWhileTuiDraws = () => {
|
|
|
13749
13727
|
};
|
|
13750
13728
|
const loadTui = Effect.suspend(() => {
|
|
13751
13729
|
silenceNodeWarningsWhileTuiDraws();
|
|
13752
|
-
return process.getBuiltinModule("node:ffi") === void 0 ? Effect.die(`upup's TUI needs Node 26.13 or newer; this is Node ${process.versions.node}`) : Effect.promise(async () => await import("./Tui-
|
|
13730
|
+
return process.getBuiltinModule("node:ffi") === void 0 ? Effect.die(`upup's TUI needs Node 26.13 or newer; this is Node ${process.versions.node}`) : Effect.promise(async () => await import("./Tui-Ri-yz-Sx.mjs"));
|
|
13753
13731
|
});
|
|
13754
13732
|
const open$1 = (begin, projectDir) => Effect.gen(function* () {
|
|
13755
13733
|
const { launch } = yield* loadTui;
|