@i4ctime/q-ring 0.14.1 → 0.16.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 CHANGED
@@ -6,11 +6,19 @@
6
6
 
7
7
  **OS keychain secrets for AI coding agents, over MCP.**
8
8
 
9
+ [![CI](https://img.shields.io/github/actions/workflow/status/I4cTime/q-ring/ci.yml?style=flat-square&label=CI)](https://github.com/I4cTime/q-ring/actions/workflows/ci.yml)
9
10
  [![NPM Version](https://img.shields.io/npm/v/@i4ctime/q-ring?style=flat-square&color=0ea5e9)](https://www.npmjs.com/package/@i4ctime/q-ring)
11
+ [![NPM Downloads](https://img.shields.io/npm/dm/@i4ctime/q-ring?style=flat-square&color=0ea5e9&label=downloads)](https://www.npmjs.com/package/@i4ctime/q-ring)
10
12
  [![Docs](https://img.shields.io/badge/docs-website-0ea5e9?style=flat-square)](https://qring.i4c.studio/docs)
11
13
  [![MCP Tools](https://img.shields.io/badge/MCP_tools-44-0ea5e9?style=flat-square)](https://glama.ai/mcp/servers/I4cTime/q-ring)
14
+ [![Smithery](https://img.shields.io/badge/smithery-i4ctime%2Fq--ring-0ea5e9?style=flat-square)](https://smithery.ai/servers/i4ctime/q-ring)
15
+ [![Cursor Directory](https://img.shields.io/badge/cursor_directory-q--ring-0ea5e9?style=flat-square)](https://cursor.directory/plugins/q-ring)
16
+ [![PulseMCP](https://img.shields.io/badge/pulsemcp-q--ring-0ea5e9?style=flat-square)](https://www.pulsemcp.com/servers/i4ctime-q-ring)
17
+ [![mcpservers.org](https://img.shields.io/badge/mcpservers.org-q--ring-0ea5e9?style=flat-square)](https://mcpservers.org/servers/i4ctime/q-ring)
12
18
  [![License](https://img.shields.io/npm/l/@i4ctime/q-ring?style=flat-square&color=0ea5e9)](https://github.com/I4cTime/q-ring/blob/main/LICENSE)
13
19
  [![Discord](https://img.shields.io/badge/discord-join%20the%20studio-5865F2?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/5uEApw5uEz)
20
+ [![YouTube](https://img.shields.io/badge/youtube-%40qring__dev-FF0000?style=flat-square&logo=youtube&logoColor=white)](https://www.youtube.com/@qring_dev)
21
+ [![X](https://img.shields.io/badge/follow-%40i4c__studio-000000?style=flat-square&logo=x&logoColor=white)](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
 
@@ -436,6 +498,43 @@ 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
+
503
+ ### Canary Honeytokens
504
+
505
+ Plant fake credentials that look and read exactly like real ones. Anything that touches one — a compromised MCP server, an over-curious agent, exfiltrated tooling sweeping the ring — gets the fake value back with no tell, while q-ring fires a desktop alert and writes a `canary` event into the tamper-evident audit chain.
506
+
507
+ ```bash
508
+ # Plant a canary shaped like a real AWS access key
509
+ qring canary plant AWS_SECRET_ACCESS_KEY --format aws
510
+
511
+ # Other shapes: github, openai, anthropic, stripe, generic
512
+ qring canary plant GHP_BACKUP_TOKEN --format github
513
+
514
+ # See what's been tripped
515
+ qring canary list
516
+ qring audit --action canary
517
+ ```
518
+
519
+ Values are CSPRNG noise in the provider's real token shape (an `aws` canary matches `AKIA[A-Z0-9]{16}`) — plausible enough to be taken, never valid. Alerts are throttled to one per key per 30 seconds; the audit trail records every read.
520
+
521
+ ### MCP Airlock
522
+
523
+ Run a third-party MCP server behind q-ring. The airlock sits between your agent host and the wrapped server, spawns it with a **stripped environment** (no inherited API keys — opt back in with `--inherit-env`), and records every tool call that crosses it as a `wrap` event in the audit chain, grouped per session and labeled with the calling client's identity. Tool arguments are never logged — they may contain secrets.
524
+
525
+ ```json
526
+ {
527
+ "mcpServers": {
528
+ "some-server": {
529
+ "command": "qring",
530
+ "args": ["mcp", "wrap", "--", "npx", "-y", "some-mcp-server"]
531
+ }
532
+ }
533
+ }
534
+ ```
535
+
536
+ Tools-only proxy today: `tools/list` and `tools/call` pass through verbatim, so the wrapped server behaves identically — it just can't read your environment, and everything it's asked to do is on the record.
537
+
439
538
  ### Just-In-Time (JIT) Provisioning
440
539
 
441
540
  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).
@@ -584,7 +683,7 @@ qring exec -- echo "hello"
584
683
 
585
684
  ### Tamper-Evident Audit
586
685
 
587
- 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.
686
+ 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. Events from MCP sessions are additionally stamped with the connecting client's self-reported identity (`clientInfo` name@version) — an audit label for "which agent did this", never an authorization boundary, since clients choose what to report.
588
687
 
589
688
  ```bash
590
689
  # Verify the entire audit chain
@@ -597,6 +696,18 @@ qring audit:export --format json --since 2026-03-01
597
696
  qring audit:export --format csv --output audit-report.csv
598
697
  ```
599
698
 
699
+ ### Encrypted File Backend (Headless / CI)
700
+
701
+ 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.
702
+
703
+ ```bash
704
+ export QRING_BACKEND=file
705
+ export QRING_FILE_PASSPHRASE="a strong passphrase" # required — no passphrase, no access
706
+ qring set CI_TOKEN
707
+ ```
708
+
709
+ 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.
710
+
600
711
  ### Team & Org Scopes
601
712
 
602
713
  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).
@@ -992,6 +1103,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide (dev environment, conv
992
1103
  ## 🔒 Security
993
1104
 
994
1105
  - **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`).
1106
+ - **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).
995
1107
  - **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).
996
1108
  - **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).
997
1109