Socket
Book a DemoInstallSign in
Socket

@cuttlefish-sync/query-token

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
Package was removed
Sorry, it seems this package was removed from the registry

@cuttlefish-sync/query-token

Framework-agnostic server package for signing Cuttlefish queries with JWT

latest
npmnpm
Version
0.0.9
Version published
Maintainers
1
Created
Source

@cuttlefish-sync/server

Framework-agnostic server package for signing Cuttlefish queries with EdDSA (Ed25519) JWTs. Use it anywhere you can run Node.js to authorize live SQL subscriptions against Cuttlefish.

Installation

npm install @cuttlefish-sync/server

Quick Start

import { signQuery } from '@cuttlefish-sync/server'

const { token, expires_in } = await signQuery({
  sql: 'SELECT * FROM users WHERE id = $1',
  params: [123],
  user_id: 'user_456',
})

// Use token to connect your client WebSocket before expires_in seconds pass

Configuration

Environment Variables

Set these values in your server environment:

CUTTLEFISH_CLIENT_ID=your_client_id
CUTTLEFISH_PRIVATE_KEY='{"kty":"OKP","crv":"Ed25519",...}'
CUTTLEFISH_UPSTREAM_ID=your_upstream_id
CUTTLEFISH_EXPIRY_SECONDS=60 # optional override

Generating Keys

import { generateKeyPair, exportJWK } from 'jose'

const { privateKey, publicKey } = await generateKeyPair('EdDSA', { crv: 'Ed25519' })
const privateJWK = await exportJWK(privateKey)
const publicJWK = await exportJWK(publicKey)

console.log('Private Key (keep secret):', JSON.stringify(privateJWK))
console.log('Public Key (upload to Cuttlefish):', JSON.stringify(publicJWK))

Getting Credentials

  • Sign in to the Cuttlefish dashboard.
  • Create a new client to receive a client_id.
  • Upload the generated public key.
  • Store the private key JSON string in your server environment.

Per-call Overrides

await signQuery({
  sql: 'SELECT 1',
  params: [],
  client_id: 'override_client',
  private_key: '{"kty":"OKP","crv":"Ed25519",...}',
  upstream_id: 'custom_upstream',
  expiry_seconds: 120,
})

API Reference

signQuery(params: SignQueryParams): Promise<SignQueryResult>

Signs a SQL query and returns an EdDSA JWT token.

Required parameters

  • sql: SQL query string using positional parameters ($1, $2, ...)
  • params: Array of parameter values

Optional parameters

  • user_id: Defaults to 'anonymous'
  • client_id, private_key, upstream_id, expiry_seconds: Override environment defaults

Return value

{
  token: string
  expires_in: number
}

Errors

  • Missing configuration (e.g. CUTTLEFISH_CLIENT_ID is required)
  • Invalid JWK JSON or curve
  • Non-positive expiry_seconds

Examples

Basic Script (examples/basic.ts)

import { signQuery } from '@cuttlefish-sync/server'

async function main() {
  const result = await signQuery({
    sql: 'SELECT * FROM todos WHERE user_id = $1',
    params: ['user_123'],
    user_id: 'user_123',
  })

  console.log('Token:', result.token)
  console.log('Expires in:', result.expires_in, 'seconds')
}

main().catch((error) => {
  console.error('Failed to sign query:', error)
  process.exitCode = 1
})

Next.js Server Action (examples/nextjs-server-action.ts)

'use server'
import { signQuery } from '@cuttlefish-sync/server'
import { auth } from '@/lib/auth'

export async function signTodosQuery() {
  const session = await auth()
  if (!session?.user) {
    throw new Error('Unauthorized')
  }

  return await signQuery({
    sql: `
      SELECT id, title, completed, created_at
      FROM todos
      WHERE user_id = $1
      ORDER BY created_at DESC
    `,
    params: [session.user.id],
    user_id: session.user.id,
    expiry_seconds: 60,
  })
}

Express Route

import express from 'express'
import { signQuery } from '@cuttlefish-sync/server'

const app = express()

app.post('/api/sign-query', async (req, res) => {
  const user = req.user
  if (!user) {
    res.status(401).json({ error: 'Unauthorized' })
    return
  }

  const result = await signQuery({
    sql: 'SELECT * FROM messages WHERE org_id = $1',
    params: [user.orgId],
    user_id: user.id,
  })

  res.json(result)
})

Custom Expiry Windows

// Short-lived token (30s)
await signQuery({
  sql: 'SELECT * FROM sensitive_data',
  params: [],
  expiry_seconds: 30,
})

// Longer window (5m)
await signQuery({
  sql: 'SELECT * FROM public_posts',
  params: [],
  expiry_seconds: 300,
})

Anonymous Queries

await signQuery({
  sql: 'SELECT * FROM public_posts LIMIT 10',
  params: [],
  // user_id defaults to 'anonymous'
})

Security Notes

JWT Claims

  • iss: client_id
  • aud: upstream_id
  • sub: user identifier (or 'anonymous')
  • exp: expiry (seconds)
  • nbf: not-before (seconds)
  • iat: issued-at (seconds)
  • jti: random UUID per token
  • query: { sql, params }

Properties

  • EdDSA (Ed25519) signatures using your private JWK
  • Tamper detection via signature verification
  • Replay resistance with short expiries and unique jti
  • User scoping with sub

Best Practices

  • Never ship private keys to the client.
  • Rotate keys periodically through the dashboard.
  • Keep expiry windows short unless strictly necessary.
  • Include user identifiers in your SQL WHERE clauses.
  • Fail closed—handle signing errors explicitly.

TypeScript Support

import type {
  Config,
  SignQueryParams,
  SignQueryResult,
} from '@cuttlefish-sync/server'

License

MIT

FAQs

Package last updated on 29 Oct 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts