Skip to content

feat(release-kit): socket-release kit — payload, installer, bootstrap, gates, skills, tests - #19

Merged
John-David Dalton (jdalton) merged 9 commits into
mainfrom
release-templates
Aug 1, 2026
Merged

feat(release-kit): socket-release kit — payload, installer, bootstrap, gates, skills, tests#19
John-David Dalton (jdalton) merged 9 commits into
mainfrom
release-templates

Conversation

@jdalton

Copy link
Copy Markdown
Collaborator

What

The SocketDev/sauce half of the Socket Release Kit: a copy-in publishing engine under release-kit/payload/scripts/socket-release/, its installer + manifest verifier, three consumer examples, four repo gates, a five-skill family, and a fully offline test matrix (192 tests across 20 files).

Design

The payload is the product. Everything a consumer runs lives in release-kit/payload/scripts/socket-release/ — 96 files, byte-pinned by a committed kit-manifest.json (sha256 of the POST-format bytes; gen-manifest.mts --check and the coherence gate refuse drift). The installer (release-kit/install.mts) copies channel-mapped subsets (npm, crates, github-release, brew, plus the implied common) into a consumer's scripts/socket-release/, plans by default, refuses per-file conflicts without --force, and --verify byte-compares forever after. Consumers exclude the tree from their own formatters/linters — same posture as this repo's own oxlint ignore tail — because a formatter rewrite would permanently break parity.

The bootstrap is an idempotent state machine. Eight steps in canonical order — preflight · placeholder · npm-access-permissive · github-env · staged-config · trusted-publisher · npm-access-staged-only · verify — each a read → pure classify → pure plan → apply → re-read module (passed only when the re-read says done, never false-green). Receipts are a reporting cache keyed to sha256(slug + package); live detection is the only authority. Exit codes pinned: 0 planned/passed · 1 failed · 2 usage · 3 blocked on a human gate · 4 precondition. --json emits exactly one schema-valid document (hand-rolled validateRunJson, no schema dependency); plan mode writes nothing, not even the state file, and renders auth-dead reads as planned/auth-unavailable instead of failing a machine it cannot fix. Only fail-closed reads (an unreachable registry is never "unpublished") fail in both modes.

The irreversible act is hard opt-in. Publishing <name>@0.0.0 burns the version forever, so a default --apply run STOPS at the reserve-name gate; only --apply --reserve <exact-package-name> publishes (mismatch = exit 2 with saw/wanted; --yes never substitutes). Detection short-circuits on a live name, so a double-publish is structurally unreachable.

Publishing access is permissive-then-staged-only (owner directive). The placeholder apply ensures BOTH direct and staged publishing right after the publish creates the package — the one window the wide shape is ever applied; npm-access-permissive is a no-op the moment the name is live (a re-run can never re-widen). After trusted publishing stands (a DAG precondition, so direct is never disabled before OIDC works), npm-access-staged-only unchecks direct publishing in the npm web UI through the ONE sanctioned browser session, and verify FAILS a package left permissive with the exact remediation command. The page parser refuses unknown shapes rather than classifying them, and the three access states ship as golden HTML fixtures.

Human moments are fleet gates. Eight factories in the kit's _shared/human-gate.mts (four ported + reserve-name, placeholder-promote, web-auth-approve, gh-env), mirror-tested for the 6-line shape in CANONICAL_GATES. Org secrets are never a gate: a negative test asserts no output ever names the release App credentials as human work. API before browser everywhere — gh api PUT + list-before-POST for environments, browser fallback as gate text only.

Brew is checksums-authority. brew-publish.mts bumps a binary-download formula only for an already-cut release (tag on origin, published non-draft, all templated assets present) and derives every sha256 from the release's own checksums.txt (both grammars) — never re-hashing. The tap commit is a GitHub-signed API commit direct to the tap default branch (never a PR), re-read and re-parsed before success is claimed.

Gates in this repo: release-kit-is-coherent (manifest freshness, marker leaks, pure-module import discipline), release-kit-launches-are-sanctioned (payload text scan + lawViolations(lawfulLaunchOptions()) === []), release-kit-workflows-are-env-mapped (no ${{ in run bodies, SHA-pinned dated uses:, permissions + concurrency), release-kit-types-resolve (payload tsc, release tier) — all auto-discovered by pnpm run check.

Adoption path

  1. In the consumer: node <sauce>/release-kit/install.mts --target . --channels npm,github-release --apply, then pnpm add -D @socketsecurity/lib@6.5.2 @socketsecurity/sdk@4.1.3 playwright-core@1.61.1, commit.
  2. node scripts/socket-release/bootstrap.mts (plan) → --apply, following nextCommand and the gates: reserve the name, approve npm's web-2FA, promote the staged placeholder, until verify reports stood-up (trusted publisher conforming, environments branch-restricted, workflows on origin, publishing access staged-only).
  3. Releases from then on: bump + chore: bump version to <v>, dispatch npm publish from the Actions UI, promote with node scripts/socket-release/npm-publish.mts --approve; the tag + immutable release follow registry liveness (ORDER RULE). The four agent skills (npm-publish, gh-release, crates-publish, brew-tap) teach an agent each flow end to end; socket-release is the user-invoked installer skill.

The consumer-side install (deliverable 2) rides this payload byte-identically and is tracked separately.

Verification

  • pnpm exec vitest run test/repo/{unit,integration}/release-kit: 20 files, 192 tests, all passing, fully offline (fake seams; synthetic authority-annotated fixtures; no browser, no socket).
  • node release-kit/gen-manifest.mts --check exits 0 AFTER pnpm run format (R11 — a second format changes nothing).
  • All four new repo checks exit 0; pnpm run lint --all and pnpm run type pass; the payload tsc program is clean.
  • pnpm run generate:check passes with the five marketplace entries.
  • Real smokes: installer --apply/--verify into a temp consumer (81 files, byte-identical), bootstrap.mts --help → 0, --apply --dry-run → 2, unknown step → 2, --status → 0, and a real --dry-run --json plan run → exit 0, one schema-valid document, zero writes.
  • Nothing real happened: no publish, no dispatch, no environment created, no registry or GitHub mutation of any kind.

Pre-existing check --all failures on main (dispatch-table, ci.yml fleet env, stable-aliases, cargo-soak fixture, CLAUDE.md rule gaps, skill catalog, gen doc script path, telemetry env, hook overlap) are untouched by this branch.

Auto-applied by socket-wheelhouse sync-scaffolding into skills.
238 file(s) touched:
  - .claude/agents/fleet/pr-feedback.md
  - .claude/hooks/fleet/_shared/branch-switch.mts
  - .claude/hooks/fleet/_shared/fleet-env.mts
  - .claude/hooks/fleet/_shared/fleet-fork.mts
  - .claude/hooks/fleet/_shared/fleet-roster.mts
  - .claude/hooks/fleet/_shared/sfw-ca.mts
  - .claude/hooks/fleet/_shared/shell-command.mts
  - .claude/hooks/fleet/_shared/squash-sentinel.mts
  - .claude/hooks/fleet/no-fleet-fork-guard/index.mts
  - .claude/hooks/fleet/no-primary-branch-switch/README.md
  - .claude/hooks/fleet/no-primary-branch-switch/index.mts
  - .claude/hooks/fleet/no-primary-branch-switch/package.json
  - .claude/hooks/fleet/no-primary-branch-switch/tsconfig.json
  - .claude/hooks/fleet/no-version-bump-pr-guard/README.md
  - .claude/hooks/fleet/no-version-bump-pr-guard/index.mts
  - .claude/hooks/fleet/no-version-bump-pr-guard/package.json
  - .claude/hooks/fleet/no-version-bump-pr-guard/tsconfig.json
  - .claude/hooks/fleet/no-wheelhouse-pr-guard/README.md
  - .claude/hooks/fleet/no-wheelhouse-pr-guard/index.mts
  - .claude/hooks/fleet/no-wheelhouse-pr-guard/package.json
  ... and 218 more
zsh-word-split-nudge and scripts/fleet/_shared/locai.mts were renamed to zsh-word-split-guard and odai.mts by the cascade; these are the stale originals left behind.
… examples

The copy-in release engine (scripts/socket-release/): the ported fleet
publish stack (npm staged publishing, cargo, web-auth router, browser
session law), a NEW eight-step bootstrap (preflight, placeholder with
hard --reserve consent, npm-access-permissive, github-env,
staged-config, trusted-publisher, npm-access-staged-only, verify), the
NEW brew tier (checksums-authority formula bumps, direct tap commits),
github-release.mts (the registry-gated tag-gap healer), env-mapped
SHA-pinned workflow templates, and the publishing-access
permissive-then-staged-only machinery.

Plus the sauce-side kit tooling: kit-manifest.json generator (--check),
the channel-mapped installer (plan default, --apply, --force, --verify
byte-parity, --json), three consumer examples with expected-install
goldens, and the kit README (deferrals, contract-drift posture,
first-publish/first-brew procedures with factory-rendered gates).
shipped-surfaces classifies the new tree with a narrow marker
allowlist for the shared browser-profile literal.
Four auto-discovered repo checks: release-kit-is-coherent (manifest
freshness, fleet-marker leaks, no shipped tests, pure-module import
discipline), release-kit-launches-are-sanctioned (the wheelhouse text
scan over the payload plus the law self-check),
release-kit-workflows-are-env-mapped (no expressions in run bodies,
SHA-pinned dated uses, permissions + concurrency), and
release-kit-types-resolve (the payload tsc program, release tier). The
payload tree joins the repo-owned oxlint ignore tail: its bytes are the
shipped product — kit-manifest.json pins them and every consumer
byte-verifies them — so lint autofixes must never rewrite them; the
kit's own gates lint it instead.
Five skills under skills/socket-release/: the user-invoked installer
skill (clone sauce, install channels, pin deps, bootstrap through the
gates, playwright law verbatim) and four agent skills that operate the
shipped flows end to end — npm-publish (bootstrap with the
publishing-access permissive/staged-only steps, staged dispatch, soak,
--approve promote, backfill, deprecate-as-rollback), gh-release (ORDER
RULE, immutable three-step cut, checksums.txt, tag-gap healing),
crates-publish (staged model, trusted publishing, index-propagation
wait, yank-as-rollback), and brew-tap (tap layout, formula bump,
sha256 verification against the release's own manifest). Every command
each skill names resolves to a shipped script; every human moment is a
fleet gate. Marketplace + generated tables updated via generate.
Unit suites over the payload's pure core: plan DAG/resume/receipts,
state round-trip + contextKey invalidation, render + the hand-rolled
validateRunJson (accepts every committed run golden, rejects mutated
documents), the eight-factory gate mirror, kit config accept/reject,
preflight's ten check arms, placeholder consent + fail-closed
classification, env probes with exact gh api argv fixes, staged-config
byte-parity + conflict refusal + surgical package.json edit,
trusted-publisher fail-closed trust reads + revoke-then-create argv,
verify aggregation with the staged-only terminal assertion, the
publishing-access parser over the three golden pages + unknown-shape
refusal, brew formula round-trips + the four tap refusals with zero
commits, install manifest/planner, and the checksum-writer grammar
round-trip. Integration: the installer against real temp dirs per
example (expected-install parity, idempotent second apply, --verify),
and full in-process bootstrap runs on fully fake seams pinned to four
run goldens with exit codes 0/2/3/4. All fixtures synthetic,
authority-annotated; no test opens a socket or launches a browser.
Auto-applied by socket-wheelhouse sync-scaffolding into skills.
67 file(s) touched:
  - .claude/hooks/fleet/_shared/fleet-markers.mts
  - .claude/hooks/fleet/_shared/sfw-ca.mts
  - .claude/hooks/fleet/gh-token-hygiene-guard/index.mts
  - .claude/hooks/fleet/readme-fleet-shape-guard/index.mts
  - .claude/hooks/fleet/release-defers-to-script-guard/index.mts
  - .claude/hooks/fleet/rust-target-sweep-nudge/README.md
  - .claude/hooks/fleet/rust-target-sweep-nudge/index.mts
  - .claude/hooks/fleet/rust-target-sweep-nudge/package.json
  - .claude/hooks/fleet/rust-target-sweep-nudge/tsconfig.json
  - .claude/hooks/fleet/stale-process-sweeper/index.mts
  - .claude/skills/fleet/auditing-gha/SKILL.md
  - .claude/skills/fleet/cascading-fleet/SKILL.md
  - .claude/skills/fleet/deduping-dependencies/SKILL.md
  - .claude/skills/fleet/delegating-execution/SKILL.md
  - .claude/skills/fleet/guarding-paths/SKILL.md
  - .claude/skills/fleet/improve/SKILL.md
  - .claude/skills/fleet/locking-down-claude/SKILL.md
  - .claude/skills/fleet/looping-quality/SKILL.md
  - .claude/skills/fleet/measuring-ecosystem-impact/SKILL.md
  - .claude/skills/fleet/property-and-fuzz-testing/SKILL.md
  ... and 47 more
@jdalton
John-David Dalton (jdalton) merged commit 7b75e2c into main Aug 1, 2026
4 checks passed
@jdalton
John-David Dalton (jdalton) deleted the release-templates branch August 1, 2026 05:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant