feat: add API key support to prover client#1912
Conversation
WalkthroughAdds optional prover API key support and splits prover endpoints by operation. CLI/config gain per-operation prover URLs and an API key; BatchContext and processor wiring are updated to carry those fields; instruction-stream builders and ProofClient are updated to accept and send an X-API-Key header when provided. Tests and docs updated accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant CLI as CLI / Config
participant EM as EpochManager
participant Proc as Processor V2
participant Utils as forester-utils (streams)
participant PC as ProofClient
participant Prover as Prover Service
CLI->>EM: StartArgs (prover_* URLs, prover_api_key)
EM->>Proc: BatchContext {append/update/address URLs, prover_api_key}
Proc->>Utils: get_*_instruction_stream(..., url, prover_api_key, ...)
Utils->>PC: ProofClient::with_config(url, ..., prover_api_key)
PC->>Prover: HTTP request (+ X-API-Key if provided)
Prover-->>PC: Job/status responses
PC-->>Utils: Proof data / job status
Utils-->>Proc: Instruction stream
Proc-->>EM: Batched instructions
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: CodeRabbit UI 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
🔇 Additional comments (3)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
forester/src/processor/v2/address.rs
Outdated
| rpc_pool: ctx.rpc_pool.clone(), | ||
| merkle_tree_pubkey: ctx.merkle_tree, | ||
| prover_url: ctx.prover_url.clone(), | ||
| prover_url: construct_prover_url(&ctx.prover_url, "/address-append"), |
There was a problem hiding this comment.
this is supposed to have the endpoint hardcoded here? @sergeytimoshin
There was a problem hiding this comment.
You are right, I'll clean it up.
There was a problem hiding this comment.
Actionable comments posted: 6
🔭 Outside diff range comments (1)
forester/tests/test_utils.rs (1)
82-90: Add per-operation prover URLs to ExternalServicesConfig in testsThe
ExternalServicesConfigstruct inforester/src/config.rsnow includes three new fields—prover_append_url,prover_update_url, andprover_address_append_url. The initializer inforester/tests/test_utils.rs(around line 82) only setsprover_url, so it will fail to compile. Update that block to:external_services: ExternalServicesConfig { rpc_url: "http://localhost:8899".to_string(), ws_rpc_url: Some("ws://localhost:8900".to_string()), indexer_url: Some("http://localhost:8784".to_string()), prover_url: Some("http://localhost:3001".to_string()), + prover_append_url: Some("http://localhost:3001".to_string()), + prover_update_url: Some("http://localhost:3001".to_string()), + prover_address_append_url: Some("http://localhost:3001".to_string()), prover_api_key: None, photon_api_key: None, pushgateway_url: None, pagerduty_routing_key: None,• Apply the same additions in other test initializers (e.g.
priority_fee_test.rs,legacy/test_utils.rs, etc.).
• If you prefer, you can replace the explicit fields with..Default::default()to cover all missing entries.
🧹 Nitpick comments (12)
js/stateless.js/README.md (3)
35-37: Bulleted example links normalized; consider adding API key usage noteFormatting looks consistent. Given this PR adds prover API key support end-to-end, should we add a brief note or link here to an example showing API key configuration/usage in the JS client (if applicable to stateless.js)?
I can draft a succinct bullet with a link to the relevant docs or an example repo section once you confirm where API key setup is documented.
44-46: Nit: “stacktraces” → “stack traces”; minor claritySmall wording fix for readability.
Apply this diff:
- - A description or context of any errors you are encountering with stacktraces if available. + - A description or context of any errors you are encountering, with stack traces if available.
60-63: Combine wrapped bullet into a single line for cleaner renderingAvoiding soft-wrapped list items improves readability and prevents accidental formatting issues in some renderers.
Apply this diff:
- - 🐞 For bugs or feature requests, please open an - [issue](https://github.com/lightprotocol/light-protocol/issues/new). - - 🔒 For security vulnerabilities, please follow the [security policy](https://github.com/Lightprotocol/light-protocol/blob/main/SECURITY.md). + - 🐞 For bugs or feature requests, please open an [issue](https://github.com/lightprotocol/light-protocol/issues/new). + - 🔒 For security vulnerabilities, please follow the [security policy](https://github.com/Lightprotocol/light-protocol/blob/main/SECURITY.md).js/compressed-token/README.md (1)
41-43: Nit: add terminal punctuation and fix “stacktraces”Minor readability polish for the help checklist.
Apply this diff:
- - A detailed description of what you're trying to achieve - - Source code, if possible - - The text of any errors you encountered, with stacktraces if available + - A detailed description of what you're trying to achieve. + - Source code, if possible. + - The text of any errors you encountered, with stack traces if available.prover/client/src/proof_client.rs (2)
164-174: Attach X-API-Key on POST: correct; consider a small helper to DRYHeader injection is right. To avoid duplication and ensure future requests also carry the header, wrap it in a helper.
Apply this diff to simplify here:
- let mut request = self - .client - .post(&url) - .header("Content-Type", "application/json"); - - if let Some(api_key) = &self.api_key { - request = request.header("X-API-Key", api_key); - } - - request + self.with_auth( + self.client + .post(&url) + .header("Content-Type", "application/json"), + ) .body(inputs_json.to_string()) .send()And add this helper somewhere in
impl ProofClient:impl ProofClient { fn with_auth(&self, req: reqwest::RequestBuilder) -> reqwest::RequestBuilder { if let Some(ref api_key) = self.api_key { req.header("X-API-Key", api_key) } else { req } } }
383-389: Attach X-API-Key on GET status: mirror POST and reuse helperThis mirrors the POST path correctly. If you adopt the helper above, this becomes more concise and harder to miss in future additions.
Apply this diff:
- let mut request = self.client.get(status_url); - - if let Some(api_key) = &self.api_key { - request = request.header("X-API-Key", api_key); - } - - let response = request.send().await.map_err(|e| { + let response = self.with_auth(self.client.get(status_url)).send().await.map_err(|e| { error!("Failed to send status request for job {}: {}", job_id, e); ProverClientError::ProverServerError(format!("Failed to check job status: {}", e)) })?;js/compressed-token/CHANGELOG.md (1)
61-78: Fix nested list indentation (markdownlint MD007) and minor style nitsIndent nested bullets by two spaces for consistency and to satisfy MD007.
Apply this diff:
-- new type: TokenPoolInfo -- Instruction Changes: - - `compress`, `mintTo`, `approveAndMintTo`, `compressSplTokenAccount` now require valid TokenPoolInfo - - `decompress` now requires an array of one or more TokenPoolInfos. - - `decompress`, `transfer` now do not allow state tree overrides. +- New type: TokenPoolInfo +- Instruction Changes: + - `compress`, `mintTo`, `approveAndMintTo`, `compressSplTokenAccount` now require valid `TokenPoolInfo` + - `decompress` now requires an array of one or more `TokenPoolInfo`s. + - `decompress`, `transfer` now do not allow state tree overrides. -- Action Changes: - - Removed optional tokenProgramId: PublicKey - - removed optional merkleTree: PublicKey - - removed optional outputStateTree: PublicKey - - added optional stateTreeInfo: StateTreeInfo - - added optional tokenPoolInfo: TokenPoolInfo +- Action Changes: + - Removed optional `tokenProgramId: PublicKey` + - Removed optional `merkleTree: PublicKey` + - Removed optional `outputStateTree: PublicKey` + - Added optional `stateTreeInfo: StateTreeInfo` + - Added optional `tokenPoolInfo: TokenPoolInfo` -- new instructions: - - `approve`, `revoke`: delegated transfer support. - - `addTokenPools`: you can now register additional token pool pdas. Use - this if you need very high concurrency. +- New instructions: + - `approve`, `revoke`: delegated transfer support. + - `addTokenPools`: you can now register additional token pool PDAs. Use this if you need very high concurrency.js/stateless.js/CHANGELOG.md (1)
166-172: Fix list indentation and a few style nitsAdjust nested bullet indentation to two spaces (MD007) and keep naming consistent.
Apply this diff:
-- ActiveTreeBundle is now a tuple of `tree`, `queue`, `cpiContext`, and `treeType`. `treeType` is a new enum ensuring forward compatibility. -- Updated LUT addresses for Mainnet and Devnet: - - stateTreeLookupTableMainnet = '7i86eQs3GSqHjN47WdWLTCGMW6gde1q96G2EVnUyK2st'; - - nullifiedStateTreeLookupTableMainnet = 'H9QD4u1fG7KmkAzn2tDXhheushxFe1EcrjGGyEFXeMqT'; - - stateTreeLookupTableDevnet = '8n8rH2bFRVA6cSGNDpgqcKHCndbFCT1bXxAQG89ejVsh'; - - nullifiedStateTreeLookupTableDevnet = '5dhaJLBjnVBQFErr8oiCJmcVsx3Zj6xDekGB2zULPsnP'; +- ActiveTreeBundle is now a tuple of `tree`, `queue`, `cpiContext`, and `treeType`. `treeType` is a new enum ensuring forward compatibility. +- Updated LUT addresses for Mainnet and Devnet: + - stateTreeLookupTableMainnet = '7i86eQs3GSqHjN47WdWLTCGMW6gde1q96G2EVnUyK2st'; + - nullifiedStateTreeLookupTableMainnet = 'H9QD4u1fG7KmkAzn2tDXhheushxFe1EcrjGGyEFXeMqT'; + - stateTreeLookupTableDevnet = '8n8rH2bFRVA6cSGNDpgqcKHCndbFCT1bXxAQG89ejVsh'; + - nullifiedStateTreeLookupTableDevnet = '5dhaJLBjnVBQFErr8oiCJmcVsx3Zj6xDekGB2zULPsnP'; @@ -- Multiple State Tree support. Allows you to pass non-default state tree pubkeys to actions and instructions. Comes out of the box with public state trees. - - `pickRandomStateTreeAndQueue` - - `getLightStateTreeInfo` +- Multiple State Tree support. Allows you to pass non-default state tree pubkeys to actions and instructions. Comes out of the box with public state trees. + - `pickRandomStateTreeAndQueue` + - `getLightStateTreeInfo`Also applies to: 187-190
forester-utils/src/instructions/address_batch_update.rs (1)
28-36: Public config now carries API key — mind downstream Debug/logging.Adding
pub prover_api_key: Option<String>is correct for capability. Ensure any Debug/trace on configs redacts this since it’s sensitive.forester/src/epoch_manager.rs (1)
1188-1224: BatchContext wiring: fallbacks & API key propagation verified
- Call sites for
get_nullify_instruction_streamandget_append_instruction_streamhave been updated to use the new prover-_* fields.- No lingering uses of the old
prover_urlfield were found.Two optional, low-risk improvements:
- Extract the default URL into a module-level
const &strto eliminate repeatedStringallocations.- Add a debug-level log of which prover endpoint is selected for each operation to simplify troubleshooting.
Example cleanup:
- let default_prover_url = "http://127.0.0.1:3001".to_string(); + const DEFAULT_PROVER_URL: &str = "http://127.0.0.1:3001"; let batch_context = BatchContext { // ... prover_append_url: self .config .external_services .prover_append_url .clone() - .unwrap_or_else(|| default_prover_url.clone()), + .unwrap_or_else(|| DEFAULT_PROVER_URL.to_string()), prover_update_url: self .config .external_services .prover_update_url .clone() - .unwrap_or_else(|| default_prover_url.clone()), + .unwrap_or_else(|| DEFAULT_PROVER_URL.to_string()), prover_address_append_url: self .config .external_services .prover_address_append_url .clone() - .unwrap_or_else(|| default_prover_url.clone()), + .unwrap_or_else(|| DEFAULT_PROVER_URL.to_string()), };Please manually verify that no other code paths still reference a single
prover_url.forester-utils/src/instructions/state_batch_append.rs (2)
130-131: Avoid unnecessary String clones when constructing ProofClientBoth
prover_urlandprover_api_keyare only used to build the client and not reused later in this scope. You can avoid allocations by moving them (or by passing string slices ifwith_configsupports it).Option A (preferred if
with_configtakes owned Strings):- let proof_client = Arc::new(ProofClient::with_config(prover_url.clone(), polling_interval, max_wait_time, prover_api_key.clone())); + let proof_client = Arc::new(ProofClient::with_config(prover_url, polling_interval, max_wait_time, prover_api_key));Option B (if
with_configaccepts string slices):- let proof_client = Arc::new(ProofClient::with_config(prover_url.clone(), polling_interval, max_wait_time, prover_api_key.clone())); + let proof_client = Arc::new(ProofClient::with_config( + prover_url.as_str(), + polling_interval, + max_wait_time, + prover_api_key.as_deref(), + ));If capture semantics with
async_stream::stream!make moving awkward, another low-impact alternative is to build the client once outside the stream block (after the early returns) and clone the Arc inside:Add (outside the stream, e.g., after Line 88):
let proof_client = Arc::new(ProofClient::with_config( prover_url, polling_interval, max_wait_time, prover_api_key, ));Then remove the client construction at this line and keep using:
let client = Arc::clone(&proof_client);
46-57: Signature change confirmed—call-sites updated; consider docs, changelog & optional refactorI’ve verified that all calls to
get_append_instruction_stream(e.g. inforester/src/processor/v2/state.rs) have been updated to include the newprover_api_keyargument. With that in place, here are the remaining non-breaking recommendations:• Add rustdoc for the new
prover_api_key, noting thatNoneomits the header and that it’s treated as a secret (avoid logging).
• If this function is part of your public API surface, update the changelog/semver entry to document the added parameter.
• Optional refactor: bundle(prover_url, prover_api_key, polling_interval, max_wait_time)into aProverClientConfigstruct to prevent future signature churn and improve readability.pub struct ProverClientConfig { pub url: String, pub api_key: Option<String>, pub polling_interval: Duration, pub max_wait_time: Duration, }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (17)
forester-utils/src/instructions/address_batch_update.rs(4 hunks)forester-utils/src/instructions/state_batch_append.rs(2 hunks)forester-utils/src/instructions/state_batch_nullify.rs(2 hunks)forester/src/cli.rs(1 hunks)forester/src/config.rs(3 hunks)forester/src/epoch_manager.rs(2 hunks)forester/src/processor/v2/address.rs(1 hunks)forester/src/processor/v2/common.rs(1 hunks)forester/src/processor/v2/state.rs(2 hunks)forester/tests/e2e_test.rs(3 hunks)forester/tests/priority_fee_test.rs(1 hunks)forester/tests/test_utils.rs(1 hunks)js/compressed-token/CHANGELOG.md(3 hunks)js/compressed-token/README.md(2 hunks)js/stateless.js/CHANGELOG.md(2 hunks)js/stateless.js/README.md(2 hunks)prover/client/src/proof_client.rs(5 hunks)
🧰 Additional context used
🪛 LanguageTool
js/compressed-token/README.md
[grammar] ~41-~41: There might be a mistake here.
Context: ...ription of what you're trying to achieve - Source code, if possible - The text of a...
(QB_NEW_EN)
[grammar] ~42-~42: There might be a mistake here.
Context: ...ng to achieve - Source code, if possible - The text of any errors you encountered, ...
(QB_NEW_EN)
js/stateless.js/README.md
[style] ~41-~41: Consider using a less common alternative to make your writing sound more unique and professional.
Context: ...shooting Have a question or a problem? Feel free to ask in the [Light](https://discord.gg/C...
(FEEL_FREE_TO_STYLE_ME)
[grammar] ~62-~62: There might be a mistake here.
Context: ...tprotocol/light-protocol/issues/new). - 🔒 For security vulnerabilities, please f...
(QB_NEW_EN)
[grammar] ~62-~62: There might be a mistake here.
Context: ...l/light-protocol/blob/main/SECURITY.md). ## Additional Resources - [Light Protocol R...
(QB_NEW_EN)
[grammar] ~66-~66: There might be a mistake here.
Context: ... Resources - Light Protocol Repository - [ZK Compression Official Documentation](h...
(QB_NEW_EN)
js/compressed-token/CHANGELOG.md
[grammar] ~3-~3: There might be a mistake here.
Context: ...g a non-payer mint and freeze authority. - More efficient computebudgets for action...
(QB_NEW_EN)
[grammar] ~4-~4: There might be a mistake here.
Context: ...re efficient computebudgets for actions. - Better DX: Parameter lookup in call sign...
(QB_NEW_EN)
[grammar] ~61-~61: There might be a mistake here.
Context: ... ### Overview - new type: TokenPoolInfo - Instruction Changes: - compress, `...
(QB_NEW_EN)
[grammar] ~67-~67: There might be a mistake here.
Context: ...state tree overrides. - Action Changes: - Removed optional tokenProgramId: PublicK...
(QB_NEW_EN)
[grammar] ~74-~74: There might be a mistake here.
Context: ...Info: TokenPoolInfo - new instructions: - approve, revoke: delegated transfer support. ...
(QB_NEW_EN)
js/stateless.js/CHANGELOG.md
[grammar] ~39-~39: There might be a mistake here.
Context: ...hanges - Renamed ActiveTreeBundle to StateTreeInfo - Updated StateTreeInfo internal structu...
(QB_NEW_EN)
[grammar] ~40-~40: There might be a mistake here.
Context: ...ted StateTreeInfo internal structure: { tree: PublicKey, queue: PublicKey, cpiContext: PublicKey | null, treeType: TreeType } - Replaced pickRandomTreeAndQueue with `...
(QB_NEW_EN)
[grammar] ~41-~41: There might be a mistake here.
Context: ... Replaced pickRandomTreeAndQueue with selectStateTreeInfo - Use selectStateTreeInfo for tree selec...
(QB_NEW_EN)
[grammar] ~167-~167: There might be a mistake here.
Context: ...ed LUT addresses for Mainnet and Devnet: - stateTreeLookupTableMainnet = '7i86eQs3G...
(QB_NEW_EN)
[grammar] ~168-~168: There might be a mistake here.
Context: ...s3GSqHjN47WdWLTCGMW6gde1q96G2EVnUyK2st'; - nullifiedStateTreeLookupTableMainnet = '...
(QB_NEW_EN)
[grammar] ~169-~169: There might be a mistake here.
Context: ...1fG7KmkAzn2tDXhheushxFe1EcrjGGyEFXeMqT'; - stateTreeLookupTableDevnet = '8n8rH2bFRV...
(QB_NEW_EN)
[grammar] ~170-~170: There might be a mistake here.
Context: ...bFRVA6cSGNDpgqcKHCndbFCT1bXxAQG89ejVsh'; - nullifiedStateTreeLookupTableDevnet = '5...
(QB_NEW_EN)
[grammar] ~195-~195: There might be a mistake here.
Context: ...amId explicitly. is backward compatible with boolean flag for t22. ### Deprecated ...
(QB_NEW_EN)
🪛 markdownlint-cli2 (0.17.2)
js/compressed-token/CHANGELOG.md
63-63: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
64-64: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
65-65: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
68-68: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
69-69: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
70-70: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
71-71: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
72-72: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
75-75: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
76-76: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
js/stateless.js/CHANGELOG.md
168-168: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
169-169: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
170-170: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
171-171: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
188-188: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
189-189: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: Forester e2e test
- GitHub Check: cli-v2
- GitHub Check: stateless-js-v2
- GitHub Check: Test program-libs-fast
- GitHub Check: Test concurrent-merkle-tree
- GitHub Check: Test sdk-libs
- GitHub Check: lint
- GitHub Check: Test batched-merkle-tree-simulate
- GitHub Check: Test program-libs-slow
- GitHub Check: stateless-js-v1
- GitHub Check: cli-v1
🔇 Additional comments (22)
js/stateless.js/README.md (1)
66-67: LGTM on resource linksLink text and targets look correct and consistent with the rest of the document.
js/compressed-token/README.md (1)
31-32: Formatting-only change LGTMThe switch to standard bullets improves readability. No content changes.
prover/client/src/proof_client.rs (1)
54-55: API key plumbing into ProofClient fully verified
- All
ProofClient::with_configcalls now include the newapi_keyargument:
- forester-utils/src/instructions/address_batch_update.rs:54
- forester-utils/src/instructions/state_batch_nullify.rs:129
- forester-utils/src/instructions/state_batch_append.rs:130
- No legacy 3-argument invocations remain (all report
commas=3, i.e. four parameters).- The request header uses
"X-API-Key"consistently in proof_client.rs (lines 170 and 386).Everything looks correct—no further changes needed.
js/stateless.js/CHANGELOG.md (1)
39-43: Breaking-changes bullets LGTMRenames and replacements are clearly listed and consistent with the migration guide.
forester/src/processor/v2/address.rs (1)
30-35: Good: per-operation endpoint + API-key plumbed (resolves “hardcoded endpoint” concern).Switching to
ctx.prover_address_append_urland threadingctx.prover_api_keyintoAddressUpdateConfiglooks correct and aligns with the new split endpoints design. This resolves the earlier feedback about hardcoding the endpoint.forester/tests/priority_fee_test.rs (1)
41-41: LGTM: explicit None keeps the test isolated.Setting
prover_api_key: Noneis appropriate for this test and shouldn’t affect behavior due to fallback handling elsewhere.forester/tests/e2e_test.rs (3)
117-123: Rename to get_photon_api_key is clear and consistent.Returning
Nonefor Local andSome(PHOTON_API_KEY)for Devnet matches the intended test behavior. No issues spotted.
194-201: Config wiring for prover_api_key and photon_api_key is correct.Passing both keys through
ExternalServicesConfigmirrors production config. Looks good.
464-465: LightClientConfig initialization updated to use photon API key.Using
get_photon_api_key()for the third parameter matches the new signature expectation and keeps Local behavior intact.forester-utils/src/instructions/address_batch_update.rs (3)
39-51: API key threaded into stream builder signature cleanly.Extending
stream_instruction_datato acceptprover_api_keykeeps the surface area minimal and avoids global state. Looks good.
325-337: Correct: passing config.prover_api_key into stream builder.This completes the end-to-end plumbing needed for authenticated prover calls. No issues.
54-55: No raw API key logging in ProofClient – resolvedVerified across the codebase that
ProofClient::with_configonly sets theX-API-Keyheader whenSome(key)and contains no log/debug/trace calls exposing the raw key.forester/src/config.rs (2)
211-236: Nice fallback behavior preserves backward compatibility.Defaulting operation-specific prover URLs to
prover_urlwhen omitted is the right call for existing deployments. The mapping looks correct.
301-304: Status config zeroes API-related fields — correct for read-only mode.Explicitly setting the new prover fields to
Nonemakes status calls environment-agnostic. LGTM.forester/src/cli.rs (3)
37-43: Per-operation append URL: looks good.Clear naming and helpful fallback hint. This aligns with downstream usage in BatchContext and state append stream.
44-50: Per-operation update URL: looks good.Consistent with nullify/update flow in state processing; fallback wording matches the config behavior.
51-57: Address-append URL: looks good.Consistent naming and help text. Downstream address pipeline can pick this up cleanly.
forester/src/processor/v2/common.rs (1)
43-47: BatchContext now models per-operation endpoints + API key: good foundation.Public fields are clear and map 1:1 to the new CLI/config. Downstream state/address processors can select the right endpoint.
forester-utils/src/instructions/state_batch_nullify.rs (2)
46-55: API key plumbed into nullify stream: signature change looks sound.The new optional
prover_api_keyparameter is in a sensible position afterprover_urland matches how state.rs calls it.
128-130: Forward API key to ProofClient configuration: correct usage.Constructing a single Arc per stream prevents redundant clients and properly carries the X-API-Key header downstream.
forester/src/processor/v2/state.rs (2)
32-37: Nullify path uses update URL + API key: correct.The parameter order matches the updated function signature in forester-utils, and correctly uses the update endpoint.
59-64: Append path uses append URL + API key: correct.Consistent with per-operation endpoint design and ProofClient expectations.
| #[arg(long, env = "FORESTER_PROVER_API_KEY")] | ||
| pub prover_api_key: Option<String>, | ||
|
|
There was a problem hiding this comment.
Avoid leaking prover_api_key in logs/debug output.
StartArgs derives Debug, which can unintentionally log the API key. Redact the value and hide env values in help/error output.
Apply this diff to avoid exposing the key in Clap output and improve UX:
- #[arg(long, env = "FORESTER_PROVER_API_KEY")]
+ #[arg(long, env = "FORESTER_PROVER_API_KEY", hide_env_values = true, value_name = "PROVER_API_KEY")]
pub prover_api_key: Option<String>,Additionally, consider replacing the auto-derived Debug for StartArgs with a manual Debug that redacts secrets (outside the shown hunk). Example:
impl std::fmt::Debug for StartArgs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("StartArgs")
.field("rpc_url", &self.rpc_url)
.field("push_gateway_url", &self.push_gateway_url)
.field("pagerduty_routing_key", &self.pagerduty_routing_key.as_ref().map(|_| "<redacted>"))
.field("ws_rpc_url", &self.ws_rpc_url)
.field("indexer_url", &self.indexer_url)
.field("prover_url", &self.prover_url)
.field("prover_append_url", &self.prover_append_url)
.field("prover_update_url", &self.prover_update_url)
.field("prover_address_append_url", &self.prover_address_append_url)
.field("prover_api_key", &self.prover_api_key.as_ref().map(|_| "<redacted>"))
// ... add remaining fields as needed
.finish()
}
}Or use a secret wrapper type to enforce redaction at the type level.
🤖 Prompt for AI Agents
In forester/src/cli.rs around lines 58–60, the prover_api_key field is declared
with #[arg(long, env = "FORESTER_PROVER_API_KEY")] which can expose the secret
via Clap help/error output and the auto-derived Debug; update the arg attribute
to hide environment values (e.g., add hide_env_values = true) so the env value
is not printed, and replace the auto-derived Debug for StartArgs with a manual
Debug implementation that redacts prover_api_key (e.g., display "<redacted>"
when Some) or use a secret wrapper type so the API key is never shown in logs or
help output.
| pub prover_append_url: Option<String>, | ||
| pub prover_update_url: Option<String>, | ||
| pub prover_address_append_url: Option<String>, | ||
| pub prover_api_key: Option<String>, | ||
| pub photon_api_key: Option<String>, |
There was a problem hiding this comment.
Security: ExternalServicesConfig derives Debug and now includes secrets — redact or remove.
ExternalServicesConfig derives Debug while holding prover_api_key and photon_api_key. Any accidental debug log will leak credentials. Redact these in Debug or stop deriving Debug.
Apply a custom Debug impl that redacts secrets:
// Replace: #[derive(Debug, Clone)]
#[derive(Clone)]
pub struct ExternalServicesConfig {
// ... fields unchanged ...
}
// Add this impl nearby
impl std::fmt::Debug for ExternalServicesConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ExternalServicesConfig")
.field("rpc_url", &self.rpc_url)
.field("ws_rpc_url", &self.ws_rpc_url)
.field("indexer_url", &self.indexer_url)
.field("prover_url", &self.prover_url)
.field("prover_append_url", &self.prover_append_url)
.field("prover_update_url", &self.prover_update_url)
.field("prover_address_append_url", &self.prover_address_append_url)
.field("prover_api_key", &"<REDACTED>")
.field("photon_api_key", &"<REDACTED>")
.field("pushgateway_url", &self.pushgateway_url)
.field("pagerduty_routing_key", &self.pagerduty_routing_key)
.field("rpc_rate_limit", &self.rpc_rate_limit)
.field("photon_rate_limit", &self.photon_rate_limit)
.field("send_tx_rate_limit", &self.send_tx_rate_limit)
.finish()
}
}Alternatively, use a secrecy type (e.g., secrecy::SecretString) for keys, which redacts Debug output by default.
🤖 Prompt for AI Agents
In forester/src/config.rs around lines 38-42, ExternalServicesConfig currently
derives Debug while containing prover_api_key and photon_api_key; remove the
Debug derive and either implement a custom std::fmt::Debug that prints all
non-secret fields but replaces prover_api_key and photon_api_key with
"<REDACTED>", or change those two fields to a secrecy wrapper type (e.g.,
secrecy::SecretString) which already redacts Debug output; update the struct
attribute to #[derive(Clone)] and add the custom Debug impl (or change types)
nearby, ensuring any existing uses that relied on the derived Debug are updated
accordingly.
| fn get_prover_api_key() -> Option<String> { | ||
| match TestMode::from_env() { | ||
| TestMode::Local => None, | ||
| TestMode::Devnet => Some(get_env_var("PROVER_API_KEY")), | ||
| } | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Potential env var naming drift: PROVER_API_KEY vs FORESTER_PROVER_API_KEY.
This test uses PROVER_API_KEY, while other parts of the repo/PR (and prior notes) mention FORESTER_PROVER_API_KEY. Inconsistent naming will cause CI/test flakiness across environments.
Run this script to inventory usages and confirm a single, consistent env var name:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Env var references (PROVER_API_KEY | FORESTER_PROVER_API_KEY | PHOTON_API_KEY):"
rg -n -C1 -P 'env::var\("(PROVER_API_KEY|FORESTER_PROVER_API_KEY|PHOTON_API_KEY)"\)'
echo
echo "All occurrences of prover_api_key symbol:"
rg -n -C2 '\bprover_api_key\b'
echo
echo "StartArgs definition and field list (to confirm CLI wiring):"
rg -n -C3 -U 'struct\s+StartArgs\b.*?{' || true
echo
echo "Look for any docs or README references to prover API key to ensure consistency:"
rg -n -C2 -i 'prover api key|PROVER_API_KEY|FORESTER_PROVER_API_KEY|photon api key|PHOTON_API_KEY' || trueLength of output: 27268
Align env var names for prover API key across code, tests, and docs
The CLI is wired to FORESTER_PROVER_API_KEY, but in forester/tests/e2e_test.rs we still call get_env_var("PROVER_API_KEY"). This mismatch (and the equivalent one for PHOTON_API_KEY) will break in CI when only the FORESTER_… vars are set. Update as follows:
• In forester/tests/e2e_test.rs, change get_prover_api_key to use "FORESTER_PROVER_API_KEY":
fn get_prover_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
- TestMode::Devnet => Some(get_env_var("PROVER_API_KEY")),
+ TestMode::Devnet => Some(get_env_var("FORESTER_PROVER_API_KEY")),
}
}• Likewise, in the same file update get_photon_api_key to "FORESTER_PHOTON_API_KEY":
fn get_photon_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
- TestMode::Devnet => Some(get_env_var("PHOTON_API_KEY")),
+ TestMode::Devnet => Some(get_env_var("FORESTER_PHOTON_API_KEY")),
}
}• Update forester/README.md examples to consistently reference FORESTER_PROVER_API_KEY and FORESTER_PHOTON_API_KEY instead of the unprefixed names.
These fixes will ensure the env-var wiring is uniform and tests won’t silently fail in CI.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fn get_prover_api_key() -> Option<String> { | |
| match TestMode::from_env() { | |
| TestMode::Local => None, | |
| TestMode::Devnet => Some(get_env_var("PROVER_API_KEY")), | |
| } | |
| } | |
| // forester/tests/e2e_test.rs | |
| fn get_prover_api_key() -> Option<String> { | |
| match TestMode::from_env() { | |
| TestMode::Local => None, | |
| TestMode::Devnet => Some(get_env_var("FORESTER_PROVER_API_KEY")), | |
| } | |
| } | |
| fn get_photon_api_key() -> Option<String> { | |
| match TestMode::from_env() { | |
| TestMode::Local => None, | |
| TestMode::Devnet => Some(get_env_var("FORESTER_PHOTON_API_KEY")), | |
| } | |
| } |
🤖 Prompt for AI Agents
In forester/tests/e2e_test.rs around lines 124 to 129, the test helper uses the
unprefixed env var names ("PROVER_API_KEY" and similarly "PHOTON_API_KEY") while
the CLI and CI expect the FORESTER_ prefixed names, causing CI failures; update
get_prover_api_key to call get_env_var("FORESTER_PROVER_API_KEY") and update
get_photon_api_key to call get_env_var("FORESTER_PHOTON_API_KEY") accordingly,
then also update forester/README.md examples to reference
FORESTER_PROVER_API_KEY and FORESTER_PHOTON_API_KEY so docs, tests, and CLI use
the same env var names.
| - `CreateMint` action now allows passing a non-payer mint and freeze authority. | ||
| - More efficient computebudgets for actions. | ||
| - Better DX: Parameter lookup in call signatures of CompressedTokenProgram instructions | ||
| - QoL: improved typedocs. |
There was a problem hiding this comment.
Fix minor wording/typos
- “computebudgets” → “compute budgets”
- “typedocs” → “TypeDoc comments”
Apply this diff:
-- More efficient computebudgets for actions.
-— QoL: improved typedocs.
+- More efficient compute budgets for actions.
+- QoL: improved TypeDoc comments.Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 LanguageTool
[grammar] ~3-~3: There might be a mistake here.
Context: ...g a non-payer mint and freeze authority. - More efficient computebudgets for action...
(QB_NEW_EN)
[grammar] ~4-~4: There might be a mistake here.
Context: ...re efficient computebudgets for actions. - Better DX: Parameter lookup in call sign...
(QB_NEW_EN)
🤖 Prompt for AI Agents
In js/compressed-token/CHANGELOG.md around lines 3 to 6, fix the minor
wording/typos: change “computebudgets” to “compute budgets” and change
“typedocs” to “TypeDoc comments” so the bullet list reads with the corrected
terms; update only those words preserving the rest of the lines and punctuation.
| - `selectMinCompressedTokenAccountsForTransfer` and | ||
| `selectMinCompressedTokenAccountsForTransferorPartial` now accept an optional | ||
| `maxInputs` parameter, defaulting to 4. | ||
|
|
There was a problem hiding this comment.
Typo: method name casing
Looks like a stray typo in the method name (“TransferorPartial”). Should be TransferOrPartial to match the casing used elsewhere.
Apply this diff:
- `selectMinCompressedTokenAccountsForTransferorPartial` now accept an optional
+ `selectMinCompressedTokenAccountsForTransferOrPartial` now accept an optional📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - `selectMinCompressedTokenAccountsForTransfer` and | |
| `selectMinCompressedTokenAccountsForTransferorPartial` now accept an optional | |
| `maxInputs` parameter, defaulting to 4. | |
| - `selectMinCompressedTokenAccountsForTransfer` and | |
| `selectMinCompressedTokenAccountsForTransferOrPartial` now accept an optional | |
| `maxInputs` parameter, defaulting to 4. |
🤖 Prompt for AI Agents
In js/compressed-token/CHANGELOG.md around lines 116 to 119, the method name
casing contains a typo "TransferorPartial"; update the text to use the correct
casing "TransferOrPartial" so it matches the rest of the codebase and other
references, i.e., replace "selectMinCompressedTokenAccountsForTransferorPartial"
with "selectMinCompressedTokenAccountsForTransferOrPartial".
| ### Changed | ||
|
|
||
| - `createMint`action now lets you pass tokenprogramId explicitly. is backward compatible with boolean flag for t22. | ||
| - `createMint`action now lets you pass tokenprogramId explicitly. is backward compatible with boolean flag for t22. |
There was a problem hiding this comment.
Fix spacing/casing and sentence capitalization
Minor doc polish.
Apply this diff:
-- `createMint`action now lets you pass tokenprogramId explicitly. is backward compatible with boolean flag for t22.
+- `createMint` action now lets you pass `tokenProgramId` explicitly. This is backward compatible with the boolean flag for t22.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - `createMint`action now lets you pass tokenprogramId explicitly. is backward compatible with boolean flag for t22. | |
| - `createMint` action now lets you pass `tokenProgramId` explicitly. This is backward compatible with the boolean flag for t22. |
🧰 Tools
🪛 LanguageTool
[grammar] ~195-~195: There might be a mistake here.
Context: ...amId explicitly. is backward compatible with boolean flag for t22. ### Deprecated ...
(QB_NEW_EN)
🤖 Prompt for AI Agents
In js/stateless.js/CHANGELOG.md around line 195, the changelog entry has
spacing/casing and sentence-capitalization issues; add a space after the closing
backtick so it reads "`createMint` action", change "tokenprogramId" to
"tokenProgramId" (camelCase), and capitalize the start of the second sentence so
it reads "Is backward compatible..." (or preferably merge into a single sentence
with proper punctuation: "...explicitly and is backward compatible with the
boolean flag for t22.").
Summary by CodeRabbit
New Features
Configuration
Tests
Documentation