Files
EscapistsReintroduced/docs/evidence/config-supply-recovery-2026-10-03/optional-identity/fix.patch
T
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

177 lines
9.3 KiB
Diff

--- /dev/null
+++ b/tools/resource_references.py
@@ -0,0 +1,31 @@
+"""Hard resource references, with one fail-closed audited optional identity test.
+
+This is not a general Enforce parser or a new external dependency allowlist.
+Changing any byte of the audited source requires reviewing this exception again.
+"""
+import hashlib
+import re
+
+OPTIONAL_FILE = 'addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c'
+OPTIONAL_SHA256 = 'bcdf98c05ac6cdf0c7eaa854531b02e9ee4f53fbb346ae01d58114e572e7dd4f'
+OPTIONAL_RESOURCE = '{574AA64002B8E308}Prefabs/Characters/REAPER_SpectatorCameraHelper.et'
+OPTIONAL_METHOD = ''' protected static bool CameraSlot(BaseContainer slot)
+ {
+ if (!slot || slot.GetName() != "SpectatorCameraHelper") return false;
+ ResourceName prefab;
+ if (!slot.Get("Prefab", prefab)) return false;
+ return prefab == "{574AA64002B8E308}Prefabs/Characters/REAPER_SpectatorCameraHelper.et";
+ }'''
+
+
+def hard_resource_references(relative_path, text):
+ """Exclude only the pinned comparison occurrence; keep all other checks."""
+ identity_offset = -1
+ if (str(relative_path) == OPTIONAL_FILE
+ and hashlib.sha256(text.encode('utf-8')).hexdigest() == OPTIONAL_SHA256
+ and text.count(OPTIONAL_METHOD) == 1
+ and text.count(OPTIONAL_RESOURCE) == 1):
+ identity_offset = text.index(OPTIONAL_METHOD) + OPTIONAL_METHOD.index(OPTIONAL_RESOURCE)
+ for match in re.finditer(r'\{([A-F0-9]{16})\}([^"\n]+)', text):
+ if match.start() != identity_offset:
+ yield match.groups()
--- a/tools/check.py
+++ b/tools/check.py
@@ -2,6 +2,7 @@
"""Validate addon/resource isolation and execute policy regressions. Not an engine compiler."""
from pathlib import Path
import json,re,subprocess,sys
+from resource_references import hard_resource_references
from external_addons import policy, ALLOWED, direct_for, resource_allowed
from prefab_identity import check_prefabs
ROOT=Path(__file__).resolve().parents[1]
@@ -65,7 +66,7 @@
if not p.is_file() or p.suffix not in ['.c','.et','.conf','.ent','.layer','.layout','.emat','.bt']:continue
s=p.read_text()
assert not re.search(r'\b(?:ESCT\w*|SCRTC_\w+|SCRT_\w+|EAI_\w+)\b',s),f'Original ecosystem dependency: {p}'
- for g,path in re.findall(r'\{([A-F0-9]{16})\}([^"\n]+)',s):
+ for g,path in hard_resource_references(p.relative_to(ROOT).as_posix(),s):
assert resources.get(g)==path or vanilla.get(path)==g or resource_allowed(external,visibility[p.relative_to(ROOT/'addons').parts[0]],g,path),f'Unresolved/mismatched resource in {p}: {g} {path}'
if g in owners:
addon=p.relative_to(ROOT/'addons').parts[0]
--- a/tools/source_bundle.py
+++ b/tools/source_bundle.py
@@ -16,6 +16,7 @@
from source_manifest import addon_manifest
from project_schema import parse_project
+from resource_references import hard_resource_references
from external_addons import policy as external_policy, direct_for, resource_allowed, ALLOWED
from release_check import audit, read_json, evidence_path
@@ -151,7 +152,7 @@
owner = name.split('/')[1]
visible = {owner, *PROJECTS[owner][2]}
if 'core' in visible: visible.update(ALLOWED)
- for guid, resource in re.findall(r'\{([A-F0-9]{16})\}([^"\n]+)', text):
+ for guid, resource in hard_resource_references(name, text):
if guid in resources:
path, target = resources[guid]
if path != resource or target not in visible:
--- a/tests/test_external_addons.py
+++ b/tests/test_external_addons.py
@@ -1,5 +1,9 @@
#!/usr/bin/env python3
"""Exercise exact dependency closure, resource ownership and isolated profile inputs."""
+import ast
+import importlib.util
+import os
+import re
import copy
import hashlib
import json
@@ -9,8 +13,11 @@
import tempfile
import unittest
sys.path.insert(0,str(Path(__file__).resolve().parents[1]/'tools'))
+TOOLS=Path(os.environ.get('ERR_OPTIONAL_IDENTITY_TOOLS',Path(__file__).resolve().parents[1]/'tools'))
+sys.path.insert(0,str(TOOLS))
+import resource_references as refs
import external_addons as ext
-ROOT=Path(__file__).resolve().parents[1]
+ROOT=Path(os.environ.get('ERR_REPO',Path(__file__).resolve().parents[1]))
class ExternalAddonsTests(unittest.TestCase):
def setUp(self):
@@ -69,4 +76,68 @@
pak=self.source/ext.DIRECT[0]/'data.pak';pak.unlink();pak.symlink_to(self.source/ext.DIRECT[1]/'data.pak')
with self.assertRaisesRegex(ValueError,'regular file'):ext.installed(self.source,self.value)
+
+class OptionalIdentityTests(unittest.TestCase):
+ def setUp(self):
+ self.name=refs.OPTIONAL_FILE
+ self.text=(ROOT/self.name).read_text()
+ self.guid='574AA64002B8E308';self.resource='Prefabs/Characters/REAPER_SpectatorCameraHelper.et'
+ def rejected_reference(self,name,text):
+ self.assertIn((self.guid,self.resource),list(refs.hard_resource_references(name,text)))
+ def test_exact_comparison_only_and_every_other_reference_retained(self):
+ all_refs=re.findall(r'\{([A-F0-9]{16})\}([^"\n]+)',self.text)
+ expected=[pair for pair in all_refs if pair!=(self.guid,self.resource)]
+ self.assertEqual(list(refs.hard_resource_references(self.name,self.text)),expected)
+ self.assertIn(('37578B1666981FCE','Prefabs/Characters/Core/Character_Base.et'),expected)
+ self.rejected_reference('addons/core/Scripts/Game/Other.c',self.text)
+ for changed in [
+ self.text+'\n', # even a benign source edit needs renewed audit
+ self.text.replace('return prefab ==', 'Resource.Load(prefab); return prefab =='),
+ self.text.replace('return prefab ==', 'return Resource.Load(').replace(refs.OPTIONAL_RESOURCE+'";',refs.OPTIONAL_RESOURCE+'");'),
+ self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");',
+ self.text+'\nSpawn("'+refs.OPTIONAL_RESOURCE+'");',
+ self.text+'\nResourceName extra = "'+refs.OPTIONAL_RESOURCE+'";',
+ self.text.replace(refs.OPTIONAL_METHOD,'/*'+refs.OPTIONAL_METHOD+'*/'),
+ self.text.replace('CameraSlot(BaseContainer slot)','DifferentMethod(BaseContainer slot)'),
+ self.text.replace('if (!ModsPresent()) return false;',''),
+ ]: self.rejected_reference(self.name,changed)
+ unknown=self.text.replace(self.guid,'574AA64002B8E309')
+ self.assertIn(('574AA64002B8E309',self.resource),list(refs.hard_resource_references(self.name,unknown)))
+ # The optional addon never enters either resource policy or dependency closure.
+ value=ext.policy(ROOT)
+ self.assertNotIn('5EB139459EBF5C16',ext.ALLOWED)
+ self.assertFalse(ext.resource_allowed(value,set(ext.ALLOWED),self.guid,self.resource))
+ def repository_resource_loop(self,name,text):
+ # Execute the actual dependency-scanner loop without running the full suite.
+ source=Path(os.environ.get('ERR_OPTIONAL_CHECK_SOURCE',TOOLS/'check.py')).read_text()
+ tree=ast.parse(source)
+ loops=[node for node in ast.walk(tree) if isinstance(node,ast.For) and isinstance(node.target,ast.Tuple)
+ and [getattr(n,'id',None) for n in node.target.elts]==['g','path']]
+ self.assertEqual(len(loops),1)
+ code=compile(ast.fix_missing_locations(ast.Module(body=loops,type_ignores=[])),'actual_repository_resource_loop','exec')
+ env=dict(re=re,hard_resource_references=refs.hard_resource_references,p=ROOT/name,ROOT=ROOT,s=text,
+ resources={},owners={},vanilla=json.loads((ROOT/'docs/vanilla-resources.json').read_text()),
+ external=ext.policy(ROOT),visibility={'core':{'core',*ext.ALLOWED}},resource_allowed=ext.resource_allowed)
+ exec(code,env)
+ def test_actual_repository_resource_loop(self):
+ self.repository_resource_loop(self.name,self.text)
+ for name,text in [(self.name,self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");'),
+ ('addons/core/Scripts/Game/Other.c',self.text),
+ (self.name,self.text.replace('return prefab ==','return Resource.Load(').replace(refs.OPTIONAL_RESOURCE+'";',refs.OPTIONAL_RESOURCE+'");'))]:
+ with self.assertRaisesRegex(AssertionError,'Unresolved/mismatched'):
+ self.repository_resource_loop(name,text)
+ def test_actual_bundle_validator(self):
+ path=Path(os.environ.get('ERR_OPTIONAL_BUNDLE_SOURCE',TOOLS/'source_bundle.py'))
+ spec=importlib.util.spec_from_file_location('optional_test_source_bundle',path)
+ bundle=importlib.util.module_from_spec(spec);spec.loader.exec_module(bundle)
+ payload={name:(ROOT/name).read_bytes() for name in bundle.inventory(ROOT)}
+ before=ext.policy(ROOT)
+ bundle.validate(payload,ROOT)
+ self.assertEqual(before,ext.policy(ROOT))
+ for changed in [self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");',
+ self.text+'\nSpawn("'+refs.OPTIONAL_RESOURCE+'");']:
+ altered=dict(payload);altered[self.name]=changed.encode()
+ with self.assertRaisesRegex(ValueError,'unresolved or nonvanilla'):
+ bundle.validate(altered,ROOT)
+
if __name__=='__main__':unittest.main()
--- a/docs/vanilla-resources.json
+++ b/docs/vanilla-resources.json
@@ -48,6 +48,7 @@
"Prefabs/AI/Waypoints/AIWaypoint_Move.et": "750A8D1695BD6998",
"Prefabs/AI/Waypoints/AIWaypoint_SearchAndDestroy.et": "B3E7B8DC2BAB8ACC",
"Prefabs/Characters/Campaign/Final/OPFOR/USSR_Army/Regular/Campaign_USSR_Player_MortarCrew.et": "86E565387A634103",
+ "Prefabs/Characters/Core/Character_Base.et": "37578B1666981FCE",
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Base.et": "836E7E39AAC5888B",
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_HeliPilot.et": "42A502E3BB727CEB",
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Sniper.et": "0F6689B491641155",