@lifeaitools/clauth 1.5.56 → 1.5.59
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/.clauth-skill/SKILL.md +216 -216
- package/.clauth-skill/references/keys-guide.md +270 -270
- package/.clauth-skill/references/operator-guide.md +148 -148
- package/README.md +211 -211
- package/cli/api.js +121 -121
- package/cli/commands/install.js +404 -404
- package/cli/commands/scrub.js +231 -231
- package/cli/commands/serve.js +7438 -7264
- package/cli/commands/uninstall.js +164 -164
- package/cli/fingerprint.js +133 -133
- package/install.ps1 +109 -51
- package/install.sh +49 -49
- package/package.json +61 -61
- package/scripts/bin/bootstrap-linux +0 -0
- package/scripts/bin/bootstrap-macos +0 -0
- package/scripts/bootstrap.cjs +121 -121
- package/scripts/build.sh +45 -45
- package/supabase/functions/auth-vault/index.ts +255 -255
- package/supabase/migrations/001_clauth_schema.sql +103 -103
- package/supabase/migrations/002_vault_helpers.sql +90 -90
- package/supabase/migrations/20260317_lockout.sql +26 -26
package/README.md
CHANGED
|
@@ -1,211 +1,211 @@
|
|
|
1
|
-
# @lifeaitools/clauth
|
|
2
|
-
|
|
3
|
-
Hardware-bound credential vault for the LIFEAI stack. Your machine is the second factor. Keys live in Supabase Vault (AES-256). Nothing sensitive ever touches a config file.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install -g @lifeaitools/clauth
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Then provision your Supabase project:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
clauth install
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
That's it. `clauth install` handles everything:
|
|
20
|
-
- Creates all database tables
|
|
21
|
-
- Deploys the `auth-vault` Edge Function
|
|
22
|
-
- Generates HMAC salt + bootstrap token
|
|
23
|
-
- Tests the connection end-to-end
|
|
24
|
-
- Installs the Claude skill
|
|
25
|
-
|
|
26
|
-
At the end it prints a **bootstrap token** — save it for the next step.
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## After Install — Register Your Machine
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
clauth setup
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Prompts for: machine label, password, bootstrap token (from `clauth install`).
|
|
37
|
-
|
|
38
|
-
Then verify:
|
|
39
|
-
```bash
|
|
40
|
-
clauth test # → PASS
|
|
41
|
-
clauth status # → 12 services, all NO KEY
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## What clauth install asks for
|
|
47
|
-
|
|
48
|
-
Two things from Supabase:
|
|
49
|
-
|
|
50
|
-
**1. Project ref** — the last segment of your Supabase project URL:
|
|
51
|
-
`https://supabase.com/dashboard/project/` **`your-ref-here`**
|
|
52
|
-
|
|
53
|
-
**2. Personal Access Token (PAT)**:
|
|
54
|
-
`https://supabase.com/dashboard/account/tokens` → Generate new token
|
|
55
|
-
|
|
56
|
-
> This is **not** your anon key or service_role key — it is your account-level token.
|
|
57
|
-
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
## Writing Your First Key
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
clauth write key github # prompts for value
|
|
64
|
-
clauth enable github
|
|
65
|
-
clauth get github
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## Command Reference
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
clauth install Provision Supabase + install Claude skill
|
|
74
|
-
clauth setup Register this machine with the vault
|
|
75
|
-
clauth status All services + state
|
|
76
|
-
clauth test Verify connection
|
|
77
|
-
|
|
78
|
-
clauth write key <service> Store a credential
|
|
79
|
-
clauth write pw Change password
|
|
80
|
-
clauth enable <svc|all> Activate service
|
|
81
|
-
clauth disable <svc|all> Suspend service
|
|
82
|
-
clauth get <service> Retrieve a key
|
|
83
|
-
|
|
84
|
-
clauth add service <n> Register new service
|
|
85
|
-
clauth remove service <n> Remove service
|
|
86
|
-
clauth revoke <svc|all> Delete key (destructive)
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Built-in Services
|
|
90
|
-
|
|
91
|
-
`github` `supabase-anon` `supabase-service` `supabase-db`
|
|
92
|
-
`vercel` `namecheap` `neo4j` `anthropic`
|
|
93
|
-
`r2` `r2-bucket` `cloudflare` `rocketreach`
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## How It Works
|
|
98
|
-
|
|
99
|
-
```
|
|
100
|
-
Machine fingerprint (BIOS UUID + OS install ID)
|
|
101
|
-
+ Your clauth password
|
|
102
|
-
→ HMAC-SHA256 token + 5-min timestamp window
|
|
103
|
-
→ Supabase Edge Function validates
|
|
104
|
-
→ Returns AES-256 encrypted key from Vault
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Nothing stored locally. Password never persisted. Machine hash is one-way only.
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
## Daemon Mode (`clauth serve`)
|
|
112
|
-
|
|
113
|
-
clauth runs as an HTTP daemon on `http://127.0.0.1:52437`. The daemon provides:
|
|
114
|
-
|
|
115
|
-
- **Web UI** — unlock vault, manage services, configure mounts
|
|
116
|
-
- **REST API** — `GET /get/<service>`, `GET /ping`, `POST /restart`, `GET /shutdown`
|
|
117
|
-
- **MCP server** — Model Context Protocol for Claude Code and claude.ai
|
|
118
|
-
- **Cloudflare Tunnel** — exposes MCP endpoints publicly for claude.ai connectors
|
|
119
|
-
|
|
120
|
-
Start: `clauth serve start` (starts locked, auto-opens browser for unlock).
|
|
121
|
-
|
|
122
|
-
Full daemon operations reference: see `regen-root/.claude/rules/clauth.md`.
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## MCP Server — 3 Namespaces, 27 Tools
|
|
127
|
-
|
|
128
|
-
clauth is the single MCP interface for all local tools. One process, namespaced paths:
|
|
129
|
-
|
|
130
|
-
| Path | Namespace | Tools | Description |
|
|
131
|
-
|------|-----------|-------|-------------|
|
|
132
|
-
| `/clauth` | `clauth_*` | 13 | Credential vault operations |
|
|
133
|
-
| `/gws` | `gws_*` | 6 | Google Workspace (Gmail, Calendar, Drive) |
|
|
134
|
-
| `/fs` | `fs_*` | 8 | Filesystem (read, write, grep, glob, delete, mkdir, mounts) |
|
|
135
|
-
| `/mcp` | all | 27 | All namespaces combined (Claude Code) |
|
|
136
|
-
|
|
137
|
-
### FS Tools (v1.5.38)
|
|
138
|
-
|
|
139
|
-
8 filesystem tools with path-jail security:
|
|
140
|
-
- `fs_read`, `fs_write`, `fs_list`, `fs_grep`, `fs_glob`, `fs_delete`, `fs_mkdir`, `fs_mounts`
|
|
141
|
-
- Uses `node:fs/promises` (async), `@vscode/ripgrep` (shipped binary), `fast-glob`
|
|
142
|
-
- Permission flags per mount: `r` (read), `w` (write), `d` (delete)
|
|
143
|
-
- Mount config stored as "fileserver" service type in vault — only configurable through web UI
|
|
144
|
-
|
|
145
|
-
### GWS Tools
|
|
146
|
-
|
|
147
|
-
6 Google Workspace tools: `gws_gmail_list`, `gws_gmail_read`, `gws_gmail_send`, `gws_gmail_draft`, `gws_calendar_list`, `gws_calendar_create`
|
|
148
|
-
- Calls `gws` CLI via `execSync` with `shell: 'bash'` (fixes Windows cmd.exe JSON quoting)
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## claude.ai Integration
|
|
153
|
-
|
|
154
|
-
### Noauth Mode (v1.5.38)
|
|
155
|
-
|
|
156
|
-
claude.ai's OAuth proxy has a confirmed bug ([anthropics/claude-code#46140](https://github.com/anthropics/claude-code/issues/46140), [anthropics/claude-ai-mcp#136](https://github.com/anthropics/claude-ai-mcp/issues/136)): it completes the token exchange but never sends the authenticated request.
|
|
157
|
-
|
|
158
|
-
**Workaround:** Noauth hosts — fresh domains where OAuth endpoints return 404. claude.ai connects directly (tunnel URL is the shared secret).
|
|
159
|
-
|
|
160
|
-
### OAuth 2.1 (v1.5.36-37)
|
|
161
|
-
|
|
162
|
-
Full OAuth 2.1 protocol implementation is present for future use when Anthropic fixes the bug:
|
|
163
|
-
- 401 gate with `WWW-Authenticate` header
|
|
164
|
-
- Dynamic client registration (public client, no secret)
|
|
165
|
-
- Mandatory PKCE S256
|
|
166
|
-
- `Cache-Control: no-store`
|
|
167
|
-
|
|
168
|
-
### Connector URLs
|
|
169
|
-
|
|
170
|
-
| Connector | URL |
|
|
171
|
-
|-----------|-----|
|
|
172
|
-
| clauth | `https://clauth.regendevcorp.com/clauth` |
|
|
173
|
-
| gws | `https://clauth.regendevcorp.com/gws` |
|
|
174
|
-
| fs | `https://fs.regendevcorp.com/fs` |
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
## Dependencies (notable)
|
|
179
|
-
|
|
180
|
-
- `@vscode/ripgrep` — shipped ripgrep binary for `fs_grep`
|
|
181
|
-
- `fast-glob` — pattern matching for `fs_glob`
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## Testing
|
|
186
|
-
|
|
187
|
-
```bash
|
|
188
|
-
node test-tools.mjs # 25 tool execution tests across all 3 namespaces
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
Tests actual MCP tool calls (not just OAuth + listing).
|
|
192
|
-
|
|
193
|
-
---
|
|
194
|
-
|
|
195
|
-
## Releasing a New Version (maintainers)
|
|
196
|
-
|
|
197
|
-
```bash
|
|
198
|
-
# 1. Bump version in package.json
|
|
199
|
-
# 2. Commit and tag
|
|
200
|
-
git tag v1.5.38
|
|
201
|
-
git push && git push --tags
|
|
202
|
-
# GitHub Actions publishes automatically via Trusted Publishing
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
**NEVER** commit a version bump without tagging — the tag triggers npm CI.
|
|
206
|
-
|
|
207
|
-
---
|
|
208
|
-
|
|
209
|
-
> Life before Profits. — LIFEAI / PRT
|
|
210
|
-
>
|
|
211
|
-
> ☕ [Support this project](https://github.com/sponsors/DaveLadouceur)
|
|
1
|
+
# @lifeaitools/clauth
|
|
2
|
+
|
|
3
|
+
Hardware-bound credential vault for the LIFEAI stack. Your machine is the second factor. Keys live in Supabase Vault (AES-256). Nothing sensitive ever touches a config file.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @lifeaitools/clauth
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then provision your Supabase project:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
clauth install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
That's it. `clauth install` handles everything:
|
|
20
|
+
- Creates all database tables
|
|
21
|
+
- Deploys the `auth-vault` Edge Function
|
|
22
|
+
- Generates HMAC salt + bootstrap token
|
|
23
|
+
- Tests the connection end-to-end
|
|
24
|
+
- Installs the Claude skill
|
|
25
|
+
|
|
26
|
+
At the end it prints a **bootstrap token** — save it for the next step.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## After Install — Register Your Machine
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
clauth setup
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Prompts for: machine label, password, bootstrap token (from `clauth install`).
|
|
37
|
+
|
|
38
|
+
Then verify:
|
|
39
|
+
```bash
|
|
40
|
+
clauth test # → PASS
|
|
41
|
+
clauth status # → 12 services, all NO KEY
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## What clauth install asks for
|
|
47
|
+
|
|
48
|
+
Two things from Supabase:
|
|
49
|
+
|
|
50
|
+
**1. Project ref** — the last segment of your Supabase project URL:
|
|
51
|
+
`https://supabase.com/dashboard/project/` **`your-ref-here`**
|
|
52
|
+
|
|
53
|
+
**2. Personal Access Token (PAT)**:
|
|
54
|
+
`https://supabase.com/dashboard/account/tokens` → Generate new token
|
|
55
|
+
|
|
56
|
+
> This is **not** your anon key or service_role key — it is your account-level token.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Writing Your First Key
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
clauth write key github # prompts for value
|
|
64
|
+
clauth enable github
|
|
65
|
+
clauth get github
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Command Reference
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
clauth install Provision Supabase + install Claude skill
|
|
74
|
+
clauth setup Register this machine with the vault
|
|
75
|
+
clauth status All services + state
|
|
76
|
+
clauth test Verify connection
|
|
77
|
+
|
|
78
|
+
clauth write key <service> Store a credential
|
|
79
|
+
clauth write pw Change password
|
|
80
|
+
clauth enable <svc|all> Activate service
|
|
81
|
+
clauth disable <svc|all> Suspend service
|
|
82
|
+
clauth get <service> Retrieve a key
|
|
83
|
+
|
|
84
|
+
clauth add service <n> Register new service
|
|
85
|
+
clauth remove service <n> Remove service
|
|
86
|
+
clauth revoke <svc|all> Delete key (destructive)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Built-in Services
|
|
90
|
+
|
|
91
|
+
`github` `supabase-anon` `supabase-service` `supabase-db`
|
|
92
|
+
`vercel` `namecheap` `neo4j` `anthropic`
|
|
93
|
+
`r2` `r2-bucket` `cloudflare` `rocketreach`
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## How It Works
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
Machine fingerprint (BIOS UUID + OS install ID)
|
|
101
|
+
+ Your clauth password
|
|
102
|
+
→ HMAC-SHA256 token + 5-min timestamp window
|
|
103
|
+
→ Supabase Edge Function validates
|
|
104
|
+
→ Returns AES-256 encrypted key from Vault
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Nothing stored locally. Password never persisted. Machine hash is one-way only.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Daemon Mode (`clauth serve`)
|
|
112
|
+
|
|
113
|
+
clauth runs as an HTTP daemon on `http://127.0.0.1:52437`. The daemon provides:
|
|
114
|
+
|
|
115
|
+
- **Web UI** — unlock vault, manage services, configure mounts
|
|
116
|
+
- **REST API** — `GET /get/<service>`, `GET /ping`, `POST /restart`, `GET /shutdown`
|
|
117
|
+
- **MCP server** — Model Context Protocol for Claude Code and claude.ai
|
|
118
|
+
- **Cloudflare Tunnel** — exposes MCP endpoints publicly for claude.ai connectors
|
|
119
|
+
|
|
120
|
+
Start: `clauth serve start` (starts locked, auto-opens browser for unlock).
|
|
121
|
+
|
|
122
|
+
Full daemon operations reference: see `regen-root/.claude/rules/clauth.md`.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## MCP Server — 3 Namespaces, 27 Tools
|
|
127
|
+
|
|
128
|
+
clauth is the single MCP interface for all local tools. One process, namespaced paths:
|
|
129
|
+
|
|
130
|
+
| Path | Namespace | Tools | Description |
|
|
131
|
+
|------|-----------|-------|-------------|
|
|
132
|
+
| `/clauth` | `clauth_*` | 13 | Credential vault operations |
|
|
133
|
+
| `/gws` | `gws_*` | 6 | Google Workspace (Gmail, Calendar, Drive) |
|
|
134
|
+
| `/fs` | `fs_*` | 8 | Filesystem (read, write, grep, glob, delete, mkdir, mounts) |
|
|
135
|
+
| `/mcp` | all | 27 | All namespaces combined (Claude Code) |
|
|
136
|
+
|
|
137
|
+
### FS Tools (v1.5.38)
|
|
138
|
+
|
|
139
|
+
8 filesystem tools with path-jail security:
|
|
140
|
+
- `fs_read`, `fs_write`, `fs_list`, `fs_grep`, `fs_glob`, `fs_delete`, `fs_mkdir`, `fs_mounts`
|
|
141
|
+
- Uses `node:fs/promises` (async), `@vscode/ripgrep` (shipped binary), `fast-glob`
|
|
142
|
+
- Permission flags per mount: `r` (read), `w` (write), `d` (delete)
|
|
143
|
+
- Mount config stored as "fileserver" service type in vault — only configurable through web UI
|
|
144
|
+
|
|
145
|
+
### GWS Tools
|
|
146
|
+
|
|
147
|
+
6 Google Workspace tools: `gws_gmail_list`, `gws_gmail_read`, `gws_gmail_send`, `gws_gmail_draft`, `gws_calendar_list`, `gws_calendar_create`
|
|
148
|
+
- Calls `gws` CLI via `execSync` with `shell: 'bash'` (fixes Windows cmd.exe JSON quoting)
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## claude.ai Integration
|
|
153
|
+
|
|
154
|
+
### Noauth Mode (v1.5.38)
|
|
155
|
+
|
|
156
|
+
claude.ai's OAuth proxy has a confirmed bug ([anthropics/claude-code#46140](https://github.com/anthropics/claude-code/issues/46140), [anthropics/claude-ai-mcp#136](https://github.com/anthropics/claude-ai-mcp/issues/136)): it completes the token exchange but never sends the authenticated request.
|
|
157
|
+
|
|
158
|
+
**Workaround:** Noauth hosts — fresh domains where OAuth endpoints return 404. claude.ai connects directly (tunnel URL is the shared secret).
|
|
159
|
+
|
|
160
|
+
### OAuth 2.1 (v1.5.36-37)
|
|
161
|
+
|
|
162
|
+
Full OAuth 2.1 protocol implementation is present for future use when Anthropic fixes the bug:
|
|
163
|
+
- 401 gate with `WWW-Authenticate` header
|
|
164
|
+
- Dynamic client registration (public client, no secret)
|
|
165
|
+
- Mandatory PKCE S256
|
|
166
|
+
- `Cache-Control: no-store`
|
|
167
|
+
|
|
168
|
+
### Connector URLs
|
|
169
|
+
|
|
170
|
+
| Connector | URL |
|
|
171
|
+
|-----------|-----|
|
|
172
|
+
| clauth | `https://clauth.regendevcorp.com/clauth` |
|
|
173
|
+
| gws | `https://clauth.regendevcorp.com/gws` |
|
|
174
|
+
| fs | `https://fs.regendevcorp.com/fs` |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Dependencies (notable)
|
|
179
|
+
|
|
180
|
+
- `@vscode/ripgrep` — shipped ripgrep binary for `fs_grep`
|
|
181
|
+
- `fast-glob` — pattern matching for `fs_glob`
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Testing
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
node test-tools.mjs # 25 tool execution tests across all 3 namespaces
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Tests actual MCP tool calls (not just OAuth + listing).
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Releasing a New Version (maintainers)
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# 1. Bump version in package.json
|
|
199
|
+
# 2. Commit and tag
|
|
200
|
+
git tag v1.5.38
|
|
201
|
+
git push && git push --tags
|
|
202
|
+
# GitHub Actions publishes automatically via Trusted Publishing
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**NEVER** commit a version bump without tagging — the tag triggers npm CI.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
> Life before Profits. — LIFEAI / PRT
|
|
210
|
+
>
|
|
211
|
+
> ☕ [Support this project](https://github.com/sponsors/DaveLadouceur)
|
package/cli/api.js
CHANGED
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
// cli/api.js
|
|
2
|
-
// Thin client that calls the auth-vault Edge Function
|
|
3
|
-
|
|
4
|
-
import { createRequire } from "module";
|
|
5
|
-
const require = createRequire(import.meta.url);
|
|
6
|
-
|
|
7
|
-
import Conf from "conf";
|
|
8
|
-
import { getConfOptions } from "./conf-path.js";
|
|
9
|
-
|
|
10
|
-
const config = new Conf(getConfOptions());
|
|
11
|
-
|
|
12
|
-
// ============================================================
|
|
13
|
-
// Get Edge Function base URL from local config
|
|
14
|
-
// ============================================================
|
|
15
|
-
export function getBaseUrl() {
|
|
16
|
-
const url = config.get("supabase_url") || process.env.CLAUTH_SUPABASE_URL;
|
|
17
|
-
if (!url) throw new Error("Supabase URL not configured. Run: clauth setup");
|
|
18
|
-
return `${url}/functions/v1/auth-vault`;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function getAnonKey() {
|
|
22
|
-
const key = config.get("supabase_anon_key") || process.env.CLAUTH_SUPABASE_ANON_KEY;
|
|
23
|
-
if (!key) throw new Error("Supabase anon key not configured. Run: clauth setup");
|
|
24
|
-
return key;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// ============================================================
|
|
28
|
-
// Core POST helper
|
|
29
|
-
// ============================================================
|
|
30
|
-
async function post(route, body) {
|
|
31
|
-
const url = `${getBaseUrl()}/${route}`;
|
|
32
|
-
const anonKey = getAnonKey();
|
|
33
|
-
|
|
34
|
-
const res = await fetch(url, {
|
|
35
|
-
method: "POST",
|
|
36
|
-
headers: {
|
|
37
|
-
"Content-Type": "application/json",
|
|
38
|
-
"Authorization": `Bearer ${anonKey}`
|
|
39
|
-
},
|
|
40
|
-
body: JSON.stringify(body)
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const data = await res.json();
|
|
44
|
-
if (!res.ok && !data.error) throw new Error(`HTTP ${res.status}`);
|
|
45
|
-
return data;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// ============================================================
|
|
49
|
-
// Auth-bearing calls (require HMAC token)
|
|
50
|
-
// ============================================================
|
|
51
|
-
async function authPost(route, password, machineHash, token, timestamp, extra = {}) {
|
|
52
|
-
return post(route, {
|
|
53
|
-
machine_hash: machineHash,
|
|
54
|
-
token,
|
|
55
|
-
timestamp,
|
|
56
|
-
password,
|
|
57
|
-
...extra
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// ============================================================
|
|
62
|
-
// Exported API surface
|
|
63
|
-
// ============================================================
|
|
64
|
-
|
|
65
|
-
export async function retrieve(password, machineHash, token, timestamp, service) {
|
|
66
|
-
return authPost("retrieve", password, machineHash, token, timestamp, { service });
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export async function write(password, machineHash, token, timestamp, service, value) {
|
|
70
|
-
return authPost("write", password, machineHash, token, timestamp, { service, value });
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export async function enable(password, machineHash, token, timestamp, service, enabled) {
|
|
74
|
-
return authPost("enable", password, machineHash, token, timestamp, { service, enabled });
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export async function addService(password, machineHash, token, timestamp, name, label, key_type, description, project) {
|
|
78
|
-
const extra = { name, label, key_type, description };
|
|
79
|
-
if (project) extra.project = project;
|
|
80
|
-
return authPost("add", password, machineHash, token, timestamp, extra);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export async function updateService(password, machineHash, token, timestamp, service, updates) {
|
|
84
|
-
return authPost("update", password, machineHash, token, timestamp, { service, ...updates });
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export async function removeService(password, machineHash, token, timestamp, service, confirm) {
|
|
88
|
-
return authPost("remove", password, machineHash, token, timestamp, { service, confirm });
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export async function revoke(password, machineHash, token, timestamp, service, confirm) {
|
|
92
|
-
return authPost("revoke", password, machineHash, token, timestamp, { service, confirm });
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export async function status(password, machineHash, token, timestamp, project) {
|
|
96
|
-
const extra = {};
|
|
97
|
-
if (project) extra.project = project;
|
|
98
|
-
return authPost("status", password, machineHash, token, timestamp, extra);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export async function test(password, machineHash, token, timestamp) {
|
|
102
|
-
return authPost("test", password, machineHash, token, timestamp);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export async function changePassword(password, machineHash, token, timestamp, newSeedHash) {
|
|
106
|
-
return authPost("change-password", password, machineHash, token, timestamp, { new_hmac_seed_hash: newSeedHash });
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export async function registerMachine(machineHash, seedHash, label, adminToken) {
|
|
110
|
-
return post("register-machine", {
|
|
111
|
-
machine_hash: machineHash,
|
|
112
|
-
hmac_seed_hash: seedHash,
|
|
113
|
-
label,
|
|
114
|
-
admin_token: adminToken
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export default {
|
|
119
|
-
retrieve, write, enable, addService, updateService, removeService, revoke,
|
|
120
|
-
status, test, registerMachine, getBaseUrl, getAnonKey
|
|
121
|
-
};
|
|
1
|
+
// cli/api.js
|
|
2
|
+
// Thin client that calls the auth-vault Edge Function
|
|
3
|
+
|
|
4
|
+
import { createRequire } from "module";
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
|
|
7
|
+
import Conf from "conf";
|
|
8
|
+
import { getConfOptions } from "./conf-path.js";
|
|
9
|
+
|
|
10
|
+
const config = new Conf(getConfOptions());
|
|
11
|
+
|
|
12
|
+
// ============================================================
|
|
13
|
+
// Get Edge Function base URL from local config
|
|
14
|
+
// ============================================================
|
|
15
|
+
export function getBaseUrl() {
|
|
16
|
+
const url = config.get("supabase_url") || process.env.CLAUTH_SUPABASE_URL;
|
|
17
|
+
if (!url) throw new Error("Supabase URL not configured. Run: clauth setup");
|
|
18
|
+
return `${url}/functions/v1/auth-vault`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getAnonKey() {
|
|
22
|
+
const key = config.get("supabase_anon_key") || process.env.CLAUTH_SUPABASE_ANON_KEY;
|
|
23
|
+
if (!key) throw new Error("Supabase anon key not configured. Run: clauth setup");
|
|
24
|
+
return key;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ============================================================
|
|
28
|
+
// Core POST helper
|
|
29
|
+
// ============================================================
|
|
30
|
+
async function post(route, body) {
|
|
31
|
+
const url = `${getBaseUrl()}/${route}`;
|
|
32
|
+
const anonKey = getAnonKey();
|
|
33
|
+
|
|
34
|
+
const res = await fetch(url, {
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: {
|
|
37
|
+
"Content-Type": "application/json",
|
|
38
|
+
"Authorization": `Bearer ${anonKey}`
|
|
39
|
+
},
|
|
40
|
+
body: JSON.stringify(body)
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const data = await res.json();
|
|
44
|
+
if (!res.ok && !data.error) throw new Error(`HTTP ${res.status}`);
|
|
45
|
+
return data;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ============================================================
|
|
49
|
+
// Auth-bearing calls (require HMAC token)
|
|
50
|
+
// ============================================================
|
|
51
|
+
async function authPost(route, password, machineHash, token, timestamp, extra = {}) {
|
|
52
|
+
return post(route, {
|
|
53
|
+
machine_hash: machineHash,
|
|
54
|
+
token,
|
|
55
|
+
timestamp,
|
|
56
|
+
password,
|
|
57
|
+
...extra
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ============================================================
|
|
62
|
+
// Exported API surface
|
|
63
|
+
// ============================================================
|
|
64
|
+
|
|
65
|
+
export async function retrieve(password, machineHash, token, timestamp, service) {
|
|
66
|
+
return authPost("retrieve", password, machineHash, token, timestamp, { service });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function write(password, machineHash, token, timestamp, service, value) {
|
|
70
|
+
return authPost("write", password, machineHash, token, timestamp, { service, value });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function enable(password, machineHash, token, timestamp, service, enabled) {
|
|
74
|
+
return authPost("enable", password, machineHash, token, timestamp, { service, enabled });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export async function addService(password, machineHash, token, timestamp, name, label, key_type, description, project) {
|
|
78
|
+
const extra = { name, label, key_type, description };
|
|
79
|
+
if (project) extra.project = project;
|
|
80
|
+
return authPost("add", password, machineHash, token, timestamp, extra);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function updateService(password, machineHash, token, timestamp, service, updates) {
|
|
84
|
+
return authPost("update", password, machineHash, token, timestamp, { service, ...updates });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function removeService(password, machineHash, token, timestamp, service, confirm) {
|
|
88
|
+
return authPost("remove", password, machineHash, token, timestamp, { service, confirm });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function revoke(password, machineHash, token, timestamp, service, confirm) {
|
|
92
|
+
return authPost("revoke", password, machineHash, token, timestamp, { service, confirm });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function status(password, machineHash, token, timestamp, project) {
|
|
96
|
+
const extra = {};
|
|
97
|
+
if (project) extra.project = project;
|
|
98
|
+
return authPost("status", password, machineHash, token, timestamp, extra);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function test(password, machineHash, token, timestamp) {
|
|
102
|
+
return authPost("test", password, machineHash, token, timestamp);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function changePassword(password, machineHash, token, timestamp, newSeedHash) {
|
|
106
|
+
return authPost("change-password", password, machineHash, token, timestamp, { new_hmac_seed_hash: newSeedHash });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export async function registerMachine(machineHash, seedHash, label, adminToken) {
|
|
110
|
+
return post("register-machine", {
|
|
111
|
+
machine_hash: machineHash,
|
|
112
|
+
hmac_seed_hash: seedHash,
|
|
113
|
+
label,
|
|
114
|
+
admin_token: adminToken
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export default {
|
|
119
|
+
retrieve, write, enable, addService, updateService, removeService, revoke,
|
|
120
|
+
status, test, registerMachine, getBaseUrl, getAnonKey
|
|
121
|
+
};
|