"""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()