Ecosystem metrics
- New Repos
- 20
- New
- Commits
- 822
- down 22.7%
- Releases
- 4
- down 50.0%
- Contributors
- 42
- down 22.2%
- Merges
- 37
- down 2.6%
Activity Overview
Commits and releases over time
- Commits
- Releases
- Authors
Repository Explorer
No repositories match that filter.
6905 commits in all time
Jun 03, 2026 13:28 – Sep 01, 2026 13:28 UTC
Merge c75a9ca8cd2c3e892b3d0f4ce25937e4a7949464 into 65896fdbf1e91d62413a51f403fa2454a87a67a2
4c298f43
pull/330/merge
4/12 ++ 17 --
docs: fix links to archived pre-reorg pages
c75a9ca8
fix/docs-staging-links
4/12 ++ 17 --
Merge babad5faa8ea8f36f3258f92c763e7f929c02c03 into a9753af2536081b26c8549679a0c9fff406fbb00
0e53dea5
pull/6722/merge
7/42 ++ 11 --
Update catchup/universalFetcher_test.go
Co-authored-by: nullun <git@nullun.com>
babad5fa
pull/6722/head
1/1 ++ 0 --
Apply suggestions from code review
Co-authored-by: nullun <git@nullun.com>
351cb6c2
pull/6722/head
2/3 ++ 2 --
Require the router to be in the group, and show where a forfeit goes (S7, S2)
**S7.** The S6 fix mirrored `_assert_group_is_clean` into the browser, and the mirror was faithful and insufficient. That guard checks hygiene - rekey, close, group fee - and hygiene is not what a hostile conversion violates. A plain asset transfer of the whole balance to a stranger carries no close, no rekey and an ordinary fee, and passed the mirror completely. The contract does not check `aamt` or `arcv` either, and does not need to: on a routed group the rest of it checks - the input proven spent, the co-signed floor, the pinned pools - and none of that runs unless the router is called. So the mirror had copied the cheap outer shell and left out the part doing the work. The two exempt entry points say the same thing from the other side: `pool_budget` and `verify_discount` skip the hygiene guard precisely because they ride alongside a route, so hygiene alone was never the safety argument. `routedGroupProblems` now also requires a call to the router whose ARC-4 selector is not one of those two - "calls the router" would have passed `[pool_budget, transfer-to-attacker]`, which calls the router and is checked by nothing. The app id comes from `data-router-app`, handed down by the view and overridable by a setting, with the same number in the widget as a fallback so a missing attribute cannot switch the rule off. Not from the plan response: an id the engine supplied would make the check agree with whatever the engine wanted, which is S2 for the third time. The two excluded selectors are recomputed from the method signatures by verify-sweep.sh rather than trusted as constants. All four router groups in the audit's evidence carry non-exempt selectors, so the rule accepts every conversion that has actually executed. It also caught a test that had gone quiet. "Accepting implies no transaction closes or rekeys" became vacuous the moment this landed - no corpus transaction is an application call, so every generated group was refused for that reason and the implication was never exercised. It now prefixes a real route call and asserts that something really was accepted. **S2 recommendation 2.** The row showed unit, id, badge, value and reason and never the address the tokens went to, so on the one disposition that gives something away the destination was the single fact the reader was not shown. `destinationLabel` is the pure half, tested; `renderLine` only appends it. A close says plainly that nothing leaves, because a blank cell there reads as a missing fact rather than as reassurance. The audit is explicit that this complements the chain lookup rather than replacing it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XqeQenXa9oWnLCWEvuiy8B
4fe081b9
review/S2-hardening
6/331 ++ 5 --
Merge 235200470de8aa72a43b74272a86d94efe8db0f1 into c9b2ce977732ae3a33529bc0e31f53a57df5a0c2
09dbe56c
pull/610/merge
1/1 ++ 1 --
docs: fix transactions concepts link on asset page
23520047
fix/docs-staging-links
1/1 ++ 1 --
Merge 31a93d49bfdc486a39e843fb216484540ee299c1 into a9753af2536081b26c8549679a0c9fff406fbb00
87bb2617
pull/6723/merge
12/476 ++ 12 --
logic: require explicit LogicSig allowances
31a93d49
safer-logicsigs
12/476 ++ 12 --
Merge 87cbfe7268ac9acef6382ae278d5f277631a60b6 into 623f3c058154e12632360cbd84a2d3c0c078314e
b023f175
pull/613/merge
3/4,217 ++ 0 --
docs: add v5 security notes on size-changing updates and post-quantum keys
87cbfe72
security-guide
1/24 ++ 0 --
Check the conversion path too, and stop a creator lookup hanging (S6)
`signAction` decided whether to inspect a group by reading `action.kind` out of the same response that carried the bytes. Every honest conversion carries a router call the contract checks - but an assertion inside an application only runs if the application is called, so a group labelled `convert` with no application call in it was refused by nobody: not by this file, which returned early, and not by `_assert_group_is_clean`, which was never in the group to object. S2 was a reference value the engine supplied; this was the switch deciding whether any checking happened. `routedGroupProblems` mirrors that guard where it always runs - no rekey, no close, no aclose, and the group's fee total against the contract's own MAX_GROUP_FEE rather than a number picked here. Mirroring cannot refuse a group the contract would accept. The decoder risk this raised is settled with evidence rather than reasoning. The seven groups in the audit's evidence/ were re-encoded from what the indexer returned and run through the shipped decodeMsgpack: 97 of 97 decode, application calls included, using only tags already supported. They are now a fixture, so the accepting side of this rule is tested against traffic that executed on mainnet instead of fixtures written to pass - and the ceiling has fourteen times the headroom it needs, the dearest real group paying 71,000 against 1,000,000. Writing it found something. "A conversion goes through the quote-signed path" passed [CLOSE_TO_SELF] as its group, a stand-in chosen because the path did not look at it. The new rule looked and refused it, correctly. That test now uses a real convert group. CREATOR_LOOKUP_TIMEOUT closes the one failure on the S2 path that neither refused nor accepted: algosdk v3 sets no timeout, so a node that never answered left the reader on a spinner with no prompt and no error. Ten seconds, then null, which is the refusal the unreachable node already produced. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XqeQenXa9oWnLCWEvuiy8B
ffe76831
review/S2-hardening
4/495 ++ 12 --
Bind the forfeit predicate to one function, and issue the lookups together
The S2 fix rests on an invariant that spans two functions: a transaction may close somewhere other than the sweeper's own account only when the plan calls the holding a forfeit, and that same condition is what sends the destination to the chain to be confirmed. Both spelled `Number(x.amount) !== 0` out separately, so nothing failed if one of them changed - `closeOutProblems` would keep accepting a forfeit that `forfeitTargetProblems` had quietly stopped looking up. That is S2 reopening with a green suite. `isForfeit` is now the single predicate, sitting beside `planLines`: that one decides which lines are readable, this one decides what a readable line means. A test crosses both halves over the amount shapes an engine can actually send. Mutating one side to `> 0` fails three of them; before, it failed nothing. The lookups also move into one `Promise.all` over the distinct asset ids, decoding once up front. A group of sixteen forfeits waited sixteen times the node's latency before the wallet prompt opened, because the await sat in the compare loop. The rejection-to-null fold moved with it, so "could not be confirmed" is still the single refusal path. The compare loop becoming a `.map` is why the group side now gets the shape guard the `described` side has had since `planLines`. Three docstrings had drifted from the code and are corrected rather than left to mislead the next reader of a security control: the fee is bounded per transaction only, and `summaryFigures` reports the planner's figures without verifying them - a planner reporting zero fees renders "0.00 ALGO" unchallenged, and what bounds the loss is MAX_CLOSE_OUT_FEE on the bytes being signed. `recoverable` genuinely is net of fees; the planner subtracts them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XqeQenXa9oWnLCWEvuiy8B
2dfc2188
review/S2-hardening
2/181 ++ 34 --
test: fix test script explorer to be network agnostic
30b9c7c8
main
3/37 ++ 1 --
feat: vault plugin for algorand post-quantum accounts
Adds a custom Vault secrets engine that manages Algorand post-quantum
(Falcon-1024) accounts, which the transit engine cannot do natively.
The plugin derives a Falcon-1024 keypair deterministically from 32 bytes of
entropy (the 25-word mnemonic) and stores the entropy, the canonical address
salt and the key material in the mount's barrier-encrypted storage — a PQ
account needs more than the mnemonic, since one public key can derive up to
256 addresses depending on the salt. Derivation follows go-algorand exactly
(SHA512-256 "PQK"/"PQA" domain separation, off-curve salt scan) and is pinned
by the official algokey test vector.
The API mirrors transit so the service can reuse its existing call patterns:
POST keys/{name} creates (idempotent), GET keys/{name} returns scheme, salt,
public key and address, POST sign/{name} signs base64 input, LIST keys
enumerates. Deletion, rotation, versioning and export are deliberately absent.
Wiring: scripts/build_vault_plugin.sh builds a static musl binary into the
plugin directory the vault container now mounts, and development-init
registers it by sha256, mounts it at pawn/pq-users and extends the AppRole
policies (users create, managers create/list/sign). CI builds the plugin
before the stack starts and runs the Go tests under the race detector.
The plugin is pinned to Go 1.23 because Vault 1.15 injects
GODEBUG=x509sha1=1 into the plugin processes it spawns and Go removed that
setting in 1.24; a newer toolchain aborts before the go-plugin handshake.
Go tests cover derivation against the official algokey vector, persistence
across a fresh backend instance and concurrent creates. The e2e suite adds a
block that talks to the mount directly — no service endpoint exposes PQ
accounts yet — re-deriving the returned address independently in TypeScript
and asserting the user AppRole can create but not sign.
f01a5667
feat/pq-accounts
13/1,124 ++ 3 --
Merge 6960bf62973759e65237740867ae52adfb4f908d into dd7be47db270b641b07a8abb0bb3995360a8e34f
3517daec
pull/911/merge
1/1 ++ 1 --
build(deps-dev): bump @typescript-eslint/eslint-plugin
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 8.69.0 to 8.68.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.68.0/packages/eslint-plugin) --- updated-dependencies: - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.68.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
6960bf62
dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-8.68.0
1/1 ++ 1 --
Merge edd1d2b93928f70946b29992936784b82cab0cb4 into 7861a68efdc034d4a01f5ba68f1acff97e28e8e6
42379a4a
pull/454/merge
15/1,388 ++ 954 --
chore(deps): update non-major dependencies
edd1d2b9
renovate/non-major-dependencies
15/1,388 ++ 954 --
feat: switch lsig to be funded/refunded to payee
cab88a45
main
4/343 ++ 158 --
Merge e19bda6a0673f116aa0b77be938e57848be7a85a into 9bc334a8819e21a61e5717e04c07dec184a7c579
18ba1d5e
pull/99/merge
2/5 ++ 3 --
chore(deps): update dependency conventional-changelog-conventionalcommits to v10
e19bda6a
renovate/conventional-changelog-conventionalcommits-10.x
2/5 ++ 3 --
Merge 8076e736e409d33e49b9f0f8b93330517469b2a9 into 9bc334a8819e21a61e5717e04c07dec184a7c579
0641241a
pull/98/merge
2/4 ++ 4 --