Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a1029c-c003-7283-acc9-930b434e6cae
201 lines
8.8 KiB
Python
201 lines
8.8 KiB
Python
import io
|
|
import json
|
|
|
|
import pytest
|
|
|
|
from informed_decision.intake_service import IntakeError, IntakeService, TokenReview, AUDIENCE
|
|
from informed_decision.store import Store
|
|
from test_intake import envelope
|
|
|
|
USERNAME = 'system:serviceaccount:state-hub:state-hub'
|
|
APPROVAL = '12345678-1234-1234-1234-123456789abc'
|
|
|
|
|
|
def token_review(body):
|
|
assert body['spec'] == {'token': 'projected-token', 'audiences': [AUDIENCE]}
|
|
return {'status': {'authenticated': True, 'audiences': [AUDIENCE],
|
|
'user': {'username': USERNAME, 'uid': 'workload-uid'}}}
|
|
|
|
|
|
@pytest.fixture
|
|
def setup(tmp_path):
|
|
private = tmp_path / 'private'
|
|
private.mkdir(mode=0o700)
|
|
store = Store(private / 'review.sqlite')
|
|
submitters, groups = tmp_path / 'submitters.json', tmp_path / 'groups.json'
|
|
submitters.write_text(json.dumps({USERNAME: {'submitter_id': 'state-hub',
|
|
'memo_classes': ['credential-lane'], 'review_groups': ['net-kingdom-admins'], 'daily_limit': 2}}))
|
|
groups.write_text(json.dumps({'net-kingdom-admins': {'subject': 'keycape-human', 'display_name': 'Reviewer'}}))
|
|
calls = []
|
|
def create(body):
|
|
calls.append(body)
|
|
assert body['human_control'] is True and body['required_count'] == 1
|
|
return {'id': APPROVAL, 'status': 'requested', 'binding': {
|
|
**body['binding'], 'human_control': True, 'digest': 'sha256:' + 'a' * 64}}
|
|
service = IntakeService(store, TokenReview(token_review), create,
|
|
submitters_path=submitters, groups_path=groups)
|
|
return service, store, calls, submitters
|
|
|
|
|
|
def request(service, body, token='projected-token', path='/v1/memos'):
|
|
raw = json.dumps(body).encode()
|
|
environ = {'PATH_INFO': path, 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/json',
|
|
'CONTENT_LENGTH': str(len(raw)), 'HTTP_AUTHORIZATION': 'Bearer ' + token,
|
|
'wsgi.input': io.BytesIO(raw)}
|
|
response = []
|
|
result = b''.join(service(environ, lambda status, headers: response.append(status)))
|
|
return int(response[0].split()[0]), json.loads(result)
|
|
|
|
|
|
def test_pose_replay_and_restart(setup):
|
|
service, store, calls, _ = setup
|
|
status, receipt = request(service, envelope())
|
|
assert status == 201
|
|
assert receipt['approval_id'] == APPROVAL
|
|
memo = store.memo(receipt['memo_id'])
|
|
assert memo.binding.principal.id == 'keycape-human'
|
|
assert memo.sealed is False
|
|
assert store.memos_for('keycape-human') == [memo]
|
|
service.store = Store(store.path)
|
|
assert request(service, envelope()) == (200, receipt)
|
|
assert len(calls) == 1
|
|
with store._connection() as db:
|
|
assert db.execute('SELECT COUNT(*) FROM documents').fetchone()[0] == 1
|
|
assert db.execute('SELECT COUNT(*) FROM dispositions').fetchone()[0] == 0
|
|
|
|
|
|
def test_revocation_refuses_even_replay(setup):
|
|
service, _, calls, config = setup
|
|
assert request(service, envelope())[0] == 201
|
|
config.write_text('{}')
|
|
assert request(service, envelope()) == (403, {'error': 'submitter_unknown'})
|
|
assert len(calls) == 1
|
|
|
|
|
|
def test_conflicts_precede_create(setup):
|
|
service, _, calls, _ = setup
|
|
assert request(service, envelope())[0] == 201
|
|
changed = envelope()
|
|
changed['memo']['brief'] += ' Changed'
|
|
assert request(service, changed) == (409, {'error': 'idempotency_conflict'})
|
|
changed = envelope()
|
|
changed['idempotency_key'] = 'different-key'
|
|
assert request(service, changed) == (409, {'error': 'memo_id_taken'})
|
|
assert len(calls) == 1
|
|
|
|
|
|
def test_uncertain_create_never_reposts_or_loads(setup):
|
|
service, store, calls, _ = setup
|
|
def lost(body):
|
|
calls.append(body)
|
|
raise OSError('sensitive upstream body')
|
|
service.creator = lost
|
|
assert request(service, envelope()) == (503, {'error': 'approval_create_unresolved'})
|
|
service.store = Store(store.path)
|
|
assert request(service, envelope()) == (409, {'error': 'approval_create_unresolved'})
|
|
assert len(calls) == 1
|
|
with store._connection() as db:
|
|
assert db.execute('SELECT COUNT(*) FROM memos').fetchone()[0] == 0
|
|
assert db.execute('SELECT COUNT(*) FROM documents').fetchone()[0] == 0
|
|
|
|
|
|
def test_created_receipt_recovers_without_create(setup):
|
|
service, store, calls, _ = setup
|
|
# Fail the load transaction, after the receipt has been persisted.
|
|
with store._connection() as db:
|
|
db.execute("CREATE TRIGGER fail_load BEFORE INSERT ON memos BEGIN SELECT RAISE(ABORT,'failure'); END")
|
|
assert request(service, envelope())[0] == 503
|
|
with store._connection() as db:
|
|
assert db.execute('SELECT COUNT(*) FROM documents').fetchone()[0] == 0
|
|
assert db.execute('SELECT state FROM intake_ledger').fetchone()[0] == 'created'
|
|
db.execute('DROP TRIGGER fail_load')
|
|
assert request(service, envelope())[0] == 201
|
|
assert len(calls) == 1
|
|
|
|
|
|
def test_budget_and_no_browser_routes(setup):
|
|
service, _, calls, config = setup
|
|
data = json.loads(config.read_text())
|
|
data[USERNAME]['daily_limit'] = 1
|
|
config.write_text(json.dumps(data))
|
|
assert request(service, envelope())[0] == 201
|
|
another = envelope()
|
|
another['memo']['id'] = 'another-memo'
|
|
another['idempotency_key'] = 'another-key'
|
|
assert request(service, another) == (429, {'error': 'submitter_budget_exhausted'})
|
|
assert request(service, envelope(), path='/review')[0] == 404
|
|
assert len(calls) == 1
|
|
|
|
|
|
@pytest.mark.parametrize('status', [
|
|
{'authenticated': False},
|
|
{'authenticated': True, 'audiences': ['wrong'], 'user': {'username': USERNAME, 'uid': 'x'}},
|
|
{'authenticated': True, 'audiences': [AUDIENCE], 'user': {'username': 'human', 'uid': 'x'}},
|
|
{'authenticated': True, 'audiences': [AUDIENCE], 'user': {'username': USERNAME}},
|
|
])
|
|
def test_token_review_fails_closed(status):
|
|
with pytest.raises(IntakeError) as error:
|
|
TokenReview(lambda body: {'status': status}).authenticate('hidden-token')
|
|
assert error.value.code == 'workload_authentication_failed'
|
|
|
|
|
|
def test_notifications_retry_and_disabled_writeback_stays_pending(setup):
|
|
from informed_decision.intake_delivery import IntakeDeliveryWorker
|
|
service, store, _, _ = setup
|
|
assert request(service, envelope())[0] == 201
|
|
seen = []
|
|
now = [100.0]
|
|
def notify(delivery_id, payload):
|
|
seen.append((delivery_id, payload))
|
|
return len(seen) > 1
|
|
worker = IntakeDeliveryWorker(store, notify=notify, clock=lambda: now[0])
|
|
assert worker.run_once() == 0
|
|
now[0] += 10
|
|
assert worker.run_once() == 1
|
|
assert seen[0] == seen[1]
|
|
assert 'brief' not in seen[0][1] and 'packet' not in seen[0][1]
|
|
with store._connection() as db:
|
|
assert db.execute("SELECT state FROM intake_deliveries WHERE kind='memo-posed'").fetchone()[0] == 'pending'
|
|
|
|
|
|
def test_terminal_disposition_queues_writeback_atomically(setup):
|
|
from informed_decision.disposition import Actor, ActorKind, Verb
|
|
from informed_decision.provenance import Claim, Route
|
|
from informed_decision.intake_delivery import IntakeDeliveryWorker
|
|
service, store, _, _ = setup
|
|
env = envelope()
|
|
env['serves']['resolves'] = 'on-answer'
|
|
status, receipt = request(service, env)
|
|
assert status == 201
|
|
p = store.present(receipt['memo_id'], principal_sub='keycape-human',
|
|
tenant=Claim('tenant:platform', Route.REGISTRATION),
|
|
principal_type=Claim('human', Route.AUTHENTICATION))
|
|
actor = Actor('keycape-human', ActorKind.PERSON)
|
|
store.acknowledge(p.id, actor, store.memo(receipt['memo_id']).required_ack_ids)
|
|
d = store.record_disposition(p.id, actor, Verb.DECLINE, operation_id='decline-once', reasons=('wrong_scope',))
|
|
store.record_disposition(p.id, actor, Verb.DECLINE, operation_id='decline-once', reasons=('wrong_scope',))
|
|
calls = []
|
|
def transport(method, url, payload):
|
|
calls.append(payload)
|
|
return 200, {}
|
|
worker = IntakeDeliveryWorker(store, hub_transport=transport, hub_base_url='http://hub', env={})
|
|
assert worker.run_once() == 0 and calls == []
|
|
worker.env = {'INFD_HUB_WRITEBACK': '1'}
|
|
assert worker.run_once() == 1
|
|
assert d.id in calls[0]['rationale']
|
|
assert worker.run_once() == 0
|
|
|
|
|
|
def test_create_adapter_has_only_create_route():
|
|
from informed_decision.intake_approval import IntakeApprovalClient
|
|
calls = []
|
|
class Transport:
|
|
def request(self, method, url, *, headers, body):
|
|
calls.append((method, url, json.loads(body)))
|
|
assert headers['Authorization'] == 'Bearer workload-token'
|
|
return 201, {'id': APPROVAL}
|
|
client = IntakeApprovalClient('https://engine.example', lambda: 'workload-token', transport=Transport())
|
|
assert client({'binding': {'actor': 'informed-decision'}, 'human_control': True, 'required_count': 1}) == {'id': APPROVAL}
|
|
assert calls[0][0:2] == ('POST', 'https://engine.example/v1/approvals')
|
|
assert calls[0][2]['pdp_path'] is False
|
|
assert 'validity' in calls[0][2]
|