@i4ctime/q-ring 0.14.0 → 0.15.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/README.md +92 -7
- package/dist/{chunk-C2TFJ2EH.js → chunk-MLBJCPX2.js} +322 -119
- package/dist/chunk-MLBJCPX2.js.map +1 -0
- package/dist/{chunk-NNIEXAW5.js → chunk-TPPPTL4J.js} +319 -116
- package/dist/chunk-TPPPTL4J.js.map +1 -0
- package/dist/{dashboard-KAUEPLXO.js → dashboard-T2UG23KI.js} +2 -2
- package/dist/{dashboard-PYYAED45.js → dashboard-TFWCG23R.js} +2 -2
- package/dist/index.js +647 -18
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +102 -7
- package/dist/mcp.js.map +1 -1
- package/package.json +5 -4
- package/dist/chunk-C2TFJ2EH.js.map +0 -1
- package/dist/chunk-NNIEXAW5.js.map +0 -1
- /package/dist/{dashboard-KAUEPLXO.js.map → dashboard-T2UG23KI.js.map} +0 -0
- /package/dist/{dashboard-PYYAED45.js.map → dashboard-TFWCG23R.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://
|
|
2
|
+
<img src="https://raw.githubusercontent.com/I4cTime/q-ring/main/assets/social-card-optimized.jpg" alt="q-ring — never paste an API key into .env again" width="100%" />
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
# q-ring
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**OS keychain secrets for AI coding agents, over MCP.**
|
|
8
8
|
|
|
9
|
+
[](https://github.com/I4cTime/q-ring/actions/workflows/ci.yml)
|
|
9
10
|
[](https://www.npmjs.com/package/@i4ctime/q-ring)
|
|
11
|
+
[](https://www.npmjs.com/package/@i4ctime/q-ring)
|
|
10
12
|
[](https://qring.i4c.studio/docs)
|
|
11
13
|
[](https://glama.ai/mcp/servers/I4cTime/q-ring)
|
|
14
|
+
[](https://smithery.ai/servers/i4ctime/q-ring)
|
|
15
|
+
[](https://cursor.directory/plugins/q-ring)
|
|
16
|
+
[](https://www.pulsemcp.com/servers/i4ctime-q-ring)
|
|
17
|
+
[](https://mcpservers.org/servers/i4ctime/q-ring)
|
|
12
18
|
[](https://github.com/I4cTime/q-ring/blob/main/LICENSE)
|
|
13
19
|
[](https://discord.gg/5uEApw5uEz)
|
|
20
|
+
[](https://www.youtube.com/@qring_dev)
|
|
21
|
+
[](https://x.com/i4c_studio)
|
|
14
22
|
|
|
15
23
|
<a href="https://glama.ai/mcp/servers/I4cTime/q-ring">
|
|
16
24
|
<img src="https://glama.ai/mcp/servers/I4cTime/q-ring/badges/card.svg" alt="q-ring MCP server" width="400" />
|
|
@@ -293,6 +301,60 @@ qring env:generate --output .env
|
|
|
293
301
|
qring env:generate --env staging --output .env.staging
|
|
294
302
|
```
|
|
295
303
|
|
|
304
|
+
### Secret References & Least-Privilege Run
|
|
305
|
+
|
|
306
|
+
A `qring://` reference is a committable pointer to a secret — it goes in your `.env` file instead of the value. `qring run` resolves references and manifest keys at spawn time, injecting **only what the project declares** (unlike `exec`, which injects the whole scope). Output is auto-redacted.
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# .env — safe to commit: these are references, not values
|
|
310
|
+
DATABASE_URL=qring://project/DATABASE_URL
|
|
311
|
+
OPENAI_API_KEY=qring://global/OPENAI_API_KEY
|
|
312
|
+
STRIPE_KEY=qring:///STRIPE_KEY # auto scope: project, then global
|
|
313
|
+
SESSION_TTL=3600 # plain values pass through
|
|
314
|
+
|
|
315
|
+
# Run with declared secrets injected (manifest + .env refs)
|
|
316
|
+
qring run -- pnpm dev
|
|
317
|
+
|
|
318
|
+
# Preview what would be injected, without running
|
|
319
|
+
qring run --dry-run -- pnpm dev
|
|
320
|
+
|
|
321
|
+
# Pin an environment, use a specific env file, or skip the manifest
|
|
322
|
+
qring run --env prod --env-file .env.prod --no-manifest -- ./deploy.sh
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
The key lives in the **path**, never the host (`qring://project/KEY`, not `qring://KEY`) — URL hosts are case-insensitive, and env-var keys are not. Malformed references fail loudly instead of leaking a literal `qring://…` string into the child. A reference pinned to an environment: `qring://project/DATABASE_URL?env=prod`.
|
|
326
|
+
|
|
327
|
+
### Editor Setup
|
|
328
|
+
|
|
329
|
+
Wire the q-ring MCP server into an editor's MCP config with one command. Merges non-destructively — other servers are preserved, and an existing q-ring entry is only replaced with `--force`.
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
qring setup cursor # .cursor/mcp.json (project) or --global for ~/.cursor
|
|
333
|
+
qring setup kiro # .kiro/settings/mcp.json, with read-only autoApprove list
|
|
334
|
+
qring setup claude # .mcp.json (project scope)
|
|
335
|
+
|
|
336
|
+
# Preview without writing
|
|
337
|
+
qring setup cursor --dry-run
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Push to Deployment Platforms
|
|
341
|
+
|
|
342
|
+
Push manifest secrets to GitHub Actions, Vercel, or Cloudflare Workers through each platform's **own authenticated CLI** (`gh` / `vercel` / `wrangler`) — q-ring never holds platform tokens, and values travel over stdin, never argv. Every push is recorded in the audit chain.
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
# Push the .q-ring.json manifest keys to GitHub Actions secrets
|
|
346
|
+
qring push github --repo you/your-app
|
|
347
|
+
|
|
348
|
+
# Push to Vercel environments
|
|
349
|
+
qring push vercel --vercel-env production,preview
|
|
350
|
+
|
|
351
|
+
# Push to Cloudflare Workers secrets
|
|
352
|
+
qring push cloudflare
|
|
353
|
+
|
|
354
|
+
# Explicit keys, preview first
|
|
355
|
+
qring push github --keys DATABASE_URL,API_KEY --dry-run
|
|
356
|
+
```
|
|
357
|
+
|
|
296
358
|
### Secret Liveness Validation
|
|
297
359
|
|
|
298
360
|
Test if a secret is actually valid with its target service. q-ring auto-detects the provider from key prefixes (`sk-` → OpenAI, `ghp_` → GitHub, etc.) or accepts an explicit provider name.
|
|
@@ -314,7 +376,7 @@ qring validate --all --manifest
|
|
|
314
376
|
qring validate --list-providers
|
|
315
377
|
```
|
|
316
378
|
|
|
317
|
-
**Built-in providers:** OpenAI, Stripe, GitHub, AWS (format check), Generic HTTP.
|
|
379
|
+
**Built-in providers:** OpenAI, Anthropic, OpenRouter, Google AI (Gemini), Groq, Hugging Face, ElevenLabs*, Vercel*, Stripe, GitHub, AWS (format check), Generic HTTP. Keys are only ever sent in headers, never URLs. (*no safe public prefix — select explicitly with `--provider` or the manifest `provider` field.)
|
|
318
380
|
|
|
319
381
|
Output:
|
|
320
382
|
|
|
@@ -383,7 +445,7 @@ qring exec -- npm run deploy
|
|
|
383
445
|
# Inject only specific tags
|
|
384
446
|
qring exec --tags backend -- node server.js
|
|
385
447
|
|
|
386
|
-
# Run with a restricted profile (blocks
|
|
448
|
+
# Run with a restricted profile (blocks network tools and interpreters/shells, 30s timeout)
|
|
387
449
|
qring exec --profile restricted -- npm test
|
|
388
450
|
```
|
|
389
451
|
|
|
@@ -436,6 +498,8 @@ qring approvals
|
|
|
436
498
|
qring approve PROD_DB_URL --revoke
|
|
437
499
|
```
|
|
438
500
|
|
|
501
|
+
When an agent is blocked on an approval-protected key, q-ring raises a desktop notification (Linux `notify-send`, macOS `osascript`) naming the key and the exact `qring approve` command — throttled per key, disabled with `QRING_NOTIFY=off`.
|
|
502
|
+
|
|
439
503
|
### Just-In-Time (JIT) Provisioning
|
|
440
504
|
|
|
441
505
|
Instead of storing static credentials, configure `q-ring` to dynamically generate short-lived tokens on the fly when requested (e.g. AWS STS, generic HTTP endpoints).
|
|
@@ -533,6 +597,8 @@ Define project-level governance rules in `.q-ring.json` to control which MCP too
|
|
|
533
597
|
|
|
534
598
|
Over MCP, policy is resolved from the directory the server was **launched** in — not from the `projectPath` a caller passes — so an agent can't sidestep restrictions by pointing at a directory with no policy. Launch the MCP server from your project root (where `.q-ring.json` lives). Edits to `.q-ring.json` are picked up automatically (the policy cache invalidates on file change), so you don't need to restart the server.
|
|
535
599
|
|
|
600
|
+
Policy files are schema-validated and **fail closed**: an invalid `policy` object (say, a typo like `denytools`) raises a `PolicyConfigError` instead of being silently ignored, so a malformed rule can never widen access.
|
|
601
|
+
|
|
536
602
|
```bash
|
|
537
603
|
# View the active policy
|
|
538
604
|
qring policy
|
|
@@ -568,7 +634,7 @@ Example policy in `.q-ring.json`:
|
|
|
568
634
|
Restrict command execution with named profiles that control allowed commands, network access, timeouts, and environment sanitization.
|
|
569
635
|
|
|
570
636
|
```bash
|
|
571
|
-
# Run with the "restricted" profile (blocks
|
|
637
|
+
# Run with the "restricted" profile (blocks network tools and interpreters/shells; 30s timeout)
|
|
572
638
|
qring exec --profile restricted -- npm test
|
|
573
639
|
|
|
574
640
|
# Run with the "ci" profile (5min timeout, allows network)
|
|
@@ -578,11 +644,11 @@ qring exec --profile ci -- npm run deploy
|
|
|
578
644
|
qring exec -- echo "hello"
|
|
579
645
|
```
|
|
580
646
|
|
|
581
|
-
**Built-in profiles:** `unrestricted`, `restricted` (
|
|
647
|
+
**Built-in profiles:** `unrestricted`, `restricted` (denies network tools *and* interpreters/shells — `python -c`, `node -e`, `bash` and friends can't exfiltrate injected secrets; 30s limit), `ci` (5min limit, blocks destructive commands).
|
|
582
648
|
|
|
583
649
|
### Tamper-Evident Audit
|
|
584
650
|
|
|
585
|
-
Every audit event includes a SHA-256 hash of the previous event, creating a tamper-evident chain. Verify integrity and export logs in multiple formats.
|
|
651
|
+
Every audit event includes a SHA-256 hash of the previous event, creating a tamper-evident chain. Since v0.14 the chain is also anchored with a keyed HMAC stored in the OS keyring, so `qring audit:verify` detects truncation and whole-file rewrites — not just in-place edits. Verify integrity and export logs in multiple formats.
|
|
586
652
|
|
|
587
653
|
```bash
|
|
588
654
|
# Verify the entire audit chain
|
|
@@ -595,6 +661,18 @@ qring audit:export --format json --since 2026-03-01
|
|
|
595
661
|
qring audit:export --format csv --output audit-report.csv
|
|
596
662
|
```
|
|
597
663
|
|
|
664
|
+
### Encrypted File Backend (Headless / CI)
|
|
665
|
+
|
|
666
|
+
Hosts with no OS keyring at all (headless Linux, containers, CI) can opt into an encrypted file store. Everything — secrets, the audit anchor, the agent-memory key — routes through it.
|
|
667
|
+
|
|
668
|
+
```bash
|
|
669
|
+
export QRING_BACKEND=file
|
|
670
|
+
export QRING_FILE_PASSPHRASE="a strong passphrase" # required — no passphrase, no access
|
|
671
|
+
qring set CI_TOKEN
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
The store is AES-256-GCM at `~/.config/q-ring/file-backend.enc` (mode `0600`, path override via `QRING_FILE_BACKEND_PATH`), keyed by PBKDF2 from the passphrase. It is **explicit-only**: a missing OS keyring never falls back to it silently, and without the passphrase every operation fails closed — q-ring never encrypts under a machine-derivable key.
|
|
675
|
+
|
|
598
676
|
### Team & Org Scopes
|
|
599
677
|
|
|
600
678
|
Extend beyond `global` and `project` scopes with `team` and `org` scopes for shared secrets across groups. Resolution order: project → team → org → global (most specific wins).
|
|
@@ -987,6 +1065,13 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide (dev environment, conv
|
|
|
987
1065
|
- **Claude Code:** `pnpm run plugin:sync:claude` copies `claude-code-plugin/` into the current directory (or pass a project path; add `--user` to install at `~/.claude/`).
|
|
988
1066
|
- See also [docs/cli-mcp-parity.md](docs/cli-mcp-parity.md).
|
|
989
1067
|
|
|
1068
|
+
## 🔒 Security
|
|
1069
|
+
|
|
1070
|
+
- **Local-first.** Core storage is your OS keychain — there is no q-ring cloud and no account. The MCP surface, audit log, and agent memory live on your machine (audit and memory files are written owner-only, `0600`).
|
|
1071
|
+
- **Written-down threat model.** What q-ring protects, what it doesn't, and where the residual risk lives — including an honest answer to the agent-exfiltration question — in [docs/threat-model.md](docs/threat-model.md).
|
|
1072
|
+
- **Hardened by adversarial review.** v0.14.0 shipped the results of an internal adversarial audit — policy-bypass, approval-scoping, and exec-profile findings all fixed, each with regression tests. Details are in the [CHANGELOG](CHANGELOG.md) `Security` sections (house style since 0.12.0: fix first, then disclose there).
|
|
1073
|
+
- **Reporting a vulnerability.** Use [GitHub private vulnerability reporting](https://github.com/I4cTime/q-ring/security/advisories/new) — see [SECURITY.md](SECURITY.md) for the supported-versions table and response commitments (48-hour acknowledgement, 7-day assessment).
|
|
1074
|
+
|
|
990
1075
|
## 📜 License
|
|
991
1076
|
|
|
992
1077
|
[AGPL-3.0](LICENSE) - Free to use, modify, and share. Any derivative work or hosted service must release its source code under the same license.
|