@loopfortress/jingle-cli
v0.0.5
Published
A policy-driven JOSE Key Management Tool
Maintainers
Readme
LoopFortress Jingle CLI
Jingle is a policy-driven JOSE Key Management Framework with declarative config, CLI, and runtime engine.
Features
General
- Uniform DX across symmetric + asymmetric + PBES2 + ECDH + AES-KW/GCMKW
- CLI for keygen, keystore and token operations
Keygen
- A declarative keygen architecture: spec → keystore → token factory (clean lifecycle flow)
- Purpose-based key groups (rotate under "access", "refresh", "userdata", etc.)
- Automatic kid assignment (user doesn’t have to care at all)
- Configurable key ID formatting (fun but harmless DX feature)
Keystore
- A type-safe JWK registry with strong typing for alg families & policies
- A clean keystore → runtime in-memory engine
- Optional external key import
- Optional strict/lenient policies and fallback logic for broken external integrations
- Automatic rotation with purpose groups
Token Factory
- Built-in JWT/JWS/JWE minting & verification
- A declarative token profile layer with mint & verify policies
- Mint & accept rules per token profile (structural authentication policy system)
Library Usage
config/jingle/Keystore.yaml
- This Keystore.yaml is used to configure the keystore.
- It defines the key groups and their policies.
- The key groups are referenced in the token factory config.
- You don't need to mount this file in the docker-compose.yaml.
- It's used to generate the keystore at build time.
version: '1.0'
forge:
sig:
demo-signer-key:
alg: ES256
policy:
curve: P-256
enc: {}config/jingle/Keystore.json
- Use the Jingle CLI to generate the keystore to a location of your choice.
- In this example, we generat the keystore next to the Jingle.yaml config file (
Jinglestore.json).
JINGLE_RC=config/jingle/Keystore.yaml jingle forge # use --force to overwrite an existing keystoreconfig/jingle/Factory.yaml
- This Jingle.yaml is used to configure the token factory and the keystore location.
- It defines the token profiles and their mint & accept rules.
- The token profiles are referenced in the app.
version: '1.0'
keystoreLocation: /etc/jingle/Jinglestore.json
factory:
# ===================== JWS Profiles =====================
jws:
demo-jws:
description: "Demo Signer (JWS)"
mint:
group: demo-signer-key
alg: ES256
accept:
kid: exact
algs: [ES256]
# ===================== JWE Profiles =====================
jwe: {}
# ===================== JWT Profiles =====================
jwt: {}
# ===================== JWN Profiles (JWE + JWS matrix) =====================
jwn: {}apps/index.ts
- Load the runtime and run validation to ensure the config is healthy.
- The runtime is used to mint and verify tokens in the app.
import { bootRuntimeOrCrash } from '@loopfortress/jingle-cli'
const rcFilePath = 'config/Factory.yaml'
console.log('Loading keys runtime', rcFilePath)
const r = async () => await bootRuntimeOrCrash(process.cwd(), rcFilePath)
export const runtime = await r()
const ok = runtime.factory.doctor()
if (!ok) {
console.error('Keys runtime failed to load')
process.exit(1)
}
console.log('Keys runtime loaded')
const jws = await runtime.factory.mintJWS('demo-jws', {/* payload */})
try {
const payload = await runtime.factory.verifyJWS('demo-jws', jws)
console.log('JWS verified:', payload)
} catch (error) {
console.error('Error verifying JWS:', error)
}docker-compose.yaml
- Define a volume mount for the Jingle.yaml config file and a keystore.
- The keystore is assumed to be previously generated.
version: '3.9'
services:
demo:
volumes:
- ./app/index.ts:/workspace/index.ts:ro
- ./config/jingle/Factory.yaml:/workspace/config/Factory.yaml:ro
- ./config/jingle/Jinglestore.json:/etc/jingle/Jinglestore.json:ro