django-cfg 1.2.15__py3-none-any.whl → 1.2.16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/maintenance/README.md +305 -0
  3. django_cfg/apps/maintenance/__init__.py +27 -0
  4. django_cfg/apps/maintenance/admin/__init__.py +28 -0
  5. django_cfg/apps/maintenance/admin/deployments_admin.py +251 -0
  6. django_cfg/apps/maintenance/admin/events_admin.py +374 -0
  7. django_cfg/apps/maintenance/admin/monitoring_admin.py +215 -0
  8. django_cfg/apps/maintenance/admin/sites_admin.py +464 -0
  9. django_cfg/apps/maintenance/apps.py +105 -0
  10. django_cfg/apps/maintenance/management/__init__.py +0 -0
  11. django_cfg/apps/maintenance/management/commands/__init__.py +0 -0
  12. django_cfg/apps/maintenance/management/commands/maintenance.py +375 -0
  13. django_cfg/apps/maintenance/management/commands/sync_cloudflare.py +168 -0
  14. django_cfg/apps/maintenance/managers/__init__.py +20 -0
  15. django_cfg/apps/maintenance/managers/deployments.py +287 -0
  16. django_cfg/apps/maintenance/managers/events.py +374 -0
  17. django_cfg/apps/maintenance/managers/monitoring.py +301 -0
  18. django_cfg/apps/maintenance/managers/sites.py +335 -0
  19. django_cfg/apps/maintenance/migrations/0001_initial.py +939 -0
  20. django_cfg/apps/maintenance/migrations/__init__.py +0 -0
  21. django_cfg/apps/maintenance/models/__init__.py +27 -0
  22. django_cfg/apps/maintenance/models/cloudflare.py +316 -0
  23. django_cfg/apps/maintenance/models/maintenance.py +334 -0
  24. django_cfg/apps/maintenance/models/monitoring.py +393 -0
  25. django_cfg/apps/maintenance/models/sites.py +419 -0
  26. django_cfg/apps/maintenance/serializers/__init__.py +60 -0
  27. django_cfg/apps/maintenance/serializers/actions.py +310 -0
  28. django_cfg/apps/maintenance/serializers/base.py +44 -0
  29. django_cfg/apps/maintenance/serializers/deployments.py +209 -0
  30. django_cfg/apps/maintenance/serializers/events.py +210 -0
  31. django_cfg/apps/maintenance/serializers/monitoring.py +278 -0
  32. django_cfg/apps/maintenance/serializers/sites.py +213 -0
  33. django_cfg/apps/maintenance/services/README.md +168 -0
  34. django_cfg/apps/maintenance/services/__init__.py +21 -0
  35. django_cfg/apps/maintenance/services/cloudflare_client.py +441 -0
  36. django_cfg/apps/maintenance/services/dns_manager.py +497 -0
  37. django_cfg/apps/maintenance/services/maintenance_manager.py +504 -0
  38. django_cfg/apps/maintenance/services/site_sync.py +448 -0
  39. django_cfg/apps/maintenance/services/sync_command_service.py +330 -0
  40. django_cfg/apps/maintenance/services/worker_manager.py +264 -0
  41. django_cfg/apps/maintenance/signals.py +38 -0
  42. django_cfg/apps/maintenance/urls.py +36 -0
  43. django_cfg/apps/maintenance/views/__init__.py +18 -0
  44. django_cfg/apps/maintenance/views/base.py +61 -0
  45. django_cfg/apps/maintenance/views/deployments.py +175 -0
  46. django_cfg/apps/maintenance/views/events.py +204 -0
  47. django_cfg/apps/maintenance/views/monitoring.py +213 -0
  48. django_cfg/apps/maintenance/views/sites.py +338 -0
  49. django_cfg/apps/urls.py +5 -1
  50. django_cfg/core/config.py +34 -3
  51. django_cfg/core/generation.py +15 -10
  52. django_cfg/models/cloudflare.py +316 -0
  53. django_cfg/models/revolution.py +1 -1
  54. django_cfg/models/tasks.py +1 -1
  55. django_cfg/modules/base.py +12 -5
  56. django_cfg/modules/django_unfold/dashboard.py +16 -1
  57. {django_cfg-1.2.15.dist-info → django_cfg-1.2.16.dist-info}/METADATA +2 -1
  58. {django_cfg-1.2.15.dist-info → django_cfg-1.2.16.dist-info}/RECORD +61 -13
  59. {django_cfg-1.2.15.dist-info → django_cfg-1.2.16.dist-info}/WHEEL +0 -0
  60. {django_cfg-1.2.15.dist-info → django_cfg-1.2.16.dist-info}/entry_points.txt +0 -0
  61. {django_cfg-1.2.15.dist-info → django_cfg-1.2.16.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,316 @@
1
+ """
2
+ Cloudflare configuration models for django_cfg.
3
+
4
+ Type-safe Cloudflare maintenance mode configuration following CRITICAL_REQUIREMENTS.
5
+ No raw Dict/Any usage - everything through Pydantic v2 models.
6
+ """
7
+
8
+ from typing import Annotated, Optional, List, Dict, Any
9
+ from pydantic import BaseModel, Field, SecretStr, field_validator, HttpUrl
10
+ from enum import Enum
11
+ from datetime import timedelta
12
+
13
+
14
+ class MaintenanceTemplate(str, Enum):
15
+ """Available maintenance page templates."""
16
+ BASIC = "basic"
17
+ MODERN = "modern"
18
+ CUSTOM = "custom"
19
+
20
+
21
+ class CloudflareConfig(BaseModel):
22
+ """
23
+ Zero-configuration Cloudflare maintenance mode setup.
24
+
25
+ Following KISS principle - user provides only api_token and domain,
26
+ everything else is auto-discovered and configured.
27
+ """
28
+
29
+ model_config = {
30
+ "env_prefix": "CLOUDFLARE_",
31
+ "case_sensitive": False,
32
+ "validate_assignment": True,
33
+ "extra": "forbid",
34
+ "str_strip_whitespace": True,
35
+ }
36
+
37
+ # === Required Configuration (Zero-config approach) ===
38
+ api_token: SecretStr = Field(
39
+ description="Cloudflare API token with Zone:Edit permissions"
40
+ )
41
+ domain: Annotated[str, Field(
42
+ min_length=3,
43
+ max_length=253,
44
+ pattern=r"^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$",
45
+ description="Domain name (auto-discovers Zone ID)"
46
+ )]
47
+
48
+ # === Auto-discovered Fields (set by system) ===
49
+ zone_id: Optional[str] = Field(
50
+ default=None,
51
+ description="Auto-discovered Cloudflare Zone ID"
52
+ )
53
+ account_id: Optional[str] = Field(
54
+ default=None,
55
+ description="Auto-discovered Cloudflare Account ID"
56
+ )
57
+
58
+ # === Optional Customization ===
59
+ enabled: bool = Field(
60
+ default=True,
61
+ description="Enable Cloudflare maintenance mode integration"
62
+ )
63
+
64
+ template: MaintenanceTemplate = Field(
65
+ default=MaintenanceTemplate.MODERN,
66
+ description="Maintenance page template"
67
+ )
68
+
69
+ maintenance_title: str = Field(
70
+ default="Site Under Maintenance",
71
+ max_length=200,
72
+ description="Title for maintenance page"
73
+ )
74
+
75
+ maintenance_message: str = Field(
76
+ default="We're performing scheduled maintenance. Please try again shortly.",
77
+ max_length=1000,
78
+ description="Message for maintenance page"
79
+ )
80
+
81
+ # === Auto-configuration Flags ===
82
+ auto_ssl: bool = Field(
83
+ default=True,
84
+ description="Automatically configure SSL/TLS settings"
85
+ )
86
+ auto_dns: bool = Field(
87
+ default=True,
88
+ description="Create missing DNS records automatically"
89
+ )
90
+ auto_monitoring: bool = Field(
91
+ default=True,
92
+ description="Enable external monitoring"
93
+ )
94
+
95
+ # === Advanced Settings (Smart Defaults) ===
96
+ worker_name: str = Field(
97
+ default="maintenance-mode",
98
+ max_length=100,
99
+ pattern=r"^[a-zA-Z0-9\-_]+$",
100
+ description="Cloudflare Worker name"
101
+ )
102
+
103
+ monitoring_interval: Annotated[int, Field(
104
+ ge=30,
105
+ le=3600,
106
+ description="Health check interval in seconds"
107
+ )] = 60
108
+
109
+ failure_threshold: Annotated[int, Field(
110
+ ge=1,
111
+ le=10,
112
+ description="Consecutive failures before enabling maintenance"
113
+ )] = 3
114
+
115
+ recovery_threshold: Annotated[int, Field(
116
+ ge=1,
117
+ le=10,
118
+ description="Consecutive successes before disabling maintenance"
119
+ )] = 2
120
+
121
+ # === Multi-site Support ===
122
+ multi_site_enabled: bool = Field(
123
+ default=False,
124
+ description="Enable multi-site management features"
125
+ )
126
+
127
+ @field_validator('domain')
128
+ @classmethod
129
+ def validate_domain(cls, v: str) -> str:
130
+ """Validate and normalize domain name."""
131
+ domain = v.lower().strip()
132
+
133
+ # Remove protocol if present
134
+ if domain.startswith(('http://', 'https://')):
135
+ raise ValueError('Domain should not include protocol (http:// or https://)')
136
+
137
+ # Remove www prefix for consistency
138
+ if domain.startswith('www.'):
139
+ domain = domain[4:]
140
+
141
+ # Basic domain validation
142
+ if not domain or '.' not in domain:
143
+ raise ValueError('Domain must be a valid domain name')
144
+
145
+ return domain
146
+
147
+ def get_api_token(self) -> str:
148
+ """Get decrypted API token."""
149
+ return self.api_token.get_secret_value()
150
+
151
+ def is_configured(self) -> bool:
152
+ """Check if Cloudflare is fully configured."""
153
+ return bool(self.zone_id and self.account_id)
154
+
155
+
156
+ class MultiSiteConfig(BaseModel):
157
+ """
158
+ Multi-site management configuration.
159
+
160
+ Extends CloudflareConfig for managing multiple sites.
161
+ """
162
+
163
+ model_config = {
164
+ "validate_assignment": True,
165
+ "extra": "forbid"
166
+ }
167
+
168
+ # === Site Discovery ===
169
+ auto_discover_sites: bool = Field(
170
+ default=True,
171
+ description="Automatically discover all sites in Cloudflare account"
172
+ )
173
+
174
+ site_filters: List[str] = Field(
175
+ default_factory=list,
176
+ description="Domain patterns to include (e.g., ['*.example.com', 'api.*.com'])"
177
+ )
178
+
179
+ excluded_domains: List[str] = Field(
180
+ default_factory=list,
181
+ description="Domains to exclude from management"
182
+ )
183
+
184
+ # === Default Site Settings ===
185
+ default_environment: str = Field(
186
+ default="production",
187
+ pattern=r"^(production|staging|development|testing)$",
188
+ description="Default environment for discovered sites"
189
+ )
190
+
191
+ default_project: str = Field(
192
+ default="",
193
+ max_length=100,
194
+ description="Default project name for discovered sites"
195
+ )
196
+
197
+ default_tags: List[str] = Field(
198
+ default_factory=list,
199
+ description="Default tags for discovered sites"
200
+ )
201
+
202
+ # === Bulk Operations ===
203
+ max_concurrent_operations: Annotated[int, Field(
204
+ ge=1,
205
+ le=50,
206
+ description="Maximum concurrent Cloudflare API operations"
207
+ )] = 10
208
+
209
+ operation_timeout: Annotated[int, Field(
210
+ ge=5,
211
+ le=300,
212
+ description="Timeout for individual operations in seconds"
213
+ )] = 30
214
+
215
+ # === Notifications ===
216
+ notification_channels: List[str] = Field(
217
+ default_factory=lambda: ["email"],
218
+ description="Notification channels for maintenance events"
219
+ )
220
+
221
+ webhook_url: Optional[HttpUrl] = Field(
222
+ default=None,
223
+ description="Webhook URL for maintenance notifications"
224
+ )
225
+
226
+
227
+ class MonitoringConfig(BaseModel):
228
+ """
229
+ External monitoring configuration.
230
+
231
+ Configures health checks and automatic maintenance triggers.
232
+ """
233
+
234
+ model_config = {
235
+ "validate_assignment": True,
236
+ "extra": "forbid"
237
+ }
238
+
239
+ # === Monitoring Settings ===
240
+ enabled: bool = Field(
241
+ default=True,
242
+ description="Enable external monitoring"
243
+ )
244
+
245
+ check_interval: Annotated[int, Field(
246
+ ge=10,
247
+ le=3600,
248
+ description="Health check interval in seconds"
249
+ )] = 60
250
+
251
+ timeout: Annotated[int, Field(
252
+ ge=1,
253
+ le=300,
254
+ description="Health check timeout in seconds"
255
+ )] = 10
256
+
257
+ # === Health Check Configuration ===
258
+ health_check_path: str = Field(
259
+ default="/health/",
260
+ description="Health check endpoint path"
261
+ )
262
+
263
+ expected_status_codes: List[int] = Field(
264
+ default_factory=lambda: [200, 201, 204],
265
+ description="Expected HTTP status codes for healthy response"
266
+ )
267
+
268
+ expected_response_time_ms: Optional[int] = Field(
269
+ default=5000,
270
+ ge=100,
271
+ le=60000,
272
+ description="Maximum expected response time in milliseconds"
273
+ )
274
+
275
+ # === Failure Detection ===
276
+ failure_threshold: Annotated[int, Field(
277
+ ge=1,
278
+ le=20,
279
+ description="Consecutive failures before triggering maintenance"
280
+ )] = 3
281
+
282
+ recovery_threshold: Annotated[int, Field(
283
+ ge=1,
284
+ le=20,
285
+ description="Consecutive successes before disabling maintenance"
286
+ )] = 2
287
+
288
+ # === Advanced Settings ===
289
+ user_agent: str = Field(
290
+ default="Django-CFG-Monitor/1.0",
291
+ description="User agent for health checks"
292
+ )
293
+
294
+ follow_redirects: bool = Field(
295
+ default=True,
296
+ description="Follow HTTP redirects during health checks"
297
+ )
298
+
299
+ verify_ssl: bool = Field(
300
+ default=True,
301
+ description="Verify SSL certificates during health checks"
302
+ )
303
+
304
+ custom_headers: Dict[str, str] = Field(
305
+ default_factory=dict,
306
+ description="Custom headers for health check requests"
307
+ )
308
+
309
+
310
+ # Export all models
311
+ __all__ = [
312
+ "CloudflareConfig",
313
+ "MultiSiteConfig",
314
+ "MonitoringConfig",
315
+ "MaintenanceTemplate",
316
+ ]
@@ -92,7 +92,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
92
92
  leads_enabled = base_module.is_leads_enabled()
93
93
  knowbase_enabled = base_module.is_knowbase_enabled()
94
94
  agents_enabled = base_module.is_agents_enabled()
95
- tasks_enabled = base_module.is_tasks_enabled()
95
+ tasks_enabled = base_module.should_enable_tasks()
96
96
 
97
97
  # Add Support zone if enabled
98
98
  default_support_zone = 'cfg_support'
@@ -411,7 +411,7 @@ class TaskConfig(BaseModel, BaseCfgAutoModule):
411
411
  return config.tasks
412
412
 
413
413
  # Check if tasks should be enabled
414
- if base_module.is_tasks_enabled():
414
+ if config.should_enable_tasks():
415
415
  # Auto-initialize with smart defaults
416
416
  task_config = cls().get_smart_defaults()
417
417
  task_config.set_config(config)
@@ -155,7 +155,7 @@ class BaseCfgModule(ABC):
155
155
  """
156
156
  return self._get_config_key('enable_knowbase', False)
157
157
 
158
- def is_tasks_enabled(self) -> bool:
158
+ def should_enable_tasks(self) -> bool:
159
159
  """
160
160
  Check if django-cfg Tasks is enabled.
161
161
  Auto-enables if knowbase or agents are enabled.
@@ -163,10 +163,17 @@ class BaseCfgModule(ABC):
163
163
  Returns:
164
164
  True if Tasks is enabled, False otherwise
165
165
  """
166
- # Auto-enable if knowbase or agents are enabled
167
- if self.is_knowbase_enabled() or self.is_agents_enabled():
168
- return True
169
- return self._get_config_key('enable_tasks', False)
166
+
167
+ return self.get_config().should_enable_tasks()
168
+
169
+ def is_maintenance_enabled(self) -> bool:
170
+ """
171
+ Check if django-cfg Maintenance is enabled.
172
+
173
+ Returns:
174
+ True if Maintenance is enabled, False otherwise
175
+ """
176
+ return self._get_config_key('enable_maintenance', False)
170
177
 
171
178
 
172
179
  # Export the base class
@@ -138,7 +138,7 @@ class DashboardManager(BaseCfgModule):
138
138
  ))
139
139
 
140
140
  # Add Tasks section if knowbase or agents are enabled
141
- if self.is_tasks_enabled():
141
+ if self.should_enable_tasks():
142
142
  navigation_sections.append(NavigationSection(
143
143
  title="Background Tasks",
144
144
  separator=True,
@@ -149,6 +149,21 @@ class DashboardManager(BaseCfgModule):
149
149
  ]
150
150
  ))
151
151
 
152
+ # Add Maintenance section if enabled
153
+ if self.is_maintenance_enabled():
154
+ navigation_sections.append(NavigationSection(
155
+ title="Maintenance Mode",
156
+ separator=True,
157
+ collapsible=True,
158
+ items=[
159
+ NavigationItem(title="Cloudflare Sites", icon=Icons.CLOUD, link="/admin/django_cfg_maintenance/cloudflaresite/"),
160
+ NavigationItem(title="Site Groups", icon=Icons.GROUP, link="/admin/django_cfg_maintenance/sitegroup/"),
161
+ NavigationItem(title="Maintenance Events", icon=Icons.BUILD, link="/admin/django_cfg_maintenance/maintenanceevent/"),
162
+ NavigationItem(title="Monitoring Targets", icon=Icons.MONITOR, link="/admin/django_cfg_maintenance/monitoringtarget/"),
163
+ NavigationItem(title="Deployments", icon=Icons.ROCKET_LAUNCH, link="/admin/django_cfg_maintenance/cloudflaredeployment/"),
164
+ ]
165
+ ))
166
+
152
167
  # Convert all NavigationSection objects to dictionaries
153
168
  return [section.to_dict() for section in navigation_sections]
154
169
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.2.15
3
+ Version: 1.2.16
4
4
  Summary: 🚀 Next-gen Django configuration: type-safety, AI features, blazing-fast setup, and automated best practices — all in one.
5
5
  Project-URL: Homepage, https://djangocfg.com
6
6
  Project-URL: Documentation, https://docs.djangocfg.com
@@ -33,6 +33,7 @@ Requires-Python: <4.0,>=3.12
33
33
  Requires-Dist: beautifulsoup4<5.0,>=4.13.0
34
34
  Requires-Dist: cachetools<7.0,>=5.3.0
35
35
  Requires-Dist: click<9.0,>=8.2.0
36
+ Requires-Dist: cloudflare<5.0,>=4.3.0
36
37
  Requires-Dist: colorlog<7.0,>=6.9.0
37
38
  Requires-Dist: coolname<3.0,>=2.2.0
38
39
  Requires-Dist: currencyconverter<1.0,>=0.18.0
@@ -1,10 +1,10 @@
1
1
  django_cfg/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- django_cfg/__init__.py,sha256=WO5eQC0F4xNgcT1pvxC4u4-1_fGdLq1oolFLlGmuRKE,1631
2
+ django_cfg/__init__.py,sha256=d92zyNG27I9W8eHo9Yi0nJRCPGak2-F4okDCnNrWMkQ,1631
3
3
  django_cfg/apps.py,sha256=k84brkeXJI7EgKZLEpTkM9YFZofKI4PzhFOn1cl9Msc,1656
4
4
  django_cfg/config.py,sha256=0cuRJVEnf03WzvEqhwzLvn9Zi1805C5KG1yk27ekABA,1190
5
5
  django_cfg/urls.py,sha256=bpRFjMonQuk4UCUMxx4ueBX3YDNB7HXKFwEghQ3KR3o,793
6
6
  django_cfg/apps/__init__.py,sha256=JtDmEYt1OcleWM2ZaeX0LKDnRQzPOavfaXBWG4ECB5Q,26
7
- django_cfg/apps/urls.py,sha256=xdRTe1bMzF753cH5tw9peIwr21kciy13I368b_JyWk0,2118
7
+ django_cfg/apps/urls.py,sha256=y10rWxIMf70GIO_QPXv59reFArkQhkvknKXTILgdvs0,2346
8
8
  django_cfg/apps/accounts/README.md,sha256=YkUYJ3iKMYTmm9ALK2PDnX75SDqZxgnkzNLCD5efxRs,8227
9
9
  django_cfg/apps/accounts/__init__.py,sha256=osecEQhMJVP8ejhZzElNsAqA1fX-GPD3K5_yNwDk6IE,100
10
10
  django_cfg/apps/accounts/apps.py,sha256=Xd4XNpY1tw3zOqk_M9L6MR6oFdfFMYrfmrmbj0uelUs,492
@@ -200,6 +200,53 @@ django_cfg/apps/leads/admin/leads_admin.py,sha256=q1d1kmTWZUCUHxePOlDrwF9jJvgjN7
200
200
  django_cfg/apps/leads/admin/resources.py,sha256=bJdydBmPMZ08N5_IylaZEtSY4JySs1-h9pJoKFm04BA,3742
201
201
  django_cfg/apps/leads/migrations/0001_initial.py,sha256=mBDupgmgmaLQFO9bLaBOODN7pervwAnN_EfsS08MoB4,4876
202
202
  django_cfg/apps/leads/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
203
+ django_cfg/apps/maintenance/README.md,sha256=8_-6LEdffnIB7oX02-rSgoXlYoHgCzrGOIJcL0_ldyw,8671
204
+ django_cfg/apps/maintenance/__init__.py,sha256=lR2bhLk0ZLrH_hnmBpbdzvDCxS_-PXqOejcGTc80YNM,851
205
+ django_cfg/apps/maintenance/apps.py,sha256=6o4B2HsukXnH5LtK0osqT2r4agULm7UzBbuyBx1pduA,4083
206
+ django_cfg/apps/maintenance/signals.py,sha256=Bw6tOEDtnEOf2-9UBGtWfSpBrW1AmqJCtGS1FpYmLws,1199
207
+ django_cfg/apps/maintenance/urls.py,sha256=kHz9y5Eud_cx7jiKxxHIP0zlzqWH3kC1a1zkCDLOF9w,1306
208
+ django_cfg/apps/maintenance/admin/__init__.py,sha256=4SL6mkxei-7PGFyfTloy2xrwhuNSau2BTvP3P_3ztb4,740
209
+ django_cfg/apps/maintenance/admin/deployments_admin.py,sha256=goJGn716XH3kq9LEo7PcDMdeEJZHNQYFgN4qHJDIUpg,8566
210
+ django_cfg/apps/maintenance/admin/events_admin.py,sha256=0EopccZ6wOHJeJLLRGtr1u6DjhLviaNTGbCoz-jBr9Q,12508
211
+ django_cfg/apps/maintenance/admin/monitoring_admin.py,sha256=tKU2V5OA9XqrRSnuOOz33pJnOBv1urkJRAmx34i7Bmc,7510
212
+ django_cfg/apps/maintenance/admin/sites_admin.py,sha256=EDMJtMW20sYl_O9vmD51N7C_hKeYSLpGhWnanOykDic,16470
213
+ django_cfg/apps/maintenance/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
214
+ django_cfg/apps/maintenance/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
215
+ django_cfg/apps/maintenance/management/commands/maintenance.py,sha256=sazsNB6n4yR9o17gD83v6SLJ-5GhBav9O_PIMriKdQY,13707
216
+ django_cfg/apps/maintenance/management/commands/sync_cloudflare.py,sha256=eAWOLfXvBTeuB_89OzhrJhRUeCZHDFtDiQNz779Od4c,5755
217
+ django_cfg/apps/maintenance/managers/__init__.py,sha256=u7lQGsD0eIrLMUXQ3EqgTheefXBPQ6-qDpTki2M6XtA,601
218
+ django_cfg/apps/maintenance/managers/deployments.py,sha256=sDt9_fmw2MN_WfJn8K4amOgQ69MGaWz65xkuYVRrRXM,9851
219
+ django_cfg/apps/maintenance/managers/events.py,sha256=Llr0FMQr861drqXHOKJv29Yhsfo02NNPhllVzgNIJhA,12236
220
+ django_cfg/apps/maintenance/managers/monitoring.py,sha256=ZkRz3K8MZyH-hWuoEFvLo98Wi5L2X6S7lKO1pO4A4go,10651
221
+ django_cfg/apps/maintenance/managers/sites.py,sha256=Srqooa3sRqPt51UIWU3B2NcD8Noy3bUb9yVxpg6fBnQ,11052
222
+ django_cfg/apps/maintenance/migrations/0001_initial.py,sha256=9pLCklZ0y5VJ2yyMiveoaEuyVyjG-HYMLqUE0XjYPsI,36531
223
+ django_cfg/apps/maintenance/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
224
+ django_cfg/apps/maintenance/models/__init__.py,sha256=yExcE0IMXMJWFFEMK4pzI54ipA-vYKU42RXy1CwwT98,611
225
+ django_cfg/apps/maintenance/models/cloudflare.py,sha256=hAB-xSrWkV4wFNlE2hfsW1STYNIEGNZtpxCWgsfun2g,11218
226
+ django_cfg/apps/maintenance/models/maintenance.py,sha256=Eyk5uYE9LduM9gGdjkR4xI4inVAJKiG5c5UJEKHamG8,10529
227
+ django_cfg/apps/maintenance/models/monitoring.py,sha256=qPEaEiQ5sMOe9nejD0lwyD58joQ8LQx39Tv6uofpXz4,12733
228
+ django_cfg/apps/maintenance/models/sites.py,sha256=487MqqLK3rM5T1VvKhqGY4Xw7unaFEHmRUCzfVCI4l4,13396
229
+ django_cfg/apps/maintenance/serializers/__init__.py,sha256=1GIRFpqo946wlHjZ30bRw0enTlhojWDDew5RYv7K5vA,1733
230
+ django_cfg/apps/maintenance/serializers/actions.py,sha256=V9DG8zw8T3ptHAF6zemFwAEMLRjomA0q-eEqei6loxM,10541
231
+ django_cfg/apps/maintenance/serializers/base.py,sha256=ia3l-sUAzCfdt-2CHJRRiuwkG7PAJh0b9zTfeISoN_k,1130
232
+ django_cfg/apps/maintenance/serializers/deployments.py,sha256=W7tNq5Iioph8gD8EeykH64xJgzy5_Ws5_jONT_8rFVg,7385
233
+ django_cfg/apps/maintenance/serializers/events.py,sha256=S6pjVnLO6Xq-1EwUtj2oq_hgAgsXaBaKbMGrPWZPGWc,7869
234
+ django_cfg/apps/maintenance/serializers/monitoring.py,sha256=ihVnf7AHYfzajlJo8Yd1UvKku8wBPRdWckLILK7UOp0,10075
235
+ django_cfg/apps/maintenance/serializers/sites.py,sha256=0zLa1a9rYiydmMAqBiPgX20O80g6pWfxPov8ntCmG8E,7648
236
+ django_cfg/apps/maintenance/services/README.md,sha256=MlttVPZhzxHW7uckQ5YduV7dB40HjhLRbrp19less0g,4311
237
+ django_cfg/apps/maintenance/services/__init__.py,sha256=LByFDu_Vlqw4mYLXFtEEs2SH6F05D88htBaSWMNLgn8,572
238
+ django_cfg/apps/maintenance/services/cloudflare_client.py,sha256=FAcXwo6qTTLl-5x8-IUxmeUoOuYJSCzEvOSIiRZ3RJQ,14444
239
+ django_cfg/apps/maintenance/services/dns_manager.py,sha256=3OOCSvrOsr-0WizKHl1y4E64sasz9uUT2yzLCjCVo8k,16035
240
+ django_cfg/apps/maintenance/services/maintenance_manager.py,sha256=YWqjYmNSQrHY4ueAYOnToxosliJlnWIdmviiGQmK7I0,18171
241
+ django_cfg/apps/maintenance/services/site_sync.py,sha256=tyAL3psJW-PHW07afQYnqbuqU6ctk4fVWCukb_burzw,16458
242
+ django_cfg/apps/maintenance/services/sync_command_service.py,sha256=Ls1sWXsbW75hd3m6giWHH_0f_dO0vWHq-CCpqy8-Sfs,10774
243
+ django_cfg/apps/maintenance/services/worker_manager.py,sha256=BE91DA3ccElFxUCLD424IOkANq-zUUn8iIhZl2IGck4,8771
244
+ django_cfg/apps/maintenance/views/__init__.py,sha256=O69OstM_-D8y6hbBaTIdktze2NOSiJzIIqudspNMToM,458
245
+ django_cfg/apps/maintenance/views/base.py,sha256=q_acqStFw6wRSbD7LWpuXO4_3We2bk7nk05sCEZCVZ0,1893
246
+ django_cfg/apps/maintenance/views/deployments.py,sha256=ujZNI1w2mP9-OAel_6NT6JaiC9UmMNG1EBL6PNnise8,6720
247
+ django_cfg/apps/maintenance/views/events.py,sha256=N0iwCuW2vEMYlBuZHgw5FEdRx163aWMgRLR5fpHiQ7Q,7552
248
+ django_cfg/apps/maintenance/views/monitoring.py,sha256=q3xtJUExuPCV9w86_9PHUrMoxg7CcsJTJyWG6Em1Rzc,7795
249
+ django_cfg/apps/maintenance/views/sites.py,sha256=5BJCyKIBqoxOVl2p1s78mgu3ryYXTY90Q_LBShs93d0,13513
203
250
  django_cfg/apps/newsletter/README.md,sha256=cnNXnAUsCVtelMNGYc4a8qJsoiVb--J2OOSh_Jw8piA,3202
204
251
  django_cfg/apps/newsletter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
205
252
  django_cfg/apps/newsletter/admin.py,sha256=7uZIL-BVtB0l22vgsofQi02Lgub_kJ66RcB154uQunQ,8816
@@ -285,10 +332,10 @@ django_cfg/cli/commands/__init__.py,sha256=EKLXDAx-QttnGmdjsmVANAfhxWplxl2V_2I0S
285
332
  django_cfg/cli/commands/create_project.py,sha256=iuf965j8Yg7zxHcPb0GtFHEj73CYXC45ZJRmd6RbA9E,21025
286
333
  django_cfg/cli/commands/info.py,sha256=o4S1xPJSHv2oEVqmH0X9RTF5f-8Wy9579yHkyd_PC3E,4923
287
334
  django_cfg/core/__init__.py,sha256=eVK57qFOok9kTeHoNEMQ1BplkUOaQ7NB9kP9eQK1vg0,358
288
- django_cfg/core/config.py,sha256=y0rvqiO5l_MMqDhQCiyA9c3GHYJlJwRpdOgvN_MfcWU,26536
335
+ django_cfg/core/config.py,sha256=YiiYU-Pu4eHg7nLPG3i3dLIp_eKsbk-dqbr3lX-0F-k,27682
289
336
  django_cfg/core/environment.py,sha256=MAoEPqIPsLVhSANT2Bz4nnus2wmbMW0RCOQxhQfDrDc,9106
290
337
  django_cfg/core/exceptions.py,sha256=RTQEoU3PfR8lqqNNv5ayd_HY2yJLs3eioqUy8VM6AG4,10378
291
- django_cfg/core/generation.py,sha256=zSVb3VIv588wzqSF1-wxOb15CW5hX2tf9fq_FRXSOzk,24990
338
+ django_cfg/core/generation.py,sha256=zq6QZRyE8vS_fZVk2SbqHsCC_43DSvAUU4T1pMf8gSs,25374
292
339
  django_cfg/core/integration.py,sha256=5kzkZSd45ij0rfrBdeNUYnDalObqvK__XpoP31xFYKo,5224
293
340
  django_cfg/core/validation.py,sha256=PhwDBTs24nuM3xqfIT3hXmN88VrhMT-Bk8Yb8FxjmPk,6590
294
341
  django_cfg/management/__init__.py,sha256=NrLAhiS59hqjy-bipOC1abNuRiNm5BpKXmjN05VzKbM,28
@@ -324,6 +371,7 @@ django_cfg/models/api.py,sha256=bCsQR3CVsAUs78m1Q1aFpPTNbvGtr1cq-fuxdCK2-JI,4596
324
371
  django_cfg/models/base.py,sha256=Gy_B2dXSu-lYQjxlCaP6tkngFKhBFkCPeMNIpkkkKSU,10408
325
372
  django_cfg/models/cache.py,sha256=oAiBPM89pZfLlruIzDVFmqNmHdOPk3a2KAgB9jubUPg,12133
326
373
  django_cfg/models/cfg.py,sha256=P6YowmE-VOqp_L25Ijxj2hjjNhB9xtlm8G35DHWqTfk,2702
374
+ django_cfg/models/cloudflare.py,sha256=6frbEeGL7kPIoBX3E_aD7wnBOwPsXQZLs6KGSZczHWM,8896
327
375
  django_cfg/models/constance.py,sha256=BqwoPvUx5vfrZT6qF2KR0prpsSM5VEYIYJUVlB50ewk,8936
328
376
  django_cfg/models/cors.py,sha256=lozVoQJVehhNL1qzOhvAkd4ZpgwAdOJ-OUX7wkJp5W4,3567
329
377
  django_cfg/models/database.py,sha256=LpcmEljjr-2pnR8UVSziUNSnucsojfh8PcgayhrWqK4,16875
@@ -334,12 +382,12 @@ django_cfg/models/jwt.py,sha256=3R_dpLmVZIcH4zdtwA4qKnuCB8RZQACrgsbbgWY2q4c,9025
334
382
  django_cfg/models/limits.py,sha256=nUfvyPykwKR38ZOlIFqlNGRmfV8RO5hiUrhDH6FCHJw,7449
335
383
  django_cfg/models/logging.py,sha256=4vZF-G9rPmXMxxtUx_ad7Esvgbe8a_5Dl692Yg0fL4A,10636
336
384
  django_cfg/models/ngrok.py,sha256=MVgcKWx0DRSW0QcwhiSx2vVwTSG49vbVrzPkZqDK-zw,3575
337
- django_cfg/models/revolution.py,sha256=gaAhdicd1ji-XiJPqUFQaUmDcgfwFHofSYS3JtLcz4A,7540
385
+ django_cfg/models/revolution.py,sha256=n8CLLniMac9PTV5KDcfoO-_8F6U40jLT3DU8-kIIZ4I,7543
338
386
  django_cfg/models/security.py,sha256=Xv19ZVOIenB_-f0wB6fm-Ap4j9kA43bSFaT2XenpSqc,4685
339
387
  django_cfg/models/services.py,sha256=fj9JjrJFrlL4DMnMbx_D8JiiZpz4E5uBqmhquAxau7c,13159
340
- django_cfg/models/tasks.py,sha256=G06kEMaJ9mZhW525y-r33q4rHswAwnvPgMt7lpbgiak,15526
388
+ django_cfg/models/tasks.py,sha256=2T3apcUFf8zevYJmapbFrh6bWv5PTJPeXR6Bc5vlj4c,15524
341
389
  django_cfg/modules/__init__.py,sha256=Ip9WMpzImEwIAywpFwU056_v0O9oIGG7nCT1YSArxkw,316
342
- django_cfg/modules/base.py,sha256=ALlsylzO1rYsrLNwL3MhEK_dqYSZV0BBZAObR6wlGEA,5343
390
+ django_cfg/modules/base.py,sha256=A-pWUckGKrCAlgfnCfkKmjwtgZjyhc_z-hvJ4ogocpI,5474
343
391
  django_cfg/modules/django_email.py,sha256=2XXlIKzD6Jao3CT4_zIE2eaM9Cc9ROA1tjp2bJ9z5Lo,16592
344
392
  django_cfg/modules/django_health.py,sha256=7QzuQ6WyjWYj6lecd4auwRvEyrMUL7N6hiAp-tLyoY4,8923
345
393
  django_cfg/modules/django_logger.py,sha256=3oP9jev0lOcFUJ1tYcpbFnK524zIGA2xIOrrAiTwpb8,6331
@@ -381,7 +429,7 @@ django_cfg/modules/django_twilio/templates/guide.md,sha256=nZfwx-sgWyK5NApm93zOe
381
429
  django_cfg/modules/django_twilio/templates/sendgrid_otp_email.html,sha256=sXR6_D9hmOFfk9CrfPizpLddVhkRirBWpZd_ioEsxVk,6671
382
430
  django_cfg/modules/django_twilio/templates/sendgrid_test_data.json,sha256=fh1VyuSiDELHsS_CIz9gp7tlsMAEjaDOoqbAPSZ3yyo,339
383
431
  django_cfg/modules/django_unfold/__init__.py,sha256=Z91x1iGmkzlRbEb2L9OCFmYDKNAV9C4G3i15j5S0esc,1898
384
- django_cfg/modules/django_unfold/dashboard.py,sha256=97KYJWjb2c1_wMzE4vgJ73DJN0p8ACuE1bVoZa43kdQ,12604
432
+ django_cfg/modules/django_unfold/dashboard.py,sha256=b2XnczCVtcneAkgE0deTHsBM9x6kIhLgk3q6zHf1eMg,13605
385
433
  django_cfg/modules/django_unfold/models.py,sha256=bY6QSSaH_-r9vOTkSQjxeIkl5RaED7XkxXkT8-W5stk,4014
386
434
  django_cfg/modules/django_unfold/system_monitor.py,sha256=cznZqldRJqiSLSJbs4U7R2rX8ClzoIpqdfXdXqI2iQw,6955
387
435
  django_cfg/modules/django_unfold/tailwind.py,sha256=X9o1K3QL0VwUISgJ26sLb6zkdK-00qiDuekqTw-fydc,10846
@@ -464,8 +512,8 @@ django_cfg/utils/path_resolution.py,sha256=C9As6p4Q9l3VeoVkFDRPQWGrzAWf8O8UxLVka
464
512
  django_cfg/utils/smart_defaults.py,sha256=b6A1z7VO1NJGq0oUQXN5P97c3k_Ssgw6qUi0mK-4TlM,19786
465
513
  django_cfg/utils/toolkit.py,sha256=Td8_iXNaftonF_xdZP4Y3uO65nuA_4_zditn5Q_Pfcw,23310
466
514
  django_cfg/utils/version_check.py,sha256=jI4v3YMdQriUEeb_TvRl511sDghy6I75iKRDUaNpucs,4800
467
- django_cfg-1.2.15.dist-info/METADATA,sha256=QcWw3jNJ4GU7JwFC9Ya3UdOT-9UFo2Au_7XeCUT3KLE,36406
468
- django_cfg-1.2.15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
469
- django_cfg-1.2.15.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
470
- django_cfg-1.2.15.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
471
- django_cfg-1.2.15.dist-info/RECORD,,
515
+ django_cfg-1.2.16.dist-info/METADATA,sha256=ymSEreTw4cDDZLlErhdC4RFh2ovx1XKEdCTHh4Njulc,36444
516
+ django_cfg-1.2.16.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
517
+ django_cfg-1.2.16.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
518
+ django_cfg-1.2.16.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
519
+ django_cfg-1.2.16.dist-info/RECORD,,