fix: report truthful compatibility outcomes and verify audit coverage
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e747-8f27-7242-8df8-8bc44f88c929
This commit is contained in:
parent
c0383c9c2b
commit
72f3513954
7 changed files with 246 additions and 16 deletions
|
|
@ -256,3 +256,57 @@ def test_receiver_failure_persists_backoff_across_connection_reopen(database):
|
|||
finally:
|
||||
await reopened.aclose()
|
||||
asyncio.run(run())
|
||||
|
||||
|
||||
def test_compatibility_key_transaction_and_outcome_rollback(database):
|
||||
import httpx
|
||||
from hub_core.runtime.app import create_app
|
||||
from hub_core.runtime.config import RuntimeSettings
|
||||
from hub_core.runtime.tables import compat_api_consumers, compat_api_keys
|
||||
from test_access_boundary import HEADERS
|
||||
|
||||
url,_ = database
|
||||
async def run():
|
||||
store = store_for(url)
|
||||
owners = Owners()
|
||||
groups = frozenset({'credentials'})
|
||||
app = create_app(settings=RuntimeSettings(environment='test',access_mode='enforce',
|
||||
backend='postgresql',v2_groups=groups,v2_write_groups=groups),
|
||||
port_store=store,access_controller=owners.controller())
|
||||
async def snapshot(table):
|
||||
async with store.sessions() as session:
|
||||
return [dict(row) for row in (await session.execute(sa.select(table))).mappings()]
|
||||
def fail(connection,cursor,statement,parameters,context,many):
|
||||
if statement.startswith('INSERT INTO runtime_outcome_outbox'):
|
||||
raise RuntimeError('fixture outbox failure')
|
||||
try:
|
||||
async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app,raise_app_exceptions=False),
|
||||
base_url='http://test') as client:
|
||||
created = await client.post('/api/v2/api-consumers',headers=HEADERS,json={'name':'Fixture'})
|
||||
assert created.status_code == 201
|
||||
path = '/api-consumers/'+created.json()['id']+'/api-keys'
|
||||
before = await snapshot(compat_api_consumers)
|
||||
sa.event.listen(store.engine.sync_engine,'before_cursor_execute',fail)
|
||||
try:
|
||||
failed = await client.post(path,headers=HEADERS,json={})
|
||||
assert failed.status_code == 500
|
||||
finally:
|
||||
sa.event.remove(store.engine.sync_engine,'before_cursor_execute',fail)
|
||||
assert await snapshot(compat_api_consumers) == before
|
||||
assert not await snapshot(compat_api_keys)
|
||||
assert len(await pending(store)) == 1
|
||||
issued = await client.post(path,headers=HEADERS,json={})
|
||||
assert issued.status_code == 201
|
||||
assert len(await snapshot(compat_api_keys)) == 1
|
||||
assert await snapshot(compat_api_consumers) != before
|
||||
outcomes = await pending(store)
|
||||
assert len(outcomes) == 2
|
||||
assert {row['envelope']['data']['operation'] for row in outcomes} == {
|
||||
'compat.consumer.created','compat.api_key.created'}
|
||||
assert all(row['envelope']['data']['authorization']['subject'] == 'immutable-root'
|
||||
for row in outcomes)
|
||||
assert issued.json()['fullKey'] not in json.dumps(outcomes)
|
||||
assert len(await snapshot(runtime_audit_ledger)) == 2
|
||||
finally:
|
||||
await store.aclose()
|
||||
asyncio.run(run())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue