aivault-mcp 0.1.0 โ 0.1.2
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 +33 -34
- package/dist/cli/cli.js +2 -1
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/commands/dashboard.d.ts.map +1 -1
- package/dist/cli/commands/dashboard.js +141 -53
- package/dist/cli/commands/dashboard.js.map +1 -1
- package/dist/cli/commands/set.d.ts +1 -1
- package/dist/cli/commands/set.d.ts.map +1 -1
- package/dist/cli/commands/set.js +2 -2
- package/dist/cli/commands/set.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AIVault
|
|
2
2
|
|
|
3
3
|
**Stop pasting API keys into AI chat.**
|
|
4
4
|
|
|
5
5
|
AIVault is an [MCP server](https://modelcontextprotocol.io) that lets AI agents use your credentials **without ever seeing them**. The AI references secrets by name (`$GITHUB_TOKEN`), AIVault injects the real values at runtime, and scrubs them from the output before the AI sees anything.
|
|
6
6
|
|
|
7
|
-
Works with
|
|
7
|
+
Works with Claude Desktop, Kiro, Cursor, Windsurf, and any MCP-compatible client.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -16,11 +16,11 @@ Every day, developers paste API keys, database passwords, and tokens directly in
|
|
|
16
16
|
|
|
17
17
|
```
|
|
18
18
|
You: "Deploy my app to AWS"
|
|
19
|
-
AI: calls run_command
|
|
20
|
-
AIVault:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
AI: calls run_command -> "aws s3 cp ./build s3://my-bucket"
|
|
20
|
+
AIVault: Injects $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY as env vars
|
|
21
|
+
Runs the command
|
|
22
|
+
Scrubs any leaked secrets from output
|
|
23
|
+
Returns clean result to AI
|
|
24
24
|
AI: "Done! All files uploaded to S3."
|
|
25
25
|
```
|
|
26
26
|
|
|
@@ -67,7 +67,6 @@ Add to your MCP config:
|
|
|
67
67
|
}
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
|
|
71
70
|
| AI Tool | Config File Location |
|
|
72
71
|
|---------|---------------------|
|
|
73
72
|
| Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) |
|
|
@@ -75,7 +74,7 @@ Add to your MCP config:
|
|
|
75
74
|
| Cursor | `.cursor/mcp.json` in your project |
|
|
76
75
|
| Windsurf | `~/.windsurf/mcp.json` |
|
|
77
76
|
|
|
78
|
-
### 5.
|
|
77
|
+
### 5. Ask your AI to use your secrets
|
|
79
78
|
|
|
80
79
|
> "Check how many users are in my database"
|
|
81
80
|
|
|
@@ -91,42 +90,42 @@ Manage secrets visually instead of the CLI:
|
|
|
91
90
|
aivault dashboard
|
|
92
91
|
```
|
|
93
92
|
|
|
94
|
-
Opens a local web UI at `http://localhost:7470` where you can add, view, and delete secrets from your browser.
|
|
93
|
+
Opens a local web UI at `http://localhost:7470` where you can add, view, edit, and delete secrets from your browser.
|
|
95
94
|
|
|
96
95
|
---
|
|
97
96
|
|
|
98
97
|
## How It Works
|
|
99
98
|
|
|
100
99
|
```
|
|
101
|
-
User
|
|
102
|
-
|
|
100
|
+
User <-> AI (Claude, Kiro, Cursor, etc.)
|
|
101
|
+
|
|
|
103
102
|
MCP Protocol
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
103
|
+
|
|
|
104
|
+
+------------------+
|
|
105
|
+
| AIVault MCP |
|
|
106
|
+
| |
|
|
107
|
+
| Secret Store | <- AES-256-GCM encrypted local file
|
|
108
|
+
| Executor | <- Injects secrets as env vars
|
|
109
|
+
| Scrubber | <- Removes secret values from output
|
|
110
|
+
+------------------+
|
|
112
111
|
```
|
|
113
112
|
|
|
114
113
|
### MCP Tools
|
|
115
114
|
|
|
116
115
|
| Tool | What it does |
|
|
117
116
|
|------|-------------|
|
|
118
|
-
| `list_secrets` | Shows available secrets (name + description only,
|
|
117
|
+
| `list_secrets` | Shows available secrets (name + description only, never values) |
|
|
119
118
|
| `run_command` | Runs a shell command with secrets injected as env vars, output scrubbed |
|
|
120
119
|
| `request_secret` | AI asks the user to add a missing secret |
|
|
121
120
|
|
|
122
121
|
### Security
|
|
123
122
|
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
123
|
+
- Encrypted at rest โ AES-256-GCM with PBKDF2 key derivation (100k iterations, SHA-512)
|
|
124
|
+
- AI never sees values โ only names, descriptions, and tags
|
|
125
|
+
- Output always scrubbed โ raw, URL-encoded, and Base64-encoded values are all caught
|
|
126
|
+
- Env var injection only โ secrets are never interpolated into command strings (prevents shell injection)
|
|
127
|
+
- Timeout enforcement โ commands are killed after 30s (configurable, max 300s)
|
|
128
|
+
- 100% local โ no cloud, no network, no telemetry
|
|
130
129
|
|
|
131
130
|
---
|
|
132
131
|
|
|
@@ -147,19 +146,19 @@ Set `AIVAULT_MASTER_PASSWORD` env var to skip password prompts.
|
|
|
147
146
|
|
|
148
147
|
## Example Interactions
|
|
149
148
|
|
|
150
|
-
|
|
149
|
+
Using a database:
|
|
151
150
|
> You: "How many orders were placed today?"
|
|
152
|
-
> AI
|
|
151
|
+
> AI runs: `psql $DB_URL -c "SELECT COUNT(*) FROM orders WHERE date = CURRENT_DATE"`
|
|
153
152
|
> Result: `count: 847` (connection string scrubbed)
|
|
154
153
|
|
|
155
|
-
|
|
154
|
+
Deploying code:
|
|
156
155
|
> You: "Push my Docker image to ECR"
|
|
157
|
-
> AI
|
|
156
|
+
> AI runs: `aws ecr get-login-password | docker login ... && docker push`
|
|
158
157
|
> AWS credentials injected via env vars, never visible to AI
|
|
159
158
|
|
|
160
|
-
|
|
159
|
+
Missing credential:
|
|
161
160
|
> You: "Send a Slack notification"
|
|
162
|
-
> AI
|
|
161
|
+
> AI: "I need a SLACK_WEBHOOK_URL. Please run: `aivault set SLACK_WEBHOOK_URL --desc 'Slack webhook'`"
|
|
163
162
|
|
|
164
163
|
---
|
|
165
164
|
|
|
@@ -169,4 +168,4 @@ MIT
|
|
|
169
168
|
|
|
170
169
|
---
|
|
171
170
|
|
|
172
|
-
Built by [Mohammed Shomis](https://github.com/mohshomis)
|
|
171
|
+
Built by [Mohammed Shomis](https://github.com/mohshomis) for developers who care about security.
|
package/dist/cli/cli.js
CHANGED
|
@@ -64,8 +64,9 @@ async function main() {
|
|
|
64
64
|
process.exit(1);
|
|
65
65
|
}
|
|
66
66
|
const tags = flags.tags ? flags.tags.split(',').map(t => t.trim()) : [];
|
|
67
|
+
const force = flags.force === 'true';
|
|
67
68
|
const password = await getPassword();
|
|
68
|
-
await (0, set_1.setCommand)(name, desc, tags, password);
|
|
69
|
+
await (0, set_1.setCommand)(name, desc, tags, password, force);
|
|
69
70
|
break;
|
|
70
71
|
}
|
|
71
72
|
case 'list': {
|
package/dist/cli/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":";;;AACA,0CAA8C;AAC9C,wCAA4C;AAC5C,0CAA8C;AAC9C,8CAAkD;AAClD,8CAAkD;AAClD,oDAAwD;AACxD,mCAAuC;AAEvC,KAAK,UAAU,WAAW;IACxB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IACxD,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IACpC,OAAO,IAAA,oBAAY,EAAC,mBAAmB,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;IAClC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,KAAK,GAA2B,EAAE,CAAC;IAEzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAChF,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;CAab,CAAC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAExE,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM;YACT,MAAM,IAAA,kBAAW,GAAE,CAAC;YACpB,MAAM;QAER,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAC;gBACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,WAAW,CAAC;YAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;gBAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACxE,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;YACrC,MAAM,IAAA,gBAAU,EAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dashboard.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dashboard.ts"],"names":[],"mappings":"AAyKA,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAiFvD"}
|
|
@@ -7,83 +7,137 @@ exports.dashboardCommand = dashboardCommand;
|
|
|
7
7
|
const http_1 = __importDefault(require("http"));
|
|
8
8
|
const store_1 = require("../../vault/store");
|
|
9
9
|
const PORT = 7470;
|
|
10
|
-
function
|
|
10
|
+
function esc(s) {
|
|
11
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
12
|
+
}
|
|
13
|
+
function html(store, message, editName) {
|
|
11
14
|
let secrets = [];
|
|
12
15
|
try {
|
|
13
16
|
secrets = store.listSecrets();
|
|
14
17
|
}
|
|
15
18
|
catch { }
|
|
19
|
+
const editSecret = editName ? store.getSecret(editName) : undefined;
|
|
16
20
|
const rows = secrets.map(s => `
|
|
17
21
|
<tr>
|
|
18
22
|
<td><code>${esc(s.name)}</code></td>
|
|
19
23
|
<td>${esc(s.description)}</td>
|
|
20
|
-
<td>${s.tags.map(t => `<span class="tag">${esc(t)}</span>`).join(' ')}</td>
|
|
21
|
-
<td>
|
|
22
|
-
<
|
|
24
|
+
<td>${s.tags.map(t => `<span class="tag">${esc(t)}</span>`).join(' ') || '<span class="muted">โ</span>'}</td>
|
|
25
|
+
<td class="actions">
|
|
26
|
+
<a href="/edit?name=${encodeURIComponent(s.name)}" class="btn-icon" title="Edit">Edit</a>
|
|
27
|
+
<form method="POST" action="/delete" style="display:inline">
|
|
23
28
|
<input type="hidden" name="name" value="${esc(s.name)}">
|
|
24
|
-
<button type="submit" class="btn-
|
|
29
|
+
<button type="submit" class="btn-icon btn-danger" onclick="return confirm('Delete ${esc(s.name)}?')" title="Delete">Delete</button>
|
|
25
30
|
</form>
|
|
26
31
|
</td>
|
|
27
32
|
</tr>`).join('');
|
|
28
33
|
const banner = message ? `<div class="banner">${esc(message)}</div>` : '';
|
|
34
|
+
const editForm = editSecret ? `
|
|
35
|
+
<div class="card">
|
|
36
|
+
<div class="card-header">
|
|
37
|
+
<h2>Edit: ${esc(editSecret.name)}</h2>
|
|
38
|
+
<a href="/" class="btn-secondary">Cancel</a>
|
|
39
|
+
</div>
|
|
40
|
+
<form method="POST" action="/update">
|
|
41
|
+
<input type="hidden" name="name" value="${esc(editSecret.name)}">
|
|
42
|
+
<div class="form-grid-edit">
|
|
43
|
+
<div><label>Description</label><input type="text" name="description" value="${esc(editSecret.description)}" required></div>
|
|
44
|
+
<div><label>New Value (leave blank to keep current)</label><input type="password" name="value" placeholder="Leave blank to keep unchanged"></div>
|
|
45
|
+
<div><label>Tags</label><input type="text" name="tags" value="${esc(editSecret.tags.join(', '))}" placeholder="comma-separated"></div>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="form-meta">
|
|
48
|
+
<span class="muted">Created: ${editSecret.created_at.split('T')[0]}</span>
|
|
49
|
+
<span class="muted">Updated: ${editSecret.updated_at.split('T')[0]}</span>
|
|
50
|
+
</div>
|
|
51
|
+
<button type="submit" class="btn">Save Changes</button>
|
|
52
|
+
</form>
|
|
53
|
+
</div>` : '';
|
|
29
54
|
return `<!DOCTYPE html>
|
|
30
55
|
<html lang="en"><head>
|
|
31
56
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
32
|
-
<title>AIVault
|
|
57
|
+
<title>AIVault</title>
|
|
33
58
|
<style>
|
|
34
59
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
35
|
-
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0d1117; color: #e6edf3; padding: 2rem; }
|
|
36
|
-
h1 { font-size: 1.
|
|
37
|
-
|
|
38
|
-
.
|
|
39
|
-
.
|
|
60
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0d1117; color: #e6edf3; padding: 2rem; max-width: 960px; margin: 0 auto; }
|
|
61
|
+
h1 { font-size: 1.5rem; margin-bottom: .2rem; }
|
|
62
|
+
h2 { font-size: 1rem; }
|
|
63
|
+
.subtitle { color: #8b949e; margin-bottom: 1.5rem; font-size: .85rem; }
|
|
64
|
+
.banner { background: #1a7f37; color: #fff; padding: .5rem 1rem; border-radius: 6px; margin-bottom: 1rem; font-size: .85rem; }
|
|
65
|
+
.card { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 1.2rem; margin-bottom: 1.2rem; }
|
|
66
|
+
.card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; }
|
|
40
67
|
table { width: 100%; border-collapse: collapse; }
|
|
41
|
-
th { text-align: left; color: #8b949e; font-size: .
|
|
42
|
-
td { padding: .
|
|
43
|
-
code { background: #1c2128; padding: .
|
|
44
|
-
.tag { background: #
|
|
45
|
-
.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
68
|
+
th { text-align: left; color: #8b949e; font-size: .75rem; text-transform: uppercase; letter-spacing: .5px; padding: .5rem .6rem; border-bottom: 1px solid #30363d; }
|
|
69
|
+
td { padding: .6rem; border-bottom: 1px solid #21262d; font-size: .85rem; }
|
|
70
|
+
code { background: #1c2128; padding: .1rem .35rem; border-radius: 3px; font-size: .8rem; color: #79c0ff; }
|
|
71
|
+
.tag { background: #1f6feb22; color: #58a6ff; padding: .1rem .45rem; border-radius: 10px; font-size: .7rem; margin-right: .3rem; }
|
|
72
|
+
.muted { color: #484f58; font-size: .8rem; }
|
|
73
|
+
.empty { color: #8b949e; text-align: center; padding: 2rem; font-size: .85rem; }
|
|
74
|
+
.actions { white-space: nowrap; }
|
|
75
|
+
label { font-size: .75rem; color: #8b949e; display: block; margin-bottom: .2rem; }
|
|
76
|
+
input[type="text"], input[type="password"], input[type="search"] { width: 100%; background: #0d1117; border: 1px solid #30363d; color: #e6edf3; padding: .45rem .6rem; border-radius: 6px; font-size: .8rem; }
|
|
49
77
|
input:focus { outline: none; border-color: #58a6ff; }
|
|
50
|
-
.btn { background: #238636; color: #fff; border: none; padding: .
|
|
78
|
+
.btn { background: #238636; color: #fff; border: none; padding: .45rem 1rem; border-radius: 6px; cursor: pointer; font-size: .8rem; margin-top: .8rem; }
|
|
51
79
|
.btn:hover { background: #2ea043; }
|
|
52
|
-
.btn-
|
|
53
|
-
.btn-
|
|
54
|
-
.
|
|
55
|
-
|
|
80
|
+
.btn-secondary { background: transparent; color: #8b949e; border: 1px solid #30363d; padding: .35rem .8rem; border-radius: 6px; cursor: pointer; font-size: .8rem; text-decoration: none; }
|
|
81
|
+
.btn-secondary:hover { color: #e6edf3; border-color: #8b949e; }
|
|
82
|
+
.btn-icon { color: #8b949e; background: none; border: 1px solid #30363d; padding: .2rem .6rem; border-radius: 4px; cursor: pointer; font-size: .75rem; text-decoration: none; margin-right: .3rem; }
|
|
83
|
+
.btn-icon:hover { color: #e6edf3; border-color: #8b949e; }
|
|
84
|
+
.btn-danger { color: #f85149; border-color: #f8514933; }
|
|
85
|
+
.btn-danger:hover { background: #f8514922; border-color: #f85149; }
|
|
86
|
+
.form-grid { display: grid; grid-template-columns: 1fr 2fr 1fr 1fr; gap: .5rem; align-items: end; }
|
|
87
|
+
.form-grid-edit { display: grid; grid-template-columns: 1fr 1fr; gap: .8rem; }
|
|
88
|
+
.form-grid-edit > div:first-child { grid-column: 1 / -1; }
|
|
89
|
+
.form-meta { display: flex; gap: 1.5rem; margin-top: .8rem; }
|
|
90
|
+
.search-bar { margin-bottom: 1rem; }
|
|
91
|
+
.toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; }
|
|
92
|
+
.count { color: #8b949e; font-size: .8rem; }
|
|
93
|
+
@media (max-width: 700px) { .form-grid { grid-template-columns: 1fr; } .form-grid-edit { grid-template-columns: 1fr; } }
|
|
56
94
|
</style>
|
|
57
95
|
</head><body>
|
|
58
|
-
<h1
|
|
59
|
-
<p class="subtitle">Manage your secrets
|
|
96
|
+
<h1>AIVault</h1>
|
|
97
|
+
<p class="subtitle">Manage your secrets. Values are never displayed.</p>
|
|
60
98
|
${banner}
|
|
99
|
+
${editForm}
|
|
61
100
|
|
|
62
101
|
<div class="card">
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
102
|
+
<details${editName ? '' : ' open'}>
|
|
103
|
+
<summary style="cursor:pointer;font-size:.9rem;margin-bottom:.8rem;color:#8b949e;">Add New Secret</summary>
|
|
104
|
+
<form method="POST" action="/add">
|
|
105
|
+
<div class="form-grid">
|
|
106
|
+
<div><label>Name</label><input type="text" name="name" placeholder="GITHUB_TOKEN" required pattern="[A-Z][A-Z0-9_]*"></div>
|
|
107
|
+
<div><label>Description</label><input type="text" name="description" placeholder="GitHub PAT for repos" required></div>
|
|
108
|
+
<div><label>Value</label><input type="password" name="value" placeholder="secret value" required></div>
|
|
109
|
+
<div><label>Tags</label><input type="text" name="tags" placeholder="github, vcs"></div>
|
|
110
|
+
</div>
|
|
111
|
+
<button type="submit" class="btn">Add Secret</button>
|
|
112
|
+
</form>
|
|
113
|
+
</details>
|
|
71
114
|
</div>
|
|
72
115
|
|
|
73
116
|
<div class="card">
|
|
74
|
-
<div
|
|
75
|
-
<h2
|
|
117
|
+
<div class="toolbar">
|
|
118
|
+
<h2>Secrets</h2>
|
|
76
119
|
<span class="count">${secrets.length} secret${secrets.length !== 1 ? 's' : ''}</span>
|
|
77
120
|
</div>
|
|
121
|
+
<div class="search-bar">
|
|
122
|
+
<input type="search" id="search" placeholder="Filter by name, description, or tag..." oninput="filterTable()">
|
|
123
|
+
</div>
|
|
78
124
|
${secrets.length === 0
|
|
79
125
|
? '<p class="empty">No secrets yet. Add one above.</p>'
|
|
80
|
-
: `<table><thead><tr><th>Name</th><th>Description</th><th>Tags</th><th></th></tr></thead><tbody>${rows}</tbody></table>`}
|
|
126
|
+
: `<table id="secrets-table"><thead><tr><th>Name</th><th>Description</th><th>Tags</th><th></th></tr></thead><tbody>${rows}</tbody></table>`}
|
|
81
127
|
</div>
|
|
128
|
+
|
|
129
|
+
<script>
|
|
130
|
+
function filterTable() {
|
|
131
|
+
const q = document.getElementById('search').value.toLowerCase();
|
|
132
|
+
const rows = document.querySelectorAll('#secrets-table tbody tr');
|
|
133
|
+
rows.forEach(row => {
|
|
134
|
+
const text = row.textContent.toLowerCase();
|
|
135
|
+
row.style.display = text.includes(q) ? '' : 'none';
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
</script>
|
|
82
139
|
</body></html>`;
|
|
83
140
|
}
|
|
84
|
-
function esc(s) {
|
|
85
|
-
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
86
|
-
}
|
|
87
141
|
function parseBody(body) {
|
|
88
142
|
const params = {};
|
|
89
143
|
for (const pair of body.split('&')) {
|
|
@@ -99,6 +153,17 @@ function readBody(req) {
|
|
|
99
153
|
req.on('end', () => resolve(data));
|
|
100
154
|
});
|
|
101
155
|
}
|
|
156
|
+
function parseQuery(url) {
|
|
157
|
+
const idx = url.indexOf('?');
|
|
158
|
+
if (idx < 0)
|
|
159
|
+
return {};
|
|
160
|
+
const params = {};
|
|
161
|
+
for (const pair of url.slice(idx + 1).split('&')) {
|
|
162
|
+
const [key, ...rest] = pair.split('=');
|
|
163
|
+
params[decodeURIComponent(key)] = decodeURIComponent(rest.join('='));
|
|
164
|
+
}
|
|
165
|
+
return params;
|
|
166
|
+
}
|
|
102
167
|
function dashboardCommand(password) {
|
|
103
168
|
const store = new store_1.VaultStore(password);
|
|
104
169
|
if (!store.isInitialized()) {
|
|
@@ -107,20 +172,26 @@ function dashboardCommand(password) {
|
|
|
107
172
|
}
|
|
108
173
|
const server = http_1.default.createServer(async (req, res) => {
|
|
109
174
|
const url = req.url || '/';
|
|
110
|
-
|
|
175
|
+
const pathname = url.split('?')[0];
|
|
176
|
+
if (req.method === 'GET' && pathname === '/') {
|
|
111
177
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
112
178
|
res.end(html(store));
|
|
113
179
|
return;
|
|
114
180
|
}
|
|
115
|
-
if (req.method === '
|
|
181
|
+
if (req.method === 'GET' && pathname === '/edit') {
|
|
182
|
+
const query = parseQuery(url);
|
|
183
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
184
|
+
res.end(html(store, undefined, query.name));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (req.method === 'POST' && pathname === '/add') {
|
|
116
188
|
const body = await readBody(req);
|
|
117
189
|
const params = parseBody(body);
|
|
118
|
-
const { name, description, value, tags } = params;
|
|
119
190
|
let msg;
|
|
120
191
|
try {
|
|
121
|
-
const tagList = tags ? tags.split(',').map(t => t.trim()).filter(Boolean) : [];
|
|
122
|
-
store.setSecret(name, value, description, tagList);
|
|
123
|
-
msg = `Secret ${name} saved`;
|
|
192
|
+
const tagList = params.tags ? params.tags.split(',').map(t => t.trim()).filter(Boolean) : [];
|
|
193
|
+
store.setSecret(params.name, params.value, params.description, tagList);
|
|
194
|
+
msg = `Secret ${params.name} saved`;
|
|
124
195
|
}
|
|
125
196
|
catch (err) {
|
|
126
197
|
msg = `Error: ${err.message}`;
|
|
@@ -129,26 +200,43 @@ function dashboardCommand(password) {
|
|
|
129
200
|
res.end(html(store, msg));
|
|
130
201
|
return;
|
|
131
202
|
}
|
|
132
|
-
if (req.method === 'POST' &&
|
|
203
|
+
if (req.method === 'POST' && pathname === '/update') {
|
|
133
204
|
const body = await readBody(req);
|
|
134
205
|
const params = parseBody(body);
|
|
135
|
-
const { name } = params;
|
|
136
206
|
let msg;
|
|
137
|
-
|
|
138
|
-
|
|
207
|
+
try {
|
|
208
|
+
const existing = store.getSecret(params.name);
|
|
209
|
+
if (!existing) {
|
|
210
|
+
msg = `Secret ${params.name} not found`;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
const newValue = params.value || existing.value;
|
|
214
|
+
const tagList = params.tags ? params.tags.split(',').map(t => t.trim()).filter(Boolean) : [];
|
|
215
|
+
store.setSecret(params.name, newValue, params.description, tagList);
|
|
216
|
+
msg = `Secret ${params.name} updated`;
|
|
217
|
+
}
|
|
139
218
|
}
|
|
140
|
-
|
|
141
|
-
msg = `
|
|
219
|
+
catch (err) {
|
|
220
|
+
msg = `Error: ${err.message}`;
|
|
142
221
|
}
|
|
143
222
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
144
223
|
res.end(html(store, msg));
|
|
145
224
|
return;
|
|
146
225
|
}
|
|
226
|
+
if (req.method === 'POST' && pathname === '/delete') {
|
|
227
|
+
const body = await readBody(req);
|
|
228
|
+
const params = parseBody(body);
|
|
229
|
+
const deleted = store.deleteSecret(params.name);
|
|
230
|
+
const msg = deleted ? `Secret ${params.name} deleted` : `Secret ${params.name} not found`;
|
|
231
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
232
|
+
res.end(html(store, msg));
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
147
235
|
res.writeHead(404);
|
|
148
236
|
res.end('Not found');
|
|
149
237
|
});
|
|
150
238
|
server.listen(PORT, '127.0.0.1', () => {
|
|
151
|
-
console.log(`\
|
|
239
|
+
console.log(`\nAIVault Dashboard running at http://localhost:${PORT}\n`);
|
|
152
240
|
console.log('Press Ctrl+C to stop.\n');
|
|
153
241
|
});
|
|
154
242
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../../src/cli/commands/dashboard.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../../src/cli/commands/dashboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function setCommand(name: string, description: string, tags: string[], password: string): Promise<void>;
|
|
1
|
+
export declare function setCommand(name: string, description: string, tags: string[], password: string, force?: boolean): Promise<void>;
|
|
2
2
|
//# sourceMappingURL=set.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/set.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/set.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
|
package/dist/cli/commands/set.js
CHANGED
|
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.setCommand = setCommand;
|
|
4
4
|
const store_1 = require("../../vault/store");
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
|
-
async function setCommand(name, description, tags, password) {
|
|
6
|
+
async function setCommand(name, description, tags, password, force = false) {
|
|
7
7
|
const store = new store_1.VaultStore(password);
|
|
8
8
|
// Check if secret already exists
|
|
9
9
|
const existing = store.getSecret(name);
|
|
10
|
-
if (existing) {
|
|
10
|
+
if (existing && !force) {
|
|
11
11
|
const overwrite = await (0, utils_1.promptConfirm)(`Secret ${name} already exists. Overwrite? (y/N): `);
|
|
12
12
|
if (!overwrite) {
|
|
13
13
|
console.log('Aborted.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set.js","sourceRoot":"","sources":["../../../src/cli/commands/set.ts"],"names":[],"mappings":";;AAGA,
|
|
1
|
+
{"version":3,"file":"set.js","sourceRoot":"","sources":["../../../src/cli/commands/set.ts"],"names":[],"mappings":";;AAGA,gCAgCC;AAnCD,6CAA+C;AAC/C,oCAAuD;AAEhD,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,WAAmB,EACnB,IAAc,EACd,QAAgB,EAChB,QAAiB,KAAK;IAEtB,MAAM,KAAK,GAAG,IAAI,kBAAU,CAAC,QAAQ,CAAC,CAAC;IAEvC,iCAAiC;IACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,MAAM,IAAA,qBAAa,EAAC,UAAU,IAAI,qCAAqC,CAAC,CAAC;QAC3F,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACxB,OAAO;QACT,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,IAAA,oBAAY,EAAC,mBAAmB,IAAI,IAAI,CAAC,CAAC;IAC9D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|