Skip to content

Bump @cipherstash/auth to 0.41 and migrate to Result API#568

Merged
coderdan merged 8 commits into
mainfrom
chore/bump-auth-0.41
Jul 8, 2026
Merged

Bump @cipherstash/auth to 0.41 and migrate to Result API#568
coderdan merged 8 commits into
mainfrom
chore/bump-auth-0.41

Conversation

@coderdan

@coderdan coderdan commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Closes #567.

What

Bumps @cipherstash/auth (and its 6 per-platform native bindings) from 0.40.0 → 0.41.0 and migrates @cipherstash/stack, the stash CLI, and @cipherstash/wizard to its new API.

Why it's not just a version bump

@cipherstash/auth 0.41 is a breaking release: every fallible auth operation now returns a @byteslice/result Result<T, AuthFailure> ({ data } on success, { failure } on error) instead of throwing, and the AuthError type is renamed to AuthFailure — a discriminated union keyed by .type ("NOT_AUTHENTICATED", "WORKSPACE_MISMATCH", …) that replaces the old error.code string. Consumers branch on if (result.failure) / failure.type rather than try/catch.

Changes

@cipherstash/stack (breaking type surface — minor)

  • Public re-export AuthErrorAuthFailure (AuthErrorCode / TokenResult unchanged)
  • WASM-inline resolveStrategy unwraps the Result from AccessKeyStrategy.create; a construction failure throws a descriptive [encryption] error naming the AuthFailure.type

stash (CLI) (patch)

  • auth login device-code flow + bindClientDevice, and the init existing-auth check, unwrap Result

@cipherstash/wizard (patch)

  • Gateway token fetch, agent access-token helper, and the credential prerequisite check (error.codefailure.type)

Catalog + tests

  • Bump auth + 6 bindings 0.40.00.41.0 in pnpm-workspace.yaml and root package.json; lockfile updated
  • Auth mocks/stubs updated to the Result shape
  • Changeset added

Verification

  • turbo build green for @cipherstash/stack, stash, @cipherstash/wizard
  • stash 334/334, @cipherstash/wizard 140/140, stack offline auth tests 40/40
  • Remaining stack integration-test failures require a live ZeroKMS workspace profile (~/.cipherstash/...) and are unrelated to this change

Note: the AuthErrorAuthFailure rename is a breaking change to @cipherstash/stack's public types, graded minor per the repo's 0.x convention.

Summary by CodeRabbit

  • New Features
    • WASM inline configuration now standardizes on authStrategy (with the older strategy kept as a deprecated alias).
  • Bug Fixes
    • Updated device-code login and token acquisition to correctly handle Result-style success/failure, with clearer errors and consistent exit behavior.
    • Improved auth detection/missing-credentials handling during setup/prompt flows.
    • Enhanced runtime validation when auth strategy and access-key options conflict.
  • Breaking Changes
    • Public auth error type naming was updated to AuthFailure.
  • Documentation
    • Updated WASM inline examples to use authStrategy.

@coderdan
coderdan requested a review from a team as a code owner July 7, 2026 02:52
@changeset-bot

changeset-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 722408f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 8 packages
Name Type
@cipherstash/stack Minor
@cipherstash/wizard Patch
stash Patch
@cipherstash/bench Patch
@cipherstash/prisma-next Patch
@cipherstash/basic-example Patch
@cipherstash/prisma-next-example Patch
@cipherstash/e2e Patch

Not sure what this means? Click here to learn what changesets are.

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

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 66be236c-fa5b-474c-b947-49f0d046ca86

📥 Commits

Reviewing files that changed from the base of the PR and between f9fd3f8 and 722408f.

📒 Files selected for processing (1)
  • packages/stack/__tests__/wasm-inline-strategy.test.ts

📝 Walkthrough

Walkthrough

This PR updates stack, CLI, and wizard auth flows for @cipherstash/auth 0.41 Result returns, renames the stack auth export to AuthFailure, and standardizes wasm-inline configuration on authStrategy with a deprecated strategy alias.

Changes

wasm-inline authStrategy config and resolveStrategy

Layer / File(s) Summary
Config type and docs
packages/stack/src/wasm-inline.ts
Documentation and WasmClientConfig now center on authStrategy, keep strategy as a deprecated alias, and describe the Result-wrapped token flow.
Warning latch and strategy resolution
packages/stack/src/wasm-inline.ts
resolveStrategy() warns once for config.strategy, prefers authStrategy, enforces exclusivity with accessKey, and unwraps AccessKeyStrategy.create() results.
Public re-export and stack tests
packages/stack/src/index.ts, packages/stack/package.json, packages/stack/__tests__/*, packages/stack/__tests__/helpers/*
The stack auth re-export switches to AuthFailure, protect-ffi is bumped, and wasm-inline mocks/tests are updated for Result shapes and warning behavior.

@cipherstash/auth 0.41 Result API migration

Layer / File(s) Summary
Version pins and changeset
.changeset/stack-auth-0-41-result-api.md, pnpm-workspace.yaml, e2e/wasm/deno.json
Auth package versions and inline import paths are updated, and the changeset documents the Result API migration and related surface changes.
CLI login and init Result handling
packages/cli/src/commands/auth/login.ts, packages/cli/src/commands/init/steps/authenticate.ts
The CLI login, device binding, and init auth detection paths now branch on Result failures and data.
Wizard token and prerequisite handling
packages/wizard/src/agent/fetch-prompt.ts, packages/wizard/src/agent/interface.ts, packages/wizard/src/lib/prerequisites.ts, packages/wizard/src/__tests__/prerequisites.test.ts
Wizard token acquisition, access-token lookup, and credential checks now consume Result-returning auth APIs and handle failure types explicitly.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

Possibly related PRs

  • cipherstash/stack#496: Both PRs touch packages/stack/src/wasm-inline.ts around auth strategy resolution and AccessKeyStrategy.create wiring.
  • cipherstash/stack#497: Both PRs modify packages/stack/src/wasm-inline.ts and the same strategy-resolution path.
  • cipherstash/stack#435: Both PRs modify packages/wizard/src/agent/fetch-prompt.ts in the wizard integration flow.

Suggested reviewers: tobyhede, auxesis

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: bumping @cipherstash/auth and migrating to its Result-based API.
Linked Issues check ✅ Passed The PR covers the required auth 0.41 bump, Result/AuthFailure migration, stack/CLI/wizard updates, tests, catalogs, and changeset.
Out of Scope Changes check ✅ Passed The changes appear focused on the auth 0.41 migration and its supporting config/test updates, with no clearly unrelated edits.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/bump-auth-0.41

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/commands/init/steps/authenticate.ts (1)

17-36: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Failure-type handling is less granular than the sibling implementation.

checkExistingAuth() treats every detected.failure / result.failure as "not authenticated" and silently falls through to undefined, whereas hasCredentials() in packages/wizard/src/lib/prerequisites.ts (same migration cohort) explicitly checks failure.type for NOT_AUTHENTICATED/MISSING_WORKSPACE_CRN and rethrows anything else. Here, a failure like WORKSPACE_MISMATCH gets silently swallowed and init re-runs the full device-code login flow instead of surfacing the real problem to the user.

This preserves prior try/catch-everything behavior so it isn't a regression, but it's an inconsistency worth aligning now that the Result API exposes failure.type for this purpose.

🔧 Suggested alignment with prerequisites.ts
+  const notAuthenticated = (failure: { type: string }): boolean =>
+    failure.type === 'NOT_AUTHENTICATED' ||
+    failure.type === 'MISSING_WORKSPACE_CRN'
+
   const detected = AutoStrategy.detect()
-  if (detected.failure) return undefined
+  if (detected.failure) {
+    if (notAuthenticated(detected.failure)) return undefined
+    throw detected.failure.error
+  }

   const result = await detected.data.getToken()
-  if (result.failure) return undefined
+  if (result.failure) {
+    if (notAuthenticated(result.failure)) return undefined
+    throw result.failure.error
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/commands/init/steps/authenticate.ts` around lines 17 - 36,
checkExistingAuth() is swallowing all Result failures and treating them as “not
authenticated,” unlike the sibling hasCredentials() flow that distinguishes
specific failure types. Update checkExistingAuth() to inspect
detected.failure.type and result.failure.type, returning undefined only for
NOT_AUTHENTICATED/MISSING_WORKSPACE_CRN and rethrowing or surfacing other
failure types like WORKSPACE_MISMATCH. Keep the behavior aligned with
packages/wizard/src/lib/prerequisites.ts and preserve the existing
AutoStrategy.detect()/getToken() handling in authenticate.ts.
🧹 Nitpick comments (3)
packages/cli/src/commands/auth/login.ts (1)

39-81: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider extracting the repeated failure-handling into a helper.

The if (x.failure) { log; process.exit(1) } pattern is repeated three times (Lines 40-43, 57-61, 76-80) with only the message/spinner text varying. A small exitOnFailure(result, onFailure?) helper would remove duplication while keeping the same error-message/exit-code behavior.

♻️ Example helper
+function exitOnAuthFailure<T>(
+  result: { failure?: { error: Error } } | { data: T },
+  onFailure?: () => void,
+): asserts result is { data: T } {
+  if ('failure' in result && result.failure) {
+    onFailure?.()
+    p.log.error(result.failure.error.message)
+    process.exit(1)
+  }
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/commands/auth/login.ts` around lines 39 - 81, The
failure-handling logic in the login and bind flows is duplicated across the
`beginDeviceCodeFlow`, `flow.pollForToken`, and `bindClientDevice` result
checks. Extract the repeated `if (result.failure) { ... process.exit(1) }`
pattern into a small helper such as `exitOnFailure` that accepts a `Result` and
optional spinner/log messages, then reuse it in `login` and `bindDevice` so the
error logging and exit behavior stay identical while removing repetition.
packages/wizard/src/__tests__/prerequisites.test.ts (1)

11-23: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering the rethrow and detect()-failure branches.

The mock only drives the getToken()NOT_AUTHENTICATED path. The new hasCredentials logic also has a detect().failure branch and a rethrow branch for unexpected failure types (Lines 50-58 in prerequisites.ts), including the MISSING_WORKSPACE_CRN case. Adding cases for a detect() failure and a non-auth failure that rethrows would guard the discriminant logic against regressions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/wizard/src/__tests__/prerequisites.test.ts` around lines 11 - 23,
The current prerequisites tests only cover the getToken() NOT_AUTHENTICATED
path, so add test cases in prerequisites.test.ts for the hasCredentials()
branches where AutoStrategy.detect() returns a failure and where getToken()
returns a non-auth failure that should be rethrown. Use the existing
hasCredentials and prerequisite logic in prerequisites.ts as the target, and
explicitly cover the MISSING_WORKSPACE_CRN case plus one unexpected failure type
to verify the discriminant/rethrow behavior stays correct.
packages/stack/__tests__/wasm-inline-strategy.test.ts (1)

139-169: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a test for the AccessKeyStrategy.create failure path.

The mock at Line 22 only returns { data: ... }. There's no test asserting resolveStrategy throws the descriptive error built at wasm-inline.ts Lines 472-476 when AccessKeyStrategy.create returns { failure }. Given this is new, non-trivial error-surfacing logic introduced by the 0.41 migration, a dedicated failure-path test would guard against regressions.

✅ Suggested additional test
it('surfaces a descriptive error when AccessKeyStrategy.create fails', () => {
  vi.mocked(AccessKeyStrategy.create).mockReturnValueOnce({
    failure: { type: 'InvalidCrn', error: { message: 'bad crn' } },
  } as any)

  expect(() =>
    resolveStrategy({ workspaceCrn: CRN, accessKey: 'CSAK.test' } as any),
  ).toThrowError(/failed to construct `AccessKeyStrategy`/)
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/stack/__tests__/wasm-inline-strategy.test.ts` around lines 139 -
169, Add a dedicated test in wasm-inline-strategy.test.ts for the
AccessKeyStrategy.create failure path: mock AccessKeyStrategy.create to return a
failure object, call resolveStrategy with workspaceCrn and accessKey, and assert
it throws the descriptive error message constructed in wasm-inline.ts. Use the
existing resolveStrategy and AccessKeyStrategy.create symbols so the test covers
the new error-surfacing behavior introduced by the migration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/stack/src/wasm-inline.ts`:
- Around line 435-478: The failure handling in resolveStrategy is reading the
auth construction error from the wrong shape, which can itself throw while
formatting the message. Update the AccessKeyStrategy.create failure branch in
resolveStrategy to use the message exposed directly on result.failure, and keep
the thrown error informative without dereferencing a nested error object.
Preserve the existing runtime checks around config.authStrategy,
config.strategy, and config.accessKey.

---

Outside diff comments:
In `@packages/cli/src/commands/init/steps/authenticate.ts`:
- Around line 17-36: checkExistingAuth() is swallowing all Result failures and
treating them as “not authenticated,” unlike the sibling hasCredentials() flow
that distinguishes specific failure types. Update checkExistingAuth() to inspect
detected.failure.type and result.failure.type, returning undefined only for
NOT_AUTHENTICATED/MISSING_WORKSPACE_CRN and rethrowing or surfacing other
failure types like WORKSPACE_MISMATCH. Keep the behavior aligned with
packages/wizard/src/lib/prerequisites.ts and preserve the existing
AutoStrategy.detect()/getToken() handling in authenticate.ts.

---

Nitpick comments:
In `@packages/cli/src/commands/auth/login.ts`:
- Around line 39-81: The failure-handling logic in the login and bind flows is
duplicated across the `beginDeviceCodeFlow`, `flow.pollForToken`, and
`bindClientDevice` result checks. Extract the repeated `if (result.failure) {
... process.exit(1) }` pattern into a small helper such as `exitOnFailure` that
accepts a `Result` and optional spinner/log messages, then reuse it in `login`
and `bindDevice` so the error logging and exit behavior stay identical while
removing repetition.

In `@packages/stack/__tests__/wasm-inline-strategy.test.ts`:
- Around line 139-169: Add a dedicated test in wasm-inline-strategy.test.ts for
the AccessKeyStrategy.create failure path: mock AccessKeyStrategy.create to
return a failure object, call resolveStrategy with workspaceCrn and accessKey,
and assert it throws the descriptive error message constructed in
wasm-inline.ts. Use the existing resolveStrategy and AccessKeyStrategy.create
symbols so the test covers the new error-surfacing behavior introduced by the
migration.

In `@packages/wizard/src/__tests__/prerequisites.test.ts`:
- Around line 11-23: The current prerequisites tests only cover the getToken()
NOT_AUTHENTICATED path, so add test cases in prerequisites.test.ts for the
hasCredentials() branches where AutoStrategy.detect() returns a failure and
where getToken() returns a non-auth failure that should be rethrown. Use the
existing hasCredentials and prerequisite logic in prerequisites.ts as the
target, and explicitly cover the MISSING_WORKSPACE_CRN case plus one unexpected
failure type to verify the discriminant/rethrow behavior stays correct.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 213c9ca1-2d4e-41cc-91ac-42c58d17a1d4

📥 Commits

Reviewing files that changed from the base of the PR and between 7f67e11 and 4f10d6d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (20)
  • .changeset/rename-strategy-to-auth-strategy.md
  • .changeset/stack-auth-0-41-result-api.md
  • package.json
  • packages/cli/src/commands/auth/login.ts
  • packages/cli/src/commands/init/steps/authenticate.ts
  • packages/stack/__tests__/helpers/stub-auth-wasm-inline.ts
  • packages/stack/__tests__/init-strategy.test.ts
  • packages/stack/__tests__/lock-context.test.ts
  • packages/stack/__tests__/wasm-inline-new-client.test.ts
  • packages/stack/__tests__/wasm-inline-strategy.test.ts
  • packages/stack/src/encryption/index.ts
  • packages/stack/src/identity/index.ts
  • packages/stack/src/index.ts
  • packages/stack/src/types.ts
  • packages/stack/src/wasm-inline.ts
  • packages/wizard/src/__tests__/prerequisites.test.ts
  • packages/wizard/src/agent/fetch-prompt.ts
  • packages/wizard/src/agent/interface.ts
  • packages/wizard/src/lib/prerequisites.ts
  • pnpm-workspace.yaml

Comment thread packages/stack/src/wasm-inline.ts
coderdan added 7 commits July 8, 2026 13:46
…ocess

Cover the once-per-process latch on both the Node and WASM entries: two
successive Encryption()/resolveStrategy() calls in one test (no beforeEach
reset between them) must warn exactly once. A regression dropping the
`if (warnedStrategyDeprecated) return` guard would warn twice and fail these.
`@cipherstash/auth` 0.41 switches every fallible auth operation to return
a `@byteslice/result` `Result<T, AuthFailure>` (`{ data }` / `{ failure }`)
instead of throwing, and renames the `AuthError` type to `AuthFailure`
(a `.type`-keyed discriminated union replacing `error.code`).

- catalog: bump `@cipherstash/auth` + 6 platform bindings 0.40.0 -> 0.41.0
  in pnpm-workspace.yaml and root package.json; update lockfile
- stack: re-export `AuthFailure` (was `AuthError`); unwrap the Result from
  `AccessKeyStrategy.create` in the wasm-inline `resolveStrategy`
- cli: unwrap Result in `stash auth login` device-code flow, `bindClientDevice`,
  and the `init` existing-auth check
- wizard: unwrap Result in gateway token fetch, agent token helper, and the
  credential prerequisite check (`error.code` -> `failure.type`)
- tests: update auth mocks/stubs to the Result shape
- changeset: stack minor (breaking type surface), stash + wizard patch

Refs #567
The Deno WASM e2e import map pinned `@cipherstash/auth@0.40.0`, but stack's
built `dist/wasm-inline.js` now unwraps the `Result` returned by auth 0.41's
`AccessKeyStrategy.create`. Under the old pin, `create` returned the strategy
directly, so `result.data` was `undefined` and protect-ffi's `newClient`
rejected with "opts.strategy is required". Point the e2e at the versions stack
actually ships (auth 0.41.0, protect-ffi 0.27.0).

Refs #567
Deno 2.9 applies a 24h `install.minimumDependencyAge` cooldown to npm
resolution by default. The WASM smoke test resolves @cipherstash/auth and
@cipherstash/protect-ffi through Deno's own npm resolver, so a freshly
published first-party version (e.g. auth 0.41.0, <24h old) is rejected with
"newer than the specified minimum dependency date" — turning CI red for ~24h
after every bump. In the 1.0 lead-up these are bumped frequently.

Mirror pnpm-workspace.yaml's minimumReleaseAge (7d) + minimumReleaseAgeExclude:
set minimumDependencyAge to P7D and exclude the first-party @cipherstash
packages, so third-party deps keep the cooldown while our own lockstep bumps
are testable immediately.

Refs #567
The declarative `install.minimumDependencyAge` exclude added in the previous
commit does not apply to `deno test`'s implicit npm resolution — Deno 2.9.1
still enforced the default 24h cooldown and rejected the freshly-published
auth 0.41.0. Use the `--minimum-dependency-age=0` flag on the test command
instead (confirmed supported by `deno test`).

Safe: the smoke test resolves only first-party @cipherstash packages (auth,
protect-ffi) plus JSR std — no third-party npm — and pnpm's 7d cooldown still
governs every real install. This unblocks lockstep first-party bumps in the
1.0 lead-up without waiting 24h per version.

Refs #567
Deno 2.9's default 24h npm freshness cooldown kept rejecting freshly
published first-party versions (auth 0.41.0), and neither the
`install.minimumDependencyAge` exclude nor the `--minimum-dependency-age=0`
flag suppressed it for `deno test` in 2.9.1. Rather than fight Deno's
cooldown knobs, stop resolving these against the registry at all.

Point the import map at the WASM-inline entries pnpm already installed
(reached via stack's own node_modules symlink), instead of `npm:@x@version`
specifiers. Both entries import only their own relative wasm bindings, so
there are no transitive npm deps. This:

- removes all `npm:` resolution from the smoke test, so Deno's cooldown never
  applies (the real gate stays pnpm's minimumReleaseAge, which already
  exempts first-party @cipherstash packages);
- keeps auth/protect-ffi in lockstep with the catalog automatically — a
  version bump no longer needs a matching edit here, which matters in the
  1.0 lead-up where these are bumped often.

Refs #567
…esult envelope

auth 0.41's WASM strategy getToken() returns the token inside a @byteslice/result
envelope (Promise<Result<TokenResult, AuthFailure>>). protect-ffi 0.27 read
`.token` directly off the resolved value and saw `undefined`, failing the WASM
encrypt/decrypt round-trip with "token field is not a string" (the Run WASM E2E
Tests (Deno) CI check). protect-ffi 0.28 unwraps the envelope (.data.token /
.failure) inside its WASM newClient — this was the parked blocker.

- Bump @cipherstash/protect-ffi 0.27.0 → 0.28.0 in packages/stack (platform
  bindings follow in lockstep via the lockfile). The WASM Deno smoke test picks
  it up automatically (resolves from packages/stack/node_modules).
- Refresh the now-stale WasmAuthStrategy doc comment: getToken returns a Result
  envelope, not a raw { token }; 0.28 is the ffi floor for the WASM path.
- Note the ffi bump in the changeset.
@coderdan
coderdan force-pushed the chore/bump-auth-0.41 branch from 6fdb103 to f9fd3f8 Compare July 8, 2026 03:54
@coderdan

coderdan commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Updated — rebased onto latest main and unblocked with protect-ffi 0.28.

The blocker (Run WASM E2E Tests / Deno). auth 0.41's WASM strategy getToken() returns the token inside a @byteslice/result envelope (Promise<Result<TokenResult, AuthFailure>>). protect-ffi 0.27 read .token straight off the resolved value → undefined → the round-trip failed with token field is not a string. protect-ffi 0.28 unwraps the envelope (.data.token / surfaces .failure) inside its WASM newClient.

Verified 0.28 actually carries the fix by diffing the 0.27 vs 0.28 WASM string tables — 0.28 gained the Result-envelope handling (failure/token, Ok/Err, the type/error/help/url/message AuthFailure shape, expected/actual for WORKSPACE_MISMATCH); 0.27 had none of it.

Changes in this push

  • Rebased onto main (81459368). The only conflict was a stale workspaces/catalogs block the branch had added to the root package.json; dropped it — catalogs live in pnpm-workspace.yaml, and main's versions are newer.
  • Bump @cipherstash/protect-ffi 0.27.00.28.0 in packages/stack (platform bindings follow in lockstep via the lockfile; the Deno smoke test resolves it from packages/stack/node_modules, so no edit needed there).
  • Refresh the now-stale WasmAuthStrategy doc comment and note the ffi bump in the changeset.

Local verification: @cipherstash/stack builds; vitest 750 passed / 246 skipped (only the DATABASE_URL-gated pg test errors on missing env). Confirmed the ffi bump adds zero new tsc errors (199 before and after — all pre-existing in unmodified test files, not a CI gate). The WASM round-trip itself needs real CS_* secrets, so CI's Run WASM E2E Tests (Deno) job is the authoritative check — now re-running green-or-not on this push.

@coderdan
coderdan requested a review from tobyhede July 8, 2026 04:02
Comment thread packages/stack/src/wasm-inline.ts
Comment thread pnpm-lock.yaml
…m-inline

resolveStrategy unwraps the Result from `@cipherstash/auth` 0.41's
`AccessKeyStrategy.create` and throws a loud construction error on the
failure arm. That branch was untested — add a unit test that overrides the
mocked `create` to return `{ failure: { type, error } }` and asserts the
thrown message names the failure type and underlying message, and that the
builder was reached (guards passed) without warning.
@coderdan
coderdan merged commit af103cd into main Jul 8, 2026
10 checks passed
@coderdan
coderdan deleted the chore/bump-auth-0.41 branch July 8, 2026 05:03
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.

Update @cipherstash/stack to @cipherstash/auth 0.41 (Result-returning API)

2 participants