Skip to content

fix(policy): advance sandbox resource version on every policy revision - #4108

Closed
jayasri-88 wants to merge 1 commit into
NVIDIA:mainfrom
jayasri-88:fix/4062-policy-revision-resource-version/jayasri-88
Closed

jayasri-88 wants to merge 1 commit into
NVIDIA:mainfrom
jayasri-88:fix/4062-policy-revision-resource-version/jayasri-88

Conversation

@jayasri-88

Copy link
Copy Markdown

Summary

put_policy_revision_atomic committed a new policy revision without advancing the sandbox's resource_version whenever the projection was a no-op (unchanged annotations, no backfill, or identical policy content). Because expected_resource_version is the optimistic-concurrency precondition, a later writer holding the pre-revision value could still commit policy content derived from an already-superseded read. Both backends now always perform the CAS-guarded sandbox row update, so every committed revision invalidates any earlier resource-version precondition.

Related Issue

Closes #4062

Changes

  • crates/openshell-server/src/persistence/sqlite.rs: put_policy_revision_atomic always runs the WHERE resource_version = ?4 CAS-guarded update, incrementing resource_version and refreshing updated_at_ms, and returns PersistenceError::Conflict on zero affected rows.
  • crates/openshell-server/src/persistence/postgres.rs: equivalent unconditional CAS-guarded update on the FOR UPDATE-locked row.
  • The projection-change boolean is no longer used to gate the update. The projection itself is unchanged, so backfill and annotation semantics are identical.
  • expected_resource_version = 0 still skips the precondition comparison, but now also advances the version.
  • Non-atomic put_policy_revision and global policy-revision behavior are untouched.

Testing

  • Checks appropriate to the affected code and behavior pass
  • Unit tests added/updated (if applicable)
  • E2E tests added/updated (if applicable)

Verification performed on Windows with Rust 1.95.0:

  • cargo fmt --all -- --check — clean.
  • cargo test -p openshell-server --lib --features prebuilt-z3 — 1871 passed, 0 failed, 8 ignored.
  • cargo clippy -p openshell-server --lib --tests --features prebuilt-z3 — exit 0, no findings in persistence/. The remaining warnings are pre-existing Windows-only lints in credentials.rs, compute/mod.rs, and openshell-extension-core, and are unrelated to this change.

Regression tests added in crates/openshell-server/src/persistence/tests.rs, one per acceptance criterion:

  • policy_atomic_write_advances_resource_version_without_projection_change — empty policy, no backfill, empty annotations still bumps the version and refreshes updated_at_ms.
  • policy_atomic_write_advances_resource_version_with_identical_backfill_policy — re-submitting the policy the sandbox is already running still bumps the version.
  • policy_atomic_write_with_zero_expected_version_still_advances — unconditional write (expected_resource_version = 0) still bumps the version.
  • policy_atomic_write_rejects_stale_expected_resource_version — a second writer using the previous nonzero version gets Conflict.
  • policy_atomic_write_succeeds_after_rereading_resource_version — re-reading permits a legitimate retry.
  • policy_atomic_write_rolls_back_sandbox_when_revision_insert_conflicts — extended to assert the sandbox version, the latest policy revision, and the absent conflicting policy row are all rolled back.

All five version-advancement tests were confirmed to fail against the unpatched implementation and pass with the fix.

PostgreSQL was updated for semantic parity but, as in the issue report, was not exercised against a live PostgreSQL instance; the test suite here runs on in-memory SQLite.

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable — no public API, config, or user-facing behavior change; the existing protobuf contract already specifies ABORTED on a version mismatch)

put_policy_revision_atomic skipped the sandbox row update whenever the
policy projection was a no-op, leaving resource_version unchanged even
though a new revision was committed. Callers pass resource_version as the
optimistic concurrency precondition on the next write, so a stale holder
of the pre-revision value could still commit policy content derived from
a read that had already been superseded.

Both the SQLite and PostgreSQL implementations now always perform the
CAS-guarded sandbox update, so every committed revision bumps
resource_version and updated_at_ms. expected_resource_version = 0 still
skips the precondition check while still advancing the version.

Closes NVIDIA#4062

Signed-off-by: jayasri-88 <jayasrimunnaluri@gmail.com>
@copy-pr-bot

copy-pr-bot Bot commented Oct 2, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

All contributors have signed the DCO ✍️ ✅
Posted by the DCO Assistant Lite bot.

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

Thank you for your interest in contributing to OpenShell, @jayasri-88.

This project uses a vouch system for first-time contributors. Before submitting a pull request, you need to be vouched by a maintainer.

To get vouched:

  1. Open a Vouch Request discussion.
  2. Describe what you want to change and why.
  3. Write in your own words — do not have an AI generate the request.
  4. A maintainer will comment /vouch if approved.
  5. Once vouched, open a new PR (preferred) or reopen this one after a few minutes.

See CONTRIBUTING.md for details.

@github-actions github-actions Bot closed this Oct 2, 2026
@jayasri-88

Copy link
Copy Markdown
Author

I have read the DCO document and I hereby sign the DCO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(policy): advance sandbox resource version for every policy revision

1 participant