Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/auth-credential-rejection-classifier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@cipherstash/auth": patch
---

Internal addition to the underlying Rust crate: `AuthError` gains an
`is_credential_rejection()` classifier used by FFI front-ends to decide
whether refreshing the credential and retrying is sensible. No API or
behaviour change for `@cipherstash/auth` consumers.
5 changes: 5 additions & 0 deletions .changeset/auth-go-credential-guest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/auth": patch
---

Device-session refresh now reports failed profile saves so callers do not silently reuse a consumed refresh token.
11 changes: 11 additions & 0 deletions .changeset/auth-http-feature-split.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@cipherstash/auth": patch
---

Internal restructuring of the underlying Rust crate: HTTP transport (reqwest
and the bundled access-key, device-session, OIDC-federation and auto
strategies) now sits behind an `http` cargo feature, on by default and always
enabled in the npm builds — no API change for `@cipherstash/auth` consumers.
The only observable difference is the wording of transport-failure error
messages, which now read "Request to the auth server failed: …" instead of
"HTTP request failed: …".
9 changes: 9 additions & 0 deletions .changeset/auth-http-transport-trait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@cipherstash/auth": patch
---

Internal restructuring of the underlying Rust crate: every strategy now sends
its requests through an `HttpTransport` trait, with the bundled reqwest client
as the default implementation, so the same strategies can run over a host's own
HTTP client (the Go binding's WASI guest). The npm builds always use the bundled
client — no API or behaviour change for `@cipherstash/auth` consumers.
6 changes: 6 additions & 0 deletions .changeset/auth-linux-x64-musl-links-musl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@cipherstash/auth": patch
---

The `linux-x64-musl` binary now links musl. In 0.44.0 it linked glibc, so
`@cipherstash/auth` did not load on musl systems such as Alpine Linux.
5 changes: 5 additions & 0 deletions .changeset/auth-mutation-regressions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/auth": patch
---

Internal test-only change to the underlying Rust crate: adds regression coverage for token expiry, credential rejection, device metadata, and browser-launch results. No API or behaviour change for `@cipherstash/auth` consumers; this entry exists because CI requires a changeset for changes under the crate.
8 changes: 8 additions & 0 deletions .changeset/auth-reexport-crn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@cipherstash/auth": patch
---

Internal addition to the underlying Rust crate: `stack_auth` now re-exports
`Crn` (the workspace CRN every strategy is bound to) so a caller that builds
a strategy by hand needs nothing else from `cts-common`. No API or behaviour
change for `@cipherstash/auth` consumers.
73 changes: 73 additions & 0 deletions .github/actions/build-auth-binding/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Build the @cipherstash/auth binding
description: >-
Compile `languages/typescript/packages/auth` into what its JS consumers load
at runtime — the napi module (cargo, debug) and optionally `wasm/`
(wasm-pack) — then prove they load.

WHY THIS EXISTS: `@cipherstash/stack`, `stash`, `@cipherstash/wizard` and the
protect-ffi integration suite take `@cipherstash/auth` from the workspace.
It ships source only there, and its `index.js` loads the napi module on
import, so every job that imports the SDK or runs the CLI builds it first.
From npm, the platform package brought a prebuilt `.node`. Without this, those
jobs fail with `Failed to load native binding for linux-x64`. It is the auth
half of `.github/actions/build-ffi-binding`, and runs after it;
scripts/__tests__/auth-binding-step-order.test.mjs holds the jobs to that.

DO NOT USE FROM A PUBLISHING WORKFLOW: release builds go through
`_build-auth-artifacts.yml`, which compiles every platform from scratch.

inputs:
wasm:
description: >-
Also build `wasm/`, which `@cipherstash/auth/wasm-inline` imports and
`@cipherstash/stack/wasm-inline` re-exports. Pass it where the job passes
`wasm: true` to build-ffi-binding.
required: false
default: 'false'

runs:
using: composite
steps:
# The runner's cargo, as build-ffi-binding uses for `index.node`. Writes
# the typings to the committed `native.d.ts`, so the tree stays clean.
- name: Build the napi module (cargo)
shell: bash

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.

Non-blocking: unlike build-ffi-binding, this action has no cache. build-ffi-binding caches index.node on a hash of its Rust inputs, so a PR that changes no Rust only restores the file. Here, each of the ~11 jobs that use this action does a cold cargo build (debug) of stack-auth-node on every run. That build includes aws-lc-sys through jsonwebtoken, and also the wasm-pack build where the job passes wasm: true.

The result is correct, so this does not block the freeze. For a follow-up, the same actions/cache pattern as build-ffi-binding would apply here, keyed on the root Cargo.lock, the stack-auth/stack-profile sources and this binding crate. The "DO NOT USE FROM A PUBLISHING WORKFLOW" note above already covers the release-cache rule.

run: pnpm --filter @cipherstash/auth run build:debug

# The root mise.toml pins wasm-pack for this build. `install_args` narrows
# the install to it: the root also pins Rust, Go and golangci-lint, which
# this needs none of. Same action and pin as build-ffi-binding.
- name: Install wasm-pack
if: inputs.wasm == 'true'
uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db # v3.6.3
with:
install: true
install_args: aqua:wasm-bindgen/wasm-pack
working_directory: .

- name: Add the wasm32 target
if: inputs.wasm == 'true'
shell: bash
run: rustup target add wasm32-unknown-unknown

- name: Build wasm/ (wasm-pack)
if: inputs.wasm == 'true'
shell: bash
run: pnpm --filter @cipherstash/auth run build:wasm

- name: Verify the binding loads
shell: bash
working-directory: languages/typescript/packages/auth
env:
WANT_WASM: ${{ inputs.wasm }}
run: |
set -euo pipefail

# index.js loads the napi module when it is required.
node -e "require('./index.js')"
echo "the napi module loads"

if [ "$WANT_WASM" = "true" ]; then
node --input-type=module -e "await import('./wasm-inline.mjs')"
echo "wasm/ loads"
fi
24 changes: 6 additions & 18 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,6 @@ updates:
patterns:
- "@types/*"
ignore:
# Catalog-managed; bump manually via pnpm-workspace.yaml + changeset.
- dependency-name: "@cipherstash/auth"
# The platform bindings MUST move in lockstep with @cipherstash/auth:
# auth pins them as exact-version optional peer deps, so a skewed set
# makes npm nest per-consumer binding copies the hoisted auth package
# cannot resolve, and every project-local install of the CLI/SDK dies
# with "Failed to load native binding". Dependabot once bumped these
# six to 0.42.0 while the ignored auth stayed 0.41.0 (the rc.2 B1
# bug). Bump all seven catalog entries together, manually. Lockstep is
# enforced by e2e/tests/supply-chain.e2e.test.ts.
- dependency-name: "@cipherstash/auth-*"
# 0.x bumps ship breaking type changes (e.g. 0.2 → 0.3 tightened the
# FailureOption constraint). Review and apply manually.
- dependency-name: "@byteslice/result"
Expand Down Expand Up @@ -126,13 +115,12 @@ updates:
- patch
ignore:
# The CipherStash crates are pinned with EXACT `=` requirements in
# crates/protect-ffi/Cargo.toml and are the same release train as the
# @cipherstash/auth catalog entries above — cipherstash-client,
# cts-common, stack-auth and stack-profile all sit at =0.42.0, matching
# the catalog's 0.42.0. Dependabot bumping a subset is the Rust version
# of the rc.2 B1 bug recorded above: it would rewrite one `=` pin and
# leave the rest, and the crates do not tolerate skew. Bump them
# together, manually, in step with the npm catalog.
# crates/protect-ffi/Cargo.toml and are one release train —
# cipherstash-client, cts-common, stack-auth and stack-profile all sit at
# the same `=` version. Dependabot bumping a subset would rewrite one `=`
# pin and leave the rest, and the crates do not tolerate skew (a skewed
# @cipherstash/auth platform set was the npm form of this, the rc.2 B1
# bug). Bump them together, manually.
#
# Caveat worth knowing: `ignore` suppresses Dependabot SECURITY PRs too,
# not just version updates. osv-scanner is the compensating control —
Expand Down
39 changes: 31 additions & 8 deletions .github/workflows/integration-drizzle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ on:
# directory, so without these two entries the only suites that would catch
# it never start. They are the files a bump actually edits: exact pins
# (`protect-ffi`, `@cipherstash/eql`) live in the package manifest,
# `catalog:` ones (`@cipherstash/auth`, which moves in lockstep with
# protect-ffi for the WASM entry) in the workspace catalog.
# `catalog:` ones in the workspace catalog.
#
# `pnpm-lock.yaml` is deliberately NOT listed. It changes on roughly every
# dependency bump in the monorepo — far more often than either file here —
# and these are credentialed, database-backed jobs. Nothing is lost: a
# protect-ffi or auth version change cannot reach the lockfile without
# editing one of the two manifests below first.
# protect-ffi version change cannot reach the lockfile without editing
# one of the two manifests below first, and an auth one edits its own
# manifest, under the auth paths below.
- 'languages/typescript/packages/stack/package.json'
- 'pnpm-workspace.yaml'
- 'languages/typescript/packages/test-kit/**'
Expand All @@ -60,6 +60,15 @@ on:
- '.github/actions/integration-setup/**'
- '.github/actions/integration-db/**'
- '.github/actions/build-ffi-binding/**'
- '.github/actions/build-auth-binding/**'
# `@cipherstash/auth` is a workspace package, and the SDK loads its napi
# module (and, for `wasm-inline`, its wasm) on import, so a change to what
# it ships arrives here rather than in `pnpm-workspace.yaml`. The paths of
# require-auth-npm-changeset.yml.
- 'packages/stack-auth/Cargo.toml'
- 'packages/stack-auth/src/**'
- 'languages/typescript/packages/auth/**'
- 'languages/typescript/packages/stack-auth-wasm/**'
# The Rust that produces every EQL payload these suites round-trip.
# Absorbing protect-ffi put it in-tree, so a crate change can now
# break them in a PR that touches no TypeScript at all.
Expand Down Expand Up @@ -126,14 +135,14 @@ on:
# directory, so without these two entries the only suites that would catch
# it never start. They are the files a bump actually edits: exact pins
# (`protect-ffi`, `@cipherstash/eql`) live in the package manifest,
# `catalog:` ones (`@cipherstash/auth`, which moves in lockstep with
# protect-ffi for the WASM entry) in the workspace catalog.
# `catalog:` ones in the workspace catalog.
#
# `pnpm-lock.yaml` is deliberately NOT listed. It changes on roughly every
# dependency bump in the monorepo — far more often than either file here —
# and these are credentialed, database-backed jobs. Nothing is lost: a
# protect-ffi or auth version change cannot reach the lockfile without
# editing one of the two manifests below first.
# protect-ffi version change cannot reach the lockfile without editing
# one of the two manifests below first, and an auth one edits its own
# manifest, under the auth paths below.
- 'languages/typescript/packages/stack/package.json'
- 'pnpm-workspace.yaml'
- 'languages/typescript/packages/test-kit/**'
Expand All @@ -145,6 +154,15 @@ on:
- '.github/actions/integration-setup/**'
- '.github/actions/integration-db/**'
- '.github/actions/build-ffi-binding/**'
- '.github/actions/build-auth-binding/**'
# `@cipherstash/auth` is a workspace package, and the SDK loads its napi
# module (and, for `wasm-inline`, its wasm) on import, so a change to what
# it ships arrives here rather than in `pnpm-workspace.yaml`. The paths of
# require-auth-npm-changeset.yml.
- 'packages/stack-auth/Cargo.toml'
- 'packages/stack-auth/src/**'
- 'languages/typescript/packages/auth/**'
- 'languages/typescript/packages/stack-auth-wasm/**'
# The Rust that produces every EQL payload these suites round-trip.
# Absorbing protect-ffi put it in-tree, so a crate change can now
# break them in a PR that touches no TypeScript at all.
Expand Down Expand Up @@ -276,6 +294,11 @@ jobs:
with:
wasm: 'true'

- name: Build the @cipherstash/auth binding
uses: ./.github/actions/build-auth-binding
with:
wasm: 'true'

# No pre-`up` cleanup step any more: the project name is unique per job, so
# a container leaked by a hard-killed prior run cannot hold this job's
# name or its (ephemeral) port. Blanket-pruning would now be actively
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/integration-prisma-next.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ on:
- '.github/actions/integration-setup/**'
- '.github/actions/integration-db/**'
- '.github/actions/build-ffi-binding/**'
- '.github/actions/build-auth-binding/**'
# The Rust that produces every EQL payload these suites round-trip.
# Absorbing protect-ffi put it in-tree, so a crate change can now
# break them in a PR that touches no TypeScript at all.
Expand Down Expand Up @@ -81,6 +82,7 @@ on:
- '.github/actions/integration-setup/**'
- '.github/actions/integration-db/**'
- '.github/actions/build-ffi-binding/**'
- '.github/actions/build-auth-binding/**'
# The Rust that produces every EQL payload these suites round-trip.
# Absorbing protect-ffi put it in-tree, so a crate change can now
# break them in a PR that touches no TypeScript at all.
Expand Down Expand Up @@ -166,6 +168,9 @@ jobs:
- name: Build the protect-ffi binding
uses: ./.github/actions/build-ffi-binding

- name: Build the @cipherstash/auth binding
uses: ./.github/actions/build-auth-binding

# No pre-`up` cleanup step any more: the project name is unique per job, so
# a container leaked by a hard-killed prior run cannot hold this job's
# name or its (ephemeral) port. Blanket-pruning would now be actively
Expand Down
27 changes: 25 additions & 2 deletions .github/workflows/integration-protect-ffi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ name: Integration — protect-ffi (native + WASM)
# queried SQL installed from the PUBLISHED EQL bundle while the payloads under
# test were emitted by the in-tree `eql-bindings`, so the two halves of EQL could
# disagree — and would have disagreed in a database, not in CI. `@cipherstash/eql`
# now resolves `workspace:^`, and `@cipherstash/auth` and `vitest` take
# now resolves `workspace:^`, `@cipherstash/auth` `workspace:*`, and `vitest`
# `catalog:repo`.
#
# Separate from `tests.yml` on purpose, and separate from `tests-rust.yml`: this
Expand All @@ -39,7 +39,7 @@ on:
# and its manifest.
- 'languages/typescript/packages/protect-ffi/integration-tests/**'
# The suite's dependency versions, now that it is a pnpm workspace member:
# `@cipherstash/auth`, `vitest` and `typescript` reach it through
# `vitest` and `typescript` reach it through
# `catalog:repo`, so a catalog bump changes what this job runs while
# editing no file under the suite. Same entry, same reason, as the other
# integration workflows — and like them, `pnpm-lock.yaml` is deliberately
Expand Down Expand Up @@ -89,6 +89,15 @@ on:
- 'packages/eql/Cargo.toml'
- '.github/workflows/integration-protect-ffi.yml'
- '.github/actions/build-ffi-binding/**'
- '.github/actions/build-auth-binding/**'
# `@cipherstash/auth` is a workspace package, and the SDK loads its napi
# module (and, for `wasm-inline`, its wasm) on import, so a change to what
# it ships arrives here rather than in `pnpm-workspace.yaml`. The paths of
# require-auth-npm-changeset.yml.
- 'packages/stack-auth/Cargo.toml'
- 'packages/stack-auth/src/**'
- 'languages/typescript/packages/auth/**'
- 'languages/typescript/packages/stack-auth-wasm/**'
- '.github/actions/require-cs-secrets/**'
pull_request:
branches: ['**']
Expand Down Expand Up @@ -119,6 +128,15 @@ on:
- 'packages/eql/Cargo.toml'
- '.github/workflows/integration-protect-ffi.yml'
- '.github/actions/build-ffi-binding/**'
- '.github/actions/build-auth-binding/**'
# `@cipherstash/auth` is a workspace package, and the SDK loads its napi
# module (and, for `wasm-inline`, its wasm) on import, so a change to what
# it ships arrives here rather than in `pnpm-workspace.yaml`. The paths of
# require-auth-npm-changeset.yml.
- 'packages/stack-auth/Cargo.toml'
- 'packages/stack-auth/src/**'
- 'languages/typescript/packages/auth/**'
- 'languages/typescript/packages/stack-auth-wasm/**'
- '.github/actions/require-cs-secrets/**'
workflow_dispatch: {}

Expand Down Expand Up @@ -292,6 +310,11 @@ jobs:
with:
wasm: 'true'

- name: Build the @cipherstash/auth binding
uses: ./.github/actions/build-auth-binding
with:
wasm: 'true'

# `working_directory` is load-bearing, not tidiness. mise reads config
# from the current directory and its PARENTS, so an action running at the
# repo root never sees languages/typescript/packages/protect-ffi/mise.toml — it would install
Expand Down
Loading
Loading