05ed037fe8
- DNS: pilot.landvex.com -> 16.170.83.169 - TLS: Let's Encrypt certificate (expires 2026-09-30) - Nginx: reverse proxy with SSL termination - API: https://pilot.landvex.com/api/v1/missions - UI: https://pilot.landvex.com/ - Upload: POST /api/v1/missions/import (multipart/form-data) Verified: ✅ https://pilot.landvex.com/health ✅ https://pilot.landvex.com/version ✅ https://pilot.landvex.com/api/v1/missions (list) ✅ https://pilot.landvex.com/api/v1/missions/:id (get) ✅ POST /api/v1/missions/import (video upload) ✅ UI loads with title 'LandveX Intelligence Lab' Next: Pilot 001 — Break the system!
189 lines
4.5 KiB
JavaScript
189 lines
4.5 KiB
JavaScript
#!/usr/bin/env node
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// Evidence Weights — Viktad evidens för bättre resolution
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Evidence Weights
|
|
*
|
|
* Varje evidens-signal har en vikt. Resolution avgör utifrån
|
|
* den sammanlagda vikten, inte långa listor av specialfall.
|
|
*/
|
|
|
|
const EVIDENCE_WEIGHTS = {
|
|
// Miljö
|
|
targetEnvironment: {
|
|
production: 100,
|
|
staging: 50,
|
|
development: 10
|
|
},
|
|
|
|
// Åtkomstmetoder
|
|
accessMethod: {
|
|
ssh: 120,
|
|
ssm: 120,
|
|
telnet: 120,
|
|
rdp: 120,
|
|
api: 80,
|
|
sdk: 80,
|
|
'aws-cli': 80
|
|
},
|
|
|
|
// Dataoperationer
|
|
dataOperation: {
|
|
update: 120,
|
|
delete: 120,
|
|
insert: 120,
|
|
alter: 120,
|
|
drop: 120,
|
|
select: -40,
|
|
read: -40
|
|
},
|
|
|
|
// Infrastrukturoperationer
|
|
infraOperation: {
|
|
create: 120,
|
|
modify: 120,
|
|
update: 120,
|
|
delete: 120,
|
|
configure: 120,
|
|
scale: 100,
|
|
inventory: -60,
|
|
plan: -60,
|
|
validate: -60
|
|
},
|
|
|
|
// Releaseoperationer
|
|
releaseOperation: {
|
|
deploy: 120,
|
|
release: 120,
|
|
publish: 120,
|
|
push: 120
|
|
},
|
|
|
|
// Sekretess
|
|
secretPattern: {
|
|
hardcoded_secret: 150,
|
|
password: 150,
|
|
token: 150,
|
|
api_key: 150
|
|
},
|
|
|
|
// Filtyper
|
|
fileType: {
|
|
mjs: 80,
|
|
js: 80,
|
|
ts: 80,
|
|
json: 60,
|
|
yml: 60,
|
|
yaml: 60,
|
|
md: -80, // Markdown är dokumentation
|
|
txt: -60, // Textfiler är dokumentation
|
|
tf: 100, // Terraform är infrastruktur
|
|
hcl: 100
|
|
},
|
|
|
|
// Kontext
|
|
context: {
|
|
manual: 20,
|
|
direct: 30,
|
|
temporary: 10
|
|
},
|
|
|
|
// Läsoperationer
|
|
readOperation: {
|
|
true: -80 // Läsning minskar risk avsevärt
|
|
},
|
|
|
|
// Observation
|
|
observeOperation: {
|
|
inventory: -100,
|
|
plan: -100,
|
|
validate: -100,
|
|
'health-check': -100
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Beräkna total vikt för en given evidensuppsättning
|
|
*/
|
|
function calculateWeightedScore(evidence) {
|
|
let score = 0;
|
|
const breakdown = {};
|
|
|
|
for (const [key, value] of Object.entries(evidence)) {
|
|
if (value === null || value === false || value === undefined) continue;
|
|
|
|
const weights = EVIDENCE_WEIGHTS[key];
|
|
if (!weights) continue;
|
|
|
|
let weight = 0;
|
|
|
|
if (typeof value === 'boolean') {
|
|
weight = weights.true || weights[String(value)] || 0;
|
|
} else if (typeof value === 'string') {
|
|
weight = weights[value] || 0;
|
|
} else if (Array.isArray(value)) {
|
|
for (const item of value) {
|
|
weight += weights[item] || 0;
|
|
}
|
|
}
|
|
|
|
score += weight;
|
|
breakdown[key] = { value, weight };
|
|
}
|
|
|
|
return { score, breakdown };
|
|
}
|
|
|
|
/**
|
|
* Avgör operation baserat på viktad score
|
|
*/
|
|
function resolveByWeight(evidence, candidates) {
|
|
const { score, breakdown } = calculateWeightedScore(evidence);
|
|
|
|
// Hitta den kandidat som bäst matchar den viktade scoren
|
|
let bestMatch = null;
|
|
let bestScore = -Infinity;
|
|
|
|
for (const candidate of candidates) {
|
|
let matchScore = 0;
|
|
|
|
// Basera på kandidatens konfidens
|
|
matchScore += candidate.confidence * 100;
|
|
|
|
// Justera baserat på evidens
|
|
if (candidate.operation === 'REMOTE_PRODUCTION_ACCESS' && evidence.accessMethod) {
|
|
matchScore += 50;
|
|
}
|
|
if (candidate.operation === 'MODIFY_PERSISTENT_PRODUCTION_DATA' && evidence.dataOperation) {
|
|
matchScore += 50;
|
|
}
|
|
if (candidate.operation === 'MODIFY_PRODUCTION_INFRASTRUCTURE' && evidence.infraOperation) {
|
|
matchScore += 50;
|
|
}
|
|
if (candidate.operation === 'PRODUCTION_RELEASE' && evidence.releaseOperation) {
|
|
matchScore += 50;
|
|
}
|
|
if (candidate.operation === 'EXPOSE_OR_CREATE_SECRET' && evidence.secretPattern) {
|
|
matchScore += 50;
|
|
}
|
|
|
|
// Markdown-filer minskar risk för data/infrastruktur-operationer
|
|
if (evidence.fileType === 'md' || evidence.fileType === 'txt') {
|
|
if (['MODIFY_PERSISTENT_PRODUCTION_DATA', 'MODIFY_PRODUCTION_INFRASTRUCTURE'].includes(candidate.operation)) {
|
|
matchScore -= 100;
|
|
}
|
|
}
|
|
|
|
if (matchScore > bestScore) {
|
|
bestScore = matchScore;
|
|
bestMatch = candidate;
|
|
}
|
|
}
|
|
|
|
return { bestMatch, weightedScore: score, breakdown };
|
|
}
|
|
|
|
export { EVIDENCE_WEIGHTS, calculateWeightedScore, resolveByWeight };
|