Skip to content

Native entry: withResult omits onException, bulk ops match FFI results positionally without a guard #746

Description

@coderdan

Summary

Two latent flaws that #741 fixed for @cipherstash/stack/wasm-inline remain on the native entry, where the same code shapes exist unguarded.

Raised as finding 11/15 in the review of #741.

1. No withResult call site passes onException

Already tracked in #743 for the whole repo — repeated here only because it is one of the two things #741 fixed locally and left unfixed natively. A non-Error rejection still becomes Error("Something went wrong") in packages/stack/src/encryption/operations/* and packages/protect/src/ffi/operations/*.

2. Native bulk ops match FFI results positionally, unguarded

packages/stack/src/encryption/operations/bulk-decrypt.ts and its siblings pair FFI results to inputs by index with no length assertion. A short response makes decryptResult undefined, and:

// bulk-decrypt.ts:49
if ('error' in decryptResult) {

throws TypeError: Cannot use 'in' operator ... undefined — a bewildering error that names nothing about the real problem. The WASM entry now fails closed here with a message naming the counts (assertBatchLength).

3. Divergent partial-failure contract between the two entries

Native bulkDecrypt returns per-item { id, data } / { id, error }, preserving partial success. The WASM one collapses any failure into a single { failure } listing every bad index. Same operation name, different contracts — worth a deliberate decision rather than an accident of two implementations.

Suggested shape

Hoist the three helpers #741 added — toError, toFailure, assertBatchLength — into @/encryption/helpers and use them from both entries, so the guarantees are shared rather than re-derived. That also removes the risk of the next batch method on either side omitting the length assert.

Not urgent

Nothing here is a live incident: the FFI does not currently return short batches, and non-Error rejections are rare on the native path (protect-ffi throws real ProtectError instances there — unlike the WASM build, which ships no error class, which is why #741 hit it first).

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    SDKbugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions