@kody-ade/kody-engine 0.4.123 → 0.4.124

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.
Files changed (2) hide show
  1. package/dist/bin/kody.js +103 -122
  2. package/package.json +1 -1
package/dist/bin/kody.js CHANGED
@@ -880,7 +880,7 @@ var init_loadPriorArt = __esm({
880
880
  // package.json
881
881
  var package_default = {
882
882
  name: "@kody-ade/kody-engine",
883
- version: "0.4.123",
883
+ version: "0.4.124",
884
884
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
885
885
  license: "MIT",
886
886
  type: "module",
@@ -8540,107 +8540,6 @@ init_loadPriorArt();
8540
8540
  import * as fs34 from "fs";
8541
8541
  import * as path33 from "path";
8542
8542
 
8543
- // src/pool/keys.ts
8544
- import { hkdfSync } from "crypto";
8545
- var POOL_API_KEY_INFO = "kody-pool-api:v1";
8546
- var RUNNER_API_KEY_INFO = "kody-runner-api:v1";
8547
- function masterKeyBytes(raw) {
8548
- const v = raw.trim();
8549
- if (!v) throw new Error("KODY_MASTER_KEY is empty");
8550
- if (/^[0-9a-fA-F]+$/.test(v) && v.length === 64) {
8551
- return Buffer.from(v, "hex");
8552
- }
8553
- return Buffer.from(v.replace(/-/g, "+").replace(/_/g, "/"), "base64");
8554
- }
8555
- function deriveKey(master, info, length = 32) {
8556
- return Buffer.from(hkdfSync("sha256", master, Buffer.alloc(0), info, length)).toString("hex");
8557
- }
8558
- function derivePoolApiKey(master) {
8559
- return deriveKey(master, POOL_API_KEY_INFO);
8560
- }
8561
- function deriveRunnerApiKey(master) {
8562
- return deriveKey(master, RUNNER_API_KEY_INFO);
8563
- }
8564
- function bearerOk(headerAuth, xApiKey, expected) {
8565
- const x = (xApiKey ?? "").trim();
8566
- if (x && timingEqual(x, expected)) return true;
8567
- const a = (headerAuth ?? "").trim();
8568
- if (a.toLowerCase().startsWith("bearer ")) {
8569
- return timingEqual(a.slice(7).trim(), expected);
8570
- }
8571
- return false;
8572
- }
8573
- function timingEqual(a, b) {
8574
- if (a.length !== b.length) return false;
8575
- let diff = 0;
8576
- for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
8577
- return diff === 0;
8578
- }
8579
-
8580
- // src/pool/vault.ts
8581
- import { createDecipheriv } from "crypto";
8582
- var GITHUB_API = "https://api.github.com";
8583
- var VAULT_PATH = ".kody/secrets.enc";
8584
- var CACHE_TTL_MS = 6e4;
8585
- var cache = /* @__PURE__ */ new Map();
8586
- function decryptVault(payload, masterKey) {
8587
- const parts = payload.split(":");
8588
- if (parts.length !== 4 || parts[0] !== "v1") {
8589
- throw new Error("invalid vault payload format");
8590
- }
8591
- const [, ivB64, ctB64, tagB64] = parts;
8592
- const iv = Buffer.from(ivB64, "base64");
8593
- const ct = Buffer.from(ctB64, "base64");
8594
- const tag = Buffer.from(tagB64, "base64");
8595
- const decipher = createDecipheriv("aes-256-gcm", masterKey, iv);
8596
- decipher.setAuthTag(tag);
8597
- return Buffer.concat([decipher.update(ct), decipher.final()]).toString("utf8");
8598
- }
8599
- async function readVaultSecrets(opts) {
8600
- const key = `${opts.owner}/${opts.repo}`.toLowerCase();
8601
- const hit = cache.get(key);
8602
- if (hit && hit.expiresAt > Date.now()) return hit.secrets;
8603
- const doFetch = opts.fetchImpl ?? fetch;
8604
- const res = await doFetch(
8605
- `${GITHUB_API}/repos/${encodeURIComponent(opts.owner)}/${encodeURIComponent(opts.repo)}/contents/${VAULT_PATH}`,
8606
- {
8607
- headers: {
8608
- Authorization: `Bearer ${opts.githubToken}`,
8609
- Accept: "application/vnd.github+json",
8610
- "User-Agent": "kody-pool-serve"
8611
- }
8612
- }
8613
- );
8614
- if (res.status === 404) {
8615
- cache.set(key, { secrets: {}, expiresAt: Date.now() + CACHE_TTL_MS });
8616
- return {};
8617
- }
8618
- if (!res.ok) {
8619
- throw new Error(`vault read ${res.status} for ${key}: ${(await res.text().catch(() => "")).slice(0, 160)}`);
8620
- }
8621
- const body = await res.json();
8622
- if (!body.content) {
8623
- cache.set(key, { secrets: {}, expiresAt: Date.now() + CACHE_TTL_MS });
8624
- return {};
8625
- }
8626
- const ciphertext = Buffer.from(body.content, body.encoding ?? "base64").toString("utf8").trim();
8627
- const doc = JSON.parse(decryptVault(ciphertext, opts.masterKey));
8628
- const flat = {};
8629
- for (const [name, entry] of Object.entries(doc.secrets ?? {})) {
8630
- if (entry && typeof entry.value === "string") flat[name] = entry.value;
8631
- }
8632
- cache.set(key, { secrets: flat, expiresAt: Date.now() + CACHE_TTL_MS });
8633
- return flat;
8634
- }
8635
- async function readRepoSecret(opts) {
8636
- const secrets = await readVaultSecrets(opts);
8637
- const v = secrets[opts.name];
8638
- return v && v.trim() ? v : null;
8639
- }
8640
- async function readRepoSecrets(opts) {
8641
- return readVaultSecrets(opts);
8642
- }
8643
-
8644
8543
  // src/scripts/kodyVariables.ts
8645
8544
  import * as fs33 from "fs";
8646
8545
  import * as path32 from "path";
@@ -8667,26 +8566,7 @@ function readKodyVariables(cwd) {
8667
8566
  }
8668
8567
 
8669
8568
  // src/scripts/loadQaContext.ts
8670
- var VAULT_REL_PATH = ".kody/secrets.enc";
8671
8569
  var PROFILE_DIR_REL_PATH = ".kody/profile";
8672
- function readVaultPassword(cwd) {
8673
- const rawKey = process.env.KODY_MASTER_KEY;
8674
- if (!rawKey) return "";
8675
- const vaultPath = path33.join(cwd, VAULT_REL_PATH);
8676
- if (!fs34.existsSync(vaultPath)) return "";
8677
- try {
8678
- const payload = fs34.readFileSync(vaultPath, "utf-8").trim();
8679
- const doc = JSON.parse(decryptVault(payload, masterKeyBytes(rawKey)));
8680
- const entry = doc.secrets?.LOGIN_PASSWORD;
8681
- if (entry && typeof entry.value === "string" && entry.value.length > 0) return entry.value;
8682
- return "";
8683
- } catch (err) {
8684
- const msg = err instanceof Error ? err.message : String(err);
8685
- process.stderr.write(`[loadQaContext] could not read LOGIN_PASSWORD from vault: ${msg}
8686
- `);
8687
- return "";
8688
- }
8689
- }
8690
8570
  function readProfile(cwd) {
8691
8571
  const dir = path33.join(cwd, PROFILE_DIR_REL_PATH);
8692
8572
  if (!fs34.existsSync(dir)) return "";
@@ -8723,7 +8603,7 @@ function composeAuthBlock(authProfile, login, password) {
8723
8603
  var loadQaContext = async (ctx) => {
8724
8604
  const vars = readKodyVariables(ctx.cwd);
8725
8605
  const login = vars.LOGIN_USER ?? "";
8726
- const password = readVaultPassword(ctx.cwd);
8606
+ const password = process.env.LOGIN_PASSWORD ?? "";
8727
8607
  const authProfile = ctx.args.authProfile;
8728
8608
  ctx.data.qaLogin = login;
8729
8609
  ctx.data.qaProfile = readProfile(ctx.cwd);
@@ -9671,6 +9551,70 @@ function errMsg2(err) {
9671
9551
  return err instanceof Error ? err.message : String(err);
9672
9552
  }
9673
9553
 
9554
+ // src/pool/vault.ts
9555
+ import { createDecipheriv } from "crypto";
9556
+ var GITHUB_API = "https://api.github.com";
9557
+ var VAULT_PATH = ".kody/secrets.enc";
9558
+ var CACHE_TTL_MS = 6e4;
9559
+ var cache = /* @__PURE__ */ new Map();
9560
+ function decryptVault(payload, masterKey) {
9561
+ const parts = payload.split(":");
9562
+ if (parts.length !== 4 || parts[0] !== "v1") {
9563
+ throw new Error("invalid vault payload format");
9564
+ }
9565
+ const [, ivB64, ctB64, tagB64] = parts;
9566
+ const iv = Buffer.from(ivB64, "base64");
9567
+ const ct = Buffer.from(ctB64, "base64");
9568
+ const tag = Buffer.from(tagB64, "base64");
9569
+ const decipher = createDecipheriv("aes-256-gcm", masterKey, iv);
9570
+ decipher.setAuthTag(tag);
9571
+ return Buffer.concat([decipher.update(ct), decipher.final()]).toString("utf8");
9572
+ }
9573
+ async function readVaultSecrets(opts) {
9574
+ const key = `${opts.owner}/${opts.repo}`.toLowerCase();
9575
+ const hit = cache.get(key);
9576
+ if (hit && hit.expiresAt > Date.now()) return hit.secrets;
9577
+ const doFetch = opts.fetchImpl ?? fetch;
9578
+ const res = await doFetch(
9579
+ `${GITHUB_API}/repos/${encodeURIComponent(opts.owner)}/${encodeURIComponent(opts.repo)}/contents/${VAULT_PATH}`,
9580
+ {
9581
+ headers: {
9582
+ Authorization: `Bearer ${opts.githubToken}`,
9583
+ Accept: "application/vnd.github+json",
9584
+ "User-Agent": "kody-pool-serve"
9585
+ }
9586
+ }
9587
+ );
9588
+ if (res.status === 404) {
9589
+ cache.set(key, { secrets: {}, expiresAt: Date.now() + CACHE_TTL_MS });
9590
+ return {};
9591
+ }
9592
+ if (!res.ok) {
9593
+ throw new Error(`vault read ${res.status} for ${key}: ${(await res.text().catch(() => "")).slice(0, 160)}`);
9594
+ }
9595
+ const body = await res.json();
9596
+ if (!body.content) {
9597
+ cache.set(key, { secrets: {}, expiresAt: Date.now() + CACHE_TTL_MS });
9598
+ return {};
9599
+ }
9600
+ const ciphertext = Buffer.from(body.content, body.encoding ?? "base64").toString("utf8").trim();
9601
+ const doc = JSON.parse(decryptVault(ciphertext, opts.masterKey));
9602
+ const flat = {};
9603
+ for (const [name, entry] of Object.entries(doc.secrets ?? {})) {
9604
+ if (entry && typeof entry.value === "string") flat[name] = entry.value;
9605
+ }
9606
+ cache.set(key, { secrets: flat, expiresAt: Date.now() + CACHE_TTL_MS });
9607
+ return flat;
9608
+ }
9609
+ async function readRepoSecret(opts) {
9610
+ const secrets = await readVaultSecrets(opts);
9611
+ const v = secrets[opts.name];
9612
+ return v && v.trim() ? v : null;
9613
+ }
9614
+ async function readRepoSecrets(opts) {
9615
+ return readVaultSecrets(opts);
9616
+ }
9617
+
9674
9618
  // src/pool/registry.ts
9675
9619
  var POOL_MIN_VAULT_KEY = "POOL_MIN";
9676
9620
  var POOL_MIN_MAX = 10;
@@ -9800,6 +9744,43 @@ var PoolRegistry = class {
9800
9744
  }
9801
9745
  };
9802
9746
 
9747
+ // src/pool/keys.ts
9748
+ import { hkdfSync } from "crypto";
9749
+ var POOL_API_KEY_INFO = "kody-pool-api:v1";
9750
+ var RUNNER_API_KEY_INFO = "kody-runner-api:v1";
9751
+ function masterKeyBytes(raw) {
9752
+ const v = raw.trim();
9753
+ if (!v) throw new Error("KODY_MASTER_KEY is empty");
9754
+ if (/^[0-9a-fA-F]+$/.test(v) && v.length === 64) {
9755
+ return Buffer.from(v, "hex");
9756
+ }
9757
+ return Buffer.from(v.replace(/-/g, "+").replace(/_/g, "/"), "base64");
9758
+ }
9759
+ function deriveKey(master, info, length = 32) {
9760
+ return Buffer.from(hkdfSync("sha256", master, Buffer.alloc(0), info, length)).toString("hex");
9761
+ }
9762
+ function derivePoolApiKey(master) {
9763
+ return deriveKey(master, POOL_API_KEY_INFO);
9764
+ }
9765
+ function deriveRunnerApiKey(master) {
9766
+ return deriveKey(master, RUNNER_API_KEY_INFO);
9767
+ }
9768
+ function bearerOk(headerAuth, xApiKey, expected) {
9769
+ const x = (xApiKey ?? "").trim();
9770
+ if (x && timingEqual(x, expected)) return true;
9771
+ const a = (headerAuth ?? "").trim();
9772
+ if (a.toLowerCase().startsWith("bearer ")) {
9773
+ return timingEqual(a.slice(7).trim(), expected);
9774
+ }
9775
+ return false;
9776
+ }
9777
+ function timingEqual(a, b) {
9778
+ if (a.length !== b.length) return false;
9779
+ let diff = 0;
9780
+ for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
9781
+ return diff === 0;
9782
+ }
9783
+
9803
9784
  // src/scripts/poolServe.ts
9804
9785
  var PERF_GUEST = {
9805
9786
  low: { cpu_kind: "shared", cpus: 2, memory_mb: 2048 },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.123",
3
+ "version": "0.4.124",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",