@hasna/machines 0.0.34 → 0.0.35

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/dist/index.js CHANGED
@@ -10982,7 +10982,103 @@ var coerce = {
10982
10982
  date: (arg) => ZodDate.create({ ...arg, coerce: true })
10983
10983
  };
10984
10984
  var NEVER = INVALID;
10985
+ // src/redaction.ts
10986
+ var REDACTED_VALUE = "[redacted]";
10987
+ var SENSITIVE_KEY_PATTERN = /(password|passwd|token|credential|private[_-]?key|privateKey|api[_-]?key|github.*key|pem|secret)/i;
10988
+ var SECRET_REFERENCE_KEY_PATTERN = /(secret(ref(erence)?|key)?|secretRef|secretKey)$/i;
10989
+ var SENSITIVE_VALUE_PATTERNS = [
10990
+ /-----BEGIN [A-Z ]*PRIVATE KEY-----/,
10991
+ /\bghp_[A-Za-z0-9_]{20,}\b/,
10992
+ /\bgithub_pat_[A-Za-z0-9_]{20,}\b/,
10993
+ /\bxox[baprs]-[A-Za-z0-9-]{20,}\b/,
10994
+ /\bAKIA[0-9A-Z]{16}\b/,
10995
+ /\bsk-[A-Za-z0-9_-]{20,}\b/
10996
+ ];
10997
+ function isSensitiveKey(key) {
10998
+ return SENSITIVE_KEY_PATTERN.test(key);
10999
+ }
11000
+ function isSecretReferenceKey(key) {
11001
+ return SECRET_REFERENCE_KEY_PATTERN.test(key);
11002
+ }
11003
+ function looksSensitiveString(value) {
11004
+ return SENSITIVE_VALUE_PATTERNS.some((pattern) => pattern.test(value));
11005
+ }
11006
+ function isRecord(value) {
11007
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
11008
+ }
11009
+ function redactPath(value) {
11010
+ return value.replace(/\/home\/[^/\s]+/g, "/home/<user>").replace(/\/Users\/[^/\s]+/g, "/Users/<user>").replace(/[A-Za-z]:\\Users\\[^\\\s]+/g, "C:\\Users\\<user>");
11011
+ }
11012
+ function redactPrivateRef(value) {
11013
+ const trimmed = value.trim();
11014
+ const scheme = trimmed.match(/^([a-z][a-z0-9+.-]*:\/\/)/i);
11015
+ if (scheme)
11016
+ return `${scheme[1]}<redacted>`;
11017
+ const colon = trimmed.match(/^([a-z][a-z0-9+.-]*):/i);
11018
+ if (colon)
11019
+ return `${colon[1]}:<redacted>`;
11020
+ return "<private-manifest-ref:redacted>";
11021
+ }
11022
+ function redactIdentifier(value) {
11023
+ return value.replace(/[^a-zA-Z0-9_.-]/g, "_").slice(0, 80) || "adapter";
11024
+ }
11025
+ function redactSensitiveValue(value, key = "") {
11026
+ if (typeof value === "string") {
11027
+ if (isSensitiveKey(key) && !(isSecretReferenceKey(key) && !looksSensitiveString(value))) {
11028
+ return REDACTED_VALUE;
11029
+ }
11030
+ if (looksSensitiveString(value))
11031
+ return REDACTED_VALUE;
11032
+ return redactPath(value);
11033
+ }
11034
+ if (Array.isArray(value)) {
11035
+ return value.map((entry) => redactSensitiveValue(entry, key));
11036
+ }
11037
+ if (isRecord(value)) {
11038
+ const redacted = {};
11039
+ for (const [entryKey, entryValue] of Object.entries(value)) {
11040
+ redacted[entryKey] = redactSensitiveValue(entryValue, entryKey);
11041
+ }
11042
+ return redacted;
11043
+ }
11044
+ return value;
11045
+ }
11046
+ function publicMetadataKeys(metadata) {
11047
+ return Object.keys(metadata ?? {}).filter((key) => !isSensitiveKey(key)).sort();
11048
+ }
11049
+ function redactMetadata(metadata) {
11050
+ return redactSensitiveValue(metadata ?? {});
11051
+ }
11052
+ function redactManifestForDiagnostics(machine) {
11053
+ const metadata = redactMetadata(machine.metadata);
11054
+ for (const key of ["user", "username", "login"]) {
11055
+ if (typeof metadata[key] === "string")
11056
+ metadata[key] = REDACTED_VALUE;
11057
+ }
11058
+ return {
11059
+ id: machine.id,
11060
+ hostname: machine.hostname ? REDACTED_VALUE : undefined,
11061
+ sshAddress: machine.sshAddress ? REDACTED_VALUE : undefined,
11062
+ tailscaleName: machine.tailscaleName ? REDACTED_VALUE : undefined,
11063
+ platform: machine.platform,
11064
+ connection: machine.connection,
11065
+ workspacePath: redactPath(machine.workspacePath),
11066
+ bunPath: machine.bunPath ? redactPath(machine.bunPath) : undefined,
11067
+ tags: machine.tags ?? [],
11068
+ metadata,
11069
+ packages: machine.packages?.map((pkg) => ({ ...pkg })),
11070
+ apps: machine.apps?.map((app) => ({ ...app })),
11071
+ files: machine.files?.map((file) => ({
11072
+ ...file,
11073
+ source: redactPath(file.source),
11074
+ target: redactPath(file.target)
11075
+ }))
11076
+ };
11077
+ }
11078
+
10985
11079
  // src/manifests.ts
11080
+ var PRIVATE_MANIFEST_REF_ENV = "HASNA_MACHINES_PRIVATE_MANIFEST_REF";
11081
+ var PRIVATE_MANIFEST_BACKEND_ENV = "HASNA_MACHINES_PRIVATE_MANIFEST_BACKEND";
10986
11082
  var packageSchema = exports_external.object({
10987
11083
  name: exports_external.string(),
10988
11084
  manager: exports_external.enum(["bun", "brew", "apt", "custom"]).optional(),
@@ -11035,6 +11131,42 @@ function normalizePlatform() {
11035
11131
  function normalizeMachines(machines) {
11036
11132
  return [...machines].sort((left, right) => left.id.localeCompare(right.id));
11037
11133
  }
11134
+ function inferPrivateBackend(rawRef, explicitBackend) {
11135
+ if (explicitBackend?.trim())
11136
+ return explicitBackend.trim();
11137
+ const scheme = rawRef.trim().match(/^([a-z][a-z0-9+.-]*)(?::\/\/|:)/i);
11138
+ return scheme?.[1] ?? null;
11139
+ }
11140
+ function fileSourceRef(path) {
11141
+ return {
11142
+ kind: "file",
11143
+ ref: redactPath(path),
11144
+ backend: "file",
11145
+ private: false,
11146
+ publicSafe: true
11147
+ };
11148
+ }
11149
+ function privateSourceRef(rawRef, backend) {
11150
+ return {
11151
+ kind: "private-ref",
11152
+ ref: redactPrivateRef(rawRef),
11153
+ backend: inferPrivateBackend(rawRef, backend),
11154
+ private: true,
11155
+ publicSafe: true
11156
+ };
11157
+ }
11158
+ function privateRefFromOptions(options) {
11159
+ const env = options.env ?? process.env;
11160
+ return options.privateRef?.trim() || env[PRIVATE_MANIFEST_REF_ENV]?.trim() || env["MACHINES_PRIVATE_MANIFEST_REF"]?.trim() || null;
11161
+ }
11162
+ function getManifestSourceRef(options = {}) {
11163
+ const rawPrivateRef = privateRefFromOptions(options);
11164
+ if (rawPrivateRef) {
11165
+ const env = options.env ?? process.env;
11166
+ return privateSourceRef(rawPrivateRef, options.privateBackend ?? env[PRIVATE_MANIFEST_BACKEND_ENV]);
11167
+ }
11168
+ return fileSourceRef(options.path ?? getManifestPath());
11169
+ }
11038
11170
  function getDefaultManifest() {
11039
11171
  return {
11040
11172
  version: 1,
@@ -11049,6 +11181,53 @@ function readManifest(path = getManifestPath()) {
11049
11181
  const raw = JSON.parse(readFileSync(path, "utf8"));
11050
11182
  return fleetSchema.parse(raw);
11051
11183
  }
11184
+ function readManifestWithSource(options = {}) {
11185
+ const path = options.path ?? getManifestPath();
11186
+ const source = getManifestSourceRef(options);
11187
+ const warnings = [];
11188
+ if (source.kind === "private-ref") {
11189
+ const rawRef = privateRefFromOptions(options);
11190
+ if (rawRef && options.adapter) {
11191
+ try {
11192
+ const manifest2 = options.adapter.readManifest({ source, rawRef });
11193
+ if (manifest2) {
11194
+ return {
11195
+ manifest: fleetSchema.parse(manifest2),
11196
+ info: {
11197
+ source,
11198
+ loadedFrom: "private-ref",
11199
+ warnings
11200
+ }
11201
+ };
11202
+ }
11203
+ warnings.push(`private_manifest_adapter_empty:${redactIdentifier(options.adapter.id)}`);
11204
+ } catch (error) {
11205
+ warnings.push(`private_manifest_adapter_failed:${redactIdentifier(options.adapter.id)}`);
11206
+ }
11207
+ } else {
11208
+ warnings.push("private_manifest_ref_without_adapter");
11209
+ }
11210
+ const fallbackSource = fileSourceRef(path);
11211
+ const manifest = readManifest(path);
11212
+ return {
11213
+ manifest,
11214
+ info: {
11215
+ source,
11216
+ loadedFrom: existsSync2(path) ? "fallback" : "default",
11217
+ fallbackSource,
11218
+ warnings
11219
+ }
11220
+ };
11221
+ }
11222
+ return {
11223
+ manifest: readManifest(path),
11224
+ info: {
11225
+ source,
11226
+ loadedFrom: existsSync2(path) ? "file" : "default",
11227
+ warnings
11228
+ }
11229
+ };
11230
+ }
11052
11231
  function validateManifest(path = getManifestPath()) {
11053
11232
  return readManifest(path);
11054
11233
  }
@@ -11375,7 +11554,7 @@ function buildEntry(input) {
11375
11554
  },
11376
11555
  route_hints: hints,
11377
11556
  tags: manifest?.tags ?? [],
11378
- metadata: manifest?.metadata ?? {}
11557
+ metadata: redactMetadata(manifest?.metadata)
11379
11558
  };
11380
11559
  }
11381
11560
  function discoverMachineTopology(options = {}) {
@@ -11644,7 +11823,7 @@ function resolveMachineRoute(machineId, options = {}) {
11644
11823
  warnings
11645
11824
  };
11646
11825
  }
11647
- function isRecord(value) {
11826
+ function isRecord2(value) {
11648
11827
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
11649
11828
  }
11650
11829
  function metadataString(metadata, keys) {
@@ -11674,13 +11853,13 @@ function metadataStringArray(metadata, keys) {
11674
11853
  function readMappedPath(input) {
11675
11854
  for (const containerName of input.containers) {
11676
11855
  const container = input.metadata[containerName];
11677
- if (!isRecord(container))
11856
+ if (!isRecord2(container))
11678
11857
  continue;
11679
11858
  for (const key of input.keys) {
11680
11859
  const value = container[key];
11681
11860
  if (typeof value === "string" && value.trim())
11682
11861
  return value.trim();
11683
- if (isRecord(value)) {
11862
+ if (isRecord2(value)) {
11684
11863
  const path = metadataString(value, ["path", "root", "workspacePath", "workspace_path"]);
11685
11864
  if (path)
11686
11865
  return path;
@@ -11934,7 +12113,7 @@ function primaryMachine(machine, projectId, primaryMachineId) {
11934
12113
  return machine.tags.includes("primary");
11935
12114
  }
11936
12115
  function metadataKeysForDiagnostics(metadata) {
11937
- return Object.keys(metadata).filter((key) => !/(secret|token|key|password|credential)/i.test(key)).sort();
12116
+ return publicMetadataKeys(metadata);
11938
12117
  }
11939
12118
  function resolveMachineWorkspace(options) {
11940
12119
  const now = options.now ?? new Date;
@@ -12859,12 +13038,28 @@ function renderDomainMapping(domain) {
12859
13038
  };
12860
13039
  }
12861
13040
  // src/commands/doctor.ts
12862
- function makeCheck2(id, status, summary, detail) {
12863
- return { id, status, summary, detail };
13041
+ var DOCTOR_OPTIONAL_ADAPTER_DOMAINS = ["secrets", "configs", "monitor", "repos", "mcps", "shield"];
13042
+ function makeCheck2(id, status, summary, detail, extra = {}) {
13043
+ const { data, ...rest } = extra;
13044
+ return {
13045
+ ...rest,
13046
+ id,
13047
+ status,
13048
+ summary,
13049
+ detail,
13050
+ data: data ? redactSensitiveValue(data) : undefined
13051
+ };
12864
13052
  }
12865
13053
  function parseKeyValueOutput(stdout) {
12866
- return Object.fromEntries(stdout.trim().split(`
12867
- `).map((line) => line.split("=")).filter((parts) => parts.length === 2).map(([key, value]) => [key, value]));
13054
+ const result = {};
13055
+ for (const line of stdout.trim().split(`
13056
+ `)) {
13057
+ const index = line.indexOf("=");
13058
+ if (index <= 0)
13059
+ continue;
13060
+ result[line.slice(0, index)] = line.slice(index + 1);
13061
+ }
13062
+ return result;
12868
13063
  }
12869
13064
  function buildDoctorCommand() {
12870
13065
  return [
@@ -12872,9 +13067,11 @@ function buildDoctorCommand() {
12872
13067
  'manifest_path="${HASNA_MACHINES_MANIFEST_PATH:-$data_dir/machines.json}"',
12873
13068
  'db_path="${HASNA_MACHINES_DB_PATH:-$data_dir/machines.db}"',
12874
13069
  'notifications_path="${HASNA_MACHINES_NOTIFICATIONS_PATH:-$data_dir/notifications.json}"',
13070
+ `printf 'data_dir=%s\\n' "$data_dir"`,
12875
13071
  `printf 'manifest_path=%s\\n' "$manifest_path"`,
12876
13072
  `printf 'db_path=%s\\n' "$db_path"`,
12877
13073
  `printf 'notifications_path=%s\\n' "$notifications_path"`,
13074
+ `printf 'data_dir_exists=%s\\n' "$(test -d "$data_dir" && printf yes || printf no)"`,
12878
13075
  `printf 'manifest_exists=%s\\n' "$(test -e "$manifest_path" && printf yes || printf no)"`,
12879
13076
  `printf 'db_exists=%s\\n' "$(test -e "$db_path" && printf yes || printf no)"`,
12880
13077
  `printf 'notifications_exists=%s\\n' "$(test -e "$notifications_path" && printf yes || printf no)"`,
@@ -12885,28 +13082,115 @@ function buildDoctorCommand() {
12885
13082
  `printf 'machines_mcp=%s\\n' "$(command -v machines-mcp 2>/dev/null || printf missing)"`
12886
13083
  ].join("; ");
12887
13084
  }
12888
- function runDoctor(machineId = getLocalMachineId()) {
12889
- const manifest = readManifest();
13085
+ function fallbackAdapterCheck(domain) {
13086
+ return makeCheck2(`${domain}-adapter`, "ok", `Optional ${domain} adapter`, `No ${domain} adapter configured; skipped optional private integration check.`, {
13087
+ optional: true,
13088
+ source: "open-machines",
13089
+ data: { configured: false, fallback: true }
13090
+ });
13091
+ }
13092
+ function sanitizeAdapterCheck(check, domain, adapterId) {
13093
+ const safeAdapterId = redactIdentifier(adapterId);
13094
+ return makeCheck2(check.id.startsWith(`${domain}-`) || check.id.startsWith(`${domain}:`) ? check.id : `${domain}:${check.id}`, check.status, check.summary, String(redactSensitiveValue(check.detail)), {
13095
+ ...check,
13096
+ optional: check.optional ?? true,
13097
+ source: check.source ? String(redactSensitiveValue(check.source)) : `adapter:${safeAdapterId}`,
13098
+ data: check.data ? redactSensitiveValue(check.data) : undefined
13099
+ });
13100
+ }
13101
+ function runOptionalAdapterChecks(context, adapters) {
13102
+ const checks = [];
13103
+ for (const domain of DOCTOR_OPTIONAL_ADAPTER_DOMAINS) {
13104
+ const adapter2 = adapters.find((candidate) => candidate.checks?.[domain]);
13105
+ const hook = adapter2?.checks?.[domain];
13106
+ if (!adapter2 || !hook) {
13107
+ checks.push(fallbackAdapterCheck(domain));
13108
+ continue;
13109
+ }
13110
+ try {
13111
+ const result = hook(context);
13112
+ const domainChecks = Array.isArray(result) ? result : result ? [result] : [fallbackAdapterCheck(domain)];
13113
+ checks.push(...domainChecks.map((check) => sanitizeAdapterCheck(check, domain, adapter2.id)));
13114
+ } catch {
13115
+ const safeAdapterId = redactIdentifier(adapter2.id);
13116
+ checks.push(makeCheck2(`${domain}-adapter`, "warn", `Optional ${domain} adapter failed`, "Adapter failed; details are intentionally hidden to avoid leaking private refs or credentials.", {
13117
+ optional: true,
13118
+ source: `adapter:${safeAdapterId}`,
13119
+ data: { adapter: safeAdapterId, fallback: true }
13120
+ }));
13121
+ }
13122
+ }
13123
+ return checks;
13124
+ }
13125
+ function runDoctor(machineId = getLocalMachineId(), options = {}) {
13126
+ const now = options.now ?? new Date;
13127
+ const { manifest, info: manifestSource } = readManifestWithSource({ adapter: options.manifestAdapter ?? null });
12890
13128
  const commandChecks = runMachineCommand(machineId, buildDoctorCommand());
12891
13129
  const details = parseKeyValueOutput(commandChecks.stdout);
12892
13130
  const machineInManifest = manifest.machines.find((machine) => machine.id === machineId);
13131
+ const optionalAdapterChecks = options.includeOptionalAdapters === false ? [] : runOptionalAdapterChecks({
13132
+ machineId,
13133
+ manifest,
13134
+ manifestSource,
13135
+ commandDetails: details,
13136
+ now
13137
+ }, options.adapters ?? []);
12893
13138
  const checks = [
12894
- makeCheck2("manifest-entry", machineInManifest ? "ok" : "warn", machineInManifest ? "Machine exists in manifest" : "Machine missing from manifest", machineInManifest ? JSON.stringify(machineInManifest) : `No manifest entry for ${machineId}`),
12895
- makeCheck2("manifest-path", details["manifest_exists"] === "yes" ? "ok" : "warn", "Manifest path check", `${details["manifest_path"] || "unknown"} ${details["manifest_exists"] === "yes" ? "exists" : "missing"}`),
12896
- makeCheck2("db-path", details["db_exists"] === "yes" ? "ok" : "warn", "DB path check", `${details["db_path"] || "unknown"} ${details["db_exists"] === "yes" ? "exists" : "missing"}`),
12897
- makeCheck2("notifications-path", details["notifications_exists"] === "yes" ? "ok" : "warn", "Notifications path check", `${details["notifications_path"] || "unknown"} ${details["notifications_exists"] === "yes" ? "exists" : "missing"}`),
13139
+ makeCheck2("manifest-source", manifestSource.warnings.length > 0 ? "warn" : "ok", "Manifest source boundary", `${manifestSource.source.kind}:${manifestSource.source.ref} loaded from ${manifestSource.loadedFrom}`, {
13140
+ data: {
13141
+ source: manifestSource.source,
13142
+ loadedFrom: manifestSource.loadedFrom,
13143
+ fallbackSource: manifestSource.fallbackSource,
13144
+ warnings: manifestSource.warnings
13145
+ },
13146
+ remediation: manifestSource.warnings.length > 0 ? ["Provide a private manifest adapter or unset the private manifest ref to use the local manifest only."] : undefined
13147
+ }),
13148
+ makeCheck2("manifest-entry", machineInManifest ? "ok" : "warn", machineInManifest ? "Machine exists in manifest" : "Machine missing from manifest", machineInManifest ? JSON.stringify(redactManifestForDiagnostics(machineInManifest)) : `No manifest entry for ${machineId}`, {
13149
+ data: {
13150
+ declared: Boolean(machineInManifest),
13151
+ machine: machineInManifest ? redactManifestForDiagnostics(machineInManifest) : null
13152
+ }
13153
+ }),
13154
+ makeCheck2("data-dir", details["data_dir_exists"] === "yes" ? "ok" : "warn", "Data directory check", `${redactPath(details["data_dir"] || "unknown")} ${details["data_dir_exists"] === "yes" ? "exists" : "missing"}`, {
13155
+ data: {
13156
+ path: redactPath(details["data_dir"] || "unknown"),
13157
+ exists: details["data_dir_exists"] === "yes"
13158
+ }
13159
+ }),
13160
+ makeCheck2("manifest-path", details["manifest_exists"] === "yes" ? "ok" : "warn", "Manifest path check", `${redactPath(details["manifest_path"] || "unknown")} ${details["manifest_exists"] === "yes" ? "exists" : "missing"}`, {
13161
+ data: {
13162
+ path: redactPath(details["manifest_path"] || "unknown"),
13163
+ exists: details["manifest_exists"] === "yes"
13164
+ }
13165
+ }),
13166
+ makeCheck2("db-path", details["db_exists"] === "yes" ? "ok" : "warn", "DB path check", `${redactPath(details["db_path"] || "unknown")} ${details["db_exists"] === "yes" ? "exists" : "missing"}`, {
13167
+ data: {
13168
+ path: redactPath(details["db_path"] || "unknown"),
13169
+ exists: details["db_exists"] === "yes"
13170
+ }
13171
+ }),
13172
+ makeCheck2("notifications-path", details["notifications_exists"] === "yes" ? "ok" : "warn", "Notifications path check", `${redactPath(details["notifications_path"] || "unknown")} ${details["notifications_exists"] === "yes" ? "exists" : "missing"}`, {
13173
+ data: {
13174
+ path: redactPath(details["notifications_path"] || "unknown"),
13175
+ exists: details["notifications_exists"] === "yes"
13176
+ }
13177
+ }),
12898
13178
  makeCheck2("bun", details["bun"] && details["bun"] !== "missing" ? "ok" : "fail", "Bun availability", details["bun"] || "missing"),
12899
13179
  makeCheck2("machines-cli", details["machines"] && details["machines"] !== "missing" ? "ok" : "warn", "machines CLI availability", details["machines"] || "missing"),
12900
13180
  makeCheck2("machines-agent-cli", details["machines_agent"] && details["machines_agent"] !== "missing" ? "ok" : "warn", "machines-agent availability", details["machines_agent"] || "missing"),
12901
13181
  makeCheck2("machines-mcp-cli", details["machines_mcp"] && details["machines_mcp"] !== "missing" ? "ok" : "warn", "machines-mcp availability", details["machines_mcp"] || "missing"),
12902
- makeCheck2("ssh", details["ssh"] === "ok" ? "ok" : "warn", "SSH availability", details["ssh"] || "missing")
13182
+ makeCheck2("ssh", details["ssh"] === "ok" ? "ok" : "warn", "SSH availability", details["ssh"] || "missing"),
13183
+ ...optionalAdapterChecks
12903
13184
  ];
12904
13185
  return {
12905
13186
  machineId,
12906
13187
  source: commandChecks.source,
12907
- manifestPath: details["manifest_path"],
12908
- dbPath: details["db_path"],
12909
- notificationsPath: details["notifications_path"],
13188
+ schemaVersion: 1,
13189
+ generatedAt: now.toISOString(),
13190
+ manifestSource,
13191
+ manifestPath: details["manifest_path"] ? redactPath(details["manifest_path"]) : undefined,
13192
+ dbPath: details["db_path"] ? redactPath(details["db_path"]) : undefined,
13193
+ notificationsPath: details["notifications_path"] ? redactPath(details["notifications_path"]) : undefined,
12910
13194
  checks
12911
13195
  };
12912
13196
  }
@@ -14320,20 +14604,20 @@ function runSync(machineId, options = {}, runner = runMachineCommand) {
14320
14604
  return summary;
14321
14605
  }
14322
14606
  // src/commands/workspace.ts
14323
- function isRecord2(value) {
14607
+ function isRecord3(value) {
14324
14608
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
14325
14609
  }
14326
14610
  function cloneMetadata(metadata) {
14327
- return isRecord2(metadata) ? { ...metadata } : {};
14611
+ return isRecord3(metadata) ? { ...metadata } : {};
14328
14612
  }
14329
14613
  function mappedPath(metadata, field, key) {
14330
14614
  const container = metadata[field];
14331
- if (!isRecord2(container))
14615
+ if (!isRecord3(container))
14332
14616
  return null;
14333
14617
  const value = container[key];
14334
14618
  if (typeof value === "string" && value.trim())
14335
14619
  return value.trim();
14336
- if (isRecord2(value)) {
14620
+ if (isRecord3(value)) {
14337
14621
  const nested = value["path"] ?? value["root"] ?? value["workspacePath"] ?? value["workspace_path"];
14338
14622
  if (typeof nested === "string" && nested.trim())
14339
14623
  return nested.trim();
@@ -14342,7 +14626,7 @@ function mappedPath(metadata, field, key) {
14342
14626
  }
14343
14627
  function writeMappedPath(metadata, field, key, path) {
14344
14628
  const existing = metadata[field];
14345
- const container = isRecord2(existing) ? { ...existing } : {};
14629
+ const container = isRecord3(existing) ? { ...existing } : {};
14346
14630
  container[key] = path;
14347
14631
  metadata[field] = container;
14348
14632
  }
@@ -23696,10 +23980,18 @@ export {
23696
23980
  renderDomainMapping,
23697
23981
  renderDashboardHtml,
23698
23982
  removeNotificationChannel,
23983
+ redactSensitiveValue,
23984
+ redactPrivateRef,
23985
+ redactPath,
23986
+ redactMetadata,
23987
+ redactManifestForDiagnostics,
23988
+ redactIdentifier,
23699
23989
  recordSyncRun,
23700
23990
  recordSetupRun,
23701
23991
  readNotificationConfig,
23992
+ readManifestWithSource,
23702
23993
  readManifest,
23994
+ publicMetadataKeys,
23703
23995
  probeTmuxPane,
23704
23996
  parseStorageTables,
23705
23997
  parsePortOutput,
@@ -23717,6 +24009,7 @@ export {
23717
24009
  listHeartbeats,
23718
24010
  listDomainMappings,
23719
24011
  listApps,
24012
+ isSensitiveKey,
23720
24013
  getSyncMetaAll,
23721
24014
  getStorageStatus,
23722
24015
  getStoragePg,
@@ -23728,6 +24021,7 @@ export {
23728
24021
  getServeInfo,
23729
24022
  getPackageVersion,
23730
24023
  getNotificationsPath,
24024
+ getManifestSourceRef,
23731
24025
  getManifestPath,
23732
24026
  getManifestMachine,
23733
24027
  getMachinesConsumerCapabilities,
@@ -23779,6 +24073,9 @@ export {
23779
24073
  STORAGE_MODE_ENV,
23780
24074
  STORAGE_DATABASE_ENV,
23781
24075
  SCREEN_SECRET_NAMESPACE_ENV,
24076
+ REDACTED_VALUE,
24077
+ PRIVATE_MANIFEST_REF_ENV,
24078
+ PRIVATE_MANIFEST_BACKEND_ENV,
23782
24079
  MACHINE_MCP_TOOL_NAMES,
23783
24080
  MACHINES_STORAGE_TABLES,
23784
24081
  MACHINES_STORAGE_MODE_FALLBACK_ENV,
@@ -23797,6 +24094,7 @@ export {
23797
24094
  MACHINES_BACKUP_PREFIX_ENV,
23798
24095
  MACHINES_BACKUP_BUCKET_FALLBACK_ENV,
23799
24096
  MACHINES_BACKUP_BUCKET_ENV,
24097
+ DOCTOR_OPTIONAL_ADAPTER_DOMAINS,
23800
24098
  DEFAULT_SCREEN_SECRET_NAMESPACE,
23801
24099
  DEFAULT_MACHINE_RESOLVER_TTL_MS,
23802
24100
  DEFAULT_BACKUP_PREFIX,
@@ -1,5 +1,21 @@
1
1
  import { z } from "zod";
2
- import type { FleetManifest, MachineManifest } from "./types.js";
2
+ import type { FleetManifest, MachineManifest, ManifestLoadInfo, ManifestSourceRef } from "./types.js";
3
+ export declare const PRIVATE_MANIFEST_REF_ENV = "HASNA_MACHINES_PRIVATE_MANIFEST_REF";
4
+ export declare const PRIVATE_MANIFEST_BACKEND_ENV = "HASNA_MACHINES_PRIVATE_MANIFEST_BACKEND";
5
+ export interface ManifestSourceAdapter {
6
+ id: string;
7
+ readManifest(input: {
8
+ source: ManifestSourceRef;
9
+ rawRef: string;
10
+ }): FleetManifest | null | undefined;
11
+ }
12
+ export interface ReadManifestWithSourceOptions {
13
+ path?: string;
14
+ env?: NodeJS.ProcessEnv;
15
+ privateRef?: string;
16
+ privateBackend?: string;
17
+ adapter?: ManifestSourceAdapter | null;
18
+ }
3
19
  export declare const machineSchema: z.ZodObject<{
4
20
  id: z.ZodString;
5
21
  hostname: z.ZodOptional<z.ZodString>;
@@ -270,8 +286,13 @@ export declare const fleetSchema: z.ZodObject<{
270
286
  version: 1;
271
287
  generatedAt?: string | undefined;
272
288
  }>;
289
+ export declare function getManifestSourceRef(options?: ReadManifestWithSourceOptions): ManifestSourceRef;
273
290
  export declare function getDefaultManifest(): FleetManifest;
274
291
  export declare function readManifest(path?: string): FleetManifest;
292
+ export declare function readManifestWithSource(options?: ReadManifestWithSourceOptions): {
293
+ manifest: FleetManifest;
294
+ info: ManifestLoadInfo;
295
+ };
275
296
  export declare function validateManifest(path?: string): FleetManifest;
276
297
  export declare function writeManifest(manifest: FleetManifest, path?: string): string;
277
298
  export declare function getManifestMachine(machineId: string, path?: string): MachineManifest | null;
@@ -1 +1 @@
1
- {"version":3,"file":"manifests.d.ts","sourceRoot":"","sources":["../src/manifests.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAoBjE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAcxB,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAItB,CAAC;AAoBH,wBAAgB,kBAAkB,IAAI,aAAa,CAMlD;AAED,wBAAgB,YAAY,CAAC,IAAI,SAAoB,GAAG,aAAa,CAMpE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,SAAoB,GAAG,aAAa,CAExE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,SAAoB,GAAG,MAAM,CAWvF;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,SAAoB,GAAG,eAAe,GAAG,IAAI,CAEtG;AAED,wBAAgB,4BAA4B,IAAI,eAAe,CAiB9D"}
1
+ {"version":3,"file":"manifests.d.ts","sourceRoot":"","sources":["../src/manifests.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtG,eAAO,MAAM,wBAAwB,wCAAwC,CAAC;AAC9E,eAAO,MAAM,4BAA4B,4CAA4C,CAAC;AAEtF,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;CACtG;AAED,MAAM,WAAW,6BAA6B;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACxC;AAoBD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAcxB,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAItB,CAAC;AAsDH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,6BAAkC,GAAG,iBAAiB,CAOnG;AAED,wBAAgB,kBAAkB,IAAI,aAAa,CAMlD;AAED,wBAAgB,YAAY,CAAC,IAAI,SAAoB,GAAG,aAAa,CAMpE;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,6BAAkC,GAAG;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAiDvI;AAED,wBAAgB,gBAAgB,CAAC,IAAI,SAAoB,GAAG,aAAa,CAExE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,SAAoB,GAAG,MAAM,CAWvF;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,SAAoB,GAAG,eAAe,GAAG,IAAI,CAEtG;AAED,wBAAgB,4BAA4B,IAAI,eAAe,CAiB9D"}