forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaccount_deletion_transitions.py
More file actions
110 lines (98 loc) · 4.24 KB
/
Copy pathaccount_deletion_transitions.py
File metadata and controls
110 lines (98 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
"""Account-deletion state transitions and deletion-scoped resource reads."""
from datetime import datetime, timezone
from typing import Any
from database._client import get_firestore_client
from google.cloud.firestore_v1 import transactional
from database.account_deletion_policy import account_deletion_blocks_access, normalize_account_deletion_status
def read_agent_vm_migration_journals(uid: str) -> list[dict[str, Any]]:
"""Read migration journals before deleting the user's Firestore subtree.
The journal is the durable source of truth for provider resources created
during an Agent VM migration. Callers must validate each returned record
against the provider before issuing destructive requests.
"""
if not uid.strip():
raise ValueError('uid is required')
client = get_firestore_client()
migration_ref = client.collection('users').document(uid).collection('agentVmMigrations')
journals: list[dict[str, Any]] = []
for snapshot in migration_ref.stream():
data = snapshot.to_dict()
if not isinstance(data, dict):
raise RuntimeError('Agent VM migration journal is malformed')
journal = dict(data)
if journal.get('migrationId') not in (None, snapshot.id):
raise RuntimeError('Agent VM migration journal identity is ambiguous')
journal['migrationId'] = snapshot.id
journals.append(journal)
journals.sort(key=lambda journal: str(journal.get('migrationId') or ''))
return journals
@transactional
def mark_wipe_completed(transaction, doc_ref) -> bool:
snapshot = doc_ref.get(transaction=transaction)
data = (snapshot.to_dict() or {}) if snapshot.exists else {}
if data.get('late_agent_vm_cleanup'):
transaction.set(
doc_ref,
{'wipe_status': 'failed', 'wipe_failed_at': datetime.now(timezone.utc)},
merge=True,
)
return False
transaction.set(
doc_ref,
{'wipe_status': 'completed', 'wipe_completed_at': datetime.now(timezone.utc)},
merge=True,
)
return True
@transactional
def record_late_agent_vm_cleanup(
transaction,
doc_ref,
vm_name: str,
zone: str,
expected_instance_id: str | None = None,
) -> bool:
snapshot = doc_ref.get(transaction=transaction)
raw_status = (snapshot.to_dict() or {}).get('wipe_status') if snapshot.exists else None
status = normalize_account_deletion_status(marker_exists=snapshot.exists, raw_status=raw_status)
if not account_deletion_blocks_access(status):
return False
if expected_instance_id is not None and (not expected_instance_id.isascii() or not expected_instance_id.isdigit()):
raise ValueError('late Agent VM cleanup instance identity must be numeric')
pending = {'vmName': vm_name, 'zone': zone}
if expected_instance_id is not None:
pending['expectedInstanceId'] = expected_instance_id
transaction.set(
doc_ref,
{
'late_agent_vm_cleanup': pending,
'wipe_status': 'failed',
'wipe_failed_at': datetime.now(timezone.utc),
},
merge=True,
)
return True
@transactional
def adopt_legacy_late_agent_vm_cleanup(
transaction,
doc_ref,
vm_name: str,
zone: str,
expected_instance_id: str,
) -> bool:
"""Add a provider identity fence to an exact pre-fence cleanup record."""
if not expected_instance_id.isascii() or not expected_instance_id.isdigit():
raise ValueError('late Agent VM cleanup instance identity must be numeric')
snapshot = doc_ref.get(transaction=transaction)
data = (snapshot.to_dict() or {}) if snapshot.exists else {}
raw_status = data.get('wipe_status')
status = normalize_account_deletion_status(marker_exists=snapshot.exists, raw_status=raw_status)
pending = data.get('late_agent_vm_cleanup')
if not account_deletion_blocks_access(status) or not isinstance(pending, dict):
return False
if pending.get('vmName') != vm_name or pending.get('zone') != zone:
return False
current_id = pending.get('expectedInstanceId')
if current_id is not None:
return current_id == expected_instance_id
transaction.update(doc_ref, {'late_agent_vm_cleanup.expectedInstanceId': expected_instance_id})
return True