net-kingdom/identity-provisioner/tests/test_group_postgres.py
tegwick 70f408ca23
Some checks failed
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Identity provider journey acceptance / provider (push) Failing after 13s
Build and Publish identity-provisioner / build-and-push (push) Successful in 26s
feat(identity): add PostgreSQL provenance and verify sealed SOPS custody
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1468b-63fa-7710-85dc-8f2e16b3ebfa
2026-10-17 01:36:38 +02:00

231 lines
12 KiB
Python

"""Binding, CAS and ambiguous-commit refusal tests; native SQL proof is separate."""
from dataclasses import replace
import json
from unittest.mock import Mock
import unittest
from group_provenance import GroupProvenanceUnavailable
from group_provenance_postgres import GroupJournalBinding, PostgresGroupProvenance
from server import configured_group_provenance
from unittest.mock import patch
import os
EPOCH = '41fbb0ed-ea3a-4682-996b-e9c94a6aa9c6'
BINDING = GroupJournalBinding('tenant:fixture:one', 'synthetic-directory', 'sha256:' + '1' * 64,
'sha256:' + '2' * 64, 'synthetic-owner', EPOCH)
REQUEST = '3' * 64
HEAD_DIGEST = 'a' * 64
META = (EPOCH, 'synthetic-directory', 7, HEAD_DIGEST, False)
def fixture(rows=(), rowcount=1, commit_error=None):
cursor = Mock()
cursor.__enter__ = Mock(return_value=cursor)
cursor.__exit__ = Mock(return_value=False)
cursor.fetchone.side_effect = rows
cursor.rowcount = rowcount
connection = Mock()
connection.__enter__ = Mock(return_value=connection)
connection.__exit__ = Mock(return_value=False, side_effect=commit_error)
connection.cursor.return_value = cursor
connector = Mock(return_value=connection)
continuity = Mock()
continuity.check.return_value = True
continuity.advance.return_value = True
store = PostgresGroupProvenance(connect=connector, binding=BINDING, continuity=continuity)
return store, connector, connection, cursor, continuity
def receipt(version=4):
return {'key': 'synthetic-operation-key', 'binding': REQUEST, 'state': 'pending', 'intent': None,
'groups': {}, 'created_groups': [], 'created_memberships': [],
'_pg_version': version, '_pg_context': BINDING.digest}
class PostgresSourceTests(unittest.TestCase):
def test_explicit_binding_and_continuity_required_without_connecting(self):
connector = Mock()
for binding, continuity in ((None, Mock()), (BINDING, None), ({'tenant_scope': 'caller-json'}, Mock())):
with self.assertRaises(ValueError):
PostgresGroupProvenance(connect=connector, binding=binding, continuity=continuity)
connector.assert_not_called()
for change in ({'tenant_scope': ''}, {'principal': ''}, {'case_digest': 'unsigned'}, {'epoch': 'default'}):
with self.assertRaises(ValueError):
replace(BINDING, **change)
self.assertNotEqual(BINDING.digest, replace(BINDING, principal='another-owner').digest)
self.assertNotEqual(BINDING.digest, replace(BINDING, tenant_scope='another-explicit-scope').digest)
def test_missing_environment_callback_path_keeps_production_disabled(self):
with patch.dict(os.environ, {'GROUP_POSTGRES_DSN': 'synthetic-only', 'GROUP_PROVENANCE_POSTGRES': 'true'}, clear=True):
self.assertIsNone(configured_group_provenance())
def test_checkpoint_mismatch_poisoned_without_receipt_query_or_effect(self):
store, connect, _, cursor, checkpoint = fixture([META])
checkpoint.check.return_value = False
with self.assertRaises(GroupProvenanceUnavailable):
store.reserve('synthetic-operation-key', REQUEST)
self.assertFalse(any('group_receipts' in c.args[0] for c in cursor.execute.call_args_list))
with self.assertRaises(GroupProvenanceUnavailable):
store.check()
self.assertEqual(1, connect.call_count)
checkpoint.advance.assert_not_called()
def test_restored_epoch_or_quarantine_refused(self):
for meta in ((EPOCH, 'other-directory', 7, HEAD_DIGEST, False), (EPOCH, 'synthetic-directory', 7, HEAD_DIGEST, True),
('98aa2b6d-a32a-44a5-a89f-b2480befc00e', 'synthetic-directory', 7, HEAD_DIGEST, False), None):
store, _, _, _, checkpoint = fixture([meta])
with self.assertRaises(GroupProvenanceUnavailable):
store.check()
checkpoint.check.assert_not_called()
def test_exactly_one_version_update_required_before_checkpoint_advance(self):
store, _, _, cursor, checkpoint = fixture([META], rowcount=0)
original = receipt()
with self.assertRaises(GroupProvenanceUnavailable):
store.save(original)
query, params = next(c.args for c in cursor.execute.call_args_list if c.args[0].startswith('UPDATE identity_provisioner.group_receipts'))
self.assertIn('AND version = %s', query)
self.assertEqual(4, params[-1])
self.assertEqual(4, original['_pg_version'])
checkpoint.advance.assert_not_called()
def test_success_acknowledges_commit_and_updates_receipt_version(self):
store, _, connection, _, checkpoint = fixture([META])
original = receipt()
store.save(original)
self.assertEqual(5, original['_pg_version'])
connection.__exit__.assert_called_once()
args = checkpoint.advance.call_args.args
self.assertEqual((EPOCH, 'synthetic-directory', 7, HEAD_DIGEST, 8), args[:5])
self.assertRegex(args[5], r'^[0-9a-f]{64}$')
self.assertNotEqual(HEAD_DIGEST, args[5])
connection.close.assert_called_once()
def test_save_preserves_nested_receipt_references_held_by_provisioner(self):
store, *_ = fixture([META])
original = receipt()
original['groups']['forge-coulomb-owners'] = {'id': None, 'before': [], 'after': ['tegwick']}
state = original['groups']['forge-coulomb-owners']
groups, created, memberships = original['groups'], original['created_groups'], original['created_memberships']
original['intent'] = {'operation': 'create_group', 'name': 'forge-coulomb-owners'}
store.save(original)
self.assertIs(groups, original['groups'])
self.assertIs(state, original['groups']['forge-coulomb-owners'])
self.assertIs(created, original['created_groups'])
self.assertIs(memberships, original['created_memberships'])
state['id'] = 4
self.assertEqual(4, original['groups']['forge-coulomb-owners']['id'])
self.assertEqual(5, original['_pg_version'])
def test_actual_provisioner_ensure_with_postgres_save_retains_created_ids(self):
from test_service_groups import Directory, req
directory = Directory()
directory.members[3].add('tegwick')
store, _, _, cursor, _ = fixture([META] * 32)
original = receipt(version=1)
payload = req()
original['key'] = payload['idempotency_key']
original['binding'] = directory._group_binding(payload['groups'], payload['members'], payload['correlation_id'])
# Reservation input is already covered by SQL unit/native oracles. Keep
# real save/_write/transaction and the real provisioner creation path.
store.reserve = Mock(return_value=(original, True))
directory.group_provenance = store
result = directory.ensure_service_groups(payload)
self.assertEqual('groups_ensured', result.status)
self.assertEqual({'forge-coulomb-owners', 'forge-coulomb-readers'}, {g['name'] for g in result.created_groups})
self.assertEqual(1, len(result.created_memberships))
self.assertEqual({'tegwick'}, directory.members[3])
bodies = [json.loads(c.args[1][2]) for c in cursor.execute.call_args_list
if c.args[0].startswith('UPDATE identity_provisioner.group_receipts')]
self.assertTrue(all(g['id'] is not None for g in bodies[-1]['groups'].values()))
self.assertEqual('ensured', bodies[-1]['state'])
def test_connection_close_failure_is_sanitized_and_stops_continuation(self):
store, _, connection, _, _ = fixture([META])
connection.close.side_effect = OSError('synthetic-private-diagnostic')
with self.assertRaisesRegex(GroupProvenanceUnavailable, '^group_provenance_unavailable$'):
store.check()
self.assertTrue(store._poisoned)
def test_commit_failure_never_advances_owner_checkpoint_or_receipt(self):
store, _, _, _, checkpoint = fixture([META], commit_error=OSError('synthetic-secret-diagnostic'))
original = receipt()
with self.assertRaisesRegex(GroupProvenanceUnavailable, '^group_provenance_unavailable$'):
store.save(original)
self.assertEqual(4, original['_pg_version'])
checkpoint.advance.assert_not_called()
def test_lost_checkpoint_acknowledgment_refuses_then_poisoned(self):
store, connect, _, _, checkpoint = fixture([META])
checkpoint.advance.side_effect = OSError('synthetic-secret-diagnostic')
original = receipt()
with self.assertRaisesRegex(GroupProvenanceUnavailable, '^group_provenance_unavailable$'):
store.save(original)
self.assertEqual(4, original['_pg_version'])
with self.assertRaises(GroupProvenanceUnavailable):
store.save(original)
self.assertEqual(1, connect.call_count)
def test_cross_case_body_or_version_cannot_be_imported(self):
for body in (dict(receipt(), _pg_context='0' * 64), dict(receipt(), _pg_version=6)):
store, _, _, _, _ = fixture([META, (REQUEST, 4, json.dumps(body), json.dumps(BINDING.__dict__, sort_keys=True))])
with self.assertRaises(GroupProvenanceUnavailable):
store.get('synthetic-operation-key', REQUEST)
def test_same_counter_divergent_body_or_context_yields_distinct_marker(self):
store, *_ = fixture()
markers = []
for change in ({}, {'intent': {'operation': 'different'}}, {'key': 'another-exact-key'}, {'_pg_version': 5}):
tx = {'head': 7, 'digest': HEAD_DIGEST}
store._transition(tx, dict(receipt(), **change), 'save')
markers.append(tx['next_digest'])
self.assertEqual(4, len(set(markers)))
tx = {'head': 7, 'digest': 'b' * 64}
store._transition(tx, receipt(), 'save')
self.assertNotIn(tx['next_digest'], markers)
foreign, *_ = fixture()
foreign.binding = replace(BINDING, principal='another-owner')
tx = {'head': 7, 'digest': HEAD_DIGEST}
foreign._transition(tx, receipt(), 'save')
self.assertNotIn(tx['next_digest'], markers)
def test_reopened_loser_clone_at_same_head_refuses_different_marker(self):
# Both DBs report head8. The independent callback accepts only winner
# digest; loser must be refused before loading any receipt or effect.
loser_digest = 'b' * 64
store, _, _, cursor, checkpoint = fixture([(EPOCH, 'synthetic-directory', 8, loser_digest, False)])
checkpoint.check.side_effect = lambda epoch, directory, head, digest: (head, digest) == (8, 'c' * 64)
with self.assertRaises(GroupProvenanceUnavailable):
store.check()
checkpoint.check.assert_called_once_with(EPOCH, 'synthetic-directory', 8, loser_digest)
self.assertFalse(any('group_receipts' in c.args[0] for c in cursor.execute.call_args_list))
def test_existing_request_mismatch_is_refused_not_rebound(self):
store, _, _, _, checkpoint = fixture([META, ('0' * 64, 4, '{}', '{}')])
with self.assertRaisesRegex(ValueError, 'binding mismatch'):
store.get('synthetic-operation-key', REQUEST)
checkpoint.advance.assert_not_called()
self.assertFalse(store._poisoned)
def test_active_fence_capacity_refusal_and_no_insert(self):
for rows in ([META, None, (1,)], [META, None, None, (256,)]):
store, _, _, cursor, checkpoint = fixture(rows)
with self.assertRaises(GroupProvenanceUnavailable):
store.reserve('synthetic-operation-key', REQUEST)
self.assertFalse(any('INSERT' in c.args[0] for c in cursor.execute.call_args_list))
checkpoint.advance.assert_not_called()
def test_new_reservation_retains_bound_context_and_write_intent(self):
store, _, _, cursor, checkpoint = fixture([META, None, None, (0,)])
created, fresh = store.reserve('synthetic-operation-key', REQUEST)
self.assertTrue(fresh)
self.assertEqual('pending', created['state'])
self.assertEqual(BINDING.digest, created['_pg_context'])
insert = next(c for c in cursor.execute.call_args_list if c.args[0].startswith('INSERT'))
self.assertIn('context_json', insert.args[0])
self.assertEqual(BINDING.tenant_scope, json.loads(insert.args[1][1])['tenant_scope'])
checkpoint.advance.assert_called_once()
if __name__ == '__main__':
unittest.main()