Skip to content

The signature code behind our provenance promise is never compiled or tested in CI #132

Description

@macanderson

The problem

contextgraph-types puts all of its signature and hashing code behind an
off-by-default Cargo feature named attestation. Nothing in this repository
ever turns that feature on
— not the workspace manifest, not another crate,
not CI, not a script. So the code that backs the protocol's provenance
attestation is compiled by nothing we run, and the tests written to prove it
correct never execute.

This matters because SPEC.md §6.5 hangs four normative rules on it. Rows
F6, F7, F8 and F9 each name contextgraph_types::attest in the
"Verified by" column. Today that column points at code no gate compiles.

What I verified

Searched every Cargo.toml, every workflow, and every script in the repo for
the feature name:

$ rg -n "attestation" --glob 'Cargo.toml' --glob '*.yml' --glob '*.sh' .
./contextgraph-types/Cargo.toml:23:attestation = ["dep:sha2", "dep:ed25519-dalek"]
./contextgraph-types/Cargo.toml:34:# docs.rs renders the attestation surface; ordinary builds still opt in.

The only two hits are the feature's own declaration and a docs.rs comment.
.github/workflows/ci.yml's test job runs cargo test over the whole
workspace and its clippy job runs clippy over the whole workspace with
-D warnings; neither passes --features attestation or --all-features, so
both use the crate's default feature set, which is empty.

Counting the difference, in a worktree at origin/main (280c545):

$ cargo test -p contextgraph-types
test result: ok. 111 passed   # unit tests
test result: ok. 0 passed     # tests/attestation_vectors.rs
test result: ok. 2 passed     # doctests

$ cargo test -p contextgraph-types --features attestation
test result: ok. 132 passed   # unit tests
test result: ok. 5 passed     # tests/attestation_vectors.rs
test result: ok. 5 passed     # doctests

21 unit tests, 5 integration tests and 3 doctests do not run in CI. They are
exactly the ones that prove the security properties the module was written for.
Some of the skipped ones, by name:

  • attest::tests::a_signature_cannot_be_lifted_onto_another_frame
  • attest::tests::an_unknown_algorithm_is_declined_rather_than_failed (this is F8)
  • attest::tests::editing_provenance_after_signing_is_caught_as_a_mismatch
  • attest::tests::the_same_frame_from_another_provider_does_not_verify
  • attest::tests::leaf_and_node_hashing_are_domain_separated
  • attest::tests::a_proof_does_not_validate_a_commitment_that_was_not_in_the_set
  • attest::tests::reordering_the_chain_changes_the_head

The whole tests/attestation_vectors.rs file is gated the same way — in a
default build it reports "0 tests" and passes.

attestation is the only Cargo feature in the entire workspace
(rg -n 'cfg\(feature' --glob '*.rs' . finds seven sites, all for this one
feature), so fixing this one feature fixes the whole class.

What is currently fine, so nobody chases a ghost

I ran the gated code by hand and it is healthy today:

  • cargo test -p contextgraph-types --features attestation — all pass.
  • cargo clippy -p contextgraph-types --all-targets --features attestation -- -D warnings — exits 0, no warnings.

So this is not a report of broken code. It is a report that nothing would
notice if the code broke tomorrow.
A refactor to Provenance, a sha2 or
ed25519-dalek bump, or an edit to the length-prefixed encoding helpers in
contextgraph-types/src/attest.rs would all sail through a green CI run.

Why this is not a duplicate

This issue is different: the tests that already exist are not run by any
gate. Fixing #88, #89 or #90 would not change that.

How to reproduce

From a clean checkout of main:

cargo test -p contextgraph-types                        # 111 + 0 + 2
cargo test -p contextgraph-types --features attestation # 132 + 5 + 5

Or prove the gate is blind directly: introduce any compile error inside a
#[cfg(feature = "attestation")] block in contextgraph-types/src/attest.rs,
then run the workspace-wide test and clippy commands from ci.yml. Both stay
green.

What "done" looks like

  • CI compiles, lints and tests the attestation code on every pull request. The
    simplest shape is to add --all-features legs to the existing test and
    clippy jobs in .github/workflows/ci.yml, or a small dedicated job running
    cargo test -p contextgraph-types --features attestation and
    cargo clippy -p contextgraph-types --all-targets --features attestation -- -D warnings.
  • The default-feature build keeps being checked too. The crate's promise is
    "zero dependencies beyond serde" for a plain consumer, so a run with the
    feature off has to stay in the matrix — otherwise the opposite mistake
    (accidentally making sha2 non-optional) becomes invisible.
  • A witness for the fix: put a deliberate compile error, or flip an assertion,
    inside a #[cfg(feature = "attestation")] block, confirm the new CI leg goes
    red, then revert.
  • SPEC.md rows F6–F9 can then honestly say contextgraph_types::attest
    verifies them, because a gate will be running it.

Constraints a fixer should know

  • contextgraph-types sets publish = true, and its whole selling point is
    the zero-dependency default. Do not "fix" this by making attestation a
    default feature — that pulls sha2 and ed25519-dalek into every consumer.
  • [package.metadata.docs.rs] all-features = true already exists, so docs.rs
    renders the surface. That is documentation, not verification.
  • RUSTFLAGS: -D warnings is set workspace-wide in ci.yml's env: block, so
    a new job inherits it.
  • The publish-dry-run job also uses default features, so it does not cover
    this either.

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageAwaiting the triage agent: sizing + priority (SCR-005)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions