Ecosystem metrics
- Commits
- 977
- up 19.6%
- Releases
- 10
- up 42.9%
- Contributors
- 59
- up 25.5%
- Merges
- 16
- down 30.4%
Activity Overview
Commits and releases over time
- Commits
- Releases
- Authors
Repository Explorer
No repositories match that filter.
10635 commits in all time
May 15, 2026 15:38 – Aug 13, 2026 15:38 UTC
Notes added by 'git notes add'
7080660f
notes/semantic-release-v1.0.0-canary.10
1/1 ++ 0 --
chore(release): [skip ci] Liquid Client
# [1.0.0-canary.10](https://github.com/algorandfoundation/liquid-auth-js/compare/v1.0.0-canary.9...v1.0.0-canary.10) (2026-08-13) ### Bug Fixes * security patches ([4cfb56f](https://github.com/algorandfoundation/liquid-auth-js/commit/4cfb56f1969d6efabb9fe99f41eb0399e093196c))
763efb0d
main
3/10 ++ 3 --
docs: add AppSizeSponsor app field for AVM v13
c3713684
feat/allow-epp-schema-change
2/15 ++ 14 --
Merge 06bd3b8216abfccdbde129d2235a148d9430f673 into d2de6fadecafa220eaa47dbd00ea1221fc6af26f
b87b2720
pull/165/merge
83/12,754 ++ 12,224 --
docs: add size-changing example to application update transaction
c5049b58
feat/allow-epp-schema-change
1/28 ++ 1 --
Refuse to sign a release whose tag and version disagree (#25)
sdk/pyproject.toml declared version = "0.1.0" while the repo carries tags v0.2.0 and v0.2.1 - and both of those tags ALSO carry "0.1.0". Two independent claims about which release this is, with nothing binding them. The first real run of this workflow would therefore have built trelyan_pq-0.1.0-*.whl, then SLSA-attested and Sigstore-signed those exact bytes under a v0.2.2 tag. The attestation would have been cryptographically valid and described the wrong release - which is worse than an unsigned artifact, because it carries an assurance nobody can act on. Nothing was published: release.yml was first committed 2026-06-18, AFTER both tags (it is absent at v0.2.0 and v0.2.1), it has never run, and both GitHub Releases have zero assets. The mislabelling was latent. Bumps the declared version to 0.2.2 - verified by building: the wheel is now trelyan_pq-0.2.2-py3-none-any.whl, previously it would have been 0.1.0 - and adds a gate in the build job, before anything is compiled or signed, that fails when the tag does not match. Simulated all three ways: v0.2.2 allowed, v0.2.1 and v9.9.9 blocked. Security impact: no crypto or protocol change. Closes a path where a signed, SLSA-attested artifact could name a different release than its tag.
c1e451f3
main
2/23 ++ 1 --
docs: note extra program pages can change after creation
75c86b2a
feat/allow-epp-schema-change
1/1 ++ 1 --
Merge 9a43d0904c72542968a74bbba96f3ef3e297fbd8 into 100dc5fa507537fffa496e22706c3a6c1e9bca2a
f591b8cd
pull/599/merge
2/607 ++ 415 --
chore(deps): bump the all group across 1 directory with 8 updates
Bumps the all group with 8 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@algorandfoundation/tealscript](https://github.com/algorandfoundation/TEALScript) | `0.106.3` | `0.107.2` | | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.64.0` | `8.66.0` | | [prettier](https://github.com/prettier/prettier) | `3.9.5` | `3.9.6` | | [rolldown](https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown) | `1.2.0` | `1.2.3` | | [rolldown-plugin-dts](https://github.com/sxzz/rolldown-plugin-dts) | `0.23.2` | `0.28.0` | | [semantic-release](https://github.com/semantic-release/semantic-release) | `25.0.7` | `25.0.9` | | [tsx](https://github.com/privatenumber/tsx) | `4.23.1` | `4.23.9` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.64.0` | `8.66.0` | Updates `@algorandfoundation/tealscript` from 0.106.3 to 0.107.2 - [Release notes](https://github.com/algorandfoundation/TEALScript/releases) - [Commits](https://github.com/algorandfoundation/TEALScript/compare/0.106.3...0.107.2) Updates `@typescript-eslint/eslint-plugin` from 8.64.0 to 8.66.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.66.0/packages/eslint-plugin) Updates `prettier` from 3.9.5 to 3.9.6 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.9.5...3.9.6) Updates `rolldown` from 1.2.0 to 1.2.3 - [Release notes](https://github.com/rolldown/rolldown/releases) - [Changelog](https://github.com/rolldown/rolldown/blob/main/CHANGELOG.md) - [Commits](https://github.com/rolldown/rolldown/commits/v1.2.3/packages/rolldown) Updates `rolldown-plugin-dts` from 0.23.2 to 0.28.0 - [Release notes](https://github.com/sxzz/rolldown-plugin-dts/releases) - [Commits](https://github.com/sxzz/rolldown-plugin-dts/compare/v0.23.2...v0.28.0) Updates `semantic-release` from 25.0.7 to 25.0.9 - [Release notes](https://github.com/semantic-release/semantic-release/releases) - [Commits](https://github.com/semantic-release/semantic-release/compare/v25.0.7...v25.0.9) Updates `tsx` from 4.23.1 to 4.23.9 - [Release notes](https://github.com/privatenumber/tsx/releases) - [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs) - [Commits](https://github.com/privatenumber/tsx/compare/v4.23.1...v4.23.9) Updates `typescript-eslint` from 8.64.0 to 8.66.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.66.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: "@algorandfoundation/tealscript" dependency-version: 0.107.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: all - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.66.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: all - dependency-name: prettier dependency-version: 3.9.6 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: all - dependency-name: rolldown dependency-version: 1.2.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: all - dependency-name: rolldown-plugin-dts dependency-version: 0.28.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: all - dependency-name: semantic-release dependency-version: 25.0.9 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: all - dependency-name: tsx dependency-version: 4.23.9 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: all - dependency-name: typescript-eslint dependency-version: 8.66.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: all ... Signed-off-by: dependabot[bot] <support@github.com>
9a43d090
dependabot/npm_and_yarn/all-13923b79ef
2/607 ++ 415 --
Merge 6e76dd8091893889075c6e47de09ec72e6c3fb2c into 3ff4f886d794f08c1c3975b1bc5f828673d26e61
4039d4d3
pull/25/merge
2/23 ++ 1 --
Refuse to sign a release whose tag and version disagree
sdk/pyproject.toml declared version = "0.1.0" while the repo carries tags v0.2.0 and v0.2.1 - and both of those tags ALSO carry "0.1.0". Two independent claims about which release this is, with nothing binding them. The first real run of this workflow would therefore have built trelyan_pq-0.1.0-*.whl, then SLSA-attested and Sigstore-signed those exact bytes under a v0.2.2 tag. The attestation would have been cryptographically valid and described the wrong release - which is worse than an unsigned artifact, because it carries an assurance nobody can act on. Nothing was published: release.yml was first committed 2026-06-18, AFTER both tags (it is absent at v0.2.0 and v0.2.1), it has never run, and both GitHub Releases have zero assets. The mislabelling was latent. Bumps the declared version to 0.2.2 - verified by building: the wheel is now trelyan_pq-0.2.2-py3-none-any.whl, previously it would have been 0.1.0 - and adds a gate in the build job, before anything is compiled or signed, that fails when the tag does not match. Simulated all three ways: v0.2.2 allowed, v0.2.1 and v9.9.9 blocked. Security impact: no crypto or protocol change. Closes a path where a signed, SLSA-attested artifact could name a different release than its tag.
6e76dd80
ci/release-tag-must-match-version
2/23 ++ 1 --
docs(PINNED_BUILD): the pin is the network's release, not staleness (#7)
Corrects the note added earlier on this branch, which was misleading in three ways. All three were found by follow-up verification and adversarial review after that note was written. 1. It said the pin is "several commits behind main" without the decisive fact: go-algorand's go.mod requires github.com/algorand/falcon v0.1.0, and that tag dereferences to exactly ce15e75b. It is the repo's ONLY tag. The pin is alignment with the code defining on-chain falcon_verify behaviour - which is the point for a signer whose output must be accepted by that verifier. main (956d9bc0) is 7 ahead / 0 behind, and UNRELEASED. 2. It called the PR #16 change "a malleability gap". Wrong term. Signature malleability means distinct valid signatures for one (key, message) pair; that does not occur on either build. It is non-canonical input acceptance in a parser. The original wording would have pointed an auditor at the wrong invariant. 3. It warned that TRELYAN's off-chain accept/reject "can diverge from what the chain accepts". Misleading: falcon_det1024_convert_compressed_to_ct is not bound by this SDK at all - trelyan_pq.falcon binds only shake256_init_prng_from_system, keygen, sign_compressed and verify_compressed. The affected function is unreachable from TRELYAN. It IS reachable in go-algorand via GetFixedLengthHashableRepresentation -> ConvertToCT, making it an upstream report rather than a local divergence. Also records that bumping was tested, not assumed: both trees built with FALCON_FPEMU=1 and compared over 120 signatures (12 keypairs x 10 message shapes) plus the committed KAT - byte-identical throughout, each build accepting the other's output. A bump would be safe but would make this repo stricter than the deployed verifier for no reachable benefit. Adds the more precise description of the underflow: sig_compressed_len - 2 wraps to SIZE_MAX on a 1-byte input, so the decoder receives a pointer past the buffer with a claimed length of 2^64-1. Docs only. Pinned commit and both digests unchanged. Co-authored-by: Brandon Sellam <brandon.sellam@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
3ff4f886
main
1/29 ++ 10 --
docs(PINNED_BUILD): the pin is the network's release, not staleness
Corrects the note added earlier on this branch, which was misleading in three ways. All three were found by follow-up verification and adversarial review after that note was written. 1. It said the pin is "several commits behind main" without the decisive fact: go-algorand's go.mod requires github.com/algorand/falcon v0.1.0, and that tag dereferences to exactly ce15e75b. It is the repo's ONLY tag. The pin is alignment with the code defining on-chain falcon_verify behaviour - which is the point for a signer whose output must be accepted by that verifier. main (956d9bc0) is 7 ahead / 0 behind, and UNRELEASED. 2. It called the PR #16 change "a malleability gap". Wrong term. Signature malleability means distinct valid signatures for one (key, message) pair; that does not occur on either build. It is non-canonical input acceptance in a parser. The original wording would have pointed an auditor at the wrong invariant. 3. It warned that TRELYAN's off-chain accept/reject "can diverge from what the chain accepts". Misleading: falcon_det1024_convert_compressed_to_ct is not bound by this SDK at all - trelyan_pq.falcon binds only shake256_init_prng_from_system, keygen, sign_compressed and verify_compressed. The affected function is unreachable from TRELYAN. It IS reachable in go-algorand via GetFixedLengthHashableRepresentation -> ConvertToCT, making it an upstream report rather than a local divergence. Also records that bumping was tested, not assumed: both trees built with FALCON_FPEMU=1 and compared over 120 signatures (12 keypairs x 10 message shapes) plus the committed KAT - byte-identical throughout, each build accepting the other's output. A bump would be safe but would make this repo stricter than the deployed verifier for no reachable benefit. Adds the more precise description of the underflow: sig_compressed_len - 2 wraps to SIZE_MAX on a 1-byte input, so the decoder receives a pointer past the buffer with a claimed length of 2^64-1. Docs only. Pinned commit and both digests unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
34b480da
pull/7/head
1/29 ++ 10 --
Gate the release on the tests passing (#20)
release.yml had no test job. The graph was
build -> provenance -> cosign-sign -> pypi-publish
with `build`'s only substantive step being `python -m build`, and no occurrence
of `pytest` or verify_pinned_digest anywhere in the file. A version tag
therefore produced a signed, SLSA-attested, Rekor-logged artifact without one
test having run.
The attestations were never WRONG about this. SLSA provenance attests to build
provenance and does not claim tests passed, and RELEASES.md's verify commands
say exactly that. The gap is that "signed, attested, transparency-logged" reads
as "vouched for" to essentially every downstream consumer, and here it vouched
only for where the bytes came from.
Adds a `test` job and makes `build` need it, so nothing is built, signed or
attested until the suite is green.
Cross-workflow `needs:` does not exist in GitHub Actions, so ci.yml cannot gate
this workflow and the check has to be duplicated here. That is why this is a
small fast job rather than the full 3-OS matrix: a release gate has to be cheap
enough that nobody is tempted to route around it.
The step also asserts 15+ tests actually EXECUTED (17 locally). pytest exits 5
on "no tests collected", but a suite that silently shrank still exits 0 - and a
release gate that passes because nothing ran is worse than no gate at all,
because it ships a signature saying otherwise. Same reasoning as the guards in
the CI workflow, applied to the path that publishes.
Found by an adversarial claim-vs-enforcement sweep (TCE-23).
Co-authored-by: Brandon Sellam <brandon.sellam@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
8082e6b4
main
1/52 ++ 0 --
Delete an inert workflow copy and fix two dangling audit references (#19)
AUDIT_READINESS.md:172 points an auditor at `sdk/ci/ci.yml` as the repo's CI definition. That file does not exist: git ls-files sdk/ci/ -> release.yml, verify_pinned_digest.py scripts/verify_all.sh:10 makes the same reference, claiming to "mirror the sdk/ci/ci.yml signature-kat job recipe EXACTLY". Both now point at .github/workflows/ci.yml, which is the file that actually runs. An auditor following the readiness doc hits a 404 on its first CI citation. sdk/ci/release.yml is deleted. GitHub Actions only executes YAML under .github/workflows/, so it never ran, and it had drifted into being the WORSE copy: ad20b42 SHA-pinned every action in the live workflow while this one kept floating tags - actions/checkout@v5 vs @fbc6f39... # v5.0.1 actions/setup-python@v6 vs @ece7cb0... # v6.0.0 actions/upload-artifact@v4 vs @ea165f8... # v4.6.2 actions/download-artifact@v4 vs @d3f86a1... # v4.3.0 sigstore/cosign-installer@v4.1.0 vs @ba7bc0a... # v4.1.0 softprops/action-gh-release@v2.6.2 vs @3bb1273... # v2.6.2 19 differing lines, all pins. An inert file is harmless right until someone copies it back - and this is the release workflow, the one that signs artifacts and publishes them. Also gitignores .venv-contracts/, the local virtualenv the contract suite needs. It was untracked and unignored, which is how a `git add -A` in this directory sweeps 1757 site-packages files into a commit. Nothing references the deleted file; verify_all.sh still parses (bash -n). Found by an adversarial claim-vs-enforcement sweep (TCE-15). Co-authored-by: Brandon Sellam <brandon.sellam@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
d52b0570
main
4/5 ++ 182 --
Run the contract suite in CI (#18)
The contract suite has never run in CI. It is the only thing that exercises
inscription.py at all - falcon_verify on-chain, the C1 ownership conjunction,
write-once, cross-cell replay, the update_owner guards - and the only record
that it passed was a hand-run note in LOCALNET_VALIDATION_2026-06-01.md, dated
two weeks BEFORE 2ec798e changed the contract.
So the flagship's on-chain logic has had no automated coverage of any kind,
and the drift in 2ec798e went unnoticed partly for that reason.
It was never wired up because it needs three things at once:
1. a LocalNet (algod on :4001) - without it: 22x urllib.error.URLError
2. the Falcon C library - without it: 19x "Could not load Falcon
shared library at './libfalcondet1024.so'"
3. the committed typed client - already in the repo
Both failure modes above were reproduced locally before writing this job, so
the recipe is derived from what actually breaks, not from guesswork. The
pinned compile venv (puyapy) is deliberately NOT needed: these tests deploy
the committed client, they do not rebuild the contract.
The library is built from the pinned tarball behind the same digest + FPEMU
gate signature-kat uses. These tests produce REAL det1024 signatures that the
AVM's falcon_verify opcode must accept, so the signer has to be the pinned
build for exactly the reason that job states.
Two guards, both from failures seen elsewhere in this workflow:
* LocalNet health is polled before the suite runs. A half-started sandbox
fails with connection errors that read like test failures, destroying the
signal this job exists to provide.
* The run asserts 20+ tests actually EXECUTED. pytest exits 5 on "no tests
collected", but a suite that silently shrank to a handful still exits 0 -
and "green meaning nothing ran" is the precise defect this job is here to
end.
Co-authored-by: Brandon Sellam <brandon.sellam@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
e4675c93
main
1/80 ++ 0 --
Run the contract suite in CI
The contract suite has never run in CI. It is the only thing that exercises
inscription.py at all - falcon_verify on-chain, the C1 ownership conjunction,
write-once, cross-cell replay, the update_owner guards - and the only record
that it passed was a hand-run note in LOCALNET_VALIDATION_2026-06-01.md, dated
two weeks BEFORE 2ec798e changed the contract.
So the flagship's on-chain logic has had no automated coverage of any kind,
and the drift in 2ec798e went unnoticed partly for that reason.
It was never wired up because it needs three things at once:
1. a LocalNet (algod on :4001) - without it: 22x urllib.error.URLError
2. the Falcon C library - without it: 19x "Could not load Falcon
shared library at './libfalcondet1024.so'"
3. the committed typed client - already in the repo
Both failure modes above were reproduced locally before writing this job, so
the recipe is derived from what actually breaks, not from guesswork. The
pinned compile venv (puyapy) is deliberately NOT needed: these tests deploy
the committed client, they do not rebuild the contract.
The library is built from the pinned tarball behind the same digest + FPEMU
gate signature-kat uses. These tests produce REAL det1024 signatures that the
AVM's falcon_verify opcode must accept, so the signer has to be the pinned
build for exactly the reason that job states.
Two guards, both from failures seen elsewhere in this workflow:
* LocalNet health is polled before the suite runs. A half-started sandbox
fails with connection errors that read like test failures, destroying the
signal this job exists to provide.
* The run asserts 20+ tests actually EXECUTED. pytest exits 5 on "no tests
collected", but a suite that silently shrank to a handful still exits 0 -
and "green meaning nothing ran" is the precise defect this job is here to
end.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
c52fe337
pull/18/head
1/80 ++ 0 --
Say that the algo-pqc-kit KAT has produced zero comparisons (#24)
The module docstring reads as evidence: "ANY divergence in the Gaussian
sampler, rounding, or compressed encoding surfaces here as a byte mismatch.
That divergence-detection is the entire point of this KAT." Nothing in it has
ever run.
Two independent reasons, and the second is the one that gets missed:
1. Nothing installs algo-pqc-kit. pyproject declares only `algorand` and
`dev`; both CI test jobs run pip install -e ".[dev]". All three
differential tests carry @requires_apk and skip on every run.
2. Installing the package would not be enough. _ApkAdapter is wired to a
GUESSED upstream API shape and degrades to NotImplementedError -> skip if
that guess is wrong. The upstream API still has to be confirmed.
The fixture IS populated, so this is a working test wired to a dependency no
environment provides - which is why it reads green.
Adds TRELYAN_REQUIRE_INTEROP=1, mirroring TRELYAN_REQUIRE_KAT in
test_signature_kat.py, where a skip fails the job. CI does NOT set it, because
the dependency genuinely is not available. It exists so the inertness is
testable on demand rather than taken on trust, and so that pinning upstream
later is one environment variable away from being enforced.
No behaviour change: unset, the new test skips like the other three.
Co-authored-by: Brandon Sellam <brandon.sellam@gmail.com>
7d513e69
main
1/59 ++ 0 --
Stop passing a signature where the SDK expects a private key (#23)
interop_algo_pqc_kit.py called
c.inscribe(cell, artifact_hash, sig, b"ipfs://demo")
but inscribe()'s third positional parameter is a PRIVATE KEY: the client
re-derives M and signs internally (inscription.py:135-136). The signature
reached falcon.py:192 and raised "privkey must be 2305 bytes, got ...".
This happened in BOTH branches, so the flagship's documented interop example
had never run as shipped. Nothing caught it because no test in this repo
touches examples/ at all -- and the file's own "NOT yet executed end-to-end"
disclaimer was doing the job a test should have been doing.
The INTEROP_RECONCILED=True branch cannot be written against today's SDK
regardless of how the encoding question lands: submitting an externally
produced signature needs an inscribe_presigned() entry point, and none
exists. That branch now stops with an explicit error naming the missing API
instead of shipping code that cannot run.
Adds tests/test_examples_call_sites.py, which binds every example's SDK call
sites to the real inspect.signature and checks provenance: a value produced
by .sign() must never land in a `privkey` parameter. Arity alone cannot see
this -- a signature and a private key are both bytes and both fit the slot.
Security impact: none at runtime. Fail-closed, no key disclosure, nothing
deployed. The defect is that an audit-bound repo shipped an examples/ file
that could not execute, and had no mechanism that would ever say so.
Co-authored-by: Brandon Sellam <brandon.sellam@gmail.com>
c20ba21a
main
2/238 ++ 22 --
One build_message per side, and a test that compares them (#22)
There were FOUR copies of the signed-message construction and no test
compared any two:
sdk/src/trelyan_pq/message.py the SDK's, published to PyPI
contracts/falcon_det1024.py the contracts-side signer
contracts/deploy_testnet.py a local copy - deleted here
contracts/test_inscription.py a local copy - deleted here
The deleted copies were not harmless duplication. deploy_testnet.py's omitted
the length checks entirely:
return DOMAIN_TAG + app_id.to_bytes(8,"big") + cell_id.to_bytes(8,"big") \
+ artifact_hash + genesis
so a 31- or 33-byte artifact hash produced a 101- or 103-byte M and was signed
without complaint - in the script that signs REAL TestNet inscriptions. The
ABI's StaticArray[Byte, 32] stops that reaching the chain, which is why this is
low rather than high, but "a later layer catches it" is a mitigation, not a
reason for the earlier layer to be wrong.
Both files already imported falcon_det1024, so removing the local definitions
is a deletion, not a refactor.
Two implementations remain on purpose: contracts/ has to work without the SDK
installed. Two is a decision; four was an accident. What makes two safe is that
something compares them, which is what
sdk/tests/test_build_message_differential.py now does:
- both implementations agree across six inputs, including uint64 max and the
live TestNet vector
- both reproduce the exact M the chain accepted for cell 763809098, read from
the live inscription record - an anchor that is neither implementation's
opinion but what TestNet actually took
- both reject wrong-length artifact and genesis hashes, which is the
divergence that actually existed
- the two names resolve to different function objects, so the comparison
cannot become a function compared with itself
Mutation-proved: flipping the contracts-side cell_id to little-endian turns 5
of the 15 tests red. Restored: 15 passed.
Fixes AUDIT_READINESS.md S2.3, which cited three tests as covering this; each
exercised one implementation and none compared two.
Contract suite still 22 passed on LocalNet.
Note for reviewers: the SDK suite reports 3 unrelated errors on this machine -
PermissionError on pytest's tmp_path directory, in test_seal.py and
test_isolated_signer.py, both last modified in 2ec798e and untouched here. It
is local file-locking, not this change; CI runs on Linux.
Found by an independent re-check of the risk register (TCE-26).
Co-authored-by: Brandon Sellam <brandon.sellam@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
751398e3
main
3/141 ++ 12 --
Test the freeze and manager guards at register_cell (#21)
register_cell asserts three things about a Cell ASA:
:205 clawback == zero_address
:206 freeze == zero_address
:207 manager == zero_address
Only :205 had a test. test_register_rejects_clawback_cell's docstring claims
to cover "clawback (or freeze/manager)" but its fixture sets only `clawback`,
and the asserts are sequential, so it trips :205 and the other two are never
evaluated. The words freeze and manager appear in this file only in prose.
Deleting :206 and :207 turns nothing red.
Not cosmetic. A live freeze address can freeze the holder AFTER registration,
and a live manager can RE-ADD clawback and freeze afterwards - which restores
both AssetHoldingGet timing vectors the hardening closed at the source. The
manager guard is the load-bearing one: it is what makes the cell's config
immutable rather than merely clean at registration time.
Adds one fixture per guard and asserts WHICH guard fired, so a future
reordering of the three asserts cannot silently leave one uncovered again.
VERIFICATION IS INCOMPLETE, and deliberately not overstated: unlike the other
contract test added in this series, these two are NOT mutation-proved. Docker
Desktop on this machine wedged part-way through (orphaned runtime sockets that
cannot be deleted without a reboot - my own hard-kill of the process is the
likely cause), so LocalNet is unavailable and the suite cannot run here.
What HAS been checked:
- both tests collect (24 collected, up from 22)
- the asserted strings match the contract's messages exactly, one occurrence
each in inscription.py and in the test
- the fixtures mirror test_register_rejects_clawback_cell, which passes
What has NOT been checked: that they fail when :206/:207 are deleted. The CI
job in the contract-suite PR runs LocalNet successfully on a GitHub runner, so
that is where this should be confirmed.
Found by an adversarial claim-vs-enforcement sweep (TCE-19).
Co-authored-by: Brandon Sellam <brandon.sellam@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
f08d0926
main
1/46 ++ 0 --