@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/consumer.js CHANGED
@@ -4186,7 +4186,103 @@ var coerce = {
4186
4186
  date: (arg) => ZodDate.create({ ...arg, coerce: true })
4187
4187
  };
4188
4188
  var NEVER = INVALID;
4189
+ // src/redaction.ts
4190
+ var REDACTED_VALUE = "[redacted]";
4191
+ var SENSITIVE_KEY_PATTERN = /(password|passwd|token|credential|private[_-]?key|privateKey|api[_-]?key|github.*key|pem|secret)/i;
4192
+ var SECRET_REFERENCE_KEY_PATTERN = /(secret(ref(erence)?|key)?|secretRef|secretKey)$/i;
4193
+ var SENSITIVE_VALUE_PATTERNS = [
4194
+ /-----BEGIN [A-Z ]*PRIVATE KEY-----/,
4195
+ /\bghp_[A-Za-z0-9_]{20,}\b/,
4196
+ /\bgithub_pat_[A-Za-z0-9_]{20,}\b/,
4197
+ /\bxox[baprs]-[A-Za-z0-9-]{20,}\b/,
4198
+ /\bAKIA[0-9A-Z]{16}\b/,
4199
+ /\bsk-[A-Za-z0-9_-]{20,}\b/
4200
+ ];
4201
+ function isSensitiveKey(key) {
4202
+ return SENSITIVE_KEY_PATTERN.test(key);
4203
+ }
4204
+ function isSecretReferenceKey(key) {
4205
+ return SECRET_REFERENCE_KEY_PATTERN.test(key);
4206
+ }
4207
+ function looksSensitiveString(value) {
4208
+ return SENSITIVE_VALUE_PATTERNS.some((pattern) => pattern.test(value));
4209
+ }
4210
+ function isRecord(value) {
4211
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4212
+ }
4213
+ function redactPath(value) {
4214
+ return value.replace(/\/home\/[^/\s]+/g, "/home/<user>").replace(/\/Users\/[^/\s]+/g, "/Users/<user>").replace(/[A-Za-z]:\\Users\\[^\\\s]+/g, "C:\\Users\\<user>");
4215
+ }
4216
+ function redactPrivateRef(value) {
4217
+ const trimmed = value.trim();
4218
+ const scheme = trimmed.match(/^([a-z][a-z0-9+.-]*:\/\/)/i);
4219
+ if (scheme)
4220
+ return `${scheme[1]}<redacted>`;
4221
+ const colon = trimmed.match(/^([a-z][a-z0-9+.-]*):/i);
4222
+ if (colon)
4223
+ return `${colon[1]}:<redacted>`;
4224
+ return "<private-manifest-ref:redacted>";
4225
+ }
4226
+ function redactIdentifier(value) {
4227
+ return value.replace(/[^a-zA-Z0-9_.-]/g, "_").slice(0, 80) || "adapter";
4228
+ }
4229
+ function redactSensitiveValue(value, key = "") {
4230
+ if (typeof value === "string") {
4231
+ if (isSensitiveKey(key) && !(isSecretReferenceKey(key) && !looksSensitiveString(value))) {
4232
+ return REDACTED_VALUE;
4233
+ }
4234
+ if (looksSensitiveString(value))
4235
+ return REDACTED_VALUE;
4236
+ return redactPath(value);
4237
+ }
4238
+ if (Array.isArray(value)) {
4239
+ return value.map((entry) => redactSensitiveValue(entry, key));
4240
+ }
4241
+ if (isRecord(value)) {
4242
+ const redacted = {};
4243
+ for (const [entryKey, entryValue] of Object.entries(value)) {
4244
+ redacted[entryKey] = redactSensitiveValue(entryValue, entryKey);
4245
+ }
4246
+ return redacted;
4247
+ }
4248
+ return value;
4249
+ }
4250
+ function publicMetadataKeys(metadata) {
4251
+ return Object.keys(metadata ?? {}).filter((key) => !isSensitiveKey(key)).sort();
4252
+ }
4253
+ function redactMetadata(metadata) {
4254
+ return redactSensitiveValue(metadata ?? {});
4255
+ }
4256
+ function redactManifestForDiagnostics(machine) {
4257
+ const metadata = redactMetadata(machine.metadata);
4258
+ for (const key of ["user", "username", "login"]) {
4259
+ if (typeof metadata[key] === "string")
4260
+ metadata[key] = REDACTED_VALUE;
4261
+ }
4262
+ return {
4263
+ id: machine.id,
4264
+ hostname: machine.hostname ? REDACTED_VALUE : undefined,
4265
+ sshAddress: machine.sshAddress ? REDACTED_VALUE : undefined,
4266
+ tailscaleName: machine.tailscaleName ? REDACTED_VALUE : undefined,
4267
+ platform: machine.platform,
4268
+ connection: machine.connection,
4269
+ workspacePath: redactPath(machine.workspacePath),
4270
+ bunPath: machine.bunPath ? redactPath(machine.bunPath) : undefined,
4271
+ tags: machine.tags ?? [],
4272
+ metadata,
4273
+ packages: machine.packages?.map((pkg) => ({ ...pkg })),
4274
+ apps: machine.apps?.map((app) => ({ ...app })),
4275
+ files: machine.files?.map((file) => ({
4276
+ ...file,
4277
+ source: redactPath(file.source),
4278
+ target: redactPath(file.target)
4279
+ }))
4280
+ };
4281
+ }
4282
+
4189
4283
  // src/manifests.ts
4284
+ var PRIVATE_MANIFEST_REF_ENV = "HASNA_MACHINES_PRIVATE_MANIFEST_REF";
4285
+ var PRIVATE_MANIFEST_BACKEND_ENV = "HASNA_MACHINES_PRIVATE_MANIFEST_BACKEND";
4190
4286
  var packageSchema = exports_external.object({
4191
4287
  name: exports_external.string(),
4192
4288
  manager: exports_external.enum(["bun", "brew", "apt", "custom"]).optional(),
@@ -4239,6 +4335,42 @@ function normalizePlatform() {
4239
4335
  function normalizeMachines(machines) {
4240
4336
  return [...machines].sort((left, right) => left.id.localeCompare(right.id));
4241
4337
  }
4338
+ function inferPrivateBackend(rawRef, explicitBackend) {
4339
+ if (explicitBackend?.trim())
4340
+ return explicitBackend.trim();
4341
+ const scheme = rawRef.trim().match(/^([a-z][a-z0-9+.-]*)(?::\/\/|:)/i);
4342
+ return scheme?.[1] ?? null;
4343
+ }
4344
+ function fileSourceRef(path) {
4345
+ return {
4346
+ kind: "file",
4347
+ ref: redactPath(path),
4348
+ backend: "file",
4349
+ private: false,
4350
+ publicSafe: true
4351
+ };
4352
+ }
4353
+ function privateSourceRef(rawRef, backend) {
4354
+ return {
4355
+ kind: "private-ref",
4356
+ ref: redactPrivateRef(rawRef),
4357
+ backend: inferPrivateBackend(rawRef, backend),
4358
+ private: true,
4359
+ publicSafe: true
4360
+ };
4361
+ }
4362
+ function privateRefFromOptions(options) {
4363
+ const env = options.env ?? process.env;
4364
+ return options.privateRef?.trim() || env[PRIVATE_MANIFEST_REF_ENV]?.trim() || env["MACHINES_PRIVATE_MANIFEST_REF"]?.trim() || null;
4365
+ }
4366
+ function getManifestSourceRef(options = {}) {
4367
+ const rawPrivateRef = privateRefFromOptions(options);
4368
+ if (rawPrivateRef) {
4369
+ const env = options.env ?? process.env;
4370
+ return privateSourceRef(rawPrivateRef, options.privateBackend ?? env[PRIVATE_MANIFEST_BACKEND_ENV]);
4371
+ }
4372
+ return fileSourceRef(options.path ?? getManifestPath());
4373
+ }
4242
4374
  function getDefaultManifest() {
4243
4375
  return {
4244
4376
  version: 1,
@@ -4253,6 +4385,53 @@ function readManifest(path = getManifestPath()) {
4253
4385
  const raw = JSON.parse(readFileSync(path, "utf8"));
4254
4386
  return fleetSchema.parse(raw);
4255
4387
  }
4388
+ function readManifestWithSource(options = {}) {
4389
+ const path = options.path ?? getManifestPath();
4390
+ const source = getManifestSourceRef(options);
4391
+ const warnings = [];
4392
+ if (source.kind === "private-ref") {
4393
+ const rawRef = privateRefFromOptions(options);
4394
+ if (rawRef && options.adapter) {
4395
+ try {
4396
+ const manifest2 = options.adapter.readManifest({ source, rawRef });
4397
+ if (manifest2) {
4398
+ return {
4399
+ manifest: fleetSchema.parse(manifest2),
4400
+ info: {
4401
+ source,
4402
+ loadedFrom: "private-ref",
4403
+ warnings
4404
+ }
4405
+ };
4406
+ }
4407
+ warnings.push(`private_manifest_adapter_empty:${redactIdentifier(options.adapter.id)}`);
4408
+ } catch (error) {
4409
+ warnings.push(`private_manifest_adapter_failed:${redactIdentifier(options.adapter.id)}`);
4410
+ }
4411
+ } else {
4412
+ warnings.push("private_manifest_ref_without_adapter");
4413
+ }
4414
+ const fallbackSource = fileSourceRef(path);
4415
+ const manifest = readManifest(path);
4416
+ return {
4417
+ manifest,
4418
+ info: {
4419
+ source,
4420
+ loadedFrom: existsSync2(path) ? "fallback" : "default",
4421
+ fallbackSource,
4422
+ warnings
4423
+ }
4424
+ };
4425
+ }
4426
+ return {
4427
+ manifest: readManifest(path),
4428
+ info: {
4429
+ source,
4430
+ loadedFrom: existsSync2(path) ? "file" : "default",
4431
+ warnings
4432
+ }
4433
+ };
4434
+ }
4256
4435
  function validateManifest(path = getManifestPath()) {
4257
4436
  return readManifest(path);
4258
4437
  }
@@ -4575,7 +4754,7 @@ function buildEntry(input) {
4575
4754
  },
4576
4755
  route_hints: hints,
4577
4756
  tags: manifest?.tags ?? [],
4578
- metadata: manifest?.metadata ?? {}
4757
+ metadata: redactMetadata(manifest?.metadata)
4579
4758
  };
4580
4759
  }
4581
4760
  function discoverMachineTopology(options = {}) {
@@ -4844,7 +5023,7 @@ function resolveMachineRoute(machineId, options = {}) {
4844
5023
  warnings
4845
5024
  };
4846
5025
  }
4847
- function isRecord(value) {
5026
+ function isRecord2(value) {
4848
5027
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4849
5028
  }
4850
5029
  function metadataString(metadata, keys) {
@@ -4874,13 +5053,13 @@ function metadataStringArray(metadata, keys) {
4874
5053
  function readMappedPath(input) {
4875
5054
  for (const containerName of input.containers) {
4876
5055
  const container = input.metadata[containerName];
4877
- if (!isRecord(container))
5056
+ if (!isRecord2(container))
4878
5057
  continue;
4879
5058
  for (const key of input.keys) {
4880
5059
  const value = container[key];
4881
5060
  if (typeof value === "string" && value.trim())
4882
5061
  return value.trim();
4883
- if (isRecord(value)) {
5062
+ if (isRecord2(value)) {
4884
5063
  const path = metadataString(value, ["path", "root", "workspacePath", "workspace_path"]);
4885
5064
  if (path)
4886
5065
  return path;
@@ -5134,7 +5313,7 @@ function primaryMachine(machine, projectId, primaryMachineId) {
5134
5313
  return machine.tags.includes("primary");
5135
5314
  }
5136
5315
  function metadataKeysForDiagnostics(metadata) {
5137
- return Object.keys(metadata).filter((key) => !/(secret|token|key|password|credential)/i.test(key)).sort();
5316
+ return publicMetadataKeys(metadata);
5138
5317
  }
5139
5318
  function resolveMachineWorkspace(options) {
5140
5319
  const now = options.now ?? new Date;
@@ -5484,21 +5663,21 @@ var MACHINES_CONSUMER_SCHEMA_BUNDLE = {
5484
5663
  }
5485
5664
  }
5486
5665
  };
5487
- function isRecord2(value) {
5666
+ function isRecord3(value) {
5488
5667
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
5489
5668
  }
5490
5669
  function hasString(value, key) {
5491
5670
  return typeof value[key] === "string" && value[key].length > 0;
5492
5671
  }
5493
5672
  function hasObject(value, key) {
5494
- return isRecord2(value[key]);
5673
+ return isRecord3(value[key]);
5495
5674
  }
5496
5675
  function hasArray(value, key) {
5497
5676
  return Array.isArray(value[key]);
5498
5677
  }
5499
5678
  function hasCacheability(value, key = "cacheability") {
5500
5679
  const cache = value[key];
5501
- return isRecord2(cache) && hasString(cache, "observed_at") && typeof cache.cacheable === "boolean" && typeof cache.stale === "boolean" && hasArray(cache, "reasons");
5680
+ return isRecord3(cache) && hasString(cache, "observed_at") && typeof cache.cacheable === "boolean" && typeof cache.stale === "boolean" && hasArray(cache, "reasons");
5502
5681
  }
5503
5682
  function requireFields(value, fields, errors2) {
5504
5683
  for (const field of fields) {
@@ -5511,7 +5690,7 @@ function getMachinesConsumerSchemaBundle() {
5511
5690
  }
5512
5691
  function validateMachinesConsumerEnvelope(envelope, value) {
5513
5692
  const errors2 = [];
5514
- if (!isRecord2(value)) {
5693
+ if (!isRecord3(value)) {
5515
5694
  return { ok: false, envelope, schema_id: MACHINES_CONSUMER_SCHEMA_URI, errors: ["not_object"] };
5516
5695
  }
5517
5696
  if (value.schema_version !== MACHINES_CONSUMER_CONTRACT_VERSION)
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./cross-project-types.js";
3
3
  export * from "./paths.js";
4
4
  export * from "./db.js";
5
5
  export * from "./manifests.js";
6
+ export * from "./redaction.js";
6
7
  export * from "./topology.js";
7
8
  export * from "./compatibility.js";
8
9
  export * from "./agent/runtime.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,oBAAoB,EACpB,6BAA6B,EAC7B,yBAAyB,EACzB,kCAAkC,EAClC,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtH,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,oBAAoB,EACpB,6BAA6B,EAC7B,yBAAyB,EACzB,kCAAkC,EAClC,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtH,cAAc,cAAc,CAAC"}