Communitygithub.com

Endurecimiento de lanzamiento de paquetes npm

Una habilidad de agente que endurece los paquetes npm antes de su publicación pública: detecta secretos enviados, desajustes en el tiempo de ejecución mínimo y basura en el tarball. Funciona en cualquier agente compatible con habilidades.

¿Qué es Endurecimiento de lanzamiento de paquetes npm?

Esta habilidad guía a un agente de IA a través de un proceso sistemático para garantizar que un paquete npm sea honesto, inspeccionable y seguro antes de su publicación. Se enfoca en la verificación real sobre sensaciones subjetivas, cubriendo el contenido del tarball, el contrato de tiempo de ejecución, la integración continua, la configuración de GitHub y la higiene de actualización de dependencias. La habilidad es compatible con cualquier agente que admita habilidades, como Claude Code, Cursor y Codex, y se adapta al gestor de paquetes detectado (npm, pnpm o yarn). Proporciona pasos procesables para verificar el archivo package.json, ejecutar pruebas en la versión mínima de Node.js, revisar el tarball con `npm pack --dry-run`, configurar flujos de trabajo de CI y Dependabot de GitHub, aplicar configuraciones de seguridad del repositorio y administrar la autenticación de publicación con procedencia. El resultado final es un informe detallado de todo lo verificado, asegurando que no se pasen por alto secretos, desajustes de tiempo de ejecución ni archivos innecesarios.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add SSBrouhard/npm-package-release-hardening

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace Endurecimiento de lanzamiento de paquetes npm?

Objetivo

Llevar un paquete npm de "funciona localmente" a "honesto, inspeccionable y seguro de publicar". Priorizar la verificación real sobre las sensaciones subjetivas: contenido del tarball del paquete, contrato de tiempo de ejecución, CI, configuración de GitHub e higiene de actualización de dependencias.

Comenzar aquí

  1. Confirmar el repositorio exacto:
pwd
git status --short --branch
git remote -v
  1. Inspeccionar la superficie del paquete:
cat package.json
ls -la
find .github -maxdepth 3 -type f -print 2>/dev/null
  1. Detectar el gestor de paquetes a partir de los archivos de bloqueo:
  • package-lock.json -> npm
  • pnpm-lock.yaml -> pnpm
  • yarn.lock -> yarn

Usar los comandos npm a continuación como valores predeterminados, pero traducir al gestor de paquetes detectado cuando sea necesario.

Contrato del paquete

Hacer que package.json diga la verdad:

  • name: el destino de publicación es intencional y está disponible
  • version: la versión de publicación prevista actual
  • description, keywords: lo suficientemente útiles para la búsqueda en el registro
  • license: presente y coincide con LICENSE
  • repository, homepage, bugs: apuntan al repositorio público. Si la URL del repositorio público aún no es definitiva, marcar estos como una tarea TODO previa a la publicación explícita en lugar de omitirlos silenciosamente
  • type, exports, main, bin: coinciden con lo que los usuarios importarán o ejecutarán
  • files: limita el tarball a los artefactos publicables
  • engines.node: tiempo de ejecución mínimo que el paquete realmente admite
  • prepublishOnly o equivalente: evita publicar resultados de compilación obsoletos

Para paquetes CLI, confirmar que el destino bin está compilado, es ejecutable cuando corresponda y se haya probado mediante el comando que los usuarios ejecutarán.

Regla del piso de tiempo de ejecución

El motor Node es una promesa, no un adorno.

  • Si engines.node dice >=20, CI debe probar Node 20.
  • Mantener @types/node en la misma línea principal que el tiempo de ejecución mínimo compatible.
  • Preferir fijar exactamente @types/node al último parche en esa línea de tiempo de ejecución.
  • No fusionar aumentos principales de @types/node por encima del piso de tiempo de ejecución a menos que también se suba engines.node.
  • engines.node es informativo: npm solo advierte y no bloquea la instalación a menos que el usuario establezca engine-strict, por lo que CI en la versión de piso es lo que realmente hace cumplir la promesa.

Por qué: los tipos de Node son solo de desarrollo, pero cambian lo que TypeScript permite. @types/node@26 puede permitir que el código compile mientras usa APIs que fallan para usuarios en Node 20.

Comandos de verificación

Para proyectos npm:

npm ci
npm run build --if-present
npm test --if-present
npm audit --omit=dev
npm pack --dry-run

Para pnpm/yarn, usar los comandos equivalentes de instalación/compilación/prueba/auditoría/empaquetado. Si el soporte de auditoría difiere, decirlo en lugar de fingir.

Para CLI, también ejecutar al menos una prueba de humo externa:

node dist/path/to/cli.js --help
npm pack --dry-run

Si es práctico, instalar el .tgz empaquetado en un directorio temporal y ejecutar el binario exactamente como lo haría un usuario.

Revisión del tarball

npm pack --dry-run es la superficie de verdad del registro. Verificar:

  • incluye la salida compilada
  • incluye README.md y LICENSE
  • excluye solo basura fuente, archivos temporales, pruebas, documentos privados, fixtures, bases de datos locales, secretos
  • el tamaño del paquete es razonable
  • la ruta bin de CLI aparece en el tarball

Si falta files, agregarlo. No confiar en .gitignore como política de publicación.

Línea base de GitHub

Agregar o verificar:

  • .github/workflows/ci.yml
  • .github/dependabot.yml
  • .github/CODEOWNERS
  • .github/pull_request_template.md
  • SECURITY.md

Usar las versiones principales compatibles actuales para las acciones propiedad de GitHub. Si Actions advierte que un tiempo de ejecución de acción está obsoleto, actualizar la acción principal después de que CI pase.

CI generalmente debe incluir:

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@CURRENT_MAJOR
      - uses: actions/setup-node@CURRENT_MAJOR
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run build --if-present
      - run: npm test --if-present

Ajustar node-version al tiempo de ejecución mínimo compatible del paquete y reemplazar cada @CURRENT_MAJOR con la etiqueta principal actual de la acción (por ejemplo, actions/checkout@v4) — fijar a una versión principal real, nunca confirmar el marcador de posición.

Línea base de Dependabot

Configurar tanto las actualizaciones del paquete como de las Acciones de GitHub:

version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly
    open-pull-requests-limit: 5
    commit-message:
      prefix: deps
      include: scope

  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: weekly
    open-pull-requests-limit: 5
    commit-message:
      prefix: deps
      include: scope

Cuando Dependabot abre PRs inmediatamente después de que la configuración aterrice, tratar eso como prueba de que la configuración está activa. Triar los PRs; no fusionar ciegamente todas las comprobaciones verdes.

Triaje de Dependabot

Usar esta regla general:

  • Parche/menor de dependencia de tiempo de ejecución: fusionar si las comprobaciones pasan y las notas de la versión son aburridas.
  • Mayor de dependencia de tiempo de ejecución: inspeccionar las notas de la versión y probar el comportamiento real del paquete.
  • Mayor de herramienta de desarrollo: fusionar si la compilación/prueba/empaquetado pasan y no altera el contrato de tiempo de ejecución.
  • @types/node por encima del piso de tiempo de ejecución: cerrar o reemplazar con una fijación al piso de tiempo de ejecución.
  • Mayor de Acciones de GitHub: fusionar si CI pasa y elimina las advertencias de obsolescencia.

Si dos PRs entran en conflicto en un archivo de configuración pequeño, fusionar uno y actualizar el otro, o aplicar el segundo directamente con un comentario claro explicando que fue reemplazado.

Endurecimiento remoto de GitHub

Aplicar lo que el repositorio/cuenta admita, luego verificar la configuración real con gh o lecturas de API.

Configuraciones útiles:

gh repo edit OWNER/REPO \
  --delete-branch-on-merge \
  --enable-squash-merge \
  --enable-merge-commit=false \
  --enable-rebase-merge=false \
  --allow-update-branch

gh api --method PUT repos/OWNER/REPO/vulnerability-alerts --silent
gh api --method PUT repos/OWNER/REPO/automated-security-fixes --silent
gh api --method PUT repos/OWNER/REPO/actions/permissions/workflow \
  -f default_workflow_permissions=read \
  -F can_approve_pull_request_reviews=false --silent

Para listas de permitidos de Actions, preferir solo acciones propiedad de GitHub cuando el flujo de trabajo use solo acciones propiedad de GitHub. Si se requieren acciones de terceros, permitir explícitamente el conjunto más pequeño.

Los repositorios públicos generalmente desbloquean más controles de seguridad. Los repositorios privados en planes gratuitos pueden bloquear:

  • protección de rama o conjuntos de reglas
  • escaneo de código
  • escaneo de secretos
  • protección de push

Señalar claramente los bloqueadores. No informar controles no disponibles como habilitados.

Protección de rama

Cuando esté disponible, proteger la rama predeterminada con:

  • requerir pull request antes de fusionar
  • requerir comprobaciones de estado de CI
  • requerir que las ramas estén actualizadas si se ajusta al proyecto
  • requerir resolución de conversación
  • bloquear fuerzas de push
  • bloquear eliminaciones
  • requerir historial lineal si se usan fusiones solo squash

Después de habilitar la protección, dejar de hacer push directo a main a menos que el usuario lo solicite explícitamente y entienda la omisión.

Herramientas de PR con compuerta

Si se usa una herramienta de revisión/compuerta automatizada, asegurarse de que el remoto tenga una rama predeterminada/base antes de pedirle a la compuerta que cree un PR. Los nuevos remotos vacíos a menudo necesitan un push inicial a main primero; de lo contrario, la compuerta puede validar y hacer push a una rama de características pero fallar la creación del PR porque no hay una ref base.

Lista de verificación de publicación

Antes de npm publish:

  • npm whoami muestra la cuenta prevista
  • npm view PACKAGE_NAME name version confirma el estado del nombre
  • CI está verde en el commit que se está publicando
  • npm pack --dry-run ha sido revisado
  • los ejemplos de instalación/uso de README coinciden con el comportamiento real
  • repository, homepage y bugs resuelven al repositorio público real (o están marcados explícitamente como TODO si la URL no es definitiva)
  • no quedan alertas de seguridad/Dependabot que bloqueen el lanzamiento
  • el aumento de versión es intencional, etiquetado en git (git tag vX.Y.Z && git push --tags) y reflejado en un CHANGELOG o lanzamiento de GitHub
  • los paquetes con ámbito (@scope/name) se publican con --access public (los paquetes con ámbito son privados/restringidos por defecto)

Para cuentas que usan autenticación web/passkey/2FA:

npm publish --auth-type=web

Preferir publicar desde CI con procedencia para un enlace verificable de la cadena de suministro. La procedencia requiere un paquete público, un CI compatible como GitHub Actions y el permiso id-token: write en el trabajo:

npm publish --provenance --access public

Después de publicar:

npm view PACKAGE_NAME version
npm view PACKAGE_NAME bin files engines repository --json
npx -y PACKAGE_NAME --help

Si se publicó con procedencia, confirmar que el registro muestra la atestación de procedencia / "Built and signed" en la página del paquete.

Respuesta final

Informar solo lo que realmente se verificó:

  • comprobaciones del paquete ejecutadas
  • resultado del tarball
  • decisiones sobre PRs de dependencias
  • commits/PRs creados o fusionados
  • configuración de GitHub confirmada
  • controles bloqueados por plan/visibilidad
  • etiqueta de lanzamiento y estado de procedencia, si se publicó
  • comando de publicación o verificación posterior a la publicación si aún es propiedad del usuario

Skills relacionados