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%

Repository Explorer

6905 commits in all time Jun 03, 2026 13:28 – Sep 01, 2026 13:28 UTC
Merge c75a9ca8cd2c3e892b3d0f4ce25937e4a7949464 into 65896fdbf1e91d62413a51f403fa2454a87a67a2
Git Commit 4c298f43 Branch pull/330/merge Document 4/12 ++ 17 --
docs: fix links to archived pre-reorg pages
Git Commit c75a9ca8 Branch fix/docs-staging-links Document 4/12 ++ 17 --
Merge babad5faa8ea8f36f3258f92c763e7f929c02c03 into a9753af2536081b26c8549679a0c9fff406fbb00
Git Commit 0e53dea5 Branch pull/6722/merge Document 7/42 ++ 11 --
Update catchup/universalFetcher_test.go
Co-authored-by: nullun <git@nullun.com>
Git Commit babad5fa Branch pull/6722/head Document 1/1 ++ 0 --
Apply suggestions from code review
Co-authored-by: nullun <git@nullun.com>
Git Commit 351cb6c2 Branch pull/6722/head Document 2/3 ++ 2 --
ipaleka widgets
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
Git Commit 4fe081b9 Branch review/S2-hardening Document 6/331 ++ 5 --
Merge 235200470de8aa72a43b74272a86d94efe8db0f1 into c9b2ce977732ae3a33529bc0e31f53a57df5a0c2
Git Commit 09dbe56c Branch pull/610/merge Document 1/1 ++ 1 --
docs: fix transactions concepts link on asset page
Git Commit 23520047 Branch fix/docs-staging-links Document 1/1 ++ 1 --
giuliop go-algorand
Merge 31a93d49bfdc486a39e843fb216484540ee299c1 into a9753af2536081b26c8549679a0c9fff406fbb00
Git Commit 87bb2617 Branch pull/6723/merge Document 12/476 ++ 12 --
joe-p js-algorand-sdk
spike: fix bigint literals
Git Commit b17a5f14 Branch spike/group_modifier Document 1/18 ++ 18 --
giuliop go-algorand
logic: require explicit LogicSig allowances
Git Commit 31a93d49 Branch safer-logicsigs Document 12/476 ++ 12 --
gabrielkuettel devportal
Merge 87cbfe7268ac9acef6382ae278d5f277631a60b6 into 623f3c058154e12632360cbd84a2d3c0c078314e
Git Commit b023f175 Branch pull/613/merge Document 3/4,217 ++ 0 --
Ganainmtech devportal
docs: add v5 security notes on size-changing updates and post-quantum keys
Git Commit 87cbfe72 Branch security-guide Document 1/24 ++ 0 --
ipaleka widgets
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
Git Commit ffe76831 Branch review/S2-hardening Document 4/495 ++ 12 --
ipaleka widgets
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
Git Commit 2dfc2188 Branch review/S2-hardening Document 2/181 ++ 34 --
bwmx intermezzo
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.
Git Commit f01a5667 Branch feat/pq-accounts Document 13/1,124 ++ 3 --
Merge 6960bf62973759e65237740867ae52adfb4f908d into dd7be47db270b641b07a8abb0bb3995360a8e34f
Git Commit 3517daec Branch pull/911/merge Document 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>
Git Commit 6960bf62 Branch dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-8.68.0 Document 1/1 ++ 1 --
Merge edd1d2b93928f70946b29992936784b82cab0cb4 into 7861a68efdc034d4a01f5ba68f1acff97e28e8e6
Git Commit 42379a4a Branch pull/454/merge Document 15/1,388 ++ 954 --
chore(deps): update non-major dependencies
Git Commit edd1d2b9 Branch renovate/non-major-dependencies Document 15/1,388 ++ 954 --
Merge e19bda6a0673f116aa0b77be938e57848be7a85a into 9bc334a8819e21a61e5717e04c07dec184a7c579
Git Commit 18ba1d5e Branch pull/99/merge Document 2/5 ++ 3 --
chore(deps): update dependency conventional-changelog-conventionalcommits to v10
Git Commit e19bda6a Branch renovate/conventional-changelog-conventionalcommits-10.x Document 2/5 ++ 3 --
Merge 8076e736e409d33e49b9f0f8b93330517469b2a9 into 9bc334a8819e21a61e5717e04c07dec184a7c579
Git Commit 0641241a Branch pull/98/merge Document 2/4 ++ 4 --