@saulwade/swl-ses 2.6.0 → 2.8.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/CLAUDE.md +209 -197
- package/README.md +647 -600
- package/agentes/accesibilidad-wcag-swl.md +690 -690
- package/agentes/arquitecto-swl.md +267 -267
- package/agentes/auto-evolucion-swl.md +932 -932
- package/agentes/backend-csharp-swl.md +420 -420
- package/agentes/backend-go-swl.md +390 -390
- package/agentes/backend-java-swl.md +281 -281
- package/agentes/backend-rust-swl.md +364 -364
- package/agentes/backend-workers-swl.md +482 -482
- package/agentes/cloud-infra-swl.md +509 -509
- package/agentes/consolidador-swl.md +541 -541
- package/agentes/depurador-swl.md +352 -352
- package/agentes/devops-ci-swl.md +400 -400
- package/agentes/disenador-ui-swl.md +569 -569
- package/agentes/documentador-swl.md +345 -345
- package/agentes/frontend-angular-swl.md +621 -621
- package/agentes/frontend-css-swl.md +716 -716
- package/agentes/frontend-react-swl.md +692 -692
- package/agentes/frontend-swl.md +496 -496
- package/agentes/frontend-tailwind-swl.md +826 -826
- package/agentes/investigador-swl.md +432 -432
- package/agentes/investigador-ux-swl.md +505 -505
- package/agentes/migrador-swl.md +442 -442
- package/agentes/mobile-android-swl.md +511 -511
- package/agentes/mobile-cross-swl.md +541 -541
- package/agentes/mobile-ios-swl.md +502 -502
- package/agentes/mobile-testing-swl.md +302 -302
- package/agentes/nemesis-auditor-swl.md +285 -285
- package/agentes/observabilidad-swl.md +438 -438
- package/agentes/pagos-swl.md +310 -310
- package/agentes/perfilador-usuario-swl.md +321 -321
- package/agentes/planificador-swl.md +399 -399
- package/agentes/producto-prd-swl.md +589 -589
- package/agentes/red-team-swl.md +218 -218
- package/agentes/release-manager-swl.md +590 -590
- package/agentes/rendimiento-swl.md +713 -713
- package/agentes/revisor-angular-swl.md +278 -278
- package/agentes/revisor-csharp-swl.md +264 -264
- package/agentes/revisor-go-swl.md +259 -259
- package/agentes/revisor-java-swl.md +257 -257
- package/agentes/revisor-kotlin-swl.md +273 -273
- package/agentes/revisor-nextjs-swl.md +281 -281
- package/agentes/revisor-php-swl.md +271 -271
- package/agentes/revisor-react-swl.md +278 -278
- package/agentes/revisor-rust-swl.md +346 -346
- package/agentes/revisor-seguridad-swl.md +399 -399
- package/agentes/revisor-swift-swl.md +268 -268
- package/agentes/revisor-typescript-swl.md +346 -346
- package/agentes/tdd-qa-swl.md +393 -393
- package/bin/swl-ses.js +10 -0
- package/comandos/swl/actualizar.md +174 -174
- package/comandos/swl/adoptar-proyecto.md +265 -265
- package/comandos/swl/aprender.md +836 -836
- package/comandos/swl/aprobar-plan.md +146 -146
- package/comandos/swl/auditar-deps.md +134 -134
- package/comandos/swl/autoresearch.md +264 -264
- package/comandos/swl/ayuda.md +224 -224
- package/comandos/swl/brainstorm.md +52 -51
- package/comandos/swl/checkpoint.md +325 -325
- package/comandos/swl/claudemd.md +234 -234
- package/comandos/swl/compactar.md +310 -310
- package/comandos/swl/configurar-ci.md +235 -235
- package/comandos/swl/contexto.md +110 -110
- package/comandos/swl/crear-skill.md +292 -292
- package/comandos/swl/cron.md +194 -194
- package/comandos/swl/deuda-codigo.md +97 -97
- package/comandos/swl/discutir-fase.md +169 -169
- package/comandos/swl/ejecutar-fase.md +233 -233
- package/comandos/swl/evaluar-skill.md +520 -520
- package/comandos/swl/evolucion-continua.md +73 -73
- package/comandos/swl/evolucionar.md +267 -267
- package/comandos/swl/exportar-vault.md +583 -583
- package/comandos/swl/fix.md +118 -118
- package/comandos/swl/gateway.md +158 -158
- package/comandos/swl/inbox.md +116 -116
- package/comandos/swl/instalar.md +220 -220
- package/comandos/swl/instintos.md +86 -86
- package/comandos/swl/mapear-codebase.md +312 -312
- package/comandos/swl/mcp-status.md +176 -175
- package/comandos/swl/modelo.md +100 -100
- package/comandos/swl/nemesis.md +433 -433
- package/comandos/swl/notificaciones.md +299 -299
- package/comandos/swl/nuevo-proyecto.md +251 -251
- package/comandos/swl/planear-fase.md +263 -263
- package/comandos/swl/plugins.md +256 -256
- package/comandos/swl/predecir.md +169 -169
- package/comandos/swl/reflect-skills.md +125 -125
- package/comandos/swl/release.md +450 -450
- package/comandos/swl/revisar-impacto.md +201 -201
- package/comandos/swl/revisar.md +330 -330
- package/comandos/swl/seguridad.md +189 -189
- package/comandos/swl/sesiones.md +200 -200
- package/comandos/swl/skill-search.md +113 -113
- package/comandos/swl/status.md +345 -345
- package/comandos/swl/verificar.md +817 -817
- package/comandos/swl/wiki.md +620 -620
- package/gateway/cron/jobs.example.json +12 -12
- package/gateway/lib/event-channel.js +191 -191
- package/habilidades/agent-deep-links/SKILL.md +148 -148
- package/habilidades/auto-evolucion-protocolo/SKILL.md +294 -294
- package/habilidades/backend-async-postgres-testing/SKILL.md +216 -215
- package/habilidades/backend-error-design/SKILL.md +221 -221
- package/habilidades/backend-production-resilience/SKILL.md +288 -288
- package/habilidades/calidad-anti-patrones-universales/SKILL.md +105 -1
- package/habilidades/calidad-contract-testing/SKILL.md +165 -165
- package/habilidades/calidad-mutation-testing/SKILL.md +25 -1
- package/habilidades/changelog-generator/SKILL.md +174 -174
- package/habilidades/checklist-seguridad/recursos/stride-cobertura.md +60 -60
- package/habilidades/ci-cd-pipelines/SKILL.md +5 -1
- package/habilidades/compactacion-contexto/SKILL.md +2 -1
- package/habilidades/contenedores-docker/SKILL.md +4 -2
- package/habilidades/css-moderno/SKILL.md +7 -1
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
- package/habilidades/doubt-driven-review/SKILL.md +207 -207
- package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
- package/habilidades/drift-detection/SKILL.md +1 -1
- package/habilidades/ejecutar-task-iterativo/SKILL.md +278 -278
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -57
- package/habilidades/extractor-de-aprendizajes/SKILL.md +12 -2
- package/habilidades/feynman-auditor-swl/recursos/preguntas-language-agnostic.md +108 -108
- package/habilidades/git-worktrees-paralelo/SKILL.md +19 -1
- package/habilidades/harness-claude-code/SKILL.md +315 -314
- package/habilidades/instalar-sistema/SKILL.md +227 -227
- package/habilidades/meta-skills-estandar/recursos/convencion-examples.md +93 -93
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -469
- package/habilidades/perfil-usuario/SKILL.md +200 -200
- package/habilidades/planear-fase/SKILL.md +358 -358
- package/habilidades/prevencion-sobreingenieria/recursos/EXAMPLES.md +580 -580
- package/habilidades/proceso-ddia-streaming/SKILL.md +231 -231
- package/habilidades/proceso-discovery-machote/SKILL.md +157 -157
- package/habilidades/proceso-dynamic-workflows/SKILL.md +60 -0
- package/habilidades/proceso-dynamic-workflows/recursos/template-adversarial-verify.js +65 -65
- package/habilidades/proceso-dynamic-workflows/recursos/template-triage.js +65 -65
- package/habilidades/proceso-ingenieria-requerimientos/SKILL.md +147 -147
- package/habilidades/proceso-intent-engineering/SKILL.md +269 -269
- package/habilidades/proceso-modular-split/SKILL.md +256 -256
- package/habilidades/release-semver/SKILL.md +2 -2
- package/habilidades/state-inconsistency-auditor-swl/recursos/coupled-state-patterns.md +147 -147
- package/habilidades/swl-claudemd/recursos/contrato-aprender.md +83 -83
- package/habilidades/swl-claudemd/recursos/duplicacion-reglas-globales.md +85 -85
- package/habilidades/swl-claudemd/recursos/plantillas-init.md +94 -94
- package/habilidades/tdd-workflow/SKILL.md +749 -749
- package/habilidades/tdd-workflow/recursos/gherkin-bdd.md +111 -111
- package/hooks/agente-lifecycle.js +1 -1
- package/hooks/audit-trail.js +1 -1
- package/hooks/auto-consolidacion.js +1 -1
- package/hooks/calidad-pre-commit.js +159 -10
- package/hooks/captura-acciones-post.js +1 -1
- package/hooks/captura-acciones-session.js +1 -1
- package/hooks/captura-feedback-usuario.js +1 -1
- package/hooks/ciclo-evolucion-subagente.js +26 -26
- package/hooks/ciclo-evolucion.js +26 -26
- package/hooks/contexto-iteracion.js +1 -1
- package/hooks/degradacion-instintos.js +1 -1
- package/hooks/grafo-contexto.js +1 -1
- package/hooks/guardrail-modelo.js +1 -1
- package/hooks/inbox-aviso.js +1 -1
- package/hooks/inyeccion-contexto.js +1 -1
- package/hooks/lib/agent-matcher.js +1 -1
- package/hooks/lib/agent-routing.js +1 -1
- package/hooks/lib/auto-consolidator.js +335 -335
- package/hooks/lib/captura-acciones.js +1 -1
- package/hooks/lib/ciclo-evolucion.js +47 -47
- package/hooks/lib/deep-links.js +185 -185
- package/hooks/lib/error-classifier.js +308 -308
- package/hooks/lib/etapa-metricas.js +1 -1
- package/hooks/lib/evolution-tracker.js +1 -1
- package/hooks/lib/gateway-notify.js +193 -193
- package/hooks/lib/mcp-health.js +1 -1
- package/hooks/lib/notificacion-formato.js +92 -0
- package/hooks/lib/nudge-tracker.js +1 -1
- package/hooks/lib/otlp-exporter.js +1 -1
- package/hooks/lib/propose-step.js +1 -1
- package/hooks/lib/provenance-tracker.js +191 -191
- package/hooks/lib/raiz-proyecto.js +158 -102
- package/hooks/lib/resource-quota.js +122 -122
- package/hooks/lib/retry-jitter.js +165 -165
- package/hooks/lib/run-log.js +1 -1
- package/hooks/lib/security-net.js +201 -201
- package/hooks/lib/singleton-guard.js +20 -13
- package/hooks/lib/skill-auditor.js +588 -588
- package/hooks/lib/sync-status.js +228 -228
- package/hooks/lib/taint-tracker.js +107 -107
- package/hooks/lib/telegram-cliente.js +11 -3
- package/hooks/lib/text-similarity.js +241 -241
- package/hooks/lib/toon-compressor.js +245 -245
- package/hooks/notificacion-telegram.js +17 -13
- package/hooks/preservar-estado-pre-compact.js +1 -1
- package/hooks/registro-turnos.js +1 -1
- package/hooks/resumen-sesion.js +1 -1
- package/hooks/risk-scoring.js +1 -1
- package/hooks/session-briefing.js +13 -5
- package/hooks/spec-gate.js +1 -1
- package/hooks/sugerir-regenerar-inventario.js +1 -1
- package/hooks/tdd-gate.js +1 -1
- package/hooks/telemetria-agentes.js +1 -1
- package/hooks/telemetria-skill-routing.js +1 -1
- package/hooks/tracking-costos.js +1 -1
- package/hooks/validar-formato-post-subagente.js +1 -1
- package/hooks/validar-intent-spec.js +1 -1
- package/hooks/validar-planning-paths.js +1 -1
- package/instintos/autonomia.yaml +27 -27
- package/instintos/prompt-appendices.yaml +57 -57
- package/llms.txt +29 -29
- package/manifiestos/agent-output-schemas.json +57 -57
- package/manifiestos/canonical-hashes.json +6250 -5257
- package/manifiestos/harness-ir.json +47536 -0
- package/manifiestos/modulos.json +1429 -1428
- package/manifiestos/policy-bundle.json +2065 -0
- package/manifiestos/policy-corpus-w2.json +3926 -0
- package/manifiestos/runtime-adapters-core3.json +208 -0
- package/manifiestos/runtime-conformance.json +139 -0
- package/manifiestos/skills-lock.json +1275 -1275
- package/package.json +94 -94
- package/plantillas/auditor-veto-template.md +105 -105
- package/plantillas/github-workflows/release-please.yml +44 -44
- package/plantillas/github-workflows/swl-ci.yml +107 -107
- package/plantillas/github-workflows/swl-security.yml +51 -51
- package/plugin.json +369 -369
- package/reglas/accesibilidad.md +10 -10
- package/reglas/auditorias-documentales-estructurales.md +7 -7
- package/reglas/cloud-infra.md +8 -8
- package/reglas/consultar-vault-primero.md +195 -195
- package/reglas/git-workflow.md +1 -0
- package/reglas/hooks.md +6 -6
- package/reglas/intent-engineering.md +218 -218
- package/reglas/markitdown.md +8 -8
- package/reglas/monitor-ci.md +12 -0
- package/reglas/patrones.md +6 -6
- package/reglas/testing.md +7 -7
- package/reglas/tests-cleanup.md +224 -224
- package/schemas/agent-message.schema.json +73 -73
- package/schemas/agent-output-implementacion.schema.json +114 -114
- package/schemas/agent-output-planificacion.schema.json +150 -150
- package/schemas/agent-output-review.schema.json +98 -98
- package/schemas/diary-entry.schema.json +112 -112
- package/schemas/gate-state.schema.json +76 -0
- package/schemas/harness-ir.schema.json +369 -0
- package/schemas/hook-profiles.schema.json +54 -54
- package/schemas/hooks-config.schema.json +89 -89
- package/schemas/legacy-gates.schema.json +45 -0
- package/schemas/modulos.schema.json +38 -38
- package/schemas/perfiles.schema.json +36 -36
- package/schemas/plugin.schema.json +77 -77
- package/schemas/policy-bundle.schema.json +140 -0
- package/schemas/policy-enforcement.schema.json +117 -0
- package/schemas/policy-operation.schema.json +261 -0
- package/schemas/runtime-adapter.schema.json +176 -0
- package/schemas/runtime-build-attestation.schema.json +100 -0
- package/schemas/runtime-conformance.schema.json +239 -0
- package/schemas/runtime-diagnostic.schema.json +395 -0
- package/schemas/skill-evals.schema.json +119 -119
- package/schemas/skill-frontmatter.schema.json +245 -245
- package/schemas/w4-certification-request.schema.json +72 -0
- package/schemas/w4-certification-verdict.schema.json +224 -0
- package/schemas/w4-corpus.schema.json +172 -0
- package/schemas/w4-mutation-report.schema.json +116 -0
- package/schemas/w4-replay-result.schema.json +164 -0
- package/schemas/w4-scoring-report.schema.json +89 -0
- package/scripts/audit-tools/audit-history.js +330 -330
- package/scripts/audit-tools/bundle-tracker.js +290 -290
- package/scripts/audit-tools/canary-monitor.js +352 -352
- package/scripts/audit-tools/code-profiler.js +605 -605
- package/scripts/audit-tools/dep-doctor.js +320 -320
- package/scripts/audit-tools/env-validator.js +206 -206
- package/scripts/audit-tools/lib/fs-walk.js +48 -48
- package/scripts/audit-tools/lib/output.js +23 -23
- package/scripts/audit-tools/migration-checker.js +392 -392
- package/scripts/audit-tools/pentest-scanner.js +1436 -1436
- package/scripts/auditar-clases-conocidas.js +134 -134
- package/scripts/bootstrap-instintos.js +88 -14
- package/scripts/canario-hooks.js +166 -166
- package/scripts/cli/aprobar-plan.js +73 -73
- package/scripts/cli/autonomia.js +23 -23
- package/scripts/cli/benchmark-memoria.js +37 -37
- package/scripts/cli/briefing.js +23 -23
- package/scripts/cli/ciclo-autonomo.js +73 -73
- package/scripts/cli/ciclo-evolucion.js +26 -26
- package/scripts/cli/ciclo-fase-b.js +102 -102
- package/scripts/cli/derivar-feature-list.js +25 -25
- package/scripts/cli/detectar-host.js +27 -27
- package/scripts/cli/diary-entry.js +69 -69
- package/scripts/cli/execution-state.js +18 -18
- package/scripts/cli/gateway-notify.js +41 -41
- package/scripts/cli/guardrail-metrics.js +39 -39
- package/scripts/cli/liberar-fase.js +42 -42
- package/scripts/cli/mark-evolved.js +56 -56
- package/scripts/cli/memoria-search.js +69 -69
- package/scripts/cli/metricas-dora.js +26 -26
- package/scripts/cli/near-duplicate.js +55 -55
- package/scripts/cli/notificaciones.js +123 -123
- package/scripts/cli/nudge-accionar.js +39 -39
- package/scripts/cli/propose-step.js +29 -29
- package/scripts/cli/run-eval.js +38 -38
- package/scripts/cli/schedule-parse.js +19 -19
- package/scripts/cli/sugerir-modelo.js +20 -20
- package/scripts/cli/verificar-plan.js +36 -36
- package/scripts/cli/verificar-trazabilidad.js +35 -35
- package/scripts/comandos/install-asistido.js +8 -7
- package/scripts/configurar-branch-protection.js +418 -418
- package/scripts/detectar-aprendizajes-duplicados.js +151 -151
- package/scripts/doctor.js +61 -13
- package/scripts/evidencia-valor.js +101 -101
- package/scripts/field-report.js +16 -16
- package/scripts/generar-checklists-consolidados.js +273 -273
- package/scripts/generar-claims-runtime.js +1342 -0
- package/scripts/generar-harness-ir.js +257 -0
- package/scripts/generar-inventario.js +52 -54
- package/scripts/generar-policy-bundle.js +202 -0
- package/scripts/instalador.js +39 -7
- package/scripts/lib/activar-hooks-proyecto.js +116 -116
- package/scripts/lib/approval-receipts.js +190 -0
- package/scripts/lib/artefactos-python.js +43 -43
- package/scripts/lib/benchmark-metrics.js +160 -160
- package/scripts/lib/budget-enforcer.js +252 -252
- package/scripts/lib/certificacion-loop-state.js +421 -0
- package/scripts/lib/ci-reader.js +193 -193
- package/scripts/lib/ciclo-autonomo/candidatos.js +174 -174
- package/scripts/lib/ciclo-autonomo/config.js +165 -165
- package/scripts/lib/ciclo-autonomo/drenador-feedback.js +174 -174
- package/scripts/lib/ciclo-autonomo/fallback.js +77 -77
- package/scripts/lib/ciclo-autonomo/guard-convivencia.js +139 -139
- package/scripts/lib/ciclo-autonomo/higiene-nudges.js +112 -112
- package/scripts/lib/ciclo-autonomo/index.js +301 -301
- package/scripts/lib/ciclo-autonomo/lock.js +124 -124
- package/scripts/lib/ciclo-autonomo/presupuesto.js +122 -122
- package/scripts/lib/ciclo-autonomo/puente-degradacion.js +240 -240
- package/scripts/lib/ciclo-autonomo/runner-fase-b.js +248 -248
- package/scripts/lib/ciclo-autonomo/writer-instintos.js +190 -190
- package/scripts/lib/ciclo-autonomo/yaml-instintos.js +591 -535
- package/scripts/lib/clasificar-directorio.js +92 -0
- package/scripts/lib/contadores-inventario.js +217 -217
- package/scripts/lib/detectar-host-swl.js +175 -175
- package/scripts/lib/detectar-runtime.js +29 -20
- package/scripts/lib/detectar-stack-detallado.js +307 -307
- package/scripts/lib/detector-autoduplicacion-intra-archivo.js +234 -234
- package/scripts/lib/detector-reglas-duplicadas.js +220 -220
- package/scripts/lib/eval-metrics-store.js +218 -218
- package/scripts/lib/eval-quality.js +171 -171
- package/scripts/lib/eval-schemas.js +144 -144
- package/scripts/lib/eval-self-correct.js +106 -106
- package/scripts/lib/eval-validator.js +185 -185
- package/scripts/lib/evidence-verifier.js +192 -0
- package/scripts/lib/evidencia-release.js +322 -322
- package/scripts/lib/evidencia-valor.js +228 -228
- package/scripts/lib/expandir-targets.js +71 -71
- package/scripts/lib/frontmatter-canonico.js +509 -0
- package/scripts/lib/gate-engine.js +871 -0
- package/scripts/lib/gate-hooks-requires.js +249 -249
- package/scripts/lib/gate-licencias.js +212 -212
- package/scripts/lib/git-config-preflight.js +48 -0
- package/scripts/lib/git-metricas.js +257 -257
- package/scripts/lib/harness-ir.js +778 -0
- package/scripts/lib/harness-source-snapshot.js +309 -0
- package/scripts/lib/integrity-ledger.js +1147 -0
- package/scripts/lib/jaccard-similarity.js +98 -98
- package/scripts/lib/legacy-gate-migration.js +324 -0
- package/scripts/lib/limpiar-basura-global.js +204 -0
- package/scripts/lib/longmemeval-runner.js +125 -125
- package/scripts/lib/metricas-dora.js +204 -204
- package/scripts/lib/notificaciones-telegram.js +1 -0
- package/scripts/lib/npm-version.js +1 -0
- package/scripts/lib/paquetes-conocidos.js +50 -50
- package/scripts/lib/plan-lock.js +61 -13
- package/scripts/lib/policy-broker.js +338 -0
- package/scripts/lib/policy-bundle.js +342 -0
- package/scripts/lib/policy-context-provider.js +310 -0
- package/scripts/lib/policy-contract.js +479 -0
- package/scripts/lib/policy-verifier-utils.js +65 -0
- package/scripts/lib/pr-analyzer.js +399 -399
- package/scripts/lib/principal-verifier.js +178 -0
- package/scripts/lib/prompt-builder.js +264 -264
- package/scripts/lib/resolver-plan-fase.js +37 -37
- package/scripts/lib/rrf-fusion.js +175 -175
- package/scripts/lib/runtime-adapter-contract.js +267 -0
- package/scripts/lib/runtime-artifact-verifier.js +426 -0
- package/scripts/lib/runtime-build-attestation.js +127 -0
- package/scripts/lib/runtime-bundle-installer.js +586 -0
- package/scripts/lib/runtime-compiler.js +327 -0
- package/scripts/lib/runtime-conformance.js +202 -0
- package/scripts/lib/runtime-doctor-core3.js +567 -0
- package/scripts/lib/runtime-doctor-input.js +59 -0
- package/scripts/lib/runtime-operation-adapter.js +267 -0
- package/scripts/lib/schema-version.js +164 -164
- package/scripts/lib/semantic-search.js +252 -252
- package/scripts/lib/signed-envelope.js +545 -0
- package/scripts/lib/single-use-store.js +359 -0
- package/scripts/lib/skills-externas.js +31 -0
- package/scripts/lib/toml-merge.js +204 -204
- package/scripts/lib/transformadores/codex.js +15 -8
- package/scripts/lib/transformadores/gemini.js +79 -5
- package/scripts/lib/w4-attestation-adapter.js +158 -0
- package/scripts/lib/w4-canario.js +337 -0
- package/scripts/lib/w4-claims.js +182 -0
- package/scripts/lib/w4-corpus-generador.js +542 -0
- package/scripts/lib/w4-gate-c5.js +115 -0
- package/scripts/lib/w4-harness-bajo-prueba.js +155 -0
- package/scripts/lib/w4-matriz-combos.js +55 -0
- package/scripts/lib/w4-motor-mutacion.js +1348 -0
- package/scripts/lib/w4-motor-replay.js +735 -0
- package/scripts/lib/w4-pin-origen.js +54 -0
- package/scripts/lib/w4-publicar-request.js +132 -0
- package/scripts/lib/w4-revocacion.js +62 -0
- package/scripts/lib/w4-runtimes-core3.js +38 -0
- package/scripts/lib/w4-scorer-certificacion.js +692 -0
- package/scripts/lib/w4-superficie-candidato.js +49 -0
- package/scripts/lib/w4-veredicto.js +452 -0
- package/scripts/lib/w4-verificar-veredicto.js +302 -0
- package/scripts/limpiar-artefactos-python.js +131 -131
- package/scripts/mcp-server/auth.js +105 -105
- package/scripts/mcp-server/cache.js +106 -106
- package/scripts/migrar-csv-a-array.js +168 -168
- package/scripts/migrar-fase-dominio.js +200 -200
- package/scripts/migrar-gates-legacy.js +108 -0
- package/scripts/publicar-certification-request.js +115 -0
- package/scripts/runtime-doctor.js +107 -0
- package/scripts/tui/componentes/selector-multi.js +189 -189
- package/scripts/tui/componentes/selector-unico.js +158 -158
- package/scripts/tui/ejecutores.js +375 -375
- package/scripts/tui/lib/colores.js +129 -129
- package/scripts/tui/lib/render.js +264 -264
- package/scripts/tui/lib/teclas.js +113 -113
- package/scripts/tui/pantallas/install-wizard.js +408 -403
- package/scripts/tui/pantallas/menu-principal.js +52 -52
- package/scripts/tui/pantallas/progreso.js +274 -274
- package/scripts/tui/pantallas/resumen.js +132 -132
- package/scripts/validar-userland-vacio.js +110 -110
- package/scripts/verificar-aislamiento-swl-eval.js +87 -0
- package/scripts/verificar-empaquetado-downstream.js +375 -0
- package/scripts/verificar-loop-constructor.js +215 -0
- package/scripts/verificar-trazabilidad.js +13 -6
- package/scripts/verificar-veredicto-real.js +84 -0
- package/instintos/.backups/perfil-usuario.yaml.2026-07-10-165128.bak +0 -53
- package/instintos/.backups/proyecto.yaml.2026-07-10-165128.bak +0 -372
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/** Verificación fail-closed de artefactos y locators runtime C10/W3. */
|
|
4
|
+
|
|
5
|
+
const crypto = require('node:crypto');
|
|
6
|
+
const fs = require('node:fs');
|
|
7
|
+
const path = require('node:path');
|
|
8
|
+
const util = require('node:util');
|
|
9
|
+
|
|
10
|
+
const MAX_ARTIFACTS = 256;
|
|
11
|
+
const MAX_ARTIFACT_BYTES = 16 * 1024 * 1024;
|
|
12
|
+
const MAX_TOTAL_BYTES = 64 * 1024 * 1024;
|
|
13
|
+
const MAX_RELATIVE_PATH = 512;
|
|
14
|
+
const MAX_PATH_SEGMENT = 128;
|
|
15
|
+
const SHA256 = /^[a-f0-9]{64}$/u;
|
|
16
|
+
const SAFE_RELATIVE_PATH = /^[A-Za-z0-9._/-]+$/u;
|
|
17
|
+
const WINDOWS_RESERVED = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu;
|
|
18
|
+
const OPEN_FLAGS = fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW || 0);
|
|
19
|
+
const VERIFIED_SETS = new WeakMap();
|
|
20
|
+
|
|
21
|
+
function crearError(code, mensaje) {
|
|
22
|
+
const error = new Error(`${code}: ${mensaje}`);
|
|
23
|
+
error.code = code;
|
|
24
|
+
error.esErrorArtefactoSWL = true;
|
|
25
|
+
return error;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function esObjetoPlano(valor) {
|
|
29
|
+
if (valor === null || typeof valor !== 'object' || Array.isArray(valor)
|
|
30
|
+
|| util.types.isProxy(valor)) return false;
|
|
31
|
+
const prototipo = Object.getPrototypeOf(valor);
|
|
32
|
+
return prototipo === Object.prototype || prototipo === null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function esMaterialDatos(valor) {
|
|
36
|
+
if (Object.getOwnPropertySymbols(valor).length > 0) return false;
|
|
37
|
+
return Object.values(Object.getOwnPropertyDescriptors(valor))
|
|
38
|
+
.every((descriptor) => descriptor.enumerable && 'value' in descriptor);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function esArrayDatos(valor) {
|
|
42
|
+
if (!Array.isArray(valor) || util.types.isProxy(valor)
|
|
43
|
+
|| Object.getOwnPropertySymbols(valor).length > 0) return false;
|
|
44
|
+
const descriptores = Object.getOwnPropertyDescriptors(valor);
|
|
45
|
+
const indices = Object.entries(descriptores).filter(([clave]) => clave !== 'length');
|
|
46
|
+
return indices.length === valor.length && indices.every(([clave, descriptor]) => (
|
|
47
|
+
/^(?:0|[1-9]\d*)$/u.test(clave) && descriptor.enumerable && 'value' in descriptor
|
|
48
|
+
));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function assertShape(valor, campos, nombre) {
|
|
52
|
+
if (!esObjetoPlano(valor)) throw crearError('LOCATOR_INVALID', `${nombre} no es objeto plano`);
|
|
53
|
+
if (!esMaterialDatos(valor)) {
|
|
54
|
+
throw crearError('LOCATOR_INVALID', `${nombre} contiene material hostil`);
|
|
55
|
+
}
|
|
56
|
+
const faltante = campos.find((campo) => !Object.hasOwn(valor, campo));
|
|
57
|
+
if (faltante) throw crearError('LOCATOR_INVALID', `${nombre} omite ${faltante}`);
|
|
58
|
+
const extra = Object.keys(valor).find((campo) => !campos.includes(campo));
|
|
59
|
+
if (extra) throw crearError('LOCATOR_INVALID', `${nombre} contiene campo ${extra}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function rutasIguales(izquierda, derecha) {
|
|
63
|
+
return path.relative(izquierda, derecha) === '';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function mismaIdentidad(izquierda, derecha) {
|
|
67
|
+
return izquierda.dev === derecha.dev && izquierda.ino === derecha.ino;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function validarDirectorio(stats, code, nombre) {
|
|
71
|
+
if (stats.isSymbolicLink() || !stats.isDirectory()) {
|
|
72
|
+
throw crearError(code, `${nombre} debe ser directorio real`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function cerrarDescriptores(descriptores) {
|
|
77
|
+
const unicos = [...new Set(descriptores.filter(Number.isInteger))];
|
|
78
|
+
const errores = [];
|
|
79
|
+
for (const descriptor of unicos) {
|
|
80
|
+
try { fs.closeSync(descriptor); } catch (error) { errores.push(error); }
|
|
81
|
+
}
|
|
82
|
+
return errores;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function cerrarRecursos(descriptores, errorOperacion) {
|
|
86
|
+
const erroresCierre = cerrarDescriptores(descriptores);
|
|
87
|
+
if (erroresCierre.length > 0) {
|
|
88
|
+
const error = crearError('CLOSE_FAILED', 'no se pudieron cerrar todos los descriptores');
|
|
89
|
+
error.cause = errorOperacion || erroresCierre[0];
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
if (errorOperacion) throw errorOperacion;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function resolverRaiz(bundleRoot) {
|
|
96
|
+
if (typeof bundleRoot !== 'string' || !path.isAbsolute(bundleRoot)) {
|
|
97
|
+
throw crearError('ROOT_INVALID', 'la raíz absoluta es requerida');
|
|
98
|
+
}
|
|
99
|
+
const ruta = path.resolve(bundleRoot);
|
|
100
|
+
try {
|
|
101
|
+
const stats = fs.lstatSync(ruta, { bigint: true });
|
|
102
|
+
validarDirectorio(stats, 'ROOT_INVALID', 'la raíz');
|
|
103
|
+
if (!rutasIguales(ruta, fs.realpathSync(ruta))) {
|
|
104
|
+
throw crearError('ROOT_INVALID', 'la raíz contiene resolución por link');
|
|
105
|
+
}
|
|
106
|
+
return { ruta, stats };
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (error.code === 'ROOT_INVALID') throw error;
|
|
109
|
+
throw crearError('ROOT_INVALID', 'la raíz no existe o no es accesible');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function abrirRaiz(bundleRoot) {
|
|
114
|
+
const { ruta, stats: antes } = resolverRaiz(bundleRoot);
|
|
115
|
+
let descriptor;
|
|
116
|
+
try {
|
|
117
|
+
descriptor = fs.openSync(ruta, OPEN_FLAGS);
|
|
118
|
+
const handle = fs.fstatSync(descriptor, { bigint: true });
|
|
119
|
+
const despues = fs.lstatSync(ruta, { bigint: true });
|
|
120
|
+
validarDirectorio(handle, 'ROOT_CHANGED', 'la raíz abierta');
|
|
121
|
+
validarDirectorio(despues, 'ROOT_CHANGED', 'la raíz actual');
|
|
122
|
+
if (!mismaIdentidad(antes, handle) || !mismaIdentidad(handle, despues)) {
|
|
123
|
+
throw crearError('ROOT_CHANGED', 'la raíz cambió entre lstat y open');
|
|
124
|
+
}
|
|
125
|
+
return { ruta, descriptor, dev: handle.dev, ino: handle.ino, code: 'ROOT_CHANGED' };
|
|
126
|
+
} catch (error) {
|
|
127
|
+
const fallo = error.code === 'ROOT_CHANGED'
|
|
128
|
+
? error
|
|
129
|
+
: crearError('OPEN_FAILED', 'no se pudo fijar la raíz');
|
|
130
|
+
cerrarRecursos([descriptor], fallo);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function validarDirectorioActual(handle) {
|
|
135
|
+
try {
|
|
136
|
+
const abierto = fs.fstatSync(handle.descriptor, { bigint: true });
|
|
137
|
+
const actual = fs.lstatSync(handle.ruta, { bigint: true });
|
|
138
|
+
validarDirectorio(abierto, handle.code, 'directorio abierto');
|
|
139
|
+
validarDirectorio(actual, handle.code, 'directorio actual');
|
|
140
|
+
if (!mismaIdentidad(handle, abierto) || !mismaIdentidad(handle, actual)) {
|
|
141
|
+
throw crearError(handle.code, 'directorio cambió de identidad');
|
|
142
|
+
}
|
|
143
|
+
} catch (error) {
|
|
144
|
+
if (error.code === handle.code) throw error;
|
|
145
|
+
throw crearError(handle.code, 'directorio desapareció o dejó de ser verificable');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function validarDirectorios(handles) {
|
|
150
|
+
handles.forEach(validarDirectorioActual);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function abrirDirectorio(ruta, padres) {
|
|
154
|
+
let descriptor;
|
|
155
|
+
let antes;
|
|
156
|
+
try {
|
|
157
|
+
antes = fs.lstatSync(ruta, { bigint: true });
|
|
158
|
+
} catch {
|
|
159
|
+
throw crearError('PATH_INVALID', 'ancestro ausente');
|
|
160
|
+
}
|
|
161
|
+
if (antes.isSymbolicLink()) throw crearError('LINK_REJECTED', 'symlink en path');
|
|
162
|
+
if (!antes.isDirectory()) throw crearError('PATH_INVALID', 'ancestro no es directorio');
|
|
163
|
+
try {
|
|
164
|
+
validarDirectorios(padres);
|
|
165
|
+
descriptor = fs.openSync(ruta, OPEN_FLAGS);
|
|
166
|
+
const abierto = fs.fstatSync(descriptor, { bigint: true });
|
|
167
|
+
const despues = fs.lstatSync(ruta, { bigint: true });
|
|
168
|
+
validarDirectorio(abierto, 'DIRECTORY_CHANGED', 'ancestro abierto');
|
|
169
|
+
validarDirectorio(despues, 'DIRECTORY_CHANGED', 'ancestro actual');
|
|
170
|
+
if (!mismaIdentidad(antes, abierto) || !mismaIdentidad(abierto, despues)) {
|
|
171
|
+
throw crearError('DIRECTORY_CHANGED', 'ancestro cambió entre lstat y open');
|
|
172
|
+
}
|
|
173
|
+
return { ruta, descriptor, dev: abierto.dev, ino: abierto.ino, code: 'DIRECTORY_CHANGED' };
|
|
174
|
+
} catch (error) {
|
|
175
|
+
const fallo = error.code === 'DIRECTORY_CHANGED'
|
|
176
|
+
? error
|
|
177
|
+
: crearError('OPEN_FAILED', 'no se pudo fijar un ancestro');
|
|
178
|
+
cerrarRecursos([descriptor], fallo);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function validarSegmentoPortable(segmento) {
|
|
183
|
+
if (segmento.length > MAX_PATH_SEGMENT || /[. ]$/u.test(segmento)) {
|
|
184
|
+
throw crearError('PATH_INVALID', 'segmento excede longitud o termina en punto/espacio');
|
|
185
|
+
}
|
|
186
|
+
if (WINDOWS_RESERVED.test(segmento)) {
|
|
187
|
+
throw crearError('PATH_INVALID', 'nombre reservado no portable');
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function validarPathRelativo(relativo) {
|
|
192
|
+
if (typeof relativo !== 'string' || relativo.length > MAX_RELATIVE_PATH
|
|
193
|
+
|| !SAFE_RELATIVE_PATH.test(relativo)) {
|
|
194
|
+
throw crearError('PATH_INVALID', 'path relativo no canónico o excede longitud');
|
|
195
|
+
}
|
|
196
|
+
const partes = relativo.split('/');
|
|
197
|
+
if (path.posix.isAbsolute(relativo) || relativo.includes(':') || relativo.includes('\\')
|
|
198
|
+
|| partes.some((parte) => parte === '' || parte === '.' || parte === '..')) {
|
|
199
|
+
throw crearError('PATH_INVALID', 'path absoluto, traversal, ADS o segmento inválido');
|
|
200
|
+
}
|
|
201
|
+
partes.forEach(validarSegmentoPortable);
|
|
202
|
+
return partes;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function validarListaRutas(rutas) {
|
|
206
|
+
if (!esArrayDatos(rutas) || rutas.length === 0) {
|
|
207
|
+
throw crearError('PATH_INVALID', 'la lista de paths debe ser datos no vacíos');
|
|
208
|
+
}
|
|
209
|
+
if (rutas.length > MAX_ARTIFACTS) throw crearError('LIMIT_EXCEEDED', 'cantidad de artefactos');
|
|
210
|
+
rutas.forEach(validarPathRelativo);
|
|
211
|
+
const ordenadas = [...rutas].sort();
|
|
212
|
+
const caseFold = rutas.map((ruta) => ruta.toLowerCase());
|
|
213
|
+
if (new Set(rutas).size !== rutas.length || new Set(caseFold).size !== rutas.length
|
|
214
|
+
|| JSON.stringify(rutas) !== JSON.stringify(ordenadas)) {
|
|
215
|
+
throw crearError('PATH_INVALID', 'paths duplicados, con colisión case-fold o fuera de orden');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function abrirAncestros(raiz, partes) {
|
|
220
|
+
const handles = [raiz];
|
|
221
|
+
let actual = raiz.ruta;
|
|
222
|
+
try {
|
|
223
|
+
for (const parte of partes.slice(0, -1)) {
|
|
224
|
+
actual = path.join(actual, parte);
|
|
225
|
+
handles.push(abrirDirectorio(actual, handles));
|
|
226
|
+
}
|
|
227
|
+
return handles;
|
|
228
|
+
} catch (error) {
|
|
229
|
+
const abiertos = handles.slice(1).reverse().map(({ descriptor }) => descriptor);
|
|
230
|
+
cerrarRecursos(abiertos, error);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function identidadArchivo(stats) {
|
|
235
|
+
return [stats.dev, stats.ino, stats.size, stats.mtimeNs, stats.ctimeNs]
|
|
236
|
+
.map((valor) => String(valor)).join(':');
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function validarStatsArchivo(stats) {
|
|
240
|
+
if (!stats.isFile()) throw crearError('TYPE_REJECTED', 'artefacto no es archivo regular');
|
|
241
|
+
if (stats.nlink !== 1n) throw crearError('LINK_REJECTED', 'hardlink detectado');
|
|
242
|
+
if (stats.size > BigInt(MAX_ARTIFACT_BYTES)) {
|
|
243
|
+
throw crearError('LIMIT_EXCEEDED', 'artefacto demasiado grande');
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function leerBytes(descriptor, longitud) {
|
|
248
|
+
const bytes = Buffer.alloc(longitud);
|
|
249
|
+
let offset = 0;
|
|
250
|
+
while (offset < longitud) {
|
|
251
|
+
const leidos = fs.readSync(descriptor, bytes, offset, longitud - offset, offset);
|
|
252
|
+
if (leidos === 0) throw crearError('ARTIFACT_CHANGED', 'EOF antes del tamaño verificado');
|
|
253
|
+
offset += leidos;
|
|
254
|
+
}
|
|
255
|
+
return bytes;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function estaConfinado(raiz, destino) {
|
|
259
|
+
const relativo = path.relative(raiz, destino);
|
|
260
|
+
const primerSegmento = relativo.split(path.sep)[0];
|
|
261
|
+
return relativo !== '' && primerSegmento !== '..' && !path.isAbsolute(relativo);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function validarPathFinal(raiz, destino, statsHandle) {
|
|
265
|
+
try {
|
|
266
|
+
const real = fs.realpathSync(destino);
|
|
267
|
+
const statsPath = fs.lstatSync(destino, { bigint: true });
|
|
268
|
+
if (!estaConfinado(raiz, real) || statsPath.isSymbolicLink()) {
|
|
269
|
+
throw crearError('PATH_ESCAPE', 'path final fuera de la raíz o symlink');
|
|
270
|
+
}
|
|
271
|
+
if (!mismaIdentidad(statsPath, statsHandle)) {
|
|
272
|
+
throw crearError('ARTIFACT_CHANGED', 'path cambió de identidad durante lectura');
|
|
273
|
+
}
|
|
274
|
+
} catch (error) {
|
|
275
|
+
if (['PATH_ESCAPE', 'ARTIFACT_CHANGED'].includes(error.code)) throw error;
|
|
276
|
+
throw crearError('ARTIFACT_CHANGED', 'path desapareció durante lectura');
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function abrirArchivo(ruta) {
|
|
281
|
+
try {
|
|
282
|
+
return fs.openSync(ruta, OPEN_FLAGS);
|
|
283
|
+
} catch {
|
|
284
|
+
throw crearError('OPEN_FAILED', 'no se pudo abrir el artefacto');
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function leerArchivoEstable(raiz, relativo) {
|
|
289
|
+
const partes = validarPathRelativo(relativo);
|
|
290
|
+
const handles = abrirAncestros(raiz, partes);
|
|
291
|
+
const destino = path.join(raiz.ruta, ...partes);
|
|
292
|
+
let descriptor;
|
|
293
|
+
let bytes;
|
|
294
|
+
let errorOperacion;
|
|
295
|
+
try {
|
|
296
|
+
validarDirectorios(handles);
|
|
297
|
+
descriptor = abrirArchivo(destino);
|
|
298
|
+
const antes = fs.fstatSync(descriptor, { bigint: true });
|
|
299
|
+
validarStatsArchivo(antes);
|
|
300
|
+
validarDirectorios(handles);
|
|
301
|
+
bytes = leerBytes(descriptor, Number(antes.size));
|
|
302
|
+
const despues = fs.fstatSync(descriptor, { bigint: true });
|
|
303
|
+
validarDirectorios(handles);
|
|
304
|
+
if (identidadArchivo(antes) !== identidadArchivo(despues)
|
|
305
|
+
|| antes.nlink !== despues.nlink) {
|
|
306
|
+
throw crearError('ARTIFACT_CHANGED', 'archivo cambió durante lectura');
|
|
307
|
+
}
|
|
308
|
+
validarStatsArchivo(despues);
|
|
309
|
+
validarPathFinal(raiz.ruta, destino, despues);
|
|
310
|
+
validarDirectorios(handles);
|
|
311
|
+
} catch (error) {
|
|
312
|
+
errorOperacion = error.esErrorArtefactoSWL
|
|
313
|
+
? error
|
|
314
|
+
: crearError('OPEN_FAILED', 'falló la lectura por descriptor');
|
|
315
|
+
}
|
|
316
|
+
const ancestros = handles.slice(1).reverse().map((handle) => handle.descriptor);
|
|
317
|
+
cerrarRecursos([descriptor, ...ancestros], errorOperacion);
|
|
318
|
+
return bytes;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function metadataDe(ruta, bytes) {
|
|
322
|
+
return Object.freeze({
|
|
323
|
+
path: ruta,
|
|
324
|
+
bytes: bytes.length,
|
|
325
|
+
sha256: crypto.createHash('sha256').update(bytes).digest('hex'),
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function registrarConjunto(entradas) {
|
|
330
|
+
const metadata = Object.freeze(entradas.map(({ path: ruta, bytes }) => metadataDe(ruta, bytes)));
|
|
331
|
+
const token = Object.freeze({ kind: 'verified-runtime-artifacts', entries: metadata });
|
|
332
|
+
const bytesPorRuta = entradas.map(({ path: ruta, bytes }) => [ruta, Buffer.from(bytes)]);
|
|
333
|
+
VERIFIED_SETS.set(token, new Map(bytesPorRuta));
|
|
334
|
+
return token;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function cargarArtefactosVerificados(bundleRoot, rutas) {
|
|
338
|
+
validarListaRutas(rutas);
|
|
339
|
+
const raiz = abrirRaiz(bundleRoot);
|
|
340
|
+
let total = 0;
|
|
341
|
+
let conjunto;
|
|
342
|
+
let errorOperacion;
|
|
343
|
+
try {
|
|
344
|
+
const entradas = rutas.map((ruta) => {
|
|
345
|
+
const bytes = leerArchivoEstable(raiz, ruta);
|
|
346
|
+
total += bytes.length;
|
|
347
|
+
if (total > MAX_TOTAL_BYTES) throw crearError('LIMIT_EXCEEDED', 'tamaño total excedido');
|
|
348
|
+
return { path: ruta, bytes };
|
|
349
|
+
});
|
|
350
|
+
validarDirectorioActual(raiz);
|
|
351
|
+
conjunto = registrarConjunto(entradas);
|
|
352
|
+
} catch (error) {
|
|
353
|
+
errorOperacion = error;
|
|
354
|
+
}
|
|
355
|
+
cerrarRecursos([raiz.descriptor], errorOperacion);
|
|
356
|
+
return conjunto;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function exigirConjunto(conjunto) {
|
|
360
|
+
const interno = VERIFIED_SETS.get(conjunto);
|
|
361
|
+
if (!interno) throw crearError('UNVERIFIED_SET', 'se requiere conjunto verificado');
|
|
362
|
+
return interno;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function esConjuntoArtefactosVerificado(valor) {
|
|
366
|
+
return VERIFIED_SETS.has(valor);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function crearLocator(conjunto) {
|
|
370
|
+
exigirConjunto(conjunto);
|
|
371
|
+
const entries = Object.freeze(conjunto.entries.map((entry) => Object.freeze({ ...entry })));
|
|
372
|
+
return Object.freeze({ schemaVersion: '1.0.0', kind: 'swl-runtime-locator', entries });
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function validarEntradaLocator(entry, indice) {
|
|
376
|
+
assertShape(entry, ['path', 'bytes', 'sha256'], `locator entry ${indice}`);
|
|
377
|
+
validarPathRelativo(entry.path);
|
|
378
|
+
if (!Number.isSafeInteger(entry.bytes) || entry.bytes < 0 || entry.bytes > MAX_ARTIFACT_BYTES) {
|
|
379
|
+
throw crearError('LOCATOR_INVALID', 'bytes de locator inválidos');
|
|
380
|
+
}
|
|
381
|
+
if (typeof entry.sha256 !== 'string' || !SHA256.test(entry.sha256)) {
|
|
382
|
+
throw crearError('LOCATOR_INVALID', 'digest de locator inválido');
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function validarLocator(locator) {
|
|
387
|
+
assertShape(locator, ['schemaVersion', 'kind', 'entries'], 'locator');
|
|
388
|
+
if (locator.schemaVersion !== '1.0.0' || locator.kind !== 'swl-runtime-locator') {
|
|
389
|
+
throw crearError('LOCATOR_INVALID', 'versión o kind de locator inválido');
|
|
390
|
+
}
|
|
391
|
+
if (!esArrayDatos(locator.entries) || locator.entries.length === 0) {
|
|
392
|
+
throw crearError('LOCATOR_INVALID', 'locator sin entradas de datos');
|
|
393
|
+
}
|
|
394
|
+
if (locator.entries.length > MAX_ARTIFACTS) {
|
|
395
|
+
throw crearError('LIMIT_EXCEEDED', 'cantidad de entradas del locator');
|
|
396
|
+
}
|
|
397
|
+
locator.entries.forEach(validarEntradaLocator);
|
|
398
|
+
validarListaRutas(locator.entries.map(({ path: ruta }) => ruta));
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function verificarLocator(bundleRoot, locator) {
|
|
402
|
+
validarLocator(locator);
|
|
403
|
+
const conjunto = cargarArtefactosVerificados(
|
|
404
|
+
bundleRoot, locator.entries.map(({ path: ruta }) => ruta)
|
|
405
|
+
);
|
|
406
|
+
if (JSON.stringify(conjunto.entries) !== JSON.stringify(locator.entries)) {
|
|
407
|
+
throw crearError('ARTIFACT_MISMATCH', 'bytes o digest no coinciden con locator');
|
|
408
|
+
}
|
|
409
|
+
return conjunto;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function leerArtefactoVerificado(conjunto, relativo) {
|
|
413
|
+
const interno = exigirConjunto(conjunto);
|
|
414
|
+
const bytes = interno.get(relativo);
|
|
415
|
+
if (!bytes) throw crearError('PATH_INVALID', 'artefacto no pertenece al conjunto');
|
|
416
|
+
return Buffer.from(bytes);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
module.exports = {
|
|
420
|
+
cargarArtefactosVerificados,
|
|
421
|
+
crearLocator,
|
|
422
|
+
esConjuntoArtefactosVerificado,
|
|
423
|
+
leerArtefactoVerificado,
|
|
424
|
+
validarListaRutasPortables: validarListaRutas,
|
|
425
|
+
verificarLocator,
|
|
426
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/** Registra una construcción Core-3 sin producir autoridad conductual. */
|
|
4
|
+
|
|
5
|
+
const util = require('node:util');
|
|
6
|
+
|
|
7
|
+
const { isKernelDependencies } = require('./policy-contract');
|
|
8
|
+
const { validarListaRutasPortables } = require('./runtime-artifact-verifier');
|
|
9
|
+
const { parsearIJson, validarTimestampIso } = require('./signed-envelope');
|
|
10
|
+
|
|
11
|
+
const MAX_RAW_BYTES = 256 * 1024;
|
|
12
|
+
const SHA256 = /^[a-f0-9]{64}$/u;
|
|
13
|
+
const PAYLOAD_KEYS = Object.freeze([
|
|
14
|
+
'schemaVersion', 'kind', 'purpose', 'runtimeId', 'installerTarget', 'adapterId',
|
|
15
|
+
'adapterSchemaVersion', 'contractVersion', 'manifestDigest', 'locatorDigest',
|
|
16
|
+
'outputs', 'builtAt', 'effectiveMode',
|
|
17
|
+
]);
|
|
18
|
+
const RUNTIMES = Object.freeze({
|
|
19
|
+
'claude-code': 'claude',
|
|
20
|
+
'codex-cli': 'codex',
|
|
21
|
+
'gemini-cli': 'gemini',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
function fail(codigo, mensaje) {
|
|
25
|
+
const error = new TypeError(mensaje);
|
|
26
|
+
error.codigo = codigo;
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function exactKeys(value, keys) {
|
|
31
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
32
|
+
&& JSON.stringify(Object.keys(value).sort()) === JSON.stringify([...keys].sort());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function validateRawBytes(rawBytes) {
|
|
36
|
+
if (!rawBytes || typeof rawBytes !== 'object' || util.types.isProxy(rawBytes)) {
|
|
37
|
+
fail('BUILD_ATTESTATION_INVALID', 'bytes de atestación inválidos');
|
|
38
|
+
}
|
|
39
|
+
const prototype = Object.getPrototypeOf(rawBytes);
|
|
40
|
+
const validPrototype = prototype === Buffer.prototype || prototype === Uint8Array.prototype;
|
|
41
|
+
const intrusive = ['buffer', 'byteOffset', 'byteLength'].some(
|
|
42
|
+
(property) => Object.hasOwn(rawBytes, property)
|
|
43
|
+
);
|
|
44
|
+
if (!validPrototype || intrusive
|
|
45
|
+
|| rawBytes.byteLength === 0 || rawBytes.byteLength > MAX_RAW_BYTES) {
|
|
46
|
+
fail('BUILD_ATTESTATION_INVALID', 'bytes de atestación inválidos');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function parsePayload(rawBytes) {
|
|
51
|
+
validateRawBytes(rawBytes);
|
|
52
|
+
try {
|
|
53
|
+
return parsearIJson(rawBytes);
|
|
54
|
+
} catch {
|
|
55
|
+
fail('BUILD_ATTESTATION_INVALID', 'atestación no es I-JSON canónico');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function validateOutputs(outputs) {
|
|
60
|
+
if (!Array.isArray(outputs) || !outputs.every((output) => (
|
|
61
|
+
exactKeys(output, ['path', 'sha256'])
|
|
62
|
+
&& typeof output.path === 'string' && output.path.startsWith('outputs/')
|
|
63
|
+
&& typeof output.sha256 === 'string' && SHA256.test(output.sha256)
|
|
64
|
+
))) return false;
|
|
65
|
+
try {
|
|
66
|
+
validarListaRutasPortables(outputs.map((output) => output.path));
|
|
67
|
+
return true;
|
|
68
|
+
} catch {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function validateBindings(payload) {
|
|
74
|
+
if (!Object.hasOwn(RUNTIMES, payload.runtimeId)) return false;
|
|
75
|
+
return payload.installerTarget === RUNTIMES[payload.runtimeId]
|
|
76
|
+
&& payload.adapterId === `runtime-adapter:${payload.runtimeId}`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function validateConstants(payload) {
|
|
80
|
+
return payload.schemaVersion === '1.0.0'
|
|
81
|
+
&& payload.kind === 'swl-runtime-build-attestation'
|
|
82
|
+
&& payload.purpose === 'runtime-build'
|
|
83
|
+
&& payload.adapterSchemaVersion === '1.0.0'
|
|
84
|
+
&& payload.contractVersion === '1.0.0'
|
|
85
|
+
&& payload.effectiveMode === 'proposal_only';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function validatePayload(payload) {
|
|
89
|
+
try {
|
|
90
|
+
validarTimestampIso(payload.builtAt, 'build timestamp');
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return exactKeys(payload, PAYLOAD_KEYS)
|
|
95
|
+
&& validateConstants(payload)
|
|
96
|
+
&& validateBindings(payload)
|
|
97
|
+
&& SHA256.test(payload.manifestDigest)
|
|
98
|
+
&& SHA256.test(payload.locatorDigest)
|
|
99
|
+
&& validateOutputs(payload.outputs);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function validateCas(expectedSequence, expectedHeadHash) {
|
|
103
|
+
if (!Number.isSafeInteger(expectedSequence) || expectedSequence < 0
|
|
104
|
+
|| Object.is(expectedSequence, -0) || typeof expectedHeadHash !== 'string'
|
|
105
|
+
|| !SHA256.test(expectedHeadHash)) {
|
|
106
|
+
fail('BUILD_CAS_INVALID', 'precondición CAS inválida');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function registrarBuildAttestation(rawBytes, expectedSequence, expectedHeadHash, dependencies) {
|
|
111
|
+
if (arguments.length !== 4 || !isKernelDependencies(dependencies)) {
|
|
112
|
+
fail('BUILD_AUTHORITY_INVALID', 'dependencias W2 no verificadas');
|
|
113
|
+
}
|
|
114
|
+
validateCas(expectedSequence, expectedHeadHash);
|
|
115
|
+
const payload = parsePayload(rawBytes);
|
|
116
|
+
if (!validatePayload(payload)) {
|
|
117
|
+
fail('BUILD_ATTESTATION_INVALID', 'contrato de atestación inválido');
|
|
118
|
+
}
|
|
119
|
+
return dependencies.integrityLedger.append({
|
|
120
|
+
expectedSequence,
|
|
121
|
+
expectedHeadHash,
|
|
122
|
+
eventType: 'runtime-build',
|
|
123
|
+
payload,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
module.exports = { registrarBuildAttestation };
|