aetherruntime-arch 2.0.0__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.
@@ -0,0 +1,314 @@
1
+ """
2
+ AetherRuntime v2.0.0 — Runtime assurance for the Aether family.
3
+
4
+ AetherRuntime is the **sixth functional dimension** (provisional) of the
5
+ Aether family. It investigates whether a runtime-assurance gap genuinely
6
+ exists, and specifies a five-layer architecture:
7
+
8
+ 1. Monitoring
9
+ 2. Detection
10
+ 3. Containment
11
+ 4. Halt
12
+ 5. Recovery
13
+
14
+ Quick start:
15
+ >>> from aetherruntime import (
16
+ ... Agent, AgentStatus, TelemetryCategory,
17
+ ... create_agent, create_runtime_config,
18
+ ... )
19
+ >>> agent = create_agent(public_key=secrets.token_bytes(32))
20
+ >>> agent.status = AgentStatus.RUNNING
21
+
22
+ Reference:
23
+ Paper (v0.1.0): https://doi.org/10.5281/zenodo.24078477
24
+ Figshare: https://doi.org/10.6084/m9.figshare.34955746
25
+ OSF: https://doi.org/10.17605/OSF.IO/KZU7P
26
+ Website: https://aetherruntime.netlify.app
27
+
28
+ Status:
29
+ Reference Implementation (v2.0.0). No real-world deployment.
30
+ Propositions P1–P2 are proof sketches.
31
+ """
32
+
33
+ # ─── Version ───
34
+ from .__version__ import (
35
+ __version__,
36
+ __paper_version__,
37
+ __author__,
38
+ __email__,
39
+ __orcid__,
40
+ __affiliation__,
41
+ __license__,
42
+ __doi__,
43
+ __figshare_doi__,
44
+ __osf_doi__,
45
+ __record_id__,
46
+ __website__,
47
+ __github__,
48
+ __gitlab__,
49
+ __codeberg__,
50
+ __bitbucket__,
51
+ __pypi__,
52
+ __aethergit_doi__,
53
+ __aetherflow_doi__,
54
+ __aetherproof_doi__,
55
+ __aethermesh_doi__,
56
+ __aethergovern_doi__,
57
+ __status__,
58
+ __real_world_deployment__,
59
+ __peer_reviewed__,
60
+ )
61
+
62
+ # ─── Models (10 entities + 4 enums) ───
63
+ from .models import (
64
+ Agent,
65
+ AgentStatus,
66
+ AnomalyAlert,
67
+ Baseline,
68
+ BaselineModel,
69
+ ContainmentLevel,
70
+ ContainmentPolicy,
71
+ HaltApproval,
72
+ HaltOrder,
73
+ RecoveryRecord,
74
+ RuntimeConfig,
75
+ Snapshot,
76
+ TelemetryCategory,
77
+ TelemetryRecord,
78
+ create_agent,
79
+ create_runtime_config,
80
+ )
81
+
82
+ # ─── Monitoring (Layer 1) ───
83
+ from .monitoring import (
84
+ collect,
85
+ collect_batch,
86
+ TelemetryLog,
87
+ update_baseline,
88
+ update_all_baselines,
89
+ BaselineRegistry,
90
+ AgentNotRunning,
91
+ InvalidValue,
92
+ NonMonotonicTimestamp,
93
+ AgentNotFound as MonitoringAgentNotFound,
94
+ InsufficientTelemetry,
95
+ InvalidWindowSize,
96
+ )
97
+
98
+ # ─── Detection (Layer 2) ───
99
+ from .detection import (
100
+ detect,
101
+ detect_batch,
102
+ summarize_detection,
103
+ DetectionSummary,
104
+ AlertRegistry,
105
+ AlertStats,
106
+ validate_alert_against_telemetry,
107
+ filter_alerts_by_confidence,
108
+ group_alerts_by_agent,
109
+ latest_alert_for_agent,
110
+ TelemetryNotFound,
111
+ BaselineNotFound,
112
+ NonDeterministic,
113
+ )
114
+
115
+ # ─── Containment (Layer 3) ───
116
+ from .containment import (
117
+ contain,
118
+ release,
119
+ is_expired,
120
+ ContainmentRegistry,
121
+ DEFAULT_RESTRICTIONS,
122
+ IsolationManager,
123
+ IsolationState,
124
+ ResourceSnapshot,
125
+ enforce_restrictions,
126
+ apply_isolation,
127
+ release_isolation,
128
+ AlertNotFound,
129
+ InvalidLevel,
130
+ ExpiryInPast,
131
+ AlreadyContained,
132
+ )
133
+
134
+ # ─── Halt (Layer 4) ───
135
+ from .halt import (
136
+ propose_halt,
137
+ HaltOrderRegistry,
138
+ compute_halt_window,
139
+ validate_halt_window,
140
+ approve_halt,
141
+ approve_batch,
142
+ QuorumTracker,
143
+ AgentNotFound as HaltAgentNotFound,
144
+ UnauthorizedProposer,
145
+ HaltNotFound,
146
+ AlreadyApproved,
147
+ QuorumAlreadyReached,
148
+ )
149
+
150
+ # ─── Recovery (Layer 5) ───
151
+ from .recovery import (
152
+ create_snapshot,
153
+ verify_snapshot,
154
+ SnapshotRegistry,
155
+ HashMismatch,
156
+ get_snapshot_hash,
157
+ compare_snapshots,
158
+ recover,
159
+ RecoveryRegistry,
160
+ RecoveryStats,
161
+ AgentNotHalted,
162
+ UnauthorizedReauthorizer,
163
+ VerificationFailed,
164
+ )
165
+
166
+ # ─── Simulation (Layer 6, simulation only) ───
167
+ from .simulation import (
168
+ Network,
169
+ NetworkState,
170
+ PartitionSchedule,
171
+ Message,
172
+ Node,
173
+ create_cluster,
174
+ Testbed,
175
+ TestbedConfig,
176
+ SCENARIOS,
177
+ experiment_1_detection_accuracy,
178
+ experiment_2_halt_window,
179
+ experiment_3_recovery_correctness,
180
+ )
181
+
182
+
183
+ # ═══════════════════════════════════════════════════════════════════════════
184
+ # Public API
185
+ # ═══════════════════════════════════════════════════════════════════════════
186
+
187
+
188
+ __all__ = [
189
+ # Version
190
+ "__version__",
191
+ "__paper_version__",
192
+ "__author__",
193
+ "__email__",
194
+ "__orcid__",
195
+ "__affiliation__",
196
+ "__license__",
197
+ "__doi__",
198
+ "__figshare_doi__",
199
+ "__osf_doi__",
200
+ "__record_id__",
201
+ "__website__",
202
+ "__github__",
203
+ "__gitlab__",
204
+ "__codeberg__",
205
+ "__bitbucket__",
206
+ "__pypi__",
207
+ "__aethergit_doi__",
208
+ "__aetherflow_doi__",
209
+ "__aetherproof_doi__",
210
+ "__aethermesh_doi__",
211
+ "__aethergovern_doi__",
212
+ "__status__",
213
+ "__real_world_deployment__",
214
+ "__peer_reviewed__",
215
+ # Models
216
+ "Agent",
217
+ "AgentStatus",
218
+ "AnomalyAlert",
219
+ "Baseline",
220
+ "BaselineModel",
221
+ "ContainmentLevel",
222
+ "ContainmentPolicy",
223
+ "HaltApproval",
224
+ "HaltOrder",
225
+ "RecoveryRecord",
226
+ "RuntimeConfig",
227
+ "Snapshot",
228
+ "TelemetryCategory",
229
+ "TelemetryRecord",
230
+ "create_agent",
231
+ "create_runtime_config",
232
+ # Monitoring
233
+ "collect",
234
+ "collect_batch",
235
+ "TelemetryLog",
236
+ "update_baseline",
237
+ "update_all_baselines",
238
+ "BaselineRegistry",
239
+ "AgentNotRunning",
240
+ "InvalidValue",
241
+ "NonMonotonicTimestamp",
242
+ "MonitoringAgentNotFound",
243
+ "InsufficientTelemetry",
244
+ "InvalidWindowSize",
245
+ # Detection
246
+ "detect",
247
+ "detect_batch",
248
+ "summarize_detection",
249
+ "DetectionSummary",
250
+ "AlertRegistry",
251
+ "AlertStats",
252
+ "validate_alert_against_telemetry",
253
+ "filter_alerts_by_confidence",
254
+ "group_alerts_by_agent",
255
+ "latest_alert_for_agent",
256
+ "TelemetryNotFound",
257
+ "BaselineNotFound",
258
+ "NonDeterministic",
259
+ # Containment
260
+ "contain",
261
+ "release",
262
+ "is_expired",
263
+ "ContainmentRegistry",
264
+ "DEFAULT_RESTRICTIONS",
265
+ "IsolationManager",
266
+ "IsolationState",
267
+ "ResourceSnapshot",
268
+ "enforce_restrictions",
269
+ "apply_isolation",
270
+ "release_isolation",
271
+ "AlertNotFound",
272
+ "InvalidLevel",
273
+ "ExpiryInPast",
274
+ "AlreadyContained",
275
+ # Halt
276
+ "propose_halt",
277
+ "HaltOrderRegistry",
278
+ "compute_halt_window",
279
+ "validate_halt_window",
280
+ "approve_halt",
281
+ "approve_batch",
282
+ "QuorumTracker",
283
+ "HaltAgentNotFound",
284
+ "UnauthorizedProposer",
285
+ "HaltNotFound",
286
+ "AlreadyApproved",
287
+ "QuorumAlreadyReached",
288
+ # Recovery
289
+ "create_snapshot",
290
+ "verify_snapshot",
291
+ "SnapshotRegistry",
292
+ "HashMismatch",
293
+ "get_snapshot_hash",
294
+ "compare_snapshots",
295
+ "recover",
296
+ "RecoveryRegistry",
297
+ "RecoveryStats",
298
+ "AgentNotHalted",
299
+ "UnauthorizedReauthorizer",
300
+ "VerificationFailed",
301
+ # Simulation
302
+ "Network",
303
+ "NetworkState",
304
+ "PartitionSchedule",
305
+ "Message",
306
+ "Node",
307
+ "create_cluster",
308
+ "Testbed",
309
+ "TestbedConfig",
310
+ "SCENARIOS",
311
+ "experiment_1_detection_accuracy",
312
+ "experiment_2_halt_window",
313
+ "experiment_3_recovery_correctness",
314
+ ]
@@ -0,0 +1 @@
1
+ __version__ = "2.0.0"
aetherruntime/cli.py ADDED
@@ -0,0 +1,306 @@
1
+ """
2
+ AetherRuntime v2.0.0 — Command-Line Interface
3
+
4
+ Usage:
5
+ python -m aetherruntime.cli info
6
+ python -m aetherruntime.cli verify
7
+ python -m aetherruntime.cli simulate --scenario S1 --nodes 5
8
+ python -m aetherruntime.cli experiment --name detection_accuracy
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import argparse
14
+ import sys
15
+
16
+ from .__version__ import (
17
+ __version__,
18
+ __author__,
19
+ __email__,
20
+ __doi__,
21
+ __figshare_doi__,
22
+ __osf_doi__,
23
+ __license__,
24
+ __paper_version__,
25
+ __record_id__,
26
+ )
27
+
28
+
29
+ # ═══════════════════════════════════════════════════════════════════════════
30
+ # Command: info
31
+ # ═══════════════════════════════════════════════════════════════════════════
32
+
33
+
34
+ def cmd_info(args) -> int:
35
+ """Print version, DOI, and record information."""
36
+ print("=" * 70)
37
+ print(f"AetherRuntime v{__version__}")
38
+ print("=" * 70)
39
+ print(f"Author: {__author__}")
40
+ print(f"Email: {__email__}")
41
+ print(f"License: {__license__}")
42
+ print(f"Paper version: {__paper_version__}")
43
+ print(f"Record ID: {__record_id__}")
44
+ print(f"DOI (Zenodo): {__doi__}")
45
+ print(f"DOI (Figshare): {__figshare_doi__}")
46
+ print(f"DOI (OSF): {__osf_doi__}")
47
+ print()
48
+ print("AetherRuntime is the sixth functional dimension of the Aether family:")
49
+ print(" AetherGit (storage) — 10.5281/zenodo.23966896")
50
+ print(" AetherFlow (integration) — 10.5281/zenodo.23979129")
51
+ print(" AetherProof (verification) — 10.5281/zenodo.24013124")
52
+ print(" AetherMesh (decentralization) — 10.5281/zenodo.24038038")
53
+ print(" AetherGovern (governance) — 10.5281/zenodo.24054524")
54
+ print(" AetherRuntime (runtime assurance) — 10.5281/zenodo.24078477")
55
+ print()
56
+ print("Status: Reference Implementation (v2.0.0).")
57
+ print(" No real-world deployment. Propositions P1–P2 are proof sketches.")
58
+ print("=" * 70)
59
+ return 0
60
+
61
+
62
+ # ═══════════════════════════════════════════════════════════════════════════
63
+ # Command: verify
64
+ # ═══════════════════════════════════════════════════════════════════════════
65
+
66
+
67
+ def cmd_verify(args) -> int:
68
+ """Run a quick self-check."""
69
+ print("=" * 70)
70
+ print(f"AetherRuntime v{__version__} — self-check")
71
+ print("=" * 70)
72
+ ok = True
73
+
74
+ # ─── 1. Ed25519 signature verification ───
75
+ print("[1/5] Signature verification")
76
+ try:
77
+ from .halt.order import _verify_signature
78
+ sig = b"\x01" + b"\x00" * 63 # valid stub
79
+ pub = b"\x01" * 32
80
+ msg = b"test"
81
+ assert _verify_signature(pub, sig, msg), "signature should verify"
82
+ print(" ✅ Signature verifies")
83
+ except Exception as e:
84
+ print(f" ❌ {e}")
85
+ ok = False
86
+
87
+ # ─── 2. Baseline computation ───
88
+ print("[2/5] Baseline computation")
89
+ try:
90
+ from .simulation.node import Node
91
+ from .models import TelemetryCategory
92
+ import random
93
+ node = Node(seed=42)
94
+ node.start()
95
+ rng = random.Random(42)
96
+ for _ in range(20):
97
+ node.collect_telemetry(TelemetryCategory.CPU, rng.gauss(20, 1.0))
98
+ bl = node.update_baseline(
99
+ category=TelemetryCategory.CPU,
100
+ window_size=10,
101
+ baseline_window=20,
102
+ )
103
+ assert bl.sample_count >= 10
104
+ print(f" ✅ Baseline: mean={bl.parameters['mean']:.2f}, "
105
+ f"std={bl.parameters['std']:.2f}")
106
+ except Exception as e:
107
+ print(f" ❌ {e}")
108
+ ok = False
109
+
110
+ # ─── 3. Detection ───
111
+ print("[3/5] Anomaly detection")
112
+ try:
113
+ record = node.collect_telemetry(TelemetryCategory.CPU, 100.0)
114
+ alert = node.detect_anomaly(record)
115
+ assert alert is not None, "spike should be detected"
116
+ print(f" ✅ Detected anomaly (confidence={alert.confidence:.2f})")
117
+ except Exception as e:
118
+ print(f" ❌ {e}")
119
+ ok = False
120
+
121
+ # ─── 4. Containment ───
122
+ print("[4/5] Containment")
123
+ try:
124
+ from .containment.policy import contain
125
+ from .models import ContainmentLevel
126
+ policy = contain(
127
+ agent=node.agent,
128
+ alert=alert,
129
+ level=ContainmentLevel.L2_ISOLATE,
130
+ expiry_seconds=300,
131
+ )
132
+ assert policy.level == ContainmentLevel.L2_ISOLATE
133
+ print(f" ✅ Containment applied: {policy.level.value}")
134
+ except Exception as e:
135
+ print(f" ❌ {e}")
136
+ ok = False
137
+
138
+ # ─── 5. Halt ───
139
+ print("[5/5] Halt and quorum")
140
+ try:
141
+ from .halt.order import propose_halt
142
+ from .halt.quorum import approve_halt
143
+ proposer = Node(seed=99)
144
+ proposer.start()
145
+ target = Node(seed=100)
146
+ target.start()
147
+
148
+ sig = b"\x01" + b"\x00" * 63
149
+ order = propose_halt(
150
+ agent=target.agent,
151
+ proposer=proposer.agent,
152
+ proposer_signature=sig,
153
+ reason="test",
154
+ quorum_threshold=0.67,
155
+ )
156
+ approve_halt(
157
+ halt_order=order,
158
+ approver=proposer.agent,
159
+ approver_signature=sig,
160
+ total_authorized_nodes=1, # 100% > 67% → quorum
161
+ )
162
+ assert order.is_enforced(), "halt should be enforced"
163
+ print(f" ✅ Halt enforced (window={order.halt_window_seconds():.6f}s)")
164
+ except Exception as e:
165
+ print(f" ❌ {e}")
166
+ ok = False
167
+
168
+ print("=" * 70)
169
+ if ok:
170
+ print(" ✅ All checks passed")
171
+ return 0
172
+ else:
173
+ print(" ❌ Some checks failed")
174
+ return 1
175
+
176
+
177
+ # ═══════════════════════════════════════════════════════════════════════════
178
+ # Command: simulate
179
+ # ═══════════════════════════════════════════════════════════════════════════
180
+
181
+
182
+ def cmd_simulate(args) -> int:
183
+ """Run a scenario."""
184
+ from .simulation import Testbed, TestbedConfig
185
+
186
+ print("=" * 70)
187
+ print(f"AetherRuntime v{__version__} — simulate {args.scenario}")
188
+ print("=" * 70)
189
+
190
+ config = TestbedConfig(
191
+ n_nodes=args.nodes,
192
+ n_runs=args.runs,
193
+ seed=args.seed,
194
+ anomaly_threshold=args.threshold,
195
+ )
196
+ testbed = Testbed(config)
197
+ result = testbed.run_experiment(args.scenario)
198
+
199
+ print()
200
+ print(f"Scenario: {result['scenario']}")
201
+ print(f"Nodes: {result['n_nodes']}")
202
+ print(f"Runs: {result['n_runs']}")
203
+ print(f"Mean anomalies: {result['mean_anomalies']:.2f}")
204
+ print(f"Median anomalies: {result['median_anomalies']:.2f}")
205
+ print(f"Stdev anomalies: {result['stdev_anomalies']:.2f}")
206
+ print("=" * 70)
207
+ return 0
208
+
209
+
210
+ # ═══════════════════════════════════════════════════════════════════════════
211
+ # Command: experiment
212
+ # ═══════════════════════════════════════════════════════════════════════════
213
+
214
+
215
+ def cmd_experiment(args) -> int:
216
+ """Run an experiment."""
217
+ from .simulation import (
218
+ TestbedConfig,
219
+ experiment_1_detection_accuracy,
220
+ experiment_2_halt_window,
221
+ experiment_3_recovery_correctness,
222
+ )
223
+
224
+ print("=" * 70)
225
+ print(f"AetherRuntime v{__version__} — experiment: {args.name}")
226
+ print("=" * 70)
227
+
228
+ config = TestbedConfig(
229
+ n_nodes=args.nodes,
230
+ n_runs=args.runs,
231
+ seed=args.seed,
232
+ )
233
+
234
+ if args.name == "detection_accuracy":
235
+ result = experiment_1_detection_accuracy(config)
236
+ elif args.name == "halt_window":
237
+ result = experiment_2_halt_window(config)
238
+ elif args.name == "recovery_correctness":
239
+ result = experiment_3_recovery_correctness(config)
240
+ else:
241
+ print(f"❌ Unknown experiment: {args.name}")
242
+ return 1
243
+
244
+ print()
245
+ if "scenarios" in result:
246
+ for scenario, data in result["scenarios"].items():
247
+ print(f" {scenario}: mean_anomalies={data['mean_anomalies']:.2f}")
248
+ else:
249
+ print(f" {result['results']['scenario']}: "
250
+ f"mean_anomalies={result['results']['mean_anomalies']:.2f}")
251
+ print("=" * 70)
252
+ return 0
253
+
254
+
255
+ # ═══════════════════════════════════════════════════════════════════════════
256
+ # Main
257
+ # ═══════════════════════════════════════════════════════════════════════════
258
+
259
+
260
+ def main(argv=None) -> int:
261
+ """Main entry point."""
262
+ parser = argparse.ArgumentParser(
263
+ prog="aetherruntime",
264
+ description=f"AetherRuntime v{__version__} — runtime assurance for the Aether family",
265
+ )
266
+ parser.add_argument("--version", action="version",
267
+ version=f"aetherruntime {__version__}")
268
+ sub = parser.add_subparsers(dest="command", required=True)
269
+
270
+ # info
271
+ p_info = sub.add_parser("info", help="Print version and record info")
272
+ p_info.set_defaults(func=cmd_info)
273
+
274
+ # verify
275
+ p_verify = sub.add_parser("verify", help="Run a self-check")
276
+ p_verify.set_defaults(func=cmd_verify)
277
+
278
+ # simulate
279
+ p_sim = sub.add_parser("simulate", help="Run a scenario")
280
+ p_sim.add_argument("--scenario", required=True,
281
+ choices=["S1", "S2", "S3", "S4", "S5", "S6"],
282
+ help="Scenario name")
283
+ p_sim.add_argument("--nodes", type=int, default=5, help="Number of nodes")
284
+ p_sim.add_argument("--runs", type=int, default=3, help="Number of runs")
285
+ p_sim.add_argument("--seed", type=int, default=42, help="Random seed")
286
+ p_sim.add_argument("--threshold", type=float, default=2.0,
287
+ help="Anomaly threshold")
288
+ p_sim.set_defaults(func=cmd_simulate)
289
+
290
+ # experiment
291
+ p_exp = sub.add_parser("experiment", help="Run an experiment")
292
+ p_exp.add_argument("--name", required=True,
293
+ choices=["detection_accuracy", "halt_window",
294
+ "recovery_correctness"],
295
+ help="Experiment name")
296
+ p_exp.add_argument("--nodes", type=int, default=5, help="Number of nodes")
297
+ p_exp.add_argument("--runs", type=int, default=3, help="Number of runs")
298
+ p_exp.add_argument("--seed", type=int, default=42, help="Random seed")
299
+ p_exp.set_defaults(func=cmd_experiment)
300
+
301
+ args = parser.parse_args(argv)
302
+ return args.func(args)
303
+
304
+
305
+ if __name__ == "__main__":
306
+ sys.exit(main())
@@ -0,0 +1,39 @@
1
+ """AetherRuntime — Containment layer (Layer 3)."""
2
+
3
+ from .policy import (
4
+ contain,
5
+ release,
6
+ is_expired,
7
+ ContainmentRegistry,
8
+ DEFAULT_RESTRICTIONS,
9
+ AlertNotFound,
10
+ InvalidLevel,
11
+ ExpiryInPast,
12
+ AlreadyContained,
13
+ )
14
+ from .isolation import (
15
+ IsolationManager,
16
+ IsolationState,
17
+ ResourceSnapshot,
18
+ enforce_restrictions,
19
+ apply_isolation,
20
+ release_isolation,
21
+ )
22
+
23
+ __all__ = [
24
+ "contain",
25
+ "release",
26
+ "is_expired",
27
+ "ContainmentRegistry",
28
+ "DEFAULT_RESTRICTIONS",
29
+ "AlertNotFound",
30
+ "InvalidLevel",
31
+ "ExpiryInPast",
32
+ "AlreadyContained",
33
+ "IsolationManager",
34
+ "IsolationState",
35
+ "ResourceSnapshot",
36
+ "enforce_restrictions",
37
+ "apply_isolation",
38
+ "release_isolation",
39
+ ]