Ecosystem metrics
- New Repos
- 19
- New
- Commits
- 464
- up 2.4%
- Releases
- 1
- down 66.7%
- Contributors
- 35
- down 10.3%
- Merges
- 6
- down 62.5%
Activity Overview
Commits and releases over time
- Commits
- Releases
- Authors
Repository Explorer
No repositories match that filter.
8917 commits in all time
Aug 12, 2026 22:39 – Nov 10, 2026 22:39 UTC
Merge ecd8de9a35af8957a4573b64cacd80b9faafaefb into 1c49eb8a4fe3fcf2b0f0140f683ff3b4bf1d8c5e
2913d881
pull/498/merge
10/531 ++ 98 --
chore(deps): update dependency tsdown to v0.23.7
ecd8de9a
renovate/wallet-adapter-packages
10/531 ++ 98 --
Notes added by 'git notes add'
27605d14
notes/semantic-release-v5.4.0
1/1 ++ 0 --
Merge d6a19ea9339ad6a620e4372ab33d60a4a4592dc1 into c9d480e9879975a0d5270975b0bc2e28cfa168e5
dfef7fc1
pull/476/merge
14/1,306 ++ 713 --
chore(deps): update non-major dependencies
d6a19ea9
renovate/non-major-dependencies
14/1,306 ++ 713 --
feat(passkey): opt-in app secret from a second PRF output (#499)
* feat(passkey): opt-in app secret from a second PRF output
An app can ask the passkey for a secret of its own, derived from the
same credential but separate from the signing key: pass
`appSecret: { label }` and read it with `withAppSecret(callback)`.
- Every PRF ceremony (connect, unlock) also evaluates `eval.second`
with `@txnlab/use-wallet-passkey:app-secret:v1:<label>` while the
option is set. The label is 1-128 characters, no `:`.
- The secret is held only while the session is unlocked and zeroed on
lock, release, a failed connect and a key mismatch. `withAppSecret`
hands the callback a copy it zeroes afterwards; while locked it runs
a PRF ceremony (confirmed per `confirm`).
- A provider that returns no second output gives `PasskeyError` code
`app-secret-unavailable`.
- `PasskeySigningRequest` gains `{ type: 'app-secret' }`.
- `APP_SECRET_PREFIX`, `appSecretInput` and `PasskeyAppSecretOptions`
are exported; the prefix is frozen.
hay.app uses it to derive a separate ZeroSignal payer account from a
passkey Haystack Login, as it already does from a legacy login's key.
* fix(passkey): fail a worker unlock as key-store-failed, not a TypeError
WorkerKeyStore.unlock transfers the entropy buffer to the worker. When the unlock then failed (the worker answered with an error, or the store locked while the worker derived the key), the catch block made a view of that detached buffer to zero it, which throws. The caller got a TypeError instead of the PasskeyError, and lock() was skipped, leaving the worker running.
Zero the buffer only while the page still holds it (a worker that never started). The test worker now detaches what it's sent, as a real one does, and tests cover a failure before and after the transfer.
* fix(passkey): tighten the app secret's label and refuse the key's own output
- The label must be a string of 1 to 128 printable ASCII characters, no ":". Anything else passed the old check as its text, so a missing value derived a secret under "undefined"; and outside ASCII, labels that look alike can encode differently (composed and decomposed accents) or differ and encode the same (lone surrogates). The label is the PRF input and frozen once used, so the rule is set before the first release.
- A second PRF output equal to the first is zeroed and treated as missing: a provider that ignores the PRF input would otherwise hand the app the Falcon key's entropy. withAppSecret throws app-secret-unavailable and the account still signs.
- The credential's own copy of the first output is zeroed like the second's. Both are copied before either is zeroed, in case they share a buffer.
The README and the guide state the label rule, and that context is not part of the secret's input.
* docs(passkey): show how to derive keys from the app secret
The app secret is key material, not a key of one kind. The README and the Passkey Accounts guide gain "Deriving keys from the secret": an HKDF helper with one info string per key, a single ed25519 account with its 25-word phrase, and an HD (xHD, ARC-52) wallet from a 24-word BIP-39 phrase with @algorandfoundation/xhd-wallet-api, down to a signed transaction.
It also says what to settle before relying on derived keys: offer the phrase as a backup, they are ed25519 and not post-quantum, they are derived on the main thread, and one secret serves every account of the passkey. The appSecret option's JSDoc points to the section.
---------
Co-authored-by: Patrick Bennett <170563+pbennett@users.noreply.github.com>
c9d480e9
main
11/955 ++ 33 --
Merge 8e449c20b6edc17069c3968025947461cb6af94f into 3563e702c453dd7767d37b4ee0d98ec76a0221f5
7a025b55
pull/499/merge
11/955 ++ 33 --
docs(passkey): show how to derive keys from the app secret
The app secret is key material, not a key of one kind. The README and the Passkey Accounts guide gain "Deriving keys from the secret": an HKDF helper with one info string per key, a single ed25519 account with its 25-word phrase, and an HD (xHD, ARC-52) wallet from a 24-word BIP-39 phrase with @algorandfoundation/xhd-wallet-api, down to a signed transaction. It also says what to settle before relying on derived keys: offer the phrase as a backup, they are ed25519 and not post-quantum, they are derived on the main thread, and one secret serves every account of the passkey. The appSecret option's JSDoc points to the section.
8e449c20
feat/passkey-app-secret
3/163 ++ 4 --
Merge 415df1c4786d715588cc34884d947fce2b91e173 into 3563e702c453dd7767d37b4ee0d98ec76a0221f5
63cbc772
pull/499/merge
11/796 ++ 33 --
fix(passkey): tighten the app secret's label and refuse the key's own output
- The label must be a string of 1 to 128 printable ASCII characters, no ":". Anything else passed the old check as its text, so a missing value derived a secret under "undefined"; and outside ASCII, labels that look alike can encode differently (composed and decomposed accents) or differ and encode the same (lone surrogates). The label is the PRF input and frozen once used, so the rule is set before the first release. - A second PRF output equal to the first is zeroed and treated as missing: a provider that ignores the PRF input would otherwise hand the app the Falcon key's entropy. withAppSecret throws app-secret-unavailable and the account still signs. - The credential's own copy of the first output is zeroed like the second's. Both are copied before either is zeroed, in case they share a buffer. The README and the guide state the label rule, and that context is not part of the secret's input.
415df1c4
feat/passkey-app-secret
8/148 ++ 34 --
fix(passkey): fail a worker unlock as key-store-failed, not a TypeError
WorkerKeyStore.unlock transfers the entropy buffer to the worker. When the unlock then failed (the worker answered with an error, or the store locked while the worker derived the key), the catch block made a view of that detached buffer to zero it, which throws. The caller got a TypeError instead of the PasskeyError, and lock() was skipped, leaving the worker running. Zero the buffer only while the page still holds it (a worker that never started). The test worker now detaches what it's sent, as a real one does, and tests cover a failure before and after the transfer.
8d043316
feat/passkey-app-secret
2/90 ++ 3 --
Merge e7ec86148c24cef5f9ef1e2c9a6482728e1d58c5 into 6256402b3196fc0e344d8aee1baa77a7b5adb529
5e37cf1f
pull/35/merge
22/6,781 ++ 6,303 --
Merge cedad15add46cd6c945e0d9637ef624c5bc78c44 into 543110998c63b82a7f517c631c32ae62b9fbe9e3
edf777be
pull/949/merge
2/42 ++ 0 --
Add HashSet regression test and fix formatting
cedad15a
pull/949/head
2/15 ++ 0 --
Merge 47f7efd2d47a0cb33b8396a96a49f60216f93d34 into 361d3066ffaca4241991cc6563403417bf562ecf
efd4321b
pull/17/merge
4/3,335 ++ 1,988 --
fix(deps): update all non-major dependencies
47f7efd2
renovate/all-minor-patch
4/3,335 ++ 1,988 --