Verify exact task metadata baseline and readback
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
parent
5f30ddd90c
commit
d870596cc7
8 changed files with 274 additions and 14 deletions
|
|
@ -32,6 +32,8 @@ class PrivateSession:
|
|||
class FixtureAdmission:
|
||||
"""Independently installed owner fixture inputs, not a request schema."""
|
||||
descriptor: bytes
|
||||
expected_before: bytes
|
||||
expected_after: bytes
|
||||
owner_token: str = field(repr=False)
|
||||
identity_session: PrivateSession = field(repr=False)
|
||||
server_process: subprocess.Popen = field(repr=False)
|
||||
|
|
@ -78,6 +80,22 @@ class NativeFixtureAdapter:
|
|||
self.hcl+='path "auth/token/revoke-self" {\n capabilities = ["update"]\n}\n'
|
||||
if self.meta['execution_grant']['openbao']['policy']!={'name':self.policy_name,'hcl':self.hcl}:
|
||||
raise Refused('native grant body differs from bound owner projection')
|
||||
# Installed owner snapshots use the existing descriptor commitments. No
|
||||
# request-supplied expectation or response may authorize itself.
|
||||
self.expected={}
|
||||
for phase in ('before','after'):
|
||||
raw=getattr(admission,'expected_'+phase)
|
||||
if type(raw) is not bytes or 'sha256:'+content_hash(raw)!=descriptor['expected_'+phase]:
|
||||
raise Refused('owner expected-state digest mismatch')
|
||||
value=json.loads(raw)
|
||||
if type(value) is not dict or set(value)!=set(paths) or encoded(value)!=raw:
|
||||
raise Refused('canonical exact target snapshot required')
|
||||
if any(item is not None and type(item) is not dict for item in value.values()):
|
||||
raise Refused('metadata snapshot object or explicit absence required')
|
||||
if phase=='after' and any(item is None for item in value.values()):
|
||||
raise Refused('present final metadata required')
|
||||
self.expected[phase]=value
|
||||
self._observed={'before':{},'after':{}}
|
||||
self.cleanup=tuple(Cleanup(item['kind'],item['call_digest']) for item in cleanup_specs(binding.operation_id))
|
||||
if self.meta['cleanup'] != cleanup_specs(binding.operation_id): raise Refused('cleanup plan mismatch')
|
||||
self.task=None; self._mint_attempted=False; self._policy_attempted=False; self._ordinal=0; self._next_metadata=0
|
||||
|
|
@ -183,11 +201,53 @@ class NativeFixtureAdapter:
|
|||
call=self.compiler.before_call(self.plan,ordinal)
|
||||
status,data=self._business(call.method,call.path,self.task.token,call.payload,task=True)
|
||||
self._next_metadata+=1
|
||||
self._ok(status,data,{200,204,404} if ordinal in {0,3} else {200,204})
|
||||
# Metadata only. The trusted owner caller must compare native normalized
|
||||
# baseline/readback to separately admitted expected state. Not KV values.
|
||||
try:
|
||||
self._ok(status,data,{200,204,404} if ordinal in {0,3} else {200,204})
|
||||
if ordinal in {0,2,3,5}:
|
||||
phase='before' if ordinal in {0,3} else 'after'
|
||||
value=self._metadata_snapshot(call.path,status,data)
|
||||
if encoded(value)!=encoded(self.expected[phase][call.path]):
|
||||
raise Refused('native exact expected-state mismatch')
|
||||
self._observed[phase][call.path]=value
|
||||
except Exception:
|
||||
state=self.journal.observe(self.binding)['state']
|
||||
if state!='unknown': self.journal.transition(self.binding,state,'unknown')
|
||||
raise Refused('native baseline or readback unconfirmed') from None
|
||||
return status,data
|
||||
|
||||
@staticmethod
|
||||
def _metadata_snapshot(path,status,response):
|
||||
# HTTP errors/denials are never absence. OpenBao's exact empty 404
|
||||
# metadata response is the only absent representation admitted here.
|
||||
if status==404 and response=={'errors':[]}:
|
||||
return None
|
||||
if status!=200 or response.get('errors') or type(response.get('data')) is not dict:
|
||||
raise Refused('metadata read not confirmed')
|
||||
value=dict(response['data'])
|
||||
if path.startswith('sys/policies/acl/'):
|
||||
if set(value)!={'cas_required','modified','name','policy','version'}:
|
||||
raise Refused('unrecognized policy metadata fields')
|
||||
modified=value.pop('modified')
|
||||
if type(modified) is not str or datetime.fromisoformat(modified.replace('Z','+00:00')).tzinfo is None:
|
||||
raise Refused('invalid policy modification timestamp')
|
||||
# All role fields, aliases, defaults and unknown additions participate in
|
||||
# exact canonical JSON comparison. True never equals integer 1 here.
|
||||
return value
|
||||
|
||||
def verify_metadata(self):
|
||||
self._fresh()
|
||||
if self._next_metadata!=6 or self.journal.observe(self.binding)['state']!='applying':
|
||||
raise Refused('complete same-live metadata sequence required')
|
||||
for phase in ('before','after'):
|
||||
if encoded(self._observed[phase])!=encoded(self.expected[phase]):
|
||||
raise Refused('complete expected metadata evidence required')
|
||||
evidence=content_hash(encoded({'expected_before':'sha256:'+content_hash(self.admission.expected_before),
|
||||
'expected_after':'sha256:'+content_hash(self.admission.expected_after),
|
||||
'scope':'per-target-sequential-readback-no-native-cas'}))
|
||||
self.journal.transition(self.binding,'applying','readback',evidence)
|
||||
self.journal.transition(self.binding,'readback','verified',evidence)
|
||||
return evidence
|
||||
|
||||
def _cleanup_admitted(self, kind, digest):
|
||||
self._live()
|
||||
expected=next(item for item in self.cleanup if item.kind==kind)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue