intake evidence β classify the box β apply policy rules β produce readiness / scan / agent posture β flag exceptions β generate a report.
WTF is in this box?
What is this?
Do we know enough?
Who owns it?
Where does it live?
Can we scan it?
Can we install an agent?
What is the risk?
What exception is needed?
What should happen next?Β
Automation shape
1. Intake
β
2. Normalize evidence
β
3. Classify machine type + zone
β
4. Apply policy rules
β
5. Produce output report / recommendation / exceptionCore files
Example
policy-engine/
βββ policies/
β βββ readiness_policy.yml
β βββ scan_agent_policy.yml
β βββ zone_mapping.yml
βββ schemas/
β βββ asset_input.schema.json
β βββ assessment_output.schema.json
βββ examples/
β βββ standard_it_server.yml
β βββ legacy_server.yml
β βββ vendor_appliance.yml
β βββ plc.yml
β βββ unknown_device.yml
βββ tests/
β βββ test_policy_cases.yml
βββ output/
β βββ assessments/
βββ assess_box.py
The central input: βWTF is this box?β
Every assessment starts with a machine record:
asset_id: BOX-001
hostname: srv-mail-01
owner: infrastructure_team
requested_role: mail_server
machine_type: standard_it_server
zone: enterprise
evidence:
inventory_record: true
owner_attestation: true
authenticated_scan: true
cloud_metadata: false
vendor_documentation: false
network_observation: true
attributes:
os_known: true
support_status: supported
internet_facing: false
safety_critical: false
vendor_managed: false
legacy: false
fragile: false
short_lived: false
operational_impact_unknown: false
constraints:
agent_install_forbidden: false
active_scan_forbidden: false
requires_manual_approval: false
That gives the policy engine enough material to make a decision without inventing things in the fog.
Policy A: readiness rules
policy_id: readiness_policy
policy_name: Machine Readiness Policy
version: 0.1
default_status: review_required
statuses:
- approved
- approved_with_limitations
- review_required
- rejected
- exception_required
- unknown
rules:
- id: RDY-001
description: System must have a known owner.
when:
owner: null
result:
readiness_status: unknown
confidence: low
recommendation: Identify accountable owner before onboarding.
- id: RDY-002
description: System must have a declared role.
when:
requested_role: null
result:
readiness_status: unknown
confidence: low
recommendation: Confirm business or technical function.
- id: RDY-003
description: System must map to a known machine type.
when:
machine_type: unknown
result:
readiness_status: review_required
confidence: low
recommendation: Classify machine type before assessment.
- id: RDY-004
description: Legacy systems require limitation notes.
when:
attributes.legacy: true
result:
readiness_status: approved_with_limitations
confidence: medium
limitation: Legacy system requires controlled handling.
- id: RDY-005
description: Vendor-managed systems require support restriction review.
when:
attributes.vendor_managed: true
result:
readiness_status: exception_required
confidence: medium
recommendation: Review vendor contract and support restrictions.
- id: RDY-006
description: OT or safety-critical systems require human review.
when:
attributes.safety_critical: true
result:
readiness_status: review_required
confidence: medium
recommendation: Require operational impact review before onboarding.
Policy B: scan / agent posture rules
policy_id: scan_agent_policy
policy_name: Scan / Agent Posture Policy
version: 0.1
default_scan_posture: limited
default_agent_posture: restricted
scan_postures:
- normal_authenticated
- controlled
- limited
- passive_only
- manual_evidence_only
- prohibited
agent_postures:
- allowed
- allowed_with_controls
- restricted
- prohibited
- exception_required
- not_applicable
rules:
- id: TCH-001
description: If operational impact is unknown, do not actively scan.
when:
attributes.operational_impact_unknown: true
result:
scan_posture: passive_only
agent_posture: restricted
recommendation: Confirm operational impact before active assessment.
- id: TCH-002
description: Safety-critical systems default to passive or manual evidence.
when:
attributes.safety_critical: true
result:
scan_posture: manual_evidence_only
agent_posture: prohibited
recommendation: Use owner/vendor evidence unless exception is approved.
- id: TCH-003
description: Vendor restrictions may prohibit agents.
when:
constraints.agent_install_forbidden: true
result:
agent_posture: prohibited
recommendation: Do not install agent.
- id: TCH-004
description: Fragile systems require controlled scan and restricted agent posture.
when:
attributes.fragile: true
result:
scan_posture: controlled
agent_posture: restricted
recommendation: Use controlled assessment window.
- id: TCH-005
description: Internet-facing systems require controlled scanning.
when:
attributes.internet_facing: true
result:
scan_posture: controlled
agent_posture: allowed_with_controls
recommendation: Log and scope scan activity.
- id: TCH-006
description: Unknown systems must not be scanned or modified.
when:
machine_type: unknown
result:
scan_posture: prohibited
agent_posture: prohibited
recommendation: Identify system before assessment.
Zone mapping automation
This is where the network diagram becomes useful without becoming the law.
zones:
enterprise:
typical_systems:
- it_server
- workstation
- dns
- mail
- jump_host
default_scan_posture: normal_authenticated
default_agent_posture: allowed
notes: Standard managed space.
it_dmz:
typical_systems:
- vpn
- web_server
- internet_facing_service
default_scan_posture: controlled
default_agent_posture: allowed_with_controls
notes: Higher exposure, controlled scanning required.
ot_dmz:
typical_systems:
- patch_mirror
- jump_host
- wsus
- vault
default_scan_posture: limited
default_agent_posture: restricted
notes: Bridge zone between IT and OT.
supervisory:
typical_systems:
- hmi
- historian
- scada
- application_server
default_scan_posture: limited
default_agent_posture: restricted
notes: Industrial context, role-based assessment.
local_station:
typical_systems:
- plc
- rtu
- relay
- sensor
- tac
default_scan_posture: manual_evidence_only
default_agent_posture: prohibited
notes: Fragile operational systems.
remote_ami:
typical_systems:
- meter
- access_point
- bridge
- field_device
default_scan_posture: limited
default_agent_posture: prohibited
notes: Remote constraints and ownership issues.
Output format
The engine should produce this:
asset_id: BOX-001
hostname: srv-mail-01
decision:
readiness_status: approved
scan_posture: normal_authenticated
agent_posture: allowed
confidence: high
findings:
- Owner is known.
- Requested role is known.
- Machine type is standard IT server.
- Zone allows normal authenticated scan.
- No agent restrictions identified.
limitations: []
recommendations:
- Admit system into managed workflow.
- Use standard authenticated scan.
- Agent installation allowed under normal controls.
exceptions:
required: false
reasons: []
reassessment:
required: true
cadence: annual
"Minimum!" viable automation
Input one machine YAML
Apply readiness policy
Apply scan / agent policy
Apply zone defaults
Produce assessment YAML or JSONThat is enough to prove the concept.
First Python sketch
import yaml
from pathlib import Path
def get_nested_value(data, dotted_key):
current = data
for part in dotted_key.split("."):
if not isinstance(current, dict):
return None
current = current.get(part)
return current
def condition_matches(asset, condition):
for key, expected in condition.items():
actual = get_nested_value(asset, key)
if actual != expected:
return False
return True
def apply_rules(asset, policy):
results = {
"matched_rules": [],
"readiness_status": policy.get("default_status"),
"scan_posture": policy.get("default_scan_posture"),
"agent_posture": policy.get("default_agent_posture"),
"confidence": "medium",
"findings": [],
"limitations": [],
"recommendations": [],
"exceptions": {
"required": False,
"reasons": []
}
}
for rule in policy.get("rules", []):
if condition_matches(asset, rule.get("when", {})):
results["matched_rules"].append(rule["id"])
rule_result = rule.get("result", {})
for key, value in rule_result.items():
if key == "recommendation":
results["recommendations"].append(value)
elif key == "limitation":
results["limitations"].append(value)
elif key == "readiness_status" and value == "exception_required":
results["readiness_status"] = value
results["exceptions"]["required"] = True
results["exceptions"]["reasons"].append(rule["description"])
else:
results[key] = value
results["findings"].append(rule["description"])
return results
def merge_results(*result_sets):
merged = {
"matched_rules": [],
"readiness_status": None,
"scan_posture": None,
"agent_posture": None,
"confidence": "medium",
"findings": [],
"limitations": [],
"recommendations": [],
"exceptions": {
"required": False,
"reasons": []
}
}
for result in result_sets:
merged["matched_rules"].extend(result.get("matched_rules", []))
merged["findings"].extend(result.get("findings", []))
merged["limitations"].extend(result.get("limitations", []))
merged["recommendations"].extend(result.get("recommendations", []))
for key in ["readiness_status", "scan_posture", "agent_posture", "confidence"]:
if result.get(key):
merged[key] = result[key]
if result.get("exceptions", {}).get("required"):
merged["exceptions"]["required"] = True
merged["exceptions"]["reasons"].extend(
result["exceptions"].get("reasons", [])
)
return merged
def assess(asset_path):
asset = yaml.safe_load(Path(asset_path).read_text())
readiness_policy = yaml.safe_load(Path("policies/readiness_policy.yml").read_text())
scan_agent_policy = yaml.safe_load(Path("policies/scan_agent_policy.yml").read_text())
readiness_result = apply_rules(asset, readiness_policy)
scan_agent_result = apply_rules(asset, scan_agent_policy)
decision = merge_results(readiness_result, scan_agent_result)
assessment = {
"asset_id": asset.get("asset_id"),
"hostname": asset.get("hostname"),
"machine_type": asset.get("machine_type"),
"zone": asset.get("zone"),
"owner": asset.get("owner"),
"requested_role": asset.get("requested_role"),
"decision": {
"readiness_status": decision.get("readiness_status"),
"scan_posture": decision.get("scan_posture"),
"agent_posture": decision.get("agent_posture"),
"confidence": decision.get("confidence"),
},
"matched_rules": decision["matched_rules"],
"findings": decision["findings"],
"limitations": decision["limitations"],
"recommendations": decision["recommendations"],
"exceptions": decision["exceptions"],
"reassessment": {
"required": True,
"cadence": "annual"
}
}
return assessment
if __name__ == "__main__":
result = assess("examples/standard_it_server.yml")
print(yaml.dump(result, sort_keys=False))The real product hiding in this
This becomes a policy-guided infrastructure intake engine.
Not a scanner.
Not an agent.
Not Kubernetes confetti.
Not βAI will fix it.β
It answers:
What is this?
Do we know enough?
Who owns it?
Where does it live?
Can we scan it?
Can we install an agent?
What is the risk?
What exception is needed?
What should happen next?That is an actual business object.
The first automation target should be:
Given one machine record, produce a readiness + touchability decision.
That is the little iron beetle we build first. Then we can bolt on CSV intake, diagram-zone mapping, report generation, and test cases after it walks.
πͺ²