diff --git a/docs/credential-lane-designs/factory-native-acceptance.md b/docs/credential-lane-designs/factory-native-acceptance.md index 864f4ee..1c4acc6 100644 --- a/docs/credential-lane-designs/factory-native-acceptance.md +++ b/docs/credential-lane-designs/factory-native-acceptance.md @@ -82,3 +82,9 @@ For independent readback, use `readback` inside a fresh attended envelope with the exact packet/run/event identities and reads only those already stored probe records and chain metadata. It creates no Job and emits no new event. The operator login remains required for that separate registry-backed reader. + +The native local rehearsal uses a setgid tmpfs root to represent fsGroup +volume inheritance. Informed Decision initializes its store through its actual +container helper; unsafe existing private directories remain refused. Failed +Jobs retain only allowlisted assertion codes and HTTP status numbers before +UID-scoped cleanup; arbitrary container output is discarded. diff --git a/scripts/native_factory_acceptance.py b/scripts/native_factory_acceptance.py index 6ff4aa3..6d76bda 100644 --- a/scripts/native_factory_acceptance.py +++ b/scripts/native_factory_acceptance.py @@ -22,7 +22,7 @@ from state_hub_preflight_lane import ROOT, LaneError, command, bao, data IMAGE = 'forgejo.coulomb.social/coulomb/approval-engine@sha256:251941a5cb2724b57cc32cff6b693b1ab0be695bee4f56f02d51961189c0fa49' RECEIVER = 'forgejo.coulomb.social/coulomb/audit-core@sha256:c82e0442de0fd181342916ae9cd5d6de41d859e1efda637bd93936c67873afa5' SOURCES = {'approval-engine':('a0a602976eef818f36dde35f76f7f2e589bd051b','approval_engine'), - 'informed-decision':('bda9381f070859ae997474cf44b86bf4eea9bb52','informed_decision')} + 'informed-decision':('1a122235741d61b649e39ab86ddfbd317e54ad2f','informed_decision')} CONFIRM = 'VERIFY CCR-2026-0021 CCR-2026-0022 PRODUCERS' diff --git a/scripts/native_factory_probe/producer.py b/scripts/native_factory_probe/producer.py index 46be089..0bdb774 100644 --- a/scripts/native_factory_probe/producer.py +++ b/scripts/native_factory_probe/producer.py @@ -157,7 +157,13 @@ def main(): require(hashlib.sha256(Path('/probe/source.zip').read_bytes()).hexdigest() == config['source_zip_sha256'], 'source_bundle_mismatch') sys.path.insert(0,'/probe/source.zip') os.umask(0o077) - directory = Path('/state/private'); directory.mkdir(mode=0o700,exist_ok=True) + directory = Path('/state/private') + receipt['phase'] = 'bootstrap' + if config['sender'] == 'informed-decision': + from informed_decision.container import private_directory + directory = private_directory(directory) + else: + directory.mkdir(mode=0o700,exist_ok=True) dbpath = directory/'outbox.db' if len(sys.argv)>1: receipt['phase'] = sys.argv[1] diff --git a/tests/test_factory_native_acceptance.py b/tests/test_factory_native_acceptance.py index 4635f7d..217ce49 100644 --- a/tests/test_factory_native_acceptance.py +++ b/tests/test_factory_native_acceptance.py @@ -85,7 +85,7 @@ class LocalReceiver(unittest.TestCase): (d/'config.json').write_text(json.dumps(config));token=d/'token';token.write_text(tokens[sender]);token.chmod(0o444) argv=['docker','run','--rm','--network','host','--read-only','--cap-drop=ALL', '--security-opt=no-new-privileges','--memory=192m', - '--tmpfs','/state:rw,nosuid,nodev,size=32m,mode=1777', + '--tmpfs','/state:rw,nosuid,nodev,size=32m,mode=2777', '--mount','type=bind,src='+str(d)+',dst=/probe,readonly', '--mount','type=bind,src='+str(token)+',dst=/credential/token,readonly', '--entrypoint','python',native.IMAGE,'-I','/probe/producer.py']