Skip to content

signetry-core v0.8.0

Latest

Choose a tag to compare

@github-actions github-actions released this 01 Sep 14:41
· 1 commit to main since this release
ee974f3

Added — the receipt format is now a published, independently testable spec

  • docs/RECEIPT_SPEC.md documents the
    signetry.remediation-receipt v1 format in full: envelope, payload,
    canonicalization, signing, the verification algorithm, the §4.3 invariants, and a
    change contract. RFC 2119 language throughout. A receipt is meant to be verifiable
    by someone who does not have this tool and is reading it years later, so the format
    is an interface and is now written down as one.
  • tests/conformance/ — 17 assertions over 7 committed JSON
    vectors, with published test-key seed strings so an implementation in any language
    can be checked against exactly the same files. Regenerate with
    python tests/conformance/generate_vectors.py; the vectors are committed rather
    than computed at test time so a change to canonicalization or signing shows up as a
    diff.
  • The spec and the suite are Apache-2.0, named as explicit
    exclusions from the BUSL Licensed Work
    in LICENSE. They carry no
    restriction and no Change Date. Writing a competing issuer or an independent
    verifier against the spec is a supported use.
  • check_invariants(receipt) (exported from signetry_core.pipeline) enforces
    RECEIPT_SPEC §4.3: auto_merge must be false, human_review_required must be
    true, plus kind/version/authority_level well-formedness. verify_receipt
    now returns conforming and invariant_violations alongside its cryptographic
    result, because those are different questions — a receipt can be correctly signed
    and still claim something the format forbids.
  • signetry verify now fails on a non-conforming receipt, not just an unverifiable
    one, and says which of the two failed. A validly signed receipt with
    auto_merge: true prints NON-CONFORMING and REJECTED and exits 1; it never
    prints a bare VERIFIED. This is what makes "Signetry never merges on its own
    judgement" a checkable property of every receipt instead of a promise in a README.

Added — policy registry

  • signetry policies and signetry init --policy <id>. Six starter admission
    contracts for common repository shapes: docs-only, dependency-bump,
    python-library, node-service, monorepo-service, ci-workflow-fix. Writing the
    first contract is where adoption stalls, and "which globs should an agent be allowed to
    touch in this stack" is a real security decision most teams defer.
  • The published file is the installed file. init --policy copies the registry bytes
    verbatim — no templating, no merge — so an adopter can diff their
    .signetry/admission.yaml against the registry and get nothing back. Verified in CI.
  • Every entry carries its own evidence. A policy declares example paths it must block and
    must allow in # @policy header comments, and tests/test_policy_registry.py runs each
    claim through the real evaluate_contract. A policy whose documentation does not match
    its behaviour fails CI. The allows direction is the one that catches an over-broad
    forbidden glob quietly making a policy useless.
  • ci-workflow-fix carries a caution that init prints at adoption time, because write
    access to .github/workflows is a privilege-escalation path and a registry that shipped
    it silently would be worse than one that omitted it.
  • New public helper is_policy_placeholder, and signetry_core/policies/ ships in the
    wheel (confirmed against a built artifact, not assumed).

Changed — licence: open core (BUSL-1.1, converting to Apache-2.0)

  • signetry-core is now licensed BUSL-1.1 and converts to
    Apache-2.0 on 2030-08-31, replacing the previous "All Rights Reserved"
    proprietary terms. You may read, run in your own CI, use in production to govern
    repositories you or your organization control, fork, modify, and redistribute it;
    the one carve-out is offering it to third parties as a paid, competing hosted
    service. pyproject.toml's license field is now BUSL-1.1.
  • The integration surface is Apache-2.0: the
    Action,
    plugins,
    pre-commit guard, and
    eval suite.
  • The CLA still applies — open core means code moves across the BUSL/Apache line,
    and the assignment is what allows that relicensing without re-asking every past
    contributor. CLA.md, CONTRIBUTING.md, and CONTRIBUTORS.md were rewritten for
    the open-source posture; README/docs/workflow comments no longer claim the project
    is "not open source" or "All Rights Reserved".
  • No functional or API change. Distribution is unchanged: still installed from source
    by tag, not published to PyPI.
  • The CLA's fallback licence grant is now non-exclusive. It previously granted the
    Owner an exclusive licence where copyright assignment is not permitted by law, which
    would have stripped contributors of the right to use their own contribution — directly
    contradicting the rights the LICENSE grants everyone. The CLA text is now identical
    across all Signetry repositories (bar the engine/integration licence wording) so the
    legal terms cannot drift per-repo again. See CLA.md §2–3.

Fixed

  • A scaffold placeholder was reported as declared provenance. signetry init writes policy_owner: your-team, and policy_status() reported
    declared"Policy declares a human owner and version (change-controlled
    metadata)"
    — for a file no human had read. Every receipt from a freshly initialised
    repo asserted change-control that did not exist.
  • Placeholder provenance is now treated as absent, with its own status value:
    declared / placeholder / incomplete, each carrying a note explaining which.
    Consumers must treat anything other than declared as not change-controlled; the extra
    values exist to say why, which is actionable, and never mean "good enough".
  • Note for consumers matching on this field: a repo that ran signetry init and never
    edited the provenance keys now reports placeholder where it previously reported
    declared. That is the bug being fixed, not a regression.
  • Two repo-root-relative links in docs/RELEASING.md resolved from docs/ and were
    therefore broken.

Added — Python insecure-deserialisation coverage

  • marshal.load(s) and shelve.open now flagged (CWE-502) — both execute arbitrary
    code during decoding, and neither was detected.
  • yaml.unsafe_load flagged, and the Loader is now resolved rather than merely
    counted: the previous check treated any Loader= kwarg as safe, so an explicitly
    unsafe yaml.load(x, Loader=yaml.Loader) passed silently.
  • Gaps identified by @AdvaitVarhade in #87/#91.

Fixed — a positional safe Loader was a false positive

  • yaml.load(x, yaml.SafeLoader) was flagged, because the old check only inspected
    keyword arguments. The Loader is now read from the keyword or the second
    positional argument, and matched on its last path segment so both yaml.SafeLoader
    and a bare imported SafeLoader are recognised.

BUSL-1.1 (Apache-2.0 on 2030-08-31); install from source:

pip install "signetry-core @ git+https://github.com/Signetry/core@v0.8.0"