infracensus-collector 1.4.4 → 1.6.0
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/a10-index.js +2 -2
- package/dist/azure-index.js +6 -6
- package/dist/{chunk-UV737N5S.js → chunk-66TRC3GH.js} +2 -2
- package/dist/{chunk-7T2LVP6E.js → chunk-7I3ZADZT.js} +4 -4
- package/dist/{chunk-PFZRGWEF.js → chunk-7LSYNWBB.js} +2 -2
- package/dist/{chunk-E45UL3V3.js → chunk-A27O5VMG.js} +39 -1
- package/dist/chunk-A27O5VMG.js.map +7 -0
- package/dist/{chunk-CZST5VMO.js → chunk-AH5OW4T3.js} +2 -2
- package/dist/{chunk-QITZIOFD.js → chunk-CHN3HHUT.js} +4 -4
- package/dist/{chunk-IVE2QR5M.js → chunk-FYKLZRHK.js} +2 -2
- package/dist/{chunk-CQYV43KA.js → chunk-HB3DUE46.js} +2 -2
- package/dist/{chunk-5ULN62DY.js → chunk-IGTUXQVG.js} +2 -2
- package/dist/{chunk-F5DB2SXP.js → chunk-KTNSYBZN.js} +24 -1
- package/dist/chunk-KTNSYBZN.js.map +7 -0
- package/dist/{chunk-62F6ZKS6.js → chunk-M6BEAG6W.js} +2 -2
- package/dist/{chunk-CBNDR2GQ.js → chunk-M6O7VA6Z.js} +2 -2
- package/dist/{chunk-RKZ6PTVB.js → chunk-M6XXRHFK.js} +2 -2
- package/dist/{chunk-TQXSTE4N.js → chunk-V6BRGNEU.js} +6 -4
- package/dist/chunk-V6BRGNEU.js.map +7 -0
- package/dist/cli.js +12 -6
- package/dist/cli.js.map +2 -2
- package/dist/{config-OIFTEYLP.js → config-7AAJ3O6N.js} +3 -3
- package/dist/configimport-index.js +4 -4
- package/dist/hyperv-index.js +6 -6
- package/dist/identity-index.js +6 -6
- package/dist/index.js +711 -29
- package/dist/index.js.map +4 -4
- package/dist/sensitive-data-index.js +5 -5
- package/dist/sql-index.js +6 -6
- package/dist/{status-MWP2NOBY.js → status-2MFYDX7U.js} +10 -8
- package/dist/vmware-index.js +6 -6
- package/dist/voice-index.js +6 -6
- package/package.json +97 -97
- package/dist/chunk-E45UL3V3.js.map +0 -7
- package/dist/chunk-F5DB2SXP.js.map +0 -7
- package/dist/chunk-TQXSTE4N.js.map +0 -7
- /package/dist/{chunk-UV737N5S.js.map → chunk-66TRC3GH.js.map} +0 -0
- /package/dist/{chunk-7T2LVP6E.js.map → chunk-7I3ZADZT.js.map} +0 -0
- /package/dist/{chunk-PFZRGWEF.js.map → chunk-7LSYNWBB.js.map} +0 -0
- /package/dist/{chunk-CZST5VMO.js.map → chunk-AH5OW4T3.js.map} +0 -0
- /package/dist/{chunk-QITZIOFD.js.map → chunk-CHN3HHUT.js.map} +0 -0
- /package/dist/{chunk-IVE2QR5M.js.map → chunk-FYKLZRHK.js.map} +0 -0
- /package/dist/{chunk-CQYV43KA.js.map → chunk-HB3DUE46.js.map} +0 -0
- /package/dist/{chunk-5ULN62DY.js.map → chunk-IGTUXQVG.js.map} +0 -0
- /package/dist/{chunk-62F6ZKS6.js.map → chunk-M6BEAG6W.js.map} +0 -0
- /package/dist/{chunk-CBNDR2GQ.js.map → chunk-M6O7VA6Z.js.map} +0 -0
- /package/dist/{chunk-RKZ6PTVB.js.map → chunk-M6XXRHFK.js.map} +0 -0
- /package/dist/{config-OIFTEYLP.js.map → config-7AAJ3O6N.js.map} +0 -0
- /package/dist/{status-MWP2NOBY.js.map → status-2MFYDX7U.js.map} +0 -0
package/dist/a10-index.js
CHANGED
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
} from "./chunk-MN4JODQW.js";
|
|
5
5
|
import {
|
|
6
6
|
requireEntitlementToScan
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-66TRC3GH.js";
|
|
8
8
|
import {
|
|
9
9
|
ROUTES
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-KTNSYBZN.js";
|
|
11
11
|
import "./chunk-CW3YCPEC.js";
|
|
12
12
|
|
|
13
13
|
// src/a10-index.ts
|
package/dist/azure-index.js
CHANGED
|
@@ -2,18 +2,18 @@ import {
|
|
|
2
2
|
ArmClient,
|
|
3
3
|
buildAzureInventory,
|
|
4
4
|
listAccessibleSubscriptions
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AH5OW4T3.js";
|
|
6
6
|
import {
|
|
7
7
|
pushAzureInventory
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-CHN3HHUT.js";
|
|
9
|
+
import "./chunk-M6O7VA6Z.js";
|
|
10
10
|
import {
|
|
11
11
|
loadAzureConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-HB3DUE46.js";
|
|
13
13
|
import {
|
|
14
14
|
requireEntitlementToScan
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-66TRC3GH.js";
|
|
16
|
+
import "./chunk-KTNSYBZN.js";
|
|
17
17
|
import "./chunk-CW3YCPEC.js";
|
|
18
18
|
|
|
19
19
|
// src/azure-index.ts
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
CollectorEntitlementResult,
|
|
4
4
|
DiscoverySnapshot,
|
|
5
5
|
ROUTES
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KTNSYBZN.js";
|
|
7
7
|
import {
|
|
8
8
|
PKG_ROOT
|
|
9
9
|
} from "./chunk-CW3YCPEC.js";
|
|
@@ -494,4 +494,4 @@ export {
|
|
|
494
494
|
requireEntitlementToScan,
|
|
495
495
|
assertEntitlementConfirmed
|
|
496
496
|
};
|
|
497
|
-
//# sourceMappingURL=chunk-
|
|
497
|
+
//# sourceMappingURL=chunk-66TRC3GH.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
collectSecretValues
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-A27O5VMG.js";
|
|
4
4
|
import {
|
|
5
5
|
configFilePath,
|
|
6
6
|
vaultSettings
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HB3DUE46.js";
|
|
8
8
|
import {
|
|
9
9
|
CredentialSetKind,
|
|
10
10
|
DomainCredentialSecret,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
VaultProtection,
|
|
13
13
|
WindowsCredential,
|
|
14
14
|
domainSecretSatisfiesKind
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-KTNSYBZN.js";
|
|
16
16
|
import {
|
|
17
17
|
PKG_ROOT
|
|
18
18
|
} from "./chunk-CW3YCPEC.js";
|
|
@@ -1263,4 +1263,4 @@ export {
|
|
|
1263
1263
|
plaintextKeyWarning,
|
|
1264
1264
|
collectorVersion
|
|
1265
1265
|
};
|
|
1266
|
-
//# sourceMappingURL=chunk-
|
|
1266
|
+
//# sourceMappingURL=chunk-7I3ZADZT.js.map
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
IdentityIngestBody,
|
|
14
14
|
M365Licensing,
|
|
15
15
|
M365Workload
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-KTNSYBZN.js";
|
|
17
17
|
|
|
18
18
|
// src/identity/graph.ts
|
|
19
19
|
var noopLog = () => {
|
|
@@ -1124,4 +1124,4 @@ export {
|
|
|
1124
1124
|
GraphClient,
|
|
1125
1125
|
buildIdentityInventory
|
|
1126
1126
|
};
|
|
1127
|
-
//# sourceMappingURL=chunk-
|
|
1127
|
+
//# sourceMappingURL=chunk-7LSYNWBB.js.map
|
|
@@ -50,6 +50,44 @@ var COLLECTOR_MODULES = [
|
|
|
50
50
|
entry: "./a10-index.js",
|
|
51
51
|
ledgerModes: ["daemon:loadbalancer"]
|
|
52
52
|
},
|
|
53
|
+
{
|
|
54
|
+
key: "storage",
|
|
55
|
+
domain: "storage",
|
|
56
|
+
consoleRefusal: null,
|
|
57
|
+
moduleKey: "storage",
|
|
58
|
+
label: "Storage arrays (NetApp / Dell EMC / EqualLogic)",
|
|
59
|
+
// Daemon-only: no one-shot entrypoint exists for this domain.
|
|
60
|
+
entry: null,
|
|
61
|
+
ledgerModes: ["daemon:storage"]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
key: "firewall",
|
|
65
|
+
domain: "firewall",
|
|
66
|
+
consoleRefusal: null,
|
|
67
|
+
// The domain is `firewall`; the catalogue sells it as `firewall-audit`.
|
|
68
|
+
moduleKey: "firewall-audit",
|
|
69
|
+
label: "Firewalls (FMC / FDM / PAN-OS)",
|
|
70
|
+
entry: null,
|
|
71
|
+
ledgerModes: ["daemon:firewall"]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
key: "wireless",
|
|
75
|
+
domain: "wireless",
|
|
76
|
+
consoleRefusal: null,
|
|
77
|
+
moduleKey: "wireless",
|
|
78
|
+
label: "Wireless controllers (WLC)",
|
|
79
|
+
entry: null,
|
|
80
|
+
ledgerModes: ["daemon:wireless"]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
key: "nac",
|
|
84
|
+
domain: "nac",
|
|
85
|
+
consoleRefusal: null,
|
|
86
|
+
moduleKey: "nac",
|
|
87
|
+
label: "Network access control (ISE / ClearPass)",
|
|
88
|
+
entry: null,
|
|
89
|
+
ledgerModes: ["daemon:nac"]
|
|
90
|
+
},
|
|
53
91
|
{
|
|
54
92
|
key: "voice",
|
|
55
93
|
domain: "voice",
|
|
@@ -207,4 +245,4 @@ export {
|
|
|
207
245
|
redactLocal,
|
|
208
246
|
redactMeta
|
|
209
247
|
};
|
|
210
|
-
//# sourceMappingURL=chunk-
|
|
248
|
+
//# sourceMappingURL=chunk-A27O5VMG.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/ui/modules.ts", "../src/core/localRedaction.ts"],
|
|
4
|
+
"sourcesContent": ["/**\r\n * The collector's scan modules, as ONE table.\r\n *\r\n * Three consumers read it, and keeping them on a single list is the point:\r\n *\r\n * - `src/cli.ts` maps `netdoc-collector scan <key>` onto the module's\r\n * existing entry file. The entrypoints themselves are untouched \u2014 they\r\n * talk to real hardware and each already knows how to load its own config,\r\n * print its own summary and set its own exit code. The CLI only DISPATCHES.\r\n * - `src/ui/status.ts` folds the use-log ledger into a per-module \"last run\"\r\n * row, and needs to know which ledger `mode` strings belong to which module.\r\n * - `src/ui/server.ts` accepts `POST /ui/api/scan {module}` and must refuse a\r\n * key that is not on this list \u2014 the module name is the only part of that\r\n * request that reaches a `spawn`, so the allowlist IS the injection guard.\r\n *\r\n * A module added here gains all three surfaces at once; a module added to only\r\n * one of them is the drift this table exists to prevent.\r\n */\r\n\r\nimport type { ModuleKey, ScanDomain } from \"@netdoc/collector-contract\";\r\n\r\nexport interface CollectorModule {\r\n /** The key typed after `scan` and posted by the UI's Run button. */\r\n key: string;\r\n /**\r\n * The control plane's name for this scan \u2014 the `domain` a job carries.\r\n *\r\n * It is what lets the UI's Run button build a LOCAL JOB and hand it to the\r\n * running daemon (`core/manualRuns.ts`) instead of spawning a one-shot child\r\n * that would demand `ORG_ID` / `SITE_ID` / `SCAN_TARGETS` from a config file\r\n * enrolment never writes them into. Stated here rather than parsed back out\r\n * of `ledgerModes`, where it has always been half-present as\r\n * `daemon:<domain>`: a string that is load-bearing for what runs should not\r\n * have to be recovered from a string that exists to match log records.\r\n *\r\n * NULL for a module that is not a scan domain at all \u2014 `config-import`, which\r\n * reads a directory of device configs rather than reaching an estate.\r\n */\r\n domain: ScanDomain | null;\r\n /**\r\n * Why the local console cannot START this module, when it cannot \u2014 the whole\r\n * sentence the button answers with, naming the command that does work.\r\n *\r\n * TWO modules refuse, for two different reasons, and keeping the reason here\r\n * rather than deriving it from `domain` is the point: `config-import` has no\r\n * domain at all, while `sensitive-data` has a perfectly real one that the\r\n * daemon nevertheless REFUSES from the scan-job queue (`core/daemon.ts` \u2014 it\r\n * pushes through a resumable run/batch/close sequence instead of one\r\n * snapshot, and the queue's dispatch chain would otherwise fall through to\r\n * the SQL Server driver). Deriving the refusal from `domain === null` would\r\n * have queued a sensitive-data job that the daemon fails a second later, and\r\n * the operator would read that as a broken scan rather than a wrong button.\r\n *\r\n * NULL means the console can run it.\r\n */\r\n consoleRefusal: string | null;\r\n /**\r\n * The licence module this scan is gated on \u2014 the key the tenant must OWN for\r\n * the resulting push to be accepted, and the one the UI checks (via\r\n * `collectorOwnsModule`) before it enables a \"Run scan\" button. It is the\r\n * catalogue name, which is not always the CLI key: `lb` is sold as\r\n * `load-balancer`, the `identity` collector feeds `cloud-identity`. Kept beside\r\n * the CLI key here rather than derived at the call site so this one table stays\r\n * the single source of truth for \"what is this module, in every sense\".\r\n */\r\n moduleKey: ModuleKey;\r\n /** Human label for the UI's modules table. */\r\n label: string;\r\n /**\r\n * The module's entry file, as an import specifier RELATIVE TO `src/` (and\r\n * therefore to the compiled `dist/`). `src/cli.ts` sits in that directory, so\r\n * a plain dynamic `import(entry)` from there resolves it in both worlds \u2014\r\n * under tsx in a checkout and as compiled JS in the installed package.\r\n */\r\n /**\r\n * The one-shot module to import for `netdoc-collector scan <key>`.\r\n *\r\n * NULL for a domain that has no one-shot entrypoint. Four of them do not \u2014\r\n * storage, firewall, wireless and NAC are implemented as DOMAIN RUNNERS in\r\n * `core/domainScan.ts` and reached through a job, which is how the portal has\r\n * always run them. They were absent from this table entirely until\r\n * 2026-09-11, so the local console offered no way to run four scan types the\r\n * collector fully supports.\r\n *\r\n * Listing them with a null entry is what fixes that without inventing four\r\n * `*-index.ts` files nobody asked for: the console's Run button builds a JOB\r\n * (see `ui/actions.ts`), which the daemon dispatches by domain, and never\r\n * touches this field. `cli.ts` does, and refuses with a sentence naming the\r\n * two ways that do work.\r\n */\r\n entry: string | null;\r\n /**\r\n * The `mode` strings this module's runs are recorded under in the use log\r\n * (`core/useLog.ts`): one-shot runs write \"scan\"/\"scan --dry-run\", daemon\r\n * jobs write \"daemon:<domain>\" where <domain> is the CONTROL PLANE's name\r\n * for the module \u2014 which is not always the CLI key (`lb` is the plane's\r\n * \"loadbalancer\"). Empty means the module keeps no ledger record today\r\n * (config-import), and its status row honestly shows \"never\".\r\n */\r\n ledgerModes: readonly string[];\r\n}\r\n\r\nexport const COLLECTOR_MODULES: readonly CollectorModule[] = [\r\n {\r\n key: \"network\",\r\n domain: \"network\",\r\n consoleRefusal: null,\r\n moduleKey: \"discovery\",\r\n label: \"Network sweep (ICMP / ARP / SNMP / SSH)\",\r\n entry: \"./index.js\",\r\n ledgerModes: [\"scan\", \"scan --dry-run\", \"daemon:network\"],\r\n },\r\n {\r\n key: \"vmware\",\r\n domain: \"vmware\",\r\n consoleRefusal: null,\r\n moduleKey: \"vmware\",\r\n label: \"VMware vSphere\",\r\n entry: \"./vmware-index.js\",\r\n ledgerModes: [\"daemon:vmware\"],\r\n },\r\n {\r\n key: \"hyperv\",\r\n domain: \"hyperv\",\r\n consoleRefusal: null,\r\n moduleKey: \"hyperv\",\r\n label: \"Hyper-V\",\r\n entry: \"./hyperv-index.js\",\r\n ledgerModes: [\"daemon:hyperv\"],\r\n },\r\n {\r\n key: \"sql\",\r\n domain: \"sql\",\r\n consoleRefusal: null,\r\n moduleKey: \"sql\",\r\n label: \"SQL Server\",\r\n entry: \"./sql-index.js\",\r\n ledgerModes: [\"daemon:sql\"],\r\n },\r\n {\r\n key: \"lb\",\r\n domain: \"loadbalancer\",\r\n consoleRefusal: null,\r\n // The CLI key is `lb`; the module is sold as `load-balancer`.\r\n moduleKey: \"load-balancer\",\r\n label: \"Load balancers (A10)\",\r\n entry: \"./a10-index.js\",\r\n ledgerModes: [\"daemon:loadbalancer\"],\r\n },\r\n {\r\n key: \"storage\",\r\n domain: \"storage\",\r\n consoleRefusal: null,\r\n moduleKey: \"storage\",\r\n label: \"Storage arrays (NetApp / Dell EMC / EqualLogic)\",\r\n // Daemon-only: no one-shot entrypoint exists for this domain.\r\n entry: null,\r\n ledgerModes: [\"daemon:storage\"],\r\n },\r\n {\r\n key: \"firewall\",\r\n domain: \"firewall\",\r\n consoleRefusal: null,\r\n // The domain is `firewall`; the catalogue sells it as `firewall-audit`.\r\n moduleKey: \"firewall-audit\",\r\n label: \"Firewalls (FMC / FDM / PAN-OS)\",\r\n entry: null,\r\n ledgerModes: [\"daemon:firewall\"],\r\n },\r\n {\r\n key: \"wireless\",\r\n domain: \"wireless\",\r\n consoleRefusal: null,\r\n moduleKey: \"wireless\",\r\n label: \"Wireless controllers (WLC)\",\r\n entry: null,\r\n ledgerModes: [\"daemon:wireless\"],\r\n },\r\n {\r\n key: \"nac\",\r\n domain: \"nac\",\r\n consoleRefusal: null,\r\n moduleKey: \"nac\",\r\n label: \"Network access control (ISE / ClearPass)\",\r\n entry: null,\r\n ledgerModes: [\"daemon:nac\"],\r\n },\r\n {\r\n key: \"voice\",\r\n domain: \"voice\",\r\n consoleRefusal: null,\r\n moduleKey: \"voice\",\r\n label: \"Voice & Collaboration (CUCM / Unity / Webex)\",\r\n entry: \"./voice-index.js\",\r\n ledgerModes: [\"daemon:voice\"],\r\n },\r\n {\r\n key: \"identity\",\r\n domain: \"identity\",\r\n consoleRefusal: null,\r\n // The `identity` collector is the Microsoft Graph one; it feeds\r\n // `cloud-identity` (Entra / M365), NOT the on-prem `ad-identity` module.\r\n moduleKey: \"cloud-identity\",\r\n label: \"Identity & Cloud (Microsoft Entra ID)\",\r\n entry: \"./identity-index.js\",\r\n ledgerModes: [\"daemon:identity\"],\r\n },\r\n {\r\n key: \"azure\",\r\n domain: \"azure\",\r\n consoleRefusal: null,\r\n moduleKey: \"azure\",\r\n label: \"Azure Cloud Posture (CSPM)\",\r\n entry: \"./azure-index.js\",\r\n ledgerModes: [\"daemon:azure\"],\r\n },\r\n {\r\n key: \"config-import\",\r\n domain: null,\r\n consoleRefusal:\r\n \"reads a directory of device configurations given as --path, which no button can supply \u2014 \" +\r\n \"run it from a shell, as: netdoc-collector scan config-import --path <directory>\",\r\n moduleKey: \"config-import\",\r\n label: \"Config import (offline device configs)\",\r\n entry: \"./configimport-index.js\",\r\n ledgerModes: [],\r\n },\r\n {\r\n // Sensitive-data discovery (PLAN-010, Phases 2-4). Its entrypoint arrived\r\n // without a row here, which left the packaged CLI unable to dispatch it \u2014\r\n // `netdoc-collector scan sensitive-data` is this line. Empty ledgerModes\r\n // like config-import: its run/batch/close ingest keeps its own records and\r\n // writes no use-log mode yet, so the status row honestly shows \"never\"\r\n // rather than guessing at a mode string the ledger never carries.\r\n //\r\n // Now that a scan classifies and PUSHES (sensitiveData/pushRun.ts), \"never\"\r\n // is a thinner answer than it was \u2014 the run is recorded in sdd_scan_runs at\r\n // the far end, just not in the local ledger this row reads. Giving it a real\r\n // mode is a small piece of work and the right one; it is deliberately not\r\n // being smuggled in with the ingest wiring.\r\n key: \"sensitive-data\",\r\n domain: \"sensitive-data\",\r\n // A real scan domain that the JOB QUEUE refuses: a share scan is millions\r\n // of reads over hours and pushes through run/batch/close instead of one\r\n // snapshot, so `core/daemon.ts` fails the job rather than letting the\r\n // dispatch chain fall through to the SQL Server driver.\r\n consoleRefusal:\r\n \"runs for hours and pushes in resumable batches rather than one snapshot, so it does not \" +\r\n \"run from the scan-job queue \u2014 run it from a shell, as: netdoc-collector scan sensitive-data\",\r\n moduleKey: \"sensitive-data\",\r\n label: \"Sensitive Data Discovery\",\r\n entry: \"./sensitive-data-index.js\",\r\n ledgerModes: [],\r\n },\r\n];\r\n\r\n/** Look a module up by its CLI/UI key. */\r\nexport function findModule(key: string): CollectorModule | undefined {\r\n return COLLECTOR_MODULES.find((m) => m.key === key);\r\n}\r\n", "/**\r\n * Redaction for the collector's LOCAL surfaces \u2014 the operator console and the\r\n * use log.\r\n *\r\n * \u2500\u2500 WHY THIS FILE EXISTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n *\r\n * Everything else in this package worries about what leaves the building. This\r\n * one worries about what stays. The collector runs on the customer's hardware,\r\n * inside their network, holding their credentials, and the two easiest places in\r\n * the whole product to print one of those credentials are a console on a shared\r\n * terminal and a log file on a jump box. Neither of those machines is ours, and\r\n * neither is covered by the outbound redaction that `showOutputPush.ts` and\r\n * `configimport/run.ts` already apply \u2014 those redact on the way to the wire, and\r\n * a local console never touches the wire.\r\n *\r\n * \u2500\u2500 TWO PASSES, BECAUSE THERE ARE TWO KINDS OF SECRET \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n *\r\n * 1. **Structural.** Device output echoed into a message is configuration text,\r\n * and configuration text has a redactor already: `redactConfig` from\r\n * `@netdoc/config-ir`, the same one the outbound path uses. It is reused\r\n * verbatim rather than reimplemented, so a rule added for the wire protects\r\n * the console the same day. Its fail-closed stance comes along with it: a\r\n * line that merely *looks* like it carries a key is redacted, which\r\n * occasionally costs a little display fidelity on an ordinary message like\r\n * \"password rejected\". That is the correct side to err on here.\r\n *\r\n * 2. **Configured.** The credentials this collector was handed \u2014 the SNMP\r\n * communities, the SSH and Windows passwords, the vCenter/SQL/Graph/Azure\r\n * secrets, and its own control-plane API key. `redactConfig` cannot see\r\n * these: `S3cretC0mm` is an unremarkable word until you know it is the\r\n * community string. So the live values are collected from the resolved\r\n * config and struck out by value.\r\n *\r\n * \u2500\u2500 THE FIELD LIST IS DERIVED, NEVER HAND-KEPT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n *\r\n * A hand-maintained roster of \"fields that hold secrets\" goes stale the first\r\n * time somebody adds a module, and it goes stale silently \u2014 the guard stays\r\n * green while its scope shrinks. So {@link isSecretField} classifies by name\r\n * over whatever keys the config schema actually declares, and\r\n * `localRedaction.test.ts` walks `FileConfig`'s shape and fails if any key is\r\n * neither classified secret nor listed as deliberately public. A new\r\n * `fooPassword` is covered without an edit here; a new field whose safety is\r\n * genuinely ambiguous fails the test until somebody decides.\r\n */\r\nimport { redactConfig } from \"@netdoc/config-ir\";\r\n\r\n/** What replaces a configured credential found in local output. */\r\nexport const CONFIGURED_SECRET_PLACEHOLDER = \"<REDACTED:configured-secret>\";\r\n\r\n/**\r\n * Name fragments that mark a config field as holding a credential.\r\n *\r\n * Matched case-insensitively against the field name, so `vcenterPass`,\r\n * `graphClientSecret`, `webexToken`, `snmpCommunities`, `sshCredentials` and\r\n * `apiKey` are all caught by shape rather than by enumeration.\r\n *\r\n * `user` is deliberately absent. A username is not a credential, and the\r\n * existing wire contract already reports one: `SshOutcome.username` names the\r\n * credential that authenticated precisely so an operator can tell which one\r\n * worked. Redacting usernames would blind the report without protecting\r\n * anything.\r\n *\r\n * The fragments are STEMS, not whole words. `communit` rather than `community`\r\n * because the field that actually holds the SNMP credentials is the plural\r\n * `snmpCommunities`, and an exact-word fragment sailed straight past it \u2014 the\r\n * coverage test in `localRedaction.test.ts` is what noticed, which is the\r\n * argument for deriving the list over the schema rather than writing it out.\r\n */\r\nconst SECRET_NAME_FRAGMENTS = [\r\n \"pass\", // vcenterPass, hypervPass, sqlPass, cucmPass, password, passwd\r\n \"secret\", // graphClientSecret, azureClientSecret, enable secret\r\n \"token\", // webexToken\r\n \"communit\", // snmpCommunity AND snmpCommunities\r\n \"credential\", // sshCredentials, windowsCredentials (arrays; walked into)\r\n \"apikey\", // apiKey \u2014 this collector's own identity on the control plane\r\n \"enable\", // the Cisco enable secret, named for what it unlocks\r\n] as const;\r\n\r\n/** Does this config field name denote a credential? */\r\nexport function isSecretField(name: string): boolean {\r\n const lowered = name.toLowerCase();\r\n return SECRET_NAME_FRAGMENTS.some((fragment) => lowered.includes(fragment));\r\n}\r\n\r\n/**\r\n * Single-character values are not collected.\r\n *\r\n * Striking every occurrence of one character out of a log would leave a file\r\n * that is useless as the evidence it exists to be, and it would do so on every\r\n * run \u2014 while a one-character credential is not a thing worth protecting at that\r\n * price. Everything from two characters up is struck. Note that the structural\r\n * pass still catches a short secret when it appears in configuration syntax,\r\n * which is the case that actually occurs.\r\n */\r\nconst MIN_SECRET_LENGTH = 2;\r\n\r\n/**\r\n * Pull every configured credential value out of a resolved config object.\r\n *\r\n * Walks recursively so credential ARRAYS are covered: `sshCredentials` is a\r\n * secret-named field but its value is a list of objects, and what matters is\r\n * the `password`/`enable` inside each one. Plain string arrays under a secret\r\n * name (`snmpCommunities`) contribute every element.\r\n *\r\n * Accepts `unknown` because the caller passes whichever of the seven config\r\n * shapes this run loaded, and they share no common type.\r\n */\r\nexport function collectSecretValues(config: unknown): string[] {\r\n const found = new Set<string>();\r\n\r\n const walk = (value: unknown, underSecretName: boolean): void => {\r\n if (typeof value === \"string\") {\r\n if (underSecretName && value.length >= MIN_SECRET_LENGTH) found.add(value);\r\n return;\r\n }\r\n if (Array.isArray(value)) {\r\n // The array itself inherits its key's classification; each element is\r\n // judged the same way, so a secret-named list of strings contributes all\r\n // of them and a list of credential objects is walked into.\r\n for (const item of value) walk(item, underSecretName);\r\n return;\r\n }\r\n if (value && typeof value === \"object\") {\r\n for (const [key, child] of Object.entries(value as Record<string, unknown>)) {\r\n walk(child, isSecretField(key));\r\n }\r\n }\r\n };\r\n\r\n walk(config, false);\r\n // Longest first: replacing \"hunter2\" before \"hunter\" stops a shorter secret\r\n // that happens to be a prefix of a longer one from carving it up and leaving\r\n // the tail in the clear.\r\n return [...found].sort((a, b) => b.length - a.length);\r\n}\r\n\r\n/**\r\n * A LIVE set of secret values, so redaction covers credentials the process did\r\n * not have when it started.\r\n *\r\n * `collectSecretValues` reads the config FILE, and the entry point calls it\r\n * once before the first job is claimed. That was the whole defence, and it\r\n * left a hole exactly the width of the daemon: every job carries its OWN\r\n * credentials \u2014 SSH passwords, enable secrets, SNMP communities, domain\r\n * passwords, all arriving from the control plane per job \u2014 and none of them\r\n * were in the frozen list. `core/daemon.ts` says \"Passwords never logged\" and\r\n * means it, but redaction by value is the net under that intention, and the\r\n * net had no job credentials in it. A vendor driver that echoes a failed\r\n * login line, or a device that prints its own community back, would have\r\n * reached the log on the customer's disk in the clear.\r\n *\r\n * Values only ever accumulate: a job's credentials stay redactable after the\r\n * job ends, because the lines it already wrote are still in the file and the\r\n * next reader of that file must not find a password in it.\r\n */\r\nexport interface SecretRegistry {\r\n /** Add values; anything null, short, or already known is ignored. */\r\n add(...values: readonly (string | null | undefined)[]): void;\r\n /** Longest-first, the order {@link redactLocal} needs. */\r\n values(): readonly string[];\r\n}\r\n\r\nexport function createSecretRegistry(initial: readonly string[] = []): SecretRegistry {\r\n const found = new Set<string>(initial.filter((s) => s.length >= MIN_SECRET_LENGTH));\r\n // Sorted on read rather than on write: adds happen per job, reads happen per\r\n // log line, and the set is tiny \u2014 but the ORDER is load-bearing (longest\r\n // first, so a short secret that prefixes a longer one cannot carve it up and\r\n // leave the tail in the clear), so it must not be skipped for speed.\r\n let cache: readonly string[] | null = null;\r\n return {\r\n add(...values) {\r\n for (const v of values) {\r\n if (typeof v !== \"string\" || v.length < MIN_SECRET_LENGTH || found.has(v)) continue;\r\n found.add(v);\r\n cache = null;\r\n }\r\n },\r\n values() {\r\n if (!cache) cache = [...found].sort((a, b) => b.length - a.length);\r\n return cache;\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Redact one piece of text destined for a local surface.\r\n *\r\n * Structural pass first \u2014 it understands configuration syntax and preserves the\r\n * shape that makes a line worth reading \u2014 then the value pass over whatever the\r\n * first one did not recognise.\r\n */\r\nexport function redactLocal(text: string, secrets: readonly string[] = []): string {\r\n let result = redactConfig(text).text;\r\n for (const secret of secrets) {\r\n if (!result.includes(secret)) continue;\r\n result = result.split(secret).join(CONFIGURED_SECRET_PLACEHOLDER);\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * Redact a log call's `meta` argument.\r\n *\r\n * `Logger`'s third parameter is `unknown`, and callers in this package pass\r\n * anything from an error message to an object. It is printed, so it is a leak\r\n * surface exactly like the message is \u2014 but it cannot be run through a\r\n * line-oriented redactor while it is still an object. Non-strings are therefore\r\n * serialised, redacted, and handed back AS the redacted string: a slightly\r\n * different console rendering is a cheap price for the guarantee that nothing\r\n * reaches the terminal unexamined. A value that will not serialise (a cycle, a\r\n * BigInt) is dropped entirely rather than printed blind.\r\n */\r\nexport function redactMeta(meta: unknown, secrets: readonly string[] = []): unknown {\r\n if (meta === undefined) return undefined;\r\n if (typeof meta === \"string\") return redactLocal(meta, secrets);\r\n try {\r\n const serialized = JSON.stringify(meta);\r\n if (serialized === undefined) return \"[unserialisable meta omitted]\";\r\n return redactLocal(serialized, secrets);\r\n } catch {\r\n return \"[unserialisable meta omitted]\";\r\n }\r\n}\r\n"],
|
|
5
|
+
"mappings": ";;;;;AAsGO,IAAM,oBAAgD;AAAA,EAC3D;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,QAAQ,kBAAkB,gBAAgB;AAAA,EAC1D;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,eAAe;AAAA,EAC/B;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,eAAe;AAAA,EAC/B;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,YAAY;AAAA,EAC5B;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA;AAAA,IAEhB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,qBAAqB;AAAA,EACrC;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,OAAO;AAAA;AAAA,IAEP,OAAO;AAAA,IACP,aAAa,CAAC,gBAAgB;AAAA,EAChC;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA;AAAA,IAEhB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,iBAAiB;AAAA,EACjC;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,iBAAiB;AAAA,EACjC;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,YAAY;AAAA,EAC5B;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,cAAc;AAAA,EAC9B;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA;AAAA;AAAA,IAGhB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,iBAAiB;AAAA,EACjC;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC,cAAc;AAAA,EAC9B;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,gBACE;AAAA,IAEF,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC;AAAA,EAChB;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAaE,KAAK;AAAA,IACL,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,IAKR,gBACE;AAAA,IAEF,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,CAAC;AAAA,EAChB;AACF;AAGO,SAAS,WAAW,KAA0C;AACnE,SAAO,kBAAkB,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG;AACpD;;;ACpNO,IAAM,gCAAgC;AAqB7C,IAAM,wBAAwB;AAAA,EAC5B;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AAGO,SAAS,cAAc,MAAuB;AACnD,QAAM,UAAU,KAAK,YAAY;AACjC,SAAO,sBAAsB,KAAK,CAAC,aAAa,QAAQ,SAAS,QAAQ,CAAC;AAC5E;AAYA,IAAM,oBAAoB;AAanB,SAAS,oBAAoB,QAA2B;AAC7D,QAAM,QAAQ,oBAAI,IAAY;AAE9B,QAAM,OAAO,CAAC,OAAgB,oBAAmC;AAC/D,QAAI,OAAO,UAAU,UAAU;AAC7B,UAAI,mBAAmB,MAAM,UAAU,kBAAmB,OAAM,IAAI,KAAK;AACzE;AAAA,IACF;AACA,QAAI,MAAM,QAAQ,KAAK,GAAG;AAIxB,iBAAW,QAAQ,MAAO,MAAK,MAAM,eAAe;AACpD;AAAA,IACF;AACA,QAAI,SAAS,OAAO,UAAU,UAAU;AACtC,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAgC,GAAG;AAC3E,aAAK,OAAO,cAAc,GAAG,CAAC;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAEA,OAAK,QAAQ,KAAK;AAIlB,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AACtD;AA4BO,SAAS,qBAAqB,UAA6B,CAAC,GAAmB;AACpF,QAAM,QAAQ,IAAI,IAAY,QAAQ,OAAO,CAAC,MAAM,EAAE,UAAU,iBAAiB,CAAC;AAKlF,MAAI,QAAkC;AACtC,SAAO;AAAA,IACL,OAAO,QAAQ;AACb,iBAAW,KAAK,QAAQ;AACtB,YAAI,OAAO,MAAM,YAAY,EAAE,SAAS,qBAAqB,MAAM,IAAI,CAAC,EAAG;AAC3E,cAAM,IAAI,CAAC;AACX,gBAAQ;AAAA,MACV;AAAA,IACF;AAAA,IACA,SAAS;AACP,UAAI,CAAC,MAAO,SAAQ,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AACjE,aAAO;AAAA,IACT;AAAA,EACF;AACF;AASO,SAAS,YAAY,MAAc,UAA6B,CAAC,GAAW;AACjF,MAAI,SAAS,aAAa,IAAI,EAAE;AAChC,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,OAAO,SAAS,MAAM,EAAG;AAC9B,aAAS,OAAO,MAAM,MAAM,EAAE,KAAK,6BAA6B;AAAA,EAClE;AACA,SAAO;AACT;AAcO,SAAS,WAAW,MAAe,UAA6B,CAAC,GAAY;AAClF,MAAI,SAAS,OAAW,QAAO;AAC/B,MAAI,OAAO,SAAS,SAAU,QAAO,YAAY,MAAM,OAAO;AAC9D,MAAI;AACF,UAAM,aAAa,KAAK,UAAU,IAAI;AACtC,QAAI,eAAe,OAAW,QAAO;AACrC,WAAO,YAAY,YAAY,OAAO;AAAA,EACxC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
AzureRbacAssignment,
|
|
9
9
|
AzureResource,
|
|
10
10
|
AzureSubscription
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-KTNSYBZN.js";
|
|
12
12
|
|
|
13
13
|
// src/azure/arm.ts
|
|
14
14
|
var noopLog = () => {
|
|
@@ -839,4 +839,4 @@ export {
|
|
|
839
839
|
listAccessibleSubscriptions,
|
|
840
840
|
buildAzureInventory
|
|
841
841
|
};
|
|
842
|
-
//# sourceMappingURL=chunk-
|
|
842
|
+
//# sourceMappingURL=chunk-AH5OW4T3.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isPlanRefusal,
|
|
3
3
|
planRefusalFrom
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-M6O7VA6Z.js";
|
|
5
5
|
import {
|
|
6
6
|
COLLECTOR_AUTH_HEADER,
|
|
7
7
|
IngestResult,
|
|
8
8
|
collectorBearer
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-66TRC3GH.js";
|
|
10
10
|
import {
|
|
11
11
|
ApiError,
|
|
12
12
|
CertReportResult,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
SddRunBatchResult,
|
|
16
16
|
SddRunCloseResult,
|
|
17
17
|
SddRunOpenResult
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-KTNSYBZN.js";
|
|
19
19
|
|
|
20
20
|
// src/core/push.ts
|
|
21
21
|
import { randomUUID } from "node:crypto";
|
|
@@ -368,4 +368,4 @@ export {
|
|
|
368
368
|
pushSddBatch,
|
|
369
369
|
pushSddRunClose
|
|
370
370
|
};
|
|
371
|
-
//# sourceMappingURL=chunk-
|
|
371
|
+
//# sourceMappingURL=chunk-CHN3HHUT.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-4RUBV5WB.js";
|
|
4
4
|
import {
|
|
5
5
|
VmwareIngestBody
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KTNSYBZN.js";
|
|
7
7
|
|
|
8
8
|
// src/vmware/soap.ts
|
|
9
9
|
import { XMLParser } from "fast-xml-parser";
|
|
@@ -1291,4 +1291,4 @@ export {
|
|
|
1291
1291
|
VsphereClient,
|
|
1292
1292
|
buildVmwareInventory
|
|
1293
1293
|
};
|
|
1294
|
-
//# sourceMappingURL=chunk-
|
|
1294
|
+
//# sourceMappingURL=chunk-FYKLZRHK.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VaultProtection
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KTNSYBZN.js";
|
|
4
4
|
import {
|
|
5
5
|
PKG_ROOT
|
|
6
6
|
} from "./chunk-CW3YCPEC.js";
|
|
@@ -795,4 +795,4 @@ export {
|
|
|
795
795
|
loadSensitiveDataConfig,
|
|
796
796
|
loadAzureConfig
|
|
797
797
|
};
|
|
798
|
-
//# sourceMappingURL=chunk-
|
|
798
|
+
//# sourceMappingURL=chunk-HB3DUE46.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HypervIngestBody
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KTNSYBZN.js";
|
|
4
4
|
|
|
5
5
|
// src/hyperv/scan.ts
|
|
6
6
|
import { spawn } from "node:child_process";
|
|
@@ -455,4 +455,4 @@ export {
|
|
|
455
455
|
scanHypervTargets,
|
|
456
456
|
buildHypervInventory
|
|
457
457
|
};
|
|
458
|
-
//# sourceMappingURL=chunk-
|
|
458
|
+
//# sourceMappingURL=chunk-IGTUXQVG.js.map
|
|
@@ -4332,6 +4332,29 @@ var CollectorSite = z20.object({
|
|
|
4332
4332
|
/** The name the portal shows. The whole reason a picker beats a typed id. */
|
|
4333
4333
|
name: z20.string(),
|
|
4334
4334
|
location: z20.string().nullable().default(null),
|
|
4335
|
+
/**
|
|
4336
|
+
* THE ORG THAT OWNS THIS SITE, WITHOUT WHICH A LOCALLY BUILT JOB CANNOT BE
|
|
4337
|
+
* INGESTED.
|
|
4338
|
+
*
|
|
4339
|
+
* An ALL-SITES collector has no org of its own — `orgId` is written empty at
|
|
4340
|
+
* enrolment on purpose, because each job is supposed to name the one it
|
|
4341
|
+
* belongs to. A job enqueued from the portal does: the plane knows the site
|
|
4342
|
+
* and stamps its org. A job built by the collector's OWN console does not,
|
|
4343
|
+
* and there was nowhere for it to learn one.
|
|
4344
|
+
*
|
|
4345
|
+
* The consequence was silent and expensive: the sweep ran to completion, the
|
|
4346
|
+
* snapshot was built with an empty `orgId`, and the plane refused the whole
|
|
4347
|
+
* push at `IngestBody.safeParse` because canonical `Id` is
|
|
4348
|
+
* `z.string().min(1)`. Twenty minutes of scanning discarded at the last step,
|
|
4349
|
+
* reported as a Zod dump in the module row.
|
|
4350
|
+
*
|
|
4351
|
+
* Defaulted to "" rather than required, for the same reason `buildings` is
|
|
4352
|
+
* defaulted: an older plane sends no such field, and a collector that
|
|
4353
|
+
* refused to parse the directory over it would lose its site picker
|
|
4354
|
+
* entirely. Empty here means what it has always meant — this collector must
|
|
4355
|
+
* fall back to its configured org, and a site-scoped collector has one.
|
|
4356
|
+
*/
|
|
4357
|
+
orgId: z20.string().default(""),
|
|
4335
4358
|
networks: z20.array(CollectorSiteNetwork),
|
|
4336
4359
|
/**
|
|
4337
4360
|
* The site's buildings, if the tenant has divided it into any.
|
|
@@ -11721,4 +11744,4 @@ export {
|
|
|
11721
11744
|
SddRunCloseResult,
|
|
11722
11745
|
ApiError
|
|
11723
11746
|
};
|
|
11724
|
-
//# sourceMappingURL=chunk-
|
|
11747
|
+
//# sourceMappingURL=chunk-KTNSYBZN.js.map
|