diff --git a/.changeset/eql-v3-supabase.md b/.changeset/eql-v3-supabase.md deleted file mode 100644 index 42a7e4f7..00000000 --- a/.changeset/eql-v3-supabase.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -'@cipherstash/stack': minor -'stash': minor ---- - -Add EQL v3 Supabase support, baselined on the `eql-3.0.0-alpha.2` release. - -`@cipherstash/stack/supabase` gains `encryptedSupabaseV3` — the EQL v3 -counterpart of `encryptedSupabase` for schemas authored with -`@cipherstash/stack/eql/v3`. The public surface and call shape are identical -to v2 (same filter methods, `withLockContext`, `audit`); only the schema type -and wire encoding differ. - -**The v3 surface** is the `eql-3.0.0-alpha.2` release artifact: domains use -SQL-standard type names (`eql_v3.integer_ord`, `eql_v3.timestamp_ord`, -`eql_v3.boolean`, … mirrored by `types.IntegerOrd`, `types.TimestampOrd`, -`types.Boolean`, …), SEM internals live in a separate `eql_v3_internal` -schema (grant it roles, never expose it — only `eql_v3` goes in Supabase's -Exposed schemas), and envelopes are versioned `v: 3`. Envelope production -rides on `@cipherstash/protect-ffi` 0.27, which takes an `eqlVersion` so the -same client emits v2 or v3 payloads per schema. - -**Adapter behaviour:** - -- columns are stored in their native `eql_v3.*` domains (raw jsonb payloads, - no composite wrap), with JS property → DB column name resolution and `Date` - reconstruction from `cast_as` on decrypted rows; -- **INTERIM:** filter operands are full storage envelopes — every `eql_v3.*` - domain CHECK requires the storage keys, and the SQL operators coerce their - operand into the domain, so a term-only operand is rejected today. This is - a tracked workaround (Linear CIP-3402), not the design: a full-envelope - operand carries a real decryptable ciphertext plus all of the column's - index terms, and PostgREST filters travel in GET query strings, so operands - can land in URL logs, proxies, and Supabase request logs (query terms are - index-terms-only by design). The fix is an EQL-side term-only scalar query - envelope (the scalar analog of `eql_v3.jsonb_query`); -- `like`/`ilike` on encrypted columns are emitted as PostgREST `cs` - (bloom-filter `@>`) — the v3 domains define no LIKE operator. Substring - search currently also requires `include_original: false` on the match - index; that requirement is a symptom of the same interim full-envelope - operand and goes away with CIP-3402; -- filters on storage-only columns (e.g. `types.Boolean`) and null filter - values are rejected at the type level and at runtime. - -The v3 builder's default row type is exactly the table's inferred plaintext -shape (no index-signature widening — widening would disable the storage-only -filter guard). Filtering or inserting plaintext passthrough columns requires -an explicit row type: `es.from('users', users)`. - -The CLI gains an EQL v3 path: `stash eql install --eql-version 3` installs the -vendored `eql-3.0.0-alpha.2` bundle (`--supabase` selects the opclass-stripped -variant and applies the role grants for both `eql_v3` and `eql_v3_internal`); -`stash db upgrade` also accepts `--eql-version`, and `stash db status` reports -v2 and v3 installs independently. The v2 `SUPABASE_PERMISSIONS_SQL` block is -now generated from a shared `supabasePermissionsSql(schemaName)` helper, with -`SUPABASE_PERMISSIONS_SQL_V3` covering the v3 schemas. diff --git a/.changeset/eql-v3-text-search.md b/.changeset/eql-v3-text-search.md deleted file mode 100644 index 1abbb191..00000000 --- a/.changeset/eql-v3-text-search.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -"@cipherstash/stack": minor ---- - -Add the EQL v3 `text_search` authoring DSL on a new `@cipherstash/stack/eql/v3` -subpath (`types.TextSearch`, v3 `encryptedTable` / `buildEncryptConfig`). The v3 -builders emit the existing `EncryptConfig` shape, so encryption, payloads, and -query paths are unchanged at runtime. - -Also widens the public client types (`EncryptionClientConfig.schemas`, -`EncryptOptions`, `SearchTerm`/`EncryptQueryOptions`) to a structural contract so -both v2 and v3 builders are accepted by `Encryption` / `encrypt` / `decrypt` / -`encryptQuery`. This is a backward-compatible widening — existing v2 usage is -unaffected. The structural contracts themselves (`BuildableColumn`, -`BuildableQueryColumn`, `BuildableV3QueryableColumn`, `BuildableTable`, -`BuildableTableColumns`) and the `encryptModel` return-type mapper -(`EncryptedFromBuildableTable`) are exported from `@cipherstash/stack/types` so -consumers can name them. diff --git a/.changeset/eql-v3-typed-client.md b/.changeset/eql-v3-typed-client.md deleted file mode 100644 index b8821cf6..00000000 --- a/.changeset/eql-v3-typed-client.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -"@cipherstash/stack": minor ---- - -Add a strongly-typed EQL v3 client surface on a new `@cipherstash/stack/v3` -subpath (`EncryptionV3`, `typedClient`, `TypedEncryptionClient`). It re-exports -the v3 `types` namespace and table API (from `@cipherstash/stack/eql/v3`), so a -single import provides everything needed to author and use a v3 schema. - -Every method derives its types from the concrete `table` / `column` builder -arguments: - -- `encrypt` / `encryptQuery` pin the plaintext to the column's domain type - (`text → string`, `int8 → bigint`, `timestamptz → Date`, …). -- `encryptQuery` constrains `queryType` to the column's capabilities and rejects - storage-only columns at compile time. -- `encryptModel` / `bulkEncryptModels` validate schema-column fields against their - inferred plaintext type (passthrough fields are untouched) and return a precise - encrypted model. -- `decryptModel` / `bulkDecryptModels` return the precise plaintext model, - reconstructing `Date` / `bigint` values from the encrypt-config `cast_as`. - -Because the typed methods bind to the concrete branded v3 classes, a hand-rolled -structural table/column is rejected — closing the soundness gap where a non-branded -table could be encrypted at runtime while typed as plaintext. - -Runtime behaviour is unchanged: the encrypt/query paths return the same operations -as the base client; only the model-decrypt paths add a per-column `Date` / `bigint` -reconstruction step. The v2 client surface (`Encryption`) is untouched. diff --git a/.changeset/eql-v3-typed-schema.md b/.changeset/eql-v3-typed-schema.md deleted file mode 100644 index a805d285..00000000 --- a/.changeset/eql-v3-typed-schema.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@cipherstash/stack': minor ---- - -Add EQL v3 schema builders for all generated SQL domains under `@cipherstash/stack/eql/v3`, exposed as the `types` namespace (one member per EQL v3 domain, e.g. `types.TextEq` / `types.Int4Ord` / `types.Timestamptz`), including explicit query capability metadata (`getQueryCapabilities()` / `isQueryable()`) and v3 table support in model encryption helpers (`encryptModel` / `bulkEncryptModels`). - -Also widen the accepted plaintext input type for `encrypt` / `encryptQuery` to include `Date` and `bigint` (via the new `Plaintext` type), so v3 `date` / `timestamptz` / `int8` domains can be encrypted and queried with their natural JavaScript values. diff --git a/.changeset/native-binary-guards.md b/.changeset/native-binary-guards.md deleted file mode 100644 index cd321d04..00000000 --- a/.changeset/native-binary-guards.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"stash": minor ---- - -Add guards for missing native binaries. When npm skips the platform-specific -optional dependency (a known npm bug), stash now prints actionable fix -guidance instead of a raw `MODULE_NOT_FOUND` stack trace. Adds a new -`stash doctor` command that diagnoses the runtime and native modules and works -even when a binary is missing. diff --git a/.changeset/refresh-package-readmes.md b/.changeset/refresh-package-readmes.md deleted file mode 100644 index 2fd97f85..00000000 --- a/.changeset/refresh-package-readmes.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@cipherstash/stack': patch -'stash': patch -'@cipherstash/protect': patch -'@cipherstash/schema': patch -'@cipherstash/drizzle': patch -'@cipherstash/nextjs': patch -'@cipherstash/protect-dynamodb': patch ---- - -Documentation: refresh package READMEs after the protectjs → stack repository rename. Fixed repository and license links, replaced dead in-repo docs links with cipherstash.com/docs URLs, rewrote the incorrect @cipherstash/nextjs README, and added guidance pointing new projects to @cipherstash/stack. diff --git a/.changeset/rename-db-install-to-eql-install.md b/.changeset/rename-db-install-to-eql-install.md deleted file mode 100644 index d2138d18..00000000 --- a/.changeset/rename-db-install-to-eql-install.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"stash": minor -"@cipherstash/wizard": minor ---- - -Rename `stash db install`, `stash db upgrade`, and `stash db status` to -`stash eql install`, `stash eql upgrade`, and `stash eql status`. These -commands manage the EQL extension itself, so they now live under a dedicated -`eql` command group. The old `db` spellings keep working as deprecated -aliases that print a warning pointing at the new names. All help text, -hints, generated migration headers, and wizard steps now reference the -`eql` commands. diff --git a/.changeset/rename-strategy-to-auth-strategy.md b/.changeset/rename-strategy-to-auth-strategy.md deleted file mode 100644 index a05a629a..00000000 --- a/.changeset/rename-strategy-to-auth-strategy.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -"@cipherstash/stack": minor ---- - -Rename the encryption client's auth strategy config field from `config.strategy` to **`config.authStrategy`** to make its purpose clear, and expand the `Encryption()` TypeDoc with a full authentication and keysets walkthrough. - -**`config.authStrategy`** is the new, documented field for supplying an auth strategy (`OidcFederationStrategy`, `AccessKeyStrategy`, or any `{ getToken() }` object). **`config.strategy` is retained as a deprecated alias** — passing it still works and forwards to the client, but logs a one-time runtime deprecation warning. When both are set, `authStrategy` wins (and the deprecation warning still fires so the leftover field gets cleaned up). - -```ts -import { Encryption, OidcFederationStrategy } from "@cipherstash/stack" - -const client = await Encryption({ - schemas: [users], - config: { - authStrategy: OidcFederationStrategy.create(workspaceCrn, () => getUserJwt()), - }, -}) -``` - -**Migration:** rename `config.strategy` → `config.authStrategy`. No behavioural change beyond the deprecation warning; the field is forwarded to protect-ffi's `strategy` option exactly as before. - -The `Encryption()` TypeDoc now documents the default `auto` strategy (env vars → local dev profile via `npx stash auth login`), the four `CS_*` production/CI variables, custom strategies (`AccessKeyStrategy`, `OidcFederationStrategy`), lock context, and keysets for multi-tenant isolation. - -The `@cipherstash/stack/wasm-inline` entry (Deno / Edge / Workers / Bun) gets the same rename so the Node and WASM interfaces stay in sync: `WasmClientConfig.authStrategy` is the documented field, `strategy` is a deprecated alias that still works and warns at runtime. diff --git a/.changeset/stack-auth-0-41-result-api.md b/.changeset/stack-auth-0-41-result-api.md deleted file mode 100644 index 0ab8677d..00000000 --- a/.changeset/stack-auth-0-41-result-api.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -"@cipherstash/stack": minor -"@cipherstash/wizard": patch -"stash": patch ---- - -Bump `@cipherstash/auth` (and its per-platform native bindings) from `0.40.0` to `0.41.0`, and migrate to its new `Result`-returning API. - -**What changed in `@cipherstash/auth` `0.41`.** Every fallible auth operation now returns a `@byteslice/result` `Result` (`{ data }` on success, `{ failure }` on error) instead of throwing. This covers strategy construction (`AccessKeyStrategy.create`, `OidcFederationStrategy.create`, `AutoStrategy.detect`, `DeviceSessionStrategy.fromProfile`), `getToken()`, and the device-code flow (`beginDeviceCodeFlow`, `pollForToken`, `openInBrowser`, `bindClientDevice`). Consumers now write `if (result.failure) …` and read `result.data` rather than `try/catch`. The `AuthError` type was renamed to **`AuthFailure`** — a discriminated union keyed by `type` (`"NOT_AUTHENTICATED"`, `"WORKSPACE_MISMATCH"`, …), replacing the old `error.code` string. - -**`@cipherstash/stack` (breaking type surface).** - -- **`AuthError` is renamed to `AuthFailure`** in the public re-exports from `@cipherstash/stack`. `AuthErrorCode` and `TokenResult` are unchanged. Anyone importing `AuthError` from `@cipherstash/stack` must switch to `AuthFailure`. -- The WASM-inline access-key path (`resolveStrategy`, used by `@cipherstash/stack/wasm-inline`'s `Encryption()`) now unwraps the `Result` from `AccessKeyStrategy.create`. A construction failure (e.g. an invalid CRN or access key) throws a descriptive `[encryption]` error naming the `AuthFailure.type` instead of surfacing the raw auth error. -- Bump `@cipherstash/protect-ffi` from `0.27.0` to `0.28.0`. auth `0.41`'s `getToken()` returns the token inside a `Result` envelope; protect-ffi `0.28` unwraps it (`.data.token`) inside its WASM `newClient`, whereas `0.27` read `.token` off the envelope and got `undefined` — which failed the WASM encrypt/decrypt round-trip with `token field is not a string`. `0.28` is the floor for the WASM path under auth `0.41`. - -**`stash` (CLI) and `@cipherstash/wizard`.** Internal auth call sites (`stash auth login`, device binding, `init` auth check, and the wizard's token acquisition / prerequisite check) were updated to unwrap `Result` and branch on `failure.type`. Behaviour is preserved — auth failures still surface the same way to end users; no CLI/wizard API changed. diff --git a/.changeset/stack-protect-ffi-0-26-oidc-strategy.md b/.changeset/stack-protect-ffi-0-26-oidc-strategy.md deleted file mode 100644 index 0e38ab81..00000000 --- a/.changeset/stack-protect-ffi-0-26-oidc-strategy.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -"@cipherstash/stack": minor ---- - -Bump `@cipherstash/protect-ffi` to `0.26.0` and `@cipherstash/auth` to `0.40.0`, and replace the lock-context token ceremony with a strategy-based approach for identity-bound encryption. - -**protect-ffi `0.26.0`** supersedes `0.25.0`. The public API is unchanged from `0.25` (internal fixes only). As in `0.25`, `serviceToken` is gone from the encrypt / decrypt / query option types; auth flows through the client's strategy / credentials, and lock contexts travel as `lockContext.identityClaim`. The WASM-inline path takes a single options object with the auth strategy nested under `strategy`, and `Encryption()` config uses **`workspaceCrn`** (`CS_WORKSPACE_CRN`) as the single source of truth — `CS_REGION` is no longer consulted. On that path `workspaceCrn` is required only alongside an `accessKey` (it derives the region); with a pre-built `strategy` it is **optional**, since the strategy already carries the CRN. - -**Strategy-based, identity-bound encryption.** `OidcFederationStrategy` federates an end user's third-party OIDC JWT (Clerk, Supabase, Auth0, …) into a CTS service token. As of `@cipherstash/auth` `0.40` it takes a `workspaceCrn` (region derived from the CRN), matching `AccessKeyStrategy`. Pass it as `config.strategy` so every ZeroKMS request authenticates *as that user*, then bind the data key to a claim with `.withLockContext({ identityClaim })`: - -```ts -import { Encryption, OidcFederationStrategy } from "@cipherstash/stack" - -const client = await Encryption({ - schemas: [users], - config: { - strategy: OidcFederationStrategy.create(workspaceCrn, () => getUserJwt()), - }, -}) - -await client - .encrypt("alice@example.com", { column: users.email, table: users }) - .withLockContext({ identityClaim: ["sub"] }) -``` - -This replaces the old ceremony (`new LockContext()` → `await lc.identify(jwt)` → `.withLockContext(lc)`), which relied on a per-operation CTS token that protect-ffi removed in `0.25`. - -- **`.withLockContext()`** now accepts a plain `{ identityClaim }` object (as well as a `LockContext`) and no longer requires a CTS token or an `identify()` call — it carries the identity claim only. -- **`LockContext.identify()` / `getLockContext()`** are **deprecated** (kept for backwards compatibility); the strategy handles token acquisition. -- **Strategies are re-exported** from `@cipherstash/stack` (`OidcFederationStrategy`, `AccessKeyStrategy`, `AutoStrategy`, `DeviceSessionStrategy`) and from `@cipherstash/stack/wasm-inline` (`OidcFederationStrategy`, `AccessKeyStrategy`) so integrators don't need a separate `@cipherstash/auth` install. `AuthStrategy` remains re-exported for the structural type. - -**Migrating `region` → `workspaceCrn` (WASM-inline).** If you previously passed `region` (or relied on `CS_REGION`) to the WASM-inline `Encryption()` path, replace it with your workspace CRN: set `workspaceCrn` in config (or `CS_WORKSPACE_CRN` in the environment) to the value shown in the CipherStash dashboard (`crn:.aws:` — it embeds the region, which is now derived from it). `region` is ignored if passed. - -**Lock-context enforcement is now server-side only.** Because the client no longer resolves a per-user CTS token at `withLockContext` time, it also cannot fail fast there: a wrong or missing identity claim surfaces as a ZeroKMS **decryption failure** (the data key simply doesn't unlock), not as a client-side error before the request. The cryptographic guarantee is unchanged — enforcement happens in ZeroKMS — but anyone relying on the old client-side throw for early feedback should assert on the operation's `failure` result instead. - -Existing credential / env behaviour is preserved when `config.strategy` is omitted. diff --git a/.changeset/stash-cli-manifest.md b/.changeset/stash-cli-manifest.md deleted file mode 100644 index e8221594..00000000 --- a/.changeset/stash-cli-manifest.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -"stash": minor ---- - -Add a command-descriptor registry and `stash manifest --json` — a structured, -versioned command surface for the docs generator and agents to consume instead -of scraping `--help`. - -- `stash manifest --json` emits `{ name, version, groups[] }`, where each command - carries its summary, optional long description, examples, and flags. `version` - comes from the CLI's own `package.json`, so a page generated from the manifest - is always stamped with the version it describes. -- `stash manifest` (no flag) prints a grouped, human-readable command list. -- The registry (`src/cli/registry.ts`) is intended to become the single source of - truth for command metadata. This is phase 1 of - `docs/plans/cli-help-and-manifest.md`; it is additive — `bin/main.ts` still - hand-maintains the `HELP` string that renders `--help`, so until the documented - follow-on renders `--help` from the registry the two are kept in sync by hand. diff --git a/.changeset/stash-non-interactive-agent-cli.md b/.changeset/stash-non-interactive-agent-cli.md deleted file mode 100644 index 9e941c11..00000000 --- a/.changeset/stash-non-interactive-agent-cli.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -"stash": minor ---- - -Add non-interactive / agent-friendly affordances so `stash init` and -`stash auth login` can run without a TTY (agents, CI, pipes). All changes are -additive — interactive behaviour in a real terminal is unchanged. - -- `--region ` / `STASH_REGION` on `stash auth login` and `stash init` - skip the interactive region picker. An unknown or missing region in a - non-TTY context now exits with an actionable message instead of hanging on - the picker (region resolution mirrors the `DATABASE_URL` resolver's - `TTY && !CI` gate). -- `stash auth login --json` emits newline-delimited device-code events. The - first event (`authorization_required`) carries the verification URL, so an - agent can trigger auth and hand the browser step to a human — only a human - completes it in the browser. `--no-open` suppresses the browser launch. -- `stash auth regions` lists the regions valid for `--region` / `STASH_REGION`; - `stash auth regions --json` emits `[{ slug, label }]` for programmatic use. diff --git a/.changeset/wizard-anthropic-sdk-security-pin.md b/.changeset/wizard-anthropic-sdk-security-pin.md deleted file mode 100644 index f6b9985f..00000000 --- a/.changeset/wizard-anthropic-sdk-security-pin.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@cipherstash/wizard": patch ---- - -Add `@anthropic-ai/sdk` `^0.106.0` as a direct dependency so the -auto-installed peer of `@anthropic-ai/claude-agent-sdk` resolves to a release -patched against GHSA-p7fg-763f-g4gf, instead of the vulnerable 0.81.0 the -peer range alone would select. The wizard never imports the SDK directly — -this is a peer-resolution pin only; no behaviour change. diff --git a/e2e/CHANGELOG.md b/e2e/CHANGELOG.md new file mode 100644 index 00000000..370ade6b --- /dev/null +++ b/e2e/CHANGELOG.md @@ -0,0 +1,24 @@ +# @cipherstash/e2e + +## 0.0.1 + +### Patch Changes + +- Updated dependencies [cc62407] +- Updated dependencies [5e4f354] +- Updated dependencies [4ceefed] +- Updated dependencies [cb34d71] +- Updated dependencies [eb94ac8] +- Updated dependencies [aa9c4b1] +- Updated dependencies [64fdeb2] +- Updated dependencies [90d19fb] +- Updated dependencies [a5f5422] +- Updated dependencies [35b9ed6] +- Updated dependencies [5e23384] +- Updated dependencies [72a3356] +- Updated dependencies [17f4745] + - @cipherstash/stack@0.19.0 + - stash@0.17.0 + - @cipherstash/protect@12.0.1 + - @cipherstash/drizzle@3.0.3 + - @cipherstash/wizard@0.4.0 diff --git a/e2e/package.json b/e2e/package.json index 46ba1555..660ff66b 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/e2e", - "version": "0.0.0", + "version": "0.0.1", "private": true, "description": "End-to-end tests that exercise built CipherStash binaries and cross-package behaviour.", "type": "module", diff --git a/examples/basic/CHANGELOG.md b/examples/basic/CHANGELOG.md index 90729ab3..b35e63dd 100644 --- a/examples/basic/CHANGELOG.md +++ b/examples/basic/CHANGELOG.md @@ -1,5 +1,19 @@ # @cipherstash/basic-example +## 1.2.13 + +### Patch Changes + +- Updated dependencies [cc62407] +- Updated dependencies [5e4f354] +- Updated dependencies [4ceefed] +- Updated dependencies [cb34d71] +- Updated dependencies [aa9c4b1] +- Updated dependencies [90d19fb] +- Updated dependencies [a5f5422] +- Updated dependencies [35b9ed6] + - @cipherstash/stack@0.19.0 + ## 1.2.12 ### Patch Changes diff --git a/examples/basic/package.json b/examples/basic/package.json index cb7d329d..87c6c8fd 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -1,7 +1,7 @@ { "name": "@cipherstash/basic-example", "private": true, - "version": "1.2.12", + "version": "1.2.13", "type": "module", "scripts": { "start": "tsx index.ts" diff --git a/examples/prisma/CHANGELOG.md b/examples/prisma/CHANGELOG.md index c1ce61e9..f815e347 100644 --- a/examples/prisma/CHANGELOG.md +++ b/examples/prisma/CHANGELOG.md @@ -1,5 +1,20 @@ # @cipherstash/prisma-next-example +## 0.0.5 + +### Patch Changes + +- Updated dependencies [cc62407] +- Updated dependencies [5e4f354] +- Updated dependencies [4ceefed] +- Updated dependencies [cb34d71] +- Updated dependencies [aa9c4b1] +- Updated dependencies [90d19fb] +- Updated dependencies [a5f5422] +- Updated dependencies [35b9ed6] + - @cipherstash/stack@0.19.0 + - @cipherstash/prisma-next@0.3.2 + ## 0.0.4 ### Patch Changes diff --git a/examples/prisma/package.json b/examples/prisma/package.json index dc8d3e84..9560b85b 100644 --- a/examples/prisma/package.json +++ b/examples/prisma/package.json @@ -1,7 +1,7 @@ { "name": "@cipherstash/prisma-next-example", "private": true, - "version": "0.0.4", + "version": "0.0.5", "description": "End-to-end example of @cipherstash/prisma-next: searchable application-layer encryption for Postgres with Prisma Next, using @cipherstash/stack as the SDK.", "type": "module", "scripts": { diff --git a/packages/bench/CHANGELOG.md b/packages/bench/CHANGELOG.md index ec91d36b..4652e87f 100644 --- a/packages/bench/CHANGELOG.md +++ b/packages/bench/CHANGELOG.md @@ -1,5 +1,19 @@ # @cipherstash/bench +## 0.0.4 + +### Patch Changes + +- Updated dependencies [cc62407] +- Updated dependencies [5e4f354] +- Updated dependencies [4ceefed] +- Updated dependencies [cb34d71] +- Updated dependencies [aa9c4b1] +- Updated dependencies [90d19fb] +- Updated dependencies [a5f5422] +- Updated dependencies [35b9ed6] + - @cipherstash/stack@0.19.0 + ## 0.0.3 ### Patch Changes diff --git a/packages/bench/package.json b/packages/bench/package.json index 16636149..40dcc4a7 100644 --- a/packages/bench/package.json +++ b/packages/bench/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/bench", - "version": "0.0.3", + "version": "0.0.4", "private": true, "description": "Performance / index-engagement benchmarks for stack integrations (Drizzle, encryptedSupabase, Prisma).", "type": "module", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index c61a4f1e..616e25c7 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,121 @@ # @cipherstash/cli +## 0.17.0 + +### Minor Changes + +- cc62407: Add EQL v3 Supabase support, baselined on the `eql-3.0.0-alpha.2` release. + + `@cipherstash/stack/supabase` gains `encryptedSupabaseV3` — the EQL v3 + counterpart of `encryptedSupabase` for schemas authored with + `@cipherstash/stack/eql/v3`. The public surface and call shape are identical + to v2 (same filter methods, `withLockContext`, `audit`); only the schema type + and wire encoding differ. + + **The v3 surface** is the `eql-3.0.0-alpha.2` release artifact: domains use + SQL-standard type names (`eql_v3.integer_ord`, `eql_v3.timestamp_ord`, + `eql_v3.boolean`, … mirrored by `types.IntegerOrd`, `types.TimestampOrd`, + `types.Boolean`, …), SEM internals live in a separate `eql_v3_internal` + schema (grant it roles, never expose it — only `eql_v3` goes in Supabase's + Exposed schemas), and envelopes are versioned `v: 3`. Envelope production + rides on `@cipherstash/protect-ffi` 0.27, which takes an `eqlVersion` so the + same client emits v2 or v3 payloads per schema. + + **Adapter behaviour:** + + - columns are stored in their native `eql_v3.*` domains (raw jsonb payloads, + no composite wrap), with JS property → DB column name resolution and `Date` + reconstruction from `cast_as` on decrypted rows; + - **INTERIM:** filter operands are full storage envelopes — every `eql_v3.*` + domain CHECK requires the storage keys, and the SQL operators coerce their + operand into the domain, so a term-only operand is rejected today. This is + a tracked workaround (Linear CIP-3402), not the design: a full-envelope + operand carries a real decryptable ciphertext plus all of the column's + index terms, and PostgREST filters travel in GET query strings, so operands + can land in URL logs, proxies, and Supabase request logs (query terms are + index-terms-only by design). The fix is an EQL-side term-only scalar query + envelope (the scalar analog of `eql_v3.jsonb_query`); + - `like`/`ilike` on encrypted columns are emitted as PostgREST `cs` + (bloom-filter `@>`) — the v3 domains define no LIKE operator. Substring + search currently also requires `include_original: false` on the match + index; that requirement is a symptom of the same interim full-envelope + operand and goes away with CIP-3402; + - filters on storage-only columns (e.g. `types.Boolean`) and null filter + values are rejected at the type level and at runtime. + + The v3 builder's default row type is exactly the table's inferred plaintext + shape (no index-signature widening — widening would disable the storage-only + filter guard). Filtering or inserting plaintext passthrough columns requires + an explicit row type: `es.from('users', users)`. + + The CLI gains an EQL v3 path: `stash eql install --eql-version 3` installs the + vendored `eql-3.0.0-alpha.2` bundle (`--supabase` selects the opclass-stripped + variant and applies the role grants for both `eql_v3` and `eql_v3_internal`); + `stash db upgrade` also accepts `--eql-version`, and `stash db status` reports + v2 and v3 installs independently. The v2 `SUPABASE_PERMISSIONS_SQL` block is + now generated from a shared `supabasePermissionsSql(schemaName)` helper, with + `SUPABASE_PERMISSIONS_SQL_V3` covering the v3 schemas. + +- eb94ac8: Add guards for missing native binaries. When npm skips the platform-specific + optional dependency (a known npm bug), stash now prints actionable fix + guidance instead of a raw `MODULE_NOT_FOUND` stack trace. Adds a new + `stash doctor` command that diagnoses the runtime and native modules and works + even when a binary is missing. +- 64fdeb2: Rename `stash db install`, `stash db upgrade`, and `stash db status` to + `stash eql install`, `stash eql upgrade`, and `stash eql status`. These + commands manage the EQL extension itself, so they now live under a dedicated + `eql` command group. The old `db` spellings keep working as deprecated + aliases that print a warning pointing at the new names. All help text, + hints, generated migration headers, and wizard steps now reference the + `eql` commands. +- 5e23384: Add a command-descriptor registry and `stash manifest --json` — a structured, + versioned command surface for the docs generator and agents to consume instead + of scraping `--help`. + + - `stash manifest --json` emits `{ name, version, groups[] }`, where each command + carries its summary, optional long description, examples, and flags. `version` + comes from the CLI's own `package.json`, so a page generated from the manifest + is always stamped with the version it describes. + - `stash manifest` (no flag) prints a grouped, human-readable command list. + - The registry (`src/cli/registry.ts`) is intended to become the single source of + truth for command metadata. This is phase 1 of + `docs/plans/cli-help-and-manifest.md`; it is additive — `bin/main.ts` still + hand-maintains the `HELP` string that renders `--help`, so until the documented + follow-on renders `--help` from the registry the two are kept in sync by hand. + +- 72a3356: Add non-interactive / agent-friendly affordances so `stash init` and + `stash auth login` can run without a TTY (agents, CI, pipes). All changes are + additive — interactive behaviour in a real terminal is unchanged. + + - `--region ` / `STASH_REGION` on `stash auth login` and `stash init` + skip the interactive region picker. An unknown or missing region in a + non-TTY context now exits with an actionable message instead of hanging on + the picker (region resolution mirrors the `DATABASE_URL` resolver's + `TTY && !CI` gate). + - `stash auth login --json` emits newline-delimited device-code events. The + first event (`authorization_required`) carries the verification URL, so an + agent can trigger auth and hand the browser step to a human — only a human + completes it in the browser. `--no-open` suppresses the browser launch. + - `stash auth regions` lists the regions valid for `--region` / `STASH_REGION`; + `stash auth regions --json` emits `[{ slug, label }]` for programmatic use. + +### Patch Changes + +- aa9c4b1: Documentation: refresh package READMEs after the protectjs → stack repository rename. Fixed repository and license links, replaced dead in-repo docs links with cipherstash.com/docs URLs, rewrote the incorrect @cipherstash/nextjs README, and added guidance pointing new projects to @cipherstash/stack. +- a5f5422: Bump `@cipherstash/auth` (and its per-platform native bindings) from `0.40.0` to `0.41.0`, and migrate to its new `Result`-returning API. + + **What changed in `@cipherstash/auth` `0.41`.** Every fallible auth operation now returns a `@byteslice/result` `Result` (`{ data }` on success, `{ failure }` on error) instead of throwing. This covers strategy construction (`AccessKeyStrategy.create`, `OidcFederationStrategy.create`, `AutoStrategy.detect`, `DeviceSessionStrategy.fromProfile`), `getToken()`, and the device-code flow (`beginDeviceCodeFlow`, `pollForToken`, `openInBrowser`, `bindClientDevice`). Consumers now write `if (result.failure) …` and read `result.data` rather than `try/catch`. The `AuthError` type was renamed to **`AuthFailure`** — a discriminated union keyed by `type` (`"NOT_AUTHENTICATED"`, `"WORKSPACE_MISMATCH"`, …), replacing the old `error.code` string. + + **`@cipherstash/stack` (breaking type surface).** + + - **`AuthError` is renamed to `AuthFailure`** in the public re-exports from `@cipherstash/stack`. `AuthErrorCode` and `TokenResult` are unchanged. Anyone importing `AuthError` from `@cipherstash/stack` must switch to `AuthFailure`. + - The WASM-inline access-key path (`resolveStrategy`, used by `@cipherstash/stack/wasm-inline`'s `Encryption()`) now unwraps the `Result` from `AccessKeyStrategy.create`. A construction failure (e.g. an invalid CRN or access key) throws a descriptive `[encryption]` error naming the `AuthFailure.type` instead of surfacing the raw auth error. + - Bump `@cipherstash/protect-ffi` from `0.27.0` to `0.28.0`. auth `0.41`'s `getToken()` returns the token inside a `Result` envelope; protect-ffi `0.28` unwraps it (`.data.token`) inside its WASM `newClient`, whereas `0.27` read `.token` off the envelope and got `undefined` — which failed the WASM encrypt/decrypt round-trip with `token field is not a string`. `0.28` is the floor for the WASM path under auth `0.41`. + + **`stash` (CLI) and `@cipherstash/wizard`.** Internal auth call sites (`stash auth login`, device binding, `init` auth check, and the wizard's token acquisition / prerequisite check) were updated to unwrap `Result` and branch on `failure.type`. Behaviour is preserved — auth failures still surface the same way to end users; no CLI/wizard API changed. + + - @cipherstash/migrate@0.2.0 + ## 0.16.0 ### Minor Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 997ac703..2c89e97c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "stash", - "version": "0.16.0", + "version": "0.17.0", "description": "CipherStash CLI — the one stash command for auth, init, encryption schema, database setup, and secrets.", "repository": { "type": "git", diff --git a/packages/drizzle/CHANGELOG.md b/packages/drizzle/CHANGELOG.md index a20f90d6..b0d308a6 100644 --- a/packages/drizzle/CHANGELOG.md +++ b/packages/drizzle/CHANGELOG.md @@ -1,5 +1,11 @@ # @cipherstash/drizzle +## 3.0.3 + +### Patch Changes + +- aa9c4b1: Documentation: refresh package READMEs after the protectjs → stack repository rename. Fixed repository and license links, replaced dead in-repo docs links with cipherstash.com/docs URLs, rewrote the incorrect @cipherstash/nextjs README, and added guidance pointing new projects to @cipherstash/stack. + ## 3.0.2 ### Patch Changes diff --git a/packages/drizzle/package.json b/packages/drizzle/package.json index 725bf38c..73cbfd00 100644 --- a/packages/drizzle/package.json +++ b/packages/drizzle/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/drizzle", - "version": "3.0.2", + "version": "3.0.3", "description": "CipherStash Protect.js Drizzle ORM integration for TypeScript", "keywords": [ "encrypted", diff --git a/packages/nextjs/CHANGELOG.md b/packages/nextjs/CHANGELOG.md index a63adc09..f12887ac 100644 --- a/packages/nextjs/CHANGELOG.md +++ b/packages/nextjs/CHANGELOG.md @@ -1,5 +1,11 @@ # @cipherstash/nextjs +## 4.1.1 + +### Patch Changes + +- aa9c4b1: Documentation: refresh package READMEs after the protectjs → stack repository rename. Fixed repository and license links, replaced dead in-repo docs links with cipherstash.com/docs URLs, rewrote the incorrect @cipherstash/nextjs README, and added guidance pointing new projects to @cipherstash/stack. + ## 4.1.0 ### Minor Changes diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index 8bc71ef1..26cbb528 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/nextjs", - "version": "4.1.0", + "version": "4.1.1", "description": "Nextjs package for use with @cipherstash/protect", "keywords": [ "encrypted", diff --git a/packages/prisma-next/CHANGELOG.md b/packages/prisma-next/CHANGELOG.md index 0625ee41..c1bb5907 100644 --- a/packages/prisma-next/CHANGELOG.md +++ b/packages/prisma-next/CHANGELOG.md @@ -1,5 +1,19 @@ # @cipherstash/prisma-next +## 0.3.2 + +### Patch Changes + +- Updated dependencies [cc62407] +- Updated dependencies [5e4f354] +- Updated dependencies [4ceefed] +- Updated dependencies [cb34d71] +- Updated dependencies [aa9c4b1] +- Updated dependencies [90d19fb] +- Updated dependencies [a5f5422] +- Updated dependencies [35b9ed6] + - @cipherstash/stack@0.19.0 + ## 0.3.1 ### Patch Changes diff --git a/packages/prisma-next/package.json b/packages/prisma-next/package.json index c0db088f..fb7f55a1 100644 --- a/packages/prisma-next/package.json +++ b/packages/prisma-next/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/prisma-next", - "version": "0.3.1", + "version": "0.3.2", "license": "MIT", "author": "CipherStash ", "description": "CipherStash extension for Prisma Next: searchable application-layer field-level encryption for Postgres, with six encrypted column types, 17 query operators, bulk encrypt/decrypt middleware, and a baseline migration that installs the vendored EQL bundle SQL byte-for-byte.", diff --git a/packages/protect-dynamodb/CHANGELOG.md b/packages/protect-dynamodb/CHANGELOG.md index 35a1a189..0b8b9905 100644 --- a/packages/protect-dynamodb/CHANGELOG.md +++ b/packages/protect-dynamodb/CHANGELOG.md @@ -1,5 +1,13 @@ # @cipherstash/protect-dynamodb +## 12.0.1 + +### Patch Changes + +- aa9c4b1: Documentation: refresh package READMEs after the protectjs → stack repository rename. Fixed repository and license links, replaced dead in-repo docs links with cipherstash.com/docs URLs, rewrote the incorrect @cipherstash/nextjs README, and added guidance pointing new projects to @cipherstash/stack. +- Updated dependencies [aa9c4b1] + - @cipherstash/protect@12.0.1 + ## 12.0.0 ### Patch Changes diff --git a/packages/protect-dynamodb/package.json b/packages/protect-dynamodb/package.json index 69bf2fdf..48ea68ee 100644 --- a/packages/protect-dynamodb/package.json +++ b/packages/protect-dynamodb/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/protect-dynamodb", - "version": "12.0.0", + "version": "12.0.1", "description": "Protect.js DynamoDB Helpers", "keywords": [ "dynamodb", diff --git a/packages/protect/CHANGELOG.md b/packages/protect/CHANGELOG.md index 4328280d..88f26a07 100644 --- a/packages/protect/CHANGELOG.md +++ b/packages/protect/CHANGELOG.md @@ -1,5 +1,13 @@ # @cipherstash/protect +## 12.0.1 + +### Patch Changes + +- aa9c4b1: Documentation: refresh package READMEs after the protectjs → stack repository rename. Fixed repository and license links, replaced dead in-repo docs links with cipherstash.com/docs URLs, rewrote the incorrect @cipherstash/nextjs README, and added guidance pointing new projects to @cipherstash/stack. +- Updated dependencies [aa9c4b1] + - @cipherstash/schema@3.0.1 + ## 12.0.0 ### Major Changes diff --git a/packages/protect/package.json b/packages/protect/package.json index 8c8cd3bc..25478789 100644 --- a/packages/protect/package.json +++ b/packages/protect/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/protect", - "version": "12.0.0", + "version": "12.0.1", "description": "CipherStash Protect for JavaScript", "keywords": [ "encrypted", diff --git a/packages/schema/CHANGELOG.md b/packages/schema/CHANGELOG.md index 79140417..3fb9edcf 100644 --- a/packages/schema/CHANGELOG.md +++ b/packages/schema/CHANGELOG.md @@ -1,5 +1,11 @@ # @cipherstash/schema +## 3.0.1 + +### Patch Changes + +- aa9c4b1: Documentation: refresh package READMEs after the protectjs → stack repository rename. Fixed repository and license links, replaced dead in-repo docs links with cipherstash.com/docs URLs, rewrote the incorrect @cipherstash/nextjs README, and added guidance pointing new projects to @cipherstash/stack. + ## 3.0.0 ### Major Changes diff --git a/packages/schema/package.json b/packages/schema/package.json index a18e3d68..2211dfc5 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/schema", - "version": "3.0.0", + "version": "3.0.1", "description": "CipherStash schema builder for TypeScript", "keywords": [ "encrypted", diff --git a/packages/stack/CHANGELOG.md b/packages/stack/CHANGELOG.md index ff6208f9..4a97e92c 100644 --- a/packages/stack/CHANGELOG.md +++ b/packages/stack/CHANGELOG.md @@ -1,5 +1,178 @@ # @cipherstash/stack +## 0.19.0 + +### Minor Changes + +- cc62407: Add EQL v3 Supabase support, baselined on the `eql-3.0.0-alpha.2` release. + + `@cipherstash/stack/supabase` gains `encryptedSupabaseV3` — the EQL v3 + counterpart of `encryptedSupabase` for schemas authored with + `@cipherstash/stack/eql/v3`. The public surface and call shape are identical + to v2 (same filter methods, `withLockContext`, `audit`); only the schema type + and wire encoding differ. + + **The v3 surface** is the `eql-3.0.0-alpha.2` release artifact: domains use + SQL-standard type names (`eql_v3.integer_ord`, `eql_v3.timestamp_ord`, + `eql_v3.boolean`, … mirrored by `types.IntegerOrd`, `types.TimestampOrd`, + `types.Boolean`, …), SEM internals live in a separate `eql_v3_internal` + schema (grant it roles, never expose it — only `eql_v3` goes in Supabase's + Exposed schemas), and envelopes are versioned `v: 3`. Envelope production + rides on `@cipherstash/protect-ffi` 0.27, which takes an `eqlVersion` so the + same client emits v2 or v3 payloads per schema. + + **Adapter behaviour:** + + - columns are stored in their native `eql_v3.*` domains (raw jsonb payloads, + no composite wrap), with JS property → DB column name resolution and `Date` + reconstruction from `cast_as` on decrypted rows; + - **INTERIM:** filter operands are full storage envelopes — every `eql_v3.*` + domain CHECK requires the storage keys, and the SQL operators coerce their + operand into the domain, so a term-only operand is rejected today. This is + a tracked workaround (Linear CIP-3402), not the design: a full-envelope + operand carries a real decryptable ciphertext plus all of the column's + index terms, and PostgREST filters travel in GET query strings, so operands + can land in URL logs, proxies, and Supabase request logs (query terms are + index-terms-only by design). The fix is an EQL-side term-only scalar query + envelope (the scalar analog of `eql_v3.jsonb_query`); + - `like`/`ilike` on encrypted columns are emitted as PostgREST `cs` + (bloom-filter `@>`) — the v3 domains define no LIKE operator. Substring + search currently also requires `include_original: false` on the match + index; that requirement is a symptom of the same interim full-envelope + operand and goes away with CIP-3402; + - filters on storage-only columns (e.g. `types.Boolean`) and null filter + values are rejected at the type level and at runtime. + + The v3 builder's default row type is exactly the table's inferred plaintext + shape (no index-signature widening — widening would disable the storage-only + filter guard). Filtering or inserting plaintext passthrough columns requires + an explicit row type: `es.from('users', users)`. + + The CLI gains an EQL v3 path: `stash eql install --eql-version 3` installs the + vendored `eql-3.0.0-alpha.2` bundle (`--supabase` selects the opclass-stripped + variant and applies the role grants for both `eql_v3` and `eql_v3_internal`); + `stash db upgrade` also accepts `--eql-version`, and `stash db status` reports + v2 and v3 installs independently. The v2 `SUPABASE_PERMISSIONS_SQL` block is + now generated from a shared `supabasePermissionsSql(schemaName)` helper, with + `SUPABASE_PERMISSIONS_SQL_V3` covering the v3 schemas. + +- 5e4f354: Add the EQL v3 `text_search` authoring DSL on a new `@cipherstash/stack/eql/v3` + subpath (`types.TextSearch`, v3 `encryptedTable` / `buildEncryptConfig`). The v3 + builders emit the existing `EncryptConfig` shape, so encryption, payloads, and + query paths are unchanged at runtime. + + Also widens the public client types (`EncryptionClientConfig.schemas`, + `EncryptOptions`, `SearchTerm`/`EncryptQueryOptions`) to a structural contract so + both v2 and v3 builders are accepted by `Encryption` / `encrypt` / `decrypt` / + `encryptQuery`. This is a backward-compatible widening — existing v2 usage is + unaffected. The structural contracts themselves (`BuildableColumn`, + `BuildableQueryColumn`, `BuildableV3QueryableColumn`, `BuildableTable`, + `BuildableTableColumns`) and the `encryptModel` return-type mapper + (`EncryptedFromBuildableTable`) are exported from `@cipherstash/stack/types` so + consumers can name them. + +- 4ceefed: Add a strongly-typed EQL v3 client surface on a new `@cipherstash/stack/v3` + subpath (`EncryptionV3`, `typedClient`, `TypedEncryptionClient`). It re-exports + the v3 `types` namespace and table API (from `@cipherstash/stack/eql/v3`), so a + single import provides everything needed to author and use a v3 schema. + + Every method derives its types from the concrete `table` / `column` builder + arguments: + + - `encrypt` / `encryptQuery` pin the plaintext to the column's domain type + (`text → string`, `int8 → bigint`, `timestamptz → Date`, …). + - `encryptQuery` constrains `queryType` to the column's capabilities and rejects + storage-only columns at compile time. + - `encryptModel` / `bulkEncryptModels` validate schema-column fields against their + inferred plaintext type (passthrough fields are untouched) and return a precise + encrypted model. + - `decryptModel` / `bulkDecryptModels` return the precise plaintext model, + reconstructing `Date` / `bigint` values from the encrypt-config `cast_as`. + + Because the typed methods bind to the concrete branded v3 classes, a hand-rolled + structural table/column is rejected — closing the soundness gap where a non-branded + table could be encrypted at runtime while typed as plaintext. + + Runtime behaviour is unchanged: the encrypt/query paths return the same operations + as the base client; only the model-decrypt paths add a per-column `Date` / `bigint` + reconstruction step. The v2 client surface (`Encryption`) is untouched. + +- cb34d71: Add EQL v3 schema builders for all generated SQL domains under `@cipherstash/stack/eql/v3`, exposed as the `types` namespace (one member per EQL v3 domain, e.g. `types.TextEq` / `types.Int4Ord` / `types.Timestamptz`), including explicit query capability metadata (`getQueryCapabilities()` / `isQueryable()`) and v3 table support in model encryption helpers (`encryptModel` / `bulkEncryptModels`). + + Also widen the accepted plaintext input type for `encrypt` / `encryptQuery` to include `Date` and `bigint` (via the new `Plaintext` type), so v3 `date` / `timestamptz` / `int8` domains can be encrypted and queried with their natural JavaScript values. + +- 90d19fb: Rename the encryption client's auth strategy config field from `config.strategy` to **`config.authStrategy`** to make its purpose clear, and expand the `Encryption()` TypeDoc with a full authentication and keysets walkthrough. + + **`config.authStrategy`** is the new, documented field for supplying an auth strategy (`OidcFederationStrategy`, `AccessKeyStrategy`, or any `{ getToken() }` object). **`config.strategy` is retained as a deprecated alias** — passing it still works and forwards to the client, but logs a one-time runtime deprecation warning. When both are set, `authStrategy` wins (and the deprecation warning still fires so the leftover field gets cleaned up). + + ```ts + import { Encryption, OidcFederationStrategy } from "@cipherstash/stack"; + + const client = await Encryption({ + schemas: [users], + config: { + authStrategy: OidcFederationStrategy.create(workspaceCrn, () => + getUserJwt() + ), + }, + }); + ``` + + **Migration:** rename `config.strategy` → `config.authStrategy`. No behavioural change beyond the deprecation warning; the field is forwarded to protect-ffi's `strategy` option exactly as before. + + The `Encryption()` TypeDoc now documents the default `auto` strategy (env vars → local dev profile via `npx stash auth login`), the four `CS_*` production/CI variables, custom strategies (`AccessKeyStrategy`, `OidcFederationStrategy`), lock context, and keysets for multi-tenant isolation. + + The `@cipherstash/stack/wasm-inline` entry (Deno / Edge / Workers / Bun) gets the same rename so the Node and WASM interfaces stay in sync: `WasmClientConfig.authStrategy` is the documented field, `strategy` is a deprecated alias that still works and warns at runtime. + +- a5f5422: Bump `@cipherstash/auth` (and its per-platform native bindings) from `0.40.0` to `0.41.0`, and migrate to its new `Result`-returning API. + + **What changed in `@cipherstash/auth` `0.41`.** Every fallible auth operation now returns a `@byteslice/result` `Result` (`{ data }` on success, `{ failure }` on error) instead of throwing. This covers strategy construction (`AccessKeyStrategy.create`, `OidcFederationStrategy.create`, `AutoStrategy.detect`, `DeviceSessionStrategy.fromProfile`), `getToken()`, and the device-code flow (`beginDeviceCodeFlow`, `pollForToken`, `openInBrowser`, `bindClientDevice`). Consumers now write `if (result.failure) …` and read `result.data` rather than `try/catch`. The `AuthError` type was renamed to **`AuthFailure`** — a discriminated union keyed by `type` (`"NOT_AUTHENTICATED"`, `"WORKSPACE_MISMATCH"`, …), replacing the old `error.code` string. + + **`@cipherstash/stack` (breaking type surface).** + + - **`AuthError` is renamed to `AuthFailure`** in the public re-exports from `@cipherstash/stack`. `AuthErrorCode` and `TokenResult` are unchanged. Anyone importing `AuthError` from `@cipherstash/stack` must switch to `AuthFailure`. + - The WASM-inline access-key path (`resolveStrategy`, used by `@cipherstash/stack/wasm-inline`'s `Encryption()`) now unwraps the `Result` from `AccessKeyStrategy.create`. A construction failure (e.g. an invalid CRN or access key) throws a descriptive `[encryption]` error naming the `AuthFailure.type` instead of surfacing the raw auth error. + - Bump `@cipherstash/protect-ffi` from `0.27.0` to `0.28.0`. auth `0.41`'s `getToken()` returns the token inside a `Result` envelope; protect-ffi `0.28` unwraps it (`.data.token`) inside its WASM `newClient`, whereas `0.27` read `.token` off the envelope and got `undefined` — which failed the WASM encrypt/decrypt round-trip with `token field is not a string`. `0.28` is the floor for the WASM path under auth `0.41`. + + **`stash` (CLI) and `@cipherstash/wizard`.** Internal auth call sites (`stash auth login`, device binding, `init` auth check, and the wizard's token acquisition / prerequisite check) were updated to unwrap `Result` and branch on `failure.type`. Behaviour is preserved — auth failures still surface the same way to end users; no CLI/wizard API changed. + +- 35b9ed6: Bump `@cipherstash/protect-ffi` to `0.26.0` and `@cipherstash/auth` to `0.40.0`, and replace the lock-context token ceremony with a strategy-based approach for identity-bound encryption. + + **protect-ffi `0.26.0`** supersedes `0.25.0`. The public API is unchanged from `0.25` (internal fixes only). As in `0.25`, `serviceToken` is gone from the encrypt / decrypt / query option types; auth flows through the client's strategy / credentials, and lock contexts travel as `lockContext.identityClaim`. The WASM-inline path takes a single options object with the auth strategy nested under `strategy`, and `Encryption()` config uses **`workspaceCrn`** (`CS_WORKSPACE_CRN`) as the single source of truth — `CS_REGION` is no longer consulted. On that path `workspaceCrn` is required only alongside an `accessKey` (it derives the region); with a pre-built `strategy` it is **optional**, since the strategy already carries the CRN. + + **Strategy-based, identity-bound encryption.** `OidcFederationStrategy` federates an end user's third-party OIDC JWT (Clerk, Supabase, Auth0, …) into a CTS service token. As of `@cipherstash/auth` `0.40` it takes a `workspaceCrn` (region derived from the CRN), matching `AccessKeyStrategy`. Pass it as `config.strategy` so every ZeroKMS request authenticates _as that user_, then bind the data key to a claim with `.withLockContext({ identityClaim })`: + + ```ts + import { Encryption, OidcFederationStrategy } from "@cipherstash/stack"; + + const client = await Encryption({ + schemas: [users], + config: { + strategy: OidcFederationStrategy.create(workspaceCrn, () => getUserJwt()), + }, + }); + + await client + .encrypt("alice@example.com", { column: users.email, table: users }) + .withLockContext({ identityClaim: ["sub"] }); + ``` + + This replaces the old ceremony (`new LockContext()` → `await lc.identify(jwt)` → `.withLockContext(lc)`), which relied on a per-operation CTS token that protect-ffi removed in `0.25`. + + - **`.withLockContext()`** now accepts a plain `{ identityClaim }` object (as well as a `LockContext`) and no longer requires a CTS token or an `identify()` call — it carries the identity claim only. + - **`LockContext.identify()` / `getLockContext()`** are **deprecated** (kept for backwards compatibility); the strategy handles token acquisition. + - **Strategies are re-exported** from `@cipherstash/stack` (`OidcFederationStrategy`, `AccessKeyStrategy`, `AutoStrategy`, `DeviceSessionStrategy`) and from `@cipherstash/stack/wasm-inline` (`OidcFederationStrategy`, `AccessKeyStrategy`) so integrators don't need a separate `@cipherstash/auth` install. `AuthStrategy` remains re-exported for the structural type. + + **Migrating `region` → `workspaceCrn` (WASM-inline).** If you previously passed `region` (or relied on `CS_REGION`) to the WASM-inline `Encryption()` path, replace it with your workspace CRN: set `workspaceCrn` in config (or `CS_WORKSPACE_CRN` in the environment) to the value shown in the CipherStash dashboard (`crn:.aws:` — it embeds the region, which is now derived from it). `region` is ignored if passed. + + **Lock-context enforcement is now server-side only.** Because the client no longer resolves a per-user CTS token at `withLockContext` time, it also cannot fail fast there: a wrong or missing identity claim surfaces as a ZeroKMS **decryption failure** (the data key simply doesn't unlock), not as a client-side error before the request. The cryptographic guarantee is unchanged — enforcement happens in ZeroKMS — but anyone relying on the old client-side throw for early feedback should assert on the operation's `failure` result instead. + + Existing credential / env behaviour is preserved when `config.strategy` is omitted. + +### Patch Changes + +- aa9c4b1: Documentation: refresh package READMEs after the protectjs → stack repository rename. Fixed repository and license links, replaced dead in-repo docs links with cipherstash.com/docs URLs, rewrote the incorrect @cipherstash/nextjs README, and added guidance pointing new projects to @cipherstash/stack. + ## 0.18.0 ### Minor Changes diff --git a/packages/stack/package.json b/packages/stack/package.json index 5efb71b2..d73f60b1 100644 --- a/packages/stack/package.json +++ b/packages/stack/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/stack", - "version": "0.18.0", + "version": "0.19.0", "description": "CipherStash Stack for TypeScript and JavaScript", "keywords": [ "encrypted", diff --git a/packages/wizard/CHANGELOG.md b/packages/wizard/CHANGELOG.md index a96c6831..aef9d034 100644 --- a/packages/wizard/CHANGELOG.md +++ b/packages/wizard/CHANGELOG.md @@ -1,5 +1,37 @@ # @cipherstash/wizard +## 0.4.0 + +### Minor Changes + +- 64fdeb2: Rename `stash db install`, `stash db upgrade`, and `stash db status` to + `stash eql install`, `stash eql upgrade`, and `stash eql status`. These + commands manage the EQL extension itself, so they now live under a dedicated + `eql` command group. The old `db` spellings keep working as deprecated + aliases that print a warning pointing at the new names. All help text, + hints, generated migration headers, and wizard steps now reference the + `eql` commands. + +### Patch Changes + +- a5f5422: Bump `@cipherstash/auth` (and its per-platform native bindings) from `0.40.0` to `0.41.0`, and migrate to its new `Result`-returning API. + + **What changed in `@cipherstash/auth` `0.41`.** Every fallible auth operation now returns a `@byteslice/result` `Result` (`{ data }` on success, `{ failure }` on error) instead of throwing. This covers strategy construction (`AccessKeyStrategy.create`, `OidcFederationStrategy.create`, `AutoStrategy.detect`, `DeviceSessionStrategy.fromProfile`), `getToken()`, and the device-code flow (`beginDeviceCodeFlow`, `pollForToken`, `openInBrowser`, `bindClientDevice`). Consumers now write `if (result.failure) …` and read `result.data` rather than `try/catch`. The `AuthError` type was renamed to **`AuthFailure`** — a discriminated union keyed by `type` (`"NOT_AUTHENTICATED"`, `"WORKSPACE_MISMATCH"`, …), replacing the old `error.code` string. + + **`@cipherstash/stack` (breaking type surface).** + + - **`AuthError` is renamed to `AuthFailure`** in the public re-exports from `@cipherstash/stack`. `AuthErrorCode` and `TokenResult` are unchanged. Anyone importing `AuthError` from `@cipherstash/stack` must switch to `AuthFailure`. + - The WASM-inline access-key path (`resolveStrategy`, used by `@cipherstash/stack/wasm-inline`'s `Encryption()`) now unwraps the `Result` from `AccessKeyStrategy.create`. A construction failure (e.g. an invalid CRN or access key) throws a descriptive `[encryption]` error naming the `AuthFailure.type` instead of surfacing the raw auth error. + - Bump `@cipherstash/protect-ffi` from `0.27.0` to `0.28.0`. auth `0.41`'s `getToken()` returns the token inside a `Result` envelope; protect-ffi `0.28` unwraps it (`.data.token`) inside its WASM `newClient`, whereas `0.27` read `.token` off the envelope and got `undefined` — which failed the WASM encrypt/decrypt round-trip with `token field is not a string`. `0.28` is the floor for the WASM path under auth `0.41`. + + **`stash` (CLI) and `@cipherstash/wizard`.** Internal auth call sites (`stash auth login`, device binding, `init` auth check, and the wizard's token acquisition / prerequisite check) were updated to unwrap `Result` and branch on `failure.type`. Behaviour is preserved — auth failures still surface the same way to end users; no CLI/wizard API changed. + +- 17f4745: Add `@anthropic-ai/sdk` `^0.106.0` as a direct dependency so the + auto-installed peer of `@anthropic-ai/claude-agent-sdk` resolves to a release + patched against GHSA-p7fg-763f-g4gf, instead of the vulnerable 0.81.0 the + peer range alone would select. The wizard never imports the SDK directly — + this is a peer-resolution pin only; no behaviour change. + ## 0.3.0 ### Minor Changes diff --git a/packages/wizard/package.json b/packages/wizard/package.json index 6483c36b..70a6d071 100644 --- a/packages/wizard/package.json +++ b/packages/wizard/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/wizard", - "version": "0.3.0", + "version": "0.4.0", "description": "AI-powered encryption setup for CipherStash. Reads your codebase, picks columns to encrypt, and wires everything up.", "repository": { "type": "git",