diff --git a/.cursor/commands/create-example-app.md b/.cursor/commands/create-example-app.md index 1125be0b..d9afd104 100644 --- a/.cursor/commands/create-example-app.md +++ b/.cursor/commands/create-example-app.md @@ -1,10 +1,11 @@ -# Cursor Super-Prompt: Protect.js Example Apps (Framework/ORM-Agnostic, No-Cheese) +# Cursor Super-Prompt: CipherStash Stack Example Apps (Framework/ORM-Agnostic, No-Cheese) ROLE -You are a senior systems engineer focused on developer experience and a core maintainer of `@cipherstash/protect`. Your mission: create a polished set of runnable **Protect.js example apps** across multiple stacks. Each example must be minimal, factual, and runnable in minutes. +You are a senior systems engineer focused on developer experience and a core maintainer of `@cipherstash/stack`. Your mission: create a polished set of runnable **CipherStash Stack example apps** across multiple stacks. Each example must be minimal, factual, and runnable in minutes. GROUNDING & SOURCES (use @ref; do not guess) -- Protect.js APIs: the Protect.js main README is the single source of truth. If not accessible, STOP and ask for the exact snippet/repo path. Do not invent APIs. +- Stack APIs: the main repo README and https://cipherstash.com/docs are the source of truth (`Encryption({ schemas })`, `encryptedTable`, `encryptedColumn`). If not accessible, STOP and ask for the exact snippet/repo path. Do not invent APIs. +- `@cipherstash/protect-ffi` is a native Node-API module: examples that bundle (Next.js, SST) must externalize it. See https://cipherstash.com/docs/stack/deploy/bundling - ORM/DB docs (pick per stack): @ref https://www.prisma.io/docs @ref https://typeorm.io @@ -26,7 +27,7 @@ STACK MATRIX (generate now) Optional (time-permitting): nextjs-prisma (App Router), fastify-knex. NO-CHEESE RULES (hard requirements) -Goal: smallest possible working example that clearly demonstrates Protect.js. Clarity > patterns > abstractions. +Goal: smallest possible working example that clearly demonstrates CipherStash Stack. Clarity > patterns > abstractions. DON'TS - No Singletons/Factories/Service-Locators/DI frameworks. - No ports & adapters/custom repo abstractions for tiny demos—call the ORM/client directly. @@ -41,7 +42,7 @@ README tone --- Simplicity budget (per example) - ≤ 8 TS source files (excluding migrations). -- Deps: ORM/client + `@cipherstash/protect` + dev tooling (ts-node or tsx). Nothing else unless required by the stack. +- Deps: ORM/client + `@cipherstash/stack` + dev tooling (ts-node or tsx). Nothing else unless required by the stack. - One `.env.example`; use `dotenv`. No layered config. CODE STYLE @@ -61,8 +62,8 @@ REQUIRED DX & SCRIPTS (per example) - `seed` → seed sensible data - `demo` → prints proof of encryption & queries - `typecheck` → `tsc --noEmit` -- `.env.example` includes DB vars and **exact** Protect.js env names from the Protect README (do not invent): - {{PROTECT_ENV_VARS := "e.g., PROTECT_PROJECT_ID, PROTECT_CLIENT_KEY, PROTECT_SERVER_URL (replace with real names from README)"}} +- Local dev auth: prefer the CipherStash profile via `npx stash auth login` (no env vars needed). For CI/deployment, `.env.example` includes DB vars and the **exact** CipherStash env names (do not invent): + `CS_WORKSPACE_CRN`, `CS_CLIENT_ID`, `CS_CLIENT_KEY`, `CS_CLIENT_ACCESS_KEY` PROJECT LAYOUT (monorepo, minimal) - Root: @@ -80,10 +81,10 @@ README REQUIREMENTS (every example) - AI banner (exact text) at the very top with {{BOOK_CHAT_URL}}. - 90-second Quickstart (copy/paste only). - "What this shows" checklist (encrypted fields, CRUD, query). -- "How encryption works here" (short, accurate, tied to Protect.js). +- "How encryption works here" (short, accurate, tied to CipherStash Stack). - Config notes for the stack (e.g., why CJS for TypeORM). -- Troubleshooting (ESM/CJS, ts-node/tsx, migration pitfalls). -- `@ref` links to stack docs + Protect README. +- Troubleshooting (ESM/CJS, ts-node/tsx, migration pitfalls, native module externalization). +- `@ref` links to https://cipherstash.com/docs + the repo README. DELIVERABLES (return in one message/PR) - Root `README.md` + `docker-compose.yml`. @@ -118,4 +119,3 @@ OUTPUT FORMAT VARIABLES TO FILL BEFORE RUN - {{BOOK_CHAT_URL}} = your booking link - {{STACKS}} = list of stacks to generate -- {{PROTECT_ENV_VARS}} = exact names from Protect.js README diff --git a/.cursorrules b/.cursorrules deleted file mode 100644 index 44f58103..00000000 --- a/.cursorrules +++ /dev/null @@ -1,50 +0,0 @@ -## Protect.js Cursor Rules - -These rules guide agents when creating or updating example apps under `examples/*` in this repository. - -### Example App Prompt (for agents) - -- **Goals** - - Show end-to-end usage of Protect.js with clear, minimal code. - - Demonstrate schema, encrypt/decrypt, and (when relevant) searchable encryption on PostgreSQL. - -- **Hard guardrails (do not violate)** - - Do not log plaintext at any time. - - Preserve the Result contract: operations return `{ data }` or `{ failure }` with stable error `type` strings. - - Do not change EQL payload shapes or keys (e.g., `c`). - - `@cipherstash/protect-ffi` is a native Node-API module and must be externalized by bundlers (loaded via runtime `require`). - - Keep both ESM and CJS exports working; do not break `require`. - -- **Prerequisites and workflow** - - Use Node.js >= 22 and pnpm 9.x. - - Install/build/test: - - `pnpm install` - - `pnpm --filter dev|build|test` - - Environment variables for examples/tests that talk to CipherStash: - - `CS_WORKSPACE_CRN`, `CS_CLIENT_ID`, `CS_CLIENT_KEY`, `CS_CLIENT_ACCESS_KEY` - - Optional for identity-aware encryption: `USER_JWT`, `USER_2_JWT` - -- **Docs to reference** - - `docs/how-to/nextjs-external-packages.md` - - `docs/how-to/sst-external-packages.md` - - `docs/how-to/npm-lockfile-v3.md` - - `docs/reference/schema.md` - - `docs/concepts/searchable-encryption.md` - -- **Deliverables checklist for a new example** - - A `protect.ts` (or equivalent) that initializes `protect({ schemas })` using `csTable`/`csColumn`. - - If targeting Postgres searchable encryption, include `.freeTextSearch().equality().orderAndRange()` on appropriate columns. - - A minimal script or route/handler that encrypts and decrypts at least one value. - - A README covering: - - Setup (env vars, install, run commands) - - Notes on native module externalization if the framework builds/bundles (e.g., Next.js, SST) - - How to run tests (if included) - - Optional: demonstrate identity-aware encryption via `LockContext` and chaining `.withLockContext()` for both encrypt and decrypt. - -- **Quality bar** - - Prefer bulk operations to demonstrate performance where appropriate. - - Keep examples small, idiomatic, and runnable as-is with documented env vars. - - Never leak secrets in code or logs; avoid any plaintext logging. - - - diff --git a/.github/ISSUE_TEMPLATE/docs-feedback.yml b/.github/ISSUE_TEMPLATE/docs-feedback.yml index 715ab346..0aa2ad9c 100644 --- a/.github/ISSUE_TEMPLATE/docs-feedback.yml +++ b/.github/ISSUE_TEMPLATE/docs-feedback.yml @@ -35,7 +35,7 @@ body: id: terms attributes: label: Code of conduct - description: By submitting this issue, you agree to follow our [Code of conduct](https://github.com/cipherstash/protectjs/blob/main/CODE_OF_CONDUCT.md). + description: By submitting this issue, you agree to follow our [Code of conduct](https://github.com/cipherstash/stack/blob/main/CODE_OF_CONDUCT.md). options: - label: I agree to follow this project's Code of conduct required: true diff --git a/AGENTS.md b/AGENTS.md index d242ff53..5a664f56 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -This is the Protect.js repository - End-to-end, per-value encryption for JavaScript/TypeScript with zero‑knowledge key management (via CipherStash ZeroKMS). Encrypted data is stored as EQL JSON payloads; searchable encryption is currently supported for PostgreSQL. +This is the CipherStash Stack repository (`cipherstash/stack`) - End-to-end, per-value encryption for JavaScript/TypeScript with zero‑knowledge key management (via CipherStash ZeroKMS). Encrypted data is stored as EQL JSON payloads; searchable encryption is currently supported for PostgreSQL. ## Prerequisites @@ -72,20 +72,26 @@ If these variables are missing, tests that require live encryption will fail or ## Repository Layout - `packages/stack`: Main package (`@cipherstash/stack`) containing the encryption client and all integrations - - Subpath exports: `@cipherstash/stack`, `@cipherstash/stack/schema`, `@cipherstash/stack/identity`, `@cipherstash/stack/secrets`, `@cipherstash/stack/drizzle`, `@cipherstash/stack/supabase`, `@cipherstash/stack/dynamodb`, `@cipherstash/stack/client`, `@cipherstash/stack/types` + - Subpath exports: `@cipherstash/stack`, `@cipherstash/stack/client`, `@cipherstash/stack/identity`, `@cipherstash/stack/secrets`, `@cipherstash/stack/schema`, `@cipherstash/stack/types`, `@cipherstash/stack/drizzle`, `@cipherstash/stack/dynamodb`, `@cipherstash/stack/supabase`, `@cipherstash/stack/encryption`, `@cipherstash/stack/errors`, `@cipherstash/stack/wasm-inline` - `packages/protect`: Core encryption library (internal, re-exported via `@cipherstash/stack`) - `src/index.ts`: Public API (`Encryption`, exports) - `src/ffi/index.ts`: `EncryptionClient` implementation, bridges to `@cipherstash/protect-ffi` - `src/ffi/operations/*`: Encrypt/decrypt/model/bulk/query operations (thenable pattern with optional `.withLockContext()`) - `__tests__/*`: End-to-end and API contract tests (Vitest) +- `packages/cli`: The `stash` CLI — auth, init, encryption schema, database setup (`stash eql install`), and secrets. Has its own `AGENTS.md`. +- `packages/wizard`: AI-powered encryption setup (`@cipherstash/wizard`) +- `packages/migrate`: Plaintext-to-encrypted column migration (`@cipherstash/migrate`) — resumable backfill, per-column state +- `packages/prisma-next`: Prisma Next integration (`@cipherstash/prisma-next`) — searchable field-level encryption for Postgres - `packages/schema`: Schema builder utilities and types (`encryptedTable`, `encryptedColumn`, `encryptedField`) - `packages/drizzle`: Drizzle ORM integration (`encryptedType`, `extractEncryptionSchema`, `createEncryptionOperators`) - `packages/nextjs`: Next.js helpers and Clerk integration (`./clerk` export) - `packages/protect-dynamodb`: DynamoDB helpers (`encryptedDynamoDB`) - `packages/utils`: Shared config (`utils/config`) and logger (`utils/logger`) -- `examples/*`: Working apps (basic, drizzle, nextjs-clerk, next-drizzle-mysql, dynamo, hono-supabase) -- `docs/*`: Concepts, how-to guides (Next.js bundling, SST, npm lockfile v3), reference -- `skills/*`: Agent skills (`stash-encryption`, `stash-drizzle`, `stash-dynamodb`, `stash-secrets`, `stash-supabase`, `stash-supply-chain-security`) +- `packages/bench`: Performance / index-engagement benchmarks (private, not published) +- `e2e/*`: Cross-package end-to-end tests (package managers, supply chain, Prisma example README) +- `examples/*`: Working apps (basic, prisma, supabase-worker) +- `docs/plans/*`: Internal design plans. User-facing documentation lives at https://cipherstash.com/docs (not in this repo). +- `skills/*`: Agent skills (`stash-cli`, `stash-encryption`, `stash-drizzle`, `stash-dynamodb`, `stash-secrets`, `stash-supabase`, `stash-supply-chain-security`) ## Supply Chain Security @@ -118,10 +124,7 @@ Three rules to remember when editing CI or pnpm config: ## Critical Gotchas (read before coding) -- **Native Node.js module**: `@cipherstash/stack` relies on `@cipherstash/protect-ffi` (Node-API). It must be loaded via native Node.js `require`. Do NOT bundle this module; configure bundlers to externalize it. - - Next.js: see `docs/how-to/nextjs-external-packages.md` - - SST/Serverless: see `docs/how-to/sst-external-packages.md` - - npm lockfile v3 on Linux: see `docs/how-to/npm-lockfile-v3.md` +- **Native module vs WASM entry**: The default `@cipherstash/stack` entry relies on `@cipherstash/protect-ffi` (Node-API) and must be loaded via native Node.js `require` — if your tooling bundles server code with it, externalize the module. For bundled or non-Node runtimes (Deno, Bun, Cloudflare Workers, Supabase Edge Functions), use `@cipherstash/stack/wasm-inline` instead: it inlines the WASM build into the JS bundle, so no externalization is needed. See the bundling guide: https://cipherstash.com/docs/stack/deploy/bundling - **Do not log plaintext**: The library never logs plaintext by design. Don't add logs that risk leaking sensitive data. - **Result shape is contract**: Operations return `{ data }` or `{ failure }`. Preserve this shape and error `type` values in `EncryptionErrorTypes`. - **Encrypted payload shape is contract**: Keys like `c` in the EQL payload are validated by tests and downstream tools. Don't change them. @@ -158,9 +161,10 @@ pnpm changeset:publish ## Bundling and Deployment Notes -- When integrating into frameworks/build tools, ensure native modules are externalized and loaded via Node's runtime require. -- For Next.js, configure `serverExternalPackages` as documented in `docs/how-to/nextjs-external-packages.md`. -- For serverless/Linux targets with npm lockfile v3, see `docs/how-to/npm-lockfile-v3.md` to avoid runtime load errors. +- Two deployment paths: + - **Native (default entry)**: keep `@cipherstash/protect-ffi` external and loaded via Node's runtime require — e.g. Next.js `serverExternalPackages`. Covers Node servers where native modules are fine. + - **WASM (`@cipherstash/stack/wasm-inline`)**: designed to be bundled — no native module, no externalization. Use for edge/serverless runtimes (Deno, Bun, Cloudflare Workers, Supabase Edge Functions) or wherever bundler externalization is awkward. +- For SST/serverless and npm-lockfile-v3 quirks on Linux, see the bundling guide: https://cipherstash.com/docs/stack/deploy/bundling ## Adding Features Safely (LLM checklist) @@ -175,8 +179,13 @@ pnpm changeset:publish - `pnpm run code:fix` - `pnpm --filter build` - `pnpm --filter test` -6. Update docs in `docs/*` and usage examples if APIs change. -7. **Add a changeset before opening or finalising the PR** when the +6. If APIs change, update usage examples in this repo and flag that the docs site (cipherstash.com/docs, maintained separately) needs a corresponding update. +7. **Keep the meta files honest.** If your change adds/removes/renames a + package, example, skill, or subpath export, update the Repository + Layout in this file and the package list in `SECURITY.md` in the + same PR. These files have drifted badly before; don't let them. + +8. **Add a changeset before opening or finalising the PR** when the change affects a published package's public behaviour or surface (new feature, bug fix, breaking change, UX-visible tweak). Run `pnpm changeset` (interactive) or hand-write a markdown file under @@ -198,26 +207,21 @@ pnpm changeset:publish `CHANGELOG.md` entries, so a missing changeset means the change ships invisibly. -## Useful Links in this repo +## Useful Links - `README.md` for quickstart and feature overview -- `docs/concepts/searchable-encryption.md` -- `docs/concepts/aws-kms-vs-cipherstash-comparison.md` -- `docs/reference/schema.md` -- `docs/reference/searchable-encryption-postgres.md` -- `docs/reference/configuration.md` -- `docs/reference/identity.md` -- `docs/reference/secrets.md` -- `docs/reference/dynamodb.md` -- `docs/reference/supabase-sdk.md` -- `docs/reference/drizzle/drizzle.md` -- `docs/how-to/nextjs-external-packages.md` -- `docs/how-to/sst-external-packages.md` -- `docs/how-to/npm-lockfile-v3.md` +- `packages/cli/AGENTS.md` for CLI-specific guidance +- `e2e/README.md` for the cross-package E2E suite +- `skills/*/SKILL.md` for per-integration agent guides +- User-facing docs (concepts, reference, how-to) live on the docs site: + - https://cipherstash.com/docs + - https://cipherstash.com/docs/stack/quickstart + - https://cipherstash.com/docs/stack/reference + - https://cipherstash.com/docs/stack/deploy/bundling ## Troubleshooting -- Module load errors on Linux/serverless: review the npm lockfile v3 guide. +- Module load errors on Linux/serverless: switch to `@cipherstash/stack/wasm-inline`, or review the bundling guide (https://cipherstash.com/docs/stack/deploy/bundling). - Can't decrypt after encrypting with a lock context: ensure the exact same lock context is provided to decrypt. - Tests failing due to missing credentials: provide `CS_*` env vars; lock-context tests are skipped without `USER_JWT`. - Performance testing: prefer bulk operations (`bulkEncrypt*` / `bulkDecrypt*`) to exercise ZeroKMS bulk speed. diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md index 4b37ed61..04c61a87 100644 --- a/CONTRIBUTE.md +++ b/CONTRIBUTE.md @@ -1,54 +1,54 @@ -# How to contribute to @cipherstash/protect +# Contributing to CipherStash Stack + +Thank you for your interest in contributing to the CipherStash Stack for TypeScript! This document walks you through the repository's structure, how to build and run the project locally, and how to make contributions effectively. ## I want to report a bug, or make a feature request Please use the GitHub issue tracker to report bugs, suggest features, or documentation improvements. -[When filing an issue](https://github.com/cipherstash/protectjs/issues/new/choose), please check [existing open](https://github.com/cipherstash/protectjs/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc), or [recently closed](https://github.com/cipherstash/protectjs/issues?q=is%3Aissue+sort%3Aupdated-desc+is%3Aclosed), issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. - ---- - -# Contributing to @cipherstash/protect - -Thank you for your interest in contributing to **@cipherstash/protect**! This document will walk you through the repository’s structure, how to build and run the project locally, and how to make contributions effectively. +[When filing an issue](https://github.com/cipherstash/stack/issues/new/choose), please check [existing open](https://github.com/cipherstash/stack/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) or [recently closed](https://github.com/cipherstash/stack/issues?q=is%3Aissue+sort%3Aupdated-desc+is%3Aclosed) issues to make sure somebody else hasn't already reported it. Please include as much information as you can. ## Repository Structure -``` +This is a [Turborepo](https://turbo.build/) monorepo managed with [pnpm](https://pnpm.io/) workspaces: + +```text . -├── examples/ -│ ├── example-app-1/ -│ └── example-app-2/ -│ ├── packages/ -│ └── protect/ <-- Main package published to npm -│ +│ ├── stack/ <-- Main package (@cipherstash/stack) +│ ├── cli/ <-- The `stash` CLI +│ ├── protect/ <-- Core encryption library (re-exported via stack) +│ └── ... <-- schema, drizzle, nextjs, prisma-next, migrate, wizard, ... +├── examples/ <-- Runnable example apps +├── e2e/ <-- Cross-package end-to-end tests +├── skills/ <-- Agent skills ├── .changeset/ -├── .turbo/ -├── CONTRIBUTING.md -├── package.json -└── ... +└── package.json ``` -### Turborepo - -This repo uses [Turborepo](https://turbo.build/) to manage multiple packages and examples in a monorepo structure. Turborepo orchestrates tasks (build, test, lint, etc.) across the different packages in a consistent and efficient manner. +See [AGENTS.md](./AGENTS.md) for a detailed layout, key APIs, environment variables, and gotchas — it's written for coding agents but is the most complete developer reference in the repo. -### `packages/protect` +### `packages/stack` -The **@cipherstash/protect** package is the core library that is published to npm under the `@cipherstash/protect` namespace. This is likely where you’ll spend most of your time if you’re contributing new features or bug fixes related to JSEQL’s core functionality. +**@cipherstash/stack** is the main package published to npm. It contains the encryption client and all integrations (Drizzle, Supabase, DynamoDB, secrets, identity). This is likely where you'll spend most of your time. ### `examples/` Directory -Within the `examples/` directory, you’ll find example applications that demonstrate how to use **@cipherstash/protect**. These examples reference the local `@cipherstash/protect` package, allowing you to test and verify your changes to **@cipherstash/protect** in a real-world application scenario. +The `examples/` directory contains applications demonstrating how to use `@cipherstash/stack`. They reference the local workspace packages, so you can verify your changes in a real application scenario. ## Setup Instructions +### Prerequisites + +- **Node.js** >= 22 +- **pnpm** (the version pinned in `package.json`'s `packageManager` field) +- CipherStash credentials if you want to run integration tests or examples (see [AGENTS.md](./AGENTS.md) for the required environment variables) + ### 1. Clone the Repo ```bash -git clone https://github.com/cipherstash/protectjs.git -cd protectjs +git clone https://github.com/cipherstash/stack.git +cd stack ``` ### 2. Install Dependencies @@ -57,46 +57,52 @@ cd protectjs pnpm install ``` -### 4. Build the Main Package - -Before you can run any example, you need to build the `@cipherstash/protect` package: +### 3. Build the Packages ```bash pnpm run build ``` -This command triggers Turborepo’s build pipeline, compiling the **@cipherstash/protect** package in `packages/protect` and linking it locally so the example can reference it. +This triggers Turborepo's build pipeline, compiling each package in `packages/*` and linking them locally so the examples can reference them. -### 5. Run an Example App +### 4. Run an Example App -Start the dev script which will watch for changes to the packages which are picked up by the example app. +Start the dev script, which watches for changes to the packages and is picked up by the example apps: ```bash pnpm run dev ``` -Navigate to one of the examples in `examples/` and follow the instructions for the corresponding example. - -Now, you can view the running application (if it’s a web or server app) or otherwise test the example’s output. This will help confirm your local build of **@cipherstash/protect** is working correctly. +Then navigate to one of the examples in `examples/` and follow its README. ## Making Changes -1. **Create a new branch** from `main` (or the default branch): +1. **Create a new branch** from `main`: ```bash git checkout -b feat/my-new-feature ``` -2. **Implement your changes** in the relevant package (most likely in `packages/protect`). +2. **Implement your changes** in the relevant package. + +3. **Write tests** to cover any new functionality or bug fixes: + ```bash + pnpm --filter test + ``` + +4. **Format and lint** with Biome before pushing: + ```bash + pnpm run code:fix + ``` -3. **Write tests** to cover any new functionality or bug fixes. +5. **Add a changeset** if your change affects a published package's public behaviour (see below). -## Publish Process (via Changeset) +## Publish Process (via Changesets) We use [**Changesets**](https://github.com/changesets/changesets) to manage versioning and publication to npm. -- When you’ve completed a feature or bug fix, **add a changeset** using `npx changeset`. +- When you've completed a feature or bug fix, **add a changeset** using `pnpm changeset`. - Follow the prompts to indicate the type of version bump (patch, minor, major). -- The [GitHub Actions](./.github/workflows/) (or other CI pipeline) will handle the **publish** step to npm once your PR is merged and the changeset is committed to `main`. +- The [GitHub Actions workflows](./.github/workflows/) handle the **publish** step to npm once your PR is merged and the changeset is committed to `main`. ## Pre release process @@ -119,8 +125,18 @@ When you merge the PR, the `next` branch will be merged into `main`, and the pac > This process can be dangerous, so please be careful when using it as it's difficult to undo mistakes. > If you are unfamiliar with the process, please reach out to the maintainers for help. +## Supply-Chain Rules + +This repo applies supply-chain controls that CI enforces (see [SECURITY.md](./SECURITY.md)). When contributing, keep in mind: + +1. **CI uses `pnpm install --frozen-lockfile`** — don't drop the flag. +2. **Adding to `pnpm.onlyBuiltDependencies` is an audit decision** — vet the package and explain the addition in the PR. +3. **Never commit auth tokens in `.npmrc`** — tokens belong in your user-level `~/.npmrc` or environment variables. + ## Additional Resources +- [AGENTS.md](./AGENTS.md) — detailed developer/agent reference for this repo +- [CipherStash documentation](https://cipherstash.com/docs) - [Turborepo Documentation](https://turbo.build/repo/docs) - [Changesets Documentation](https://github.com/changesets/changesets) @@ -128,7 +144,7 @@ When you merge the PR, the `next` branch will be merged into `main`, and the pac If you discover a potential security issue in this project, we ask that you contact us at security@cipherstash.com. -Please do not create a public GitHub issue. +Please do not create a public GitHub issue. See [SECURITY.md](./SECURITY.md) for our full security policy. ## Code of Conduct diff --git a/SECURITY.md b/SECURITY.md index 2bba6976..cbbb1e2f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -5,52 +5,22 @@ This document describes the security posture, reporting process, and guidelines ## Supported Packages -This repository contains the JavaScript/TypeScript SDK for CipherStash and related packages. - -The below tables list each package along with the currently supported (receiving security updates). - -### `@cipherstash/stack` - -| Version | Supported | -| ------- | ------------------ | -| 0.4.x | :white_check_mark: | -| < 0.4 | :x: | - -### `@cipherstash/protect` - -| Version | Supported | -| ------- | ------------------ | -| 10.1.x | :white_check_mark: | -| 9.6.x | :white_check_mark: | -| < 9.6 | :x: | - -### `@cipherstash/drizzle` - -| Version | Supported | -| ------- | ------------------ | -| 1.1.x | :white_check_mark: | -| < 1.1 | :x: | - -### `@cipherstash/schema` - -| Version | Supported | -| ------- | ------------------ | -| 2.0.x | :white_check_mark: | -| < 2.0 | :x: | - -### `@cipherstash/protect-dynamodb` - -| Version | Supported | -| ------- | ------------------ | -| 5.1.x | :white_check_mark: | -| < 5.1 | :x: | - -### `@cipherstash/nextjs` - -| Version | Supported | -| ------- | ------------------ | -| 4.0.x | :white_check_mark: | -| < 4.0 | :x: | +This repository is the CipherStash Stack monorepo for JavaScript/TypeScript. It publishes the following packages to npm: + +| Package | Description | +| ------- | ----------- | +| `@cipherstash/stack` | Main package: encryption client and all integrations | +| `stash` | CipherStash CLI | +| `@cipherstash/protect` | Core encryption library (re-exported via `@cipherstash/stack`) | +| `@cipherstash/schema` | Schema builder utilities | +| `@cipherstash/drizzle` | Drizzle ORM integration | +| `@cipherstash/nextjs` | Next.js helpers | +| `@cipherstash/protect-dynamodb` | DynamoDB helpers | +| `@cipherstash/migrate` | Plaintext-to-encrypted column migration tooling | +| `@cipherstash/prisma-next` | Prisma Next integration (searchable field-level encryption for Postgres) | +| `@cipherstash/wizard` | AI-powered encryption setup | + +**Security fixes are released for the latest release line of each package.** Security reports are welcome for any version, but fixes land in the latest release — if you are running an older major version, plan to upgrade to receive them. All packages follow semantic versioning and undergo internal security review, automated analysis, and reproducible builds as part of our SDLC. @@ -97,9 +67,9 @@ We will never take legal action against good-faith security researchers who foll The following are **in scope**: -- The `cipherstash/protectjs` GitHub repository -- All published NPM packages under the `@cipherstash/protect*` namespace -- Protect.js cryptographic implementations, configuration layers, and CLI tooling +- The `cipherstash/stack` GitHub repository +- All npm packages published from this repository (listed under Supported Packages above) +- CipherStash Stack cryptographic implementations, configuration layers, and CLI tooling - Key-handling, authenticated encryption behaviour, JSON/JSONB field-level encryption flows - Documentation or code examples that could lead to insecure usage - CipherStash’s internal infrastructure @@ -107,7 +77,7 @@ The following are **in scope**: The following are **out of scope**: -- Example applications in the `examples` dir (though we are still grateful for any relevant disclosires there) +- Example applications in the `examples` dir (though we are still grateful for any relevant disclosures there) - Social engineering, physical attacks, or denial-of-service - Attacks requiring privileged access to developer machines or CI/CD infrastructure @@ -137,8 +107,19 @@ To maintain a strong security posture, contributors MUST: ## CI/CD Supply-Chain Hardening +This repo applies a set of supply-chain controls sourced from +[lirantal/npm-security-best-practices](https://github.com/lirantal/npm-security-best-practices): +a post-install script policy, a 7-day dependency cooldown (pnpm +`minimumReleaseAge`, mirrored by Dependabot's cooldown), exotic-dependency +blocking (`blockExoticSubdeps`), frozen-lockfile CI, registry pinning, and +CODEOWNERS coverage of supply-chain-critical paths. These controls are +validated by `e2e/tests/supply-chain.e2e.test.ts` so silent regressions fail +CI. See `skills/stash-supply-chain-security/SKILL.md` for the full guide. + The `release.yml` workflow publishes packages to npm using OIDC trusted -publishing and an `NPM_TOKEN`. +publishing (`id-token: write`). There is no long-lived `NPM_TOKEN` — the +workflow deliberately avoids one, and setting one would bypass trusted +publishing. [GitHub Actions cache poisoning is a known attack][1] against credential-bearing workflows. The mechanism is: diff --git a/package.json b/package.json index 0ee6eb63..43c10a0b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { - "name": "@cipherstash/protectjs", - "description": "CipherStash Protect for JavaScript/TypeScript", - "author": "CipherStash ", + "name": "@cipherstash/stack-monorepo", + "description": "CipherStash Stack for JavaScript/TypeScript", + "private": true, + "author": "CipherStash ", "keywords": [ "encrypted", "query", @@ -11,11 +12,11 @@ "eql" ], "bugs": { - "url": "https://github.com/cipherstash/protectjs/issues" + "url": "https://github.com/cipherstash/stack/issues" }, "repository": { "type": "git", - "url": "git+https://github.com/cipherstash/protectjs.git" + "url": "git+https://github.com/cipherstash/stack.git" }, "license": "MIT", "workspaces": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 3246b838..9a294704 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -8,7 +8,7 @@ "directory": "packages/cli" }, "license": "MIT", - "author": "CipherStash ", + "author": "CipherStash ", "files": [ "dist", "README.md", diff --git a/packages/drizzle/package.json b/packages/drizzle/package.json index af5aa5e6..725bf38c 100644 --- a/packages/drizzle/package.json +++ b/packages/drizzle/package.json @@ -20,7 +20,7 @@ "directory": "packages/drizzle" }, "license": "MIT", - "author": "CipherStash ", + "author": "CipherStash ", "type": "module", "bin": { "generate-eql-migration": "./dist/bin/generate-eql-migration.js" diff --git a/packages/migrate/package.json b/packages/migrate/package.json index bf873a26..30afb188 100644 --- a/packages/migrate/package.json +++ b/packages/migrate/package.json @@ -15,7 +15,7 @@ "eql" ], "license": "MIT", - "author": "CipherStash ", + "author": "CipherStash ", "files": [ "dist", "README.md", diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index 5329fe44..ab9c78f1 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -17,7 +17,7 @@ "directory": "packages/nextjs" }, "license": "MIT", - "author": "CipherStash ", + "author": "CipherStash ", "type": "module", "exports": { ".": { diff --git a/packages/protect-dynamodb/package.json b/packages/protect-dynamodb/package.json index 27a7ae1d..69bf2fdf 100644 --- a/packages/protect-dynamodb/package.json +++ b/packages/protect-dynamodb/package.json @@ -19,7 +19,7 @@ "directory": "packages/protect-dynamodb" }, "license": "MIT", - "author": "CipherStash ", + "author": "CipherStash ", "type": "module", "exports": { ".": { diff --git a/packages/protect/package.json b/packages/protect/package.json index d7d55c9d..8c8cd3bc 100644 --- a/packages/protect/package.json +++ b/packages/protect/package.json @@ -19,7 +19,7 @@ "directory": "packages/protect" }, "license": "MIT", - "author": "CipherStash ", + "author": "CipherStash ", "type": "module", "bin": { "stash": "./dist/bin/stash.js" diff --git a/packages/schema/package.json b/packages/schema/package.json index faee86e0..a18e3d68 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -17,7 +17,7 @@ "directory": "packages/schema" }, "license": "MIT", - "author": "CipherStash ", + "author": "CipherStash ", "type": "module", "exports": { ".": { diff --git a/packages/stack/package.json b/packages/stack/package.json index 60c00c1c..fbdf6b68 100644 --- a/packages/stack/package.json +++ b/packages/stack/package.json @@ -19,7 +19,7 @@ "directory": "packages/stack" }, "license": "MIT", - "author": "CipherStash ", + "author": "CipherStash ", "files": [ "dist", "README.md", diff --git a/packages/wizard/package.json b/packages/wizard/package.json index 87c6c73e..365186fb 100644 --- a/packages/wizard/package.json +++ b/packages/wizard/package.json @@ -8,7 +8,7 @@ "directory": "packages/wizard" }, "license": "MIT", - "author": "CipherStash ", + "author": "CipherStash ", "files": [ "dist", "dist/skills",