You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
data-plane: serve the Native file mutations other than writes - #1373
Adds the Native file mutations other than writes to the data plane's files routes, behind the same SPACE_DATA_PLANE_NATIVE_FILES=serve setting as #1372: files:mkdir, files:remove, files:rename, files:changes_enable, files:changes_disable and files:modified.
Each request follows space-api's handler, in its order:
Authorization from the headers (AuthorizeNativeFileRequest).
The JSON body. The tracking calls read it as space-api's Option<Json<_>> does, so no Content-Type means no body.
The Idempotency-Key check, right after the body, with space-api's messages.
The field checks.
For mkdir, remove and rename, the request's fingerprint, computed with the shared pplx-space-native-files functions and sent with PrepareNativeFileCall. space-api binds the key before it wakes or reaches the sandbox.
The sandbox call on the granted route.
What follows from that:
Changed request: a different request under a bound key gets space-api's 409 idempotency_conflict and never reaches the sandbox.
Rename key: a rename carries the guest key space-api derives in its grant, so a retry on either server is replayed by the same key. A grant without one is answered with a 500 and is not sent.
Change tracking: it checks its key but neither binds nor sends it, as on space-api. files:modified takes no key.
Reconnect: every call reconnects once through a fresh preparation when the node-api drains, and not after a closed connection, as space-api's spaced client does for these unary calls.
No blind retry: failures map through the shared files mapping. For mkdir, remove and tracking, which the sandbox runs without a key, a failure that may have applied the change is not retryable.
cargo arch against main's baseline, renames and ARCHITECTURE.toml: 0 required findings and 112 advisory, the same findings as main.
cargo nextest run --config 'profile.test.package.pplx-space-api.opt-level=0' --all-features --all-targets, one package at a time, with Postgres and Redis from the nextest setup scripts and SPACE_CI_REQUIRE_TEST_DEPS=1: pplx-space-data-plane-server 405 passed; pplx-space-data-plane-svc 7 passed; pplx-space-api 2189 passed, 1 skipped; pplx-space-native-files 2 passed.
The scripted API in these tests binds keys as space-api's handler does: it keeps the first fingerprint per key and refuses a different one with the 409, and derives the guest key with the shared guest_key. Each new test was mutation-checked: I applied the change, rebuilt, saw the test fail, and reverted.
All six answer in space-api's shapes. The sandbox gets space-api's guest requests (exist_ok, missing_ok, roots and globs, window) for the granted sandbox, with the route token. mkdir, remove and rename are prepared with the fingerprint the shared function computes for their body, the others with none. The rename carries the guest key derived from the bound key and that fingerprint
fingerprint over another request; send the client's key instead of the grant's; build files:modified for the placeholder sandbox; require a JSON body for changes_disable
A replay is prepared with the same fingerprint and reaches the sandbox with the same guest key. A changed rename, mkdir or remove is refused with the 409 and never reaches it. A rename granted without a guest key is a 500 and is not sent. A request without its key is never prepared
prepare a rename or a mkdir without its fingerprint; drop the mkdir key check; send a rename without the grant's key
For each of the six: a drain reconnects once, with the same fingerprint on both preparations. A closed connection does not reconnect. The 503 for it is retryable only for rename and modified
reconnect a rename on a closed connection; map unkeyed mutations like keyed ones
each_failure_answers_as_the_api_answers_it (from #1372, 9 new rows)
Missing and invalid keys; the key checked after the body (a 422 wins); tracking enable with enabled: false; two modified filters; a non-RFC3339 since; a mkdir failure that may have applied (not retryable); a mkdir refused before start (retryable, Retry-After: 2); a rename failure (retryable)
drop the key check; check the key before the body; drop the tracking and filter checks; map unkeyed mutations like keyed ones
Not validated here: a real space-api and runtime. The Kind run at PR 11's head covers that.
Severity and risk
Severity: does not apply (new, off by default).
Risk:
With the setting off: nothing changes.
With serve: mutations answered by the data plane bind the same public_idempotency_records rows as space-api, so a retry may land on either server. A wrong fingerprint encoding would turn cross-server retries into 409s. The tests pin the encodings to the shared functions.
Rollback: set the setting to off, or revert this PR.
Stack
This is PR 7 of 12 and is based on data-plane-native-files-read (#1372). Merge order:
Writes: until the next PR lands, serve does not answer files:write or files:write_batch. Route only the operations it answers to the data plane.
Reconnect re-binding: a reconnect prepares again, which renews the same binding with the same fingerprint, where space-api's own reconnect does not bind again. The outcome is the same.
AI assistance: Claude Code drafted the code, tests, and this description; the author reviewed them.
The reason will be displayed to describe this comment to others. Learn more.
Checked mkdir/remove/rename/changes_enable/changes_disable/modified against the space-api handlers: fingerprints are built from the same parsed path/flag/user inputs; the API binds them (and derives the rename guest key) in PrepareNativeFileCall via the forwarded Idempotency-Key; a drain-reconnect re-prepares with the same fingerprint and resends the same guest key. Error mapping (unprotected vs file_call_error) and operation budgets match the API's spaced client. No blocking issues.
Why: The new file-mutation routes change how requests reach sandbox workers. No specific failure is established, but the change warrants moderate merge risk under the repository’s guidance.
Commit: 50c6608046a9.
No actionable comments were generated in the recent review.
Walkthrough
The native file API now routes mkdir, remove, rename, change-tracking, and modified-file requests to sandbox workers. The handlers validate request bodies and idempotency keys, bind fingerprints for keyed mutations, and use operation-specific sandbox budgets. Grants can include a parsed guest replay key. Tests cover request validation, idempotency conflicts, sandbox failures, and draining-node reconnection.
Possibly related PRs
perplexityai/SPACE#1317: Implements Windows guest filesystem operations for mkdir, remove, and rename, including keyed replay and conflict handling.
Merge Risk: Moderate · up to 50c66
The new file-mutation routes change how requests reach sandbox workers. No specific failure is established, but the change warrants moderate merge risk under the repository’s guidance.
Security architecture risk: Low · up to 50c66
The additional mutation routes preserve sandbox authorization and request-binding controls. Rename retains its replay identity, and automatic retries of unkeyed mutations are restricted to requests rejected before execution. No introduced security defect was established, but deployment and recovery coverage is not complete.
Retained concerns
No architecture-level concerns identified.
Security review details
Security Blast Radius
inferred — An admitted caller can mutate paths and tracking state within the granted sandbox using the established guest-user contract. The inspected boundary constrains the target through organization and sandbox ownership checks; the new request body does not select an independent tenant or runtime endpoint.
Trust Boundaries and Controls
observed — Authorization remains with the API rather than moving into data-plane body processing. Both initial authorization and preparation enter the API ownership decision, and draining recovery prepares again before another privileged call. Key binding occurs before runtime access, while rename requires the API-derived replay key.
Resilience and Maintainability Implications
observed — The existing tracking owner uses service-owned serialized updates so caller cancellation cannot reorder acknowledgements. Watch setup publishes under a state lock, rolls back partially registered consumers on failure, and uses a generation fence so disable supersedes pending setup. These mechanisms remain unchanged for the additional callers.
Important
Pre-merge checks failed
Please resolve all errors before merging. Addressing warnings is optional.
Failed checks: 2 inconclusive
Check name
Status
Explanation
Resolution
Description Follows The Pr Template
The available description excerpt contains substantive ## Summary and ## Validation sections. The excerpt is explicitly truncated before the remaining content, so the presence and real content of …
Provide the complete PR description, including the text after the truncated validation table, so the ## Severity and risk and AI assistance: requirements can be checked.
Public-Safe Content
The title and reviewed diff contain no credentials, private keys, internal URLs or hostnames, cloud identifiers, workstation paths, logs, or incident details. The supplied PR description is truncated,…
Provide the complete PR description or rerun the check with the full description available.
Passed checks: 3 passed
Check name
Status
Explanation
Title check
The title starts with the lowercase area "data-plane:" and a lowercase summary. It accurately describes serving Native file mutations other than writes and has no trailing period, ticket ID, or intern…
Bug Fixes Name A Regression Test
PASS. The PR adds previously unserved Native file mutation routes; it does not fix an existing application defect. The Validation section also states that each new test was mutation-checked and names …
Weakened Safeguards Are Justified
No safeguard was weakened. The PR adds mutation tests and assertions, with no changes to CI, lint, guard, allowlist, baseline, or nextest configuration. The only production deletion moves rejected f…
Full details: Title check
Explanation
The title starts with the lowercase area "data-plane:" and a lowercase summary. It accurately describes serving Native file mutations other than writes and has no trailing period, ticket ID, or internal link.
Full details: Bug Fixes Name A Regression Test
Explanation
PASS. The PR adds previously unserved Native file mutation routes; it does not fix an existing application defect. The Validation section also states that each new test was mutation-checked and names tests such as mutations_answer_through_the_granted_route_in_the_apis_shapes and a_changed_request_under_a_bound_key_never_reaches_the_sandbox. The diff adds these tests under crates/.
Full details: Weakened Safeguards Are Justified
Explanation
No safeguard was weakened. The PR adds mutation tests and assertions, with no changes to CI, lint, guard, allowlist, baseline, or nextest configuration. The only production deletion moves rejected from native_files/read.rs to the parent module without changing its implementation; existing read handlers still use it. The fake worker refactor preserves the existing Stat path and adds scripted mutation replies.
Full details: Description Follows The Pr Template
Explanation
The available description excerpt contains substantive ## Summary and ## Validation sections. The excerpt is explicitly truncated before the remaining content, so the presence and real content of ## Severity and risk and the AI assistance: line cannot be verified. The full PR description is not available in the checkout.
Resolution
Provide the complete PR description, including the text after the truncated validation table, so the ## Severity and risk and AI assistance: requirements can be checked.
Full details: Public-Safe Content
Explanation
The title and reviewed diff contain no credentials, private keys, internal URLs or hostnames, cloud identifiers, workstation paths, logs, or incident details. The supplied PR description is truncated, and no complete description is available in the checkout or Git metadata. This check also covers the description, so the omitted text cannot be verified.
Resolution
Provide the complete PR description or rerun the check with the full description available.
Tip
🎯 Customize your risk assessments
Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.
✅ Automatic approvals, with your rules
Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.
Recent review info
Automatic approval policy
Commit: 50c6608046a9.
Setting
Effective value
Source
Automatic approvals
Enabled
Global configuration
Merge risk
Low
Override 2
Security risk
Not set
Global configuration
Matching overrides (numbered as in the resolved configuration):
Any matching disabled override withholds approval, regardless of risk. Otherwise, the strictest explicitly set limit wins for each score. Limits omitted by all matching overrides inherit the global configuration.
Not set means no limit was configured after inheritance. Use @coderabbitai configuration to inspect the resolved settings and their sources.
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.
Add files:mkdir, files:remove, files:rename, files:changes_enable,
files:changes_disable and files:modified to the data plane's Native
files routes, in the steps and order of space-api's handlers:
- the JSON body (Option<Json> for the tracking calls);
- the Idempotency-Key check;
- the field checks;
- for mkdir, remove and rename, the shared pplx-space-native-files
fingerprint, sent with PrepareNativeFileCall so space-api binds the
key before anything reaches the sandbox.
A changed request under a bound key is refused with space-api's 409 and
never reaches the sandbox. The rename carries the guest key space-api
derives in its grant; a grant without one is a 500 and is not sent.
Change tracking checks its key but neither binds nor sends it, as on
space-api.
Every call reconnects once through a fresh preparation when the node-api
drains, and not after a closed connection, as space-api's spaced client
does. A failure that may have applied an unkeyed mutation (mkdir,
remove, tracking) does not invite a retry.
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
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
Adds the Native file mutations other than writes to the data plane's files routes, behind the same
SPACE_DATA_PLANE_NATIVE_FILES=servesetting as #1372:files:mkdir,files:remove,files:rename,files:changes_enable,files:changes_disableandfiles:modified.Each request follows space-api's handler, in its order:
AuthorizeNativeFileRequest).Option<Json<_>>does, so noContent-Typemeans no body.Idempotency-Keycheck, right after the body, with space-api's messages.pplx-space-native-filesfunctions and sent withPrepareNativeFileCall. space-api binds the key before it wakes or reaches the sandbox.What follows from that:
idempotency_conflictand never reaches the sandbox.files:modifiedtakes no key.Write and write_batch are the next PR.
Validation
At this head (
2947d368), onmainat0271415a:git range-diffreports it identical).cargo fmt --all -- --check,scripts/generate-env-contract.sh --check,scripts/check-rust-error-policy.shandscripts/source_guards/env_test_hook_boundary.pypass.cargo clippy --locked --all-targets --all-features -p pplx-space-data-plane-server -- -D warningspasses.cargo check --workspace --all-targets --lockedpasses.cargo archagainstmain's baseline, renames andARCHITECTURE.toml: 0 required findings and 112 advisory, the same findings asmain.cargo nextest run --config 'profile.test.package.pplx-space-api.opt-level=0' --all-features --all-targets, one package at a time, with Postgres and Redis from the nextest setup scripts andSPACE_CI_REQUIRE_TEST_DEPS=1:pplx-space-data-plane-server405 passed;pplx-space-data-plane-svc7 passed;pplx-space-api2189 passed, 1 skipped;pplx-space-native-files2 passed.The scripted API in these tests binds keys as space-api's handler does: it keeps the first fingerprint per key and refuses a different one with the 409, and derives the guest key with the shared
guest_key. Each new test was mutation-checked: I applied the change, rebuilt, saw the test fail, and reverted.mutations_answer_through_the_granted_route_in_the_apis_shapesexist_ok,missing_ok, roots and globs, window) for the granted sandbox, with the route token. mkdir, remove and rename are prepared with the fingerprint the shared function computes for their body, the others with none. The rename carries the guest key derived from the bound key and that fingerprintfiles:modifiedfor the placeholder sandbox; require a JSON body forchanges_disablea_changed_request_under_a_bound_key_never_reaches_the_sandboxeach_mutation_reconnects_only_when_the_node_api_drainseach_failure_answers_as_the_api_answers_it(from #1372, 9 new rows)enabled: false; two modified filters; a non-RFC3339since; a mkdir failure that may have applied (not retryable); a mkdir refused before start (retryable,Retry-After: 2); a rename failure (retryable)Not validated here: a real space-api and runtime. The Kind run at PR 11's head covers that.
Severity and risk
Severity: does not apply (new, off by default).
Risk:
serve: mutations answered by the data plane bind the samepublic_idempotency_recordsrows as space-api, so a retry may land on either server. A wrong fingerprint encoding would turn cross-server retries into 409s. The tests pin the encodings to the shared functions.off, or revert this PR.Stack
This is PR 7 of 12 and is based on
data-plane-native-files-read(#1372). Merge order:data-plane-native-files-writedata-plane-native-files-drainkind-native-files-data-planesmoke-native-files-data-planedocs-native-files-data-planeNot covered
servedoes not answerfiles:writeorfiles:write_batch. Route only the operations it answers to the data plane.AI assistance: Claude Code drafted the code, tests, and this description; the author reviewed them.