feat: KMS client + sync all package versions to 1.8.0
- Add shared/kms.ts: lightweight KMS client (list, get, create, update, delete secrets) - Add KMS_API_URL + kmsApiUrl to shared config with runtime override support - Sync versions: VS Code 1.7.27→1.8.0, JetBrains 1.7.18→1.8.0, DXT 1.7.27→1.8.0, Tools 1.7.27→1.8.0 - KMS uses IAM bearer tokens — no separate credentials needed
This commit is contained in:
@@ -39,6 +39,11 @@ export const STORAGE_KEYS = {
|
||||
/** Cloud API base — override via storage key 'hanzo_config_api_base' */
|
||||
export const API_BASE_URL = 'https://api.hanzo.ai';
|
||||
|
||||
// ── KMS (Secrets Management) ──────────────────────────────────────────
|
||||
|
||||
/** KMS API base — override via storage key 'hanzo_config_kms_url' */
|
||||
export const KMS_API_URL = 'https://kms.hanzo.ai';
|
||||
|
||||
// ── Local Provider Defaults ────────────────────────────────────────────
|
||||
|
||||
export const LOCAL_PROVIDER_DEFAULTS = {
|
||||
@@ -79,6 +84,7 @@ export interface RuntimeConfig {
|
||||
iamLoginUrl: string;
|
||||
iamApiUrl: string;
|
||||
apiBaseUrl: string;
|
||||
kmsApiUrl: string;
|
||||
clientId: string;
|
||||
scopes: string;
|
||||
redirectUri: string;
|
||||
@@ -89,6 +95,7 @@ const CONFIG_STORAGE_MAP: Record<keyof RuntimeConfig, { key: string; fallback: s
|
||||
iamLoginUrl: { key: 'hanzo_config_iam_login_url', fallback: IAM_LOGIN_URL },
|
||||
iamApiUrl: { key: 'hanzo_config_iam_api_url', fallback: IAM_API_URL },
|
||||
apiBaseUrl: { key: 'hanzo_config_api_base', fallback: API_BASE_URL },
|
||||
kmsApiUrl: { key: 'hanzo_config_kms_url', fallback: KMS_API_URL },
|
||||
clientId: { key: 'hanzo_config_client_id', fallback: DEFAULT_CLIENT_ID },
|
||||
scopes: { key: 'hanzo_config_scopes', fallback: DEFAULT_SCOPES },
|
||||
redirectUri: { key: 'hanzo_config_redirect_uri', fallback: DEFAULT_REDIRECT_URI },
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* KMS (Key Management / Secrets) client — shared across all browser targets.
|
||||
*
|
||||
* Lightweight fetch-based client for Hanzo KMS (kms.hanzo.ai).
|
||||
* Uses IAM bearer tokens for auth — no separate KMS credentials needed.
|
||||
*
|
||||
* API surface mirrors @hanzo/kms-sdk SecretsApi:
|
||||
* GET /api/v3/secrets/raw → list
|
||||
* GET /api/v3/secrets/raw/:name → get
|
||||
* POST /api/v3/secrets/raw/:name → create
|
||||
* PATCH /api/v3/secrets/raw/:name → update
|
||||
* DELETE /api/v3/secrets/raw/:name → delete
|
||||
*/
|
||||
|
||||
import { KMS_API_URL } from './config.js';
|
||||
|
||||
// ── Types ───────────────────────────────────────────────────────────────
|
||||
|
||||
export interface KmsSecret {
|
||||
secretKey: string;
|
||||
secretValue?: string;
|
||||
version?: number;
|
||||
type?: string;
|
||||
environment?: string;
|
||||
secretPath?: string;
|
||||
}
|
||||
|
||||
export interface KmsListParams {
|
||||
workspaceId: string;
|
||||
environment: string;
|
||||
secretPath?: string;
|
||||
}
|
||||
|
||||
export interface KmsSecretParams extends KmsListParams {
|
||||
secretName: string;
|
||||
}
|
||||
|
||||
// ── Helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
function kmsHeaders(token: string): Record<string, string> {
|
||||
return {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
}
|
||||
|
||||
function kmsUrl(path: string, baseUrl?: string): string {
|
||||
return `${baseUrl || KMS_API_URL}${path}`;
|
||||
}
|
||||
|
||||
function buildQuery(params: Record<string, string | undefined>): string {
|
||||
const entries = Object.entries(params).filter(([, v]) => v !== undefined) as [string, string][];
|
||||
if (!entries.length) return '';
|
||||
return '?' + new URLSearchParams(entries).toString();
|
||||
}
|
||||
|
||||
// ── API Functions ───────────────────────────────────────────────────────
|
||||
|
||||
/** List secrets in a workspace/environment */
|
||||
export async function kmsListSecrets(
|
||||
token: string,
|
||||
params: KmsListParams,
|
||||
baseUrl?: string,
|
||||
): Promise<KmsSecret[]> {
|
||||
const query = buildQuery({
|
||||
workspaceId: params.workspaceId,
|
||||
environment: params.environment,
|
||||
secretPath: params.secretPath,
|
||||
});
|
||||
const resp = await fetch(kmsUrl(`/api/v3/secrets/raw${query}`, baseUrl), {
|
||||
headers: kmsHeaders(token),
|
||||
});
|
||||
if (!resp.ok) throw new Error(`KMS list failed: ${resp.status} ${await resp.text()}`);
|
||||
const data = await resp.json();
|
||||
return data.secrets || data;
|
||||
}
|
||||
|
||||
/** Get a single secret by name */
|
||||
export async function kmsGetSecret(
|
||||
token: string,
|
||||
params: KmsSecretParams,
|
||||
baseUrl?: string,
|
||||
): Promise<KmsSecret> {
|
||||
const query = buildQuery({
|
||||
workspaceId: params.workspaceId,
|
||||
environment: params.environment,
|
||||
secretPath: params.secretPath,
|
||||
});
|
||||
const resp = await fetch(
|
||||
kmsUrl(`/api/v3/secrets/raw/${encodeURIComponent(params.secretName)}${query}`, baseUrl),
|
||||
{ headers: kmsHeaders(token) },
|
||||
);
|
||||
if (!resp.ok) throw new Error(`KMS get failed: ${resp.status} ${await resp.text()}`);
|
||||
const data = await resp.json();
|
||||
return data.secret || data;
|
||||
}
|
||||
|
||||
/** Create a new secret */
|
||||
export async function kmsCreateSecret(
|
||||
token: string,
|
||||
params: KmsSecretParams,
|
||||
value: string,
|
||||
baseUrl?: string,
|
||||
): Promise<KmsSecret> {
|
||||
const resp = await fetch(
|
||||
kmsUrl(`/api/v3/secrets/raw/${encodeURIComponent(params.secretName)}`, baseUrl),
|
||||
{
|
||||
method: 'POST',
|
||||
headers: kmsHeaders(token),
|
||||
body: JSON.stringify({
|
||||
workspaceId: params.workspaceId,
|
||||
environment: params.environment,
|
||||
secretPath: params.secretPath,
|
||||
secretValue: value,
|
||||
type: 'shared',
|
||||
}),
|
||||
},
|
||||
);
|
||||
if (!resp.ok) throw new Error(`KMS create failed: ${resp.status} ${await resp.text()}`);
|
||||
const data = await resp.json();
|
||||
return data.secret || data;
|
||||
}
|
||||
|
||||
/** Update an existing secret */
|
||||
export async function kmsUpdateSecret(
|
||||
token: string,
|
||||
params: KmsSecretParams,
|
||||
value: string,
|
||||
baseUrl?: string,
|
||||
): Promise<KmsSecret> {
|
||||
const resp = await fetch(
|
||||
kmsUrl(`/api/v3/secrets/raw/${encodeURIComponent(params.secretName)}`, baseUrl),
|
||||
{
|
||||
method: 'PATCH',
|
||||
headers: kmsHeaders(token),
|
||||
body: JSON.stringify({
|
||||
workspaceId: params.workspaceId,
|
||||
environment: params.environment,
|
||||
secretPath: params.secretPath,
|
||||
secretValue: value,
|
||||
}),
|
||||
},
|
||||
);
|
||||
if (!resp.ok) throw new Error(`KMS update failed: ${resp.status} ${await resp.text()}`);
|
||||
const data = await resp.json();
|
||||
return data.secret || data;
|
||||
}
|
||||
|
||||
/** Delete a secret */
|
||||
export async function kmsDeleteSecret(
|
||||
token: string,
|
||||
params: KmsSecretParams,
|
||||
baseUrl?: string,
|
||||
): Promise<void> {
|
||||
const resp = await fetch(
|
||||
kmsUrl(`/api/v3/secrets/raw/${encodeURIComponent(params.secretName)}`, baseUrl),
|
||||
{
|
||||
method: 'DELETE',
|
||||
headers: kmsHeaders(token),
|
||||
body: JSON.stringify({
|
||||
workspaceId: params.workspaceId,
|
||||
environment: params.environment,
|
||||
secretPath: params.secretPath,
|
||||
}),
|
||||
},
|
||||
);
|
||||
if (!resp.ok) throw new Error(`KMS delete failed: ${resp.status} ${await resp.text()}`);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hanzo/dxt",
|
||||
"version": "1.7.27",
|
||||
"version": "1.8.0",
|
||||
"description": "Hanzo AI DXT Bundle",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -4,7 +4,7 @@ pluginGroup = ai.hanzo
|
||||
pluginName = Hanzo AI
|
||||
pluginRepositoryUrl = https://github.com/hanzoai/hanzo-ai-jetbrains
|
||||
# SemVer format -> https://semver.org
|
||||
pluginVersion = 1.7.18
|
||||
pluginVersion = 1.8.0
|
||||
|
||||
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
|
||||
pluginSinceBuild = 233
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hanzo/cli-tools",
|
||||
"version": "1.7.27",
|
||||
"version": "1.8.0",
|
||||
"description": "Hanzo AI CLI Tools Integration",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "hanzo-ide",
|
||||
"displayName": "Hanzo AI",
|
||||
"description": "The ultimate meta AI development platform. Manage and run all LLMs and CLI tools (Claude, Codex, Gemini, OpenHands, Aider) in one unified interface. Features MCP integration, async execution, git worktrees, and universal context sync.",
|
||||
"version": "1.7.27",
|
||||
"version": "1.8.0",
|
||||
"publisher": "hanzo-ai",
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
|
||||
Reference in New Issue
Block a user