Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions skills/sourcepack/scripts/sourcelens/pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def build_pack(run,destination,include_originals=True):
gaps.extend(cm.get('gaps',[]));scope='acquired' if root==run else f'companion-{len(register)+1}-acquired'
if include_originals:
for p in (root/'acquired').rglob('*'):
if p.is_symlink():raise ContractError('Acquisition originals cannot contain symlinks')
if not p.is_file():continue
if p.name=='request.json' or p.name.startswith('worker.'):
omissions.append({'path':str(p.relative_to(root)),'reason':'runtime diagnostics; retained privately in run'});continue
Expand Down
32 changes: 32 additions & 0 deletions tests/test_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,35 @@ def test_supporting_sources_are_bounded_and_uninspected(self):
child=root/'child4';w.prepare(str(p),child)
with self.assertRaises(ContractError):register_supporting_source(run,child,'extra')
self.assertEqual(len(w.load(run)[1]['supporting_sources']),3)
def test_collection_export_rejects_unregistered_acquisition_symlinks(self):
for kind in ('file', 'directory', 'broken'):
with self.subTest(kind=kind), tempfile.TemporaryDirectory() as td:
root=Path(td);source=root/'source.md';source.write_text('Synthetic source.')
run=root/'run';w.prepare(str(source),run)
outside=root/'outside';outside.mkdir();private=outside/'private.txt';private.write_text('Synthetic private data.')
target={'file':private,'directory':outside,'broken':outside/'missing'}[kind]
(run/'acquired'/'unregistered').symlink_to(target,target_is_directory=kind=='directory')
destination=root/'export'
with self.assertRaisesRegex(ContractError,'symlink'):
build_pack(run,destination)
self.assertFalse(destination.exists())
self.assertEqual(private.read_text(),'Synthetic private data.')
def test_collection_export_rejects_supporting_source_acquisition_symlink(self):
with tempfile.TemporaryDirectory() as td:
root=Path(td);source=root/'source.md';source.write_text('Synthetic source.')
run=root/'run';child=root/'child';w.prepare(str(source),run);w.prepare(str(source),child)
register_supporting_source(run,child,'official docs')
private=root/'private.txt';private.write_text('Synthetic private data.')
(child/'acquired'/'unregistered.txt').symlink_to(private)
with self.assertRaisesRegex(ContractError,'symlink'):
build_pack(run,root/'export')
self.assertFalse((root/'export').exists())
def test_lightweight_collection_export_does_not_read_unregistered_symlink(self):
with tempfile.TemporaryDirectory() as td:
root=Path(td);source=root/'source.md';source.write_text('Synthetic source.')
run=root/'run';w.prepare(str(source),run)
private=root/'private.txt';private.write_text('Synthetic private data.')
(run/'acquired'/'unregistered.txt').symlink_to(private)
build_pack(run,root/'export',include_originals=False)
self.assertFalse((root/'export'/'acquired').exists())
self.assertFalse(json.loads((root/'export'/'manifest.json').read_text())['self_contained_originals'])
Loading