@visulima/vis 1.0.0-alpha.19 → 1.0.0-alpha.20

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.
Files changed (107) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/LICENSE.md +187 -779
  3. package/README.md +1 -1
  4. package/dist/config/index.d.ts +535 -121
  5. package/dist/config/index.js +1 -1
  6. package/dist/packem_chunks/bin.js +380 -286
  7. package/dist/packem_chunks/config.js +15 -14
  8. package/dist/packem_chunks/doctor-probe.js +2 -2
  9. package/dist/packem_chunks/fix.js +9 -9
  10. package/dist/packem_chunks/handler.js +1 -1
  11. package/dist/packem_chunks/handler10.js +1 -2
  12. package/dist/packem_chunks/handler11.js +5 -1
  13. package/dist/packem_chunks/handler12.js +1 -5
  14. package/dist/packem_chunks/handler13.js +27 -1
  15. package/dist/packem_chunks/handler14.js +5 -20
  16. package/dist/packem_chunks/handler15.js +1 -1
  17. package/dist/packem_chunks/handler16.js +1 -1
  18. package/dist/packem_chunks/handler17.js +1 -1
  19. package/dist/packem_chunks/handler18.js +1 -1
  20. package/dist/packem_chunks/handler19.js +1 -5
  21. package/dist/packem_chunks/handler20.js +5 -2
  22. package/dist/packem_chunks/handler21.js +2 -18
  23. package/dist/packem_chunks/handler22.js +2 -1
  24. package/dist/packem_chunks/handler23.js +18 -1
  25. package/dist/packem_chunks/handler24.js +1 -5
  26. package/dist/packem_chunks/handler25.js +1 -1
  27. package/dist/packem_chunks/handler26.js +5 -3
  28. package/dist/packem_chunks/handler27.js +1 -1
  29. package/dist/packem_chunks/handler28.js +3 -1
  30. package/dist/packem_chunks/handler29.js +1 -7
  31. package/dist/packem_chunks/handler3.js +3 -3
  32. package/dist/packem_chunks/handler30.js +6 -22
  33. package/dist/packem_chunks/handler31.js +33 -3
  34. package/dist/packem_chunks/handler32.js +3 -1
  35. package/dist/packem_chunks/handler33.js +1 -2
  36. package/dist/packem_chunks/handler34.js +25 -24
  37. package/dist/packem_chunks/handler35.js +3 -3
  38. package/dist/packem_chunks/handler36.js +6 -21
  39. package/dist/packem_chunks/handler37.js +22 -428
  40. package/dist/packem_chunks/handler38.js +428 -6
  41. package/dist/packem_chunks/handler39.js +6 -5
  42. package/dist/packem_chunks/handler4.js +8 -2
  43. package/dist/packem_chunks/handler40.js +24 -10
  44. package/dist/packem_chunks/handler41.js +10 -24
  45. package/dist/packem_chunks/handler42.js +1 -1
  46. package/dist/packem_chunks/handler43.js +6 -6
  47. package/dist/packem_chunks/handler44.js +13 -13
  48. package/dist/packem_chunks/handler45.js +213 -3
  49. package/dist/packem_chunks/handler46.js +3 -27
  50. package/dist/packem_chunks/handler47.js +21 -161
  51. package/dist/packem_chunks/handler48.js +166 -33
  52. package/dist/packem_chunks/handler49.js +34 -0
  53. package/dist/packem_chunks/handler5.js +1 -8
  54. package/dist/packem_chunks/handler6.js +1 -1
  55. package/dist/packem_chunks/handler7.js +1 -1
  56. package/dist/packem_chunks/handler8.js +1 -1
  57. package/dist/packem_chunks/handler9.js +2 -1
  58. package/dist/packem_chunks/heal-accept.js +2 -2
  59. package/dist/packem_chunks/heal.js +1 -1
  60. package/dist/packem_chunks/help-command.js +16 -16
  61. package/dist/packem_chunks/index.js +6 -6
  62. package/dist/packem_chunks/keys-refresh.js +4 -0
  63. package/dist/packem_chunks/list.js +3 -0
  64. package/dist/packem_chunks/loader.js +1 -1
  65. package/dist/packem_chunks/prune.js +3 -0
  66. package/dist/packem_chunks/run.js +1 -0
  67. package/dist/packem_chunks/status.js +2 -0
  68. package/dist/packem_chunks/sync.js +2 -0
  69. package/dist/packem_chunks/sync2.js +2 -0
  70. package/dist/packem_chunks/tripwire.js +2 -0
  71. package/dist/packem_shared/advisories-DsynpacV.js +1 -0
  72. package/dist/packem_shared/{ai-analysis-C_GpXikx.js → ai-analysis-uYuTIIXi.js} +1 -1
  73. package/dist/packem_shared/{ai-cache-DrCLD4gc.js → ai-cache-DuwHYx2O.js} +1 -1
  74. package/dist/packem_shared/{ai-fix-CWOz12Om.js → ai-fix-DzrA-dVz.js} +4 -4
  75. package/dist/packem_shared/applyDefaults-BOVDw1jD.js +1 -0
  76. package/dist/packem_shared/build-scripts-DsWMSWDs.js +1 -0
  77. package/dist/packem_shared/{cache-directory-C_U1qsIw.js → cache-directory-DQak1Vjc.js} +1 -1
  78. package/dist/packem_shared/cyclonedx-CiHXuG8M.js +4 -0
  79. package/dist/packem_shared/dependency-scan-DC3nAFHS.js +1 -0
  80. package/dist/packem_shared/{docker-B4s1fjiN.js → docker-B-CIN_nj.js} +19 -19
  81. package/dist/packem_shared/{failure-log-CSC6KfcO.js → failure-log-C3LEMmkq.js} +1 -1
  82. package/dist/packem_shared/{flakiness-DUtrm-wS.js → flakiness-Dq6K4ymq.js} +1 -1
  83. package/dist/packem_shared/glob-MHJQjR39-CQ2GC0b_.js +1 -0
  84. package/dist/packem_shared/{lifecycle-CgK8pcfa.js → lifecycle-Dv3nAtoD.js} +2 -2
  85. package/dist/packem_shared/{lockfile-i-qvq_k8.js → lockfile-C5DYMHVq.js} +1 -1
  86. package/dist/packem_shared/manifests-B0fMp872.js +1 -0
  87. package/dist/packem_shared/min-release-age-BFozFonQ.js +34 -0
  88. package/dist/packem_shared/native-config-sync-Dvi1g2nQ.js +21 -0
  89. package/dist/packem_shared/registry-keys-CewRFW0e.js +1 -0
  90. package/dist/packem_shared/resolve-explicit-CC4Kifk5.js +5 -0
  91. package/dist/packem_shared/{run-summary-utils-CJv75pla.js → run-summary-utils-BaBGP3bo.js} +1 -1
  92. package/dist/packem_shared/{runtime-check-CBU6W8qG.js → runtime-check-BusAwPb2.js} +1 -1
  93. package/dist/packem_shared/scan-progress-CMynp3eA.js +2 -0
  94. package/dist/packem_shared/signatures-5ZdjJ2Pu.js +2 -0
  95. package/dist/packem_shared/{toolchain-B7dckBQ1.js → toolchain-Cc3cwyLP.js} +3 -3
  96. package/dist/packem_shared/typosquats-BCeR-sLf.js +1 -0
  97. package/dist/packem_shared/verify-07kUNTuP.js +1 -0
  98. package/dist/packem_shared/{vis-update-app-D0uL3eO5.js → vis-update-app-CFrlJ3mW.js} +1 -1
  99. package/index.d.ts +358 -0
  100. package/index.js +56 -53
  101. package/package.json +14 -13
  102. package/schemas/vis-config.schema.json +595 -100
  103. package/dist/packem_shared/applyDefaults-DLY94gWA.js +0 -1
  104. package/dist/packem_shared/dependency-scan-YdgNVvoz.js +0 -2
  105. package/dist/packem_shared/readTomlSync-1fKo0R52-DtxWULlF.js +0 -109
  106. package/dist/packem_shared/typosquats-B3A38-qx.js +0 -1
  107. package/dist/packem_shared/verify-WDStBFvK.js +0 -1
@@ -516,13 +516,55 @@ interface VisPlugin {
516
516
  */
517
517
  setup?: (hooks: Hookable<VisHooks>) => Promise<void> | void;
518
518
  }
519
+ /**
520
+ * The 8 Socket.dev-style supply-chain policies. Used in `security.policies`
521
+ * and `security.acceptedRisks[*].policies`. Kept as a const tuple so callers
522
+ * can import the runtime array (`POLICY_NAMES`) for iteration without
523
+ * drifting from the union type.
524
+ */
525
+ declare const POLICY_NAMES: readonly ["firstSeen", "installScripts", "license", "malware", "publisherChange", "score", "unexpectedDeps", "vulnerability"];
526
+ type PolicyName = (typeof POLICY_NAMES)[number];
527
+ /**
528
+ * Recognised input sources for the codeowners aggregator.
529
+ *
530
+ * - `project-json` — owners declared on each project's `project.json`.
531
+ * Canonical source; takes precedence over the other two on path conflicts.
532
+ * - `nested-codeowners` — `CODEOWNERS` files placed at arbitrary depth
533
+ * in the workspace tree (excluding the generated root file).
534
+ * - `package-json-maintainers` — fallback that reads each project's
535
+ * `package.json#maintainers` and emits one entry per project root for
536
+ * projects with no `project.json owners`. GitHub handles are extracted
537
+ * from each maintainer's `url` (e.g. `https://github.com/&lt;handle&gt;`).
538
+ */
539
+ type CodeownersSource = "nested-codeowners" | "package-json-maintainers" | "project-json";
519
540
  interface CodeownersConfig {
541
+ /** Markers that bracket the generated block when `preserveBlock` is set. */
542
+ blockMarker?: {
543
+ begin: string;
544
+ end: string;
545
+ };
520
546
  /** Workspace-level paths that apply outside any project (e.g., `.github/**`). */
521
547
  globalPaths?: Record<string, string[]>;
548
+ /** Glob patterns used to discover nested `CODEOWNERS` files. Defaults to `["**\/CODEOWNERS"]`. */
549
+ nestedIncludes?: string[];
522
550
  /** Sort order for generated entries — mirrors moon's `orderBy`. */
523
551
  orderBy?: "file-source" | "project-id";
552
+ /**
553
+ * When set, the generated content is spliced between
554
+ * {@link CodeownersConfig.blockMarker} markers in the existing file
555
+ * (markers are appended if missing) instead of overwriting the file.
556
+ */
557
+ preserveBlock?: boolean;
524
558
  /** Provider determines whether `channel` is emitted (GitHub supports it via comment). */
525
559
  provider?: "bitbucket" | "github" | "gitlab" | "other";
560
+ /**
561
+ * Header instruction shown to reviewers. Replaces the default
562
+ * "Update each project's project.json `owners` field…" line. Useful
563
+ * when the canonical regenerate path is a custom script.
564
+ */
565
+ regenerationCommand?: string;
566
+ /** Enabled input sources. Defaults to `["project-json"]`. */
567
+ sources?: CodeownersSource[];
526
568
  }
527
569
  /**
528
570
  * One user-declared customTypes entry. See `policy.customTypes.extraTypes`
@@ -576,7 +618,7 @@ interface OwnersEntry {
576
618
  */
577
619
  interface VisTaskConfig {
578
620
  /** Per-target overrides — same shape as `project.json#targets`. */
579
- targets?: Record<string, VisTargetConfiguration>;
621
+ tasks?: Record<string, VisTargetConfiguration>;
580
622
  }
581
623
  /**
582
624
  * Per-project metadata surfaced by `project.json`. Extended beyond the
@@ -619,10 +661,10 @@ interface ProjectJson {
619
661
  targets?: Record<string, VisTargetConfiguration>;
620
662
  }
621
663
  /**
622
- * A scope predicate used by {@link VisConfig.taskDefaults}.
664
+ * A predicate used by {@link VisConfig.scopedTasks}.
623
665
  * All listed constraints must match for the block to apply.
624
666
  */
625
- interface TaskDefaultsScope {
667
+ interface ScopedTasksMatch {
626
668
  /** Match on primary language. */
627
669
  language?: string | string[];
628
670
  /** Match on project layer. */
@@ -635,14 +677,14 @@ interface TaskDefaultsScope {
635
677
  tags?: string[];
636
678
  }
637
679
  /**
638
- * A single task-defaults block — a set of target defaults gated by an
639
- * optional scope predicate.
680
+ * A single scoped-tasks block — a set of task defaults gated by an
681
+ * optional match predicate.
640
682
  */
641
- interface TaskDefaultsBlock {
642
- /** Optional scope predicate; if omitted, the block applies universally. */
643
- scope?: TaskDefaultsScope;
644
- /** Target default configurations. */
645
- targets: Record<string, Partial<VisTargetConfiguration>>;
683
+ interface ScopedTasksBlock {
684
+ /** Optional match predicate; if omitted, the block applies universally. */
685
+ match?: ScopedTasksMatch;
686
+ /** Task default configurations, keyed by target name. */
687
+ tasks: Record<string, Partial<VisTargetConfiguration>>;
646
688
  }
647
689
  interface VisConfig {
648
690
  /** AI analysis configuration */
@@ -1293,6 +1335,22 @@ interface VisConfig {
1293
1335
  services?: "auto" | "ephemeral" | "off" | "persistent";
1294
1336
  };
1295
1337
  /**
1338
+ * Cascading scoped-task blocks. Each block may narrow its tasks to a
1339
+ * subset of projects via `match`. Blocks are evaluated in order; later
1340
+ * blocks override earlier ones when the same field is set.
1341
+ *
1342
+ * Match predicates are additive — if `match` is omitted, the block applies
1343
+ * to every project.
1344
+ * @example
1345
+ * ```
1346
+ * scopedTasks: [
1347
+ * { match: { tags: ["frontend"] }, tasks: { build: { cache: true } } },
1348
+ * { match: { projectType: "library" }, tasks: { lint: { cache: true } } },
1349
+ * ]
1350
+ * ```
1351
+ */
1352
+ scopedTasks?: ScopedTasksBlock[];
1353
+ /**
1296
1354
  * Default options for `vis secrets`. CLI flags always take precedence;
1297
1355
  * this block provides workspace-wide defaults so teams can commit config
1298
1356
  * once and every invocation picks it up.
@@ -1356,19 +1414,162 @@ interface VisConfig {
1356
1414
  */
1357
1415
  security?: {
1358
1416
  /**
1359
- * Map of package names/patterns to allow (true) or deny (false) build scripts.
1360
- * Packages not listed are denied by default.
1361
- * Equivalent to pnpm's `allowBuilds` setting.
1417
+ * Packages whose policy findings have been reviewed and explicitly
1418
+ * accepted. Matched against every policy unless `policies` narrows the
1419
+ * scope. Replaces the legacy `security.socket.acceptedRisks` map.
1420
+ *
1421
+ * Key format: package name (`"lodash"`), name@version
1422
+ * (`"lodash@4.17.21"`), or glob (`"@myorg/*"`). Unversioned keys match
1423
+ * all versions of that package.
1424
+ * @example
1425
+ * ```
1426
+ * acceptedRisks: {
1427
+ * "some-risky-pkg": {
1428
+ * reason: "Internal fork, low score expected",
1429
+ * acceptedAt: "2026-03-15T10:00:00Z",
1430
+ * acceptedScore: 0.25,
1431
+ * policies: ["score"],
1432
+ * expiresAt: "2026-12-31",
1433
+ * },
1434
+ * }
1435
+ * ```
1436
+ */
1437
+ acceptedRisks?: Record<string, {
1438
+ /** ISO 8601 timestamp when the risk was accepted. */
1439
+ acceptedAt: string;
1440
+ /**
1441
+ * The overall Socket.dev score at the time of acceptance,
1442
+ * in the range `[0, 1]` (mirrors `policies.score.minimum`).
1443
+ * Only relevant for the `score` policy; ignored elsewhere.
1444
+ */
1445
+ acceptedScore?: number;
1446
+ /**
1447
+ * ISO 8601 date (or datetime). After this point the acceptance
1448
+ * stops applying and vis emits a warning. Leave undefined for
1449
+ * non-expiring entries. Values that fail to parse as a Date
1450
+ * are rejected by the loader rather than silently treated as
1451
+ * "always expired".
1452
+ */
1453
+ expiresAt?: string;
1454
+ /**
1455
+ * Which policies this acceptance covers. When undefined the
1456
+ * acceptance applies to every policy finding on this package.
1457
+ */
1458
+ policies?: PolicyName[];
1459
+ /** User-provided reason for accepting the risk. */
1460
+ reason: string;
1461
+ }>;
1462
+ /**
1463
+ * Map of bin names (or `pkg#bin` qualifiers) blessed for shadowing.
1464
+ * When two installed packages expose the same bin name, vis flags
1465
+ * the collision in `vis security list` and the post-install drift
1466
+ * report — set the bin (or `pkg#bin`) to `true` here to suppress
1467
+ * the warning once you've reviewed the conflict.
1468
+ *
1469
+ * Port of LavaMoat allow-scripts' experimental `allowBins`.
1470
+ * Bare names match any conflicting bin with that name; the
1471
+ * `pkg#bin` form scopes the approval to a single package's bin.
1362
1472
  * @example
1363
1473
  * ```
1364
- * allowBuilds: {
1365
- * "esbuild": true,
1366
- * "core-js": false,
1367
- * "@prisma/client": true,
1474
+ * allowBins: {
1475
+ * tsc: true, // bless any 'tsc' bin
1476
+ * "typescript#tsc": true, // bless only typescript's 'tsc'
1368
1477
  * }
1369
1478
  * ```
1370
1479
  */
1371
- allowBuilds?: Record<string, boolean>;
1480
+ allowBins?: Record<string, boolean>;
1481
+ /**
1482
+ * Offline OSV advisory + `vis audit` configuration.
1483
+ *
1484
+ * Controls `vis audit --offline` and `vis advisories sync` behavior:
1485
+ * - `audit.advisories.source` is the OSV mirror to download from. It
1486
+ * must be `https://` and resolve to a host in `allowedHosts` (or one
1487
+ * of the built-in defaults).
1488
+ * - `audit.offlineByDefault` flips the default of `--offline`.
1489
+ *
1490
+ * Vulnerability severity gating and reachability filtering live under
1491
+ * `policies.vulnerability` (see below).
1492
+ */
1493
+ audit?: {
1494
+ /**
1495
+ * Offline advisory cache settings.
1496
+ */
1497
+ advisories?: {
1498
+ /**
1499
+ * Extra hosts permitted as `audit.advisories.source`. The
1500
+ * built-in allowlist is enforced even if this field is
1501
+ * omitted; entries here add to it.
1502
+ * @example ["mirror.corp.example.com"]
1503
+ */
1504
+ allowedHosts?: string[];
1505
+ /**
1506
+ * Number of hours after `lastSyncIso` before `vis audit`
1507
+ * prints a "your advisory cache may be stale" notice.
1508
+ * `vis audit` never auto-syncs — the user runs
1509
+ * `vis advisories sync` themselves.
1510
+ * @default 24
1511
+ */
1512
+ refreshIntervalHours?: number;
1513
+ /**
1514
+ * OSV mirror base URL (no trailing slash). Defaults to the
1515
+ * public Google Cloud Storage bucket. Override to point at a
1516
+ * corporate mirror; the hostname must appear in `allowedHosts`
1517
+ * (or one of the built-in defaults) and the scheme must be
1518
+ * `https://`.
1519
+ * @default "https://osv-vulnerabilities.storage.googleapis.com"
1520
+ */
1521
+ source?: string;
1522
+ /**
1523
+ * Sigstore signature verification for the OSV dump.
1524
+ * Requires the native binding to be built with the
1525
+ * `verify-signatures` Cargo feature (default in the release
1526
+ * build). Off by default — the upstream OSV bucket does not
1527
+ * ship signatures today.
1528
+ */
1529
+ verify?: {
1530
+ /**
1531
+ * Enable signature verification. The sync flow downloads
1532
+ * `&lt;eco>/all.zip.sig` next to the zip and aborts if it
1533
+ * cannot verify against `expectedIssuer` / `expectedSubject`.
1534
+ * @default false
1535
+ */
1536
+ enabled?: boolean;
1537
+ /** OIDC issuer that signed the bundle. */
1538
+ expectedIssuer?: string;
1539
+ /** OIDC subject (workload identity) that signed the bundle. */
1540
+ expectedSubject?: string;
1541
+ };
1542
+ };
1543
+ /**
1544
+ * Gates for the auto-fix flow (`vis audit --fix` /
1545
+ * `--fix-transitive`). The CLI prompts outside CI; inside CI
1546
+ * the flags refuse to run unless `--yes` is set and, for
1547
+ * transitives, `apply.transitive.enabled = true`.
1548
+ */
1549
+ apply?: {
1550
+ /**
1551
+ * Gates for `vis audit --fix-transitive`. Two-lock: the
1552
+ * CLI requires `--yes` AND this flag set to `true` before
1553
+ * it will rewrite override entries in CI.
1554
+ */
1555
+ transitive?: {
1556
+ /**
1557
+ * When true, allows `--fix-transitive` to run in CI
1558
+ * environments. Defaults to false because rewriting
1559
+ * overrides is a higher blast radius than bumping a
1560
+ * direct dep.
1561
+ * @default false
1562
+ */
1563
+ enabled?: boolean;
1564
+ };
1565
+ };
1566
+ /**
1567
+ * When true, `vis audit` skips network calls and queries the
1568
+ * offline cache. Equivalent to the CLI `--offline` flag.
1569
+ * @default false
1570
+ */
1571
+ offlineByDefault?: boolean;
1572
+ };
1372
1573
  /**
1373
1574
  * When true, prevents transitive dependencies from using exotic sources
1374
1575
  * (git repositories, direct tarball URLs). Only direct dependencies may
@@ -1377,54 +1578,301 @@ interface VisConfig {
1377
1578
  */
1378
1579
  blockExoticSubdeps?: boolean;
1379
1580
  /**
1380
- * Minimum number of minutes that must pass after a version is published
1381
- * before vis will allow installation. Reduces risk of installing
1382
- * compromised packages that are typically discovered within hours.
1383
- * Equivalent to pnpm's `minimumReleaseAge`.
1384
- * @default 0
1385
- * @example 1440 // 24 hours
1581
+ * Pre-install marshall pipeline packument-derived supply-chain
1582
+ * gates (author, provenance, new-bin, metadata, downloads,
1583
+ * expired-domains, signatures, archived-repo) that run before
1584
+ * `vis add` / `vis install &lt;pkg>` / `vis update &lt;pkg>` hand off to
1585
+ * the underlying package manager. Every entry is optional; omit a
1586
+ * key and the marshall runs with defaults. Set `enabled: false`
1587
+ * on a specific marshall to skip it without touching env vars.
1386
1588
  */
1387
- minimumReleaseAge?: number;
1589
+ marshalls?: {
1590
+ /** Archived-repo marshall (GitHub repository status). */
1591
+ archivedRepo?: {
1592
+ /** Package names to skip. */
1593
+ allowlist?: string[];
1594
+ /** Default: marshall is on. Set false to disable. */
1595
+ enabled?: boolean;
1596
+ /** GitHub PAT for the API call (5k/hr vs 60/hr). */
1597
+ githubToken?: string;
1598
+ };
1599
+ /** Author / publisher heuristics. */
1600
+ author?: {
1601
+ allowlist?: string[]; /** Days since the publisher's last release before flagging as error. */
1602
+ dormantErrorDays?: number;
1603
+ /** Days since the publisher's last release before flagging as warning. */
1604
+ dormantWarnDays?: number;
1605
+ enabled?: boolean; /** Window for the "new publisher on an established package" check. */
1606
+ newPublisherWindowDays?: number;
1607
+ /** Days since the resolved version was published — error threshold. */
1608
+ recentVersionErrorDays?: number;
1609
+ /** Days since the resolved version was published — warning threshold. */
1610
+ recentVersionWarnDays?: number;
1611
+ };
1612
+ /** Monthly download-count floor. */
1613
+ downloads?: {
1614
+ allowlist?: string[];
1615
+ enabled?: boolean; /** Below this monthly count → error (default: 20). */
1616
+ errorThreshold?: number;
1617
+ /** Below this monthly count → warning (default: 1000). */
1618
+ warnThreshold?: number;
1619
+ };
1620
+ /** Maintainer-email-domain NS lookup. */
1621
+ expiredDomains?: {
1622
+ /** Domains exempted from the check (legacy / internal). */
1623
+ allowDomains?: string[];
1624
+ allowlist?: string[]; /** DNS resolvers to query (default: system). */
1625
+ dnsServers?: string[];
1626
+ enabled?: boolean; /** Per-domain DNS timeout (default: 5000). */
1627
+ timeoutMs?: number;
1628
+ };
1629
+ /** README / license / repository presence checks. */
1630
+ metadata?: {
1631
+ allowlist?: string[]; /** Subset of checks to run. Default: all three. */
1632
+ checks?: ("license" | "readme" | "repo")[];
1633
+ enabled?: boolean;
1634
+ };
1635
+ /** New CLI-bin script introduced in this version. */
1636
+ newBin?: {
1637
+ allowlist?: string[];
1638
+ enabled?: boolean;
1639
+ };
1640
+ /** Provenance regression check. */
1641
+ provenance?: {
1642
+ allowlist?: string[];
1643
+ enabled?: boolean;
1644
+ };
1645
+ /**
1646
+ * ECDSA P-256 verification against npm's signing keys. Disabled
1647
+ * by default because npm coverage still has gaps that produce
1648
+ * noisy warnings on legitimate packages.
1649
+ */
1650
+ signatures?: {
1651
+ allowlist?: string[]; /** Default: marshall is *off*. Set true to enable. */
1652
+ enabled?: boolean;
1653
+ /** Override the keys endpoint (default: npm registry). */
1654
+ keysUrl?: string;
1655
+ /** How to treat an expired-but-known key. Default: "warning". */
1656
+ treatExpiredAs?: "error" | "warning";
1657
+ };
1658
+ };
1388
1659
  /**
1389
- * Package names/patterns excluded from minimumReleaseAge check.
1390
- * Equivalent to pnpm's `minimumReleaseAgeExclude`.
1391
- * @example ["webpack", "react", "@myorg/*"]
1660
+ * When true, `security.policies.installScripts.allow` keys are matched
1661
+ * as `name@version`. A version bump on an approved package drops it from
1662
+ * the allowlist until the new version is explicitly re-approved (port
1663
+ * of LavaMoat allow-scripts' version-aware policy matcher).
1664
+ *
1665
+ * After a version bump, run `vis approve-builds` or `vis security list`
1666
+ * — both surface a "Version drift" block with the suggested new key
1667
+ * (`old-key → new-key`) so you can update `vis.config.ts` by hand.
1668
+ * @default false
1392
1669
  */
1393
- minimumReleaseAgeExclude?: string[];
1670
+ pinVersions?: boolean;
1394
1671
  /**
1395
- * Socket.dev security intelligence configuration.
1396
- * When enabled, vis fetches package security scores, alerts, and report
1397
- * data from the Socket.dev API during install, update, and check commands.
1398
- * @see https://socket.dev
1672
+ * Supply-chain policy gates. Each sub-block enables one policy and
1673
+ * configures its behavior. When a sub-block is omitted the policy is
1674
+ * inactive. `acceptedRisks` (above) silences specific packages without
1675
+ * disabling a policy globally.
1676
+ *
1677
+ * The 8 policies are inspired by Socket.dev's classification:
1678
+ * - `malware` — Socket-flagged malicious packages
1679
+ * - `firstSeen` — packages published less than N minutes ago
1680
+ * - `unexpectedDeps` — packages outside an allow-list / baseline
1681
+ * - `publisherChange` — maintainer set changed between installs
1682
+ * - `installScripts` — preinstall/install/postinstall scripts
1683
+ * - `score` — Socket overall score below threshold
1684
+ * - `vulnerability` — OSV vulnerability findings
1685
+ * - `license` — SPDX allow / deny lists
1399
1686
  */
1400
- socket?: {
1687
+ policies?: {
1401
1688
  /**
1402
- * Packages whose low Socket.dev scores or alerts have been reviewed
1403
- * and explicitly accepted. These packages skip the confirmation
1404
- * prompt during `vis add` and show as "acknowledged" in `vis audit`.
1405
- *
1406
- * Key format: package name (`"lodash"`), name@version
1407
- * (`"lodash@4.17.21"`), or glob (`"@myorg/*"`).
1408
- * Unversioned keys match all versions of that package.
1689
+ * Minimum number of minutes that must pass after a version is
1690
+ * published before vis will allow installation. Migrated from
1691
+ * the legacy `security.minimumReleaseAge` field. Equivalent to
1692
+ * pnpm's `minimumReleaseAge`.
1693
+ * @default 0
1694
+ * @example { minutes: 1440, exclude: ["@myorg/*"] } // 24 hours
1695
+ */
1696
+ firstSeen?: {
1697
+ /**
1698
+ * Package names/patterns excluded from the firstSeen check.
1699
+ * Equivalent to pnpm's `minimumReleaseAgeExclude`.
1700
+ * @example ["webpack", "react", "@myorg/*"]
1701
+ */
1702
+ exclude?: string[];
1703
+ /** Minutes after publish before install is allowed. */
1704
+ minutes?: number;
1705
+ };
1706
+ /**
1707
+ * Build-script (pre/install/postinstall/prepare) controls.
1708
+ * Migrated from the legacy `security.allowBuilds` /
1709
+ * `security.strictDepBuilds` fields.
1710
+ * @example { allow: { esbuild: true }, strict: true }
1711
+ */
1712
+ installScripts?: {
1713
+ /**
1714
+ * Map of package names/patterns to allow (true) or deny
1715
+ * (false) build scripts. Packages not listed are denied
1716
+ * by default. Equivalent to pnpm's `allowBuilds`.
1717
+ */
1718
+ allow?: Record<string, boolean>;
1719
+ /**
1720
+ * When true, installation will fail (exit non-zero) if any
1721
+ * dependencies have unreviewed build scripts. Equivalent to
1722
+ * pnpm's `strictDepBuilds`.
1723
+ * @default false
1724
+ */
1725
+ strict?: boolean;
1726
+ };
1727
+ /**
1728
+ * SPDX license allow / deny lists. Deny wins on any sub-license
1729
+ * match in SPDX expressions (`(MIT OR GPL-3.0)` against
1730
+ * `deny: ["GPL-3.0"]` is blocked). Packages with no declared
1731
+ * license are flagged when `allow` is set.
1409
1732
  * @example
1410
1733
  * ```
1411
- * acceptedRisks: {
1412
- * "some-risky-pkg": {
1413
- * reason: "Internal fork, low score expected",
1414
- * acceptedAt: "2026-03-15T10:00:00Z",
1415
- * acceptedScore: 0.25,
1416
- * },
1734
+ * license: {
1735
+ * allow: ["MIT", "Apache-2.0", "BSD-3-Clause"],
1736
+ * deny: ["GPL-3.0", "AGPL-3.0"],
1417
1737
  * }
1418
1738
  * ```
1419
1739
  */
1420
- acceptedRisks?: Record<string, {
1421
- /** ISO 8601 timestamp when the risk was accepted. */
1422
- acceptedAt: string;
1423
- /** The overall Socket.dev score at the time of acceptance. */
1424
- acceptedScore: number;
1425
- /** User-provided reason for accepting the risk. */
1426
- reason: string;
1427
- }>;
1740
+ license?: {
1741
+ /**
1742
+ * SPDX identifiers that are explicitly permitted. When set,
1743
+ * any package whose declared license is not on this list is
1744
+ * blocked.
1745
+ */
1746
+ allow?: string[];
1747
+ /**
1748
+ * SPDX identifiers that are explicitly forbidden. Always
1749
+ * wins over `allow` when both reference the same identifier.
1750
+ */
1751
+ deny?: string[];
1752
+ };
1753
+ /**
1754
+ * Behavior when the Socket.dev feed flags a package as malicious
1755
+ * (`alerts[].type === "Malware"`).
1756
+ *
1757
+ * The default is cross-field: `{ mode: "block" }` whenever
1758
+ * `security.socket.enabled !== false` (the engine cannot evaluate
1759
+ * malware without Socket data), and `"off"` otherwise. Consumers
1760
+ * resolve this default at evaluation time.
1761
+ */
1762
+ malware?: {
1763
+ /**
1764
+ * - `"block"` — emit a block decision.
1765
+ * - `"warn"` — surface as a warning; do not gate exit code.
1766
+ * - `"off"` — disable the policy entirely.
1767
+ */
1768
+ mode?: "block" | "off" | "warn";
1769
+ };
1770
+ /**
1771
+ * Trust-level checking for package publishing. Migrated from the
1772
+ * legacy `security.trustPolicy*` fields. Equivalent to pnpm's
1773
+ * `trustPolicy`.
1774
+ * @example { mode: "no-downgrade", ignoreAfter: 43200 } // 30 days
1775
+ */
1776
+ publisherChange?: {
1777
+ /**
1778
+ * Package selectors excluded from the check.
1779
+ * Equivalent to pnpm's `trustPolicyExclude`.
1780
+ * @example ["chokidar@4.0.3"]
1781
+ */
1782
+ exclude?: string[];
1783
+ /**
1784
+ * Ignore packages published more than N minutes ago. Useful
1785
+ * for older packages that pre-date provenance support.
1786
+ * Equivalent to pnpm's `trustPolicyIgnoreAfter`.
1787
+ */
1788
+ ignoreAfter?: number;
1789
+ /**
1790
+ * - `"off"` — no trust checking (default).
1791
+ * - `"no-downgrade"` — block when a package's trust level
1792
+ * has decreased compared to previous releases (e.g., was
1793
+ * published by trusted publisher, now only has provenance).
1794
+ */
1795
+ mode?: "no-downgrade" | "off";
1796
+ };
1797
+ /**
1798
+ * Socket.dev overall-score threshold. Packages scoring below
1799
+ * `minimum` trigger a block decision (or interactive prompt
1800
+ * during `vis add`). Migrated from the legacy
1801
+ * `security.socket.minimumScore` field.
1802
+ * @example { minimum: 0.4 }
1803
+ */
1804
+ score?: {
1805
+ /**
1806
+ * Minimum overall Socket.dev score (0–1). Set to 0 to
1807
+ * disable the gate while keeping Socket data fetched.
1808
+ *
1809
+ * Consulted by `vis add`, `audit`, `doctor`, `check`, and
1810
+ * `update`; resolved once in `buildSocketOptions`, then
1811
+ * threaded through every consumer. Falls back to
1812
+ * `DEFAULT_LOW_SCORE_THRESHOLD` (`0.4`) when unset.
1813
+ */
1814
+ minimum?: number;
1815
+ };
1816
+ /**
1817
+ * Net-new transitive dependency detection. Either provide a
1818
+ * static allow-list, a baseline lockfile path (recommended), or
1819
+ * both — the intersection is enforced.
1820
+ * @example { baselineLockfile: "./security/lockfile.baseline.yaml" }
1821
+ */
1822
+ unexpectedDeps?: {
1823
+ /**
1824
+ * Allow-list of dependency names that may appear in the
1825
+ * resolved package set. Glob patterns are supported.
1826
+ * @example ["lodash", "axios", "@myorg/*"]
1827
+ */
1828
+ allow?: string[];
1829
+ /**
1830
+ * Path (absolute or relative to the workspace root) to a
1831
+ * baseline lockfile snapshot. The policy diffs the current
1832
+ * lockfile against this baseline and flags any package that
1833
+ * didn't exist before.
1834
+ * @example "./security/lockfile.baseline.yaml"
1835
+ */
1836
+ baselineLockfile?: string;
1837
+ };
1838
+ /**
1839
+ * OSV vulnerability gating. Migrated from the legacy
1840
+ * `security.audit.failOn` + `security.audit.usage` fields.
1841
+ */
1842
+ vulnerability?: {
1843
+ /**
1844
+ * Severity threshold that makes `vis audit` exit non-zero.
1845
+ * Equivalent to the CLI `--fail-on` flag.
1846
+ * @example "high"
1847
+ */
1848
+ failOn?: "critical" | "high" | "low" | "medium";
1849
+ /**
1850
+ * Reachability filter — only report vulnerabilities in
1851
+ * packages the workspace statically imports.
1852
+ */
1853
+ usage?: {
1854
+ /**
1855
+ * Packages to always treat as reachable even if no
1856
+ * static import is found.
1857
+ * @example ["esbuild", "webpack-cli"]
1858
+ */
1859
+ alwaysAssumeUsed?: string[];
1860
+ /**
1861
+ * Enable the reachability filter by default. Equivalent
1862
+ * to `--usage` on the CLI; `--no-usage` disables.
1863
+ * @default false
1864
+ */
1865
+ enabled?: boolean;
1866
+ };
1867
+ };
1868
+ };
1869
+ /**
1870
+ * Socket.dev data-source configuration. Connection knobs only — score
1871
+ * thresholds and accepted-risk overrides moved to `policies.score` and
1872
+ * `security.acceptedRisks` respectively.
1873
+ * @see https://socket.dev
1874
+ */
1875
+ socket?: {
1428
1876
  /**
1429
1877
  * Custom Socket.dev API token. Falls back to the public API token.
1430
1878
  * Set via VIS_SOCKET_TOKEN environment variable or here.
@@ -1441,50 +1889,12 @@ interface VisConfig {
1441
1889
  */
1442
1890
  enabled?: boolean;
1443
1891
  /**
1444
- * Minimum overall Socket.dev score (0–1) for a package to be
1445
- * accepted without a confirmation prompt during `vis add`.
1446
- * Packages scoring below this threshold trigger an interactive
1447
- * prompt asking the user to confirm. Set to 0 to disable.
1448
- * @default 0.4
1449
- */
1450
- minimumScore?: number;
1451
- /**
1452
1892
  * Request timeout in milliseconds for the Socket.dev API.
1453
1893
  * @default 15_000 (15 seconds)
1454
1894
  */
1455
1895
  timeoutMs?: number;
1456
1896
  };
1457
1897
  /**
1458
- * When true, installation will fail (exit non-zero) if any dependencies
1459
- * have unreviewed build scripts. Equivalent to pnpm's `strictDepBuilds`.
1460
- * @default false
1461
- */
1462
- strictDepBuilds?: boolean;
1463
- /**
1464
- * Trust level checking for package publishing.
1465
- * - "off": No trust checking (default)
1466
- * - "no-downgrade": Fail if a package's trust level has decreased
1467
- * compared to previous releases (e.g., was published by trusted
1468
- * publisher, now only has provenance).
1469
- * Equivalent to pnpm's `trustPolicy`.
1470
- * @default "off"
1471
- */
1472
- trustPolicy?: "no-downgrade" | "off";
1473
- /**
1474
- * Package selectors excluded from trust policy checks.
1475
- * Equivalent to pnpm's `trustPolicyExclude`.
1476
- * @example ["chokidar@4.0.3", "@babel/core@7.28.5"]
1477
- */
1478
- trustPolicyExclude?: string[];
1479
- /**
1480
- * Ignore the trust policy check for packages published more than
1481
- * the specified number of minutes ago. Useful for older packages
1482
- * that pre-date provenance support.
1483
- * Equivalent to pnpm's `trustPolicyIgnoreAfter` (10.27+).
1484
- * @example 43200 // 30 days
1485
- */
1486
- trustPolicyIgnoreAfter?: number;
1487
- /**
1488
1898
  * Package names to skip during typosquat detection.
1489
1899
  * Use this for internal packages or known-safe names that happen to
1490
1900
  * look similar to popular packages.
@@ -1563,24 +1973,6 @@ interface VisConfig {
1563
1973
  * @default false
1564
1974
  */
1565
1975
  strictEnv?: boolean;
1566
- /** Target default configurations */
1567
- targetDefaults?: Record<string, Partial<VisTargetConfiguration>>;
1568
- /**
1569
- * Cascading task-default blocks. Each block may scope its targets to a
1570
- * subset of projects via `scope`. Blocks are evaluated in order; later
1571
- * blocks override earlier ones when the same field is set.
1572
- *
1573
- * Scope matching is additive — if `scope` is omitted, the block applies
1574
- * to every project.
1575
- * @example
1576
- * ```
1577
- * taskDefaults: [
1578
- * { scope: { tags: ["frontend"] }, targets: { build: { cache: true } } },
1579
- * { scope: { projectType: "library" }, targets: { lint: { cache: true } } },
1580
- * ]
1581
- * ```
1582
- */
1583
- taskDefaults?: TaskDefaultsBlock[];
1584
1976
  /**
1585
1977
  * Named bundles of target dependencies, referenceable from any task's
1586
1978
  * `dependsOn`. `dependsOn: [{ group: "lint" }]` expands to every entry
@@ -1598,10 +1990,16 @@ interface VisConfig {
1598
1990
  * Task runner options forwarded verbatim to `defaultTaskRunner`.
1599
1991
  *
1600
1992
  * Includes `remoteCache` (HTTP or REAPI gRPC backend), `cacheDirectory`,
1601
- * `parallel`, `globalEnv`, `globalInputs`, `targetDefaults`, etc.
1993
+ * `parallel`, `globalEnv`, `globalInputs`, etc.
1602
1994
  * See `TaskRunnerOptions` for the full surface.
1603
1995
  */
1604
- taskRunnerOptions?: Partial<TaskRunnerOptions>;
1996
+ taskRunner?: Partial<TaskRunnerOptions>;
1997
+ /**
1998
+ * Workspace-wide task defaults keyed by target name. Applied universally
1999
+ * to every project that exposes a matching target. Use `scopedTasks` when
2000
+ * defaults should only apply to a subset of projects.
2001
+ */
2002
+ tasks?: Record<string, Partial<VisTargetConfiguration>>;
1605
2003
  /**
1606
2004
  * Toolchain (Node / pnpm / python / rust / ...) management. vis
1607
2005
  * delegates to whichever version manager (proto, mise, fnm, volta,
@@ -2258,14 +2656,24 @@ declare const definePlugin: (plugin: VisPlugin) => VisPlugin;
2258
2656
  declare const CONFIG_FILES: string[];
2259
2657
  /** Per-package overlay file names, checked in priority order. */
2260
2658
  declare const TASK_CONFIG_FILES: string[];
2659
+ /**
2660
+ * Default `security.policies.firstSeen.minutes` applied by `vis init`.
2661
+ * 2 days — long enough to filter out most rage-published malware while
2662
+ * staying short enough that genuine fixes still land in a working week.
2663
+ *
2664
+ * Note: this is NOT merged into `SECURITY_DEFAULTS` — leaving it undefined
2665
+ * preserves the "no opinion" semantics that downstream drift checks rely
2666
+ * on. `vis init` writes the value explicitly into the generated config.
2667
+ */
2668
+
2261
2669
  /**
2262
2670
  * Secure-by-default security settings based on npm supply chain best practices.
2263
2671
  *
2264
- * These defaults are applied automatically when using `defineConfig()` or `loadVisConfig()`.
2672
+ * Applied automatically when using `defineConfig()` or `loadVisConfig()`.
2265
2673
  * Users can override any value — their settings always take precedence.
2266
2674
  * @see https://github.com/lirantal/awesome-npm-security-best-practices
2267
2675
  */
2268
- declare const SECURITY_DEFAULTS: Required<Pick<NonNullable<VisConfig["security"]>, "blockExoticSubdeps" | "strictDepBuilds" | "trustPolicy" | "trustPolicyIgnoreAfter">>;
2676
+ declare const SECURITY_DEFAULTS: NonNullable<VisConfig["security"]>;
2269
2677
  /**
2270
2678
  * Apply secure defaults to a raw config object.
2271
2679
  * Merges `SECURITY_DEFAULTS` into `config.security`, preserving all user overrides.
@@ -2356,9 +2764,13 @@ declare const defineTaskConfig: (config: VisTaskConfig) => VisTaskConfig;
2356
2764
  *
2357
2765
  * export default defineConfig({
2358
2766
  * security: {
2359
- * allowBuilds: {
2360
- * esbuild: true,
2361
- * "@prisma/client": true,
2767
+ * policies: {
2768
+ * installScripts: {
2769
+ * allow: {
2770
+ * esbuild: true,
2771
+ * "@prisma/client": true,
2772
+ * },
2773
+ * },
2362
2774
  * },
2363
2775
  * },
2364
2776
  * });
@@ -2370,9 +2782,11 @@ declare const defineTaskConfig: (config: VisTaskConfig) => VisTaskConfig;
2370
2782
  *
2371
2783
  * export default defineConfig({
2372
2784
  * security: {
2373
- * // Relax cooldown to 24 hours instead of the default 14 days
2374
- * minimumReleaseAge: 1440,
2375
- * allowBuilds: { esbuild: true },
2785
+ * policies: {
2786
+ * // Relax cooldown to 24 hours instead of the default 14 days
2787
+ * firstSeen: { minutes: 1440 },
2788
+ * installScripts: { allow: { esbuild: true } },
2789
+ * },
2376
2790
  * },
2377
2791
  * });
2378
2792
  * ```