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

fise

v2.0.0

Published

Fast Interoperable Structured Envelope (FISE) - generated, profile-governed application representations for structured and binary data.

Downloads

102

Readme

FISE — Fast Interoperable Structured Envelope

npm version license Tests

Generate one Profile. Share it. Transform data into a profile-specific envelope.

FISE is a keyless data-representation protocol for web applications: it replaces directly readable JSON, text, and binary payloads with a profile-specific reversible envelope. Instead of a secret encryption key, FISE uses generated Profile runtime code as the reversible rule shared by the frontend and backend. The encrypt and decrypt methods are operational names for that reversible transform, not a cryptographic guarantee.

FISE is not encryption. It is a data-representation (obfuscation) layer. encrypt/decrypt name a reversible transform—not confidentiality, integrity, or authentication—and the generated Profile is public application code, not a secret key. Keep TLS, server-side authorization, and (for real secrets) authenticated encryption. See the security boundary.

Run fise generate once, commit and share the exact generated Profile, encrypt on one side, and decrypt on the other. Each Profile contains a different verified byte-transformation pipeline while remaining deterministic and reversible. The same Profile handles structured data, text, and binary data such as images, files, or videos; full binary transformation is the default.

With default full coverage, a captured FISE payload cannot be consumed directly as the original JSON, text, or file bytes. A basic scraper or generic decoder must integrate that deployment's matching Profile, positional context contract, and decrypt path. Different generated Profiles reduce reuse of one static signature or universal decoder across applications.

FISE returns a JSON-safe string for text and structured data, and binary output for binary input. Repetitive structured data is compressed automatically when that makes its internal payload smaller. Large binary data can be restored by range, one chunk at a time, or processed through WASM and workers. An optional edge mode transforms only the beginning and end of a binary value when lower transform cost matters more than covering its middle bytes. Envelopes can also carry a runtime TTL.

Keyless means there is no secret encryption-key lifecycle; it does not mean the Profile is secret. Generated Profile code, context conventions, and decrypt logic are visible to the frontend. A scraper that controls or instruments that runtime can still call or hook decrypt and read the restored data. Keep TLS, authentication, server-side authorization, cryptographic encryption, integrity protection, and input validation.

Read the engineering whitepaper for the design, boundaries, and evaluation method.

Implement in five steps

1. Install FISE

npm install fise

npx uses the project-local CLI, so no global installation is needed. FISE is ESM-only and requires Node.js 20+ or a modern browser.

For a Python backend, also install the dependency-free Python 3.10+ runtime:

python -m pip install fise

2. Generate one Profile

npx fise generate ./src/fise.profile.ts

A Profile is generated source code that tells FISE how to transform and restore data. Every generation samples a fresh independently randomized candidate and verifies it before writing. Commit the generated file to Git; do not edit it by hand.

If the backend is Python, choose it in the same generation command:

npx fise generate ./src/fise.profile.ts --backend python

This emits fise.profile.ts for the frontend and fise_profile.py for the backend from one candidate. The two files carry the same fingerprint and are verified for exact cross-language wire compatibility before either is written.

See the CLI reference for verify, --override, CI use, and the complete command contract.

3. Share the exact Profile

Frontend and backend must use the exact generated Profile artifact or JavaScript/Python pair from one command. Do not generate either side independently.

┌─────────────┐       ┌────────────────┐       ┌─────────────┐
│ Backend     │──────▶│ One Profile    │◀──────│ Frontend    │
└──────┬──────┘       └────────────────┘       └──────▲──────┘
       └────────────── FISE data ─────────────────────┘

In a JavaScript monorepo, keep the Profile in a shared package. For a Python backend, keep the generated .ts/.py pair under one owner and distribute each language artifact without regenerating it. Run fise verify on every copy and confirm the fingerprint matches.

Context is an optional ordered list of values already known by both sides, for example a session ID and user ID:

const context = [sessionId, userId, "orders", "v1"];

Context makes the result depend on those values. Decrypt with the same values in the same order. FISE does not store them in the envelope, but they are not a secret key or an authorization check. sessionId here must be a client-visible, non-credential identifier—not an authentication token or protected cookie. If context is not useful for your flow, omit the second argument on both sides.

4. Encrypt on the backend

import { Fise } from "fise";
import profile from "./fise.profile.js";

const fise = new Fise(profile);
const context = [sessionId, userId, "orders", "v1"];

const encryptedData = fise.encrypt(order, context);

The Python backend API is the same small profile-bound model:

from fise import Fise
from fise_profile import profile

fise = Fise(profile)
context = [session_id, user_id, "orders", "v1"]

encrypted_data = fise.encrypt(order, context)

For text or structured data, encryptedData is a JSON-safe Base64URL string that can be placed directly in the application's existing API response.

5. Decrypt on the frontend

import { Fise } from "fise";
import profile from "./fise.profile.js";

const fise = new Fise(profile);
const context = [sessionId, userId, "orders", "v1"];

const order = fise.decrypt(encryptedData, context);

The restored value has the original text, structured, or binary type. The same Profile can also be used in the opposite direction. Validate restored structured data with the application's normal response schema before using it.

See the runnable HTTP web-application example, the Python agent-backend interoperability example, the web integration guide, and the examples guide.

Binary data

Binary input returns binary FISE data:

const encryptedFile = fise.encrypt(fileBytes, context);
const restoredFile = fise.decrypt(encryptedFile, context);

Restore only a requested byte range without restoring the whole file:

const range = fise.decryptRange(
  encryptedFile,
  { start: 1_000, endExclusive: 2_000 },
  context
);

Or restore chunks as the application asks for them:

for await (const chunk of fise.decryptProgressive(encryptedFile, context, {
  chunkSize: 256 * 1024
})) {
  consume(chunk);
}

Full transformation is the default. For large videos or files, edge mode can reduce transform work by processing only the first and last resolved bytes:

const mediaFise = new Fise(profile, {
  binary: { mode: "edges" }
});

const encryptedVideo = mediaFise.encrypt(videoBytes, context);

Edge mode uses 1 MiB per side by default. Advanced users can set edgeBytes in the same constructor option. decrypt, range, and progressive restoration read the resolved policy from the envelope; consumers do not repeat it. The middle bytes remain untransformed and can be inspected, so edge mode is an explicit performance trade-off—not the same coverage as the default full mode. It still returns one complete in-memory envelope.

See binary data for coverage choices and large-file limits.

Optional TTL

Set the lifetime once on the encrypting instance:

const fise = new Fise(profile, { ttlSeconds: 30 });
const encryptedData = fise.encrypt(data, context);

Python uses Fise(profile, ttl_seconds=30) for the same wire behavior.

The consumer calls decrypt normally. At the expiry second, FISE throws ENVELOPE_EXPIRED. This is a normal-runtime freshness rule, not cryptographic expiration or replay prevention; a controlled client can patch the check or its clock. Browser-facing flows must also allow for network delay and clock skew between producer and consumer; avoid very short TTLs when correctness depends on separate device clocks.

Optional raw fallback

FISE throws on failure by default. An application that prioritizes availability can explicitly return the original input when ordinary encrypt or decrypt fails:

const fise = new Fise(profile, { strict: false });

const encryptedOrRaw = fise.encrypt(data, context);
const restoredOrRaw = fise.decrypt(received, context);

Python uses Fise(profile, strict=False) for the equivalent opt-in behavior.

Expiration and clock failures always throw. Range and progressive methods also remain strict. A failed encryption can expose the original data, so the application must support and monitor both outcomes. See the security boundary before enabling fallback.

Documentation

FISE is available under the MIT License.