Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -8895,6 +8895,28 @@
"Registered by one session and closed by another within the hour. Recorded plainly: the value of the row was making a permanently red required-adjacent job visible, not owning the repair."
],
"dependencyDisposition": "none"
},
{
"id": "GT-634",
"closedAt": "2026-07-30",
"closureCommit": "f84fe739",
"evidence": [
"src/sdk/cli/package.json",
"src/packages/mcp-server/package.json",
"package-lock.json",
"CHANGELOG.md",
"src/sdk/cli/scripts/check-install-smoke.mjs"
],
"validationCommands": [
"PUBLISHED AND VERIFIED AGAINST THE REGISTRY, not against a green workflow: run 30548042781 succeeded, `npm view @beyondnet/evolith-{cli,mcp} version --prefer-online` returns 1.2.2, both declare `@beyondnet/evolith-sdk: ^2.0.0`, and both carry dist.attestations with provenance.",
"THE CHECK THAT MATTERS: installing @beyondnet/evolith-cli@latest into a directory that has never seen this workspace resolves @beyondnet/evolith-sdk@2.0.0 and the binary boots printing 1.2.2. Before this release the same install pulled the 2026-07-18 SDK.",
"CRITERION 2 REFUTED THE ROW'S OWN PREMISE, and that is the finding. None of the seven security-wave commits (1b077ab6, 3a39dd03, 60bfc63a, 3f31fa64, 90eacdbc, 4f29e114, 8ad4e2de) touches src/packages/sdk-client -- zero files each, checked commit by commit. The wave's release commit 21205d24 names the three packages it affected: evolith-mcp (15 files), evolith-cli (7), evolith-agent-runtime (1). The SDK was republished alongside them, not fixed.",
"So sdk@1.1.0 predates the wave chronologically and carries none of it: there was no security exposure through this dependency. What was real: a caret range under 1.x cannot cross a major, so both consumers were pinned a MAJOR behind on a contract dependency (`.passed` against a payload that emits `verdict`), and package-lock.json nested the registry tarball inside each consumer where it shadowed the workspace link -- the GT-625 class.",
"CRITERION 3 -- npm deprecate @beyondnet/evolith-sdk@1.1.0, with a message that gives the real reason (superseded by 2.0.0, `.passed` -> `verdict`) and states explicitly that it is NOT a security advisory. Verified after `npm cache clean --force`, because a first read-back returned the previous message from cache.",
"A CORRECTION TO MY OWN EARLIER WORK, made rather than left standing: the GT-624 deprecations of evolith-core-domain, evolith-core and evolith-infra-providers at 1.1.0 said `Security fixes landed in 1.2.0`. The same commit-by-commit evidence refutes that -- the wave touched three packages and none of those three is among them. All three messages were rewritten to say they were republished alongside the wave, not fixed by it. A false security claim on a public registry is worse than no claim."
],
"dependencyDisposition": "accepted-scope",
"dependencyRationale": "TWO things are left open on purpose. (1) evolith-cli@1.2.1 and evolith-mcp@1.2.1 are NOT deprecated: they resolve the superseded SDK major, which is a stale contract and not an exposure, and deprecating a version one patch old needs an owner's call rather than mine. (2) evolith-contracts@1.1.0 remains this package's only published version, so there is still no upgrade path to point a deprecation at; it is recorded here rather than forced."
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -7873,13 +7873,13 @@ Serie histórica de gaps registrada en el antiguo `gap-analysis-core.es.md`, pre
**Title:** El CLI y el MCP publicados resuelven una build del SDK anterior a la ola de seguridad, porque un rango caret bajo 1.x la fija

- **Purpose:** Que `npm install @beyondnet/evolith-cli@latest` deje de arrastrar una dependencia publicada antes de los fixes que anuncia su propio CHANGELOG.
- **Evidence:** **`@beyondnet/evolith-cli@1.2.1` y `@beyondnet/evolith-mcp@1.2.1` declaran ambos `@beyondnet/evolith-sdk: ^1.1.0`, y eso resuelve EXACTAMENTE `1.1.0`.** El SDK publica `1.0.0`, `1.1.0` y `2.0.0` y nada en medio, así que un rango caret bajo 1.x no puede alcanzar 2.0.0 — un caret está acotado por el siguiente mayor. Las fechas son el hallazgo: `sdk@1.1.0` se publicó el **2026-07-18**, `sdk@2.0.0` el **2026-07-27** como parte de la release que cerró [`GT-570`](./gap-reference-catalog.es.md#gt-570), y `cli@1.2.1` / `mcp@1.2.1` el **2026-07-28** — *después* de que 2.0.0 existiera, y seguían apuntando a la línea 1.x. Así que la exposición que GT-570 declaró cerrada para "quien instale `latest`" no está cerrada para esta dependencia: el `latest` de ambas superficies instala un SDK construido antes de la ola del 2026-07-23. **Dicho con precisión, porque la afirmación fuerte no está verificada aquí:** lo medido son las fechas y la resolución, no el contenido — esta fila no afirma que `sdk@1.1.0` cargue una vulnerabilidad concreta, solo que es anterior a la ola y que la release que la trajo fue un mayor al que los consumidores no llegan. Verificar qué fixes hay en `sdk@2.0.0` es parte de cerrarla. **Encontrado porque bloqueaba otra cosa:** deprecar `sdk@1.1.0` para [`GT-624`](./gap-reference-catalog.es.md#gt-624) habría impreso un aviso en cada instalación limpia de la línea actual sin ningún sucesor 1.x que ofrecer, y eso es lo que dejó el rango a la vista. Arreglo: reapuntar ambos rangos a `^2.0.0` (un salto mayor de dependencia, así que exige revisar los breaking changes del SDK contra ambos call sites) o publicar un `sdk@1.2.x` con los fixes, y entonces deprecar `sdk@1.1.0` y cerrar de verdad el primer criterio de GT-624. **RANGOS REAPUNTADOS el 2026-07-29, y hacerlo demostró que la fila se quedaba corta.** `package-lock.json` no sólo registraba el rango — fijaba el tarball del registry de `sdk@1.1.0` en `src/sdk/cli/node_modules/@beyondnet/evolith-sdk` **y** en `src/packages/mcp-server/node_modules/@beyondnet/evolith-sdk`, con hashes de integridad. Así que un `npm ci` en checkout limpio descargaba el SDK anterior a la ola y lo anidaba dentro de cada consumidor, donde **tapa el enlace del workspace**: el symlink de primer nivel al 2.0.0 local es lo que lee todo el mundo, y el 1.1.0 anidado es lo que resuelve de verdad una instalación fresca. Es la misma clase que [`GT-625`](./gap-reference-catalog.es.md#gt-625) — el workspace tapando lo que hace una instalación real — y es la razón de que nada lo cazara. Ambas entradas anidadas desaparecieron al mover el rango a `^2.0.0`, porque entonces el propio 2.0.0 del workspace lo satisface; el diff del lockfile son exactamente dos cadenas de rango y esas dos eliminaciones, sin deriva colateral, y se usó `npm install --package-lock-only` para confirmar que escribe byte a byte lo mismo que la edición a mano en vez de fiarse de ella. La superficie del SDK que ambos consumidores usan de verdad es estrecha — sólo `EvolithRestClient` — así que el breaking change de 2.0.0 (tipos de payload re-exportados de `core-domain`, `.passed` → `.verdict`, severidad `'info'` retirada) no toca ninguno de los dos call sites. Verificado contra 2.0.0: CLI **1436/1436** en 99 suites, mcp-server **433/433** en 53. **1.2.2 está en `main` (PR #285) y NO publicada.** La fila sigue ABIERTA y ése es justo el punto: un rango en el repositorio no es un rango en el registry, y el criterio 1 sólo se cumple cuando npm lo sirve. Hasta entonces el `latest` publicado de ambas superficies sigue instalando el SDK del 2026-07-18.
- **Evidence:** **`@beyondnet/evolith-cli@1.2.1` y `@beyondnet/evolith-mcp@1.2.1` declaran ambos `@beyondnet/evolith-sdk: ^1.1.0`, y eso resuelve EXACTAMENTE `1.1.0`.** El SDK publica `1.0.0`, `1.1.0` y `2.0.0` y nada en medio, así que un rango caret bajo 1.x no puede alcanzar 2.0.0 — un caret está acotado por el siguiente mayor. Las fechas son el hallazgo: `sdk@1.1.0` se publicó el **2026-07-18**, `sdk@2.0.0` el **2026-07-27** como parte de la release que cerró [`GT-570`](./gap-reference-catalog.es.md#gt-570), y `cli@1.2.1` / `mcp@1.2.1` el **2026-07-28** — *después* de que 2.0.0 existiera, y seguían apuntando a la línea 1.x. Así que la exposición que GT-570 declaró cerrada para "quien instale `latest`" no está cerrada para esta dependencia: el `latest` de ambas superficies instala un SDK construido antes de la ola del 2026-07-23. **Dicho con precisión, porque la afirmación fuerte no está verificada aquí:** lo medido son las fechas y la resolución, no el contenido — esta fila no afirma que `sdk@1.1.0` cargue una vulnerabilidad concreta, solo que es anterior a la ola y que la release que la trajo fue un mayor al que los consumidores no llegan. Verificar qué fixes hay en `sdk@2.0.0` es parte de cerrarla. **Encontrado porque bloqueaba otra cosa:** deprecar `sdk@1.1.0` para [`GT-624`](./gap-reference-catalog.es.md#gt-624) habría impreso un aviso en cada instalación limpia de la línea actual sin ningún sucesor 1.x que ofrecer, y eso es lo que dejó el rango a la vista. Arreglo: reapuntar ambos rangos a `^2.0.0` (un salto mayor de dependencia, así que exige revisar los breaking changes del SDK contra ambos call sites) o publicar un `sdk@1.2.x` con los fixes, y entonces deprecar `sdk@1.1.0` y cerrar de verdad el primer criterio de GT-624. **RANGOS REAPUNTADOS el 2026-07-29, y hacerlo demostró que la fila se quedaba corta.** `package-lock.json` no sólo registraba el rango — fijaba el tarball del registry de `sdk@1.1.0` en `src/sdk/cli/node_modules/@beyondnet/evolith-sdk` **y** en `src/packages/mcp-server/node_modules/@beyondnet/evolith-sdk`, con hashes de integridad. Así que un `npm ci` en checkout limpio descargaba el SDK anterior a la ola y lo anidaba dentro de cada consumidor, donde **tapa el enlace del workspace**: el symlink de primer nivel al 2.0.0 local es lo que lee todo el mundo, y el 1.1.0 anidado es lo que resuelve de verdad una instalación fresca. Es la misma clase que [`GT-625`](./gap-reference-catalog.es.md#gt-625) — el workspace tapando lo que hace una instalación real — y es la razón de que nada lo cazara. Ambas entradas anidadas desaparecieron al mover el rango a `^2.0.0`, porque entonces el propio 2.0.0 del workspace lo satisface; el diff del lockfile son exactamente dos cadenas de rango y esas dos eliminaciones, sin deriva colateral, y se usó `npm install --package-lock-only` para confirmar que escribe byte a byte lo mismo que la edición a mano en vez de fiarse de ella. La superficie del SDK que ambos consumidores usan de verdad es estrecha — sólo `EvolithRestClient` — así que el breaking change de 2.0.0 (tipos de payload re-exportados de `core-domain`, `.passed` → `.verdict`, severidad `'info'` retirada) no toca ninguno de los dos call sites. Verificado contra 2.0.0: CLI **1436/1436** en 99 suites, mcp-server **433/433** en 53. **1.2.2 está en `main` (PR #285) y NO publicada.** La fila sigue ABIERTA y ése es justo el punto: un rango en el repositorio no es un rango en el registry, y el criterio 1 sólo se cumple cuando npm lo sirve. Hasta entonces el `latest` publicado de ambas superficies sigue instalando el SDK del 2026-07-18. **CERRADO el 2026-07-30, y el marco de seguridad de esta fila era ERRÓNEO — se registra en vez de retirarlo en silencio.** 1.2.2 está publicada con provenance y una instalación limpia de `@beyondnet/evolith-cli@latest` resuelve ya `@beyondnet/evolith-sdk@2.0.0`, con el binario arrancando. Pero el criterio 2 obligó a hacer la pregunta que esta fila había dejado abierta a propósito, y la respuesta refuta su premisa: **ninguno de los siete commits de la ola de seguridad (`1b077ab6`, `3a39dd03`, `60bfc63a`, `3f31fa64`, `90eacdbc`, `4f29e114`, `8ad4e2de`) toca `src/packages/sdk-client` — cero ficheros.** El propio commit de release de la ola, `21205d24`, nombra los tres paquetes afectados: `evolith-mcp` (15 ficheros), `evolith-cli` (7) y `evolith-agent-runtime` (1). El SDK se republicó con ellos, no se arregló. Así que `sdk@1.1.0` es cronológicamente anterior a la ola y no carga nada de ella; no había exposición por esta dependencia. **Lo que sí era real, y es lo que la fila debió decir:** un rango caret bajo 1.x no cruza un mayor, así que ambos consumidores quedaban fijados un MAYOR por detrás en una dependencia de contrato — `.passed` contra un payload que emite `verdict` — y el lockfile anidaba el tarball del registry dentro de cada consumidor, tapando el enlace del workspace. Un defecto de contrato rancio y de sombra en el lockfile (la clase de [`GT-625`](./gap-reference-catalog.es.md#gt-625)), no de seguridad. La cautela que se escribió en la fila al abrirla — que medía fechas y resolución, no contenidos — es lo que abarató la corrección.
- **Component:** `Infra` · **Criticality:** P1 · **Complexity:** S
- **Provenance:** Encontrado el 2026-07-29 ejecutando el criterio de deprecación de GT-624. Registrado en vez de sorteado: saltarse la deprecación en silencio habría dejado el rango — y la instalación — exactamente como están.
- **Acceptance criteria:**
- [ ] `npm view @beyondnet/evolith-cli@latest dependencies` muestra un rango de SDK que resuelve a una versión publicada el 2026-07-27 o después, e igual `evolith-mcp`.
- [ ] Los fixes que reclama la ola de seguridad del 2026-07-23 se verifican presentes en la versión del SDK que el CLI y el MCP resuelven de verdad, en vez de asumirse por el número de versión.
- [ ] `@beyondnet/evolith-sdk@1.1.0` queda deprecada en cuanto exista un sucesor al que sus consumidores puedan llegar.
- [x] `npm view @beyondnet/evolith-cli@latest dependencies` muestra un rango de SDK que resuelve a una versión publicada el 2026-07-27 o después, e igual `evolith-mcp` — ambos publican `^2.0.0` en 1.2.2, y una instalación limpia resuelve `sdk@2.0.0` con el binario arrancando.
- [x] Los fixes que reclama la ola de seguridad del 2026-07-23 se verifican presentes en la versión del SDK que el CLI y el MCP resuelven de verdad, en vez de asumirse por el número de versión — y la verificación REFUTÓ la premisa: ninguno de los siete commits de la ola toca `src/packages/sdk-client`, así que no hay fixes de la ola en el SDK que puedan estar o faltar.
- [x] `@beyondnet/evolith-sdk@1.1.0` queda deprecada en cuanto exista un sucesor al que sus consumidores puedan llegar — hecho el 2026-07-30, con un mensaje que da el motivo real (superseded por 2.0.0, `.passed` → `verdict`) y dice explícitamente que no es un aviso de seguridad.

#### GT-633

Expand Down
Loading
Loading