omgkit 2.12.0 → 2.15.0
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.
- package/README.md +97 -12
- package/package.json +2 -2
- package/plugin/agents/api-designer.md +5 -0
- package/plugin/agents/architect.md +8 -0
- package/plugin/agents/brainstormer.md +4 -0
- package/plugin/agents/cicd-manager.md +6 -0
- package/plugin/agents/code-reviewer.md +6 -0
- package/plugin/agents/copywriter.md +2 -0
- package/plugin/agents/data-engineer.md +255 -0
- package/plugin/agents/database-admin.md +10 -0
- package/plugin/agents/debugger.md +10 -0
- package/plugin/agents/devsecops.md +314 -0
- package/plugin/agents/docs-manager.md +4 -0
- package/plugin/agents/domain-decomposer.md +181 -0
- package/plugin/agents/embedded-systems.md +397 -0
- package/plugin/agents/fullstack-developer.md +12 -0
- package/plugin/agents/game-systems-designer.md +375 -0
- package/plugin/agents/git-manager.md +10 -0
- package/plugin/agents/journal-writer.md +2 -0
- package/plugin/agents/ml-engineer.md +284 -0
- package/plugin/agents/observability-engineer.md +353 -0
- package/plugin/agents/oracle.md +9 -0
- package/plugin/agents/performance-engineer.md +290 -0
- package/plugin/agents/pipeline-architect.md +6 -0
- package/plugin/agents/planner.md +12 -0
- package/plugin/agents/platform-engineer.md +325 -0
- package/plugin/agents/project-manager.md +3 -0
- package/plugin/agents/researcher.md +5 -0
- package/plugin/agents/scientific-computing.md +426 -0
- package/plugin/agents/scout.md +3 -0
- package/plugin/agents/security-auditor.md +7 -0
- package/plugin/agents/sprint-master.md +17 -0
- package/plugin/agents/tester.md +10 -0
- package/plugin/agents/ui-ux-designer.md +12 -0
- package/plugin/agents/vulnerability-scanner.md +6 -0
- package/plugin/commands/data/pipeline.md +47 -0
- package/plugin/commands/data/quality.md +49 -0
- package/plugin/commands/domain/analyze.md +34 -0
- package/plugin/commands/domain/map.md +41 -0
- package/plugin/commands/game/balance.md +56 -0
- package/plugin/commands/game/optimize.md +62 -0
- package/plugin/commands/iot/provision.md +58 -0
- package/plugin/commands/ml/evaluate.md +47 -0
- package/plugin/commands/ml/train.md +48 -0
- package/plugin/commands/perf/benchmark.md +54 -0
- package/plugin/commands/perf/profile.md +49 -0
- package/plugin/commands/platform/blueprint.md +56 -0
- package/plugin/commands/security/audit.md +54 -0
- package/plugin/commands/security/scan.md +55 -0
- package/plugin/commands/sre/dashboard.md +53 -0
- package/plugin/registry.yaml +711 -0
- package/plugin/skills/ai-ml/experiment-tracking/SKILL.md +338 -0
- package/plugin/skills/ai-ml/feature-stores/SKILL.md +340 -0
- package/plugin/skills/ai-ml/llm-ops/SKILL.md +454 -0
- package/plugin/skills/ai-ml/ml-pipelines/SKILL.md +390 -0
- package/plugin/skills/ai-ml/model-monitoring/SKILL.md +398 -0
- package/plugin/skills/ai-ml/model-serving/SKILL.md +386 -0
- package/plugin/skills/event-driven/cqrs-patterns/SKILL.md +348 -0
- package/plugin/skills/event-driven/event-sourcing/SKILL.md +334 -0
- package/plugin/skills/event-driven/kafka-deep/SKILL.md +252 -0
- package/plugin/skills/event-driven/saga-orchestration/SKILL.md +335 -0
- package/plugin/skills/event-driven/schema-registry/SKILL.md +328 -0
- package/plugin/skills/event-driven/stream-processing/SKILL.md +313 -0
- package/plugin/skills/game/game-audio/SKILL.md +446 -0
- package/plugin/skills/game/game-networking/SKILL.md +490 -0
- package/plugin/skills/game/godot-patterns/SKILL.md +413 -0
- package/plugin/skills/game/shader-programming/SKILL.md +492 -0
- package/plugin/skills/game/unity-patterns/SKILL.md +488 -0
- package/plugin/skills/iot/device-provisioning/SKILL.md +405 -0
- package/plugin/skills/iot/edge-computing/SKILL.md +369 -0
- package/plugin/skills/iot/industrial-protocols/SKILL.md +438 -0
- package/plugin/skills/iot/mqtt-deep/SKILL.md +418 -0
- package/plugin/skills/iot/ota-updates/SKILL.md +426 -0
- package/plugin/skills/microservices/api-gateway-patterns/SKILL.md +201 -0
- package/plugin/skills/microservices/circuit-breaker-patterns/SKILL.md +246 -0
- package/plugin/skills/microservices/contract-testing/SKILL.md +284 -0
- package/plugin/skills/microservices/distributed-tracing/SKILL.md +246 -0
- package/plugin/skills/microservices/service-discovery/SKILL.md +304 -0
- package/plugin/skills/microservices/service-mesh/SKILL.md +181 -0
- package/plugin/skills/mobile-advanced/mobile-ci-cd/SKILL.md +407 -0
- package/plugin/skills/mobile-advanced/mobile-security/SKILL.md +403 -0
- package/plugin/skills/mobile-advanced/offline-first/SKILL.md +473 -0
- package/plugin/skills/mobile-advanced/push-notifications/SKILL.md +494 -0
- package/plugin/skills/mobile-advanced/react-native-deep/SKILL.md +374 -0
- package/plugin/skills/simulation/numerical-methods/SKILL.md +434 -0
- package/plugin/skills/simulation/parallel-computing/SKILL.md +382 -0
- package/plugin/skills/simulation/physics-engines/SKILL.md +377 -0
- package/plugin/skills/simulation/validation-verification/SKILL.md +479 -0
- package/plugin/skills/simulation/visualization-scientific/SKILL.md +365 -0
- package/plugin/templates/autonomous/archetypes/event-driven-app.yaml +460 -0
- package/plugin/templates/autonomous/archetypes/microservices-app.yaml +431 -0
- package/plugin/templates/autonomous/state-schema.yaml +1 -1
- package/plugin/workflows/ai-engineering/agent-development.md +3 -3
- package/plugin/workflows/ai-engineering/fine-tuning.md +3 -3
- package/plugin/workflows/ai-engineering/model-evaluation.md +3 -3
- package/plugin/workflows/ai-engineering/prompt-engineering.md +2 -2
- package/plugin/workflows/ai-engineering/rag-development.md +4 -4
- package/plugin/workflows/ai-ml/data-pipeline.md +188 -0
- package/plugin/workflows/ai-ml/experiment-cycle.md +203 -0
- package/plugin/workflows/ai-ml/feature-engineering.md +208 -0
- package/plugin/workflows/ai-ml/model-deployment.md +199 -0
- package/plugin/workflows/ai-ml/monitoring-setup.md +227 -0
- package/plugin/workflows/api/api-design.md +1 -1
- package/plugin/workflows/api/api-testing.md +2 -2
- package/plugin/workflows/content/technical-docs.md +1 -1
- package/plugin/workflows/database/migration.md +1 -1
- package/plugin/workflows/database/optimization.md +1 -1
- package/plugin/workflows/database/schema-design.md +3 -3
- package/plugin/workflows/development/bug-fix.md +3 -3
- package/plugin/workflows/development/code-review.md +2 -1
- package/plugin/workflows/development/feature.md +3 -3
- package/plugin/workflows/development/refactor.md +2 -2
- package/plugin/workflows/event-driven/consumer-groups.md +190 -0
- package/plugin/workflows/event-driven/event-storming.md +172 -0
- package/plugin/workflows/event-driven/replay-testing.md +186 -0
- package/plugin/workflows/event-driven/saga-implementation.md +206 -0
- package/plugin/workflows/event-driven/schema-evolution.md +173 -0
- package/plugin/workflows/fullstack/authentication.md +4 -4
- package/plugin/workflows/fullstack/full-feature.md +4 -4
- package/plugin/workflows/game-dev/content-pipeline.md +218 -0
- package/plugin/workflows/game-dev/platform-submission.md +263 -0
- package/plugin/workflows/game-dev/playtesting.md +237 -0
- package/plugin/workflows/game-dev/prototype-to-production.md +205 -0
- package/plugin/workflows/microservices/contract-first.md +151 -0
- package/plugin/workflows/microservices/distributed-tracing.md +166 -0
- package/plugin/workflows/microservices/domain-decomposition.md +123 -0
- package/plugin/workflows/microservices/integration-testing.md +149 -0
- package/plugin/workflows/microservices/service-mesh-setup.md +153 -0
- package/plugin/workflows/microservices/service-scaffolding.md +151 -0
- package/plugin/workflows/omega/1000x-innovation.md +2 -2
- package/plugin/workflows/omega/100x-architecture.md +2 -2
- package/plugin/workflows/omega/10x-improvement.md +2 -2
- package/plugin/workflows/quality/performance-optimization.md +2 -2
- package/plugin/workflows/research/best-practices.md +1 -1
- package/plugin/workflows/research/technology-research.md +1 -1
- package/plugin/workflows/security/penetration-testing.md +3 -3
- package/plugin/workflows/security/security-audit.md +3 -3
- package/plugin/workflows/sprint/sprint-execution.md +2 -2
- package/plugin/workflows/sprint/sprint-retrospective.md +1 -1
- package/plugin/workflows/sprint/sprint-setup.md +1 -1
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
# OTA Updates
|
|
2
|
+
|
|
3
|
+
Over-the-air firmware updates including delta updates, rollback mechanisms, A/B partitioning, and update orchestration.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
OTA (Over-The-Air) updates enable remote firmware upgrades for IoT devices, ensuring security patches and feature updates reach deployed devices.
|
|
8
|
+
|
|
9
|
+
## Core Concepts
|
|
10
|
+
|
|
11
|
+
### Update Strategies
|
|
12
|
+
- **Full Image**: Complete firmware replacement
|
|
13
|
+
- **Delta Updates**: Only changed bytes
|
|
14
|
+
- **A/B Partitioning**: Dual partition failsafe
|
|
15
|
+
- **Staged Rollout**: Gradual deployment
|
|
16
|
+
|
|
17
|
+
### Update Lifecycle
|
|
18
|
+
```
|
|
19
|
+
Create → Sign → Upload → Deploy → Monitor → Rollback (if needed)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## A/B Partition System
|
|
23
|
+
|
|
24
|
+
### Partition Layout
|
|
25
|
+
```
|
|
26
|
+
Flash Memory Layout:
|
|
27
|
+
┌─────────────────────────────────┐
|
|
28
|
+
│ Bootloader (Protected) │
|
|
29
|
+
├─────────────────────────────────┤
|
|
30
|
+
│ Partition A (Active) │
|
|
31
|
+
│ - Application │
|
|
32
|
+
│ - Version: 1.2.0 │
|
|
33
|
+
├─────────────────────────────────┤
|
|
34
|
+
│ Partition B (Standby) │
|
|
35
|
+
│ - Application │
|
|
36
|
+
│ - Version: 1.1.0 │
|
|
37
|
+
├─────────────────────────────────┤
|
|
38
|
+
│ Configuration (Shared) │
|
|
39
|
+
├─────────────────────────────────┤
|
|
40
|
+
│ OTA Staging Area │
|
|
41
|
+
└─────────────────────────────────┘
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### ESP32 OTA Implementation
|
|
45
|
+
```cpp
|
|
46
|
+
#include <WiFi.h>
|
|
47
|
+
#include <HTTPClient.h>
|
|
48
|
+
#include <Update.h>
|
|
49
|
+
#include <esp_ota_ops.h>
|
|
50
|
+
#include <ArduinoJson.h>
|
|
51
|
+
|
|
52
|
+
const char* FIRMWARE_VERSION = "1.2.0";
|
|
53
|
+
const char* UPDATE_SERVER = "https://ota.example.com";
|
|
54
|
+
|
|
55
|
+
struct UpdateInfo {
|
|
56
|
+
String version;
|
|
57
|
+
String url;
|
|
58
|
+
String checksum;
|
|
59
|
+
size_t size;
|
|
60
|
+
bool mandatory;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
class OTAManager {
|
|
64
|
+
private:
|
|
65
|
+
String deviceId;
|
|
66
|
+
String currentVersion;
|
|
67
|
+
|
|
68
|
+
public:
|
|
69
|
+
OTAManager(const String& id) : deviceId(id), currentVersion(FIRMWARE_VERSION) {}
|
|
70
|
+
|
|
71
|
+
bool checkForUpdate(UpdateInfo& info) {
|
|
72
|
+
HTTPClient http;
|
|
73
|
+
String url = String(UPDATE_SERVER) + "/api/updates/check";
|
|
74
|
+
url += "?device_id=" + deviceId;
|
|
75
|
+
url += "¤t_version=" + currentVersion;
|
|
76
|
+
url += "&device_type=sensor-v2";
|
|
77
|
+
|
|
78
|
+
http.begin(url);
|
|
79
|
+
int httpCode = http.GET();
|
|
80
|
+
|
|
81
|
+
if (httpCode != 200) {
|
|
82
|
+
http.end();
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
String payload = http.getString();
|
|
87
|
+
http.end();
|
|
88
|
+
|
|
89
|
+
StaticJsonDocument<512> doc;
|
|
90
|
+
deserializeJson(doc, payload);
|
|
91
|
+
|
|
92
|
+
if (!doc["update_available"].as<bool>()) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
info.version = doc["version"].as<String>();
|
|
97
|
+
info.url = doc["url"].as<String>();
|
|
98
|
+
info.checksum = doc["sha256"].as<String>();
|
|
99
|
+
info.size = doc["size"].as<size_t>();
|
|
100
|
+
info.mandatory = doc["mandatory"].as<bool>();
|
|
101
|
+
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
bool performUpdate(const UpdateInfo& info) {
|
|
106
|
+
Serial.printf("Starting OTA update to version %s\n", info.version.c_str());
|
|
107
|
+
|
|
108
|
+
HTTPClient http;
|
|
109
|
+
http.begin(info.url);
|
|
110
|
+
int httpCode = http.GET();
|
|
111
|
+
|
|
112
|
+
if (httpCode != 200) {
|
|
113
|
+
Serial.println("Failed to download firmware");
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
int contentLength = http.getSize();
|
|
118
|
+
WiFiClient* stream = http.getStreamPtr();
|
|
119
|
+
|
|
120
|
+
if (!Update.begin(contentLength)) {
|
|
121
|
+
Serial.println("Not enough space for OTA");
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Write firmware
|
|
126
|
+
size_t written = 0;
|
|
127
|
+
uint8_t buff[1024];
|
|
128
|
+
while (http.connected() && written < contentLength) {
|
|
129
|
+
size_t available = stream->available();
|
|
130
|
+
if (available) {
|
|
131
|
+
int read = stream->readBytes(buff, min(available, sizeof(buff)));
|
|
132
|
+
Update.write(buff, read);
|
|
133
|
+
written += read;
|
|
134
|
+
|
|
135
|
+
// Progress callback
|
|
136
|
+
int progress = (written * 100) / contentLength;
|
|
137
|
+
reportProgress(progress);
|
|
138
|
+
}
|
|
139
|
+
yield();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!Update.end(true)) {
|
|
143
|
+
Serial.printf("Update failed: %s\n", Update.errorString());
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Verify checksum
|
|
148
|
+
if (!verifyChecksum(info.checksum)) {
|
|
149
|
+
Serial.println("Checksum verification failed");
|
|
150
|
+
rollback();
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
Serial.println("Update successful, rebooting...");
|
|
155
|
+
reportUpdateComplete(info.version);
|
|
156
|
+
ESP.restart();
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
void validateUpdate() {
|
|
161
|
+
// Called after boot to confirm update worked
|
|
162
|
+
const esp_partition_t* running = esp_ota_get_running_partition();
|
|
163
|
+
esp_ota_img_states_t ota_state;
|
|
164
|
+
|
|
165
|
+
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
|
|
166
|
+
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
|
|
167
|
+
// Perform self-tests
|
|
168
|
+
if (selfTest()) {
|
|
169
|
+
esp_ota_mark_app_valid_cancel_rollback();
|
|
170
|
+
Serial.println("Update validated successfully");
|
|
171
|
+
} else {
|
|
172
|
+
Serial.println("Self-test failed, rolling back");
|
|
173
|
+
esp_ota_mark_app_invalid_rollback_and_reboot();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
void rollback() {
|
|
180
|
+
const esp_partition_t* running = esp_ota_get_running_partition();
|
|
181
|
+
const esp_partition_t* other = esp_ota_get_next_update_partition(running);
|
|
182
|
+
|
|
183
|
+
if (other) {
|
|
184
|
+
esp_ota_set_boot_partition(other);
|
|
185
|
+
ESP.restart();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private:
|
|
190
|
+
bool selfTest() {
|
|
191
|
+
// Verify critical systems
|
|
192
|
+
bool wifiOk = WiFi.status() == WL_CONNECTED;
|
|
193
|
+
bool sensorsOk = testSensors();
|
|
194
|
+
bool mqttOk = testMqttConnection();
|
|
195
|
+
|
|
196
|
+
return wifiOk && sensorsOk && mqttOk;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
void reportProgress(int progress) {
|
|
200
|
+
// Report to cloud
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
void reportUpdateComplete(const String& version) {
|
|
204
|
+
// Report successful update
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
bool verifyChecksum(const String& expected) {
|
|
208
|
+
// Verify SHA256 of installed image
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Delta Updates
|
|
215
|
+
|
|
216
|
+
### Creating Delta Updates
|
|
217
|
+
```python
|
|
218
|
+
import bsdiff4
|
|
219
|
+
import hashlib
|
|
220
|
+
from pathlib import Path
|
|
221
|
+
|
|
222
|
+
class DeltaUpdateGenerator:
|
|
223
|
+
def create_delta(
|
|
224
|
+
self,
|
|
225
|
+
old_firmware: Path,
|
|
226
|
+
new_firmware: Path,
|
|
227
|
+
output_path: Path
|
|
228
|
+
) -> dict:
|
|
229
|
+
"""Create a binary delta between firmware versions"""
|
|
230
|
+
old_data = old_firmware.read_bytes()
|
|
231
|
+
new_data = new_firmware.read_bytes()
|
|
232
|
+
|
|
233
|
+
# Generate delta patch
|
|
234
|
+
patch = bsdiff4.diff(old_data, new_data)
|
|
235
|
+
|
|
236
|
+
# Compress if beneficial
|
|
237
|
+
if len(patch) < len(new_data) * 0.7:
|
|
238
|
+
output_path.write_bytes(patch)
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
'type': 'delta',
|
|
242
|
+
'old_version_hash': hashlib.sha256(old_data).hexdigest(),
|
|
243
|
+
'new_version_hash': hashlib.sha256(new_data).hexdigest(),
|
|
244
|
+
'patch_hash': hashlib.sha256(patch).hexdigest(),
|
|
245
|
+
'patch_size': len(patch),
|
|
246
|
+
'full_size': len(new_data),
|
|
247
|
+
'savings_percent': round((1 - len(patch) / len(new_data)) * 100, 2)
|
|
248
|
+
}
|
|
249
|
+
else:
|
|
250
|
+
# Delta not worth it, use full update
|
|
251
|
+
return None
|
|
252
|
+
|
|
253
|
+
def apply_delta(self, old_firmware: bytes, patch: bytes) -> bytes:
|
|
254
|
+
"""Apply delta patch to create new firmware"""
|
|
255
|
+
return bsdiff4.patch(old_firmware, patch)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Update Orchestration
|
|
259
|
+
|
|
260
|
+
### Fleet Update Service
|
|
261
|
+
```python
|
|
262
|
+
from fastapi import FastAPI, BackgroundTasks
|
|
263
|
+
from pydantic import BaseModel
|
|
264
|
+
from typing import List, Optional
|
|
265
|
+
from enum import Enum
|
|
266
|
+
import asyncio
|
|
267
|
+
|
|
268
|
+
class UpdateState(Enum):
|
|
269
|
+
PENDING = "pending"
|
|
270
|
+
DOWNLOADING = "downloading"
|
|
271
|
+
INSTALLING = "installing"
|
|
272
|
+
VALIDATING = "validating"
|
|
273
|
+
COMPLETE = "complete"
|
|
274
|
+
FAILED = "failed"
|
|
275
|
+
ROLLED_BACK = "rolled_back"
|
|
276
|
+
|
|
277
|
+
class DeploymentConfig(BaseModel):
|
|
278
|
+
firmware_version: str
|
|
279
|
+
target_devices: List[str] # Device IDs or "all"
|
|
280
|
+
target_groups: List[str]
|
|
281
|
+
rollout_percentage: int = 100
|
|
282
|
+
rollout_interval_minutes: int = 60
|
|
283
|
+
failure_threshold_percent: int = 10
|
|
284
|
+
mandatory: bool = False
|
|
285
|
+
|
|
286
|
+
class DeviceUpdateStatus(BaseModel):
|
|
287
|
+
device_id: str
|
|
288
|
+
state: UpdateState
|
|
289
|
+
progress: int
|
|
290
|
+
error_message: Optional[str]
|
|
291
|
+
started_at: Optional[str]
|
|
292
|
+
completed_at: Optional[str]
|
|
293
|
+
|
|
294
|
+
class UpdateOrchestrator:
|
|
295
|
+
def __init__(self, db, notification_service):
|
|
296
|
+
self.db = db
|
|
297
|
+
self.notifications = notification_service
|
|
298
|
+
|
|
299
|
+
async def create_deployment(self, config: DeploymentConfig) -> str:
|
|
300
|
+
"""Create a new firmware deployment"""
|
|
301
|
+
deployment_id = generate_id()
|
|
302
|
+
|
|
303
|
+
# Get target devices
|
|
304
|
+
devices = await self.resolve_targets(config)
|
|
305
|
+
|
|
306
|
+
# Calculate rollout batches
|
|
307
|
+
batches = self.create_rollout_batches(
|
|
308
|
+
devices,
|
|
309
|
+
config.rollout_percentage,
|
|
310
|
+
config.rollout_interval_minutes
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
# Store deployment
|
|
314
|
+
await self.db.deployments.insert_one({
|
|
315
|
+
'id': deployment_id,
|
|
316
|
+
'config': config.dict(),
|
|
317
|
+
'batches': batches,
|
|
318
|
+
'status': 'active',
|
|
319
|
+
'created_at': datetime.utcnow()
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
# Start first batch
|
|
323
|
+
asyncio.create_task(self.execute_deployment(deployment_id))
|
|
324
|
+
|
|
325
|
+
return deployment_id
|
|
326
|
+
|
|
327
|
+
async def execute_deployment(self, deployment_id: str):
|
|
328
|
+
"""Execute deployment batches"""
|
|
329
|
+
deployment = await self.db.deployments.find_one({'id': deployment_id})
|
|
330
|
+
|
|
331
|
+
for batch_idx, batch in enumerate(deployment['batches']):
|
|
332
|
+
if deployment['status'] == 'paused':
|
|
333
|
+
break
|
|
334
|
+
|
|
335
|
+
# Notify devices in batch
|
|
336
|
+
for device_id in batch['devices']:
|
|
337
|
+
await self.notify_device(device_id, deployment['config'])
|
|
338
|
+
|
|
339
|
+
# Wait for batch completion
|
|
340
|
+
success_count, failure_count = await self.wait_for_batch(
|
|
341
|
+
deployment_id,
|
|
342
|
+
batch['devices'],
|
|
343
|
+
timeout_minutes=30
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Check failure threshold
|
|
347
|
+
failure_rate = failure_count / len(batch['devices']) * 100
|
|
348
|
+
if failure_rate > deployment['config']['failure_threshold_percent']:
|
|
349
|
+
await self.pause_deployment(deployment_id, f"Failure rate {failure_rate}% exceeded threshold")
|
|
350
|
+
break
|
|
351
|
+
|
|
352
|
+
# Wait before next batch
|
|
353
|
+
if batch_idx < len(deployment['batches']) - 1:
|
|
354
|
+
await asyncio.sleep(deployment['config']['rollout_interval_minutes'] * 60)
|
|
355
|
+
|
|
356
|
+
async def notify_device(self, device_id: str, config: dict):
|
|
357
|
+
"""Notify device of available update"""
|
|
358
|
+
await self.notifications.send(
|
|
359
|
+
device_id,
|
|
360
|
+
topic=f"devices/{device_id}/ota",
|
|
361
|
+
payload={
|
|
362
|
+
'action': 'update_available',
|
|
363
|
+
'version': config['firmware_version'],
|
|
364
|
+
'mandatory': config['mandatory']
|
|
365
|
+
}
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
async def report_device_status(
|
|
369
|
+
self,
|
|
370
|
+
deployment_id: str,
|
|
371
|
+
device_id: str,
|
|
372
|
+
status: DeviceUpdateStatus
|
|
373
|
+
):
|
|
374
|
+
"""Record device update status"""
|
|
375
|
+
await self.db.device_updates.update_one(
|
|
376
|
+
{'deployment_id': deployment_id, 'device_id': device_id},
|
|
377
|
+
{'$set': status.dict()},
|
|
378
|
+
upsert=True
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
# Check for completion
|
|
382
|
+
if status.state in [UpdateState.COMPLETE, UpdateState.FAILED, UpdateState.ROLLED_BACK]:
|
|
383
|
+
await self.check_batch_completion(deployment_id)
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Best Practices
|
|
387
|
+
|
|
388
|
+
1. **A/B Partitions**: Always have rollback capability
|
|
389
|
+
2. **Signature Verification**: Sign all firmware
|
|
390
|
+
3. **Staged Rollout**: Never update all devices at once
|
|
391
|
+
4. **Health Checks**: Validate after update
|
|
392
|
+
5. **Failure Thresholds**: Auto-pause on failures
|
|
393
|
+
|
|
394
|
+
## Security
|
|
395
|
+
|
|
396
|
+
```
|
|
397
|
+
□ Firmware signed with private key
|
|
398
|
+
□ Signature verified before installation
|
|
399
|
+
□ Secure boot enabled
|
|
400
|
+
□ Encrypted transport (HTTPS/TLS)
|
|
401
|
+
□ Version downgrade prevention
|
|
402
|
+
□ Tamper detection
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## Anti-Patterns
|
|
406
|
+
|
|
407
|
+
- No rollback capability
|
|
408
|
+
- Updating all devices simultaneously
|
|
409
|
+
- Skipping signature verification
|
|
410
|
+
- No progress reporting
|
|
411
|
+
- Missing failure handling
|
|
412
|
+
|
|
413
|
+
## When to Use
|
|
414
|
+
|
|
415
|
+
- Deployed IoT fleets
|
|
416
|
+
- Security patch distribution
|
|
417
|
+
- Feature updates
|
|
418
|
+
- Bug fixes
|
|
419
|
+
- Configuration changes
|
|
420
|
+
|
|
421
|
+
## When NOT to Use
|
|
422
|
+
|
|
423
|
+
- Development devices (use wired)
|
|
424
|
+
- Single prototype
|
|
425
|
+
- No connectivity
|
|
426
|
+
- Critical real-time systems (plan carefully)
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# API Gateway Patterns
|
|
2
|
+
|
|
3
|
+
Advanced API gateway implementation with Kong, Traefik, rate limiting, authentication, and request transformation.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
API gateways serve as the single entry point for client requests, handling cross-cutting concerns like authentication, rate limiting, and routing.
|
|
8
|
+
|
|
9
|
+
## Key Patterns
|
|
10
|
+
|
|
11
|
+
### Request Routing
|
|
12
|
+
- **Path-based Routing**: Route by URL path
|
|
13
|
+
- **Header-based Routing**: Route by headers
|
|
14
|
+
- **Method-based Routing**: Route by HTTP method
|
|
15
|
+
- **Version Routing**: API versioning strategies
|
|
16
|
+
|
|
17
|
+
### Security
|
|
18
|
+
- **Authentication**: JWT, OAuth2, API keys
|
|
19
|
+
- **Authorization**: Role-based, scope-based
|
|
20
|
+
- **Rate Limiting**: Protect backend services
|
|
21
|
+
- **IP Filtering**: Allow/deny lists
|
|
22
|
+
|
|
23
|
+
### Traffic Management
|
|
24
|
+
- **Load Balancing**: Distribute requests
|
|
25
|
+
- **Circuit Breaking**: Fail gracefully
|
|
26
|
+
- **Retries**: Handle transient failures
|
|
27
|
+
- **Timeouts**: Prevent hanging requests
|
|
28
|
+
|
|
29
|
+
### Request/Response Transformation
|
|
30
|
+
- **Header Manipulation**: Add/remove/modify headers
|
|
31
|
+
- **Body Transformation**: JSON/XML conversion
|
|
32
|
+
- **URL Rewriting**: Modify request paths
|
|
33
|
+
- **Response Aggregation**: Combine multiple responses
|
|
34
|
+
|
|
35
|
+
## Kong Configuration
|
|
36
|
+
|
|
37
|
+
### Service and Route
|
|
38
|
+
```yaml
|
|
39
|
+
# Kong declarative config
|
|
40
|
+
_format_version: "3.0"
|
|
41
|
+
|
|
42
|
+
services:
|
|
43
|
+
- name: user-service
|
|
44
|
+
url: http://user-service:8080
|
|
45
|
+
routes:
|
|
46
|
+
- name: user-route
|
|
47
|
+
paths:
|
|
48
|
+
- /api/users
|
|
49
|
+
strip_path: true
|
|
50
|
+
|
|
51
|
+
- name: order-service
|
|
52
|
+
url: http://order-service:8080
|
|
53
|
+
routes:
|
|
54
|
+
- name: order-route
|
|
55
|
+
paths:
|
|
56
|
+
- /api/orders
|
|
57
|
+
strip_path: true
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Rate Limiting Plugin
|
|
61
|
+
```yaml
|
|
62
|
+
plugins:
|
|
63
|
+
- name: rate-limiting
|
|
64
|
+
service: user-service
|
|
65
|
+
config:
|
|
66
|
+
minute: 100
|
|
67
|
+
hour: 1000
|
|
68
|
+
policy: local
|
|
69
|
+
fault_tolerant: true
|
|
70
|
+
hide_client_headers: false
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### JWT Authentication
|
|
74
|
+
```yaml
|
|
75
|
+
plugins:
|
|
76
|
+
- name: jwt
|
|
77
|
+
service: user-service
|
|
78
|
+
config:
|
|
79
|
+
uri_param_names:
|
|
80
|
+
- jwt
|
|
81
|
+
header_names:
|
|
82
|
+
- Authorization
|
|
83
|
+
claims_to_verify:
|
|
84
|
+
- exp
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Request Transformation
|
|
88
|
+
```yaml
|
|
89
|
+
plugins:
|
|
90
|
+
- name: request-transformer
|
|
91
|
+
service: user-service
|
|
92
|
+
config:
|
|
93
|
+
add:
|
|
94
|
+
headers:
|
|
95
|
+
- X-Request-ID:$(uuid)
|
|
96
|
+
- X-Forwarded-Service:user-service
|
|
97
|
+
remove:
|
|
98
|
+
headers:
|
|
99
|
+
- X-Internal-Header
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Traefik Configuration
|
|
103
|
+
|
|
104
|
+
### Dynamic Routing
|
|
105
|
+
```yaml
|
|
106
|
+
# Traefik IngressRoute
|
|
107
|
+
apiVersion: traefik.containo.us/v1alpha1
|
|
108
|
+
kind: IngressRoute
|
|
109
|
+
metadata:
|
|
110
|
+
name: api-route
|
|
111
|
+
spec:
|
|
112
|
+
entryPoints:
|
|
113
|
+
- web
|
|
114
|
+
routes:
|
|
115
|
+
- match: PathPrefix(`/api/users`)
|
|
116
|
+
kind: Rule
|
|
117
|
+
services:
|
|
118
|
+
- name: user-service
|
|
119
|
+
port: 8080
|
|
120
|
+
middlewares:
|
|
121
|
+
- name: rate-limit
|
|
122
|
+
- name: auth
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Middleware Chain
|
|
126
|
+
```yaml
|
|
127
|
+
apiVersion: traefik.containo.us/v1alpha1
|
|
128
|
+
kind: Middleware
|
|
129
|
+
metadata:
|
|
130
|
+
name: rate-limit
|
|
131
|
+
spec:
|
|
132
|
+
rateLimit:
|
|
133
|
+
average: 100
|
|
134
|
+
burst: 50
|
|
135
|
+
period: 1m
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
apiVersion: traefik.containo.us/v1alpha1
|
|
139
|
+
kind: Middleware
|
|
140
|
+
metadata:
|
|
141
|
+
name: auth
|
|
142
|
+
spec:
|
|
143
|
+
forwardAuth:
|
|
144
|
+
address: http://auth-service:8080/verify
|
|
145
|
+
trustForwardHeader: true
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Best Practices
|
|
149
|
+
|
|
150
|
+
1. **Centralize Cross-Cutting Concerns**: Auth, logging, rate limiting
|
|
151
|
+
2. **Version APIs**: Use path or header versioning
|
|
152
|
+
3. **Health Check Endpoints**: Bypass auth for health checks
|
|
153
|
+
4. **Correlation IDs**: Add unique IDs for tracing
|
|
154
|
+
5. **Graceful Degradation**: Return cached responses when backend fails
|
|
155
|
+
|
|
156
|
+
## Rate Limiting Strategies
|
|
157
|
+
|
|
158
|
+
### Token Bucket
|
|
159
|
+
```
|
|
160
|
+
- Bucket fills at constant rate
|
|
161
|
+
- Requests consume tokens
|
|
162
|
+
- Allows bursts up to bucket size
|
|
163
|
+
- Good for: APIs with occasional spikes
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Sliding Window
|
|
167
|
+
```
|
|
168
|
+
- Count requests in rolling time window
|
|
169
|
+
- Smoother than fixed window
|
|
170
|
+
- More memory intensive
|
|
171
|
+
- Good for: Consistent rate enforcement
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Leaky Bucket
|
|
175
|
+
```
|
|
176
|
+
- Fixed output rate
|
|
177
|
+
- Queue excess requests
|
|
178
|
+
- Smooths traffic completely
|
|
179
|
+
- Good for: Protecting slow backends
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Anti-Patterns
|
|
183
|
+
|
|
184
|
+
- Gateway as business logic layer
|
|
185
|
+
- Single point of failure without HA
|
|
186
|
+
- Not monitoring gateway performance
|
|
187
|
+
- Over-aggressive rate limiting
|
|
188
|
+
- Exposing internal service details
|
|
189
|
+
|
|
190
|
+
## When to Use
|
|
191
|
+
|
|
192
|
+
- Multiple clients (web, mobile, third-party)
|
|
193
|
+
- Need for consistent authentication
|
|
194
|
+
- API monetization with rate limits
|
|
195
|
+
- Backend service protection
|
|
196
|
+
|
|
197
|
+
## When NOT to Use
|
|
198
|
+
|
|
199
|
+
- Single backend service
|
|
200
|
+
- Internal service-to-service communication
|
|
201
|
+
- When latency is extremely critical
|