coulomb-social/tests/test_bubble_access_audit.py
tegwick 52168c3bd4
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
Inventory retained source access fields without inferring grants
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
2026-10-31 15:07:15 +01:00

110 lines
4.3 KiB
Python

"""Missing access metadata must never turn into empty or approved permissions."""
import hashlib
import importlib.util
import json
from pathlib import Path
import pytest
SPEC = importlib.util.spec_from_file_location(
'bubble_access_audit', Path(__file__).resolve().parents[1] / 'scripts/audit-bubble-access.py')
audit = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(audit)
def inputs():
return {'spaces': {'1x1': {'crew_list_user': ['LOOKUP__User__9x9'],
'members_list_user': [], 'isprivate_boolean': False}},
'articles': {'2x2': {'_owner_user': '9x9', 'Created By': 'unresolved'}},
'retained_spaces': {'1x1': {}, '3x3': {}}}
def test_aliases_collapse_but_no_grants_or_empty_missing_inference():
report = audit.audit(inputs())
assert report['source_principals'] == ['9x9']
fields = report['records']['spaces'][0]['fields']
assert fields['members_list_user']['state'] == 'empty'
assert fields['guests_list_user']['state'] == 'missing'
created_by = report['records']['articles'][0]['fields']['Created By']
assert created_by['state'] == 'unresolved_reference'
assert report['inventory_only_space_ids'] == ['3x3']
assert report['summary']['known_spaces'] == 2
assert report['summary']['target_grants_proposed'] == 0
assert report['summary']['target_identity_mappings_established'] == 0
assert '9x9' not in json.dumps(report['summary'])
@pytest.mark.parametrize('raw,expected', [(None, 'null'), ('9x9', 'invalid_container'),
([], 'empty'), ([{}], 'unresolved_reference'),
(['9x9', None], 'unresolved_reference')])
def test_field_states(raw, expected):
result = audit.field_state({'members_list_user': raw}, 'members_list_user', True)
assert result['state'] == expected
assert result['raw'] == raw
def test_private_html_escapes_source_and_disables_network():
data = inputs()
data['articles']['2x2']['Created By'] = '<script>alert(1)</script>'
result = audit.review_html(audit.audit(data))
assert b'<script>' not in result
assert b'&lt;script&gt;' in result
assert b"default-src 'none'" in result
assert b"form-action 'none'" in result
def source_bundle(tmp_path):
tmp_path.chmod(0o700)
source = tmp_path / 'source'
source.mkdir(mode=0o700)
capture = source / 'source-capture'
capture.mkdir(mode=0o700)
hashes = {}
for kind, values in inputs().items():
raw = json.dumps(values).encode()
path = capture / (kind + '.json')
path.write_bytes(raw)
path.chmod(0o600)
hashes[kind] = hashlib.sha256(raw).hexdigest()
path = source / 'reconciliation.json'
path.write_text(json.dumps({'schema': 'coulomb.bubble-review-bundle.v1',
'status': 'completed_offline_preparation', 'source_sha256': hashes}))
path.chmod(0o600)
return source
def test_source_binding_private_modes_and_no_overwrite(tmp_path):
source = source_bundle(tmp_path)
before = {p: p.read_bytes() for p in source.rglob('*') if p.is_file()}
out = tmp_path / 'review'
result = audit.prepare(source, out)
assert all(p.read_bytes() == raw for p, raw in before.items())
assert not out.stat().st_mode & 0o077
for name, digest in result['output_sha256'].items():
assert hashlib.sha256((out / name).read_bytes()).hexdigest() == digest
assert not (out / name).stat().st_mode & 0o077
with pytest.raises(ValueError):
audit.prepare(source, out)
@pytest.mark.parametrize('defect', ['drift', 'public', 'symlink', 'hardlink', 'nested-output'])
def test_unsafe_custody_or_drift_refused(tmp_path, defect):
source = source_bundle(tmp_path)
path = source / 'source-capture/articles.json'
out = tmp_path / 'review'
if defect == 'drift':
path.write_text('{}')
elif defect == 'public':
path.chmod(0o644)
elif defect == 'symlink':
saved = path.with_suffix('.saved')
path.rename(saved)
path.symlink_to(saved)
elif defect == 'hardlink':
path.with_suffix('.linked').hardlink_to(path)
else:
out = source / 'review'
with pytest.raises(ValueError):
audit.prepare(source, out)
assert not out.exists()