chore: relicense to BUSL-1.1 + publish the receipt spec (Signetry goes open core) - #107
Conversation
…s open core) Relicenses signetry-core from "All Rights Reserved" to BUSL-1.1, converting to Apache-2.0 on 2030-08-31, and publishes the receipt format as an Apache-2.0 specification with a conformance suite that is explicitly excluded from the BUSL Licensed Work. The spec is the substantive half. A receipt has to be verifiable by someone who does not have this tool and is reading it years later, so the format is an interface: docs/RECEIPT_SPEC.md writes it down (RFC 2119, threat model, change contract) and tests/conformance/ tests it with 7 committed language-agnostic JSON vectors and published test-key seeds. Two vectors carry the weight, because a signature-only verifier gets them wrong: resigned-other-key.json (a self-consistent envelope signed with the attacker's own keypair — verification must be against a pinned key, §8.1) and auto-merge-true.json (correctly signed, still non-conforming). So the verifier now checks conformance too: - check_invariants(receipt) returns RECEIPT_SPEC §4.3 violations - verify_receipt returns conforming/invariant_violations alongside the cryptographic result — separate questions, reported separately - signetry verify exits non-zero on a non-conforming receipt and never prints a bare VERIFIED when an invariant is broken The CLA's fallback grant changes from exclusive to non-exclusive: an exclusive fallback could be read as stripping a contributor of the right to use their own code, which was never the intent. .signetry/admission.yaml gains LICENSE* and install.sh so this change is admissible under core's own contract; evaluated empirically, status: pass. pytest: 298 passed (281 existing + 17 conformance).
Signetry Reviewer — 🟣 Escalate to a designated reviewerEscalate to a designated reviewer — this PR touches security-sensitive surface (.github/workflows/cla.yml, .github/workflows/release.yml, .github/workflows/reviewer.yml). No blocking issue was found automatically, but a human owner should sign off. Deterministic gates (the authority)
Findings (5, 0 blocking)
Sensitive surfaceThis PR changes security-sensitive paths that warrant a designated reviewer:
MergeA designated reviewer / code owner should sign off before merge (sensitive surface).
|
§9 said provenance fields are OPTIONAL and "when absent the policy MUST be treated as unsigned". `signetry init` writes `policy_owner: your-team`, which is *present* — so the letter of the spec was satisfied by exactly the value that means nobody has adopted the policy. A verifier testing for a non-empty string would report a policy no human has read as change-controlled. The addition closes that: presence is not a declaration. Scaffold placeholder text MUST be treated as if the field were absent, because converting an unanswered question into a false answer is strictly worse than reporting it unowned. Consumers MAY distinguish placeholder from absent when explaining *why* a policy is unowned, but neither may confer provenance. No `version` bump: per §12 that is reserved for changes which would make a conforming verifier reject a valid receipt, and this changes how a value is interpreted and reported, not whether a receipt is accepted. The spec is being published for the first time here, so this is part of v1 as published rather than an amendment to it. The reference implementation of this requirement is core#108, which stops `policy_status()` returning `declared` for scaffold text. Until that lands, this engine does not yet satisfy its own §9 — merge the two adjacently.
|
Pushed one more commit: §9 as originally written said provenance fields are OPTIONAL and "when absent the policy MUST be treated as unsigned". But Worth catching before publication, since this spec is the artifact people will implement against. Two notes:
|
Relicenses
signetry-corefrom "All Rights Reserved" to BUSL-1.1, and publishesthe receipt format as an Apache-2.0 specification with a conformance suite.
The licence line
action,plugins,precommit,eval,codex,claude-code,cursor,github-app)Licensed WorkUnder BUSL you may read the source, run it in your own CI, use it in production to
govern repositories you or your organization control, fork it, patch it, and publish
those patches. The one carve-out is offering it to third parties as a paid, competing
hosted governance service. Every released version carries its own four-year clock, so
the version you install today is guaranteed Apache-2.0 four years from its publication
whatever happens to this project.
The receipt spec is the substantive half of this PR
A receipt is only worth something if it can be verified by someone who does not have
this tool, does not trust it, and is reading it years later. That makes the format an
interface, so this PR writes it down and tests it as one.
docs/RECEIPT_SPEC.md— the v1 format in full: envelope, payload,canonicalization, signing, the verification algorithm, the §4.3 invariants, a change
contract, and a threat-model table. RFC 2119 throughout.
tests/conformance/— 7 committed JSON vectors, 17 assertions, and publishedtest-key seed strings so an implementation in any language can be checked
against exactly the same files. Vectors are committed rather than computed at test
time: a change to canonicalization or signing then shows up as a reviewable diff
instead of silently redefining what "correct" means.
LICENSE'sLicensed Workparameter now names both as exclusions, licensedunder
LICENSE-Apache-2.0.txtwith no restriction and no Change Date. Writing acompeting issuer or an independent verifier is a supported use, not a tolerated one.
Two of the vectors are the point
A verifier that only checks cryptography passes most of the suite and fails these:
resigned-other-key.json— an envelope signed with the attacker's own keypair,embedded public key swapped to match. Hash matches, signature verifies against
envelope.public_key, nothing malformed. It MUST still fail, because verificationis against a key you obtained some other way (§8.1). An implementation that trusts
the embedded key reports this forgery as valid.
auto-merge-true.json— correctly signed, and non-conforming, becauseauto_merge: falseandhuman_review_required: trueare invariants inside thesigned payload. They can't be flipped or dropped without breaking the signature —
but that only becomes a guarantee if the verifier checks them.
So this PR makes the verifier check them:
check_invariants(receipt)(new, exported fromsignetry_core.pipeline) returnsthe §4.3 violations.
verify_receiptnow returnsconformingandinvariant_violationsalongside itscryptographic result — reported separately, because "is the signature genuine" and
"does this payload claim something the format forbids" are different questions.
signetry verifyexits non-zero on a non-conforming receipt, not only anunverifiable one, and never prints a bare
VERIFIEDwhen an invariant is broken:That is what turns "Signetry never merges on its own judgement" from a sentence in a
README into a checkable property of every receipt.
One substantive legal change, please read
The CLA's fallback grant was exclusive; it is now non-exclusive. §2 assigns
copyright to the Owner, and where law does not permit assignment it falls back to a
licence grant. An exclusive fallback could be read as stripping a contributor of the
right to use their own code — never the intent. §2 now also says so in plain terms.
LICENSING.md(in the umbrella repo) describes the CLA honestly: it is a copyrightassignment, and if that is not acceptable to you, say so on the issue before you start
— a DCO-only path for small fixes is a reasonable thing to ask for.
Contract compliance
coregoverns its own PRs. Verified empirically against this diff, not by inspection:.signetry/admission.yamlneeded two scope additions for this change to be admissibleat all:
LICENSE→LICENSE*(forLICENSE-Apache-2.0.txt) andinstall.sh. Bothare in the diff.
Verification
pytest tests/ -q→ 298 passed (281 existing + 17 new conformance assertions).signetry verifyexercised againstvalid,auto-merge-true, andresigned-other-key: exit 0 / 1 / 1 respectively, with the expected reasons.pre-existing broken links in
docs/RELEASING.md(repo-root-relative paths resolvedfrom
docs/) are fixed here.ruff checkon the new and edited files is clean. The repo's 73 pre-existing lintfindings are untouched — out of scope for a licensing PR.
No functional change to admission
Authority is still earned from evidence,
auto_mergeis still false at every level,and distribution is unchanged (installed from source by tag, not published to PyPI).
The only behavioural change is that
signetry verifynow refuses to bless a receiptthat breaks a format invariant.