Repository navigation
Commit b9e106d
v5: socket.yml patch rollout config and filtering (#293)
* Plan staged patch rollout for v5
Adds the design for rolling Socket patches out gradually: a
`patches:` block in socket.yml that narrows what scan may patch
(paths, ecosystems, packages, severity floor, on/off), and a
severity-ordered per-run cap on new patches so each scan lands the
next few most critical fixes.
The plan splits the work into two parallel items with a frozen
interface, lists every hard-coded filter and where it belongs, and
covers the depscan autopatch follow-up. configuration.md now records
that socket-patch reads socket.yml for selection policy only, with
the trust boundary unchanged.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Revise rollout plan after adversarial review
Three independent reviews (ambiguity, churn, trust boundary) found
gaps that would have let the two implementations disagree or let a
repo file widen or stall the rollout. The plan now:
- matches paths against marker files with the backend's top-down
gitignore rules, so projectIgnorePaths means the same everywhere
- uses one data source for severity, supersession and ordering
- spends the budget only on patches the planning pass proves can
land, and admits nothing new when a lookup failed
- uses the merged recorded view in every mode and engine
- has depscan read the policy from the base commit for PR jobs
- hardens file handling (regular files, aliases, size, encoding,
trusted repo root) and reports what a policy hides
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Close interface gaps in the rollout plan
A final consistency pass found places where the two work items
would have produced incompatible code: base purls admitted in one
directory being charged again in the next, no defined hand-off of
the unfiltered offers from the severity filter to classification,
no shared repo-relative path helper, and override sources the JSON
must report but the interface could not carry. The shared contract
now defines each of these, and the parity tests match each engine's
budget scope.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Clarify who shapes scan's selection output
The plan said both that the selector returns the shared offers
struct (work item A) and that it returns admitted/deferred rows
(work item B). The selector now returns the offers, and B adds the
rollout stage after it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Add the socket.yml selection policy to core
New socket_patch_core::policy module: the SelectionPolicy, Offers and
repo-root helpers that the staged-rollout plan freezes as the shared
contract between the socket.yml work and the --max-new-patches work.
It reads the repo root's socket.yml/socket.yaml strictly and fails
closed: bad YAML, a misspelled `patches` block, unknown keys (with a
did-you-mean hint), wrong types, empty allowlists, bad globs and
anchors or aliases inside the keys we read are all errors that name
the key path. Path lists match marker files with npm `ignore`
semantics, walked top-down; a golden fixture generated from the npm
package pins that. The built-in test/fixture ignores become
overridable defaults for discovered roots.
--package matching moves to core so scan and the policy share it.
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Honor socket.yml patch policy in disk scans
scan now reads the repo root's socket.yml before any write and applies
its patches block in hosted, vendored and agent mode, --dry-run
included: path filters on project roots (PATH-glob matches also get
the built-in test/fixture ignores), ecosystem and package filters on
crawled packages, and a severity floor on the patches a package may
receive. An invalid or ambiguous file fails the run with exit 1 and
an errorCode before any request.
Packages that already carry a patch are never removed, upgraded or
replaced by the policy: they are held and reported under
policy.retained. A recorded patch below a new floor stays in place.
patches.enabled: false reports what would be patched and writes
nothing.
New flags: --no-socket-yml / SOCKET_NO_SOCKET_YML and
--min-severity / SOCKET_MIN_SEVERITY. Every successful scan --json
result gains a top-level policy block. A PATH outside the repository
root is a usage error.
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Apply socket.yml policy in the in-memory engine
selectHostedScanPaths now streams the root socket.yml/socket.yaml and
returns them as policyPaths; it drops test and fixture trees through
the policy's built-in default ignores instead of a hard-coded segment
list (structural excludes like node_modules and vendor stay fixed).
The session reads the policy before any root is processed: path
filters run before the project limit, ecosystem and package filters
on each root's packages, and the severity floor before selection. A
listed policy file that arrives without content, or an invalid one,
yields policyError with no root processed and no file changed. New
options noSocketYml, minSeverity and policyPaths; the result gains a
policy block. hosted-bundle and index.d.ts carry the new fields.
get now warns policy_bypassed when the repo's socket.yml would have
skipped the package it patches.
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Document the socket.yml patch policy
CLI_CONTRACT.md gains a "socket.yml patch policy" section (grammar,
precedence, paths, lookup, validation, commands, error codes and the
policy JSON block), the flag and env rows, and the "narrow or pace"
half of the trust-boundary rule. README adds a "Roll out gradually"
section with copyable socket.yml recipes, CHANGELOG lists the new
policy and the breaking scan changes, and the design docs record the
decisions made while building it.
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Harden the socket.yml policy after review
Fixes from an adversarial self-review of the policy work:
- A non-ASCII package spec no longer panics validation, and error
text, warnings and verbose lines drop terminal escapes and bidi or
zero-width characters.
- Ignore lists that fail to compile together are an error instead of
silently matching nothing, and the policy file is opened by its
resolved path without following a swapped-in symlink.
- A top-level key that looks like a misspelled `patches` (`patchs`),
a top-level merge key or an aliased key now fails closed.
- Repo-root lookup follows a `.git` symlink and trusts the checkout
owner under root and sudo, so CI containers keep the policy.
- The severity floor always reports the patch it held back, report-
only --json runs report what a floor or `enabled: false` hides, a
root skipped as a whole is always one entry and no longer prints
"No packages found", warnings print once per invocation, and the
policy line is omitted when there is nothing to say.
- policy entries are sorted and use canonical purls on disk and in
memory; the in-memory engine applies a socket.yml negation of a
built-in ignore to roots it was given, and policyError carries no
CLI-only remedy.
- A lockfile-less disk root matches path filters by its manifests.
Tests cover each fix, plus the prune universe, agent path filters, a
vendored package held byte-identical, and tighter oracles; docs are
corrected where they overstated what the human output names.
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Give the release test job more time
The optimized test job now has to build two more crates and one more
test binary for the socket.yml policy. It ran out of time on its last
40 minutes, about a minute short, and a docs-only change already takes
38. Raise the limit to 50 minutes so it can finish.
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Apply socket.yml paths during memory selection
The merged plan makes in-memory path selection two-phase: the host
fetches the root socket.yml first and passes its text to
selectHostedScanPaths. Selection now applies the full path policy, so
a negation such as `!/e2e/tests/` brings a test tree back in memory
exactly as on disk. A listed policy file that is missing, symlinked
or invalid returns policyError with nothing selected.
Selection returns policySha256, and the session fails closed when the
policy it reads differs. Roots the policy excludes keep their marker
files presence-only, so the session still lists them as filtered.
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Keep excluded roots out of the memory stream
Review follow-ups to two-phase selection:
- Roots the policy excludes are reported in ignoredSample instead of
streamed presence-only, so a repo with many fixture lockfiles no
longer runs into the session's file limit.
- A session that bypasses socket.yml while selection applied it now
fails closed instead of processing roots it never fetched.
- The docs say policy text must decode losslessly (TextDecoder drops
a BOM) and when policySha256 is null.
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Keep scan -h short with the policy flags
The v5 help rules cap each command's short help at about eight
options. `--no-socket-yml` and `--min-severity` pushed `scan -h` to
ten, so they now appear only in `scan --help`, like the other
advanced scan flags.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
* Fail report-only JSON when detail queries fail
A report-only `scan --json` (`--prune` with no mode) with a severity
floor or `enabled: false` fetches patch details to fill
`policy.filtered[]`. If every query failed it still printed a success
envelope and exited 0. It now reports the error and exits 1, like the
agent and vendored runs.
Human-mode policy warnings now print `Warning: <detail>` like the rest
of `scan`; the code stays in the JSON `warnings[]` entry.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent b97a1c2 commit b9e106d
49 files changed
Lines changed: 7891 additions & 204 deletions
File tree
- crates
- socket-patch-cli
- src
- commands
- scan
- tests
- hosted_memory_common
- socket-patch-core
- src
- hosted/memory
- policy
- tests/fixtures
- socket-patch-node/npm
- docs/design
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
652 | 652 | | |
653 | 653 | | |
654 | 654 | | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
655 | 679 | | |
656 | 680 | | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
657 | 706 | | |
658 | 707 | | |
659 | 708 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
| 62 | + | |
| 63 | + | |
62 | 64 | | |
63 | 65 | | |
64 | 66 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
413 | 413 | | |
414 | 414 | | |
415 | 415 | | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
416 | 420 | | |
417 | 421 | | |
418 | 422 | | |
| |||
647 | 651 | | |
648 | 652 | | |
649 | 653 | | |
| 654 | + | |
| 655 | + | |
650 | 656 | | |
651 | 657 | | |
652 | 658 | | |
| |||
692 | 698 | | |
693 | 699 | | |
694 | 700 | | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
695 | 767 | | |
696 | 768 | | |
697 | 769 | | |
| |||
0 commit comments