axvault 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,17 +32,27 @@ Setting `--refresh-threshold 0` disables automatic credential refresh.
32
32
 
33
33
  ## API Keys
34
34
 
35
- API keys control access to the credential API. Each key has configurable read and write permissions.
35
+ API keys control access to the credential API. Each key has configurable permissions:
36
+
37
+ - **Read**: retrieve credentials
38
+ - **Write**: store and delete credentials
39
+ - **Grant**: delegate access to other keys (enforcement coming in future release)
36
40
 
37
41
  ### Create an API Key
38
42
 
39
43
  ```bash
40
- # Full access
44
+ # Full access (read, write, and grant)
45
+ axvault key create --name "Admin" --read "*" --write "*" --grant "*"
46
+
47
+ # Read/write access only
41
48
  axvault key create --name "CI Pipeline" --read "*" --write "*"
42
49
 
43
50
  # Restricted access
44
- axvault key create --name "Claude Reader" --read "claude/*"
51
+ axvault key create --name "Claude Reader" --read "claude/work,claude/ci"
45
52
  axvault key create --name "Deploy Script" --write "claude/prod,codex/prod"
53
+
54
+ # Grant-only key (for delegation, does not allow direct read/write)
55
+ axvault key create --name "Issuer" --grant "claude/work,claude/ci"
46
56
  ```
47
57
 
48
58
  The command outputs metadata to stderr and the secret key to stdout for easy piping:
@@ -53,6 +63,7 @@ Created API key: CI Pipeline
53
63
  ID: k_a1b2c3d4e5f6
54
64
  Read access: *
55
65
  Write access: *
66
+ Grant access: (none)
56
67
 
57
68
  Save this key securely - it cannot be retrieved later.
58
69
 
@@ -68,6 +79,24 @@ To copy directly to clipboard: `axvault key create --name "My Key" --read "*" |
68
79
  axvault key list
69
80
  ```
70
81
 
82
+ ### Update a Key
83
+
84
+ Modify an existing key's permissions:
85
+
86
+ ```bash
87
+ # Add read access for new credentials
88
+ axvault key update k_a1b2c3d4e5f6 --add-read "gemini/prod"
89
+
90
+ # Remove write access
91
+ axvault key update k_a1b2c3d4e5f6 --remove-write "claude/test"
92
+
93
+ # Add grant permissions
94
+ axvault key update k_a1b2c3d4e5f6 --add-grant "claude/work"
95
+
96
+ # Multiple changes at once
97
+ axvault key update k_a1b2c3d4e5f6 --add-read "codex/ci" --remove-write "claude/dev"
98
+ ```
99
+
71
100
  ### Revoke a Key
72
101
 
73
102
  ```bash
@@ -148,10 +177,10 @@ Exec into the container to manage API keys:
148
177
 
149
178
  ```bash
150
179
  # Podman
151
- sudo podman exec axvault /nodejs/bin/node node_modules/axvault/bin/axvault key create --name "My Key" --write "*"
180
+ sudo podman exec axvault /nodejs/bin/node node_modules/axvault/bin/axvault key create --name "My Key" --read "*" --write "*"
152
181
 
153
182
  # Docker
154
- docker exec axvault /nodejs/bin/node node_modules/axvault/bin/axvault key create --name "My Key" --write "*"
183
+ docker exec axvault /nodejs/bin/node node_modules/axvault/bin/axvault key create --name "My Key" --read "*" --write "*"
155
184
  ```
156
185
 
157
186
  ## Credentials API
@@ -163,11 +192,14 @@ curl -X PUT https://vault.example.com/api/v1/credentials/claude/prod \
163
192
  -H "Authorization: Bearer <api_key>" \
164
193
  -H "Content-Type: application/json" \
165
194
  -d '{
166
- "data": {"accessToken": "...", "refreshToken": "..."},
195
+ "type": "oauth",
196
+ "data": {"access_token": "...", "refresh_token": "..."},
167
197
  "expiresAt": "2025-12-31T23:59:59Z"
168
198
  }'
169
199
  ```
170
200
 
201
+ The `type` field is required and must be either `"oauth"` (for refreshable tokens) or `"api-key"` (for static keys). Only `oauth` credentials are eligible for auto-refresh.
202
+
171
203
  ### Retrieve a Credential
172
204
 
173
205
  ```bash
package/dist/cli.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * axvault - Remote credential storage server for axpoint.
3
+ * axvault - Remote credential storage server for axkit.
4
4
  *
5
5
  * Stores agent credentials and serves them via API.
6
6
  */
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * axvault - Remote credential storage server for axpoint.
3
+ * axvault - Remote credential storage server for axkit.
4
4
  *
5
5
  * Stores agent credentials and serves them via API.
6
6
  */
@@ -8,7 +8,7 @@ import { Command } from "@commander-js/extra-typings";
8
8
  import packageJson from "../package.json" with { type: "json" };
9
9
  import { handleCredentialDelete, handleCredentialList, } from "./commands/credential.js";
10
10
  import { handleInit } from "./commands/init.js";
11
- import { handleKeyCreate, handleKeyList, handleKeyRevoke, } from "./commands/key.js";
11
+ import { handleKeyCreate, handleKeyList, handleKeyRevoke, handleKeyUpdate, } from "./commands/key.js";
12
12
  import { handleServe } from "./commands/serve.js";
13
13
  const program = new Command()
14
14
  .name(packageJson.name)
@@ -35,11 +35,14 @@ Examples:
35
35
  axvault key create --name "Uploader" --write "claude/backups"
36
36
 
37
37
  # Create an admin API key with full access
38
- axvault key create --name "Admin" --read "*" --write "*"
38
+ axvault key create --name "Admin" --read "*" --write "*" --grant "*"
39
39
 
40
40
  # List all API keys
41
41
  axvault key list
42
42
 
43
+ # Update an API key's permissions
44
+ axvault key update k_abc123def456 --add-read "claude/new"
45
+
43
46
  # Revoke an API key
44
47
  axvault key revoke k_abc123def456
45
48
 
@@ -73,6 +76,7 @@ keyCommand
73
76
  .requiredOption("-n, --name <name>", "Name for the API key")
74
77
  .option("-r, --read <access>", "Comma-separated read access list (e.g., 'claude/work,codex/ci' or '*')")
75
78
  .option("-w, --write <access>", "Comma-separated write access list (e.g., 'claude/ci' or '*')")
79
+ .option("-g, --grant <access>", "Comma-separated grant access list (can delegate these to other keys)")
76
80
  .option("--json", "Output as JSON")
77
81
  .option("--db-path <path>", "Database file path")
78
82
  .action(handleKeyCreate);
@@ -88,6 +92,19 @@ keyCommand
88
92
  .argument("<id>", "API key ID (e.g., k_abc123def456)")
89
93
  .option("--db-path <path>", "Database file path")
90
94
  .action(handleKeyRevoke);
95
+ keyCommand
96
+ .command("update")
97
+ .description("Update an API key's permissions")
98
+ .argument("<id>", "API key ID (e.g., k_abc123def456)")
99
+ .option("--add-read <access>", "Add read access entries")
100
+ .option("--add-write <access>", "Add write access entries")
101
+ .option("--add-grant <access>", "Add grant access entries")
102
+ .option("--remove-read <access>", "Remove read access entries")
103
+ .option("--remove-write <access>", "Remove write access entries")
104
+ .option("--remove-grant <access>", "Remove grant access entries")
105
+ .option("--json", "Output as JSON")
106
+ .option("--db-path <path>", "Database file path")
107
+ .action(handleKeyUpdate);
91
108
  // Credential management commands
92
109
  const credentialCommand = program
93
110
  .command("credential")
@@ -8,13 +8,14 @@ import { deleteCredential, listCredentials, } from "../db/repositories/credentia
8
8
  import { containsControlChars, formatDateForJson, formatExpiresAt, formatRelativeTime, getErrorMessage, sanitizeForTsv, } from "../lib/format.js";
9
9
  /** Print credentials as TSV table */
10
10
  function printCredentialTable(credentials) {
11
- console.log("AGENT\tNAME\tEXPIRES\tUPDATED");
11
+ console.log("AGENT\tNAME\tTYPE\tEXPIRES\tUPDATED");
12
12
  for (const cred of credentials) {
13
13
  const agent = sanitizeForTsv(cred.agent);
14
14
  const name = sanitizeForTsv(cred.name);
15
+ const type = sanitizeForTsv(cred.type);
15
16
  const expires = formatExpiresAt(cred.expiresAt);
16
17
  const updated = formatRelativeTime(cred.updatedAt);
17
- console.log(`${agent}\t${name}\t${expires}\t${updated}`);
18
+ console.log(`${agent}\t${name}\t${type}\t${expires}\t${updated}`);
18
19
  }
19
20
  }
20
21
  /**
@@ -59,6 +60,7 @@ export function handleCredentialList(options) {
59
60
  const output = credentials.map((cred) => ({
60
61
  agent: cred.agent,
61
62
  name: cred.name,
63
+ type: cred.type,
62
64
  createdAt: cred.createdAt.toISOString(),
63
65
  updatedAt: cred.updatedAt.toISOString(),
64
66
  expiresAt: formatDateForJson(cred.expiresAt),
@@ -0,0 +1,13 @@
1
+ /**
2
+ * API key create command handler.
3
+ */
4
+ interface KeyCreateOptions {
5
+ dbPath?: string;
6
+ name: string;
7
+ read?: string;
8
+ write?: string;
9
+ grant?: string;
10
+ json?: boolean;
11
+ }
12
+ export declare function handleKeyCreate(options: KeyCreateOptions): void;
13
+ export {};
@@ -0,0 +1,99 @@
1
+ /**
2
+ * API key create command handler.
3
+ */
4
+ import { getServerConfig } from "../config.js";
5
+ import { closeDatabase, getDatabase } from "../db/client.js";
6
+ import { runMigrations } from "../db/migrations.js";
7
+ import { createApiKey } from "../db/repositories/api-keys.js";
8
+ import { containsControlChars, formatAccessList, getAccessListErrorMessage, getErrorMessage, normalizeAccessList, parseAccessList, sanitizeForTsv, } from "../lib/format.js";
9
+ export function handleKeyCreate(options) {
10
+ // Validate key name (reject control characters)
11
+ if (containsControlChars(options.name)) {
12
+ console.error("Error: Key name contains control characters.");
13
+ process.exitCode = 2;
14
+ return;
15
+ }
16
+ // Parse and validate access lists
17
+ const readResult = parseAccessList(options.read);
18
+ const writeResult = parseAccessList(options.write);
19
+ const grantResult = parseAccessList(options.grant);
20
+ if (readResult.error) {
21
+ console.error(`Error: ${getAccessListErrorMessage(readResult.error)}`);
22
+ process.exitCode = 2;
23
+ return;
24
+ }
25
+ if (writeResult.error) {
26
+ console.error(`Error: ${getAccessListErrorMessage(writeResult.error)}`);
27
+ process.exitCode = 2;
28
+ return;
29
+ }
30
+ if (grantResult.error) {
31
+ console.error(`Error: ${getAccessListErrorMessage(grantResult.error)}`);
32
+ process.exitCode = 2;
33
+ return;
34
+ }
35
+ // Normalize wildcards (warn if mixed with specific entries)
36
+ const readNorm = normalizeAccessList(readResult.entries, "read");
37
+ const writeNorm = normalizeAccessList(writeResult.entries, "write");
38
+ const grantNorm = normalizeAccessList(grantResult.entries, "grant");
39
+ if (readNorm.warning)
40
+ console.warn(`Warning: ${readNorm.warning}`);
41
+ if (writeNorm.warning)
42
+ console.warn(`Warning: ${writeNorm.warning}`);
43
+ if (grantNorm.warning)
44
+ console.warn(`Warning: ${grantNorm.warning}`);
45
+ const readAccess = readNorm.normalized;
46
+ const writeAccess = writeNorm.normalized;
47
+ const grantAccess = grantNorm.normalized;
48
+ // Validate: at least one access must be specified
49
+ if (readAccess.length === 0 &&
50
+ writeAccess.length === 0 &&
51
+ grantAccess.length === 0) {
52
+ console.error("Error: At least one of --read, --write, or --grant must be specified.");
53
+ console.error("Try 'axvault key create --help' for more information.");
54
+ process.exitCode = 2;
55
+ return;
56
+ }
57
+ try {
58
+ const config = getServerConfig(options);
59
+ const database = getDatabase(config.databasePath);
60
+ runMigrations(database);
61
+ const apiKey = createApiKey(database, {
62
+ name: options.name,
63
+ readAccess,
64
+ writeAccess,
65
+ grantAccess,
66
+ });
67
+ if (options.json) {
68
+ console.warn("Warning: JSON output contains the secret key. Avoid logging in CI.");
69
+ console.log(JSON.stringify({
70
+ id: apiKey.id,
71
+ name: apiKey.name,
72
+ key: apiKey.key,
73
+ readAccess: apiKey.readAccess,
74
+ writeAccess: apiKey.writeAccess,
75
+ grantAccess: apiKey.grantAccess,
76
+ createdAt: apiKey.createdAt.toISOString(),
77
+ }, undefined, 2));
78
+ }
79
+ else {
80
+ console.error(`Created API key: ${sanitizeForTsv(apiKey.name)}`);
81
+ console.error(`ID: ${sanitizeForTsv(apiKey.id)}`);
82
+ console.error(`Read access: ${sanitizeForTsv(formatAccessList(apiKey.readAccess))}`);
83
+ console.error(`Write access: ${sanitizeForTsv(formatAccessList(apiKey.writeAccess))}`);
84
+ console.error(`Grant access: ${sanitizeForTsv(formatAccessList(apiKey.grantAccess))}`);
85
+ console.error("");
86
+ // Output the secret key to stdout for piping
87
+ console.log(apiKey.key);
88
+ console.error("");
89
+ console.error("Save this key securely - it cannot be retrieved later.");
90
+ }
91
+ }
92
+ catch (error) {
93
+ console.error(`Error: Failed to create API key: ${getErrorMessage(error)}`);
94
+ process.exitCode = 1;
95
+ }
96
+ finally {
97
+ closeDatabase();
98
+ }
99
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * API key list command handler.
3
+ */
4
+ interface KeyListOptions {
5
+ dbPath?: string;
6
+ json?: boolean;
7
+ }
8
+ export declare function handleKeyList(options: KeyListOptions): void;
9
+ export {};
@@ -0,0 +1,43 @@
1
+ /**
2
+ * API key list command handler.
3
+ */
4
+ import { getServerConfig } from "../config.js";
5
+ import { closeDatabase, getDatabase } from "../db/client.js";
6
+ import { runMigrations } from "../db/migrations.js";
7
+ import { listApiKeys } from "../db/repositories/api-keys.js";
8
+ import { formatDateForJson, formatKeyRow, getErrorMessage, } from "../lib/format.js";
9
+ export function handleKeyList(options) {
10
+ try {
11
+ const config = getServerConfig(options);
12
+ const database = getDatabase(config.databasePath);
13
+ runMigrations(database);
14
+ const keys = listApiKeys(database);
15
+ if (options.json) {
16
+ const output = keys.map((key) => ({
17
+ id: key.id,
18
+ name: key.name,
19
+ readAccess: key.readAccess,
20
+ writeAccess: key.writeAccess,
21
+ grantAccess: key.grantAccess,
22
+ createdAt: key.createdAt.toISOString(),
23
+ lastUsedAt: formatDateForJson(key.lastUsedAt),
24
+ }));
25
+ console.log(JSON.stringify(output, undefined, 2));
26
+ }
27
+ else if (keys.length === 0) {
28
+ console.error("No API keys found.\nCreate one with: axvault key create --name <name> [--read <access>] [--write <access>] [--grant <access>]");
29
+ }
30
+ else {
31
+ console.log("ID\tNAME\tREAD ACCESS\tWRITE ACCESS\tGRANT ACCESS\tLAST USED");
32
+ for (const key of keys)
33
+ console.log(formatKeyRow(key));
34
+ }
35
+ }
36
+ catch (error) {
37
+ console.error(`Error: Failed to list API keys: ${getErrorMessage(error)}`);
38
+ process.exitCode = 1;
39
+ }
40
+ finally {
41
+ closeDatabase();
42
+ }
43
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * API key revoke command handler.
3
+ */
4
+ interface KeyRevokeOptions {
5
+ dbPath?: string;
6
+ }
7
+ export declare function handleKeyRevoke(id: string, options: KeyRevokeOptions): void;
8
+ export {};
@@ -0,0 +1,47 @@
1
+ /**
2
+ * API key revoke command handler.
3
+ */
4
+ import { getServerConfig } from "../config.js";
5
+ import { closeDatabase, getDatabase } from "../db/client.js";
6
+ import { runMigrations } from "../db/migrations.js";
7
+ import { deleteApiKey } from "../db/repositories/api-keys.js";
8
+ import { containsControlChars, getErrorMessage, isValidKeyId, sanitizeForTsv, } from "../lib/format.js";
9
+ export function handleKeyRevoke(id, options) {
10
+ // Reject inputs containing control characters BEFORE trimming
11
+ // (prevents silent bypass where \n or \t would be removed by trim)
12
+ if (containsControlChars(id)) {
13
+ console.error("Error: Invalid API key ID: contains control characters.");
14
+ console.error("API key IDs have format: k_<12 hex chars> (e.g., k_abc123def456)");
15
+ process.exitCode = 2;
16
+ return;
17
+ }
18
+ // Trim whitespace from ID (common copy-paste issue)
19
+ const trimmedId = id.trim();
20
+ // Validate ID format (k_ + 12 hex chars)
21
+ if (!isValidKeyId(trimmedId)) {
22
+ console.error(`Error: Invalid API key ID format: ${trimmedId}`);
23
+ console.error("API key IDs have format: k_<12 hex chars> (e.g., k_abc123def456)");
24
+ process.exitCode = 2;
25
+ return;
26
+ }
27
+ try {
28
+ const config = getServerConfig(options);
29
+ const database = getDatabase(config.databasePath);
30
+ runMigrations(database);
31
+ const deleted = deleteApiKey(database, trimmedId);
32
+ if (deleted) {
33
+ console.error(`Revoked API key: ${sanitizeForTsv(trimmedId)}`);
34
+ }
35
+ else {
36
+ console.error(`Error: API key not found: ${sanitizeForTsv(trimmedId)}`);
37
+ process.exitCode = 1;
38
+ }
39
+ }
40
+ catch (error) {
41
+ console.error(`Error: Failed to revoke API key: ${getErrorMessage(error)}`);
42
+ process.exitCode = 1;
43
+ }
44
+ finally {
45
+ closeDatabase();
46
+ }
47
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * API key update command handler.
3
+ */
4
+ interface KeyUpdateOptions {
5
+ dbPath?: string;
6
+ addRead?: string;
7
+ addWrite?: string;
8
+ addGrant?: string;
9
+ removeRead?: string;
10
+ removeWrite?: string;
11
+ removeGrant?: string;
12
+ json?: boolean;
13
+ }
14
+ export declare function handleKeyUpdate(id: string, options: KeyUpdateOptions): void;
15
+ export {};
@@ -0,0 +1,109 @@
1
+ /**
2
+ * API key update command handler.
3
+ */
4
+ import { getServerConfig } from "../config.js";
5
+ import { closeDatabase, getDatabase } from "../db/client.js";
6
+ import { runMigrations } from "../db/migrations.js";
7
+ import { findApiKeyById, updateApiKeyAccess, } from "../db/repositories/api-keys.js";
8
+ import { containsControlChars, formatAccessList, formatDateForJson, getErrorMessage, isValidKeyId, sanitizeForTsv, } from "../lib/format.js";
9
+ import { computeUpdatedAccess, normalizeAllAccess, parseAccessOptions, } from "../lib/parse-access-options.js";
10
+ export function handleKeyUpdate(id, options) {
11
+ // Validate key ID
12
+ if (containsControlChars(id)) {
13
+ console.error("Error: Invalid API key ID: contains control characters.");
14
+ console.error("API key IDs have format: k_<12 hex chars> (e.g., k_abc123def456)");
15
+ process.exitCode = 2;
16
+ return;
17
+ }
18
+ const trimmedId = id.trim();
19
+ if (!isValidKeyId(trimmedId)) {
20
+ console.error(`Error: Invalid API key ID format: ${trimmedId}`);
21
+ console.error("API key IDs have format: k_<12 hex chars> (e.g., k_abc123def456)");
22
+ process.exitCode = 2;
23
+ return;
24
+ }
25
+ // Parse and validate access options
26
+ const parsed = parseAccessOptions(options);
27
+ if (!parsed)
28
+ return; // Error already logged
29
+ // Check if any updates were requested
30
+ const hasUpdates = parsed.addRead.length > 0 ||
31
+ parsed.addWrite.length > 0 ||
32
+ parsed.addGrant.length > 0 ||
33
+ parsed.removeRead.length > 0 ||
34
+ parsed.removeWrite.length > 0 ||
35
+ parsed.removeGrant.length > 0;
36
+ if (!hasUpdates) {
37
+ console.error("Error: No updates specified.");
38
+ console.error("Try 'axvault key update --help' for more information.");
39
+ process.exitCode = 2;
40
+ return;
41
+ }
42
+ try {
43
+ const config = getServerConfig(options);
44
+ const database = getDatabase(config.databasePath);
45
+ runMigrations(database);
46
+ // Find existing key
47
+ const existingKey = findApiKeyById(database, trimmedId);
48
+ if (!existingKey) {
49
+ console.error(`Error: API key not found: ${sanitizeForTsv(trimmedId)}`);
50
+ process.exitCode = 1;
51
+ return;
52
+ }
53
+ // Compute new access lists
54
+ const newReadAccess = computeUpdatedAccess(existingKey.readAccess, parsed.addRead, parsed.removeRead);
55
+ const newWriteAccess = computeUpdatedAccess(existingKey.writeAccess, parsed.addWrite, parsed.removeWrite);
56
+ const newGrantAccess = computeUpdatedAccess(existingKey.grantAccess, parsed.addGrant, parsed.removeGrant);
57
+ // Normalize and update
58
+ const normalized = normalizeAllAccess(newReadAccess, newWriteAccess, newGrantAccess);
59
+ // Validate: at least one access must remain after update
60
+ if (normalized.read.length === 0 &&
61
+ normalized.write.length === 0 &&
62
+ normalized.grant.length === 0) {
63
+ console.error("Error: Update would leave the key with no permissions. At least one of read, write, or grant access must remain.");
64
+ process.exitCode = 2;
65
+ return;
66
+ }
67
+ updateApiKeyAccess(database, trimmedId, {
68
+ readAccess: normalized.read,
69
+ writeAccess: normalized.write,
70
+ grantAccess: normalized.grant,
71
+ });
72
+ // Fetch updated key for output
73
+ const updatedKey = findApiKeyById(database, trimmedId);
74
+ if (!updatedKey) {
75
+ console.error("Error: Failed to fetch updated key.");
76
+ process.exitCode = 1;
77
+ return;
78
+ }
79
+ outputKeyDetails(updatedKey, options.json ?? false);
80
+ }
81
+ catch (error) {
82
+ console.error(`Error: Failed to update API key: ${getErrorMessage(error)}`);
83
+ process.exitCode = 1;
84
+ }
85
+ finally {
86
+ closeDatabase();
87
+ }
88
+ }
89
+ /** Output key details in JSON or human-readable format */
90
+ function outputKeyDetails(key, json) {
91
+ if (json) {
92
+ console.log(JSON.stringify({
93
+ id: key.id,
94
+ name: key.name,
95
+ readAccess: key.readAccess,
96
+ writeAccess: key.writeAccess,
97
+ grantAccess: key.grantAccess,
98
+ createdAt: key.createdAt.toISOString(),
99
+ lastUsedAt: formatDateForJson(key.lastUsedAt),
100
+ }, undefined, 2));
101
+ }
102
+ else {
103
+ console.error(`Updated API key: ${sanitizeForTsv(key.name)}`);
104
+ console.error(`ID: ${sanitizeForTsv(key.id)}`);
105
+ console.error(`Read access: ${sanitizeForTsv(formatAccessList(key.readAccess))}`);
106
+ console.error(`Write access: ${sanitizeForTsv(formatAccessList(key.writeAccess))}`);
107
+ console.error(`Grant access: ${sanitizeForTsv(formatAccessList(key.grantAccess))}`);
108
+ }
109
+ }
@@ -1,21 +1,9 @@
1
1
  /**
2
2
  * API key management command handlers.
3
+ *
4
+ * Re-exports handlers from separate modules for better maintainability.
3
5
  */
4
- interface KeyCreateOptions {
5
- dbPath?: string;
6
- name: string;
7
- read?: string;
8
- write?: string;
9
- json?: boolean;
10
- }
11
- interface KeyListOptions {
12
- dbPath?: string;
13
- json?: boolean;
14
- }
15
- interface KeyRevokeOptions {
16
- dbPath?: string;
17
- }
18
- export declare function handleKeyCreate(options: KeyCreateOptions): void;
19
- export declare function handleKeyList(options: KeyListOptions): void;
20
- export declare function handleKeyRevoke(id: string, options: KeyRevokeOptions): void;
21
- export {};
6
+ export { handleKeyCreate } from "./key-create.js";
7
+ export { handleKeyList } from "./key-list.js";
8
+ export { handleKeyRevoke } from "./key-revoke.js";
9
+ export { handleKeyUpdate } from "./key-update.js";