Repository navigation
fix(backend): i128 cap, event-history auth, SSE client ids, cancel signing docs (#1532, #1533, #1534, #1547) - #1630
Merged
K1NGD4VID merged 4 commits intoOct 18, 2026
Conversation
createStreamSchema is wired into POST /v1/streams, but its depositedAmount field only checked the numeric format, so a value larger than 2^127-1 could reach BigInt arithmetic and the i128 DB columns unchecked. Share the i128 bound helper between ratePerSecond and depositedAmount and cover both the schema and the HTTP route with regression tests. Closes LabsCrypt#1532 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
GET /v1/users/:publicKey/events was unauthenticated and unscoped, so any caller could enumerate any wallet's stream history by public key. Require a bearer token and reject 403 unless the path publicKey matches the authenticated wallet, mirroring GET /v1/events. Regenerate the OpenAPI spec and API types, and add route-level regression tests. Closes LabsCrypt#1533 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
The SSE subscribe handler built client ids from Date.now() plus a short Math.random() suffix, so two concurrently connecting clients could collide and overwrite each other's registration. Use the CSPRNG-backed randomUUID already used by every other id generator in the backend, and assert the format in the subscribe test. Closes LabsCrypt#1534 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
The action signing tables omitted Cancel entirely, leaving reviewers unable to tell whether cancellation holds custodial risk. Add a Cancel row to both architecture docs and state the actual rule: only top-up is signed with KEEPER_SECRET_KEY, while cancel is submitted server-side using the caller-supplied senderSecret. Closes LabsCrypt#1547 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes four third-wave audit issues in one branch.
#1532 —
depositedAmounthas no i128 capcreateStreamSchemais already wired intoPOST /v1/streams, but itsdepositedAmountfield only enforced the numeric format, so a decimal string abovei128::MAXpassed validation and reachedBigIntarithmetic / the i128 DB columns. The i128 bound check is now shared betweenratePerSecondanddepositedAmountinbackend/src/validators/stream.validator.ts.POST /v1/streamstests asserting400.#1533 —
GET /v1/users/:publicKey/eventshad no authThe route now uses
requireAuth, andgetUserEventsrejects (403) when the authenticated caller's public key differs from the:publicKeypath param, mirroringGET /v1/events. Missing auth is rejected with 401 (middleware and controller guard).#1534 — SSE
clientIdusesMath.random()backend/src/controllers/sse.controller.tsnow generatesclientIdwithcrypto.randomUUID(), matching every other id generator in the backend. The subscribe test asserts the UUID format and that theconnectedevent carries the same id.#1547 — Action Signing Model omitted Cancel
Both
docs/ARCHITECTURE.mdandbackend/docs/ARCHITECTURE.mdnow include a Cancel row and corrected prose.Note: the issue's premise no longer matches
main.backend/src/controllers/stream/cancel.tsdoes not readKEEPER_SECRET_KEY; it requiressenderSecretin the request body and passes it tosorobanService.cancelStream(). A grep ofbackend/srcconfirmstopUpStream()is the only caller of the keeper secret, so documenting Cancel as custodial would make the docs wrong. Instead the docs now state that cancel is submitted server-side but authorized with the caller's own key, and explicitly list the set of custodial vs. user-authorized actions, with the grep evidence.Verification
cd backend && npx tsc --noEmit— cleancd backend && npx vitest run --exclude='tests/integration/**' --coverage.enabled=false— 59 files, 727 passed, 3 skippedcd backend && npx vitest run --coverage.enabled=false tests/stream.validator.test.ts tests/stream.controller.test.ts tests/user.controller.test.ts tests/sse.controller.test.ts tests/integration/events-list.test.ts tests/integration/sse-subscribe.test.ts tests/stream.test.ts— all passingnpm run codegen:openapi+npm run codegen:api-typesregenerate cleanly (spec/types committed)Closes #1532
Closes #1533
Closes #1534
Closes #1547