@le-space/rootfs 0.3.22 → 0.3.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@le-space/rootfs",
3
- "version": "0.3.22",
3
+ "version": "0.3.24",
4
4
  "description": "Shared rootfs contract parsing, reference profile assets, and build helpers.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -111,31 +111,49 @@ def sign_aleph_message(unsigned_message: dict[str, object], private_key: str) ->
111
111
  return signed
112
112
 
113
113
 
114
- def is_invalid_message_format(http_status: int, payload: dict) -> bool:
114
+ def iter_validation_errors(payload: object) -> list[dict]:
115
+ if isinstance(payload, list):
116
+ return [entry for entry in payload if isinstance(entry, dict)]
117
+ return []
118
+
119
+
120
+ def is_invalid_message_format(http_status: int, payload: object) -> bool:
115
121
  if http_status != 422:
116
122
  return False
117
- details = payload.get("details")
118
- if isinstance(details, str) and "InvalidMessageFormat" in details:
119
- return True
120
- if isinstance(details, dict):
121
- message = details.get("message")
123
+
124
+ if isinstance(payload, dict):
125
+ details = payload.get("details")
126
+ if isinstance(details, str) and "InvalidMessageFormat" in details:
127
+ return True
128
+ if isinstance(details, dict):
129
+ message = details.get("message")
130
+ if isinstance(message, str) and "InvalidMessageFormat" in message:
131
+ return True
132
+
133
+ for entry in iter_validation_errors(payload):
134
+ message = entry.get("msg")
135
+ location = entry.get("loc")
122
136
  if isinstance(message, str) and "InvalidMessageFormat" in message:
123
137
  return True
138
+ if message == "Field required" and location == ["message"]:
139
+ return True
140
+
124
141
  return False
125
142
 
126
143
 
127
- def is_retryable_broadcast_failure(http_status: int, payload: dict) -> bool:
144
+ def is_retryable_broadcast_failure(http_status: int, payload: object) -> bool:
128
145
  if http_status >= 500:
129
146
  return True
130
- publication_status = payload.get("publication_status")
131
- if isinstance(publication_status, dict):
132
- status = publication_status.get("status")
133
- if isinstance(status, str) and status.strip().lower() == "error":
134
- return True
147
+ if isinstance(payload, dict):
148
+ publication_status = payload.get("publication_status")
149
+ if isinstance(publication_status, dict):
150
+ status = publication_status.get("status")
151
+ if isinstance(status, str) and status.strip().lower() == "error":
152
+ return True
135
153
  return False
136
154
 
137
155
 
138
- def broadcast_aleph_message(api_host: str, message: dict[str, object]) -> tuple[int, dict]:
156
+ def broadcast_aleph_message(api_host: str, message: dict[str, object]) -> tuple[int, object]:
139
157
  url = urllib.parse.urljoin(api_host.rstrip("/") + "/", "api/v0/messages")
140
158
  attempts = [
141
159
  {"sync": True, "message": message},
@@ -303,31 +303,49 @@ def sign_aleph_message(unsigned_message: dict[str, object], private_key: str) ->
303
303
  return signed
304
304
 
305
305
 
306
- def is_invalid_message_format(http_status: int, payload: dict) -> bool:
306
+ def iter_validation_errors(payload: object) -> list[dict]:
307
+ if isinstance(payload, list):
308
+ return [entry for entry in payload if isinstance(entry, dict)]
309
+ return []
310
+
311
+
312
+ def is_invalid_message_format(http_status: int, payload: object) -> bool:
307
313
  if http_status != 422:
308
314
  return False
309
- details = payload.get("details")
310
- if isinstance(details, str) and "InvalidMessageFormat" in details:
311
- return True
312
- if isinstance(details, dict):
313
- message = details.get("message")
315
+
316
+ if isinstance(payload, dict):
317
+ details = payload.get("details")
318
+ if isinstance(details, str) and "InvalidMessageFormat" in details:
319
+ return True
320
+ if isinstance(details, dict):
321
+ message = details.get("message")
322
+ if isinstance(message, str) and "InvalidMessageFormat" in message:
323
+ return True
324
+
325
+ for entry in iter_validation_errors(payload):
326
+ message = entry.get("msg")
327
+ location = entry.get("loc")
314
328
  if isinstance(message, str) and "InvalidMessageFormat" in message:
315
329
  return True
330
+ if message == "Field required" and location == ["message"]:
331
+ return True
332
+
316
333
  return False
317
334
 
318
335
 
319
- def is_retryable_broadcast_failure(http_status: int, payload: dict) -> bool:
336
+ def is_retryable_broadcast_failure(http_status: int, payload: object) -> bool:
320
337
  if http_status >= 500:
321
338
  return True
322
- publication_status = payload.get("publication_status")
323
- if isinstance(publication_status, dict):
324
- status = publication_status.get("status")
325
- if isinstance(status, str) and status.strip().lower() == "error":
326
- return True
339
+ if isinstance(payload, dict):
340
+ publication_status = payload.get("publication_status")
341
+ if isinstance(publication_status, dict):
342
+ status = publication_status.get("status")
343
+ if isinstance(status, str) and status.strip().lower() == "error":
344
+ return True
327
345
  return False
328
346
 
329
347
 
330
- def broadcast_aleph_message(api_host: str, message: dict[str, object]) -> tuple[int, dict]:
348
+ def broadcast_aleph_message(api_host: str, message: dict[str, object]) -> tuple[int, object]:
331
349
  url = urllib.parse.urljoin(api_host.rstrip("/") + "/", "api/v0/messages")
332
350
  attempts = [
333
351
  {"sync": True, "message": message},