@i4ctime/q-ring 0.13.1 → 0.14.1
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 +15 -6
- package/assets/icon-192.png +0 -0
- package/assets/icon-512.png +0 -0
- package/assets/mark-mono.svg +27 -0
- package/assets/mark-small.svg +15 -0
- package/assets/mark.svg +44 -0
- package/assets/repo-social-preview.png +0 -0
- package/assets/social-card-optimized.jpg +0 -0
- package/dist/{chunk-Z7UJFHVE.js → chunk-C2TFJ2EH.js} +440 -186
- package/dist/chunk-C2TFJ2EH.js.map +1 -0
- package/dist/{chunk-Q3UCKJAJ.js → chunk-NNIEXAW5.js} +428 -180
- package/dist/chunk-NNIEXAW5.js.map +1 -0
- package/dist/{dashboard-2UDYGGTT.js → dashboard-KAUEPLXO.js} +2 -2
- package/dist/{dashboard-2IGUR7PA.js → dashboard-PYYAED45.js} +2 -2
- package/dist/index.js +60 -8
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +49 -7
- package/dist/mcp.js.map +1 -1
- package/package.json +18 -6
- package/dist/chunk-Q3UCKJAJ.js.map +0 -1
- package/dist/chunk-Z7UJFHVE.js.map +0 -1
- /package/dist/{dashboard-2IGUR7PA.js.map → dashboard-KAUEPLXO.js.map} +0 -0
- /package/dist/{dashboard-2UDYGGTT.js.map → dashboard-PYYAED45.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
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
9
|
[](https://www.npmjs.com/package/@i4ctime/q-ring)
|
|
10
10
|
[](https://qring.i4c.studio/docs)
|
|
11
11
|
[](https://glama.ai/mcp/servers/I4cTime/q-ring)
|
|
12
12
|
[](https://github.com/I4cTime/q-ring/blob/main/LICENSE)
|
|
13
|
+
[](https://discord.gg/5uEApw5uEz)
|
|
13
14
|
|
|
14
15
|
<a href="https://glama.ai/mcp/servers/I4cTime/q-ring">
|
|
15
16
|
<img src="https://glama.ai/mcp/servers/I4cTime/q-ring/badges/card.svg" alt="q-ring MCP server" width="400" />
|
|
@@ -382,7 +383,7 @@ qring exec -- npm run deploy
|
|
|
382
383
|
# Inject only specific tags
|
|
383
384
|
qring exec --tags backend -- node server.js
|
|
384
385
|
|
|
385
|
-
# Run with a restricted profile (blocks
|
|
386
|
+
# Run with a restricted profile (blocks network tools and interpreters/shells, 30s timeout)
|
|
386
387
|
qring exec --profile restricted -- npm test
|
|
387
388
|
```
|
|
388
389
|
|
|
@@ -532,6 +533,8 @@ Define project-level governance rules in `.q-ring.json` to control which MCP too
|
|
|
532
533
|
|
|
533
534
|
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.
|
|
534
535
|
|
|
536
|
+
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.
|
|
537
|
+
|
|
535
538
|
```bash
|
|
536
539
|
# View the active policy
|
|
537
540
|
qring policy
|
|
@@ -567,7 +570,7 @@ Example policy in `.q-ring.json`:
|
|
|
567
570
|
Restrict command execution with named profiles that control allowed commands, network access, timeouts, and environment sanitization.
|
|
568
571
|
|
|
569
572
|
```bash
|
|
570
|
-
# Run with the "restricted" profile (blocks
|
|
573
|
+
# Run with the "restricted" profile (blocks network tools and interpreters/shells; 30s timeout)
|
|
571
574
|
qring exec --profile restricted -- npm test
|
|
572
575
|
|
|
573
576
|
# Run with the "ci" profile (5min timeout, allows network)
|
|
@@ -577,11 +580,11 @@ qring exec --profile ci -- npm run deploy
|
|
|
577
580
|
qring exec -- echo "hello"
|
|
578
581
|
```
|
|
579
582
|
|
|
580
|
-
**Built-in profiles:** `unrestricted`, `restricted` (
|
|
583
|
+
**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).
|
|
581
584
|
|
|
582
585
|
### Tamper-Evident Audit
|
|
583
586
|
|
|
584
|
-
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.
|
|
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.
|
|
585
588
|
|
|
586
589
|
```bash
|
|
587
590
|
# Verify the entire audit chain
|
|
@@ -986,6 +989,12 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide (dev environment, conv
|
|
|
986
989
|
- **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/`).
|
|
987
990
|
- See also [docs/cli-mcp-parity.md](docs/cli-mcp-parity.md).
|
|
988
991
|
|
|
992
|
+
## 🔒 Security
|
|
993
|
+
|
|
994
|
+
- **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`).
|
|
995
|
+
- **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
|
+
- **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
|
+
|
|
989
998
|
## 📜 License
|
|
990
999
|
|
|
991
1000
|
[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.
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="none">
|
|
2
|
+
<!-- q-ring brand mark, single-color cut (badges/stickers/engraving). -->
|
|
3
|
+
<defs>
|
|
4
|
+
<mask id="qhole" maskUnits="userSpaceOnUse" x="0" y="0" width="512" height="512">
|
|
5
|
+
<rect width="512" height="512" fill="#fff"/>
|
|
6
|
+
<ellipse cx="256" cy="243" rx="78" ry="73" fill="#000"/>
|
|
7
|
+
</mask>
|
|
8
|
+
</defs>
|
|
9
|
+
<g stroke="#f8f8ff" fill="none" stroke-linecap="round">
|
|
10
|
+
<path d="M256 84C204 110 146 116 94 122C92 242 130 364 256 452C382 364 420 242 418 122C366 116 308 110 256 84Z" stroke-width="9"/>
|
|
11
|
+
<path d="M256 102C209.2 125.4 157 130.8 110.2 136.2C108.4 244.2 142.6 354 256 433.2C369.4 354 403.6 244.2 401.8 136.2C355 130.8 302.8 125.4 256 102Z" stroke-width="4.5"/>
|
|
12
|
+
<g mask="url(#qhole)">
|
|
13
|
+
<ellipse cx="256" cy="243" rx="118" ry="46" transform="rotate(-62 256 243)" stroke-width="4"/>
|
|
14
|
+
<ellipse cx="256" cy="243" rx="118" ry="46" transform="rotate(0 256 243)" stroke-width="4"/>
|
|
15
|
+
<ellipse cx="256" cy="243" rx="118" ry="46" transform="rotate(62 256 243)" stroke-width="4"/>
|
|
16
|
+
</g>
|
|
17
|
+
<ellipse cx="256" cy="243" rx="72" ry="72" stroke-width="6.5"/>
|
|
18
|
+
<ellipse cx="256" cy="243" rx="76.5" ry="65.5" transform="rotate(30 256 243)" stroke-width="5.5"/>
|
|
19
|
+
<ellipse cx="256" cy="243" rx="76.5" ry="65.5" transform="rotate(-30 256 243)" stroke-width="5.5"/>
|
|
20
|
+
<circle cx="323.37" cy="157.7" r="8" fill="#f8f8ff" stroke="none"/>
|
|
21
|
+
<circle cx="188.63" cy="328.3" r="8" fill="#f8f8ff" stroke="none"/>
|
|
22
|
+
<circle cx="155.93" cy="267.38" r="8" fill="#f8f8ff" stroke="none"/>
|
|
23
|
+
<circle cx="356.07" cy="218.62" r="8" fill="#f8f8ff" stroke="none"/>
|
|
24
|
+
<circle cx="189.28" cy="192.57" r="8" fill="#f8f8ff" stroke="none"/>
|
|
25
|
+
<circle cx="322.72" cy="293.43" r="8" fill="#f8f8ff" stroke="none"/>
|
|
26
|
+
</g>
|
|
27
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="none">
|
|
2
|
+
<!-- q-ring brand mark, small-size cut (favicon-legible): shield + ring.
|
|
3
|
+
Colors canonical; source of truth: apps/qring/lib/palette.ts. -->
|
|
4
|
+
<defs>
|
|
5
|
+
<linearGradient id="qg" gradientUnits="userSpaceOnUse" x1="72" y1="256" x2="440" y2="256">
|
|
6
|
+
<stop offset="0" stop-color="#00D1FF"/>
|
|
7
|
+
<stop offset="0.52" stop-color="#7B2DFF"/>
|
|
8
|
+
<stop offset="1" stop-color="#D946EF"/>
|
|
9
|
+
</linearGradient>
|
|
10
|
+
</defs>
|
|
11
|
+
<g stroke="url(#qg)" fill="none" stroke-linecap="round">
|
|
12
|
+
<path d="M256 84C204 110 146 116 94 122C92 242 130 364 256 452C382 364 420 242 418 122C366 116 308 110 256 84Z" stroke-width="24"/>
|
|
13
|
+
<circle cx="256" cy="246" r="96" stroke-width="28"/>
|
|
14
|
+
</g>
|
|
15
|
+
</svg>
|
package/assets/mark.svg
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="none">
|
|
2
|
+
<!-- q-ring brand mark. Colors are canonical brand hex values; source of
|
|
3
|
+
truth: apps/qring/lib/palette.ts + app/globals.css @theme. -->
|
|
4
|
+
<defs>
|
|
5
|
+
<linearGradient id="qg" gradientUnits="userSpaceOnUse" x1="72" y1="256" x2="440" y2="256">
|
|
6
|
+
<stop offset="0" stop-color="#00D1FF"/>
|
|
7
|
+
<stop offset="0.52" stop-color="#7B2DFF"/>
|
|
8
|
+
<stop offset="1" stop-color="#D946EF"/>
|
|
9
|
+
</linearGradient>
|
|
10
|
+
<mask id="qhole" maskUnits="userSpaceOnUse" x="0" y="0" width="512" height="512">
|
|
11
|
+
<rect width="512" height="512" fill="#fff"/>
|
|
12
|
+
<ellipse cx="256" cy="243" rx="78" ry="73" fill="#000"/>
|
|
13
|
+
</mask>
|
|
14
|
+
<filter id="qglow-wide" x="-30%" y="-30%" width="160%" height="160%">
|
|
15
|
+
<feGaussianBlur stdDeviation="9"/>
|
|
16
|
+
</filter>
|
|
17
|
+
<filter id="qglow-tight" x="-30%" y="-30%" width="160%" height="160%">
|
|
18
|
+
<feGaussianBlur stdDeviation="2.5"/>
|
|
19
|
+
</filter>
|
|
20
|
+
<g id="qart">
|
|
21
|
+
<g stroke="url(#qg)" fill="none" stroke-linecap="round">
|
|
22
|
+
<path d="M256 84C204 110 146 116 94 122C92 242 130 364 256 452C382 364 420 242 418 122C366 116 308 110 256 84Z" stroke-width="9"/>
|
|
23
|
+
<path d="M256 102C209.2 125.4 157 130.8 110.2 136.2C108.4 244.2 142.6 354 256 433.2C369.4 354 403.6 244.2 401.8 136.2C355 130.8 302.8 125.4 256 102Z" stroke-width="4.5"/>
|
|
24
|
+
<g mask="url(#qhole)">
|
|
25
|
+
<ellipse cx="256" cy="243" rx="118" ry="46" transform="rotate(-62 256 243)" stroke-width="4"/>
|
|
26
|
+
<ellipse cx="256" cy="243" rx="118" ry="46" transform="rotate(0 256 243)" stroke-width="4"/>
|
|
27
|
+
<ellipse cx="256" cy="243" rx="118" ry="46" transform="rotate(62 256 243)" stroke-width="4"/>
|
|
28
|
+
</g>
|
|
29
|
+
<ellipse cx="256" cy="243" rx="72" ry="72" stroke-width="6.5"/>
|
|
30
|
+
<ellipse cx="256" cy="243" rx="76.5" ry="65.5" transform="rotate(30 256 243)" stroke-width="5.5"/>
|
|
31
|
+
<ellipse cx="256" cy="243" rx="76.5" ry="65.5" transform="rotate(-30 256 243)" stroke-width="5.5"/>
|
|
32
|
+
<circle cx="323.37" cy="157.7" r="8" fill="url(#qg)" stroke="none"/>
|
|
33
|
+
<circle cx="188.63" cy="328.3" r="8" fill="url(#qg)" stroke="none"/>
|
|
34
|
+
<circle cx="155.93" cy="267.38" r="8" fill="url(#qg)" stroke="none"/>
|
|
35
|
+
<circle cx="356.07" cy="218.62" r="8" fill="url(#qg)" stroke="none"/>
|
|
36
|
+
<circle cx="189.28" cy="192.57" r="8" fill="url(#qg)" stroke="none"/>
|
|
37
|
+
<circle cx="322.72" cy="293.43" r="8" fill="url(#qg)" stroke="none"/>
|
|
38
|
+
</g>
|
|
39
|
+
</g>
|
|
40
|
+
</defs>
|
|
41
|
+
<use href="#qart" filter="url(#qglow-wide)" opacity="0.75"/>
|
|
42
|
+
<use href="#qart" filter="url(#qglow-tight)" opacity="0.9"/>
|
|
43
|
+
<use href="#qart"/>
|
|
44
|
+
</svg>
|
|
Binary file
|
|
Binary file
|