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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions