Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
618198f
added aws sdk
nafees87n Jan 15, 2026
36a2aa7
added refreshSecrets
nafees87n Jan 15, 2026
74de3a0
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 15, 2026
19e82b5
fix: webpack config
nafees87n Jan 15, 2026
f19b6d4
fix
nafees87n Jan 16, 2026
2c7faa3
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 16, 2026
7804ed1
fix
nafees87n Jan 16, 2026
74f3589
fix: class singleton initialization
nafees87n Jan 16, 2026
f01d364
fix: SecretReference type
nafees87n Jan 16, 2026
c935804
fix: getSecrets
nafees87n Jan 16, 2026
f88792e
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 20, 2026
c848582
fix: getSecrets
nafees87n Jan 20, 2026
94f66c6
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 20, 2026
2cb9f34
added fallback
nafees87n Jan 20, 2026
988dd94
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 20, 2026
2aba2f9
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 20, 2026
71cfafa
fix: cache cleanup
nafees87n Jan 20, 2026
4a648db
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 20, 2026
6452f00
fix: initialization
nafees87n Jan 20, 2026
a502c64
fix: infinite loop
nafees87n Jan 20, 2026
4e410c4
fix: types
nafees87n Jan 20, 2026
9beaa0a
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 21, 2026
6829224
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 21, 2026
07b888a
fix: init
nafees87n Jan 21, 2026
491ebdb
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 21, 2026
b48422c
fix: eslint rules
nafees87n Jan 21, 2026
9e0478e
revert eslint changes
nafees87n Jan 21, 2026
986438a
remove change
nafees87n Jan 21, 2026
3ae4aab
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 21, 2026
95b60b6
added ipc methods
nafees87n Jan 22, 2026
98627e5
added listProviders
nafees87n Jan 22, 2026
16a4a14
fix: initialization
nafees87n Jan 23, 2026
ecd380a
exposed getSecrets
nafees87n Jan 27, 2026
9898462
fix: event name
nafees87n Jan 27, 2026
6c67bcc
only return metadata for listing
nafees87n Jan 27, 2026
8237627
added providers onCHange listener
nafees87n Jan 27, 2026
cce2bd6
added storage listener in secrets manager
nafees87n Jan 27, 2026
bc4baca
Merge branch 'secrets/storage-listener' into ipc-layer
nafees87n Jan 27, 2026
a0d5cf6
Merge branch 'initialization' into aws-secrets-manager
nafees87n Jan 28, 2026
6b06a4e
Merge branch 'aws-secrets-manager' into secrets/storage-listener
nafees87n Jan 28, 2026
57c27c8
remove unsubscribe listener
nafees87n Jan 28, 2026
27ef8b3
Merge branch 'secrets/storage-listener' into ipc-layer
nafees87n Jan 28, 2026
203acf0
Merge branch 'initialization' into secrets/storage-listener
nafees87n Jan 30, 2026
44bdcac
[DB-28] error handling in secretsManager (#278)
nafees87n Jan 30, 2026
1f1c66a
Merge branch 'secrets/storage-listener' into ipc-layer
nafees87n Jan 30, 2026
645fa39
Merge branch 'initialization' into secrets/storage-listener
nafees87n Jan 30, 2026
fe6aea2
Merge branch 'secrets/storage-listener' into ipc-layer
nafees87n Jan 30, 2026
63ff56a
remove examples.ts
nafees87n Jan 30, 2026
0a95cda
mfa code without callback
nafees87n Feb 25, 2026
6aa516c
Merge branch 'initialization' of github.com:requestly/requestly-deskt…
nafees87n Feb 25, 2026
8f56d1a
Merge branch 'secrets/storage-listener' of github.com:requestly/reque…
nafees87n Feb 25, 2026
e12cbe3
fix: type
nafees87n Feb 25, 2026
00add6f
added IPC event to test connection with config
nafees87n Mar 3, 2026
01c2e73
added alias in secretReference type
nafees87n Mar 4, 2026
44d4f4d
Merge branch 'initialization' of github.com:requestly/requestly-deskt…
nafees87n Mar 9, 2026
006ffc8
[DB-48] added persistence to secret values (#306)
nafees87n Mar 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/lib/secretsManager/baseTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@ export interface ProviderConfig<T extends SecretProviderType, C> {
* @template T - The provider type
*/
export interface SecretReference<T extends SecretProviderType> {
id: string;
type: T;
alias: string;
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
import { SecretProviderConfig } from "../types";
import { SecretProviderConfig, SecretValue } from "../types";

export type StorageChangeCallback = (
data: Record<string, SecretProviderConfig>
export type ProviderStorageChangeCallback = (
providers: Record<string, SecretProviderConfig>
) => void;
export type SecretStorageChangeCallback = (
secrets: Record<string, SecretValue>
) => void;

export abstract class AbstractSecretsManagerStorage {
abstract set(_key: string, _data: SecretProviderConfig): Promise<void>;

abstract get(_key: string): Promise<SecretProviderConfig | null>;
abstract setProviderConfig(
_providerId: string,
_data: SecretProviderConfig
): Promise<void>;
abstract setSecretValue(_secretId: string, _data: SecretValue): Promise<void>;
abstract setSecretValues(
_entries: Record<string, SecretValue>
): Promise<void>;

abstract getAll(): Promise<SecretProviderConfig[]>;
abstract getProviderConfig(
_providerId: string
): Promise<SecretProviderConfig | null>;
abstract getSecretValue(_secretId: string): Promise<SecretValue | null>;

abstract delete(_key: string): Promise<void>;
abstract getAllProviderConfigs(): Promise<SecretProviderConfig[]>;
abstract getAllSecretValues(): Promise<SecretValue[]>;
abstract deleteProviderConfig(_providerId: string): Promise<void>;
abstract deleteSecretValue(_secretId: string): Promise<void>;
abstract deleteSecretValues(_keys: string[]): Promise<void>;

abstract onStorageChange(callback: StorageChangeCallback): () => void;
abstract onProvidersChange(
callback: ProviderStorageChangeCallback
): () => void;
abstract onSecretsChange(callback: SecretStorageChangeCallback): () => void;
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,96 @@
import {
AbstractSecretsManagerStorage,
StorageChangeCallback,
ProviderStorageChangeCallback,
SecretStorageChangeCallback,
} from "./AbstractSecretsManagerStorage";
import { EncryptedElectronStore } from "../../storage/EncryptedElectronStore";
import { SecretProviderConfig } from "../types";
import { SecretProviderConfig, SecretReference, SecretValue } from "../types";

export class SecretsManagerEncryptedStorage extends AbstractSecretsManagerStorage {
private encryptedStore: EncryptedElectronStore;

constructor(storeName: string) {
constructor(storeName: string, userId: string) {
super();
this.encryptedStore = new EncryptedElectronStore(storeName);
this.encryptedStore.set("userId", userId);
}

async set(key: string, data: SecretProviderConfig): Promise<void> {
return this.encryptedStore.set<SecretProviderConfig>(key, data);
async setProviderConfig(
providerId: string,
data: SecretProviderConfig
): Promise<void> {
return this.encryptedStore.set<SecretProviderConfig>(
`providers.${providerId}`,
data
);
}

async get(key: string): Promise<SecretProviderConfig | null> {
return this.encryptedStore.get<SecretProviderConfig>(key);
async setSecretValue(secretId: string, data: SecretValue): Promise<void> {
return this.encryptedStore.set<SecretValue>(`secrets.${secretId}`, data);
}

async getAll(): Promise<SecretProviderConfig[]> {
const allData = this.encryptedStore.getAll<SecretProviderConfig>();
return Object.values(allData);
async setSecretValues(entries: Record<string, SecretValue>): Promise<void> {
const current =
this.encryptedStore.get<Record<string, SecretValue>>("secrets") ?? {};
this.encryptedStore.set<Record<string, SecretValue>>("secrets", {
...current,
...entries,
});
}

async delete(key: string): Promise<void> {
return this.encryptedStore.delete(key);
async getProviderConfig(
providerId: string
): Promise<SecretProviderConfig | null> {
return this.encryptedStore.get<SecretProviderConfig>(
`providers.${providerId}`
);
}

onStorageChange(callback: StorageChangeCallback): () => void {
return this.encryptedStore.onChange<SecretProviderConfig>(callback);
async getSecretValue(secretId: string): Promise<SecretValue | null> {
return this.encryptedStore.get<SecretValue>(`secrets.${secretId}`);
}

async getAllProviderConfigs(): Promise<SecretProviderConfig[]> {
const allProviders =
this.encryptedStore.get<Record<string, SecretProviderConfig>>(
`providers`
);
return Object.values(allProviders ?? {});
}

async getAllSecretValues(): Promise<SecretValue[]> {
const allSecrets =
this.encryptedStore.get<Record<string, SecretValue>>(`secrets`);
return Object.values(allSecrets ?? {});
}

async deleteProviderConfig(providerId: string): Promise<void> {
return this.encryptedStore.delete(`providers.${providerId}`);
}

async deleteSecretValue(secretId: string): Promise<void> {
return this.encryptedStore.delete(`secrets.${secretId}`);
}

async deleteSecretValues(keys: string[]): Promise<void> {
const current =
this.encryptedStore.get<Record<string, SecretValue>>("secrets") ?? {};
for (const key of keys) {
delete current[key];
}
this.encryptedStore.set<Record<string, SecretValue>>("secrets", current);
}

onProvidersChange(callback: ProviderStorageChangeCallback): () => void {
return this.encryptedStore.onKeyChange<
Record<string, SecretProviderConfig>
>("providers", callback);
}

onSecretsChange(callback: SecretStorageChangeCallback): () => void {
return this.encryptedStore.onKeyChange<Record<string, SecretValue>>(
"secrets",
callback
);
}
}
65 changes: 65 additions & 0 deletions src/lib/secretsManager/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { SecretReference, SecretValue } from "./types";

export enum SecretsErrorCode {
SAFE_STORAGE_ENCRYPTION_NOT_AVAILABLE = "safe_storage_encryption_not_available",
INVALID_USER_ID = "invalid_user_id",

PROVIDER_NOT_FOUND = "provider_not_found",

AUTH_FAILED = "auth_failed",
PERMISSION_DENIED = "permission_denied",

SECRET_NOT_FOUND = "secret_not_found",
SECRET_FETCH_FAILED = "secret_fetch_failed",

STORAGE_READ_FAILED = "storage_read_failed",
STORAGE_WRITE_FAILED = "storage_write_failed",

UNKNOWN = "unknown",
}

export interface SecretsError {
code: SecretsErrorCode;
message: string;
providerId?: string;
secretRef?: SecretReference;
cause?: Error; // Original error
}

export type SecretsManagerError = {
type: "error";
error: SecretsError;
};

export type SecretsSuccess<T> = T extends void
? { type: "success" }
: { type: "success"; data: T };

export type SecretsResult<T> = SecretsSuccess<T> | SecretsManagerError;

export type SecretsResultPromise<T> = Promise<SecretsResult<T>>;

export interface SecretFetchError {
secretRefId: string;
message: string;
}

export interface FetchSecretsResultData {
secrets: SecretValue[];
errors: SecretFetchError[];
}

export function createSecretsError(
code: SecretsErrorCode,
message: string,
context?: Omit<SecretsError, "code" | "message">
): SecretsManagerError {
return {
type: "error",
error: {
code,
message,
...context,
},
};
}
Loading