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.
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Parse and validate access list options from CLI flags.
3
+ */
4
+ import { getAccessListErrorMessage, normalizeAccessList, parseAccessList, } from "./format.js";
5
+ /**
6
+ * Parse all access list options and validate them.
7
+ * Returns parsed entries or logs error and sets exit code.
8
+ */
9
+ export function parseAccessOptions(options) {
10
+ const addReadResult = parseAccessList(options.addRead);
11
+ const addWriteResult = parseAccessList(options.addWrite);
12
+ const addGrantResult = parseAccessList(options.addGrant);
13
+ const removeReadResult = parseAccessList(options.removeRead);
14
+ const removeWriteResult = parseAccessList(options.removeWrite);
15
+ const removeGrantResult = parseAccessList(options.removeGrant);
16
+ if (addReadResult.error) {
17
+ console.error(`Error in --add-read: ${getAccessListErrorMessage(addReadResult.error)}`);
18
+ process.exitCode = 2;
19
+ return undefined;
20
+ }
21
+ if (addWriteResult.error) {
22
+ console.error(`Error in --add-write: ${getAccessListErrorMessage(addWriteResult.error)}`);
23
+ process.exitCode = 2;
24
+ return undefined;
25
+ }
26
+ if (addGrantResult.error) {
27
+ console.error(`Error in --add-grant: ${getAccessListErrorMessage(addGrantResult.error)}`);
28
+ process.exitCode = 2;
29
+ return undefined;
30
+ }
31
+ if (removeReadResult.error) {
32
+ console.error(`Error in --remove-read: ${getAccessListErrorMessage(removeReadResult.error)}`);
33
+ process.exitCode = 2;
34
+ return undefined;
35
+ }
36
+ if (removeWriteResult.error) {
37
+ console.error(`Error in --remove-write: ${getAccessListErrorMessage(removeWriteResult.error)}`);
38
+ process.exitCode = 2;
39
+ return undefined;
40
+ }
41
+ if (removeGrantResult.error) {
42
+ console.error(`Error in --remove-grant: ${getAccessListErrorMessage(removeGrantResult.error)}`);
43
+ process.exitCode = 2;
44
+ return undefined;
45
+ }
46
+ return {
47
+ addRead: addReadResult.entries,
48
+ addWrite: addWriteResult.entries,
49
+ addGrant: addGrantResult.entries,
50
+ removeRead: removeReadResult.entries,
51
+ removeWrite: removeWriteResult.entries,
52
+ removeGrant: removeGrantResult.entries,
53
+ };
54
+ }
55
+ /**
56
+ * Compute updated access list by adding and removing entries.
57
+ */
58
+ export function computeUpdatedAccess(current, toAdd, toRemove) {
59
+ const set = new Set(current);
60
+ for (const entry of toAdd)
61
+ set.add(entry);
62
+ for (const entry of toRemove)
63
+ set.delete(entry);
64
+ return [...set];
65
+ }
66
+ /**
67
+ * Normalize all access lists and print warnings.
68
+ */
69
+ export function normalizeAllAccess(readAccess, writeAccess, grantAccess) {
70
+ const readNorm = normalizeAccessList(readAccess, "read");
71
+ const writeNorm = normalizeAccessList(writeAccess, "write");
72
+ const grantNorm = normalizeAccessList(grantAccess, "grant");
73
+ if (readNorm.warning)
74
+ console.warn(`Warning: ${readNorm.warning}`);
75
+ if (writeNorm.warning)
76
+ console.warn(`Warning: ${writeNorm.warning}`);
77
+ if (grantNorm.warning)
78
+ console.warn(`Warning: ${grantNorm.warning}`);
79
+ return {
80
+ read: readNorm.normalized,
81
+ write: writeNorm.normalized,
82
+ grant: grantNorm.normalized,
83
+ };
84
+ }
@@ -5,6 +5,7 @@
5
5
  * with axauth's refresh functionality.
6
6
  */
7
7
  import type Database from "better-sqlite3";
8
+ import type { CredentialType } from "../db/repositories/credentials.js";
8
9
  /** Key for credential-specific mutex */
9
10
  type CredentialKey = `${string}/${string}`;
10
11
  /** Result type for the full refresh operation */
@@ -40,12 +41,13 @@ declare function buildKey(agent: string, name: string): CredentialKey;
40
41
  * @param database - Database connection
41
42
  * @param agent - Agent name
42
43
  * @param name - Credential name
44
+ * @param type - Credential type (must be "oauth"; caller must gate on type)
43
45
  * @param data - Current decrypted credential data
44
46
  * @param apiKeyId - API key ID for audit logging
45
47
  * @param originalUpdatedAt - Original updatedAt for optimistic locking
46
48
  * @param options - Refresh options
47
49
  * @returns Refresh result with new data, expiresAt, updatedAt or error
48
50
  */
49
- declare function refreshWithMutex(database: Database.Database, agent: string, name: string, data: Record<string, unknown>, apiKeyId: string, originalUpdatedAt: Date, options: RefreshManagerOptions): Promise<FullRefreshResult>;
51
+ declare function refreshWithMutex(database: Database.Database, agent: string, name: string, type: CredentialType, data: Record<string, unknown>, apiKeyId: string, originalUpdatedAt: Date, options: RefreshManagerOptions): Promise<FullRefreshResult>;
50
52
  export { extractExpiryDate, isRefreshable, needsRefresh, toAxauthCredentials, } from "./check-refresh.js";
51
53
  export { buildKey, refreshWithMutex };
@@ -19,7 +19,7 @@ function buildKey(agent, name) {
19
19
  * Execute the full refresh operation: call axauth, validate, persist.
20
20
  * This is the inner operation that gets stored in the mutex.
21
21
  */
22
- async function executeRefresh(database, agent, name, data, apiKeyId, originalUpdatedAt, refreshStartedAt, options) {
22
+ async function executeRefresh(database, agent, name, type, data, apiKeyId, originalUpdatedAt, refreshStartedAt, options) {
23
23
  const logContext = { database, apiKeyId, agent, name };
24
24
  // Map to axauth format
25
25
  const creds = toAxauthCredentials(agent, data);
@@ -54,6 +54,7 @@ async function executeRefresh(database, agent, name, data, apiKeyId, originalUpd
54
54
  upsertCredential(database, {
55
55
  agent,
56
56
  name,
57
+ type,
57
58
  ...encrypted,
58
59
  expiresAt,
59
60
  });
@@ -98,13 +99,14 @@ async function executeRefresh(database, agent, name, data, apiKeyId, originalUpd
98
99
  * @param database - Database connection
99
100
  * @param agent - Agent name
100
101
  * @param name - Credential name
102
+ * @param type - Credential type (must be "oauth"; caller must gate on type)
101
103
  * @param data - Current decrypted credential data
102
104
  * @param apiKeyId - API key ID for audit logging
103
105
  * @param originalUpdatedAt - Original updatedAt for optimistic locking
104
106
  * @param options - Refresh options
105
107
  * @returns Refresh result with new data, expiresAt, updatedAt or error
106
108
  */
107
- async function refreshWithMutex(database, agent, name, data, apiKeyId, originalUpdatedAt, options) {
109
+ async function refreshWithMutex(database, agent, name, type, data, apiKeyId, originalUpdatedAt, options) {
108
110
  const key = buildKey(agent, name);
109
111
  // Check if refresh already in progress
110
112
  const existing = pendingRefreshes.get(key);
@@ -115,7 +117,7 @@ async function refreshWithMutex(database, agent, name, data, apiKeyId, originalU
115
117
  }
116
118
  // Start new refresh - store promise for the FULL operation
117
119
  const refreshStartedAt = new Date();
118
- const fullOperationPromise = executeRefresh(database, agent, name, data, apiKeyId, originalUpdatedAt, refreshStartedAt, options);
120
+ const fullOperationPromise = executeRefresh(database, agent, name, type, data, apiKeyId, originalUpdatedAt, refreshStartedAt, options);
119
121
  pendingRefreshes.set(key, {
120
122
  promise: fullOperationPromise,
121
123
  startedAt: refreshStartedAt,
package/package.json CHANGED
@@ -2,8 +2,8 @@
2
2
  "name": "axvault",
3
3
  "author": "Łukasz Jerciński",
4
4
  "license": "MIT",
5
- "version": "1.0.0",
6
- "description": "Remote credential storage server for axpoint",
5
+ "version": "1.2.0",
6
+ "description": "Remote credential storage server for axkit",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/Jercik/axvault.git"
@@ -81,7 +81,7 @@
81
81
  "@types/node": "^25.0.3",
82
82
  "@vitest/coverage-v8": "^4.0.16",
83
83
  "eslint": "^9.39.2",
84
- "eslint-config-axpoint": "^1.0.0",
84
+ "eslint-config-axkit": "^1.0.0",
85
85
  "fta-check": "^1.5.1",
86
86
  "fta-cli": "^3.0.0",
87
87
  "knip": "^5.80.0",