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

@graphorin/store-sqlite-encrypted

v0.8.0

Published

Optional encryption-at-rest sub-pack for the Graphorin framework's default SQLite store. Pulls in `better-sqlite3-multiple-ciphers@^12.9.0` (a drop-in fork of `better-sqlite3` that bundles SQLite3MultipleCiphers / SQLCipher v4), exposes the `encryptDataba

Readme

@graphorin/store-sqlite-encrypted

Optional encryption-at-rest sub-pack for the Graphorin framework's default SQLite store. Pulls in better-sqlite3-multiple-ciphers@^12.9.0 (a drop-in fork of better-sqlite3 that bundles the SQLite3MultipleCiphers extension) and exposes the encrypt / rekey / integrity-check runners that back the graphorin storage CLI subcommand group.

Project Graphorin · v0.8.0 · MIT License · © 2026 Oleksiy Stepurenko · https://github.com/o-stepper/graphorin


Status

  • Published: v0.8.0 (optional sub-pack)
  • Default cipher: sqlcipher (SQLCipher v4 compatible, legacy=4)
  • Defaults: encryption-at-rest is OFF by default. Opt in through graphorin init --encrypted.
  • audit.db: ALWAYS encrypted regardless of this opt-in. Installing this sub-pack is the only supported way to satisfy that requirement on fresh installations.

Install

pnpm add @graphorin/store-sqlite-encrypted
# Pulls in better-sqlite3-multiple-ciphers@^12.9.0 as a peer dep.

The cipher peer ships prebuilt binaries for every Node 22+ target (macOS arm64/x64, Linux x64/arm/arm64 with both glibc and musl, Windows x86/x64/arm64) so there is no compile step on pnpm install for the default platforms.

If you are on a platform without a prebuilt binary you will need a C++ toolchain and Python 3 available; consult the upstream better-sqlite3-multiple-ciphers README for details.


Usage

One-shot encryption migration (CLI flow)

# 1. Stop any running graphorin server / writers.
graphorin stop

# 2. Back up the unencrypted DB.
cp ~/.graphorin/data.db ~/.graphorin/data.db.backup-$(date +%Y%m%d-%H%M)

# 3. Encrypt + verify (passphrase resolved from a SecretRef chain).
graphorin storage encrypt --passphrase-from keyring:graphorin_db_passphrase

# 4. Update the config and restart.
graphorin config set storage.encryption.enabled true
graphorin config set storage.encryption.passphraseRef keyring:graphorin_db_passphrase
graphorin start

# 5. After a verification window (default 7 days) drop the backup.
graphorin storage cleanup-backups --older-than 7d

Programmatic use

import {
  createEncryptedConnection,
  encryptDatabase,
  rekeyDatabase,
  cipherIntegrityCheck,
} from '@graphorin/store-sqlite-encrypted';

// Open an existing encrypted DB.
const conn = await createEncryptedConnection({
  path: '/var/lib/graphorin/data.db',
  encryption: {
    enabled: true,
    passphraseResolver: async () => process.env.GRAPHORIN_DB_PASSPHRASE!,
  },
});

// Verify the cipher header on startup or via a triggers cron.
const integrity = cipherIntegrityCheck(conn);
if (!integrity.ok) {
  throw new Error(`cipher_integrity_check failed: ${integrity.rows.join('; ')}`);
}

// One-shot migration of an unencrypted file into a new encrypted one.
await encryptDatabase({
  sourcePath: '/var/lib/graphorin/data.db',
  targetPath: '/var/lib/graphorin/data.db.encrypted',
  passphrase: process.env.GRAPHORIN_DB_PASSPHRASE!,
  swap: true, // atomic rename + .bak.<timestamp> kept for recovery
});

// Rotate the passphrase in place (PRAGMA rekey under the hood).
await rekeyDatabase({
  path: '/var/lib/graphorin/data.db',
  oldPassphrase: process.env.OLD_PASSPHRASE!,
  newPassphrase: process.env.NEW_PASSPHRASE!,
});

Cipher selection

The default cipher is 'sqlcipher' with the legacy=4 parameter set - SQLCipher v4 compatible - chosen for ecosystem tooling compatibility (DB Browser for SQLCipher, sqlcipher CLI, GUI inspectors). Other cipher modes shipped by the cipher peer are accepted; pass them via the cipher option:

| Cipher | Notes | |---------------|-----------------------------------------------------------------------------| | 'sqlcipher' | Default. AES-256-CBC + HMAC-SHA1 + Argon2id KDF. SQLCipher v4 compatible. | | 'chacha20' | The cipher peer's own default (ChaCha20-Poly1305). | | 'aes256cbc' | Raw AES-256-CBC without the SQLCipher HMAC envelope. | | 'aes128cbc' | AES-128-CBC variant. | | 'rc4' | Legacy interop only. Do not use for new deployments. |


Operational notes

  • Passphrase loss = total data loss. The cipher peer cannot recover an encrypted DB without the passphrase. Store the passphrase in a keyring or vault (the graphorin storage encrypt CLI prompts for this).
  • WAL housekeeping bytes are visible to an attacker on file leak (page numbers, lengths). Row contents are not. See ADR-030 § 5 for the threat-model nuance.
  • Performance overhead is typically 5-15 % on OLTP workloads (read / write of small rows). The triggers cron that runs the daily cipher_integrity_check is a read-only pragma so it does not block writers.
  • Edge runtimes (Cloudflare Workers, Vercel Edge) are not supported. The cipher peer is a native addon. For edge deployments use @graphorin/store-libsql (Turso encryption is a separate story).

Related decisions

  • ADR-030 - SQLite encryption at rest (SQLCipher v4 baseline + KDF parameters).
  • ADR-008 - Storage default better-sqlite3 (synchronous embedded SQLite + WAL hardening).

License

MIT © 2026 Oleksiy Stepurenko


Project Graphorin · v0.8.0 · MIT License · © 2026 Oleksiy Stepurenko · https://github.com/o-stepper/graphorin