Skip to content

test(python): verify the two engine facts the spec depends on (#1384) - #1414

Merged
yujiyokoo merged 2 commits into
feat/python-sdk-cifrom
feat/python-sdk-gate-facts
Nov 13, 2026
Merged

yujiyokoo merged 2 commits into
feat/python-sdk-cifrom
feat/python-sdk-gate-facts

Conversation

@yujiyokoo

Copy link
Copy Markdown
Contributor

Summary

The Python SDK spec (#1341) depends on two facts about the engine that nobody had checked. This PR checks both, with a probe for each, and records the results in languages/python/docs/gate-facts/. Both facts hold. No SDK code changes, and the normal wheel build is unchanged.

The engine is the Rust crate stack-encrypt. The engine encrypts and decrypts. The extension is the Rust code compiled into the Python package. Python calls the extension, and the extension calls the engine.

  • Fact 1: the extension can read the record the engine returns after decrypting, and find each field's type. The extension needs only the engine's public API.
  • Fact 2: a Ctrl-C (KeyboardInterrupt) during an engine call is raised only after the call finishes. Also, a request object (Pending) that is dropped early wipes the plaintext it contains.

Changes

  • crates/core/tests/gate_frame_reader.rs: the probe for fact 1. A reader written outside the engine walks a record and records each field's type.
  • crates/engine/src/lib.rs and crates/engine/Cargo.toml: the probe for fact 2. A function that blocks with Python's global interpreter lock (GIL) released, behind a new cargo feature, gate-probe. The feature is off by default, so the function is not in a normal wheel.
  • tests/test_gate_keyboard_interrupt.py: sends Ctrl-C during that call. The tests skip themselves when the feature is not built.
  • docs/gate-facts/frame-reader.md and docs/gate-facts/keyboard-interrupt.md: the findings, how to run each probe again, and what was not tested.
  • Cargo.lock: one line, for tokio as an optional dependency of the probe feature.

Verification

All of this was run on macOS 14 (arm64) with Python 3.14.7:

  • cargo test --locked -p stackencrypt-core --test gate_frame_reader: 2 passed.
  • The Ctrl-C probe, built with --features gate-probe: 2 passed. Ctrl-C was sent 0.2 seconds into a 1-second call. The interrupt was raised after 1.01 seconds. As a control, the same signal interrupted a plain Python time.sleep(1.0) after 0.21 seconds.
  • mise run test: 4 passed and 2 skipped. The 2 skipped tests are the probe tests, in a normal build.
  • mise run test:cargo and cargo fmt --check: both pass.
  • cargo clippy -D warnings, with and without the probe feature: passes.
  • pnpm run test:scripts on Node 22: 83 of 83 test files pass.

Not tested:

  • Linux and Windows were not run for the Ctrl-C probe.
  • The Ctrl-C probe blocks on a tokio sleep, not on a real engine call.
  • The wipe in fact 2 comes from reading the source. Nothing was run for it.
  • CI has not run on this branch yet.

Related

Closes #1384. Refs #1341 (the spec). Stacked on #1406.

Review notes

Start with the two files in docs/gate-facts/. Each one says what was checked, how, and what was not.

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 909bd36

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI; Enforced overrides: Organization
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7e662b2d-220d-46ee-bc56-322ab65731c3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review

yujiyokoo and others added 2 commits November 5, 2026 00:17
The spec in #1341 depends on two facts that had not been checked. The
first is that the extension can read the engine's decrypted record
frame with the public stack-encrypt API. The second is the sync
contract: an interrupt waits for a GIL-released call, and a dropped
Pending wipes its plaintext.

Both facts hold. A Sink written outside the engine reads the frame. A
probe function behind an off-by-default cargo feature is sent SIGINT
during the call. The interrupt arrives after the call returns. The wipe
is from source reading only.

The issue's wording of the first fact is corrected: a sealed value's
kind is inside its encryption, so the kind is read after decrypting.

The findings, how to run each probe again, and what was not tested are
in languages/python/docs/.

Refs #1384

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
)

The codes follow the amendment on #1341.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@yujiyokoo
yujiyokoo force-pushed the feat/python-sdk-gate-facts branch from eeab4bd to 909bd36 Compare November 4, 2026 15:24
@yujiyokoo
yujiyokoo marked this pull request as ready for review November 10, 2026 00:40
@yujiyokoo
yujiyokoo requested a review from a team as a code owner November 10, 2026 00:40

@cipherstash-agent cipherstash-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review attestation

Reviewed 909bd36 · posted from Claude Code · claude-sonnet-5-5 · effort medium
Sources: code-review · claude-sonnet-5-5
Skills: code-review, review-cross-check, review-post

Findings (3): 0 critical, 0 major, 3 minor — 3 inline, 0 below.

Verified against the PR diff and the head file content only; the engine source was not available in this session, so two further candidate findings (frame passthrough round trip, maturin feature merge) were not confirmed and are not posted.

Source: code-review · claude-sonnet-5-5


Generated by Claude Code

@cipherstash-bot cipherstash-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommendation: 🟡 merge after changes

Change before merging: the frame reader probe must cover a typed null and a sequence, and the SIGINT timer in the Python test must be cancelled in a finally block. The other points can wait.

Other findings not posted as comments

  • languages/python/tests/test_gate_keyboard_interrupt.py:30: the tests assume SIGINT raises KeyboardInterrupt. If the launcher ignores SIGINT, both tests fail with DID NOT RAISE. Install signal.default_int_handler in a fixture and restore it afterwards.
  • languages/python/tests/test_gate_keyboard_interrupt.py:21: no CI job builds with gate-probe, so the tests always skip in CI. Add a CI step that builds with the feature and fails when the tests skip.
  • languages/python/docs/gate-facts/keyboard-interrupt.md:12: part 2 of fact 2 (a dropped Pending wipes its plaintext) has no executable test. The doc already says so. Add a heap-hygiene test beside packages/stack-encrypt/tests/heap_hygiene.rs.
  • languages/python/crates/engine/src/lib.rs:32: the probe builds a new tokio runtime on each call and panics if the build fails. Optional: keep one runtime in a OnceLock and return a PyResult.
  • languages/python/crates/core/tests/gate_frame_reader.rs:201: the malformed-frame test checks only truncation. Optional: add a case for trailing bytes and an empty buffer.
How this review was made
Agent Model Review type Result
claude claude-opus-5-5 test-gap 2 found, 1 posted
claude claude-opus-5-5 rust 3 found, 2 posted
claude claude-opus-5-5 python 2 found, 0 posted
claude claude-opus-5-5 infracode 0 found, 0 posted
codex gpt-5.6-terra test-gap 1 found, 0 posted
codex gpt-5.6-terra rust 0 found, 0 posted
codex gpt-5.6-terra python 1 found, 1 posted
codex gpt-5.6-terra infracode 0 found, 0 posted

Synthesis: claude-sonnet-5-5 merged the findings, removed duplicates and dropped findings it could not confirm in the code. 0 posted finding(s) were raised by two or more models.

Plain language: the reader test did not run; only the word-and-shape check was applied.

Stack: position 3 of 15 (#1405, #1406, *️⃣ #1414, #1415, #1433, #1437, #1453, #1499, #1509, #1510, #1511, #1513, #1516, #1517, #1582). *️⃣ marks this pull request.

Context loaded: the description, 2 linked issue(s) and 6 discussion entries.

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.

3 participants