Copy the checklist below into every PR review comment so GrantFox campaign reviewers can audit decisions. The PR author fills out their self-check first; the maintainer confirms each item or marks it as needing changes.
- References the original issue with
Closes #NNNin the PR body. - Acceptance criteria on the issue are checked off individually in the PR description, each with a file/line or commit reference.
-
pnpm lintpasses locally. -
pnpm typecheckpasses locally. -
pnpm testpasses locally. -
pnpm contract:testpasses locally (if anything undercontracts/changed). -
pnpm format:checkpasses orpnpm formatwas applied.
- Any new Stellar public-key / secret-key parsing matches the branded types.
- Amounts remain 7-decimal strings (not
number/ floats) through the change. - Memo rules (28-byte text; ID digits; 64-hex hash) are enforced if touched.
- Horizon error handling still maps to the typed
StellarKitErrorcodes correctly.
- Every new admin-only function calls
require_auth()on the stored admin Address. - Milestone status transitions remain in the allowed DAG.
- Evidence hash is still required before approval.
-
ApprovalAfterDisputeis still enforced unless aresolve_disputecall was added. -
DuplicateReleaseis still enforced. - Events are published with the correct tuple topic.
-
read_summaryaggregations still add up (no underflow / overflow arithmetic in a way that breaks the test suite).
- R0: No new
console.log/ logger / error.messagecontains a raw secret. - R1: No secret echoed in UI text, copy-to-clipboard, or URL.
- R2: No new
localStorage/ cookie / persistent store of secrets. - R3: No secret in a constructed URL, callback, query param, or auth header.
- R4: Structural validation runs before
Keypair.fromSecretor similar SDK calls that could leak into stack traces. - R5: All new secret-accepting APIs accept
unknown, Zod-validate, and return branded types. - R6: No committed real secret keys anywhere in fixtures/examples; only synthetic throwaway keypairs.
- New public functions in packages/ have a positive and a negative Vitest case.
- Any new branch in error mapping or status transitions has a test.
- For contract changes: happy path + error path tests added under
src/test.rscovering the specific new guard. - Tests do not print or assert on raw secret keys.
-
/docs/PROJECT_OVERVIEW.mdor the relevant topic doc updated for any new user-facing package export. - README or
/docs/LOCAL_SETUP.mdupdated if setup steps changed. - Contributor-facing
/docs/*.mdupdated if the issue-template or review workflow changed.
- Search the diff for the regexp
/S[A-Z2-7]{50,}/— zero hits outside of intentional test fixtures (and those fixtures are test-only throwaway keys). - Error messages, new alerts, and UI labels only show redacted secrets when needed.
- Defaults remain testnet-first.
- Any new mainnet code path is behind
assertNetworkAllowed(...)and is not reachable from the web dashboard without an explicit env override. - No hardcoded mainnet production URLs, custodial wallets, or payment submission that could be triggered accidentally.
- Every checkbox from the issue’s Acceptance Criteria is satisfied in this PR or explicitly deferred to a follow-up issue with that issue linked.
- No out-of-scope refactors or unrelated changes slipped in; if they did, they are split into a separate PR.
- Approve and merge.
- Approve with follow-up issue (link): …
- Changes requested before re-review.
Maintainer notes / GrantFox reviewer context:
…