@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
Keywords
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_EVENTSenvironment variable) - Type Safety: Full TypeScript support with Zod schema validation
- Error Handling: Robust error handling with detailed error context
Installation
npm install @cipherstash/controllerEnvironment 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=trueUsage
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:
- A valid Clerk JWT template configured via
CLERK_JWT_TEMPLATE - 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 cleanLicense
Copyright © CipherStash. All rights reserved.
Licensed under the MIT License. See the LICENSE file for details.
