Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
98 lines
6.6 KiB
Python
98 lines
6.6 KiB
Python
"""Pure proposed grant projection: source provenance, never approval/native proof."""
|
|
import copy
|
|
from pathlib import Path
|
|
import sys
|
|
import pytest
|
|
sys.path.insert(0,str(Path(__file__).resolve().parents[1]/'scripts'))
|
|
import task_execution_grant as grant
|
|
|
|
|
|
@pytest.fixture
|
|
def record():
|
|
return {'id':'CCR-FIXTURE-GRANT','kind':'credential-change-request','schema_version':1,
|
|
'request_type':'task-execution-grant','title':'Proposed source fixture','status':'proposed',
|
|
'created':'2026-10-16','updated':'2026-10-16','requester':{'agent':'fixture','reason':'Local proof'},
|
|
'review':{'required':True,'required_approvers':['railiance-platform-owner','secrets-engine-owner','access-engine-owner','approval-engine-owner'],'comments':[]},
|
|
'target':{'domain':'infotech','tenant':'platform','workload':'secrets-engine','environment':'production','purpose':'fixture'},
|
|
'execution':{'action':'execute-ccr','descriptor_binding':{'operation_deadline':'2026-10-16T12:00:00Z','ccr_immutable_sha256':'sha256:'+'a'*64},
|
|
'source_pins':{'/fixture/source':'sha256:'+'b'*64},'cleanup':[{'kind':'task-token-revoke','call_digest':'c'*64}]},
|
|
'openbao':{'policy':{'name':'task-exec-fixture','hcl':'exact owner generated HCL'},
|
|
'token_create_body':{'ttl':'120s','num_uses':12,'renewable':False}},'evidence':{'events':[]}}
|
|
|
|
|
|
def comment():return {'at':'2026-10-16T12:00:00Z','reviewer':'railiance-platform-owner','decision':'approved','comment':'Source only; no execution authority'}
|
|
def event():return {'at':'2026-10-16T12:00:00Z','kind':'test','result':'unknown','reference_sha256':'sha256:'+'e'*64}
|
|
|
|
|
|
def test_only_typed_review_comments_and_evidence_events_are_excluded(record):
|
|
changed=copy.deepcopy(record);changed['review']['comments'].append(comment());changed['evidence']['events'].append(event())
|
|
assert grant.immutable_digest(changed)==grant.immutable_digest(record)
|
|
grant.require_append_only(record,changed)
|
|
assert record['review']['comments']==[] # detached immutable projection
|
|
|
|
|
|
@pytest.mark.parametrize('field',['status','updated','title','requester','target','execution','openbao','review'])
|
|
def test_every_other_root_or_effectful_field_changes_digest(record,field):
|
|
changed=copy.deepcopy(record)
|
|
if field=='status':changed[field]='approved'
|
|
elif field=='updated':changed[field]='2026-10-17'
|
|
elif field=='title':changed[field]='different title'
|
|
elif field=='requester':changed[field]['reason']='different requester reason'
|
|
elif field=='target':changed[field]['purpose']='different purpose'
|
|
elif field=='execution':changed[field]['source_pins']['/fixture/source']='sha256:'+'f'*64
|
|
elif field=='openbao':changed[field]['policy']['hcl']='different HCL'
|
|
elif field=='review':changed[field]['required_approvers'].reverse()
|
|
if field=='review':
|
|
with pytest.raises(grant.Refused):grant.immutable_digest(changed)
|
|
else:
|
|
assert grant.immutable_digest(changed)!=grant.immutable_digest(record)
|
|
with pytest.raises(grant.Refused):grant.require_append_only(record,changed)
|
|
|
|
|
|
@pytest.mark.parametrize('location,key',[('root','audit'),('root','receipts'),('root','evidence_exclusions'),('evidence','files'),('evidence','policy'),('review','approval_ref'),('review','exclusions')])
|
|
def test_guessed_evidence_exclusions_or_unknown_fields_refuse(record,location,key):
|
|
changed=copy.deepcopy(record)
|
|
(changed if location=='root' else changed[location])[key]=[]
|
|
with pytest.raises(grant.Refused):grant.immutable_digest(changed)
|
|
|
|
|
|
def test_append_only_rejects_removal_rewrite_and_reordering(record):
|
|
previous=copy.deepcopy(record);previous['review']['comments']=[comment(),dict(comment(),comment='Second')]
|
|
previous['evidence']['events']=[event()]
|
|
for field,value in [('comments',[]),('comments',[dict(comment(),decision='declined')]),('comments',list(reversed(previous['review']['comments']))),('events',[])]:
|
|
changed=copy.deepcopy(previous);changed['review' if field=='comments' else 'evidence'][field]=value
|
|
assert grant.immutable_digest(changed)==grant.immutable_digest(previous)
|
|
with pytest.raises(grant.Refused):grant.require_append_only(previous,changed)
|
|
|
|
|
|
@pytest.mark.parametrize('change',['policy','token_budget','cleanup','source','deadline','target_ccr','wrong_hash','grant_id'])
|
|
def test_bind_reconstructs_effects_and_exact_existing_descriptor_join(record,change):
|
|
expected=copy.deepcopy(record);changed=copy.deepcopy(record);digest=grant.immutable_digest(record);grant_id=record['id']
|
|
if change=='policy':changed['openbao']['policy']['hcl']='path "*" {}'
|
|
elif change=='token_budget':changed['openbao']['token_create_body']['num_uses']=13
|
|
elif change=='cleanup':changed['execution']['cleanup'][0]['kind']='kv-delete'
|
|
elif change=='source':changed['execution']['source_pins']['/fixture/source']='sha256:'+'f'*64
|
|
elif change=='deadline':changed['execution']['descriptor_binding']['operation_deadline']='2027-01-01T00:00:00Z'
|
|
elif change=='target_ccr':changed['execution']['descriptor_binding']['ccr_immutable_sha256']='sha256:'+'f'*64
|
|
elif change=='wrong_hash':digest='sha256:'+'f'*64
|
|
elif change=='grant_id':grant_id='CCR-OTHER'
|
|
with pytest.raises(grant.Refused):grant.bind(changed,grant_id=grant_id,expected_execution=expected['execution'],expected_openbao=expected['openbao'],expected_digest=digest)
|
|
|
|
|
|
def test_proposed_source_record_can_bind_without_becoming_approved(record):
|
|
projection=grant.bind(record,grant_id=record['id'],expected_execution=record['execution'],expected_openbao=record['openbao'],expected_digest=grant.immutable_digest(record))
|
|
assert projection['status']=='proposed'
|
|
|
|
|
|
@pytest.mark.parametrize('change',['schema_bool','comment_extra','event_extra','unaware_comment','event_missing','nan','tuple','integer_key','status_list'])
|
|
def test_closed_types_refuse_instead_of_silent_coercion(record,change):
|
|
if change=='schema_bool':record['schema_version']=True
|
|
elif change=='comment_extra':record['review']['comments']=[dict(comment(),policy='unreviewed')]
|
|
elif change=='event_extra':record['evidence']['events']=[dict(event(),token='never accepted')]
|
|
elif change=='unaware_comment':record['review']['comments']=[dict(comment(),at='2026-10-16T12:00:00')]
|
|
elif change=='event_missing':record['evidence']['events']=[{'kind':'test'}]
|
|
elif change=='nan':record['execution']['value']=float('nan')
|
|
elif change=='tuple':record['execution']['value']=(1,2)
|
|
elif change=='integer_key':record['execution'][1]='invalid'
|
|
elif change=='status_list':record['status']=[]
|
|
with pytest.raises(grant.Refused):grant.immutable_digest(record)
|