-
Notifications
You must be signed in to change notification settings - Fork 131
feat(api-public): expose actor kv api #3410
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
3 Skipped Deployments
|
PR Review: Expose Actor KV APII've reviewed this PR that exposes the actor key-value API through both the public and peer APIs. Here's my feedback: ✅ Strengths
🔍 Issues & Concerns1. URL Encoding Vulnerability (Critical)// api-public/src/actors/kv_get.rs:68
&format\!("/actors/{}/kv/keys/{}", path.actor_id, path.key)Problem: The Fix: URL-encode the key parameter: &format\!("/actors/{}/kv/keys/{}", path.actor_id, urlencoding::encode(&path.key))2. Inconsistent Field Naming (Medium)// api-peer/src/actors/kv_get.rs:63
update_ts: metadata[0].create_ts,Problem: The response field is named Options:
Recommendation: Rename to pub struct KvGetResponse {
pub value: String,
pub updated_at: i64, // or created_at
}3. Missing Structured Logging (Medium)The code lacks logging statements. Per CLAUDE.md guidelines: // Add to api-peer/src/actors/kv_get.rs after line 42
tracing::info\!(?path.actor_id, key_len=?path.key.len(), "fetching kv entry");
// Add after line 54
tracing::warn\!(?path.actor_id, ?key_bytes, "kv key not found");Note: Use structured logging with 4. Authorization Gaps (High)The public API ( // api-peer should verify actor access
let actors_res = ctx
.op(pegboard::ops::actor::get::Input {
actor_ids: vec\![path.actor_id],
})
.await?;
let actor = actors_res
.actors
.into_iter()
.next()
.ok_or_else(|| pegboard::errors::Actor::NotFound.build())?;
// Optional: verify namespace if provided via query paramRisk: Any authenticated user could read KV data from any actor, regardless of namespace ownership. 5. Missing Input Validation
6. Performance: Unnecessary Clone (Low)// api-peer/src/actors/kv_get.rs:51
actor_kv::get(&*udb, path.actor_id, vec\![key_bytes.clone()]).await?;The actor_kv::get(&*udb, path.actor_id, vec\![key_bytes]).await?;📝 Additional Recommendations
SummaryThis PR has good structure and follows most project conventions, but has critical security and correctness issues that should be addressed before merging: Must Fix:
Should Fix:
Nice to Have:
|
More templates
@rivetkit/actor
@rivetkit/cloudflare-workers
@rivetkit/core
@rivetkit/db
@rivetkit/framework-base
@rivetkit/next-js
@rivetkit/react
rivetkit
@rivetkit/sql-loader
@rivetkit/engine-runner
@rivetkit/engine-runner-protocol
commit: |
a3b30a7 to
3c5d900
Compare
4f3a2a9 to
42bf4e8
Compare
PR Review: feat(api-public): expose actor kv apiThank you for this PR! Overall, the implementation looks solid and follows the codebase conventions well. Here are my findings: ✅ Strengths
🔴 Critical Issues1. Missing Authorization Check (Security)The Current code (api-peer/src/actors/kv_get.rs:42-65): pub async fn kv_get(ctx: ApiCtx, path: KvGetPath, _query: KvGetQuery) -> Result<KvGetResponse> {
// Decode base64 key
let key_bytes = BASE64_STANDARD
.decode(&path.key)
.context("failed to decode base64 key")?;
// Get the KV value - NO AUTHORIZATION CHECK\!
let udb = ctx.pools().udb()?;
let (keys, values, metadata) =
actor_kv::get(&*udb, path.actor_id, vec\![key_bytes.clone()]).await?;Recommendation: Add authorization similar to // Get the actor first to verify it exists
let actors_res = ctx
.op(pegboard::ops::actor::get::Input {
actor_ids: vec\![path.actor_id],
})
.await?;
let actor = actors_res
.actors
.into_iter()
.next()
.ok_or_else(|| pegboard::errors::Actor::NotFound.build())?;
// Optionally verify namespace if needed for authorizationThis ensures that:
2. URL Encoding Issue (Potential Bug)The key is passed as a path parameter and expected to be base64-encoded. However, base64 strings can contain Problem: A key like Options:
Recommendation: Use base64url encoding for URL safety: use base64::prelude::BASE64_URL_SAFE_NO_PAD;
let key_bytes = BASE64_URL_SAFE_NO_PAD
.decode(&path.key)
.context("failed to decode base64 key")?;
|
Code Review for PR #3410: feat(api-public): expose actor kv apiI've reviewed this PR which adds a new KV get endpoint to expose actor key-value storage through both the public and peer APIs. Here's my feedback: ✅ Positive Aspects
🔍 Issues & Concerns1. CRITICAL: Missing namespace validation in peer API
|
42bf4e8 to
da963b1
Compare
3c5d900 to
290e897
Compare
Code Review for PR #3410Thank you for implementing the Actor KV API! Here's my detailed review: ✅ Strengths
🐛 Potential Issues1. Critical: Index out of bounds risk (api-peer/src/actors/kv_get.rs:59-63)// Current code:
if keys.is_empty() {
return Err(pegboard::errors::Actor::KvKeyNotFound.build());
}
let value_base64 = BASE64_STANDARD.encode(&values[0]);
Ok(KvGetResponse {
value: value_base64,
update_ts: metadata[0].create_ts,
})Problem: While you check if Recommendation: Add assertions or validate all three arrays: if keys.is_empty() {
return Err(pegboard::errors::Actor::KvKeyNotFound.build());
}
// Ensure consistency
ensure\!(
values.len() == 1 && metadata.len() == 1,
"inconsistent KV response: expected 1 key, value, and metadata"
);
let value_base64 = BASE64_STANDARD.encode(&values[0]);
Ok(KvGetResponse {
value: value_base64,
update_ts: metadata[0].create_ts,
})2. Misleading field name (api-peer/src/actors/kv_get.rs:26)The field is named Options:
3. Missing authorization checkThe endpoint doesn't verify that the authenticated user has permission to access this actor's KV data. Compare with Recommendation: Add namespace validation: // Get actor to verify it exists and belongs to the correct namespace
let actors_res = ctx.op(pegboard::ops::actor::get::Input {
actor_ids: vec\![path.actor_id],
}).await?;
let actor = actors_res.actors.into_iter().next()
.ok_or_else(|| pegboard::errors::Actor::NotFound.build())?;
// Verify namespace if provided (or always require it)
// ... namespace validation logic ...4. Missing structured loggingPer CLAUDE.md guidelines, the logging should include structured parameters: #[tracing::instrument(skip_all, fields(actor_id = %path.actor_id, key_len = path.key.len()))]And if you add debug logging, use: tracing::debug\!(?actor_id, key_len = key_bytes.len(), "fetching kv value");🔍 Questions & Considerations5. URL encoding concerns (api-public/src/actors/kv_get.rs:68)When forwarding to remote datacenters: &format\!("/actors/{}/kv/keys/{}", path.actor_id, path.key)If Recommendation: Use URL encoding: use urlencoding::encode;
&format\!("/actors/{}/kv/keys/{}", path.actor_id, encode(&path.key))6. Performance: unnecessary clone (api-peer/src/actors/kv_get.rs:51)let (keys, values, metadata) =
actor_kv::get(&*udb, path.actor_id, vec\![key_bytes.clone()]).await?;The 📝 Minor Improvements7. OpenAPI documentationThe OpenAPI spec is missing:
8. Missing testsNo test coverage was added. Consider adding:
🎯 SummaryMust Fix:
Should Fix:
Nice to Have:
Overall, this is a solid implementation that follows the codebase patterns well. The main concerns are around safety (array indexing) and security (authorization). 🤖 Generated with Claude Code |
PR Review: feat(api-public): expose actor kv apiThis PR adds a GET endpoint to retrieve KV values for actors through both the public and peer APIs. Overall, the implementation is well-structured and follows existing patterns in the codebase. Here are my findings: ✅ Strengths
🔍 Potential Issues1. Inconsistent Field Naming (Minor)
The response uses
Recommendation: Either rename the field to 2. Missing Authorization Check in Peer API (Security)
The peer API endpoint lacks any authorization checks. While peer APIs are typically called from trusted sources (the public API layer), there's no validation that:
Compare with Recommendation: Add namespace ownership validation in the peer API similar to other actor operations. 3. Array Index Without Bounds Check (Safety)
After checking let value_base64 = BASE64_STANDARD.encode(&values[0]);
// ...
update_ts: metadata[0].create_ts,Recommendation: Add assertions or length checks for defensive programming: ensure!(
keys.len() == values.len() && keys.len() == metadata.len(),
"KV response length mismatch"
);4. Unnecessary Clone (Performance)
The code clones actor_kv::get(&*udb, path.actor_id, vec![key_bytes.clone()]).await?;Since Recommendation: Remove actor_kv::get(&*udb, path.actor_id, vec![key_bytes]).await?;5. Missing Documentation (Documentation)Neither the peer nor public endpoint includes documentation about:
Recommendation: Add doc comments explaining the encoding requirements and link to relevant constraints from 📝 Minor Observations
🧪 Test CoverageI didn't see any tests added for this new endpoint. Consider adding:
📊 SummaryRisk Level: Medium Priority Fixes:
Nice to Have:
|
9624b78 to
9b70310
Compare
7d62e3b to
2294806
Compare
9b70310 to
83a610d
Compare
PR Review: feat(api-public): expose actor kv apiSummaryThis PR exposes the actor KV (key-value) storage API through both the peer and public API endpoints, allowing clients to retrieve KV values stored for actors. The implementation follows the datacenter-aware routing pattern used in other endpoints. ✅ Strengths
🔍 Issues & Recommendations1. Critical: URL encoding issue in remote datacenter requests// api-public/src/actors/kv_get.rs:68
&format!("/actors/{}/kv/keys/{}", path.actor_id, path.key),Problem: The Fix: URL-encode the key parameter: &format!("/actors/{}/kv/keys/{}", path.actor_id, urlencoding::encode(&path.key))Or better yet, use the key from the path which is already URL-encoded by axum. 2. Inconsistent naming:
|
Pull Request Review: Actor KV API ExposureSummaryThis PR exposes the Actor KV (key-value) storage API through the public and peer APIs, enabling external access to actor key-value data. The implementation follows established patterns in the codebase for distributed datacenter routing. Code Quality & Best Practices✅ Strengths
Issues & Concerns🔴 Critical Issues1. Incorrect Timestamp Field Name (api-peer/src/actors/kv_get.rs:63)update_ts: metadata[0].create_ts,Problem: The response field is named Impact: This is misleading API design - the field name suggests it tracks updates, but it actually only tracks creation. Recommendation: Either:
2. Missing Namespace Authorization (api-peer/src/actors/kv_get.rs:42-65)pub async fn kv_get(ctx: ApiCtx, path: KvGetPath, _query: KvGetQuery) -> Result<KvGetResponse> {
// No namespace verification!
let udb = ctx.pools().udb()?;
let (keys, values, metadata) =
actor_kv::get(&*udb, path.actor_id, vec![key_bytes.clone()]).await?;Problem: Unlike other peer endpoints (e.g., Security Risk: HIGH - Unauthorized access to actor data Fix Required: Add namespace verification similar to other endpoints: // Resolve namespace to verify actor belongs to it
let namespace = ctx
.op(namespace::ops::resolve_for_name_global::Input {
name: query.namespace.clone(),
})
.await?
.ok_or_else(|| namespace::errors::Namespace::NotFound.build())?;
// Then verify actor belongs to namespace via actor::get operation3. Potential Index Out of Bounds (api-peer/src/actors/kv_get.rs:59, 63)let value_base64 = BASE64_STANDARD.encode(&values[0]);
// ...
update_ts: metadata[0].create_ts,Problem: After checking Recommendation: Add assertion or explicit length check: ensure!(
values.len() == 1 && metadata.len() == 1,
"unexpected kv get response length"
);
|
83a610d to
a9a9e7c
Compare
PR Review: feat(api-public): expose actor kv apiThank you for this PR! Overall, the implementation looks solid and follows the codebase patterns well. Here are my findings: Code Quality & Best Practices ✅Strengths:
Issues:
Potential Bugs & Issues
|
Merge activity
|

No description provided.