@ingeniomaps/cauce 0.86.0 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -14,6 +14,26 @@ desde este repositorio no va, porque el que lee no puede actuar sobre eso. Cuand
14
14
  unas pocas líneas casi siempre es porque cuenta cómo se descubrió el problema o por qué se eligió el
15
15
  diseño — eso vive en el commit y en el código.
16
16
 
17
+ ## [0.87.0] - 2026-09-14
18
+
19
+ ### Corregido
20
+
21
+ - **El aviso de credenciales sin dueño mira el `.env.example` entero y ya no sus primeras cuarenta
22
+ variables.** `check` te avisa de las credenciales que ningún contrato declara, y el escaneo cortaba en
23
+ cuarenta variables por servicio **antes** de mirar qué era cada una. En un servicio grande eso no
24
+ recortaba una lista: apagaba el análisis, y qué credencial se veía terminaba dependiendo de en qué línea
25
+ del archivo había caído.
26
+
27
+ El riesgo estaba escrito como aceptado y sin medir desde que el tope existe. Medirlo contra una instancia
28
+ real lo convirtió en dos nombres: un servicio con 61 variables tenía tres credenciales pasado el corte y
29
+ **dos que ningún contrato declaraba**, en las líneas 43 y 60. Lo único que salía era el aviso de que había
30
+ cortado.
31
+
32
+ Ahora el tope recorta lo que se **lista** y no lo que se mira: las credenciales se buscan sobre el archivo
33
+ entero, y `scan` sigue mostrando cuarenta y diciendo cuántas más hay. Si tenés un servicio con más de
34
+ cuarenta variables, contá con avisos nuevos en el próximo `check` — son credenciales que ya estaban y que
35
+ nadie estaba mirando.
36
+
17
37
  ## [0.86.0] - 2026-09-12
18
38
 
19
39
  ### Corregido
@@ -143,7 +143,13 @@ function scan(target, cli) {
143
143
  for (const service of result.services.slice(0, MAX_LISTED)) {
144
144
  // El proyecto que vive en la raíz se nombra por su carpeta: `.` a secas no dice de cuál se habla.
145
145
  const label = service.path === '.' ? `. (${path.basename(service.root || result.root)})` : service.path
146
- const expects = service.env ? `\n espera ${service.env.names.join(', ')} (${service.env.file})` : ''
146
+ // La lista llega entera —quien busca credenciales la necesita así, ver `core/scan.js`— y el recorte
147
+ // de pantalla se aplica acá, junto al de servicios de arriba y por la misma razón.
148
+ const shown = service.env ? service.env.names.slice(0, service.env.names.length - service.env.truncated) : []
149
+ const expects = service.env
150
+ ? `\n espera ${shown.join(', ')}${service.env.truncated ? ` y ${service.env.truncated} más` : ''} `
151
+ + `(${service.env.file})`
152
+ : ''
147
153
  console.log(
148
154
  `${label} [${(service.runtimes || []).join(', ')}]${SC.commandsLine(service.commands)}${expects}`,
149
155
  )
@@ -127,7 +127,9 @@ function orphanCredentials(root) {
127
127
  for (const name of env.names || []) {
128
128
  if (sensitiveKey(name) && !named(contracts, name)) orphans.push({ name, service: service.path })
129
129
  }
130
- if (env.truncated) cut.push(`${service.path} (${env.truncated} de ${env.names.length + env.truncated})`)
130
+ // `names` llega entero desde el 134 —el tope recorta lo que se lista, no lo que se mira—, así que el
131
+ // total es su largo a secas: sumarle `truncated` contaría dos veces lo mismo.
132
+ if (env.truncated) cut.push(`${service.path} (${env.truncated} de ${env.names.length})`)
131
133
  }
132
134
  const warnings = []
133
135
  if (orphans.length) {
@@ -141,11 +143,12 @@ function orphanCredentials(root) {
141
143
  + 'organization/workspace.md o en una fila de planning/HUMAN_ACTIONS.md; el criterio es el nombre, así '
142
144
  + 'que una credencial con nombre de configuración no aparece acá')
143
145
  }
144
- // El escaneo corta cada ejemplo en un tope, y lo que quedó afuera no se miró: con el filtro, puede ser
145
- // justo la credencial.
146
+ // El tope recorta lo que se **lista**, no lo que se mira: las credenciales de arriba salen del ejemplo
147
+ // entero. Esto se sigue diciendo porque un corte que no se anuncia hace pasar lo listado por todo lo que
148
+ // hay —y hasta el 134 además cegaba el análisis, que es de donde viene la redacción vieja—.
146
149
  if (cut.length) {
147
- warnings.push(`sin revisar por credenciales sin dueño, pasado el tope de variables por servicio: `
148
- + `${cut.join(', ')} — lo que quedó afuera puede incluir una credencial que nadie carga`)
150
+ warnings.push(`pasado el tope de variables por servicio: ${cut.join(', ')} — el ejemplo se lista `
151
+ + 'recortado; las credenciales se buscan igual sobre el archivo entero')
149
152
  }
150
153
  return warnings
151
154
  }
@@ -107,7 +107,12 @@ function manifestsOf(dir) {
107
107
  // diciendo «la credencial del proveedor» en vez de nombrarla.
108
108
  const ENV_EXAMPLES = ['.env.example', '.env.sample', '.env.template', '.env.dist']
109
109
 
110
- // Un ejemplo con cientos de variables es un archivo generado, no un contrato: se corta y se dice.
110
+ // Un ejemplo con cientos de variables es un archivo generado, no un contrato: se corta lo que **se
111
+ // lista** y se dice cuánto. Lo que no se corta es lo que se **mira**: hasta el 134 este número recortaba
112
+ // las dos cosas, así que una credencial en la posición 41 no existía para quien busca credenciales sin
113
+ // dueño —medido en una instancia real: dos, sobre las 61 variables de un servicio, y el único aviso era
114
+ // que se había cortado—. Quién recorta para imprimir está en `cli/wiring.js`, junto al otro recorte de
115
+ // ese mismo comando.
111
116
  const ENV_MAX = 40
112
117
 
113
118
  function expectedEnv(dir) {
@@ -122,7 +127,7 @@ function expectedEnv(dir) {
122
127
  .map((line) => line.replace(/^export\s+/, '').split('=')[0].trim())
123
128
  .filter((key) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
124
129
  if (!names.length) return null
125
- return { file: name, names: names.slice(0, ENV_MAX), truncated: Math.max(0, names.length - ENV_MAX) }
130
+ return { file: name, names, truncated: Math.max(0, names.length - ENV_MAX) }
126
131
  }
127
132
  return null
128
133
  }
@@ -14,6 +14,20 @@ const GRANT = 'planning/.grant-log'
14
14
  const LOCAL = [VERIFY, PUSH, GRANT]
15
15
 
16
16
  const { spawnSync } = require('node:child_process')
17
+ const { mode } = require('./ownership')
18
+
19
+ // A quién le toca esta pregunta. Los rastros los escribe Cauce **dentro de una instancia**, así que en una
20
+ // raíz que no lo es no existen ni van a existir, y avisar ahí es hablar de algo imposible: el molde de este
21
+ // repositorio lo recibía una vez por corrida, con `check template/planning` (caso 133).
22
+ //
23
+ // Se mira el modo declarado y no el nombre de la carpeta, porque las tres formas de no ser una instancia
24
+ // son la misma pregunta: `toolkit` —acá se fabrica Cauce—, `{{MODE}}` sin renderizar —el molde, que es la
25
+ // raíz que dispara el falso positivo— y la ausencia de configuración. Un modo ilegible o fuera del enum
26
+ // también cae del lado silencioso, y eso no esconde nada: `check` ya los denuncia como error y sale 1.
27
+ const INSTANCE = new Set(['embedded', 'sidecar'])
28
+ const forInstance = (root) => {
29
+ try { return INSTANCE.has(mode(root)) } catch { return false }
30
+ }
17
31
 
18
32
  // Cuáles de esos rastros **git no está ignorando** en esta instancia.
19
33
  //
@@ -43,6 +57,7 @@ function unignored(root) {
43
57
  // son exactamente lo que hay que pegar, que es lo único accionable — el archivo es de la empresa y Cauce
44
58
  // no lo edita.
45
59
  function warnings(root) {
60
+ if (!forInstance(root)) return []
46
61
  const missing = unignored(root)
47
62
  if (!missing.length) return []
48
63
  return [`${missing.length} rastro(s) local(es) que git no ignora (${missing.join(', ')}); `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingeniomaps/cauce",
3
- "version": "0.86.0",
3
+ "version": "0.87.0",
4
4
  "description": "Sistema portable de planificación y ejecución verificable para cualquier proyecto",
5
5
  "keywords": [
6
6
  "planning",