@sirrlock/node 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SirrVault
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # @sirrlock/node
2
+
3
+ [![CI](https://github.com/sirrlock/node/actions/workflows/ci.yml/badge.svg)](https://github.com/sirrlock/node/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/@sirrlock/node)](https://www.npmjs.com/package/@sirrlock/node)
5
+ [![npm downloads](https://img.shields.io/npm/dm/@sirrlock/node)](https://www.npmjs.com/package/@sirrlock/node)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5-blue)](https://www.typescriptlang.org/)
7
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
9
+
10
+ **Node.js client and npx CLI for [Sirr](https://github.com/sirrlock/sirr) — ephemeral secret management.**
11
+
12
+ Give AI agents exactly the credentials they need, for exactly as long as they need them. Read once and it's gone. Expired by time and you never have to clean anything up.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ npm install @sirrlock/node
18
+ ```
19
+
20
+ Or use without installing:
21
+
22
+ ```bash
23
+ npx @sirrlock/node push DB_URL="postgres://..." --reads 1 --ttl 1h
24
+ ```
25
+
26
+ ## CLI
27
+
28
+ ```bash
29
+ # Push a secret that burns after one read
30
+ sirr push DB_URL="postgres://..." --reads 1 --ttl 1h
31
+
32
+ # Retrieve (burns on read if reads=1)
33
+ sirr get DB_URL
34
+
35
+ # Push entire .env — expires in 24h
36
+ sirr push .env --ttl 24h # not yet implemented, use key=value form
37
+
38
+ # Manage
39
+ sirr list
40
+ sirr delete API_KEY
41
+ sirr prune
42
+ sirr health
43
+ ```
44
+
45
+ Config via env vars:
46
+ ```bash
47
+ export SIRR_SERVER=http://localhost:8080
48
+ export SIRR_TOKEN=your-master-key
49
+ ```
50
+
51
+ ## Programmatic API
52
+
53
+ ```typescript
54
+ import { SirrClient, SirrError } from '@sirrlock/node'
55
+
56
+ const sirr = new SirrClient({
57
+ server: process.env.SIRR_SERVER ?? 'http://localhost:8080',
58
+ token: process.env.SIRR_TOKEN!,
59
+ })
60
+
61
+ // Push a one-time secret
62
+ await sirr.push('API_KEY', 'sk-...', { ttl: 3600, reads: 1 })
63
+
64
+ // Retrieve — null if burned or expired
65
+ const value = await sirr.get('API_KEY')
66
+
67
+ // Pull all secrets into a plain object
68
+ const secrets = await sirr.pullAll()
69
+
70
+ // Inject all secrets as env vars for the duration of a callback
71
+ await sirr.withSecrets(async () => {
72
+ // process.env.API_KEY is set here
73
+ await runAgentTask()
74
+ })
75
+
76
+ // Delete immediately
77
+ await sirr.delete('API_KEY')
78
+
79
+ // List active secrets (metadata only — no values)
80
+ const list = await sirr.list()
81
+ ```
82
+
83
+ ### Error Handling
84
+
85
+ ```typescript
86
+ import { SirrError } from '@sirrlock/node'
87
+
88
+ try {
89
+ await sirr.push('KEY', 'value')
90
+ } catch (e) {
91
+ if (e instanceof SirrError) {
92
+ console.error(`API error ${e.status}: ${e.message}`)
93
+ }
94
+ }
95
+ ```
96
+
97
+ ## AI Workflows
98
+
99
+ ### LangChain.js tool with scoped credential
100
+
101
+ ```typescript
102
+ import { DynamicTool } from 'langchain/tools'
103
+
104
+ const dbTool = new DynamicTool({
105
+ name: 'query_database',
106
+ description: 'Run a SQL query against the production database',
107
+ func: async (query) => {
108
+ const connStr = await sirr.get('AGENT_DB')
109
+ if (!connStr) throw new Error('DB credential expired or burned')
110
+ return runQuery(connStr, query)
111
+ },
112
+ })
113
+ ```
114
+
115
+ ### Inject secrets into a subprocess
116
+
117
+ ```typescript
118
+ await sirr.withSecrets(async () => {
119
+ await execa('python', ['agent.py'])
120
+ })
121
+ ```
122
+
123
+ ### CI/CD: one-time deploy credential
124
+
125
+ ```typescript
126
+ await sirr.push('DEPLOY_TOKEN', process.env.PERMANENT_TOKEN!, { reads: 1 })
127
+ await execa('sirr', ['run', '--', './deploy.sh'])
128
+ // DEPLOY_TOKEN was read once and is now deleted
129
+ ```
130
+
131
+ ### pytest-style fixture for Node.js tests
132
+
133
+ ```typescript
134
+ beforeAll(async () => {
135
+ await sirr.withSecrets(async () => {
136
+ // All vault secrets set as process.env for the test suite
137
+ await runTestSuite()
138
+ })
139
+ })
140
+ ```
141
+
142
+ ## Related
143
+
144
+ | Package | Description |
145
+ |---------|-------------|
146
+ | [sirr](https://github.com/sirrlock/sirr) | Rust monorepo: `sirrd` server + `sirr` CLI |
147
+ | [@sirrlock/mcp](https://github.com/sirrlock/mcp) | MCP server for AI assistants |
148
+ | [sirr (PyPI)](https://github.com/sirrlock/python) | Python SDK |
149
+ | [Sirr.Client (NuGet)](https://github.com/sirrlock/dotnet) | .NET SDK |
150
+ | [sirr.dev](https://sirr.dev) | Documentation |
151
+ | [sirrlock.com](https://sirrlock.com) | Managed cloud + license keys |
package/dist/cli.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Sirr CLI — thin Node.js wrapper for use via `npx sirr` or `npm i -g sirr`.
4
+ *
5
+ * Reads SIRR_SERVER (default: http://localhost:8080) and SIRR_TOKEN.
6
+ */
7
+ export declare function parseArgs(argv: string[]): Record<string, string | number | boolean>;
8
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAiCH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAqBnF"}
package/dist/cli.js ADDED
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Sirr CLI — thin Node.js wrapper for use via `npx sirr` or `npm i -g sirr`.
5
+ *
6
+ * Reads SIRR_SERVER (default: http://localhost:8080) and SIRR_TOKEN.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.parseArgs = parseArgs;
10
+ const index_1 = require("./index");
11
+ const server = process.env.SIRR_SERVER ?? "http://localhost:8080";
12
+ const token = process.env.SIRR_TOKEN ?? "";
13
+ function usage() {
14
+ console.error(`
15
+ Usage: sirr <command> [options]
16
+
17
+ Commands:
18
+ push KEY=value [--ttl <secs>] [--reads <n>]
19
+ get KEY
20
+ list
21
+ delete KEY
22
+ prune
23
+ health
24
+ audit [--since <ts>] [--action <action>] [--limit <n>]
25
+ webhooks list
26
+ webhooks add <url> [--events <csv>]
27
+ webhooks remove <id>
28
+ keys list
29
+ keys create <label> [--permissions <csv>]
30
+ keys remove <id>
31
+
32
+ Environment:
33
+ SIRR_SERVER Server URL (default: http://localhost:8080)
34
+ SIRR_TOKEN Bearer token
35
+ `);
36
+ process.exit(1);
37
+ }
38
+ function parseArgs(argv) {
39
+ const result = {};
40
+ const positional = [];
41
+ for (let i = 0; i < argv.length; i++) {
42
+ const arg = argv[i];
43
+ if (arg.startsWith("--")) {
44
+ const key = arg.slice(2);
45
+ const next = argv[i + 1];
46
+ if (next && !next.startsWith("--")) {
47
+ result[key] = next;
48
+ i++;
49
+ }
50
+ else {
51
+ result[key] = true;
52
+ }
53
+ }
54
+ else {
55
+ positional.push(arg);
56
+ result[`_${positional.length - 1}`] = arg;
57
+ }
58
+ }
59
+ result._count = positional.length;
60
+ return result;
61
+ }
62
+ async function main() {
63
+ const [, , subcmd, ...rest] = process.argv;
64
+ if (!subcmd)
65
+ usage();
66
+ const args = parseArgs(rest);
67
+ const client = new index_1.SirrClient({ server, token });
68
+ try {
69
+ switch (subcmd) {
70
+ case "health": {
71
+ const r = await client.health();
72
+ console.log(JSON.stringify(r));
73
+ break;
74
+ }
75
+ case "push": {
76
+ const target = args._0;
77
+ if (!target)
78
+ usage();
79
+ const ttlArg = args.ttl;
80
+ const readsArg = args.reads;
81
+ if (!target.includes("=")) {
82
+ console.error("push: expected KEY=value");
83
+ process.exit(1);
84
+ }
85
+ const eqIdx = target.indexOf("=");
86
+ const key = target.slice(0, eqIdx);
87
+ const value = target.slice(eqIdx + 1);
88
+ await client.push(key, value, {
89
+ ttl: ttlArg ? Number.parseInt(ttlArg, 10) : undefined,
90
+ reads: readsArg ? Number.parseInt(readsArg, 10) : undefined,
91
+ });
92
+ console.log(`✓ pushed ${key}`);
93
+ break;
94
+ }
95
+ case "get": {
96
+ const key = args._0;
97
+ if (!key)
98
+ usage();
99
+ const value = await client.get(key);
100
+ if (value === null) {
101
+ console.error("not found or expired");
102
+ process.exit(1);
103
+ }
104
+ console.log(value);
105
+ break;
106
+ }
107
+ case "list": {
108
+ const metas = await client.list();
109
+ if (metas.length === 0) {
110
+ console.log("(no active secrets)");
111
+ }
112
+ else {
113
+ for (const m of metas) {
114
+ console.log(` ${m.key} — reads: ${m.read_count}${m.max_reads != null ? `/${m.max_reads}` : ""}`);
115
+ }
116
+ }
117
+ break;
118
+ }
119
+ case "delete": {
120
+ const key = args._0;
121
+ if (!key)
122
+ usage();
123
+ const existed = await client.delete(key);
124
+ console.log(existed ? `✓ deleted ${key}` : "not found");
125
+ break;
126
+ }
127
+ case "prune": {
128
+ const n = await client.prune();
129
+ console.log(`pruned ${n} expired secret(s)`);
130
+ break;
131
+ }
132
+ case "audit": {
133
+ const events = await client.getAuditLog({
134
+ since: args.since ? Number(args.since) : undefined,
135
+ action: args.action,
136
+ limit: args.limit ? Number(args.limit) : undefined,
137
+ });
138
+ if (events.length === 0) {
139
+ console.log("(no audit events)");
140
+ }
141
+ else {
142
+ for (const e of events) {
143
+ console.log(` [${e.timestamp}] ${e.action} key=${e.key ?? "-"} ip=${e.source_ip} ${e.success ? "ok" : "FAIL"}`);
144
+ }
145
+ }
146
+ break;
147
+ }
148
+ case "webhooks": {
149
+ const sub = args._0;
150
+ if (!sub)
151
+ usage();
152
+ switch (sub) {
153
+ case "list": {
154
+ const wh = await client.listWebhooks();
155
+ if (wh.length === 0) {
156
+ console.log("(no webhooks)");
157
+ }
158
+ else {
159
+ for (const w of wh) {
160
+ console.log(` ${w.id} ${w.url} [${w.events.join(",")}]`);
161
+ }
162
+ }
163
+ break;
164
+ }
165
+ case "add": {
166
+ const url = args._1;
167
+ if (!url)
168
+ usage();
169
+ const eventsArg = args.events;
170
+ const events = eventsArg ? eventsArg.split(",") : undefined;
171
+ const result = await client.createWebhook(url, { events });
172
+ console.log("webhook registered");
173
+ console.log(` id: ${result.id}`);
174
+ console.log(` secret: ${result.secret}`);
175
+ break;
176
+ }
177
+ case "remove": {
178
+ const id = args._1;
179
+ if (!id)
180
+ usage();
181
+ await client.deleteWebhook(id);
182
+ console.log(`webhook ${id} removed`);
183
+ break;
184
+ }
185
+ default:
186
+ usage();
187
+ }
188
+ break;
189
+ }
190
+ case "keys": {
191
+ const sub = args._0;
192
+ if (!sub)
193
+ usage();
194
+ switch (sub) {
195
+ case "list": {
196
+ const keys = await client.listApiKeys();
197
+ if (keys.length === 0) {
198
+ console.log("(no API keys)");
199
+ }
200
+ else {
201
+ for (const k of keys) {
202
+ console.log(` ${k.id} ${k.label} [${k.permissions.join(",")}] prefix=${k.prefix ?? "*"}`);
203
+ }
204
+ }
205
+ break;
206
+ }
207
+ case "create": {
208
+ const label = args._1;
209
+ if (!label)
210
+ usage();
211
+ const permsArg = args.permissions;
212
+ const permissions = permsArg ? permsArg.split(",") : ["read", "write"];
213
+ const prefix = args.prefix;
214
+ const result = await client.createApiKey({ label, permissions, prefix });
215
+ console.log("API key created");
216
+ console.log(` id: ${result.id}`);
217
+ console.log(` key: ${result.key}`);
218
+ console.log(` (save the key — it won't be shown again)`);
219
+ break;
220
+ }
221
+ case "remove": {
222
+ const id = args._1;
223
+ if (!id)
224
+ usage();
225
+ await client.deleteApiKey(id);
226
+ console.log(`API key ${id} removed`);
227
+ break;
228
+ }
229
+ default:
230
+ usage();
231
+ }
232
+ break;
233
+ }
234
+ default:
235
+ usage();
236
+ }
237
+ }
238
+ catch (e) {
239
+ console.error(e.message ?? String(e));
240
+ process.exit(1);
241
+ }
242
+ }
243
+ if (require.main === module) {
244
+ main();
245
+ }
246
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * @sirrlock/node — Sirr Node.js client
3
+ *
4
+ * Thin fetch wrapper around the Sirr HTTP API.
5
+ * No native dependencies. Works in Node 18+.
6
+ */
7
+ export interface SirrClientOptions {
8
+ /** Sirr server base URL. Default: http://localhost:8080 */
9
+ server?: string;
10
+ /** Bearer token (SIRR_MASTER_KEY on the server side). */
11
+ token: string;
12
+ }
13
+ export interface PushOptions {
14
+ /** TTL in seconds. */
15
+ ttl?: number;
16
+ /** Maximum number of reads before the secret self-destructs. */
17
+ reads?: number;
18
+ }
19
+ export interface SecretMeta {
20
+ key: string;
21
+ created_at: number;
22
+ expires_at: number | null;
23
+ max_reads: number | null;
24
+ read_count: number;
25
+ }
26
+ export interface AuditEvent {
27
+ id: number;
28
+ timestamp: number;
29
+ action: string;
30
+ key: string | null;
31
+ source_ip: string;
32
+ success: boolean;
33
+ detail: string | null;
34
+ }
35
+ export interface AuditOptions {
36
+ since?: number;
37
+ until?: number;
38
+ action?: string;
39
+ limit?: number;
40
+ }
41
+ export interface Webhook {
42
+ id: string;
43
+ url: string;
44
+ events: string[];
45
+ created_at: number;
46
+ }
47
+ export interface WebhookCreateResult {
48
+ id: string;
49
+ secret: string;
50
+ }
51
+ export interface ApiKey {
52
+ id: string;
53
+ label: string;
54
+ permissions: string[];
55
+ prefix: string | null;
56
+ created_at: number;
57
+ }
58
+ export interface ApiKeyCreateResult {
59
+ id: string;
60
+ key: string;
61
+ label: string;
62
+ permissions: string[];
63
+ prefix: string | null;
64
+ }
65
+ export interface CreateApiKeyOptions {
66
+ label: string;
67
+ permissions: string[];
68
+ prefix?: string;
69
+ }
70
+ export declare class SirrError extends Error {
71
+ readonly status: number;
72
+ constructor(status: number, message: string);
73
+ }
74
+ export declare class SirrClient {
75
+ private readonly server;
76
+ private readonly token;
77
+ constructor(opts: SirrClientOptions);
78
+ private headers;
79
+ private request;
80
+ /** Check server health. Does not require authentication. */
81
+ health(): Promise<{
82
+ status: string;
83
+ }>;
84
+ /**
85
+ * Push a secret to the vault.
86
+ *
87
+ * @param key Secret key name
88
+ * @param value Secret value
89
+ * @param opts TTL (seconds) and/or max read count
90
+ */
91
+ push(key: string, value: string, opts?: PushOptions): Promise<void>;
92
+ /**
93
+ * Retrieve a secret by key. Increments the read counter.
94
+ * Returns `null` if the secret does not exist or has expired/burned.
95
+ */
96
+ get(key: string): Promise<string | null>;
97
+ /** List metadata for all active secrets. Values are never returned. */
98
+ list(): Promise<SecretMeta[]>;
99
+ /** Delete a secret immediately. Returns true if it existed. */
100
+ delete(key: string): Promise<boolean>;
101
+ /**
102
+ * Retrieve all secrets and return them as a key→value map.
103
+ * Each GET increments the respective read counter.
104
+ */
105
+ pullAll(): Promise<Record<string, string>>;
106
+ /** Trigger an immediate sweep of expired secrets on the server. */
107
+ prune(): Promise<number>;
108
+ /**
109
+ * Inject all vault secrets as process.env variables, then invoke `fn`.
110
+ * Useful in test harnesses and scripts.
111
+ */
112
+ withSecrets<T>(fn: () => Promise<T>): Promise<T>;
113
+ /** Query the audit log. */
114
+ getAuditLog(opts?: AuditOptions): Promise<AuditEvent[]>;
115
+ /** Register a webhook. Returns the ID and signing secret. */
116
+ createWebhook(url: string, opts?: {
117
+ events?: string[];
118
+ }): Promise<WebhookCreateResult>;
119
+ /** List registered webhooks. Signing secrets are redacted. */
120
+ listWebhooks(): Promise<Webhook[]>;
121
+ /** Delete a webhook by ID. Returns false if not found. */
122
+ deleteWebhook(id: string): Promise<boolean>;
123
+ /** Create a scoped API key. The raw key is returned once. */
124
+ createApiKey(opts: CreateApiKeyOptions): Promise<ApiKeyCreateResult>;
125
+ /** List all scoped API keys. Key hashes are never returned. */
126
+ listApiKeys(): Promise<ApiKey[]>;
127
+ /** Delete an API key by ID. Returns false if not found. */
128
+ deleteApiKey(id: string): Promise<boolean>;
129
+ }
130
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ /**
3
+ * @sirrlock/node — Sirr Node.js client
4
+ *
5
+ * Thin fetch wrapper around the Sirr HTTP API.
6
+ * No native dependencies. Works in Node 18+.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.SirrClient = exports.SirrError = void 0;
10
+ class SirrError extends Error {
11
+ constructor(status, message) {
12
+ super(`Sirr API error ${status}: ${message}`);
13
+ this.status = status;
14
+ this.name = "SirrError";
15
+ }
16
+ }
17
+ exports.SirrError = SirrError;
18
+ function validateKey(key) {
19
+ if (!key) {
20
+ throw new Error("Secret key must not be empty");
21
+ }
22
+ }
23
+ class SirrClient {
24
+ constructor(opts) {
25
+ if (!opts.token) {
26
+ throw new Error("SirrClient requires a non-empty token");
27
+ }
28
+ this.server = (opts.server ?? "http://localhost:8080").replace(/\/$/, "");
29
+ this.token = opts.token;
30
+ }
31
+ headers() {
32
+ return {
33
+ Authorization: `Bearer ${this.token}`,
34
+ "Content-Type": "application/json",
35
+ };
36
+ }
37
+ async request(method, path, body) {
38
+ const res = await fetch(`${this.server}${path}`, {
39
+ method,
40
+ headers: this.headers(),
41
+ body: body !== undefined ? JSON.stringify(body) : undefined,
42
+ });
43
+ if (!res.ok) {
44
+ let message = "unknown error";
45
+ try {
46
+ const json = (await res.json());
47
+ message = json.error ?? message;
48
+ }
49
+ catch {
50
+ try {
51
+ const text = await res.text();
52
+ if (text)
53
+ message = text.slice(0, 200);
54
+ }
55
+ catch {
56
+ // body already consumed or unreadable — keep default message
57
+ }
58
+ }
59
+ throw new SirrError(res.status, message);
60
+ }
61
+ return (await res.json());
62
+ }
63
+ /** Check server health. Does not require authentication. */
64
+ async health() {
65
+ const res = await fetch(`${this.server}/health`);
66
+ if (!res.ok) {
67
+ throw new SirrError(res.status, "health check failed");
68
+ }
69
+ return res.json();
70
+ }
71
+ /**
72
+ * Push a secret to the vault.
73
+ *
74
+ * @param key Secret key name
75
+ * @param value Secret value
76
+ * @param opts TTL (seconds) and/or max read count
77
+ */
78
+ async push(key, value, opts = {}) {
79
+ validateKey(key);
80
+ await this.request("POST", "/secrets", {
81
+ key,
82
+ value,
83
+ ttl_seconds: opts.ttl ?? null,
84
+ max_reads: opts.reads ?? null,
85
+ });
86
+ }
87
+ /**
88
+ * Retrieve a secret by key. Increments the read counter.
89
+ * Returns `null` if the secret does not exist or has expired/burned.
90
+ */
91
+ async get(key) {
92
+ validateKey(key);
93
+ try {
94
+ const data = await this.request("GET", `/secrets/${encodeURIComponent(key)}`);
95
+ return data.value;
96
+ }
97
+ catch (e) {
98
+ if (e instanceof SirrError && e.status === 404)
99
+ return null;
100
+ throw e;
101
+ }
102
+ }
103
+ /** List metadata for all active secrets. Values are never returned. */
104
+ async list() {
105
+ const data = await this.request("GET", "/secrets");
106
+ return data.secrets;
107
+ }
108
+ /** Delete a secret immediately. Returns true if it existed. */
109
+ async delete(key) {
110
+ validateKey(key);
111
+ try {
112
+ await this.request("DELETE", `/secrets/${encodeURIComponent(key)}`);
113
+ return true;
114
+ }
115
+ catch (e) {
116
+ if (e instanceof SirrError && e.status === 404)
117
+ return false;
118
+ throw e;
119
+ }
120
+ }
121
+ /**
122
+ * Retrieve all secrets and return them as a key→value map.
123
+ * Each GET increments the respective read counter.
124
+ */
125
+ async pullAll() {
126
+ const metas = await this.list();
127
+ const result = {};
128
+ await Promise.all(metas.map(async (m) => {
129
+ const value = await this.get(m.key);
130
+ if (value !== null)
131
+ result[m.key] = value;
132
+ }));
133
+ return result;
134
+ }
135
+ /** Trigger an immediate sweep of expired secrets on the server. */
136
+ async prune() {
137
+ const data = await this.request("POST", "/prune");
138
+ return data.pruned;
139
+ }
140
+ /**
141
+ * Inject all vault secrets as process.env variables, then invoke `fn`.
142
+ * Useful in test harnesses and scripts.
143
+ */
144
+ async withSecrets(fn) {
145
+ const secrets = await this.pullAll();
146
+ const originals = {};
147
+ for (const [k, v] of Object.entries(secrets)) {
148
+ originals[k] = process.env[k];
149
+ process.env[k] = v;
150
+ }
151
+ try {
152
+ return await fn();
153
+ }
154
+ finally {
155
+ for (const [k, orig] of Object.entries(originals)) {
156
+ if (orig === undefined)
157
+ delete process.env[k];
158
+ else
159
+ process.env[k] = orig;
160
+ }
161
+ }
162
+ }
163
+ /** Query the audit log. */
164
+ async getAuditLog(opts = {}) {
165
+ const params = new URLSearchParams();
166
+ if (opts.since != null)
167
+ params.set("since", String(opts.since));
168
+ if (opts.until != null)
169
+ params.set("until", String(opts.until));
170
+ if (opts.action != null)
171
+ params.set("action", opts.action);
172
+ if (opts.limit != null)
173
+ params.set("limit", String(opts.limit));
174
+ const qs = params.toString();
175
+ const data = await this.request("GET", `/audit${qs ? `?${qs}` : ""}`);
176
+ return data.events;
177
+ }
178
+ /** Register a webhook. Returns the ID and signing secret. */
179
+ async createWebhook(url, opts) {
180
+ const body = { url };
181
+ if (opts?.events)
182
+ body.events = opts.events;
183
+ return this.request("POST", "/webhooks", body);
184
+ }
185
+ /** List registered webhooks. Signing secrets are redacted. */
186
+ async listWebhooks() {
187
+ const data = await this.request("GET", "/webhooks");
188
+ return data.webhooks;
189
+ }
190
+ /** Delete a webhook by ID. Returns false if not found. */
191
+ async deleteWebhook(id) {
192
+ try {
193
+ await this.request("DELETE", `/webhooks/${encodeURIComponent(id)}`);
194
+ return true;
195
+ }
196
+ catch (e) {
197
+ if (e instanceof SirrError && e.status === 404)
198
+ return false;
199
+ throw e;
200
+ }
201
+ }
202
+ /** Create a scoped API key. The raw key is returned once. */
203
+ async createApiKey(opts) {
204
+ return this.request("POST", "/keys", opts);
205
+ }
206
+ /** List all scoped API keys. Key hashes are never returned. */
207
+ async listApiKeys() {
208
+ const data = await this.request("GET", "/keys");
209
+ return data.keys;
210
+ }
211
+ /** Delete an API key by ID. Returns false if not found. */
212
+ async deleteApiKey(id) {
213
+ try {
214
+ await this.request("DELETE", `/keys/${encodeURIComponent(id)}`);
215
+ return true;
216
+ }
217
+ catch (e) {
218
+ if (e instanceof SirrError && e.status === 404)
219
+ return false;
220
+ throw e;
221
+ }
222
+ }
223
+ }
224
+ exports.SirrClient = SirrClient;
225
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@sirrlock/node",
3
+ "version": "0.1.0",
4
+ "description": "Sirr (سر) — Node.js client and npx CLI for the ephemeral secret vault",
5
+ "license": "MIT",
6
+ "author": "sirrlock",
7
+ "homepage": "https://github.com/sirrlock/node#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/sirrlock/node"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/sirrlock/node/issues"
14
+ },
15
+ "keywords": [
16
+ "sirr",
17
+ "secrets",
18
+ "ephemeral",
19
+ "vault",
20
+ "secret-management",
21
+ "burn-after-reading",
22
+ "ai-agents",
23
+ "mcp"
24
+ ],
25
+ "main": "dist/index.js",
26
+ "types": "dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "import": "./dist/index.js",
30
+ "require": "./dist/index.js",
31
+ "types": "./dist/index.d.ts"
32
+ }
33
+ },
34
+ "bin": {
35
+ "sirr": "dist/cli.js"
36
+ },
37
+ "files": [
38
+ "dist"
39
+ ],
40
+ "scripts": {
41
+ "build": "tsc",
42
+ "dev": "tsc --watch",
43
+ "test": "jest",
44
+ "lint": "biome check src/",
45
+ "lint:fix": "biome check --write src/",
46
+ "prepublishOnly": "npm run lint && npm run build && npm test"
47
+ },
48
+ "engines": {
49
+ "node": ">=18"
50
+ },
51
+ "dependencies": {},
52
+ "devDependencies": {
53
+ "@biomejs/biome": "^1.9.0",
54
+ "@jest/globals": "^30.0.0",
55
+ "@types/node": "^20.0.0",
56
+ "esbuild": "^0.25.0",
57
+ "jest": "^30.0.0",
58
+ "ts-jest": "^29.0.0",
59
+ "typescript": "^5.4.0"
60
+ },
61
+ "jest": {
62
+ "preset": "ts-jest",
63
+ "testEnvironment": "node",
64
+ "testPathIgnorePatterns": ["/node_modules/", "/dist/"]
65
+ }
66
+ }