fix: KMS on its own host (kms.<brand>), stable doctor probes
Live infra drift (gateway redeploy): api.hanzo.ai/v1/kms is NOT proxied (404), and the bare /health path moved (/health 404, /v1/health 200). Two fixes: - KMS runs on its dedicated host kms.<brand> (kms.hanzo.ai, per IAM's per-brand KMSHost). Added brand.kms + endpoints.kms (HANZO_KMS_URL override); KMS client targets it instead of api.hanzo.ai/v1/kms. Verified live: kms.hanzo.ai/v1/kms/ orgs/hanzo/secrets → 401 (gated, live). - doctor now probes the STABLE endpoints the tool actually depends on — IAM /.well-known/openid-configuration + api /v1/models — not a bare /health that varies by gateway config. Both 200. - kms-secrets action base-url default → kms.hanzo.ai. Release 1.0.6 (helper + @hanzo/kms + lux/zoo/zen forks).
This commit is contained in:
@@ -20,9 +20,9 @@ inputs:
|
||||
trust the GitHub issuer; otherwise pass an IAM machine-identity token.
|
||||
required: true
|
||||
base-url:
|
||||
description: Gateway base that serves /v1/kms (KMS owns this namespace).
|
||||
description: KMS host that serves /v1/kms (its own host, not api.<brand>).
|
||||
required: false
|
||||
default: https://api.hanzo.ai
|
||||
default: https://kms.hanzo.ai
|
||||
export:
|
||||
description: "Where to put secrets: 'env' (job environment) or 'file'."
|
||||
required: false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@luxfi/helper",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Lux CLI helper — sign in to Lux and use its AI models in Claude Code, Codex, and more",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
@@ -28,6 +28,6 @@
|
||||
},
|
||||
"homepage": "https://lux.network",
|
||||
"dependencies": {
|
||||
"@hanzo/helper": "^1.0.5"
|
||||
"@hanzo/helper": "^1.0.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@zenlm/helper",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Zen CLI helper — sign in to Zen and use its AI models in Claude Code, Codex, and more",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
@@ -29,6 +29,6 @@
|
||||
},
|
||||
"homepage": "https://zenlm.org",
|
||||
"dependencies": {
|
||||
"@hanzo/helper": "^1.0.5"
|
||||
"@hanzo/helper": "^1.0.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@zooai/helper",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Zoo CLI helper — sign in to Zoo and use its AI models in Claude Code, Codex, and more",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
@@ -28,6 +28,6 @@
|
||||
},
|
||||
"homepage": "https://zoo.ngo",
|
||||
"dependencies": {
|
||||
"@hanzo/helper": "^1.0.5"
|
||||
"@hanzo/helper": "^1.0.6"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hanzo/helper",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Hanzo CLI helper for API access, cloud services, MCP, and plugins",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hanzo/kms",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Standalone `kms` CLI — sign in with IAM and pull environment secrets for local dev",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
@@ -31,6 +31,6 @@
|
||||
},
|
||||
"homepage": "https://hanzo.ai",
|
||||
"dependencies": {
|
||||
"@hanzo/helper": "^1.0.5"
|
||||
"@hanzo/helper": "^1.0.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@ export const doctorCmd = new Command('doctor')
|
||||
.action(async () => {
|
||||
const checks: Check[] = [];
|
||||
|
||||
checks.push(await reachable('IAM', `${endpoints.iam}/health`));
|
||||
checks.push(await reachable('Cloud API', `${endpoints.api}/health`));
|
||||
// Probe the real endpoints the tool depends on (stable), not a bare /health
|
||||
// path (which varies by gateway config): IAM issuer discovery + the model list.
|
||||
checks.push(await reachable('IAM', `${endpoints.iam}/.well-known/openid-configuration`));
|
||||
checks.push(await reachable('Cloud API', `${endpoints.api}/v1/models`));
|
||||
|
||||
const { apiKey, user } = await getConfig();
|
||||
checks.push({
|
||||
|
||||
@@ -25,6 +25,9 @@ export interface Brand {
|
||||
clientId: string;
|
||||
/** Public web root — ecosystem install/download pages hang off it. */
|
||||
site: string;
|
||||
/** KMS host (secrets). KMS owns its own host; matches IAM's per-brand KMSHost
|
||||
* (iam cmd/iam/cli/init_apps.go brandSpecs). */
|
||||
kms: string;
|
||||
}
|
||||
|
||||
const BRANDS: Record<Brand['id'], Brand> = {
|
||||
@@ -36,6 +39,7 @@ const BRANDS: Record<Brand['id'], Brand> = {
|
||||
api: 'https://api.hanzo.ai',
|
||||
clientId: 'hanzo-app',
|
||||
site: 'https://hanzo.ai',
|
||||
kms: 'https://kms.hanzo.ai',
|
||||
},
|
||||
lux: {
|
||||
id: 'lux',
|
||||
@@ -45,6 +49,7 @@ const BRANDS: Record<Brand['id'], Brand> = {
|
||||
api: 'https://api.lux.network',
|
||||
clientId: 'lux-app',
|
||||
site: 'https://lux.network',
|
||||
kms: 'https://kms.lux.network',
|
||||
},
|
||||
zoo: {
|
||||
id: 'zoo',
|
||||
@@ -54,6 +59,7 @@ const BRANDS: Record<Brand['id'], Brand> = {
|
||||
api: 'https://api.zoo.ngo',
|
||||
clientId: 'zoo-app',
|
||||
site: 'https://zoo.ngo',
|
||||
kms: 'https://kms.zoo.network',
|
||||
},
|
||||
zen: {
|
||||
id: 'zen',
|
||||
@@ -63,6 +69,7 @@ const BRANDS: Record<Brand['id'], Brand> = {
|
||||
api: 'https://api.zenlm.org',
|
||||
clientId: 'zen-app',
|
||||
site: 'https://zenlm.org',
|
||||
kms: 'https://kms.zenlm.org',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,14 @@ export const endpoints = {
|
||||
get pricing(): string {
|
||||
return env('HANZO_PRICING_URL', `https://pricing.${new URL(brand.site).host}`);
|
||||
},
|
||||
/**
|
||||
* KMS — secrets, on its own host (`kms.<brand>`, per IAM's KMSHost). KMS is
|
||||
* NOT proxied under api.<brand>/v1/kms today, so target the dedicated host;
|
||||
* HANZO_KMS_URL overrides if a deployment fronts it elsewhere.
|
||||
*/
|
||||
get kms(): string {
|
||||
return env('HANZO_KMS_URL', brand.kms);
|
||||
},
|
||||
} as const;
|
||||
|
||||
/** IAM ops, all relative to the issuer base. */
|
||||
|
||||
+3
-2
@@ -10,7 +10,8 @@
|
||||
*
|
||||
* By KMS's design the bulk list returns KEYS ONLY; values are read one at a
|
||||
* time. `pullSecrets` composes the two: list the env, then read each value.
|
||||
* IAM lives under /v1/iam/*, KMS under /v1/kms/* — the helper never crosses them.
|
||||
* KMS runs on its own host (`kms.<brand>`, endpoints.kms) — it is not proxied
|
||||
* under api.<brand>/v1/kms — and IAM lives under /v1/iam/*; never crossed.
|
||||
*/
|
||||
|
||||
import { endpoints } from './endpoints';
|
||||
@@ -32,7 +33,7 @@ interface SecretMeta {
|
||||
env: string;
|
||||
}
|
||||
|
||||
const base = (org: string) => `${endpoints.api}/v1/kms/orgs/${encodeURIComponent(org)}/secrets`;
|
||||
const base = (org: string) => `${endpoints.kms}/v1/kms/orgs/${encodeURIComponent(org)}/secrets`;
|
||||
|
||||
const authFail = (res: Response, what: string): KmsError =>
|
||||
res.status === 401 || res.status === 403
|
||||
|
||||
Reference in New Issue
Block a user