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
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ospec-workflow",
"description": "Spec-Driven Development workflow for VS Code Agent Customization with OpenSpec, strict TDD, phase agents, skills, hooks, and verification contracts.",
"version": "2.53.0",
"version": "2.53.1",
"author": {
"name": "Manuel Michael Retamozo García"
},
Expand Down
2 changes: 1 addition & 1 deletion .plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ospec-workflow",
"description": "Spec-Driven Development workflow for VS Code Agent Customization with OpenSpec, strict TDD, phase agents, skills, hooks, and verification contracts.",
"version": "2.53.0",
"version": "2.53.1",
"author": {
"name": "Manuel Michael Retamozo García"
},
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.53.1] - 2026-08-28

### Security
- **Segregación física de `rawEvidence` y rechazo explícito de metadatos de caller (`UNTRUSTED_CALLER_METADATA`)**:
- `normalizeEvidence` rechaza de forma fail-closed (`UNTRUSTED_CALLER_METADATA`) cualquier observación `rawEvidence` que contenga propiedades semánticas (`role`, `obligation_ids`, `obligation_id`, `evidence_requirements_satisfied`).
- Las observaciones físicas admiten estrictamente: `bytes` / `rawBytes`, `provenance`, `origin`, `node_id`, `execution_sequence`.
- Se eliminan atributos semánticos del payload devuelto por `normalizeEvidence`.

### Changed
- **Derivación autoritativa desde Runner Receipts y eliminación de copia ciega**:
- `verifyCandidate` resuelve `role` y `obligation_ids` consultando el Execution Graph y runner receipts (`node.role`, `node.kind`, `receipt.role`, `graphObligations.implemented_by`).
- `evidence_requirements_satisfied` se deriva exclusivamente de los tokens atestiguados en `runner_receipts` o `receipts` del harness; se erradica por completo la copia automática de `node.required_evidence`.
- Ausencia de receipts para una obligación MUST produce `UNFULFILLED_MUST` sin generar afirmaciones espurias.
- **Validación cronológica causal obligatoria por `execution_sequence`**:
- `assertRoleOrder` exige la presencia de `execution_sequence` (`run_id`, `ordinal` monotónico creciente y `previous_evidence_id`) en estrategias temporales (`strict-tdd`, `bug`, `refactor`).
- Se prohíbe explícitamente el fallback al orden posicional del array JSON.
- Verificación causal estricta: `red.ordinal < green.ordinal` (y enlace `previous_evidence_id`) en TDD, `red < patch < green` en `bug`, y `before < after` en `refactor`. Violaciones emiten `STRATEGY_SEQUENCE_VIOLATION`.
- **Replay criptográficamente íntegro de Evidence en Assurance Graph**:
- `validateReplayRecords` recomputa `digestRawBytes` y `computeEvidenceId(record, bytes)` validando igualdad exacta contra `record.digest` y `record.evidence_id`.
- Revalidación obligatoria de procedencia mediante `evaluateProvenanceSufficiency(record, { requireRuntime: true })`, fallando con `GRAPH_DIVERGENCE` ante adulteración de digest, id o insuficiencia de provenance.
- ADRs `docs/adr/adr-20260828-010` a `013`. Specs `independent-verification` y `assurance-graph`.
- Cierre definitivo de los hallazgos B1, B2, B3 y H1 de K6b. Archivado en `openspec/changes/archive/2026-08-28-k6b-trusted-evidence-replay-closure/`.

## [2.53.0] - 2026-08-28

### Added
Expand Down
20 changes: 20 additions & 0 deletions docs/adr/adr-20260828-010-untrusted-caller-metadata-rejection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ADR-001: Segregación física estricta de rawEvidence (UNTRUSTED_CALLER_METADATA)

- Status: proposed
- Change: k6b-trusted-evidence-replay-closure
- Date: 2026-08-28

## Context
Los llamadores y workers no confiables podían inyectar propiedades semánticas (`role`, `obligation_ids`, `evidence_requirements_satisfied`) directamente en el objeto `rawEvidence`, eludiendo la verificación independiente y comprometiendo la frontera de confianza.

## Decision
Rechazar de forma inmediata y fail-closed con `UNTRUSTED_CALLER_METADATA` en `normalizeEvidence` cualquier payload `rawEvidence` que contenga `role`, `obligation_ids`, `obligation_id` o `evidence_requirements_satisfied`. La observación física sólo admite `bytes`/`rawBytes`, `provenance`, `origin`, `node_id` y `execution_sequence`.

## Alternatives
- Filtrar o ignorar silenciosamente las propiedades semánticas del caller — rechazado: enmascara bugs en el harness y potenciales intentos de inyección maliciosa.
- Aceptar metadatos de caller como sugerencias no vinculantes — rechazado: debilita la frontera de confianza del verificador independiente.

## Consequences
- Facilita: Garantía estricta de que las observaciones físicas no contienen aserciones semánticas no verificadas.
- Dificulta: Requiere que todos los harnesses y generadores de fixtures envíen exclusivamente cargas físicas puras.
- Reversibilidad: Alta (ajustable en `normalizeEvidence`).
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ADR-002: Derivación autoritativa de satisfacción desde Runner Receipts

- Status: proposed
- Change: k6b-trusted-evidence-replay-closure
- Date: 2026-08-28

## Context
El verificador independiente permitía un fallback de copia ciega de `node.required_evidence` hacia `evidence_requirements_satisfied` cuando el payload no declaraba cobertura, aprobando obligaciones críticas sin que un recibo de ejecución hubiera atestiguado la prueba efectiva.

## Decision
Derivar `evidence_requirements_satisfied` en `verifyCandidate` exclusivamente a partir de runner receipts confiables (`receipts` / `runner_receipts`) emitidos por el harness de ejecución. Se prohíbe explícitamente la copia automática o por defecto de `node.required_evidence`; si no hay recibo que lo atestigüe, el conjunto de satisfacción es vacío y la obligación MUST falla con `UNFULFILLED_MUST`.

## Alternatives
- Mantener la copia por defecto de `node.required_evidence` cuando no se especifica satisfacción — rechazado: genera falsos positivos donde la mera existencia de un archivo da por probada una obligación.
- Asumir satisfacción completa si el nodo del grafo está vinculado — rechazado: viola el principio de evidencia fail-closed sin atestación.

## Consequences
- Facilita: Verificación infalsificable donde cada token satisfecho está respaldado por un recibo de ejecución real.
- Dificulta: Exige que el harness y los tests pasen explícitamente recibos de runner para que las obligaciones MUST alcancen `PASS`.
- Reversibilidad: Alta (ajustable en `verifyCandidate`).
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ADR-003: Cronología causal estricta mediante execution_sequence

- Status: proposed
- Change: k6b-trusted-evidence-replay-closure
- Date: 2026-08-28

## Context
Las estrategias temporales (`strict-tdd`, `bug`, `refactor`) recurrían al orden posicional de los elementos en el array JSON de `rawEvidence` para evaluar la secuencia cronológica, lo que permitía simular TDD o refactorizaciones invirtiendo el orden de las evidencias en el array sin atestación causal.

## Decision
Exigir obligatoriamente en `assertRoleOrder` un objeto `execution_sequence` válido (`run_id` consistente, `ordinal` monotónico creciente y encadenamiento `previous_evidence_id`) para cada evidencia en estrategias `strict-tdd`, `bug` y `refactor`. Se prohíbe de forma tajante el fallback a índices de array JSON, fallando inmediatamente con `STRATEGY_SEQUENCE_VIOLATION` ante ausencia o violación de orden.

## Alternatives
- Mantener el índice de array como fallback si falta `execution_sequence` — rechazado: la posición en un array JSON no tiene valor criptográfico ni atestación temporal.
- Comparar timestamps de archivo (mtime/ctime) — rechazado: no deterministas y fácilmente manipulables por el sistema operativo o workers.

## Consequences
- Facilita: Garantía causal matemática de que RED precedió a GREEN y que `characterization-before` precedió a `after`.
- Dificulta: Requiere que todos los pipelines y tests emitan metadatos de secuencia causal en sus observaciones de prueba.
- Reversibilidad: Alta (ajustable en `strategy-policy.js`).
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ADR-004: Replay criptográficamente íntegro en Assurance Graph

- Status: proposed
- Change: k6b-trusted-evidence-replay-closure
- Date: 2026-08-28

## Context
La validación en `replayAssuranceGraph` (`validateReplayRecords`) omitía la recomputación de `computeEvidenceId` y la invocación de `evaluateProvenanceSufficiency` durante la revalidación de evidencias, lo que permitía persistir o reproducir grafos con identificadores desfasados o procedencias débiles sin detección.

## Decision
Extender `validateReplayRecords` para recomputar exhaustivamente el digest de bytes con `digestRawBytes(bytes)`, recomputar `computeEvidenceId(record, bytes)`, contrastar ambos contra `record.digest` y `record.evidence_id`, y ejecutar `evaluateProvenanceSufficiency(record)`. Cualquier discrepancia, mutación de bytes o insuficiencia de procedencia detona inmediatamente un fallo `GRAPH_DIVERGENCE`.

## Alternatives
- Revalidar únicamente la conformidad sintáctica contra el esquema JSON — rechazado: no detecta sustitución de hashes ni inconsistencias en identificadores derivados.
- Asumir que los identificadores persistidos son válidos por construcción — rechazado: ignora posibles corrupciones o modificaciones en el medio de persistencia.

## Consequences
- Facilita: Replay determinista e inmutable donde cualquier manipulación o degradación de evidencias es detectada y rechazada.
- Dificulta: El proceso de replay debe recibir o tener acceso a los bytes de las evidencias para la recomputación criptográfica.
- Reversibilidad: Alta (ajustable en `assurance-graph/index.js`).
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Apply Progress: K6b Trusted Evidence and Replay Closure

## Phase 1: Physical Observation Segregation
- **Tasks Completed**: 1.1, 1.2, 1.3
- **Changes**:
- In `scripts/lib/independent-verifier/evidence.js` (`normalizeEvidence`), added fail-closed validation rejecting caller-supplied semantic metadata (`role`, `obligation_ids`, `obligation_id`, `evidence_requirements_satisfied`) with `UNTRUSTED_CALLER_METADATA`.
- Stripped caller semantic attributes from normalized return payload, returning only physical observation properties (`evidence`, `execution_sequence`, `raw`).
- Added dedicated unit test suite in `scripts/lib/independent-verifier/evidence.test.js` validating individual and combined injection attempts.
- **Verification**: `node --test scripts/lib/independent-verifier/evidence.test.js` passed (7 tests).

## Phase 2: Authoritative Derivation from Receipts
- **Tasks Completed**: 2.1, 2.2, 2.3, 2.4
- **Changes**:
- In `scripts/lib/independent-verifier/index.js` (`verifyCandidate`), implemented authoritative resolution of `role` and `obligation_ids` from Execution Graph and runner receipts.
- Resolved `evidence_requirements_satisfied` strictly from trusted execution receipts (`input.receipts` or `input.runner_receipts`) matching `node_id` or `evidence_id`, setting `[]` when no receipt confirms satisfaction and eliminating blind copying of `node.required_evidence`.
- In `scripts/lib/independent-verifier/obligation-coverage.js`, updated `walkMustObligations` to evaluate receipt satisfaction strictly and emit assessments only when coverage is non-empty.
- Added tests in `scripts/lib/independent-verifier/obligation-coverage.test.js` verifying `UNFULFILLED_MUST` upon receipt absence and elimination of blind copying.
- **Verification**: `node --test scripts/lib/independent-verifier/obligation-coverage.test.js` passed (16 tests).

## Phase 3: Strict Causal Chronology
- **Tasks Completed**: 3.1, 3.2, 3.3
- **Changes**:
- In `scripts/lib/independent-verifier/strategy-policy.js` (`assertRoleOrder`), enforced strict `execution_sequence` validation (`run_id`, strictly monotonic increasing `ordinal`, and valid `previous_evidence_id` chaining) for temporal strategies (`strict-tdd`, `bug`, `refactor`).
- Eliminated fallback to JSON array index comparisons.
- Enforced causal sequence rules: RED < GREEN (and RED < PATCH < GREEN in bug strategy; before < after and `previous_evidence_id` linking in refactor strategy).
- Added test coverage in `scripts/lib/independent-verifier/index.test.js` for reversed ordinals, missing execution sequences, and broken chaining.
- **Verification**: `node --test scripts/lib/independent-verifier/index.test.js` passed (45 tests).

## Phase 4: Full Cryptographic Replay
- **Tasks Completed**: 4.1, 4.2, 4.3
- **Changes**:
- In `scripts/lib/assurance-graph/index.js` (`validateReplayRecords`), enhanced replay verification to recompute `digestRawBytes` and `computeEvidenceId(record, bytes)`, asserting exact equality against persisted digests and IDs.
- Added runtime provenance sufficiency verification via `evaluateProvenanceSufficiency(record, { requireRuntime: true })` failing closed on insufficient provenance with `GRAPH_DIVERGENCE`.
- In `scripts/lib/assurance-graph/index.test.js`, added replay tests for tampered `evidence_id`, modified raw bytes, mismatched candidate subjects, and insufficient provenance.
- **Verification**: `node --test scripts/lib/assurance-graph/index.test.js` passed (21 tests).

## Phase 5: Harness Fixtures Update, E2E Suite & Adversarials
- **Tasks Completed**: 5.1, 5.2, 5.3
- **Changes**:
- Refactored test harness and fixture generators across `scripts/lib/independent-verifier/index.test.js`, `scripts/lib/assurance-graph/index.test.js`, and `scripts/k6b-verifier-assurance-graph-e2e.test.js` to separate physical observations from runner receipts and supply canonical `execution_sequence` objects.
- Created end-to-end integration and adversarial test suite in `test/e2e/k6b-verifier-assurance-graph-e2e.test.js` validating the full verification, projection, and replay lifecycle with caller injection attacks (B1), ungrounded MUST attacks (B2), causality tampering (B3), and replayed evidence tampering (H1).
- Executed full repository test suite `npm test` across all 2790+ tests with 0 failures.
- **Verification**: `npm test` exited 0 (all checks passed).
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"schema_version": 1,
"change": "k6b-trusted-evidence-replay-closure",
"source_fingerprint": "sha256:8288fa2aecb9a4e12a8984ffd80cc7a1100274682bc79817e01b6f07cf2b1aa1",
"spec_writes": [
{
"domain": "independent-verification",
"source_delta": "specs/independent-verification/spec.md",
"target": "openspec/specs/independent-verification/spec.md",
"target_before_sha256": "sha256:9f1a6009b5693407d91da43f8911a2b3bdabeafa6b3a6a339a9b881bb6c75267",
"content_sha256": "sha256:e126b0bb2a160602992fe3b4386d86c4da1c6bdbe1d4dd7fb3ccbe94dc517aa4"
},
{
"domain": "assurance-graph",
"source_delta": "specs/assurance-graph/spec.md",
"target": "openspec/specs/assurance-graph/spec.md",
"target_before_sha256": "sha256:5c34c40d7c4020665701e32ddd0df35a97954d83b6d6f413dcbdb38988a723f8",
"content_sha256": "sha256:698c734aa1e89729b873ef313368e9e59fdf8cdc90aaa0c78fce6f8709600ccc"
}
],
"adr_promotions": [
{
"source": "decisions/adr-001.md",
"target": "docs/adr/adr-20260828-010-untrusted-caller-metadata-rejection.md",
"content_sha256": "sha256:a57128d1a63d501af13514d1c34feb61cbecdc1f2408e8c4ff43f86aefa86c02"
},
{
"source": "decisions/adr-002.md",
"target": "docs/adr/adr-20260828-011-authoritative-receipt-derivation-no-blind-copy.md",
"content_sha256": "sha256:8911c196a45611ddfb295ce1f465ed030a3836c48da35b33acc5e8507de0583c"
},
{
"source": "decisions/adr-003.md",
"target": "docs/adr/adr-20260828-012-strict-causal-chronology-execution-sequence.md",
"content_sha256": "sha256:6254e66c3a9047c4d64e6eaa50576c4e885be38453118c54d04963ae64faeda5"
},
{
"source": "decisions/adr-004.md",
"target": "docs/adr/adr-20260828-013-cryptographic-evidence-replay-integrity.md",
"content_sha256": "sha256:22b0797ed6b038d5c3f2e5f8401265d7ac3b59d85cc24fab17c792e71983f59c"
}
],
"archive_inventory": [
"apply-progress.md",
"archive-report.md",
"decisions/adr-001.md",
"decisions/adr-002.md",
"decisions/adr-003.md",
"decisions/adr-004.md",
"design.md",
"proposal.md",
"specs/assurance-graph/spec.md",
"specs/independent-verification/spec.md",
"state.yaml",
"tasks.md",
"verify-report.md"
],
"accepted_warnings": [],
"rollback": {
"strategy": "staging-rename"
}
}
Loading