Private identity

Stable avatars without exposing the identifier.

Ordinary deterministic output is reproducible by anyone who knows the seed. For emails, account IDs, or other sensitive values, derive an HMAC seed on a trusted Node.js server first.

Derive on the server, render the result.

The private entry point canonicalizes the identifier and namespace, then signs a domain-separated message with HMAC-SHA-256. Only the derived value needs to reach ordinary rendering code.

1. Trusted input

Receive the sensitive identity inside a server route, job, or trusted Node.js process.

2. HMAC derivation

Use a secret of at least 32 encoded bytes. The secret never belongs in a client bundle.

3. Safe rendering seed

Render the returned hmac-sha256: value or call a private avatar helper directly.

Three asynchronous helpers.

Import from the Node.js-only agent-avatars/private entry point. It uses the Web Crypto implementation from node:crypto.

import { derivePrivateSeed } from "agent-avatars/private";
import { createHashAvatar } from "agent-avatars";

const privateSeed = await derivePrivateSeed("person@example.com", {
  namespace: "my-product/users",
  secret: process.env.AVATAR_HMAC_SECRET,
});

const svg = createHashAvatar(privateSeed, {
  seedMode: "raw",
  namespace: "my-product/users",
});

derivePrivateSeed()

Returns the stable HMAC-derived seed for storage or use by another renderer.

createPrivateAvatarDescriptor()

Returns a complete descriptor without exposing an ordinary seed to the avatar selection step.

createPrivateHashAvatar()

Derives and renders an SVG string in one asynchronous call.

Treat the secret as production infrastructure.

Use a secret manager or protected environment configuration. Validate that it exists at startup and keep environments isolated.

Do

  • Generate a high-entropy value of at least 32 bytes.
  • Keep separate secrets for unrelated trust boundaries.
  • Limit access to the service that derives identities.
  • Back up the secret if identities must remain stable.

Do not

  • Commit the secret to source control.
  • Prefix a public seed with a fixed string and call it private.
  • Expose the private entry point or secret in browser code.
  • Log the original identifier and secret together.

Secret rotation changes identity.

HMAC output depends on the secret. Rotating it intentionally produces new derived seeds and therefore new avatars.

Plan rotation like a data migration: version the active secret, keep the previous version during a controlled transition, regenerate stored output, and remove old access only when clients have adopted the new identity.

The package does not manage keys, store identifiers, or migrate existing records. Those responsibilities remain with the application.

Know what HMAC does not solve.

It prevents reproduction without the secret; it does not make the final avatar anonymous in every product context.

Stable output is still linkable

The same private identity remains recognizable wherever the same derivation domain and rendering options are reused.

Access patterns still matter

Application logs, URLs, analytics payloads, and surrounding profile data can reveal identity independently of the avatar.

Keep public and private identity flows separate.

Use ordinary seeds for agents and services that are already public. Reserve server-side derivation for identifiers that should not be guessable.