fix: validate Gitea conversation caches and safe commit messages

This commit is contained in:
2026-10-13 13:50:10 +00:00
parent a7a13aa4d5
commit a74fb747a5
6 changed files with 227 additions and 17 deletions
@@ -138,11 +138,16 @@ class ReworkReadbackAdapter:
for scope in ('pr','pr_issue'):
spec = object_value(aggregate[scope])
parts = spec.get('components')
if (set(spec) != {'field','components'} or spec.get('field') != 'comments'
mode = spec.get('cache_mode')
allowed_keys = {'field','components'} if mode is None and 'cache_mode' not in spec else {'field','components','cache_mode'}
if (set(spec) != allowed_keys or spec.get('field') != 'comments'
or type(parts) is not list or not parts
or any(type(part) is not str or part not in ('top_level','reviews','inline') for part in parts)
or len(parts) != len(set(parts)) or 'top_level' not in parts):
raise ReadbackError('invalid aggregate count declaration')
if 'cache_mode' in spec and (mode != 'gitea-conversation-v1' or contract['version'] != '1.27.3'
or set(parts) != {'top_level','reviews'}):
raise ReadbackError('invalid aggregate cache declaration')
inline = object_value(contract.get('inline'))
if (set(inline) != {'mode','field','components'}
or inline.get('mode') not in ('per_review','per_review_or_pr_count')
@@ -392,7 +397,12 @@ class ReworkReadbackAdapter:
raise ReadbackError('inline provider counter crosscheck failed')
for scope in ('pr','pr_issue'):
spec = self.provider['aggregate'][scope]
if integer(raw[scope].get(spec['field'])) != sum(counts[name] for name in spec['components']):
observed = raw[scope].get(spec['field'])
computed = sum(counts[name] for name in spec['components'])
if spec.get('cache_mode') == 'gitea-conversation-v1':
if integer(observed) > computed:
raise ReadbackError('cached provider aggregate count exceeds collection')
elif integer(observed) != computed:
raise ReadbackError('provider aggregate count mismatch')
return counts
@@ -586,8 +596,17 @@ class ReworkReadbackAdapter:
raise ReadbackError('source Issue metadata drift')
else:
field = self.provider['aggregate'][name]['field']
if integer(now.pop(field)) != integer(before.pop(field)) + (1 if action == 'create' else 0):
spec = self.provider['aggregate'][name]
before_value, now_value = integer(before.get(field)), integer(now.get(field))
if spec.get('cache_mode') == 'gitea-conversation-v1':
desired = (sum(self.counts(a)[part] for part in spec['components'])
if action == 'create' else before_value)
if now_value != desired:
raise ReadbackError('cached PR counter causality mismatch')
elif now_value != before_value + (1 if action == 'create' else 0):
raise ReadbackError('PR counter delta causality mismatch')
before.pop(field)
now.pop(field)
if name != 'source_issue' and action == 'create' and now['updated_at'] != before['updated_at']:
if now['updated_at'] != matched['created_at']:
raise ReadbackError('uncausal Issue or PR timestamp')