Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions .claude/skills/cascading-fleet/lib/cascade-template.sh

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions .claude/skills/cascading-fleet/lib/fleet-repos.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"$schema": "./fleet-repos.schema.json",
"repos": [
{
"name": "socket-addon",
"description": "NAPI .node binaries for @socketaddon/* npm packages"
},
{
"name": "socket-bin",
"description": "SEA-packed CLI distributions for @socketbin/* packages"
},
{
"name": "socket-btm",
"description": "Build toolchain — produces signed prebuilt binaries for @socketaddon/* and @socketbin/*"
},
{
"name": "socket-cli",
"description": "Command-line interface for socket.dev security analysis"
},
{
"name": "socket-lib",
"description": "Core library: fs, processes, HTTP, logging, env detection"
},
{
"name": "socket-mcp",
"description": "Model Context Protocol server for socket.dev integration"
},
{
"name": "socket-packageurl-js",
"description": "purl spec implementation for JavaScript"
},
{
"name": "socket-registry",
"description": "Optimized package overrides for Socket Optimize"
},
{
"name": "socket-sdk-js",
"description": "JavaScript SDK for the socket.dev API"
},
{
"name": "sdxgen",
"description": "CycloneDX and SPDX manifest generator (Socket dx gen)"
},
{
"name": "stuie",
"description": "Terminal UI library: OpenTUI + yoga-layout + React"
},
{
"name": "socket-wheelhouse",
"description": "Internal scaffolding template for socket-* repos"
}
]
}
5 changes: 3 additions & 2 deletions .claude/skills/cascading-fleet/lib/fleet-repos.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions .config/.markdownlint-cli2.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// markdownlint-cli2 configuration for fleet repos.
//
// Loaded by `pnpm run lint` (template/scripts/lint.mts invokes
// markdownlint-cli2 with `-c .config/.markdownlint-cli2.jsonc`).
//
// Two concerns:
// 1. Stock markdownlint rules — disable a handful that bite real prose
// without adding value, leave the rest at defaults.
// 2. Fleet-canonical custom rules under markdownlint-rules/ — these
// enforce the fleet's README hygiene contract (no private-repo
// mentions, no relative-path commands, README skeleton structure).
{
"config": {
"default": true,
// MD013 (line-length) bites code-block-heavy READMEs without warning.
// Disabled fleet-wide; reviewers catch genuinely-too-long prose.
"MD013": false,
// MD033 (no inline HTML) bites our <details> collapsed Development
// sections and Socket-badge img tags. Allow specific tags only.
"MD033": { "allowed_elements": ["details", "summary", "img", "br"] },
// MD041 (first-line-h1) is the contract; keep it on.
// MD024 (no-duplicate-heading) — siblings-only mode so that ### subsections
// can repeat under different ## parents (common in API docs).
"MD024": { "siblings_only": true }
},
// Globs: every *.md / *.mdx under the repo, except generated output,
// node_modules, vendored upstream trees, and CHANGELOG.md (auto-generated).
"globs": ["**/*.md", "**/*.mdx"],
"ignores": [
"**/node_modules/**",
"**/dist/**",
"**/build/**",
"**/coverage/**",
"**/vendor/**",
"**/upstream/**",
"**/third_party/**",
"**/CHANGELOG.md",
// .claude/ markdown is internal scaffolding (hook READMEs, agent
// role files, skill SKILL.mds, command reminders) — scoped docs
// with their own shape conventions. Excluded from the public-
// facing markdown lint surface.
"**/.claude/**"
],
// Custom rule plugins live under markdownlint-rules/, byte-identical
// across the fleet via sync-scaffolding manifest registration.
"customRules": [
"./markdownlint-rules/socket-no-private-wheelhouse-leak.mjs",
"./markdownlint-rules/socket-no-relative-sibling-script.mjs",
"./markdownlint-rules/socket-readme-required-sections.mjs"
]
}
14 changes: 14 additions & 0 deletions .config/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,17 @@
template/.claude/hooks/_shared/acorn/acorn.wasm
template/.claude/hooks/_shared/acorn/acorn-bindgen.cjs
.claude/hooks/_shared/acorn/acorn-bindgen.cjs

# Vendored / upstream trees — kept byte-identical with their source
# of truth. Per CLAUDE.md "Untracked-by-default for vendored / build-
# copied trees": these are someone else's source, not ours, and the
# formatter would happily rewrite (e.g.) an upstream HTML test
# fixture or shipped third-party JS into our local style.
**/upstream/**
upstream/**
**/vendor/**
vendor/**
**/third_party/**
third_party/**
**/external/**
external/**
39 changes: 39 additions & 0 deletions .config/markdownlint-rules/_shared/wheelhouse-self-skip.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @file Shared helper for fleet markdown rules: detect whether the lint
* is running inside socket-wheelhouse itself, in which case the rule
* should bail. The custom rules in this directory exist to protect
* PUBLIC fleet consumers from leaking internal scaffolding; wheelhouse
* referencing itself in its own docs is the canonical case and must
* not trigger.
*
* Detection prefers explicit env override (CI sets
* SOCKET_FLEET_REPO_NAME) then falls back to checking the cwd's
* basename and git remote.
*/

import { execSync } from 'node:child_process'
import path from 'node:path'

export function isInsideWheelhouse() {
const envName = process.env['SOCKET_FLEET_REPO_NAME']
if (envName) {
return envName === 'socket-wheelhouse'
}
const cwd = process.cwd()
if (path.basename(cwd) === 'socket-wheelhouse') {
return true
}
// Fallback: probe the git remote URL. Tolerates renamed local
// checkout dirs (`~/projects/wheelhouse/` would still match).
try {
const remote = execSync('git config --get remote.origin.url', {
cwd,
stdio: ['ignore', 'pipe', 'ignore'],
})
.toString()
.trim()
return /[/:]socket-wheelhouse(?:\.git)?$/.test(remote)
} catch {
return false
}
}
63 changes: 63 additions & 0 deletions .config/markdownlint-rules/socket-no-private-wheelhouse-leak.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* @file Flag mentions of `socket-wheelhouse` in public-facing markdown.
*
* socket-wheelhouse is a private repo. Public READMEs / docs / release notes
* that link to it leak the internal tooling layout to users who can't access
* the link anyway. Whatever the markdown is trying to teach should be
* rewritten to not require the reference.
*
* Detects:
* - The literal token `socket-wheelhouse` (case-insensitive) anywhere
* in a line.
* - `https://github.com/SocketDev/socket-wheelhouse...` URL forms.
*
* Skips fenced code blocks because those are intentional examples
* (and fenced-block scanning would false-positive on the very
* markdownlint config that references this file).
*
* No autofix: the right rewrite is contextual.
*/

import { isInsideWheelhouse } from './_shared/wheelhouse-self-skip.mjs'

const RULE_NAME = 'socket-no-private-wheelhouse-leak'
const FORBIDDEN_TOKEN_RE = /socket-wheelhouse/i

/** @type {import("markdownlint").Rule} */
const rule = {
names: [RULE_NAME, 'socket/no-private-wheelhouse-leak'],
description:
'socket-wheelhouse is a private repo — never reference it in public markdown',
tags: ['socket', 'privacy'],
parser: 'none',
function(params, onError) {
if (isInsideWheelhouse()) {
return
}
let inFence = false
for (let i = 0; i < params.lines.length; i += 1) {
const line = params.lines[i]
// Track fenced-code state. Open/close on lines that START with ``` or ~~~.
if (/^\s*(?:```|~~~)/.test(line)) {
inFence = !inFence
continue
}
if (inFence) {
continue
}
const match = FORBIDDEN_TOKEN_RE.exec(line)
if (!match) {
continue
}
onError({
lineNumber: i + 1,
detail:
'Rewrite to not mention socket-wheelhouse — it is a private repo and the link will 404 for outside readers.',
context: line.trim().slice(0, 120),
range: [match.index + 1, match[0].length],
})
}
},
}

export default rule
68 changes: 68 additions & 0 deletions .config/markdownlint-rules/socket-no-relative-sibling-script.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* @file Flag commands that reference sibling repos via relative paths.
*
* `node ../socket-foo/scripts/bar.mts` in a fleet README assumes the
* reader has the sibling repo checked out at exactly the right level
* relative to the current repo. That's almost never true for an
* outside user, and the command silently fails.
*
* Detects (inside fenced code blocks and inline `code`):
* - `node ../<segment>/...` invocations
* - `pnpm ../<segment>/...` invocations
* - Bare `../socket-<segment>/...` references in code/inline-code
*
* Skips: relative paths to the current repo's own tree (`./scripts/`,
* `../package.json` within a monorepo), which are useful and don't
* leak sibling state.
*
* No autofix: the rewrite is to either inline the script's content or
* publish the helper to npm and reference the published name.
*/

import { isInsideWheelhouse } from './_shared/wheelhouse-self-skip.mjs'

const RULE_NAME = 'socket-no-relative-sibling-script'
const SIBLING_PATH_RES = [
// Detect `<runner> ../<sibling>/...` where runner is node/pnpm/npm/yarn/bun
// (anything resembling a runtime invocation).
/\b(?:node|pnpm|npm|yarn|bun|deno)\s+\.\.\/[\w@-]+\//,
// Detect bare ../<segment>/ where the first segment doesn't start with `.`
// (i.e. genuine sibling, not the current repo's `..` for monorepo packages).
/(?:^|\s)\.\.\/socket-[\w-]+\//i,
/(?:^|\s)\.\.\/sdxgen\//,
/(?:^|\s)\.\.\/stuie\//,
]

/** @type {import("markdownlint").Rule} */
const rule = {
names: [RULE_NAME, 'socket/no-relative-sibling-script'],
description:
'Commands referencing sibling fleet repos via relative paths fail for outside readers',
tags: ['socket', 'fleet'],
parser: 'none',
function(params, onError) {
if (isInsideWheelhouse()) {
return
}
for (let i = 0; i < params.lines.length; i += 1) {
const line = params.lines[i]
for (let j = 0; j < SIBLING_PATH_RES.length; j += 1) {
const re = SIBLING_PATH_RES[j]
const match = re.exec(line)
if (!match) {
continue
}
onError({
lineNumber: i + 1,
detail:
'Rewrite the command to not depend on a sibling-repo checkout. Inline the script, link to its source on GitHub, or publish the helper to npm and reference the package name.',
context: line.trim().slice(0, 120),
range: [match.index + 1, match[0].length],
})
break
}
}
},
}

export default rule
Loading
Loading