@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/README.md +17 -0
- package/dist/cli/index.js +310 -24
- package/dist/commands/doctor.d.ts +23 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/consumer.js +188 -9
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +322 -24
- package/dist/manifests.d.ts +22 -1
- package/dist/manifests.d.ts.map +1 -1
- package/dist/mcp/index.js +303 -19
- package/dist/redaction.d.ts +11 -0
- package/dist/redaction.d.ts.map +1 -0
- package/dist/topology.d.ts.map +1 -1
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/scripts/consumer-conformance.mjs +3 -2
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
|
|
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 (!
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 (!
|
|
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";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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"}
|