@lifeaitools/clauth 1.5.59 → 1.5.62

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
@@ -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
+ };