Skip to content

Agent skills and README teach the deprecated LockContext.identify() identity API #591

Description

@coderdan

Summary

Several developer-facing surfaces in this repo still teach new LockContext().identify(jwt) for identity-aware encryption. Per-operation CTS tokens were removed in protect-ffi 0.25, and the shipped types now mark identify() @deprecated:

Per-operation CTS tokens were removed in protect-ffi 0.25. Authenticate the client as the user with an OidcFederationStrategy (config.authStrategy) instead, and pass the claim to .withLockContext(). The token fetched here is no longer used by encryption operations.

This is a quiet failure. Code using identify() compiles, logs a deprecation warning, and silently does not bind the value to an identity. Anyone following these examples believes they have per-user encryption and does not.

The docs site is being fixed in cipherstash/docs#57. This issue covers the surfaces that ship from this repo.

The correct API

import { Encryption, OidcFederationStrategy } from "@cipherstash/stack"

const client = await Encryption({
  schemas: [users],
  config: {
    authStrategy: OidcFederationStrategy.create(workspaceCrn, () => getUserJwt()),
  },
})

await client
  .encrypt(value, { column: users.email, table: users })
  .withLockContext({ identityClaim: ["sub"] })

What needs updating

1. Agent skills (highest impact)

The cipherstash/stack skill pack is installed into user projects with npx skills add cipherstash/stack, and its whole purpose is to stop AI coding agents from hallucinating API surfaces. Right now it teaches agents to generate the deprecated pattern, so agents will keep emitting silently-broken identity code until the skills are updated.

  • stash-encryption — advertises "Identity-aware encryption with LockContext and JWT-based access control"
  • stash-supabase — advertises "Identity-aware encryption with .withLockContext()"

Both should cover OidcFederationStrategy via config.authStrategy, and .withLockContext({ identityClaim }).

2. @cipherstash/stack README

The Identity-Aware Encryption section still shows the full new LockContext()identify(userJwt).withLockContext(lockContext) flow. Note the repo's own root README already describes the correct API ("authenticate as the end user with OidcFederationStrategy ... bind the data key to their identity with .withLockContext({ identityClaim })"), so the two disagree.

3. TypeDoc doc comments

Two examples in the generated API reference are wrong independently of the deprecation:

  • EncryptionClient's class-level example passes the Result to .withLockContext(lockContext), where LockContext.identify() returns Result<LockContext, EncryptionError>. It should pass .data. LockContext's own docstring gets this right (identified.data), so the two examples contradict each other.
  • The LockContext docstring and Encryption's config.authStrategy docstring both pass OidcFederationStrategy.create(...) directly to authStrategy, while @cipherstash/auth's README unwraps the Result first (if (created.failure) ...; created.data). Whichever is right, they should agree.

Two API questions this surfaced

Supabase's withLockContext is typed narrower than the core operations. In dist/supabase/index.d.ts:

withLockContext(lockContext: LockContext): EncryptedQueryBuilder<T, FK>;

while the core operations accept LockContextInput = LockContext | Context. So on the Supabase path you cannot pass { identityClaim: ["sub"] } and must construct new LockContext({ context: { identityClaim: ["sub"] } }), which reads like the deprecated flow even though it isn't. Consider widening it to LockContextInput for consistency.

Is @cipherstash/nextjs still required? v4.1.1 (published this week) still exports protectClerkMiddleware and getCtsToken, and is still built around fetching a CTS token per request to hand to new LockContext({ ctsToken }). Since encryption operations no longer consume a CTS token, that middleware appears to have no effect on key derivation. If that's right, the package needs a deprecation note or a rewrite around OidcFederationStrategy; if it's wrong, the docs need to explain when it is still needed.

Environment

  • @cipherstash/stack 0.19.0
  • @cipherstash/auth 0.42.0
  • @cipherstash/protect-ffi 0.28.0

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions