veryfront 0.1.1213 → 0.1.1214
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/esm/deno.js +1 -1
- package/esm/src/agent/runtime/index.d.ts.map +1 -1
- package/esm/src/agent/runtime/index.js +2 -6
- package/esm/src/agent/runtime/skill-policy-enforcement.d.ts +1 -1
- package/esm/src/agent/runtime/skill-policy-enforcement.d.ts.map +1 -1
- package/esm/src/agent/runtime/skill-policy-enforcement.js +1 -8
- package/esm/src/html/hydration-script-builder/hydration-runtime.generated.js +1 -1
- package/esm/src/platform/adapters/index.d.ts +25 -0
- package/esm/src/platform/adapters/index.d.ts.map +1 -0
- package/esm/src/platform/adapters/index.js +23 -0
- package/esm/src/platform/adapters/security/index.d.ts +8 -0
- package/esm/src/platform/adapters/security/index.d.ts.map +1 -0
- package/esm/src/platform/adapters/security/index.js +7 -0
- package/esm/src/platform/adapters/token/factory.d.ts +10 -0
- package/esm/src/platform/adapters/token/factory.d.ts.map +1 -0
- package/esm/src/platform/adapters/token/factory.js +79 -0
- package/esm/src/platform/adapters/token/index.d.ts +9 -0
- package/esm/src/platform/adapters/token/index.d.ts.map +1 -0
- package/esm/src/platform/adapters/token/index.js +8 -0
- package/esm/src/platform/adapters/token/integration.d.ts +6 -0
- package/esm/src/platform/adapters/token/integration.d.ts.map +1 -0
- package/esm/src/platform/adapters/token/integration.js +61 -0
- package/esm/src/platform/adapters/token/veryfront/adapter.d.ts +22 -0
- package/esm/src/platform/adapters/token/veryfront/adapter.d.ts.map +1 -0
- package/esm/src/platform/adapters/token/veryfront/adapter.js +88 -0
- package/esm/src/platform/adapters/token/veryfront/api-client.d.ts +15 -0
- package/esm/src/platform/adapters/token/veryfront/api-client.d.ts.map +1 -0
- package/esm/src/platform/adapters/token/veryfront/api-client.js +212 -0
- package/esm/src/platform/adapters/token/veryfront/index.d.ts +10 -0
- package/esm/src/platform/adapters/token/veryfront/index.d.ts.map +1 -0
- package/esm/src/platform/adapters/token/veryfront/index.js +9 -0
- package/esm/src/platform/adapters/token/veryfront/memory-adapter.d.ts +20 -0
- package/esm/src/platform/adapters/token/veryfront/memory-adapter.d.ts.map +1 -0
- package/esm/src/platform/adapters/token/veryfront/memory-adapter.js +52 -0
- package/esm/src/platform/adapters/token/veryfront/types.d.ts +86 -0
- package/esm/src/platform/adapters/token/veryfront/types.d.ts.map +1 -0
- package/esm/src/platform/adapters/token/veryfront/types.js +81 -0
- package/esm/src/platform/compat/http/pinned-fetch.d.ts +1 -1
- package/esm/src/security/http/config.d.ts +5 -0
- package/esm/src/security/http/config.d.ts.map +1 -1
- package/esm/src/security/http/config.js +16 -1
- package/esm/src/security/http/derived-csp-cache.d.ts +33 -0
- package/esm/src/security/http/derived-csp-cache.d.ts.map +1 -0
- package/esm/src/security/http/derived-csp-cache.js +101 -0
- package/esm/src/security/http/derived-csp-origins.d.ts +54 -0
- package/esm/src/security/http/derived-csp-origins.d.ts.map +1 -0
- package/esm/src/security/http/derived-csp-origins.js +156 -0
- package/esm/src/security/http/response/security-handler.d.ts.map +1 -1
- package/esm/src/security/http/response/security-handler.js +9 -2
- package/esm/src/security/sandbox/constants.d.ts +3 -0
- package/esm/src/security/sandbox/constants.d.ts.map +1 -0
- package/esm/src/security/sandbox/constants.js +2 -0
- package/esm/src/security/sandbox/deno-sandbox.d.ts +71 -0
- package/esm/src/security/sandbox/deno-sandbox.d.ts.map +1 -0
- package/esm/src/security/sandbox/deno-sandbox.js +184 -0
- package/esm/src/security/sandbox/permission-system.d.ts +11 -0
- package/esm/src/security/sandbox/permission-system.d.ts.map +1 -0
- package/esm/src/security/sandbox/permission-system.js +85 -0
- package/esm/src/server/runtime-handler/project-runtime-context.d.ts.map +1 -1
- package/esm/src/server/runtime-handler/project-runtime-context.js +97 -1
- package/esm/src/types/server.d.ts +10 -0
- package/esm/src/types/server.d.ts.map +1 -1
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/esm/src/workflow/api.d.ts +2 -2
- package/package.json +8 -8
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Storage Adapter Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates the appropriate token storage adapter based on configuration.
|
|
5
|
+
* For auto-detection from environment variables, use getTokenStorageAdapter()
|
|
6
|
+
* from token/integration.ts instead.
|
|
7
|
+
*/
|
|
8
|
+
import { logger as baseLogger } from "../../../utils/index.js";
|
|
9
|
+
import { withSpan } from "../../../observability/tracing/otlp-setup.js";
|
|
10
|
+
import { createError, toError } from "../../../errors/veryfront-error.js";
|
|
11
|
+
const logger = baseLogger.component("token-adapter-factory");
|
|
12
|
+
export function createTokenStorageAdapter(config) {
|
|
13
|
+
const type = config.type ?? "memory";
|
|
14
|
+
const veryfront = config.veryfront;
|
|
15
|
+
const veryfrontSnapshot = type === "veryfront-api" && veryfront !== undefined
|
|
16
|
+
? snapshotVeryfrontOptions(veryfront)
|
|
17
|
+
: undefined;
|
|
18
|
+
return withSpan("platform.token.createAdapter", async () => {
|
|
19
|
+
logger.debug("Creating adapter", { type });
|
|
20
|
+
if (type === "memory") {
|
|
21
|
+
if (veryfront !== undefined) {
|
|
22
|
+
throw toError(createError({
|
|
23
|
+
type: "config",
|
|
24
|
+
message: 'Veryfront token configuration requires adapter type "veryfront-api"; refusing to fall back to memory storage.',
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
const { MemoryTokenAdapter } = await import("./veryfront/memory-adapter.js");
|
|
28
|
+
return await initializeAdapter(new MemoryTokenAdapter());
|
|
29
|
+
}
|
|
30
|
+
if (type === "veryfront-api") {
|
|
31
|
+
if (veryfrontSnapshot === undefined) {
|
|
32
|
+
throw toError(createError({
|
|
33
|
+
type: "config",
|
|
34
|
+
message: "Veryfront token adapter requires veryfront configuration",
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
const { VeryfrontTokenAdapter } = await import("./veryfront/adapter.js");
|
|
38
|
+
return await initializeAdapter(new VeryfrontTokenAdapter({
|
|
39
|
+
type: "veryfront-api",
|
|
40
|
+
veryfront: veryfrontSnapshot,
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
throw toError(createError({
|
|
44
|
+
type: "config",
|
|
45
|
+
message: `Token storage adapter type "${type}" is not implemented. Supported types: "memory", "veryfront-api".`,
|
|
46
|
+
}));
|
|
47
|
+
}, { "token.adapter.type": type });
|
|
48
|
+
}
|
|
49
|
+
function snapshotVeryfrontOptions(options) {
|
|
50
|
+
const retry = options.retry;
|
|
51
|
+
return Object.freeze({
|
|
52
|
+
apiToken: options.apiToken,
|
|
53
|
+
projectSlug: options.projectSlug,
|
|
54
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
55
|
+
timeoutMs: options.timeoutMs,
|
|
56
|
+
retry: retry === undefined ? undefined : Object.freeze({
|
|
57
|
+
maxRetries: retry.maxRetries,
|
|
58
|
+
initialDelay: retry.initialDelay,
|
|
59
|
+
maxDelay: retry.maxDelay,
|
|
60
|
+
}),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
async function initializeAdapter(adapter) {
|
|
64
|
+
try {
|
|
65
|
+
await adapter.initialize?.();
|
|
66
|
+
return adapter;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
try {
|
|
70
|
+
adapter.dispose?.();
|
|
71
|
+
}
|
|
72
|
+
catch (cleanupError) {
|
|
73
|
+
logger.warn("Failed to dispose token adapter after initialization failure", {
|
|
74
|
+
cleanupError,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapters - Token
|
|
3
|
+
*
|
|
4
|
+
* @module platform/adapters/token
|
|
5
|
+
*/
|
|
6
|
+
export { MemoryTokenAdapter, TOKEN_STORAGE_ERROR, type TokenStorageAdapter, type TokenStorageAdapterConfig, TokenStorageApiClient, VeryfrontTokenAdapter, type VeryfrontTokenConfig, } from "./veryfront/index.js";
|
|
7
|
+
export { createTokenStorageAdapter } from "./factory.js";
|
|
8
|
+
export { getTokenStorageAdapter, getTokenStorageType, isTokenStorageConfigured, resetTokenStorageAdapter, } from "./integration.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/adapters/token/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapters - Token
|
|
3
|
+
*
|
|
4
|
+
* @module platform/adapters/token
|
|
5
|
+
*/
|
|
6
|
+
export { MemoryTokenAdapter, TOKEN_STORAGE_ERROR, TokenStorageApiClient, VeryfrontTokenAdapter, } from "./veryfront/index.js";
|
|
7
|
+
export { createTokenStorageAdapter } from "./factory.js";
|
|
8
|
+
export { getTokenStorageAdapter, getTokenStorageType, isTokenStorageConfigured, resetTokenStorageAdapter, } from "./integration.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TokenStorageAdapter } from "./veryfront/types.js";
|
|
2
|
+
export declare function getTokenStorageAdapter(): Promise<TokenStorageAdapter>;
|
|
3
|
+
export declare function isTokenStorageConfigured(): boolean;
|
|
4
|
+
export declare function getTokenStorageType(): string;
|
|
5
|
+
export declare function resetTokenStorageAdapter(): void;
|
|
6
|
+
//# sourceMappingURL=integration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/adapters/token/integration.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAA6B,MAAM,sBAAsB,CAAC;AAQ3F,wBAAgB,sBAAsB,IAAI,OAAO,CAAC,mBAAmB,CAAC,CA0BrE;AAED,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAK/C"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { logger as baseLogger } from "../../../utils/index.js";
|
|
2
|
+
import { withSpan } from "../../../observability/tracing/otlp-setup.js";
|
|
3
|
+
import { getEnv } from "../../compat/process/env.js";
|
|
4
|
+
import { createTokenStorageAdapter } from "./factory.js";
|
|
5
|
+
const logger = baseLogger.component("token-adapter-integration");
|
|
6
|
+
let tokenStorageAdapter = null;
|
|
7
|
+
let tokenStorageAdapterCreation = null;
|
|
8
|
+
let tokenStorageGeneration = 0;
|
|
9
|
+
export function getTokenStorageAdapter() {
|
|
10
|
+
if (tokenStorageAdapter)
|
|
11
|
+
return Promise.resolve(tokenStorageAdapter);
|
|
12
|
+
if (tokenStorageAdapterCreation)
|
|
13
|
+
return tokenStorageAdapterCreation;
|
|
14
|
+
const generation = tokenStorageGeneration;
|
|
15
|
+
const rawCreation = withSpan("platform.token.getTokenStorageAdapter", async () => {
|
|
16
|
+
const adapterConfig = buildAdapterConfigFromEnv();
|
|
17
|
+
const candidate = await createTokenStorageAdapter(adapterConfig);
|
|
18
|
+
if (generation !== tokenStorageGeneration) {
|
|
19
|
+
candidate.dispose?.();
|
|
20
|
+
throw new Error("Token storage adapter creation was invalidated by reset");
|
|
21
|
+
}
|
|
22
|
+
tokenStorageAdapter = candidate;
|
|
23
|
+
return candidate;
|
|
24
|
+
}, { "token.storage.type": getTokenStorageType() });
|
|
25
|
+
const trackedCreation = rawCreation.finally(() => {
|
|
26
|
+
if (tokenStorageAdapterCreation === trackedCreation) {
|
|
27
|
+
tokenStorageAdapterCreation = null;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
tokenStorageAdapterCreation = trackedCreation;
|
|
31
|
+
return trackedCreation;
|
|
32
|
+
}
|
|
33
|
+
export function isTokenStorageConfigured() {
|
|
34
|
+
return Boolean(getEnvVar("VERYFRONT_API_TOKEN") && getEnvVar("VERYFRONT_PROJECT_SLUG"));
|
|
35
|
+
}
|
|
36
|
+
export function getTokenStorageType() {
|
|
37
|
+
return isTokenStorageConfigured() ? "veryfront-api" : "memory";
|
|
38
|
+
}
|
|
39
|
+
export function resetTokenStorageAdapter() {
|
|
40
|
+
tokenStorageGeneration++;
|
|
41
|
+
tokenStorageAdapter?.dispose?.();
|
|
42
|
+
tokenStorageAdapter = null;
|
|
43
|
+
tokenStorageAdapterCreation = null;
|
|
44
|
+
}
|
|
45
|
+
function buildAdapterConfigFromEnv() {
|
|
46
|
+
const apiToken = getEnvVar("VERYFRONT_API_TOKEN");
|
|
47
|
+
const projectSlug = getEnvVar("VERYFRONT_PROJECT_SLUG");
|
|
48
|
+
const apiBaseUrl = getEnvVar("VERYFRONT_API_URL");
|
|
49
|
+
if (!apiToken || !projectSlug) {
|
|
50
|
+
logger.debug("Using in-memory storage (development)");
|
|
51
|
+
return { type: "memory" };
|
|
52
|
+
}
|
|
53
|
+
logger.debug("Using Veryfront Cloud storage", { projectSlug });
|
|
54
|
+
return {
|
|
55
|
+
type: "veryfront-api",
|
|
56
|
+
veryfront: { apiToken, projectSlug, apiBaseUrl },
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function getEnvVar(name) {
|
|
60
|
+
return getEnv(name);
|
|
61
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Veryfront Token Storage Adapter
|
|
3
|
+
*
|
|
4
|
+
* Stores encrypted OAuth tokens in Veryfront Cloud.
|
|
5
|
+
* Tokens are encrypted client-side before being sent to the API.
|
|
6
|
+
*/
|
|
7
|
+
import { type TokenStorageAdapter, type TokenStorageAdapterConfig } from "./types.js";
|
|
8
|
+
export declare class VeryfrontTokenAdapter implements TokenStorageAdapter {
|
|
9
|
+
private client;
|
|
10
|
+
private initialized;
|
|
11
|
+
private initialization;
|
|
12
|
+
private lifecycleGeneration;
|
|
13
|
+
constructor(config: TokenStorageAdapterConfig);
|
|
14
|
+
initialize(): Promise<void>;
|
|
15
|
+
get(key: string): Promise<string | null>;
|
|
16
|
+
set(key: string, value: string): Promise<void>;
|
|
17
|
+
delete(key: string): Promise<void>;
|
|
18
|
+
list(prefix?: string): Promise<string[]>;
|
|
19
|
+
dispose(): void;
|
|
20
|
+
private doInitialize;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/token/veryfront/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC/B,MAAM,YAAY,CAAC;AASpB,qBAAa,qBAAsB,YAAW,mBAAmB;IAC/D,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,cAAc,CAAsC;IAC5D,OAAO,CAAC,mBAAmB,CAAK;gBAEpB,MAAM,EAAE,yBAAyB;IAUvC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB3B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAMxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAM9C,OAAO,IAAI,IAAI;YAUD,YAAY;CAqB3B"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Veryfront Token Storage Adapter
|
|
3
|
+
*
|
|
4
|
+
* Stores encrypted OAuth tokens in Veryfront Cloud.
|
|
5
|
+
* Tokens are encrypted client-side before being sent to the API.
|
|
6
|
+
*/
|
|
7
|
+
import { logger as baseLogger } from "../../../../utils/index.js";
|
|
8
|
+
import { TOKEN_STORAGE_ERROR } from "../../../../errors/index.js";
|
|
9
|
+
import { TokenStorageApiClient } from "./api-client.js";
|
|
10
|
+
import { createTokenConfig, } from "./types.js";
|
|
11
|
+
const logger = baseLogger.component("veryfront-token-adapter");
|
|
12
|
+
export class VeryfrontTokenAdapter {
|
|
13
|
+
client;
|
|
14
|
+
initialized = false;
|
|
15
|
+
initialization = null;
|
|
16
|
+
lifecycleGeneration = 0;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
const tokenConfig = createTokenConfig(config);
|
|
19
|
+
this.client = new TokenStorageApiClient(tokenConfig);
|
|
20
|
+
logger.debug("Created", {
|
|
21
|
+
apiBaseUrl: tokenConfig.apiBaseUrl,
|
|
22
|
+
projectSlug: tokenConfig.projectSlug,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
async initialize() {
|
|
26
|
+
if (this.initialized)
|
|
27
|
+
return;
|
|
28
|
+
if (this.initialization)
|
|
29
|
+
return await this.initialization.promise;
|
|
30
|
+
logger.debug("Initializing...");
|
|
31
|
+
const generation = this.lifecycleGeneration;
|
|
32
|
+
const controller = new AbortController();
|
|
33
|
+
const initialization = {
|
|
34
|
+
controller,
|
|
35
|
+
promise: this.doInitialize(generation, controller.signal),
|
|
36
|
+
};
|
|
37
|
+
this.initialization = initialization;
|
|
38
|
+
try {
|
|
39
|
+
await initialization.promise;
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
if (this.initialization === initialization) {
|
|
43
|
+
this.initialization = null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async get(key) {
|
|
48
|
+
await this.initialize();
|
|
49
|
+
logger.debug("Get", { key });
|
|
50
|
+
return this.client.get(key);
|
|
51
|
+
}
|
|
52
|
+
async set(key, value) {
|
|
53
|
+
await this.initialize();
|
|
54
|
+
logger.debug("Set", { key, valueLength: value.length });
|
|
55
|
+
await this.client.set(key, value);
|
|
56
|
+
}
|
|
57
|
+
async delete(key) {
|
|
58
|
+
await this.initialize();
|
|
59
|
+
logger.debug("Delete", { key });
|
|
60
|
+
await this.client.delete(key);
|
|
61
|
+
}
|
|
62
|
+
async list(prefix) {
|
|
63
|
+
await this.initialize();
|
|
64
|
+
logger.debug("List", { prefix });
|
|
65
|
+
return this.client.list(prefix);
|
|
66
|
+
}
|
|
67
|
+
dispose() {
|
|
68
|
+
this.lifecycleGeneration++;
|
|
69
|
+
this.initialization?.controller.abort(new DOMException("Token storage initialization was invalidated", "AbortError"));
|
|
70
|
+
this.initialization = null;
|
|
71
|
+
this.initialized = false;
|
|
72
|
+
logger.debug("Disposed");
|
|
73
|
+
}
|
|
74
|
+
async doInitialize(generation, signal) {
|
|
75
|
+
const connected = await this.client.ping(signal);
|
|
76
|
+
signal.throwIfAborted();
|
|
77
|
+
if (generation !== this.lifecycleGeneration) {
|
|
78
|
+
throw new DOMException("Token storage initialization was invalidated", "AbortError");
|
|
79
|
+
}
|
|
80
|
+
if (!connected) {
|
|
81
|
+
throw TOKEN_STORAGE_ERROR.create({
|
|
82
|
+
detail: "Failed to connect to Veryfront token storage API",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
this.initialized = true;
|
|
86
|
+
logger.debug("Initialized successfully");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type VeryfrontTokenConfig } from "./types.js";
|
|
2
|
+
export declare class TokenStorageApiClient {
|
|
3
|
+
private readonly config;
|
|
4
|
+
private readonly transport;
|
|
5
|
+
constructor(config: VeryfrontTokenConfig);
|
|
6
|
+
get(key: string): Promise<string | null>;
|
|
7
|
+
set(key: string, value: string): Promise<void>;
|
|
8
|
+
delete(key: string): Promise<void>;
|
|
9
|
+
list(prefix?: string, signal?: AbortSignal): Promise<string[]>;
|
|
10
|
+
ping(signal?: AbortSignal): Promise<boolean>;
|
|
11
|
+
private buildUrl;
|
|
12
|
+
private parseJsonBody;
|
|
13
|
+
private wrapError;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/token/veryfront/api-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,YAAY,CAAC;AAsCpB,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkD;gBAEhE,MAAM,EAAE,oBAAoB;IAkDlC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA+BxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBlC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAiD9D,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAWlD,OAAO,CAAC,QAAQ;IAMhB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,SAAS;CAgBlB"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { logger as baseLogger } from "../../../../utils/index.js";
|
|
2
|
+
import { readResponseTextPrefix } from "../../../../utils/response-body.js";
|
|
3
|
+
import { assertTokenStorageKey, assertTokenStoragePrefix, assertTokenStorageValue, } from "./types.js";
|
|
4
|
+
import { TOKEN_STORAGE_ERROR } from "../../../../errors/error-registry.js";
|
|
5
|
+
import { VeryfrontError } from "../../../../errors/types.js";
|
|
6
|
+
import { createVeryfrontApiTransport, } from "../../veryfront-api-transport.js";
|
|
7
|
+
const logger = baseLogger.component("token-storage-api-client");
|
|
8
|
+
const MAX_TOKEN_STORAGE_RESPONSE_BODY_BYTES = 1024 * 1024;
|
|
9
|
+
function cancelResponseBody(response, operation) {
|
|
10
|
+
if (!response.body)
|
|
11
|
+
return;
|
|
12
|
+
try {
|
|
13
|
+
void response.body.cancel().catch((error) => {
|
|
14
|
+
logger.debug("Response body cancellation failed during token storage cleanup", {
|
|
15
|
+
operation,
|
|
16
|
+
status: response.status,
|
|
17
|
+
error,
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
logger.debug("Response body cancellation failed during token storage cleanup", {
|
|
23
|
+
operation,
|
|
24
|
+
status: response.status,
|
|
25
|
+
error,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export class TokenStorageApiClient {
|
|
30
|
+
config;
|
|
31
|
+
transport;
|
|
32
|
+
constructor(config) {
|
|
33
|
+
this.config = config;
|
|
34
|
+
const { maxRetries, initialDelay, maxDelay } = config.retry;
|
|
35
|
+
this.transport = createVeryfrontApiTransport({
|
|
36
|
+
baseUrl: config.apiBaseUrl,
|
|
37
|
+
getToken: () => config.apiToken,
|
|
38
|
+
retry: { maxRetries, initialDelay, maxDelay },
|
|
39
|
+
timeoutMs: config.timeoutMs,
|
|
40
|
+
defaultHeaders: { "Accept": "application/json" },
|
|
41
|
+
onResponse: async (response, _init, _url, signal) => {
|
|
42
|
+
// 5xx / 429: throw to trigger retry logic. Cancel the body first so
|
|
43
|
+
// retries do not hold connections/buffers open.
|
|
44
|
+
if (!response.ok && (response.status >= 500 || response.status === 429)) {
|
|
45
|
+
cancelResponseBody(response, "retry");
|
|
46
|
+
throw TOKEN_STORAGE_ERROR.create({
|
|
47
|
+
detail: `Server error: ${response.status}`,
|
|
48
|
+
status: response.status,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const { text, truncated } = await readResponseTextPrefix(response, MAX_TOKEN_STORAGE_RESPONSE_BODY_BYTES, signal);
|
|
52
|
+
if (truncated) {
|
|
53
|
+
throw TOKEN_STORAGE_ERROR.create({
|
|
54
|
+
detail: `Token storage response body exceeds ${MAX_TOKEN_STORAGE_RESPONSE_BODY_BYTES} bytes`,
|
|
55
|
+
status: 502,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
ok: response.ok,
|
|
60
|
+
status: response.status,
|
|
61
|
+
statusText: response.statusText,
|
|
62
|
+
bodyText: text,
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
wrapFinalError: (lastError) => TOKEN_STORAGE_ERROR.create({
|
|
66
|
+
detail: `Request failed after ${maxRetries} retries: ${lastError.message}`,
|
|
67
|
+
}),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async get(key) {
|
|
71
|
+
assertTokenStorageKey(key);
|
|
72
|
+
const url = this.buildUrl(key);
|
|
73
|
+
try {
|
|
74
|
+
const response = await this.transport.request(url);
|
|
75
|
+
if (response.status === 404) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
throw TOKEN_STORAGE_ERROR.create({
|
|
80
|
+
detail: `Failed to get token: ${response.statusText}`,
|
|
81
|
+
status: response.status,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
const data = this.parseJsonBody(response, "get");
|
|
85
|
+
if (!isRecord(data) || typeof data.value !== "string") {
|
|
86
|
+
throw TOKEN_STORAGE_ERROR.create({
|
|
87
|
+
detail: "Malformed get response: expected an object with a string value",
|
|
88
|
+
status: 502,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return data.value;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
throw this.wrapError(error, "Get", key, `Failed to get token`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async set(key, value) {
|
|
98
|
+
assertTokenStorageKey(key);
|
|
99
|
+
assertTokenStorageValue(value);
|
|
100
|
+
const url = this.buildUrl(key);
|
|
101
|
+
try {
|
|
102
|
+
const response = await this.transport.request(url, {
|
|
103
|
+
method: "PUT",
|
|
104
|
+
headers: { "Content-Type": "application/json" },
|
|
105
|
+
body: JSON.stringify({ value }),
|
|
106
|
+
});
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
throw TOKEN_STORAGE_ERROR.create({
|
|
109
|
+
detail: `Failed to set token: ${response.statusText}`,
|
|
110
|
+
status: response.status,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
throw this.wrapError(error, "Set", key, `Failed to set token`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async delete(key) {
|
|
119
|
+
assertTokenStorageKey(key);
|
|
120
|
+
const url = this.buildUrl(key);
|
|
121
|
+
try {
|
|
122
|
+
const response = await this.transport.request(url, { method: "DELETE" });
|
|
123
|
+
if (response.ok || response.status === 404) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
throw TOKEN_STORAGE_ERROR.create({
|
|
127
|
+
detail: `Failed to delete token: ${response.statusText}`,
|
|
128
|
+
status: response.status,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw this.wrapError(error, "Delete", key, `Failed to delete token`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async list(prefix, signal) {
|
|
136
|
+
assertTokenStoragePrefix(prefix);
|
|
137
|
+
let url = `/v1/projects/${encodeURIComponent(this.config.projectSlug)}/tokens`;
|
|
138
|
+
if (prefix !== undefined && prefix.length > 0) {
|
|
139
|
+
const search = new URLSearchParams({ prefix });
|
|
140
|
+
url += `?${search.toString()}`;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const response = await this.transport.request(url, { signal });
|
|
144
|
+
if (!response.ok) {
|
|
145
|
+
throw TOKEN_STORAGE_ERROR.create({
|
|
146
|
+
detail: `Failed to list tokens: ${response.statusText}`,
|
|
147
|
+
status: response.status,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
const data = this.parseJsonBody(response, "list");
|
|
151
|
+
if (!isRecord(data) ||
|
|
152
|
+
(data.keys !== undefined &&
|
|
153
|
+
(!Array.isArray(data.keys) ||
|
|
154
|
+
!data.keys.every((key) => typeof key === "string")))) {
|
|
155
|
+
throw TOKEN_STORAGE_ERROR.create({
|
|
156
|
+
detail: "Malformed list response: expected an object with a string keys array",
|
|
157
|
+
status: 502,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return data.keys ?? [];
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
signal?.throwIfAborted();
|
|
164
|
+
if (error instanceof VeryfrontError && error.slug === "token-storage-error") {
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
168
|
+
logger.error("List failed", {
|
|
169
|
+
prefix,
|
|
170
|
+
error: message,
|
|
171
|
+
});
|
|
172
|
+
throw TOKEN_STORAGE_ERROR.create({ detail: `Failed to list tokens: ${message}` });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async ping(signal) {
|
|
176
|
+
try {
|
|
177
|
+
await this.list(undefined, signal);
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
signal?.throwIfAborted();
|
|
182
|
+
/* expected: ping returns false when API is unreachable */
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
buildUrl(key) {
|
|
187
|
+
return `/v1/projects/${encodeURIComponent(this.config.projectSlug)}/tokens/${encodeURIComponent(key)}`;
|
|
188
|
+
}
|
|
189
|
+
parseJsonBody(response, operation) {
|
|
190
|
+
try {
|
|
191
|
+
return JSON.parse(response.bodyText);
|
|
192
|
+
}
|
|
193
|
+
catch (cause) {
|
|
194
|
+
throw TOKEN_STORAGE_ERROR.create({
|
|
195
|
+
detail: `Malformed ${operation} response: expected valid JSON`,
|
|
196
|
+
cause,
|
|
197
|
+
status: 502,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
wrapError(error, action, key, prefixMessage) {
|
|
202
|
+
if (error instanceof VeryfrontError && error.slug === "token-storage-error") {
|
|
203
|
+
return error;
|
|
204
|
+
}
|
|
205
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
206
|
+
logger.error(`${action} failed`, { key, error: message });
|
|
207
|
+
return TOKEN_STORAGE_ERROR.create({ detail: `${prefixMessage}: ${message}` });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function isRecord(value) {
|
|
211
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
212
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token - Veryfront
|
|
3
|
+
*
|
|
4
|
+
* @module platform/adapters/token/veryfront
|
|
5
|
+
*/
|
|
6
|
+
export { TokenStorageApiClient } from "./api-client.js";
|
|
7
|
+
export { VeryfrontTokenAdapter } from "./adapter.js";
|
|
8
|
+
export { MemoryTokenAdapter } from "./memory-adapter.js";
|
|
9
|
+
export { createTokenConfig, TOKEN_STORAGE_ERROR, type TokenStorageAdapter, type TokenStorageAdapterConfig, type VeryfrontTokenConfig, } from "./types.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/token/veryfront/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,GAC1B,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token - Veryfront
|
|
3
|
+
*
|
|
4
|
+
* @module platform/adapters/token/veryfront
|
|
5
|
+
*/
|
|
6
|
+
export { TokenStorageApiClient } from "./api-client.js";
|
|
7
|
+
export { VeryfrontTokenAdapter } from "./adapter.js";
|
|
8
|
+
export { MemoryTokenAdapter } from "./memory-adapter.js";
|
|
9
|
+
export { createTokenConfig, TOKEN_STORAGE_ERROR, } from "./types.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Memory Token Storage Adapter
|
|
3
|
+
*
|
|
4
|
+
* Development-only adapter that stores tokens in memory.
|
|
5
|
+
* Tokens are lost when the process restarts.
|
|
6
|
+
*/
|
|
7
|
+
import { type TokenStorageAdapter } from "./types.js";
|
|
8
|
+
export declare class MemoryTokenAdapter implements TokenStorageAdapter {
|
|
9
|
+
private readonly storage;
|
|
10
|
+
constructor();
|
|
11
|
+
initialize(): Promise<void>;
|
|
12
|
+
get(key: string): Promise<string | null>;
|
|
13
|
+
set(key: string, value: string): Promise<void>;
|
|
14
|
+
delete(key: string): Promise<void>;
|
|
15
|
+
list(prefix?: string): Promise<string[]>;
|
|
16
|
+
dispose(): void;
|
|
17
|
+
get size(): number;
|
|
18
|
+
clear(): void;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=memory-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-adapter.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/token/veryfront/memory-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,YAAY,CAAC;AAIpB,qBAAa,kBAAmB,YAAW,mBAAmB;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;;IAUrD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAOxC,OAAO,IAAI,IAAI;IAKf,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Memory Token Storage Adapter
|
|
3
|
+
*
|
|
4
|
+
* Development-only adapter that stores tokens in memory.
|
|
5
|
+
* Tokens are lost when the process restarts.
|
|
6
|
+
*/
|
|
7
|
+
import { logger as baseLogger } from "../../../../utils/index.js";
|
|
8
|
+
import { assertTokenStorageKey, assertTokenStoragePrefix, assertTokenStorageValue, } from "./types.js";
|
|
9
|
+
const logger = baseLogger.component("memory-token-adapter");
|
|
10
|
+
export class MemoryTokenAdapter {
|
|
11
|
+
storage = new Map();
|
|
12
|
+
constructor() {
|
|
13
|
+
logger.warn("[MemoryTokenAdapter] Using in-memory storage. " +
|
|
14
|
+
"Tokens will be lost on restart. " +
|
|
15
|
+
"Configure Veryfront Cloud for production.");
|
|
16
|
+
}
|
|
17
|
+
initialize() {
|
|
18
|
+
return Promise.resolve();
|
|
19
|
+
}
|
|
20
|
+
get(key) {
|
|
21
|
+
assertTokenStorageKey(key);
|
|
22
|
+
return Promise.resolve(this.storage.get(key) ?? null);
|
|
23
|
+
}
|
|
24
|
+
set(key, value) {
|
|
25
|
+
assertTokenStorageKey(key);
|
|
26
|
+
assertTokenStorageValue(value);
|
|
27
|
+
this.storage.set(key, value);
|
|
28
|
+
return Promise.resolve();
|
|
29
|
+
}
|
|
30
|
+
delete(key) {
|
|
31
|
+
assertTokenStorageKey(key);
|
|
32
|
+
this.storage.delete(key);
|
|
33
|
+
return Promise.resolve();
|
|
34
|
+
}
|
|
35
|
+
list(prefix) {
|
|
36
|
+
assertTokenStoragePrefix(prefix);
|
|
37
|
+
const keys = Array.from(this.storage.keys());
|
|
38
|
+
if (!prefix)
|
|
39
|
+
return Promise.resolve(keys);
|
|
40
|
+
return Promise.resolve(keys.filter((k) => k.startsWith(prefix)));
|
|
41
|
+
}
|
|
42
|
+
dispose() {
|
|
43
|
+
this.storage.clear();
|
|
44
|
+
logger.debug("Disposed");
|
|
45
|
+
}
|
|
46
|
+
get size() {
|
|
47
|
+
return this.storage.size;
|
|
48
|
+
}
|
|
49
|
+
clear() {
|
|
50
|
+
this.storage.clear();
|
|
51
|
+
}
|
|
52
|
+
}
|