This commit is contained in:
@@ -5,10 +5,13 @@ const { deploymentIdentity, deploymentEvidenceHash, deploymentAuthorityKey } = r
|
||||
const BACKUP = /(?:^|[\\/._-])(backup|bak|archive|snapshot|old|previous)(?:[\\/._-]|$)/i;
|
||||
const RELEASE = /(?:^|[\\/])(releases?|versions?)(?:[\\/]|$)/i;
|
||||
const STAGING = /(?:^|[\\/._-])(staging|stage|test|qa|preview)(?:[\\/._-]|$)/i;
|
||||
const TEMPORARY = /(?:^|[\\/._-])(candidate|rollback|ephemeral)(?:[\\/._-]|$)|^GITEA-ACTIONS-TASK-/i;
|
||||
const SYSTEM = /^(?:traefik|nginx-proxy-manager|watchtower|portainer|dockerman|unraid-|cloudflared|redis|postgres|mariadb|mysql)(?:$|[-_.])/i;
|
||||
|
||||
function baseClassification(workload) {
|
||||
const location = `${workload.compose?.workingDir || ""} ${(workload.compose?.configFiles || []).join(" ")}`;
|
||||
const sourceRepository = String(workload.metadata?.sourceRepository || "").trim();
|
||||
const hasGitProvenance = /^(?:git@|ssh:\/\/|https?:\/\/)/i.test(sourceRepository);
|
||||
const decision = workload.reviewDecision;
|
||||
if (["manual-exclude", "exclude-scan-root", "ignore"].includes(decision?.action)) return { type: "manually-excluded", reason: decision.reason || "Persisted manual exclusion", decisionAction: decision.action };
|
||||
if (["mark-historical", "archive-link"].includes(decision?.action)) return { type: "historical-compose", reason: decision.reason || "Reviewed as historical", decisionAction: decision.action };
|
||||
@@ -17,12 +20,13 @@ function baseClassification(workload) {
|
||||
if (BACKUP.test(location)) return { type: "backup", reason: "Path matches backup/archive evidence" };
|
||||
if (RELEASE.test(location)) return { type: "release-folder", reason: "Path is below a release/version directory" };
|
||||
if (STAGING.test(location)) return { type: "staging", reason: "Path or project identifies a staging/test workload" };
|
||||
if (TEMPORARY.test(`${workload.displayName || ""} ${location}`)) return { type: "temporary-runtime", reason: "Runtime identity marks a candidate, rollback or CI workload" };
|
||||
if (SYSTEM.test(workload.displayName || "") && !workload.metadata?.sourceRepository) return { type: "system-container", reason: "Known infrastructure identity without repository provenance" };
|
||||
if (workload.link && workload.runtime?.running) return { type: "active-application", reason: "Linked deployment with running container evidence" };
|
||||
if (workload.link && !workload.runtime?.running) return { type: "stopped-application", reason: "Linked deployment without a running container" };
|
||||
if (!workload.containers?.length && workload.compose?.configFiles?.length) return { type: "historical-compose", reason: "Compose definition exists without container runtime" };
|
||||
if (workload.status === "ambiguous") return { type: "ambiguous", reason: "Multiple candidates have equivalent evidence" };
|
||||
if (!workload.metadata?.sourceRepository && !workload.candidates?.length) return { type: "orphan-container", reason: "Runtime has no repository provenance or candidate" };
|
||||
if (!workload.candidates?.length) return { type: "external-container", reason: hasGitProvenance ? "Repository provenance does not match an accessible configured Gitea repository" : "Runtime has no Git repository provenance and remains monitoring-only" };
|
||||
if (!workload.runtime?.running && workload.candidates?.length) return { type: "stopped-application", reason: "Stopped runtime has repository evidence" };
|
||||
return { type: workload.runtime?.running ? "active-application" : "ambiguous", reason: workload.runtime?.running ? "Running application evidence" : "Insufficient authoritative evidence" };
|
||||
}
|
||||
@@ -46,8 +50,12 @@ function classifyInventory(workloads, profiles = [], decisions = []) {
|
||||
}
|
||||
workload.evidenceHash = hash;
|
||||
workload.classification = baseClassification(workload);
|
||||
if (workload.link && ["backup", "release-folder", "staging", "temporary-runtime", "historical-compose", "system-container", "external-container", "manually-excluded"].includes(workload.classification.type)) {
|
||||
workload.shadowedLink = workload.link;
|
||||
workload.link = null;
|
||||
}
|
||||
const key = deploymentAuthorityKey(identity);
|
||||
if (identity.repository) {
|
||||
if (identity.repository && (workload.link || workload.candidates?.length) && !["backup", "release-folder", "staging", "temporary-runtime", "historical-compose", "system-container", "external-container", "manually-excluded"].includes(workload.classification.type)) {
|
||||
const group = authorities.get(key) || [];
|
||||
group.push(workload);
|
||||
authorities.set(key, group);
|
||||
@@ -55,17 +63,21 @@ function classifyInventory(workloads, profiles = [], decisions = []) {
|
||||
return workload;
|
||||
});
|
||||
for (const group of authorities.values()) {
|
||||
if (group.length < 2) continue;
|
||||
if (group.length < 2) {
|
||||
group[0].authoritative = true;
|
||||
continue;
|
||||
}
|
||||
const ranked = [...group].sort((a, b) => Number(b.reviewDecision?.action === "select-authoritative") - Number(a.reviewDecision?.action === "select-authoritative") || Number(b.runtime?.running) - Number(a.runtime?.running) || Number(Boolean(b.link)) - Number(Boolean(a.link)) || Number(Boolean(b.metadata?.liveRevision)) - Number(Boolean(a.metadata?.liveRevision)));
|
||||
ranked[0].authoritative = true;
|
||||
for (const duplicate of ranked.slice(1)) {
|
||||
duplicate.authoritative = false;
|
||||
duplicate.classification = { type: "duplicate", reason: `Conflicts with authoritative workload ${ranked[0].workloadId}`, authoritativeWorkloadId: ranked[0].workloadId };
|
||||
duplicate.status = "duplicate";
|
||||
duplicate.shadowedLink = duplicate.link;
|
||||
duplicate.link = null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = { classifyInventory, classifyWorkload: baseClassification, inventoryPathPatterns: { BACKUP, RELEASE, STAGING, SYSTEM } };
|
||||
module.exports = { classifyInventory, classifyWorkload: baseClassification, inventoryPathPatterns: { BACKUP, RELEASE, STAGING, TEMPORARY, SYSTEM } };
|
||||
|
||||
Reference in New Issue
Block a user