axvault 1.9.2 → 1.9.3
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.
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* Encapsulates refresh decision logic + per-credential mutex so the handler
|
|
5
5
|
* stays small enough for static complexity checks (FTA).
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
8
|
-
import { isValidAgentCli, isRefreshableCredentialType, parseCredentials, } from "axshared";
|
|
7
|
+
import { refreshBlob } from "axauth";
|
|
9
8
|
import { getCredential, updateCredentialIfUnchanged, } from "../db/repositories/credentials.js";
|
|
10
9
|
import { logAccess } from "../db/repositories/audit-log.js";
|
|
11
10
|
import { decryptCredential, encryptCredential } from "../lib/encryption.js";
|
|
11
|
+
import { shouldRefreshCredential } from "./should-refresh-credential.js";
|
|
12
12
|
/** Per-credential mutex to prevent concurrent refreshes */
|
|
13
13
|
const pendingRefreshes = new Map();
|
|
14
14
|
function getRefreshPromise(name, blob, agent, provider, refreshTimeoutMs) {
|
|
@@ -29,31 +29,8 @@ function getRefreshPromise(name, blob, agent, provider, refreshTimeoutMs) {
|
|
|
29
29
|
return promise;
|
|
30
30
|
}
|
|
31
31
|
async function refreshCredentialOnRead(options) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
status: "ok",
|
|
35
|
-
blob: options.blob,
|
|
36
|
-
updatedAt: options.expectedUpdatedAt,
|
|
37
|
-
wasRefreshed: false,
|
|
38
|
-
refreshFailed: false,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
// Refresh requires a valid agent ID (empty means pre-v2 credential)
|
|
42
|
-
if (!isValidAgentCli(options.agent)) {
|
|
43
|
-
return {
|
|
44
|
-
status: "ok",
|
|
45
|
-
blob: options.blob,
|
|
46
|
-
updatedAt: options.expectedUpdatedAt,
|
|
47
|
-
wasRefreshed: false,
|
|
48
|
-
refreshFailed: false,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
const agent = options.agent;
|
|
52
|
-
const parsedCredentials = parseCredentials(options.blob);
|
|
53
|
-
if (parsedCredentials === undefined ||
|
|
54
|
-
!isRefreshableCredentialType(parsedCredentials.type) ||
|
|
55
|
-
!isRefreshable(parsedCredentials.data) ||
|
|
56
|
-
isCredentialExpired(parsedCredentials.data, options.refreshThresholdSeconds) !== true) {
|
|
32
|
+
const decision = shouldRefreshCredential(options.blob, options.agent, options.refreshThresholdSeconds);
|
|
33
|
+
if (!decision.refresh) {
|
|
57
34
|
return {
|
|
58
35
|
status: "ok",
|
|
59
36
|
blob: options.blob,
|
|
@@ -63,7 +40,7 @@ async function refreshCredentialOnRead(options) {
|
|
|
63
40
|
};
|
|
64
41
|
}
|
|
65
42
|
try {
|
|
66
|
-
const refreshResult = await getRefreshPromise(options.name, options.blob, agent, options.provider, options.refreshTimeoutMs);
|
|
43
|
+
const refreshResult = await getRefreshPromise(options.name, options.blob, decision.agent, options.provider, options.refreshTimeoutMs);
|
|
67
44
|
if (refreshResult.ok) {
|
|
68
45
|
const encrypted = encryptCredential(refreshResult.blob);
|
|
69
46
|
const updateResult = updateCredentialIfUnchanged(options.database, {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decision logic for whether a credential should be refreshed on read.
|
|
3
|
+
*
|
|
4
|
+
* Extracted to keep refresh-credential-on-read.ts under the FTA threshold.
|
|
5
|
+
*/
|
|
6
|
+
import { type AgentCli } from "axshared";
|
|
7
|
+
/** Check whether a credential should be refreshed */
|
|
8
|
+
declare function shouldRefreshCredential(blob: unknown, agent: string, refreshThresholdSeconds: number): {
|
|
9
|
+
refresh: true;
|
|
10
|
+
agent: AgentCli;
|
|
11
|
+
} | {
|
|
12
|
+
refresh: false;
|
|
13
|
+
};
|
|
14
|
+
export { shouldRefreshCredential };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decision logic for whether a credential should be refreshed on read.
|
|
3
|
+
*
|
|
4
|
+
* Extracted to keep refresh-credential-on-read.ts under the FTA threshold.
|
|
5
|
+
*/
|
|
6
|
+
import { isCredentialExpired, isRefreshable } from "axauth";
|
|
7
|
+
import { isValidAgentCli, isRefreshableCredentialType, parseCredentials, } from "axshared";
|
|
8
|
+
/** Check whether a credential should be refreshed */
|
|
9
|
+
function shouldRefreshCredential(blob, agent, refreshThresholdSeconds) {
|
|
10
|
+
if (refreshThresholdSeconds <= 0)
|
|
11
|
+
return { refresh: false };
|
|
12
|
+
if (!isValidAgentCli(agent))
|
|
13
|
+
return { refresh: false };
|
|
14
|
+
const parsed = parseCredentials(blob);
|
|
15
|
+
if (parsed === undefined ||
|
|
16
|
+
!isRefreshableCredentialType(parsed.type) ||
|
|
17
|
+
!isRefreshable(parsed.data) ||
|
|
18
|
+
isCredentialExpired(parsed.data, refreshThresholdSeconds) !== true) {
|
|
19
|
+
return { refresh: false };
|
|
20
|
+
}
|
|
21
|
+
return { refresh: true, agent };
|
|
22
|
+
}
|
|
23
|
+
export { shouldRefreshCredential };
|