Release note · August 3, 2026

A package signature can change scope without changing a cell

By SybilGambleyyu · FormulaFence 0.223.0 and WCAB 0.41.0

A workbook can keep every worksheet cell and ordinary formula stable while the declared scope of a package signature changes. That is material review evidence: signature metadata is part of a workbook's integrity and provenance surface. But it is also an area where reports must be precise. A changed declaration is not proof that a signature is valid, that a certificate is trusted, or that a package consumer will accept it.

The Open Packaging Conventions specification defines package relationships and signature parts. The W3C XML Signature specification distinguishes the references in SignedInfo from references collected in a Manifest. Those distinctions matter: a SignedInfo reference can identify a local signature object, while an Object/Manifest/Reference can declare a package part. A tool should not mistake the former for the latter.

Review the declared scope, not an invented trust result

FormulaFence 0.223.0 reads the bounded OPC signature structure and reports safe aggregate counts: Manifest references, direct part references, relationship selectors, and direct workbook, worksheet, VBA-project, and external-data-connection categories. A selector is treated as declared package scope only when its OPC Relationships Transform is immediately followed by XML C14N, with or without comments. When the bounded coverage changes, it emits high-severity FF050 evidence with:

package_signature_material_changed: true
package_signature_manifest_coverage_changed: true

The report intentionally does not serialize a Manifest URI, selector, digest, signature value, certificate, identity, or trust assertion. Malformed or unsafe declarations are handled conservatively. FormulaFence does not calculate a digest, validate a signature or transform, build a certificate chain, check revocation, apply policy, or predict a consumer decision.

A deterministic fixture that separates the two reference scopes

Workbook Change Assurance Benchmark (WCAB) 0.38.0 introduced a compact direct-part pair for this boundary. The package keeps one root-to-origin relationship, one origin-to-signature relationship, required content types, and a SignedInfo reference to a local #idWCABPackageObject fixed. Its ordinary Controls!B10=12 value and Controls!D10=B10*C10 formula also remain fixed.

The only changed archive member is _xmlsignatures/sig1.xml. Inside that part, one Object/Manifest/Reference/@URI moves from the direct workbook part to the first worksheet part. WCAB's raw validator establishes that package shape and compares the signature XML after erasing only that URI. Its digest and signature values are deliberately synthetic: this is a declaration-scope fixture, not a sample valid signature.

Equal counts can still conceal a material retarget

WCAB 0.39.0 adds the harder companion case. Its Manifest URI remains the root relationships part; it contains one OPC Relationships Transform immediately followed by XML C14N. Only one RelationshipReference/@SourceId moves: from the root office-document relationship to the root signature-origin relationship. The graph, cells, formulas, transform sequence, and every archive member except _xmlsignatures/sig1.xml remain fixed.

Every redacted aggregate stays equal before and after: one Manifest reference, one relationship selector, zero direct-part references, one origin, and one XML signature. FormulaFence therefore must surface the private material difference through package_signature_manifest_coverage_changed: true, not through a changed count or exposed selector. A selected relationship entry is not proof that its target part was signed. Neither WCAB nor FormulaFence executes the transform or makes a digest, signature, certificate, trust, or consumer-decision claim.

A resolved comment can move without a cell change

Modern threaded comments are likewise worksheet-associated package state, rather than ordinary cell values. WCAB 0.40.0 adds a deterministic pair with one top-level synthetic thread whose threadedComment/@done value moves from 0 to 1. The only changed archive member is xl/threadedComments/threadedComment1.xml; comment text, person data, timestamps, cell binding, content types, relationship graph, ordinary values, formulas, and calculation properties stay fixed.

FormulaFence reports the transition only as high-severity threaded_comment_controls_changed/FF045 evidence with a redacted resolved_comment_count transition from 0 to 1. WCAB's raw validator retains the precise synthetic package boundary without placing text, person or comment identifiers, timestamps, cell references, or relationship IDs in its public fact. A stored resolved flag does not prove that someone reviewed or approved work, received a notification, held an identity, or completed an authorization or workflow step.

A revision log can change without a cell change

Legacy shared-workbook revision history is another package surface that can retain a material change after ordinary cells stay stable. Microsoft’s Headers class reference describes revision history as persisted through headers and revision-log parts. WCAB 0.41.0 adds a deterministic pair with one workbook revision-header part, one relationship-backed revision-log part, three revision records, and matching enabled shared-workbook tracking, retention, and history-protection controls.

The only changed archive member is xl/revisions/revisionLog1.xml. Inside it, one synthetic historic old value changes while the workbook-to-header-to-log graph, content types, control profile, revision-record shape, ordinary values, formulas, and calculation properties remain fixed. The raw validator uses that narrow synthetic boundary privately; its public fact carries only the safe equal-count profile, not historic values, cell locations, author data, timestamps, GUIDs, or relationship IDs.

FormulaFence exposes the difference only as high-severity shared_workbook_revisions_changed/FF062 evidence with equal safe counts and revision_log_material_changed: true. A stored revision entry is not proof of provenance, an author’s identity, conflict resolution, review, approval, authorization, workflow completion, or what an Office client will do.

Two layers, each with a narrower job

The optional WCAB adapter accepts the direct-part fact only when FormulaFence emits the exact high-severity digital_signature_controls_changed record and matching FF050, with one origin, one XML signature, one Manifest direct-part reference, no certificates/VBA signatures/selectors, and an aggregate transition from one workbook part to one worksheet part. For the selector case, it instead requires equal aggregate profiles plus the separate coverage-change flag and FF050. The threaded-comment case requires its exact safe aggregate profile, an explicit definition-material signal, and high FF045 evidence. The revision-log case requires the exact redacted one-header, one-log profile, the material-change signal, and high FF062 evidence. WCAB independently checks its public synthetic URI or source-ID transition and the one-member package boundary that FormulaFence deliberately withholds.

That division lets a production CI artifact describe a meaningful scope transition without becoming a ledger of signature material or a false trust verdict. It also gives a benchmark a concrete way to reject a tool that notices only that a signature part exists while missing what its Manifest now declares.

Evidence before the claim

FormulaFence 0.223.0 passed 1,596 tests, lint, package checks, fresh-install verification, and hosted CI. WCAB 0.41.0 contains 58 cases and 60 observable facts; its 273 tests, fixture validation, fresh wheel/source installs, byte-for-byte manifest reproduction, and hosted Python 3.10/3.13 CI passed. The WCAB dataset mirror is available on Hugging Face.

Use the releases

python -m pip install https://github.com/SybilGambleyyu/formulafence/releases/download/v0.223.0/formulafence-0.223.0-py3-none-any.whl
formulafence diff approved.xlsx candidate.xlsx

git clone https://github.com/SybilGambleyyu/workbook-change-benchmark.git
cd workbook-change-benchmark
python -m venv .venv
.venv/bin/python -m pip install -e '.[dev]'
wcab validate --fixtures fixtures
wcab formulafence-observations --fixtures fixtures --executable formulafence --output /tmp/formulafence-observations.json
wcab score --fixtures fixtures --observations /tmp/formulafence-observations.json

Both projects are MIT-licensed. Read the FormulaFence release, the WCAB release, or the full benchmark note for the underlying contracts and validation records.