npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cipherstash/controller

v0.1.0

Published

A TypeScript SDK for managing CipherStash workspaces, keysets, clients, and access keys. This package provides server-side functions for interacting with the CipherStash control plane API.

Downloads

43

Readme

@cipherstash/controller

A TypeScript SDK for managing CipherStash workspaces, keysets, clients, and access keys. This package provides server-side functions for interacting with the CipherStash control plane API.

Features

  • Workspace Management: Create and list workspaces across different regions
  • Membership Management: Get workspace memberships and add members to workspaces
  • Keyset Operations: Create, list, enable, disable, grant, and revoke keysets
  • Client Management: Create, list, and delete client keys for applications
  • Access Key Management: Create and manage access keys for API authentication
  • OIDC Provider Integration: Manage OIDC providers for authentication
  • Event Tracking: Automatic tracking of workspace creation and other operations (can be disabled via DISABLE_EVENTS environment variable)
  • Type Safety: Full TypeScript support with Zod schema validation
  • Error Handling: Robust error handling with detailed error context

Installation

npm install @cipherstash/controller

Environment Variables

The controller requires the following environment variables:

# Required
CTS_ENDPOINT=https://your-cipherstash-endpoint.com

# Optional (for ZeroKMS operations)
ZEROKMS_ENDPOINT=https://your-zerokms-endpoint.com
# OR configure individual components
ZEROKMS_PROTOCOL=https
ZEROKMS_HOST=aws.viturhosted.net
ZEROKMS_PORT=443

# Required for authentication (if using Clerk)
CLERK_JWT_TEMPLATE=your-jwt-template-name
CLERK_SECRET_KEY=your-clerk-secret-key

# Optional (for debugging, disabled by default)
CS_CONTROLLER_DEBUG=true

# Optional (to disable event tracking, events are enabled by default)
DISABLE_EVENTS=true

Usage

Note: All functions in this package are server-side only (marked with 'use server'). They are designed to be used in server actions, API routes, or other server-side environments. They require Clerk authentication and cannot be used in client-side code.

Workspace Management

import { createWorkspace, getWorkspaces } from '@cipherstash/controller'

// Create a new workspace
const result = await createWorkspace('my-workspace', 'us-east-1', '[email protected]')
if (result.failure) {
  console.error('Failed to create workspace:', result.failure.message)
} else {
  console.log('Workspace created:', result.data.id)
}

// List all workspaces
const workspaces = await getWorkspaces()
if (workspaces.failure) {
  console.error('Failed to fetch workspaces:', workspaces.failure.message)
} else {
  console.log('Workspaces:', workspaces.data)
}

Membership Management

import { getMemberships, addMembershipToWorkspace } from '@cipherstash/controller'

// Get workspace memberships (includes user data from Clerk)
const memberships = await getMemberships('workspace-id')
if (memberships.failure) {
  console.error('Failed to fetch memberships:', memberships.failure.message)
} else {
  console.log('Memberships:', memberships.data)
  // Each membership includes user information if available
}

// Add a member to a workspace
const result = await addMembershipToWorkspace('workspace-id', 'user-id', 'member')
if (result.failure) {
  console.error('Failed to add membership:', result.failure.message)
} else {
  console.log('Membership added successfully')
}

Keyset Management

import { createKeyset, getKeysets, enableKeyset, disableKeyset, grantKeyset, revokeKeyset } from '@cipherstash/controller'

const workspace = { id: 'workspace-id', region: 'us-east-1' }

// Create a new keyset
const keyset = await createKeyset(workspace, 'my-keyset', 'Description of my keyset')
if (keyset.failure) {
  console.error('Failed to create keyset:', keyset.failure.message)
} else {
  console.log('Keyset created:', keyset.data.id)
}

// List keysets (optionally include disabled keysets)
const keysets = await getKeysets(workspace, true) // true to include disabled keysets
if (keysets.failure) {
  console.error('Failed to fetch keysets:', keysets.failure.message)
} else {
  console.log('Keysets:', keysets.data)
}

// Enable a keyset
const enableResult = await enableKeyset(workspace, 'keyset-id')
if (enableResult.failure) {
  console.error('Failed to enable keyset:', enableResult.failure.message)
}

// Disable a keyset
const disableResult = await disableKeyset(workspace, 'keyset-id')
if (disableResult.failure) {
  console.error('Failed to disable keyset:', disableResult.failure.message)
}

// Grant access to a keyset
const grantResult = await grantKeyset(workspace, 'client-id', 'keyset-id')
if (grantResult.failure) {
  console.error('Failed to grant keyset:', grantResult.failure.message)
}

// Revoke access from a keyset
const revokeResult = await revokeKeyset(workspace, 'client-id', 'keyset-id')
if (revokeResult.failure) {
  console.error('Failed to revoke keyset:', revokeResult.failure.message)
}

Client Key Management

import { createClientKey, getClients, deleteClient } from '@cipherstash/controller'

const workspace = { id: 'workspace-id', region: 'us-east-1' }

// Create a new client key
const client = await createClientKey(workspace, 'my-client', 'keyset-id')
if (client.failure) {
  console.error('Failed to create client:', client.failure.message)
} else {
  console.log('Client created:', client.data.id)
  console.log('Client key:', client.data.client_key)
}

// List clients
const clients = await getClients(workspace)
if (clients.failure) {
  console.error('Failed to fetch clients:', clients.failure.message)
} else {
  console.log('Clients:', clients.data)
}

// Delete a client
const deleteResult = await deleteClient(workspace, 'client-id')
if (deleteResult.failure) {
  console.error('Failed to delete client:', deleteResult.failure.message)
} else {
  console.log('Client deleted successfully')
}

Access Key Management

import { createAccessKey, getAccessKeys } from '@cipherstash/controller'

const workspace = { id: 'workspace-id', region: 'us-east-1' }

// Create a new access key
const accessKey = await createAccessKey(workspace, 'my-access-key', 'admin')
if (accessKey.failure) {
  console.error('Failed to create access key:', accessKey.failure.message)
} else {
  // Note: The response may have either 'accessKey' or 'access_key' property
  const key = 'accessKey' in accessKey.data ? accessKey.data.accessKey : accessKey.data.access_key
  console.log('Access key created:', key)
}

// List access keys
const accessKeys = await getAccessKeys(workspace)
if (accessKeys.failure) {
  console.error('Failed to fetch access keys:', accessKeys.failure.message)
} else {
  console.log('Access keys:', accessKeys.data)
}

OIDC Provider Management

import { createOidcProvider, getOidcProviders } from '@cipherstash/controller'

const workspace = { id: 'workspace-id', region: 'us-east-1' }

// Create a new OIDC provider
const provider = await createOidcProvider(workspace, 'google', 'https://accounts.google.com')
if (provider.failure) {
  console.error('Failed to create OIDC provider:', provider.failure.message)
} else {
  console.log('OIDC provider created:', provider.data.id)
}

// List OIDC providers
const providers = await getOidcProviders(workspace)
if (providers.failure) {
  console.error('Failed to fetch OIDC providers:', providers.failure.message)
} else {
  console.log('OIDC providers:', providers.data)
}

TypeScript Support

The package exports TypeScript types for all data structures:

import type { 
  Workspace, 
  Keyset, 
  ClientKey, 
  AccessKey, 
  OidcProvider,
  Membership,
  MembershipWithUser,
  ClerkUser,
  Host
} from '@cipherstash/controller'

// Use the types in your code
const workspace: Workspace = {
  id: 'workspace-id',
  name: 'My Workspace',
  role: 'owner',
  region: 'us-east-1'
}

const membership: MembershipWithUser = {
  id: 'membership-id',
  workspace_id: 'workspace-id',
  role: 'member',
  console_updated_at: '2024-01-01T00:00:00Z',
  sub: 'user-id',
  user: {
    id: 'user-id',
    first_name: 'John',
    last_name: 'Doe',
    primary_email_address_id: 'email-id',
    two_factor_enabled: false,
    email_addresses: [{ id: 'email-id', email_address: '[email protected]' }]
  }
}

Schema Validation

The package uses Zod schemas for runtime validation. You can import schemas directly:

import { workspaceSchema, keysetSchema } from '@cipherstash/controller/schema'

// Validate data at runtime
const isValidWorkspace = workspaceSchema.safeParse(data)
if (isValidWorkspace.success) {
  // Data is valid
  console.log(isValidWorkspace.data)
} else {
  // Handle validation errors
  console.error(isValidWorkspace.error)
}

Error Handling

All functions return a result object with either data or failure:

const result = await createWorkspace('name', 'region')

if (result.failure) {
  // Handle error
  console.error('Error type:', result.failure.type)
  console.error('Error message:', result.failure.message)
} else {
  // Handle success
  console.log('Success:', result.data)
}

Authentication

The controller automatically handles authentication using Clerk when available. It requires:

  1. A valid Clerk JWT template configured via CLERK_JWT_TEMPLATE
  2. User authentication through Clerk's auth system

For ZeroKMS operations, the controller automatically fetches and uses CTS tokens for authentication.

Supported Regions

The package supports the following AWS regions:

  • ap-southeast-2.aws - Asia Pacific (Sydney)
  • eu-central-1.aws - Europe (Frankfurt)
  • eu-west-1.aws - Europe (Ireland)
  • us-east-1.aws - US East (N. Virginia)
  • us-east-2.aws - US East (Ohio)
  • us-west-1.aws - US West (N. California)
  • us-west-2.aws - US West (Oregon)

Development

# Install dependencies
pnpm install

# Build the package
pnpm build

# Watch for changes during development
pnpm dev

# Clean build artifacts
pnpm clean

License

Copyright © CipherStash. All rights reserved.

Licensed under the MIT License. See the LICENSE file for details.