onec-interactive-runtime-core 0.1.19__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.
- onec_interactive_runtime_core-0.1.19.dist-info/METADATA +12 -0
- onec_interactive_runtime_core-0.1.19.dist-info/RECORD +87 -0
- onec_interactive_runtime_core-0.1.19.dist-info/WHEEL +4 -0
- onec_interactive_runtime_core-0.1.19.dist-info/licenses/COPYRIGHT +9 -0
- onec_interactive_runtime_core-0.1.19.dist-info/licenses/LICENSE +232 -0
- onec_interactive_runtime_core-0.1.19.dist-info/licenses/THIRD_PARTY_NOTICES.txt +32 -0
- onec_runtime/AGENTS.md +7 -0
- onec_runtime/__init__.py +3 -0
- onec_runtime/artifacts.py +59 -0
- onec_runtime/bootstrap.py +310 -0
- onec_runtime/breakpoint_workspace.py +249 -0
- onec_runtime/bsl/__init__.py +139 -0
- onec_runtime/bsl/diagnostics.py +1046 -0
- onec_runtime/bsl/full_ast_worker_projection.py +522 -0
- onec_runtime/bsl/generated_semantic_parser.py +6322 -0
- onec_runtime/bsl/lexer.py +164 -0
- onec_runtime/bsl/module_catalog.py +420 -0
- onec_runtime/bsl/module_delta.py +1079 -0
- onec_runtime/bsl/module_universe.py +1877 -0
- onec_runtime/bsl/notebook_cells.py +232 -0
- onec_runtime/bsl/notebook_method_globals.py +74 -0
- onec_runtime/bsl/notebook_methods.py +175 -0
- onec_runtime/bsl/parser_artifact_identity.py +119 -0
- onec_runtime/bsl/parser_target.py +388 -0
- onec_runtime/bsl/preprocessor.py +16 -0
- onec_runtime/bsl/semantic_lowering.py +1539 -0
- onec_runtime/bsl/source_maps.py +2411 -0
- onec_runtime/bsl/worker_dependency_resolver.py +289 -0
- onec_runtime/bsl/worker_preprocessor.py +247 -0
- onec_runtime/bsl/worker_projection_model.py +137 -0
- onec_runtime/bsl/worker_reload_source_map.py +1697 -0
- onec_runtime/capture.py +113 -0
- onec_runtime/capture_source.py +453 -0
- onec_runtime/compact_table.py +376 -0
- onec_runtime/compact_table_backend.py +500 -0
- onec_runtime/config.py +198 -0
- onec_runtime/configurator_agent.py +520 -0
- onec_runtime/controller_worker.py +400 -0
- onec_runtime/credentials.py +18 -0
- onec_runtime/epf_container.py +196 -0
- onec_runtime/errors.py +205 -0
- onec_runtime/experiment.py +130 -0
- onec_runtime/extension_bundle.py +944 -0
- onec_runtime/extension_lifecycle.py +402 -0
- onec_runtime/extension_state.py +222 -0
- onec_runtime/fault_injection.py +30 -0
- onec_runtime/kernel.py +179 -0
- onec_runtime/lease.py +123 -0
- onec_runtime/observation.py +287 -0
- onec_runtime/performance_profile.py +245 -0
- onec_runtime/privacy.py +263 -0
- onec_runtime/processes.py +265 -0
- onec_runtime/prototype_runtime.py +2644 -0
- onec_runtime/rdbg/__init__.py +1 -0
- onec_runtime/rdbg/models.py +130 -0
- onec_runtime/rdbg/reconnect.py +59 -0
- onec_runtime/rdbg/session.py +913 -0
- onec_runtime/rdbg/transport.py +138 -0
- onec_runtime/rdbg/xml_codec.py +980 -0
- onec_runtime/recovery.py +106 -0
- onec_runtime/recovery_journal.py +79 -0
- onec_runtime/resources/extension/OnecInteractiveRuntime.cfe +0 -0
- onec_runtime/resources/extension/extension-manifest.json +108 -0
- onec_runtime/runtime_api.py +5272 -0
- onec_runtime/runtime_contracts.py +196 -0
- onec_runtime/server_worker.py +2034 -0
- onec_runtime/session.py +2123 -0
- onec_runtime/startup_diagnostics.py +45 -0
- onec_runtime/stop_routing.py +65 -0
- onec_runtime/supervised_processes.py +232 -0
- onec_runtime/supervised_runtime.py +512 -0
- onec_runtime/supervisor.py +363 -0
- onec_runtime/supervisor_model.py +148 -0
- onec_runtime/supervisor_protocol.py +77 -0
- onec_runtime/table_materialization.py +471 -0
- onec_runtime/table_transfer_backend.py +203 -0
- onec_runtime/table_value.py +311 -0
- onec_runtime/toolchain.py +730 -0
- onec_runtime/value_materialization.py +432 -0
- onec_runtime/value_transfer_backend.py +199 -0
- onec_runtime/worker_breakpoints.py +1431 -0
- onec_runtime/worker_epf.py +313 -0
- onec_runtime/worker_epf_template.py +53 -0
- onec_runtime/worker_stage_protocol.py +516 -0
- onec_runtime/worker_universe.py +3772 -0
- onec_runtime_build/__init__.py +1 -0
- onec_runtime_build/parser_target_development.py +116 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import asdict, dataclass
|
|
4
|
+
from time import perf_counter_ns, process_time_ns
|
|
5
|
+
from typing import Callable, TypeVar
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
T = TypeVar("T")
|
|
9
|
+
|
|
10
|
+
PARSER_CALL_COUNTERS = (
|
|
11
|
+
"full_module_parses",
|
|
12
|
+
"delta_method_parses",
|
|
13
|
+
"packaging_validation_parses",
|
|
14
|
+
)
|
|
15
|
+
_INTERNAL_PARSER_CALL_COUNTERS = (*PARSER_CALL_COUNTERS, "worker_profile_parses")
|
|
16
|
+
|
|
17
|
+
_PING_PARSE_PHASES = frozenset(
|
|
18
|
+
{
|
|
19
|
+
"rdbg.ping.parse_xml",
|
|
20
|
+
"rdbg.ping.parse_targets",
|
|
21
|
+
"rdbg.ping.parse_stops",
|
|
22
|
+
"rdbg.ping.parse_local_variables",
|
|
23
|
+
"rdbg.ping.parse_evaluations",
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass(frozen=True, slots=True)
|
|
29
|
+
class PhaseEvent:
|
|
30
|
+
sequence: int
|
|
31
|
+
phase: str
|
|
32
|
+
wall_ns: int
|
|
33
|
+
cpu_ns: int
|
|
34
|
+
input_bytes: int = 0
|
|
35
|
+
output_bytes: int = 0
|
|
36
|
+
item_count: int = 0
|
|
37
|
+
page_start: int | None = None
|
|
38
|
+
result_id: str = ""
|
|
39
|
+
error_present: bool = False
|
|
40
|
+
|
|
41
|
+
def as_dict(self) -> dict[str, object]:
|
|
42
|
+
return asdict(self)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True, slots=True)
|
|
46
|
+
class ParserCallCounters:
|
|
47
|
+
full_module_parses: int = 0
|
|
48
|
+
delta_method_parses: int = 0
|
|
49
|
+
packaging_validation_parses: int = 0
|
|
50
|
+
worker_profile_parses: int = 0
|
|
51
|
+
|
|
52
|
+
def as_tuple(self) -> tuple[int, int, int]:
|
|
53
|
+
return (
|
|
54
|
+
self.full_module_parses,
|
|
55
|
+
self.delta_method_parses,
|
|
56
|
+
self.packaging_validation_parses,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
def as_dict(self) -> dict[str, int]:
|
|
60
|
+
return {
|
|
61
|
+
"full_module_parses": self.full_module_parses,
|
|
62
|
+
"delta_method_parses": self.delta_method_parses,
|
|
63
|
+
"packaging_validation_parses": self.packaging_validation_parses,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class PhaseRecorder:
|
|
68
|
+
"""Records aggregate timings without retaining runtime values or payloads."""
|
|
69
|
+
|
|
70
|
+
def __init__(
|
|
71
|
+
self,
|
|
72
|
+
*,
|
|
73
|
+
wall_clock_ns: Callable[[], int] = perf_counter_ns,
|
|
74
|
+
cpu_clock_ns: Callable[[], int] = process_time_ns,
|
|
75
|
+
) -> None:
|
|
76
|
+
self.events: list[PhaseEvent] = []
|
|
77
|
+
self._wall_clock_ns = wall_clock_ns
|
|
78
|
+
self._cpu_clock_ns = cpu_clock_ns
|
|
79
|
+
self._parser_calls = {name: 0 for name in _INTERNAL_PARSER_CALL_COUNTERS}
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def parser_calls(self) -> ParserCallCounters:
|
|
83
|
+
return ParserCallCounters(**self._parser_calls)
|
|
84
|
+
|
|
85
|
+
def measure_parser(
|
|
86
|
+
self,
|
|
87
|
+
counter: str,
|
|
88
|
+
operation: Callable[[], T],
|
|
89
|
+
) -> T:
|
|
90
|
+
self.record_parser_call(counter)
|
|
91
|
+
return self.measure("semantic_parse", operation)
|
|
92
|
+
|
|
93
|
+
def record_parser_call(self, counter: str) -> None:
|
|
94
|
+
if counter not in self._parser_calls:
|
|
95
|
+
raise ValueError("parser call counter is invalid")
|
|
96
|
+
self._parser_calls[counter] += 1
|
|
97
|
+
|
|
98
|
+
def record_duration(
|
|
99
|
+
self,
|
|
100
|
+
phase: str,
|
|
101
|
+
*,
|
|
102
|
+
wall_ns: int,
|
|
103
|
+
cpu_ns: int = 0,
|
|
104
|
+
input_bytes: int = 0,
|
|
105
|
+
output_bytes: int = 0,
|
|
106
|
+
item_count: int = 0,
|
|
107
|
+
result_id: str = "",
|
|
108
|
+
) -> None:
|
|
109
|
+
if not isinstance(phase, str) or not phase:
|
|
110
|
+
raise ValueError("phase must not be empty")
|
|
111
|
+
counters = (wall_ns, cpu_ns, input_bytes, output_bytes, item_count)
|
|
112
|
+
if any(type(value) is not int or value < 0 for value in counters):
|
|
113
|
+
raise ValueError("profile counters must be non-negative integers")
|
|
114
|
+
self.events.append(
|
|
115
|
+
PhaseEvent(
|
|
116
|
+
sequence=len(self.events) + 1,
|
|
117
|
+
phase=phase,
|
|
118
|
+
wall_ns=wall_ns,
|
|
119
|
+
cpu_ns=cpu_ns,
|
|
120
|
+
input_bytes=input_bytes,
|
|
121
|
+
output_bytes=output_bytes,
|
|
122
|
+
item_count=item_count,
|
|
123
|
+
result_id=result_id,
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def measure(
|
|
128
|
+
self,
|
|
129
|
+
phase: str,
|
|
130
|
+
operation: Callable[[], T],
|
|
131
|
+
*,
|
|
132
|
+
input_bytes: int = 0,
|
|
133
|
+
page_start: int | None = None,
|
|
134
|
+
result_id: str = "",
|
|
135
|
+
output_bytes: Callable[[T], int] | None = None,
|
|
136
|
+
item_count: Callable[[T], int] | None = None,
|
|
137
|
+
) -> T:
|
|
138
|
+
if not phase:
|
|
139
|
+
raise ValueError("phase must not be empty")
|
|
140
|
+
if input_bytes < 0 or (page_start is not None and page_start < 0):
|
|
141
|
+
raise ValueError("profile counters must be non-negative")
|
|
142
|
+
wall_started = self._wall_clock_ns()
|
|
143
|
+
cpu_started = self._cpu_clock_ns()
|
|
144
|
+
try:
|
|
145
|
+
result = operation()
|
|
146
|
+
except BaseException:
|
|
147
|
+
self._append(
|
|
148
|
+
phase,
|
|
149
|
+
wall_started,
|
|
150
|
+
cpu_started,
|
|
151
|
+
input_bytes=input_bytes,
|
|
152
|
+
page_start=page_start,
|
|
153
|
+
result_id=result_id,
|
|
154
|
+
error_present=True,
|
|
155
|
+
)
|
|
156
|
+
raise
|
|
157
|
+
measured_output = output_bytes(result) if output_bytes is not None else 0
|
|
158
|
+
measured_items = item_count(result) if item_count is not None else 0
|
|
159
|
+
if measured_output < 0 or measured_items < 0:
|
|
160
|
+
raise ValueError("profile counters must be non-negative")
|
|
161
|
+
self._append(
|
|
162
|
+
phase,
|
|
163
|
+
wall_started,
|
|
164
|
+
cpu_started,
|
|
165
|
+
input_bytes=input_bytes,
|
|
166
|
+
output_bytes=measured_output,
|
|
167
|
+
item_count=measured_items,
|
|
168
|
+
page_start=page_start,
|
|
169
|
+
result_id=result_id,
|
|
170
|
+
)
|
|
171
|
+
return result
|
|
172
|
+
|
|
173
|
+
def _append(
|
|
174
|
+
self,
|
|
175
|
+
phase: str,
|
|
176
|
+
wall_started: int,
|
|
177
|
+
cpu_started: int,
|
|
178
|
+
*,
|
|
179
|
+
input_bytes: int = 0,
|
|
180
|
+
output_bytes: int = 0,
|
|
181
|
+
item_count: int = 0,
|
|
182
|
+
page_start: int | None = None,
|
|
183
|
+
result_id: str = "",
|
|
184
|
+
error_present: bool = False,
|
|
185
|
+
) -> None:
|
|
186
|
+
self.events.append(
|
|
187
|
+
PhaseEvent(
|
|
188
|
+
sequence=len(self.events) + 1,
|
|
189
|
+
phase=phase,
|
|
190
|
+
wall_ns=self._wall_clock_ns() - wall_started,
|
|
191
|
+
cpu_ns=self._cpu_clock_ns() - cpu_started,
|
|
192
|
+
input_bytes=input_bytes,
|
|
193
|
+
output_bytes=output_bytes,
|
|
194
|
+
item_count=item_count,
|
|
195
|
+
page_start=page_start,
|
|
196
|
+
result_id=result_id,
|
|
197
|
+
error_present=error_present,
|
|
198
|
+
)
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def summarize_phases(events: list[PhaseEvent]) -> dict[str, object]:
|
|
203
|
+
by_phase: dict[str, dict[str, int]] = {}
|
|
204
|
+
for event in events:
|
|
205
|
+
totals = by_phase.setdefault(
|
|
206
|
+
event.phase,
|
|
207
|
+
{
|
|
208
|
+
"calls": 0,
|
|
209
|
+
"wall_ns": 0,
|
|
210
|
+
"cpu_ns": 0,
|
|
211
|
+
"input_bytes": 0,
|
|
212
|
+
"output_bytes": 0,
|
|
213
|
+
"item_count": 0,
|
|
214
|
+
"error_count": 0,
|
|
215
|
+
},
|
|
216
|
+
)
|
|
217
|
+
totals["calls"] += 1
|
|
218
|
+
totals["wall_ns"] += event.wall_ns
|
|
219
|
+
totals["cpu_ns"] += event.cpu_ns
|
|
220
|
+
totals["input_bytes"] += event.input_bytes
|
|
221
|
+
totals["output_bytes"] += event.output_bytes
|
|
222
|
+
totals["item_count"] += event.item_count
|
|
223
|
+
totals["error_count"] += int(event.error_present)
|
|
224
|
+
ping_response_bytes = by_phase.get("rdbg.ping.request", {}).get(
|
|
225
|
+
"output_bytes", 0
|
|
226
|
+
)
|
|
227
|
+
ping_parser_input_bytes = sum(
|
|
228
|
+
by_phase.get(phase, {}).get("input_bytes", 0)
|
|
229
|
+
for phase in _PING_PARSE_PHASES
|
|
230
|
+
)
|
|
231
|
+
return {
|
|
232
|
+
"event_count": len(events),
|
|
233
|
+
"by_phase": by_phase,
|
|
234
|
+
"derived": {
|
|
235
|
+
"ping_response_bytes": ping_response_bytes,
|
|
236
|
+
"ping_parser_input_bytes": ping_parser_input_bytes,
|
|
237
|
+
"ping_xml_parse_amplification": (
|
|
238
|
+
ping_parser_input_bytes / ping_response_bytes
|
|
239
|
+
if ping_response_bytes
|
|
240
|
+
else 0.0
|
|
241
|
+
),
|
|
242
|
+
"profiled_wall_ns": sum(event.wall_ns for event in events),
|
|
243
|
+
"profiled_cpu_ns": sum(event.cpu_ns for event in events),
|
|
244
|
+
},
|
|
245
|
+
}
|
onec_runtime/privacy.py
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import fields, is_dataclass
|
|
4
|
+
from hashlib import sha256
|
|
5
|
+
import re
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from onec_runtime.runtime_contracts import sanitize_normalized_diagnostic
|
|
9
|
+
from onec_runtime.bsl import NormalizedDiagnostic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
_PLATFORM_DIAGNOSTIC_LIMIT = 4_096
|
|
13
|
+
_SENSITIVE_DIAGNOSTIC_KEY = (
|
|
14
|
+
r"(?:"
|
|
15
|
+
r"[0-9A-Za-z_.-]*"
|
|
16
|
+
r"(?:password|passwd|passphrase|secret|token|authorization|credential(?:s)?)"
|
|
17
|
+
r"(?:[_.-]?(?:id|key|value|header))?|"
|
|
18
|
+
r"rdbg[_\-.]?(?:session|connection|client|server|process|subject|"
|
|
19
|
+
r"target|object|property|seance)"
|
|
20
|
+
r"(?:[_\-.]?(?:pid|id|key))?|"
|
|
21
|
+
r"rdbg[0-9A-Za-z_.-]*(?:pid|id|key)|"
|
|
22
|
+
r"(?:process|session|connection|client|server|subject|runtime|worker)"
|
|
23
|
+
r"[_\-.]?(?:pid|id|token|key|secret|credential(?:s)?)|"
|
|
24
|
+
r"(?:process|session|connection|client|server|subject|runtime|worker)"
|
|
25
|
+
r"[ \t]+(?:pid|id|token|key|secret|credential(?:s)?)|"
|
|
26
|
+
r"(?:access|refresh|auth|api)[_\-.]?(?:key|secret|credential|header)|"
|
|
27
|
+
r"pid"
|
|
28
|
+
r")"
|
|
29
|
+
)
|
|
30
|
+
_SENSITIVE_ASSIGNMENT_RE = re.compile(
|
|
31
|
+
rf"""
|
|
32
|
+
(?P<head>
|
|
33
|
+
(?:
|
|
34
|
+
["']{_SENSITIVE_DIAGNOSTIC_KEY}["']
|
|
35
|
+
|
|
|
36
|
+
(?<![0-9A-Za-z_]){_SENSITIVE_DIAGNOSTIC_KEY}(?![0-9A-Za-z_])
|
|
37
|
+
)
|
|
38
|
+
(?:[ \t]*(?:=|:)[ \t]*|[ \t]+)
|
|
39
|
+
)
|
|
40
|
+
(?P<value>
|
|
41
|
+
"(?:\\.|[^"\\])*"
|
|
42
|
+
|'(?:\\.|[^'\\])*'
|
|
43
|
+
|[^\r\n,;}}\]]+
|
|
44
|
+
)
|
|
45
|
+
""",
|
|
46
|
+
re.IGNORECASE | re.VERBOSE,
|
|
47
|
+
)
|
|
48
|
+
_AUTHORIZATION_RE = re.compile(
|
|
49
|
+
r"\b(?:bearer|basic)\s+[^\s,;}}\]]+",
|
|
50
|
+
re.IGNORECASE,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def diagnostic_to_public_wire(value: NormalizedDiagnostic) -> dict[str, object]:
|
|
55
|
+
"""Render one canonical visible-only diagnostic or fail closed."""
|
|
56
|
+
try:
|
|
57
|
+
safe = sanitize_normalized_diagnostic(value)
|
|
58
|
+
if safe is None:
|
|
59
|
+
return {}
|
|
60
|
+
visible_location = safe.visible_location
|
|
61
|
+
related = safe.related_visible_span
|
|
62
|
+
return {
|
|
63
|
+
"diagnostic_id": safe.diagnostic_id,
|
|
64
|
+
"runtime_summary": safe.runtime_summary,
|
|
65
|
+
"stage": safe.stage.value,
|
|
66
|
+
"mapping_confidence": safe.mapping_confidence.value,
|
|
67
|
+
"visible_location": (
|
|
68
|
+
None
|
|
69
|
+
if visible_location is None
|
|
70
|
+
else {
|
|
71
|
+
"line": visible_location.line,
|
|
72
|
+
"column": visible_location.column,
|
|
73
|
+
"span": _span_wire(visible_location.span),
|
|
74
|
+
}
|
|
75
|
+
),
|
|
76
|
+
"related_visible_span": (
|
|
77
|
+
None if related is None else _span_wire(related)
|
|
78
|
+
),
|
|
79
|
+
"excerpt": None,
|
|
80
|
+
"synthetic_region": safe.synthetic_region,
|
|
81
|
+
}
|
|
82
|
+
except BaseException:
|
|
83
|
+
return {}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def diagnostic_to_expert_wire(value: NormalizedDiagnostic) -> dict[str, object]:
|
|
87
|
+
"""Render the bounded expert allowlist without source or runtime identity."""
|
|
88
|
+
try:
|
|
89
|
+
safe = sanitize_normalized_diagnostic(value)
|
|
90
|
+
public = diagnostic_to_public_wire(value)
|
|
91
|
+
if safe is None or not public:
|
|
92
|
+
return {}
|
|
93
|
+
lowered = safe.lowered_location
|
|
94
|
+
platform, platform_truncated, platform_redacted = (
|
|
95
|
+
bounded_platform_diagnostic(
|
|
96
|
+
safe.platform_diagnostic,
|
|
97
|
+
truncated=safe.platform_diagnostic_truncated,
|
|
98
|
+
redacted=safe.platform_diagnostic_redacted,
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
return {
|
|
102
|
+
**public,
|
|
103
|
+
"lowered_location": (
|
|
104
|
+
None
|
|
105
|
+
if lowered is None
|
|
106
|
+
else {
|
|
107
|
+
"line": lowered.line,
|
|
108
|
+
"column": lowered.column,
|
|
109
|
+
"offset": lowered.offset,
|
|
110
|
+
"span": _span_wire(lowered.span),
|
|
111
|
+
}
|
|
112
|
+
),
|
|
113
|
+
"platform_diagnostic": platform,
|
|
114
|
+
"platform_diagnostic_sha256": safe.platform_diagnostic_sha256,
|
|
115
|
+
"platform_diagnostic_truncated": platform_truncated,
|
|
116
|
+
"platform_diagnostic_redacted": platform_redacted,
|
|
117
|
+
"execution_artifact_sha256": safe.execution_artifact_sha256,
|
|
118
|
+
"source_map_sha256": safe.source_map_sha256,
|
|
119
|
+
# RuntimeApi can bind these exact nullable fields from its
|
|
120
|
+
# pre-dispatch provenance; the diagnostic itself never invents it.
|
|
121
|
+
"worker_generation": None,
|
|
122
|
+
"worker_manifest_sha256": None,
|
|
123
|
+
}
|
|
124
|
+
except BaseException:
|
|
125
|
+
return {}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def bounded_platform_diagnostic(
|
|
129
|
+
value: str | None,
|
|
130
|
+
*,
|
|
131
|
+
truncated: bool,
|
|
132
|
+
redacted: bool,
|
|
133
|
+
) -> tuple[str | None, bool, bool]:
|
|
134
|
+
"""Bound and redact credential/process identities in expert-only prose."""
|
|
135
|
+
if type(truncated) is not bool or type(redacted) is not bool:
|
|
136
|
+
return None, True, True
|
|
137
|
+
if value is None:
|
|
138
|
+
return None, truncated, redacted
|
|
139
|
+
if type(value) is not str:
|
|
140
|
+
return None, True, True
|
|
141
|
+
bounded = value[:_PLATFORM_DIAGNOSTIC_LIMIT]
|
|
142
|
+
input_truncated = len(value) > _PLATFORM_DIAGNOSTIC_LIMIT
|
|
143
|
+
bounded, assignment_count = _SENSITIVE_ASSIGNMENT_RE.subn(
|
|
144
|
+
lambda match: f"{match.group('head')}<redacted>",
|
|
145
|
+
bounded,
|
|
146
|
+
)
|
|
147
|
+
bounded, authorization_count = _AUTHORIZATION_RE.subn(
|
|
148
|
+
"<redacted credential>",
|
|
149
|
+
bounded,
|
|
150
|
+
)
|
|
151
|
+
expansion_truncated = len(bounded) > _PLATFORM_DIAGNOSTIC_LIMIT
|
|
152
|
+
if len(bounded) > _PLATFORM_DIAGNOSTIC_LIMIT:
|
|
153
|
+
bounded = bounded[:_PLATFORM_DIAGNOSTIC_LIMIT]
|
|
154
|
+
return (
|
|
155
|
+
bounded,
|
|
156
|
+
truncated or input_truncated or expansion_truncated,
|
|
157
|
+
redacted or assignment_count > 0 or authorization_count > 0,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _span_wire(value: object) -> dict[str, object]:
|
|
162
|
+
return {
|
|
163
|
+
"start": getattr(value, "start"),
|
|
164
|
+
"end": getattr(value, "end"),
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def public_artifact_value(value: Any) -> Any:
|
|
169
|
+
"""Recursively redact reversible BSL sources from automatic evidence paths."""
|
|
170
|
+
kind = type(value).__name__
|
|
171
|
+
if kind == "ModuleLocation":
|
|
172
|
+
return {
|
|
173
|
+
"module_type": value.module_type,
|
|
174
|
+
"line": value.line,
|
|
175
|
+
"extension_name": value.extension_name,
|
|
176
|
+
}
|
|
177
|
+
if kind == "WorkerGenerationDebugView":
|
|
178
|
+
return {
|
|
179
|
+
"handle": public_artifact_value(value.handle),
|
|
180
|
+
"module_count": len(value.modules),
|
|
181
|
+
}
|
|
182
|
+
if kind == "WorkerModuleDebugView":
|
|
183
|
+
return {
|
|
184
|
+
"source_unit": public_artifact_value(value.source_unit),
|
|
185
|
+
"canonical_module": value.canonical_module,
|
|
186
|
+
"artifact_sha256": value.artifact_sha256,
|
|
187
|
+
"source_map_sha256": value.source_map_sha256,
|
|
188
|
+
}
|
|
189
|
+
if kind == "WorkerBreakpointPlan":
|
|
190
|
+
return {
|
|
191
|
+
"proposal_id": value.proposal_id,
|
|
192
|
+
"expected_catalog_version": value.expected_catalog_version,
|
|
193
|
+
"result_id": value.result_id,
|
|
194
|
+
"desired_slot_count": len(value.desired_slots),
|
|
195
|
+
"removed_ids": public_artifact_value(value.removed_ids),
|
|
196
|
+
"next_snapshot": public_artifact_value(value.next_snapshot),
|
|
197
|
+
}
|
|
198
|
+
if kind == "WorkerBreakpointBinding":
|
|
199
|
+
return {
|
|
200
|
+
"breakpoint_id": value.breakpoint_id,
|
|
201
|
+
"generation": public_artifact_value(value.generation),
|
|
202
|
+
"location": public_artifact_value(value.location),
|
|
203
|
+
}
|
|
204
|
+
if kind == "WorkerFrameProvenance":
|
|
205
|
+
return "<redacted worker frame provenance>"
|
|
206
|
+
if kind == "WorkerArtifact":
|
|
207
|
+
return {
|
|
208
|
+
"logical_name": value.logical_name,
|
|
209
|
+
"source_sha256": value.source_sha256,
|
|
210
|
+
"source_map_sha256": value.source_map_sha256,
|
|
211
|
+
"artifact_sha256": value.artifact_sha256,
|
|
212
|
+
"source_provenance": public_artifact_value(value.source_provenance),
|
|
213
|
+
"exports": public_artifact_value(value.exports),
|
|
214
|
+
}
|
|
215
|
+
if kind == "OperationHandle":
|
|
216
|
+
return {
|
|
217
|
+
"operation_id": value.operation_id,
|
|
218
|
+
"visible_source_sha256": _source_sha256(value.visible_source),
|
|
219
|
+
"lowered_source_sha256": _source_sha256(value.lowered_source),
|
|
220
|
+
"messages_intercepted": value.messages_intercepted,
|
|
221
|
+
}
|
|
222
|
+
if kind == "CaptureCellResult":
|
|
223
|
+
return {
|
|
224
|
+
"operation_id": value.operation_id,
|
|
225
|
+
"visible_source_sha256": _source_sha256(value.visible_source),
|
|
226
|
+
"lowered_source_sha256": _source_sha256(value.lowered_source),
|
|
227
|
+
"result": public_artifact_value(value.result),
|
|
228
|
+
"messages": public_artifact_value(value.messages),
|
|
229
|
+
}
|
|
230
|
+
if kind == "NotebookCell":
|
|
231
|
+
return {
|
|
232
|
+
"worker_source_sha256": _source_sha256(value.worker_source),
|
|
233
|
+
"statement_source_sha256": _source_sha256(value.statement_source),
|
|
234
|
+
"exports": public_artifact_value(value.exports),
|
|
235
|
+
}
|
|
236
|
+
if is_dataclass(value) and not isinstance(value, type):
|
|
237
|
+
return {
|
|
238
|
+
item.name: public_artifact_value(getattr(value, item.name))
|
|
239
|
+
for item in fields(value)
|
|
240
|
+
}
|
|
241
|
+
if isinstance(value, dict):
|
|
242
|
+
return _public_mapping(value)
|
|
243
|
+
if isinstance(value, (tuple, list, set, frozenset)):
|
|
244
|
+
return [public_artifact_value(item) for item in value]
|
|
245
|
+
return value
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _source_sha256(source: str) -> str:
|
|
249
|
+
return sha256(source.encode("utf-8")).hexdigest()
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _public_mapping(value: dict[Any, Any]) -> dict[str, Any]:
|
|
253
|
+
result = {str(key): public_artifact_value(item) for key, item in value.items()}
|
|
254
|
+
for field_name in (
|
|
255
|
+
"visible_source",
|
|
256
|
+
"lowered_source",
|
|
257
|
+
"worker_source",
|
|
258
|
+
"statement_source",
|
|
259
|
+
):
|
|
260
|
+
source = result.pop(field_name, None)
|
|
261
|
+
if isinstance(source, str):
|
|
262
|
+
result[f"{field_name}_sha256"] = _source_sha256(source)
|
|
263
|
+
return result
|