@trap_stevo/aegis
v0.0.0
Published
The Shield of Secrets. Encrypted, attestable, process.env-safe credentials vault with bootstrap, admin passkeys, developer enrollment, and enum-based storage.
Maintainers
Keywords
Readme
🛡️ @trap_stevo/aegis
The Shield of Secrets.
An encrypted, attestable, process-safe credentials vault with bootstrap, admin passkeys, developer enrollment, and enum-based storage — designed to safeguard credentials while staying effortless to use across machines, CI/CD pipelines, and runtime apps.
🚀 Features
- 🧱 Machine-Bound Encryption – Secrets are sealed to your machine’s identity
- 🧩 Bootstrap & Admin Flow – Securely initialize, bootstrap, and manage passkeys
- 👥 Developer Enrollment – Invite and register developers with time-limited codes
- 🔑 Grant System – Enforce which scripts, tokens, or modules can read secrets
- ⚙️ Enum-Based Storage – Portable secure paths (PROJECT, USER, SYSTEM, TEMP)
- 🔒 Vault API & Client API – Use high-level or low-level interfaces as needed
- 🧰 CLI Ready – Initialize, bootstrap, set, or read secrets interactively
- 💨 process.env Integration – Optional runtime injector for dynamic secret binding
⚙️ System Requirements
| Requirement | Version | |--------------|----------| | Node.js | ≥ 18.x | | npm | ≥ 9.x | | OS | Windows, macOS, Linux |
Entry Points
const { createAegis, createAegisEnv, inject } = require("@trap_stevo/aegis");🧠 Core Concepts
| Layer | Description | |--------|--------------| | Aegis API | Full administrative access (bootstrap, manage, rotate, invite) | | Aegis Env API | Lightweight, read-only runtime access for apps | | Inject API | Auto-injects vault secrets into process.env dynamically |
⚙️ Configuration
createAegis(options)
| Option | Type | Default | Description | |---------|------|----------|--------------| | storagePath | string | required | Base directory or enum (PROJECT, USER, SYSTEM, TEMP) | | namespace | string | "vault" | Folder name under storage path | | offset | string | "machine-v1" | Salted key derivation offset | | lockprint | string | null | Custom fingerprint override | | lockprintOptions | object | {} | Fingerprint file and size options | | shardCount | number | 32 | Internal vault shard count |
createAegisEnv(options)
| Option | Type | Default | Description | |---------|------|----------|--------------| | storagePath | string | required | Same enum or path as createVault | | namespace | string | "vault" | Name of vault directory | | offset | string | "machine-v1" | Salt key for machine binding | | lockprint | string | null | Optional fingerprint override | | lockprintOptions | object | {} | Lockprint configuration | | AEGIS_GRANTS_MODE | string | "strict" | Env override for dev mode ("permissive") |
inject(options)
| Option | Type | Default | Description | |---------|------|----------|--------------| | storagePath | string | required | Vault root path or enum | | namespace | string | "vault" | Vault directory | | offset | string | "machine-v1" | Key offset | | lockprint | string | null | Custom fingerprint | | preload | boolean | true | Preload all secrets to process.env | | cacheSeconds | number | 0 | Cache TTL for injected secrets | | enforceNoPlainOverwrite | boolean | true | Prevent overwriting existing env vars |
🧰 API Specifications
🔐 Aegis Methods
| Method | Description | Async | |---------|--------------|--------| | init() | Initialize the vault and create bootstrap token | ✅ | | bootstrapAdmin(adminID, token, passphrase) | Secure the vault and establish admin credentials | ✅ | | addDeveloper(devID, tempPass, adminID, adminPass) | Create a new developer entry | ✅ | | createInvite(devID, adminID, adminPass, opts) | Generate one-time invite codes | ✅ | | addDevWithInvite(devID, inviteCode, adminID, adminPass) | Add developer directly using an invite | ✅ | | claimInvite(devID, code, newPassphrase) | Developer claims an invite and sets password | ✅ | | changePassphrase(devID, oldPass, newPass) | Change developer password | ✅ | | removeDeveloper(devID, adminID, adminPass) | Remove developer access | ✅ | | setSecret(name, value, adminID, adminPass) | Store a secret securely | ✅ | | importSecrets(object, adminID, adminPass, opts) | Bulk import secrets | ✅ | | getSecret(name, opts) | Retrieve a secret by key | ✅ | | listNames() | List all stored secret names | ✅ | | deleteSecret(name, adminID, adminPass) | Delete a secret | ✅ | | addGrant(appID, grant, adminID, adminPass) | Add a new grant rule | ✅ | | removeGrant(appID, adminID, adminPass) | Remove a grant rule | ✅ |
🧩 Aegis Env Methods
| Method | Description | Async | |---------|--------------|--------| | get(name, { appID, appCWD }) | Retrieve secret (grant enforced) | ✅ | | getSync(name, { appID, appCWD }) | Retrieve secret synchronously | ❌ |
Supported Grant Types
- file_hash – pin to file SHA-256 hash
- token – signed token file verification
- plugin – external module-based verifier
🌐 Aegis Inject API
| Method | Description | Async | |---------|--------------|--------| | injectKey(name) | Inject one secret into process.env | ✅ | | refresh() | Clear cache and reload all injected values | ✅ | | list() | List all injected secret names | ✅ |
🔑 Grant Types
| Type | Description | Ideal Use | |------|--------------|------------| | file_hash | Locks access to a specific file checksum | CLI or local scripts | | token | Validates signed token file (ed25519) | CI/CD, build pipelines | | plugin | Loads verifier module dynamically | Custom policies or SDKs |
🧩 Example Grant
await vault.addGrant("demo-app", {
type : "file_hash",
path : "./aegisClientDemo.js",
sha256 : "abc123..."
}, "admin:local", "admin-pass");💻 CLI Command Reference
| Command | Description |
|----------|--------------|
| aegis init | Initialize a new vault and print bootstrap token |
| aegis bootstrap-admin <adminID> | Secure vault and create admin credentials |
| aegis add-dev <devID> <adminID> | Register a new developer |
| aegis create-invite <devID> <adminID> | Create a one-time invite code |
| aegis claim-invite <devID> <code> | Developer claims an invite and sets password |
| aegis set <key> <value> <adminID> | Store a new secret |
| aegis get <key> | Read a secret value |
| aegis list | List all stored secret names |
| aegis delete <key> | Delete a secret |
| aegis add-grant <appID> | Add a file_hash, token, or plugin grant |
| aegis remove-grant <appID> | Remove an existing grant |
| aegis info | Display vault configuration summary |
🧪 Example CLI Workflow
npm run start-aegis-init
npm run start-aegis-set -- --grant
npm run start-aegis-clientRe-run npm run start-aegis-set -- --grant whenever your file hash changes to refresh the grant.
📦 Installation
npm install @trap_stevo/aegis🏁 Quick Start
Initialize and Bootstrap
npx aegis init
npx aegis bootstrap-admin <adminDevID>Add Developer
npx aegis add-dev <devID> <adminDevID>Set Secret
npx aegis set API_KEY my-secret-value <adminDevID>Read Secret Programmatically
const { createAegisEnv } = require("@trap_stevo/aegis");
(async () => {
const env = createAegisEnv({ storagePath : "PROJECT", namespace : "vault" });
const key = await env.get("API_KEY", { appID : "demo-app" });
console.log("API Key:", key);
})();🧭Initializing Aegis via Code
Initializes the vault and bootstraps an admin account.
"use strict";
const { createAegis } = require("@trap_stevo/aegis");
const path = require("path");
const STORAGE = path.resolve(__dirname, ".aegis_store");
const NAMESPACE = "vault";
const ADMIN_ID = process.env.AEGIS_ADMIN_ID || "admin:local";
const ADMIN_PASS= process.env.AEGIS_ADMIN_PASS|| "aegis";
(async () => {
const vault = createAegis({ storagePath : STORAGE, namespace : NAMESPACE });
const token = vault.init();
console.log("[init] bootstrap token:", token);
vault.bootstrapAdmin(ADMIN_ID, token, ADMIN_PASS);
console.log("[init] admin bootstrapped:", ADMIN_ID);
console.log(`[init] vault ready at ${path.join(STORAGE, NAMESPACE)}`);
})();🧱 Setting Secrets via Code
Sets secrets into the vault and optionally registers a grant (using --grant).
"use strict";
const { createAegis } = require("@trap_stevo/aegis");
const crypto = require("crypto");
const path = require("path");
const fs = require("fs");
const STORAGE = path.resolve(__dirname, ".aegis_store");
const NAMESPACE = "vault";
const ADMIN_ID = process.env.AEGIS_ADMIN_ID || "admin:local";
const ADMIN_PASS = process.env.AEGIS_ADMIN_PASS || "aegis";
const ADD_GRANT = process.argv.includes("--grant") || process.env.AEGIS_ADD_GRANT === "1";
const APP_ID = process.env.AEGIS_APP_ID || "demo-app";
const READER_REL = process.env.AEGIS_READER_REL || "./aegisClientDemo.js";
function sha256FileHex(p)
{
const h = crypto.createHash("sha256");
h.update(fs.readFileSync(p));
return h.digest("hex");
};
(async () => {
const vault = createAegis({ storagePath: STORAGE, namespace: NAMESPACE });
await vault.setSecret("SERVICE_API_KEY", "sk_live_123", ADMIN_ID, ADMIN_PASS);
await vault.setSecret("DB_PASSWORD", "p@ssw0rd!", ADMIN_ID, ADMIN_PASS);
await vault.importSecrets({ MAILGUN_KEY: "mg_abc", S3_SECRET: "s3_xyz" }, ADMIN_ID, ADMIN_PASS, { overwrite: false });
console.log("[set] secrets written.");
if (ADD_GRANT)
{
const fullReader = path.resolve(__dirname, READER_REL);
const readerHash = sha256FileHex(fullReader);
await vault.addGrant(
APP_ID,
{ type : "file_hash", path : READER_REL, sha256 : readerHash },
ADMIN_ID,
ADMIN_PASS
);
console.log(`[grant] Added file_hash grant for appID=${APP_ID}`);
console.log(`[grant] path=${READER_REL}`);
console.log(`[grant] sha256=${readerHash}`);
console.log("[grant] Vault now in STRICT mode (since at least one grant exists).");
}
})();📖 Accessing Secrets Directly through Aegis
Reads secrets directly from the vault (admin access).
"use strict";
const { createAegis } = require("@trap_stevo/aegis");
const path = require("path");
const STORAGE = path.resolve(__dirname, ".aegis_store");
const NAMESPACE = "vault";
const ADMIN_ID = process.env.AEGIS_ADMIN_ID || "admin:local";
const ADMIN_PASS = process.env.AEGIS_ADMIN_PASS || "aegis";
(async () => {
const vault = createAegis({ storagePath: STORAGE, namespace: NAMESPACE });
try
{
const apiKey = await vault.getSecret("SERVICE_API_KEY", { devID : ADMIN_ID, passphrase : ADMIN_PASS });
const dbPass = vault.getSecretSync("DB_PASSWORD", { devID : ADMIN_ID, passphrase : ADMIN_PASS });
const names = await vault.listNames();
console.log("SERVICE_API_KEY =", apiKey);
console.log("DB_PASSWORD =", dbPass);
console.log("All keys =", names);
}
catch (error)
{
console.error("[Vault] read failed ~", error.message);
process.exitCode = 1;
}
})();🔐 Accessing Secrets through Client
Reads secrets through the Aegis Env API, validating with grant enforcement.
"use strict";
const { createAegisEnv } = require("@trap_stevo/aegis");
const path = require("path");
const STORAGE = path.resolve(__dirname, ".aegis_store");
const NAMESPACE = "vault";
const APP_ID = process.env.AEGIS_APP_ID || "demo-app";
(async () => {
const env = createAegisEnv({ storagePath : STORAGE, namespace : NAMESPACE });
try
{
const apiKey = await env.get("SERVICE_API_KEY", { appID : APP_ID, appCWD : __dirname });
console.log("SERVICE_API_KEY =", apiKey);
const dbPass = env.getSync("DB_PASSWORD", { appID : APP_ID, appCWD : __dirname });
console.log("DB_PASSWORD =", dbPass);
const mailgun = await env.get("MAILGUN_KEY", { appID : APP_ID, appCWD : __dirname });
console.log("MAILGUN_KEY =", mailgun);
}
catch (error)
{
console.error("[Client] read failed ~", error.code, error.message);
process.exitCode = 1;
}
})();🧪 Example Workflows
🧭 Initialize Vault and Bootstrap Admin
const { createAegis } = require("@trap_stevo/aegis");
(async () => {
const vault = createAegis({ storagePath : "PROJECT", namespace : "vault" });
await vault.init();
await vault.bootstrapAdmin("admin:local", "BOOTSTRAP_TOKEN", "supersecure");
console.log("Vault initialized.");
})();👤 Add Developer and Set Secrets
const vault = createAegis({ storagePath : "PROJECT" });
await vault.addDeveloper("devA", "temp123", "admin:local", "supersecure");
await vault.setSecret("SERVICE_API_KEY", "sk_live_123", "admin:local", "supersecure");🧰 Using a Token Grant (CI/CD Mode)
await vault.addGrant("pipeline", {
type : "token",
path : "./deploy.sig",
adminPubKey : "BASE64_PUB_KEY",
alg : "ed25519"
}, "admin:local", "supersecure");Then in the pipeline runner:
const { createAegisEnv } = require("@trap_stevo/aegis");
const env = createAegisEnv({ storagePath : "PROJECT" });
const key = await env.get("SERVICE_API_KEY", { appID : "pipeline", appCWD : process.cwd() });
console.log(key);####🔌 Plugin Grant Example
await vault.addGrant("custom-app", {
type : "plugin",
modulePath : "./verifyCustom.js",
moduleHash : "sha256_of_module",
config : { allow : ["CI", "PROD"] }
}, "admin:local", "supersecure");verifyCustom.js must export:
exports.verifySync = ({ meta, appCWD, config }) => {
return config.allow.includes("PROD");
};🧰 Development Mode (No Grant Enforcement)
Set environment variable:
AEGIS_GRANTS_MODE=permissive
This bypasses strict grant verification for local testing.
⚡ Troubleshooting
- ERR_NO_GRANT – Missing grant for appID
- ERR_UNAUTHORIZED – Invalid signature, token, or module hash
- ERR_UNVERIFIED_MACHINE – Lockprint mismatch; regenerate lockprint or re-init vault
- Grant mismatch after editing file – Re-run
npm run start-aegis-set -- --grant
📜 License
See LICENSE.md
🛡️ Protect What Powers You
Aegis defends your application’s core credentials with simplicity and precision —
no agents, no cloud dependencies, no clutter. Just encrypted, attestable trust at rest and in runtime.
