From 4409b68eb3616ecaf3df8278c4f87a8a2fe25bcd Mon Sep 17 00:00:00 2001 From: Jakob Heuser Date: Wed, 2 Sep 2026 11:46:35 -0700 Subject: [PATCH] chore(openspec): archive signature-coverage-statement #247 merged the change and never took its tip step, so the statement it exists to make lived in a change directory and not in the spec. Archiving is what promotes a delta into `openspec/specs/`, which means until now `cli-rule-reconciliation` did not carry the coverage rule we declined the generator team's per-file signature proposal on the strength of writing down. All four scenarios survive the promotion, including the two that were nearly dropped in review: parameter-parsing order and whole-string comparison. Nothing checks for this in either direction, which is how #246 came to be outstanding too. A single-PR change has no later slice to carry the archive, so it has to happen on the same PR or immediately after. --- .../.openspec.yaml | 0 .../proposal.md | 0 .../specs/cli-rule-reconciliation/spec.md | 0 .../tasks.md | 2 +- openspec/specs/cli-rule-reconciliation/spec.md | 18 +++++++++++++++++- 5 files changed, 18 insertions(+), 2 deletions(-) rename openspec/changes/{signature-coverage-statement => archive/2026-09-02-signature-coverage-statement}/.openspec.yaml (100%) rename openspec/changes/{signature-coverage-statement => archive/2026-09-02-signature-coverage-statement}/proposal.md (100%) rename openspec/changes/{signature-coverage-statement => archive/2026-09-02-signature-coverage-statement}/specs/cli-rule-reconciliation/spec.md (100%) rename openspec/changes/{signature-coverage-statement => archive/2026-09-02-signature-coverage-statement}/tasks.md (87%) diff --git a/openspec/changes/signature-coverage-statement/.openspec.yaml b/openspec/changes/archive/2026-09-02-signature-coverage-statement/.openspec.yaml similarity index 100% rename from openspec/changes/signature-coverage-statement/.openspec.yaml rename to openspec/changes/archive/2026-09-02-signature-coverage-statement/.openspec.yaml diff --git a/openspec/changes/signature-coverage-statement/proposal.md b/openspec/changes/archive/2026-09-02-signature-coverage-statement/proposal.md similarity index 100% rename from openspec/changes/signature-coverage-statement/proposal.md rename to openspec/changes/archive/2026-09-02-signature-coverage-statement/proposal.md diff --git a/openspec/changes/signature-coverage-statement/specs/cli-rule-reconciliation/spec.md b/openspec/changes/archive/2026-09-02-signature-coverage-statement/specs/cli-rule-reconciliation/spec.md similarity index 100% rename from openspec/changes/signature-coverage-statement/specs/cli-rule-reconciliation/spec.md rename to openspec/changes/archive/2026-09-02-signature-coverage-statement/specs/cli-rule-reconciliation/spec.md diff --git a/openspec/changes/signature-coverage-statement/tasks.md b/openspec/changes/archive/2026-09-02-signature-coverage-statement/tasks.md similarity index 87% rename from openspec/changes/signature-coverage-statement/tasks.md rename to openspec/changes/archive/2026-09-02-signature-coverage-statement/tasks.md index ff1f0433..f8c580d1 100644 --- a/openspec/changes/signature-coverage-statement/tasks.md +++ b/openspec/changes/archive/2026-09-02-signature-coverage-statement/tasks.md @@ -17,4 +17,4 @@ One PR. A single requirement gains two sentences. ## 3. Close out -- [ ] 3.1 Archive the change +- [x] 3.1 Archive the change. Archiving is what promotes the delta into the standing spec, so until this ran the coverage statement lived only in the change directory and `openspec/specs/cli-rule-reconciliation/spec.md` did not carry it diff --git a/openspec/specs/cli-rule-reconciliation/spec.md b/openspec/specs/cli-rule-reconciliation/spec.md index e6e7fb6f..d12c48d9 100644 --- a/openspec/specs/cli-rule-reconciliation/spec.md +++ b/openspec/specs/cli-rule-reconciliation/spec.md @@ -15,10 +15,21 @@ before the **first** `;` is the algoVersion and SHALL be read up to that one del detect the version (and therefore the normalization procedure and hash algorithm) before any `key=value` parameters are parsed. Signatures SHALL be compared as whole strings. +The algoVersion SHALL also determine **what the signature covers**. A signature at +algoVersion `1` covers exactly one file: the engine's `ruleFile` from the rule layout +table, which is `check.ts` for the runtime engine. An engine that requires more than one +file to be signed SHALL do so under a later algoVersion. + +**Rationale.** Coverage is a property of the signature scheme, not of the delivery that +carries a signature. Stating it on the version keeps a payload from having to say which +of its files is the signed one, and gives a future multi-file scheme a mechanism that +already exists rather than a new payload shape. Leaving it unstated is what let both +teams hold the same binding as a private assumption. + #### Scenario: Envelope is emitted for algoVersion 1 - **WHEN** the CLI computes a signature for a rule file's bytes using algoVersion 1 -- **THEN** the result SHALL be a string `1;h=sha-256;d=` with `` lowercase +- **THEN** the signature SHALL be the string `1;h=sha-256;d=` for that file's normalized bytes #### Scenario: Version is read before parameters @@ -31,6 +42,11 @@ any `key=value` parameters are parsed. Signatures SHALL be compared as whole str - **WHEN** the CLI compares two signatures for equality - **THEN** it SHALL compare the full envelope strings, not the bare digests +#### Scenario: A v1 signature covers the engine's rule file + +- **WHEN** a runtime rule carries a signature at algoVersion 1 +- **THEN** that signature SHALL be over `check.ts` and over no other file in the rule directory + ### Requirement: Signature normalization procedure (algoVersion 1) The CLI SHALL compute an algoVersion-1 digest as `SHA-256( normalize(fileText) )`,