Enforce READ_ONLY write blocking and add smoke coverage#1549
Merged
TheLastCicada merged 11 commits intov2-rc2from Mar 25, 2026
Merged
Enforce READ_ONLY write blocking and add smoke coverage#1549TheLastCicada merged 11 commits intov2-rc2from
TheLastCicada merged 11 commits intov2-rc2from
Conversation
Harden observer-node behavior by blocking write methods in middleware, closing known controller gaps, and unifying read-only failures to a canonical 403 payload. This prevents write side effects in read-only mode while preserving explicit controller guards for GET endpoints that can still trigger writes.
Avoid mapping unrelated 403 errors to the canonical read-only response by matching only explicit READ_ONLY-coded errors, and ensure V1 filestore delete maps read-only assertion failures to the shared 403 payload.
Avoid path-segment parsing issues for base64 file IDs by accepting `fileId` on the GET query string instead of as a URL path parameter. This preserves the POST removal while keeping lookups reliable through proxy layers that normalize encoded slashes.
Drop unused V2 filestore path-param validation and remove an unreachable READ_ONLY error branch from V1 getFileList to keep read-only mapping focused on actual write-guarded handlers.
Ensure write requests in READ_ONLY mode always return the canonical 403 by checking read-only state before wallet availability assertions in the common middleware chain. Also add explicit workflow token permissions for the read-only live smoke job to satisfy code scanning requirements.
Keep write blocking in the common-assertions middleware and retain the header-only READ_ONLY middleware behavior to avoid duplicated config checks and unreachable code paths.
Run read-only live smoke in the shared tests pipeline so it follows the same trigger and execution pattern as other live-api jobs, while keeping its lightweight setup by skipping faucet funding and governance/mirror bootstrap dependencies.
Delete the unused V1 governance subscribe validation schema left behind after removing the deprecated subscribe route so the validation surface matches active endpoints.
Map READ_ONLY assertion errors to the shared 403 payload in V1 and V2 GET offer generation handlers so read-only mode is enforced consistently for GET endpoints that can trigger write-side behavior.
Broaden the live read-only smoke suite with representative write and write-like GET endpoint canaries across v1 and v2.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Align the successful unsubscribe response text with the 200 status to avoid client confusion when parsing operation results.
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
403response payload and apply missing V1/V2 controller checks for organization, governance, offer, and filestore paths/v2/filestore/get_filein favor of GET path-param usage, with updated validations and integration teststest:v2:readonly, new integration spec, live-api smoke spec) plus a gated live smoke workflow for self-hosted runnersTest plan
npm run test:v2:readonlybash tests/run-tests.sh npx cross-env NODE_ENV=test USE_SIMULATOR=true CW_PORT=31311 mocha --loader node_modules/extensionless/src/register.js tests/v2/integration/filestore-v2.spec.js --reporter spec --exit --timeout 300000npm run test:live:readonly:smoke(requires live environment withREAD_ONLY=true)Note
Medium Risk
Changes request handling and API contracts (middleware-level write blocking, new 403 payload, and removal of routes), which can break existing clients or alter behavior in production. Risk is mitigated by added integration and live smoke tests but still touches core request paths.
Overview
Enforces
READ_ONLYmode across the API by blocking non-GET/HEAD/OPTIONSrequests insrc/middleware.jsand standardizing failures to a canonical403JSON payload via newsrc/utils/read-only-response.js.Adds missing read-only guards + consistent error handling to multiple V1/V2 controllers (governance, organizations, offers, filestore) and updates org read responses to omit wallet-derived fields (
xchAddress/balance) when read-only.Tightens API contracts by removing V1 governance
POST /subscribe, and changing V2 filestoreget_filetoGET /v2/filestore/get_file?fileId=...(dropping the legacy POST/body behavior), with corresponding validation + integration test updates.Adds new test entrypoints (
test:v2:readonly,test:live:readonly:smoke), new read-only enforcement and live smoke specs, and a new GitHub Actions job to run the live read-only smoke flow against a real Chia environment.Written by Cursor Bugbot for commit 77c536a. This will update automatically on new commits. Configure here.