sova-oss 0.1.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.
- sova/__init__.py +14 -0
- sova/__main__.py +7 -0
- sova/acceptance/__init__.py +35 -0
- sova/acceptance/io.py +98 -0
- sova/acceptance/lab.py +234 -0
- sova/acceptance/model.py +321 -0
- sova/adapters/__init__.py +45 -0
- sova/adapters/codex_exec.py +345 -0
- sova/adapters/security_catalog.py +685 -0
- sova/adapters/security_contracts.py +711 -0
- sova/adapters/security_parsers.py +635 -0
- sova/adapters/security_runner.py +683 -0
- sova/assessment.py +542 -0
- sova/audit/__init__.py +66 -0
- sova/audit/agentdojo.py +340 -0
- sova/audit/engine.py +695 -0
- sova/audit/report.py +168 -0
- sova/audit/specs/__init__.py +2 -0
- sova/audit/specs/agentdojo-v1.2.2.json +603 -0
- sova/benchmarks/__init__.py +14 -0
- sova/benchmarks/comparative.py +167 -0
- sova/capsule/__init__.py +47 -0
- sova/capsule/lifecycle.py +64 -0
- sova/capsule/migrate.py +405 -0
- sova/capsule/model.py +490 -0
- sova/capsule/primitives.py +132 -0
- sova/cli.py +6941 -0
- sova/command_audit.py +111 -0
- sova/community/__init__.py +94 -0
- sova/community/agent_arena.py +1094 -0
- sova/community/arena.py +256 -0
- sova/community/browser_swarm.py +1218 -0
- sova/community/browser_swarm_config.py +270 -0
- sova/community/chamber.py +1361 -0
- sova/community/chamber_config.py +324 -0
- sova/community/config.py +569 -0
- sova/community/ctf.py +103 -0
- sova/community/executor_capsule_reproduction.py +280 -0
- sova/community/executor_chamber.py +2782 -0
- sova/community/executor_chamber_config.py +731 -0
- sova/community/executor_engine.py +886 -0
- sova/community/executor_engine_full.py +577 -0
- sova/community/executor_engine_runtime_config.py +446 -0
- sova/community/executor_surfaces.py +1001 -0
- sova/community/leaderboard.py +221 -0
- sova/community/live_executor_engine.py +649 -0
- sova/community/media.py +170 -0
- sova/community/probe.py +244 -0
- sova/community/software_executor_engine.py +549 -0
- sova/community/swarm/__init__.py +41 -0
- sova/community/swarm/blackboard.py +123 -0
- sova/community/swarm/budget.py +191 -0
- sova/community/swarm/coordinator.py +535 -0
- sova/community/swarm/coverage.py +173 -0
- sova/community/swarm/message.py +116 -0
- sova/community/swarm/runtime.py +178 -0
- sova/community/swarm/software.py +215 -0
- sova/community/swarm/stress.py +242 -0
- sova/community/swarm/worker.py +267 -0
- sova/composition/__init__.py +55 -0
- sova/composition/fixtures.py +90 -0
- sova/composition/graph.py +149 -0
- sova/composition/model.py +232 -0
- sova/composition/portable.py +41 -0
- sova/composition/search.py +349 -0
- sova/conformance.py +209 -0
- sova/contracts/__init__.py +94 -0
- sova/contracts/coverage.py +182 -0
- sova/contracts/data/__init__.py +2 -0
- sova/contracts/data/attack-taxonomy-0.1.0.toml +366 -0
- sova/contracts/errors.py +28 -0
- sova/contracts/identifiers.py +160 -0
- sova/contracts/lifecycle.py +182 -0
- sova/contracts/taxonomy.py +233 -0
- sova/contracts/versions.py +209 -0
- sova/contracts/vocabulary.py +47 -0
- sova/desktop/__init__.py +25 -0
- sova/desktop/appium.py +393 -0
- sova/desktop/atspi.py +256 -0
- sova/desktop/conformance.py +123 -0
- sova/detonation/__init__.py +75 -0
- sova/detonation/backends.py +87 -0
- sova/detonation/coverage.py +240 -0
- sova/detonation/demo.py +517 -0
- sova/detonation/sensors.py +221 -0
- sova/detonation/targets.py +148 -0
- sova/detonation/world.py +445 -0
- sova/evidence/__init__.py +45 -0
- sova/evidence/adjudication.py +120 -0
- sova/evidence/bundle.py +253 -0
- sova/evidence/disclosure.py +173 -0
- sova/evidence/model.py +212 -0
- sova/evidence/report.py +70 -0
- sova/executors/__init__.py +75 -0
- sova/executors/contract.py +233 -0
- sova/executors/docker_desktop.py +652 -0
- sova/executors/gvisor.py +462 -0
- sova/executors/local.py +928 -0
- sova/executors/runner.py +555 -0
- sova/executors/scripted.py +143 -0
- sova/executors/workspace.py +653 -0
- sova/experiments/__init__.py +20 -0
- sova/experiments/matrix.py +283 -0
- sova/extensions/__init__.py +39 -0
- sova/extensions/model.py +171 -0
- sova/extensions/runner.py +218 -0
- sova/extensions/workflow.py +539 -0
- sova/forensics/__init__.py +67 -0
- sova/forensics/attribution.py +170 -0
- sova/forensics/benchmark.py +158 -0
- sova/forensics/blinded.py +825 -0
- sova/forensics/browser_counterfactual.py +425 -0
- sova/forensics/fixtures.py +101 -0
- sova/forensics/model.py +193 -0
- sova/forensics/reconstruct.py +214 -0
- sova/formats/__init__.py +20 -0
- sova/formats/canonical.py +267 -0
- sova/formats/errors.py +35 -0
- sova/formats/package.py +416 -0
- sova/formats/schema.py +160 -0
- sova/front_door.py +77 -0
- sova/intake/__init__.py +49 -0
- sova/intake/contracts.py +657 -0
- sova/intake/frontends.py +3182 -0
- sova/intake/materials.py +373 -0
- sova/intake/model.py +484 -0
- sova/intake/pipeline.py +455 -0
- sova/interoperability/__init__.py +14 -0
- sova/interoperability/agentdojo.py +665 -0
- sova/interoperability/inspect_ai.py +129 -0
- sova/interoperability/inspect_log.py +510 -0
- sova/interoperability/record.py +145 -0
- sova/interoperability/trace_attestation.py +255 -0
- sova/live/__init__.py +158 -0
- sova/live/action_lab.py +934 -0
- sova/live/adaptive_campaign.py +493 -0
- sova/live/adversarial_missions.py +307 -0
- sova/live/agent_campaign.py +610 -0
- sova/live/browser.py +865 -0
- sova/live/campaign.py +1047 -0
- sova/live/control.py +331 -0
- sova/live/fixture_web.py +132 -0
- sova/live/held_out_web.py +365 -0
- sova/live/persistent_session.py +563 -0
- sova/live/recording.py +280 -0
- sova/live/semantic_browser_driver.py +1408 -0
- sova/live/semantic_workflow.py +1420 -0
- sova/live/software.py +881 -0
- sova/live/startup.py +37 -0
- sova/local_mcp/__init__.py +39 -0
- sova/local_mcp/approval.py +220 -0
- sova/local_mcp/model.py +125 -0
- sova/local_mcp/server.py +135 -0
- sova/local_mcp/tools.py +514 -0
- sova/mapping/__init__.py +60 -0
- sova/mapping/analysis.py +257 -0
- sova/mapping/discovery.py +864 -0
- sova/mapping/drift.py +113 -0
- sova/mapping/model.py +342 -0
- sova/mapping/report.py +122 -0
- sova/mcp/__init__.py +73 -0
- sova/mcp/adapter.py +1606 -0
- sova/mcp/broker.py +136 -0
- sova/mcp/cua_driver.py +163 -0
- sova/mcp/profile_state.py +213 -0
- sova/mcp/protocol.py +410 -0
- sova/mcp/receipts.py +146 -0
- sova/mcp/specs.py +476 -0
- sova/methodology/__init__.py +58 -0
- sova/methodology/compiler.py +870 -0
- sova/methodology/contracts.py +830 -0
- sova/methodology/contribution.py +190 -0
- sova/methodology/data/__init__.py +2 -0
- sova/methodology/data/playbook-seeds-0.1.0.json +95 -0
- sova/methodology/library.py +814 -0
- sova/models/__init__.py +10 -0
- sova/models/scripted.py +128 -0
- sova/monitoring/__init__.py +39 -0
- sova/monitoring/alerts.py +175 -0
- sova/monitoring/diff.py +113 -0
- sova/monitoring/integrity.py +121 -0
- sova/monitoring/model.py +93 -0
- sova/monitoring/recorder.py +162 -0
- sova/monitoring/sentinel.py +175 -0
- sova/monitoring/service.py +565 -0
- sova/onboarding.py +348 -0
- sova/oracle_lab/__init__.py +78 -0
- sova/oracle_lab/calibration.py +285 -0
- sova/oracle_lab/comparison.py +103 -0
- sova/oracle_lab/contracts.py +641 -0
- sova/oracle_lab/coverage.py +118 -0
- sova/oracle_lab/evidence.py +44 -0
- sova/oracle_lab/io.py +136 -0
- sova/oracle_lab/proposal.py +76 -0
- sova/oracle_lab/reproduction.py +118 -0
- sova/oracle_lab/study.py +160 -0
- sova/oracles.py +528 -0
- sova/providers/__init__.py +56 -0
- sova/providers/core.py +633 -0
- sova/providers/runtime.py +372 -0
- sova/py.typed +1 -0
- sova/registry/__init__.py +66 -0
- sova/registry/adapters.py +128 -0
- sova/registry/auto_contribute.py +112 -0
- sova/registry/backup.py +321 -0
- sova/registry/client.py +184 -0
- sova/registry/contribution.py +172 -0
- sova/registry/index.py +298 -0
- sova/registry/model.py +189 -0
- sova/registry/pr_contribution.py +120 -0
- sova/registry/service.py +1390 -0
- sova/registry/sync.py +101 -0
- sova/rehearsal/__init__.py +61 -0
- sova/rehearsal/agent.py +83 -0
- sova/rehearsal/backend.py +73 -0
- sova/rehearsal/environment.py +176 -0
- sova/rehearsal/model.py +299 -0
- sova/rehearsal/provider.py +863 -0
- sova/rehearsal/runner.py +439 -0
- sova/release.py +456 -0
- sova/replay/__init__.py +55 -0
- sova/replay/capsule.py +363 -0
- sova/replay/controlled.py +120 -0
- sova/replay/model.py +240 -0
- sova/replay/render.py +695 -0
- sova/replay/semantic.py +210 -0
- sova/replay/service.py +369 -0
- sova/replay/verification.py +288 -0
- sova/reproduction.py +304 -0
- sova/rerun/__init__.py +50 -0
- sova/rerun/agentdojo.py +673 -0
- sova/rerun/calibrate.py +475 -0
- sova/rerun/command.py +538 -0
- sova/rerun/decision.py +648 -0
- sova/rerun/engine.py +1241 -0
- sova/rerun/findings.py +346 -0
- sova/rerun/judges.py +86 -0
- sova/rerun/matrix.py +340 -0
- sova/rerun/providers.py +524 -0
- sova/rerun/records.py +293 -0
- sova/rerun/tracing.py +258 -0
- sova/runtime/__init__.py +105 -0
- sova/runtime/action_codecs.py +1179 -0
- sova/runtime/bound_environment.py +1128 -0
- sova/runtime/browser_surface.py +759 -0
- sova/runtime/computer_surface.py +458 -0
- sova/runtime/environment_builder.py +271 -0
- sova/runtime/evidence.py +426 -0
- sova/runtime/experience.py +111 -0
- sova/runtime/managed_surfaces.py +588 -0
- sova/runtime/melra_computer.py +386 -0
- sova/runtime/native_windows_computer.py +599 -0
- sova/runtime/oci_agent.py +631 -0
- sova/runtime/orchestration.py +613 -0
- sova/runtime/profiles.py +65 -0
- sova/runtime/reliability.py +260 -0
- sova/runtime/sessions.py +555 -0
- sova/runtime/software_target.py +421 -0
- sova/runtime/target_environment.py +413 -0
- sova/runtime/unified_execution.py +1005 -0
- sova/runtime/window_recording.py +770 -0
- sova/safety/__init__.py +91 -0
- sova/safety/authorization.py +1094 -0
- sova/safety/containment.py +326 -0
- sova/safety/disclosure.py +81 -0
- sova/safety/privacy.py +142 -0
- sova/safety/profiles.py +162 -0
- sova/schemas/README.md +71 -0
- sova/schemas/__init__.py +2 -0
- sova/schemas/adapter-descriptor-0.1.0.schema.json +95 -0
- sova/schemas/adapter-run-report-0.1.0.schema.json +51 -0
- sova/schemas/assessment-coverage-0.1.0.schema.json +15 -0
- sova/schemas/blinded-causal-answer-key-0.1.0.schema.json +51 -0
- sova/schemas/blinded-causal-predictions-0.1.0.schema.json +35 -0
- sova/schemas/blinded-causal-score-0.1.0.schema.json +140 -0
- sova/schemas/blinded-causal-study-0.1.0.schema.json +62 -0
- sova/schemas/blinded-evaluation-protocol-0.1.0.schema.json +74 -0
- sova/schemas/blinded-evaluation-report-0.1.0.schema.json +189 -0
- sova/schemas/blinded-oracle-answer-key-0.1.0.schema.json +13 -0
- sova/schemas/blinded-oracle-predictions-0.1.0.schema.json +13 -0
- sova/schemas/blinded-oracle-study-0.1.0.schema.json +18 -0
- sova/schemas/capsule-manifest-0.1.0.schema.json +225 -0
- sova/schemas/composition-report-0.1.0.schema.json +24 -0
- sova/schemas/decisive-evidence-set-0.1.0.schema.json +15 -0
- sova/schemas/evaluation-observation-ledger-0.1.0.schema.json +43 -0
- sova/schemas/evaluation-work-order-set-0.1.0.schema.json +25 -0
- sova/schemas/event-0.1.0.schema.json +128 -0
- sova/schemas/evidence-0.1.0.schema.json +39 -0
- sova/schemas/external-benchmark-case-0.1.0.schema.json +23 -0
- sova/schemas/firecracker-execution-receipt-0.1.0.schema.json +98 -0
- sova/schemas/firecracker-launch-plan-0.1.0.schema.json +19 -0
- sova/schemas/firecracker-network-plan-0.1.0.schema.json +42 -0
- sova/schemas/forensic-reconstruction-0.1.0.schema.json +52 -0
- sova/schemas/fresh-reproduction-0.1.0.schema.json +20 -0
- sova/schemas/intake-report-0.1.0.schema.json +174 -0
- sova/schemas/launch-dossier-0.1.0.schema.json +154 -0
- sova/schemas/launch-evidence-bundle-0.1.0.schema.json +25 -0
- sova/schemas/launch-gate-receipt-0.1.0.schema.json +24 -0
- sova/schemas/launch-trust-policy-0.1.0.schema.json +31 -0
- sova/schemas/map-report-0.1.0.schema.json +226 -0
- sova/schemas/methodology-observations-0.1.0.schema.json +9 -0
- sova/schemas/methodology-plan-0.1.0.schema.json +17 -0
- sova/schemas/methodology-policy-0.1.0.schema.json +12 -0
- sova/schemas/normalized-observation-0.1.0.schema.json +42 -0
- sova/schemas/oracle-calibration-0.1.0.schema.json +39 -0
- sova/schemas/oracle-comparison-0.1.0.schema.json +23 -0
- sova/schemas/oracle-proposal-0.1.0.schema.json +41 -0
- sova/schemas/playbook-0.1.0.schema.json +107 -0
- sova/schemas/playbook-library-0.1.0.schema.json +14 -0
- sova/schemas/playbook-submission-0.1.0.schema.json +5 -0
- sova/schemas/public-claims-snapshot-0.1.0.schema.json +43 -0
- sova/schemas/registry-beta-readiness-0.1.0.schema.json +39 -0
- sova/schemas/registry-operational-receipt-0.1.0.schema.json +21 -0
- sova/schemas/release-candidate-0.1.0.schema.json +22 -0
- sova/schemas/release-gate-ledger-0.1.0.schema.json +50 -0
- sova/schemas/release-review-receipt-0.1.0.schema.json +22 -0
- sova/schemas/scenario-0.1.0.schema.json +105 -0
- sova/schemas/target-profile-0.1.0.schema.json +94 -0
- sova/schemas/trace-manifest-0.1.0.schema.json +219 -0
- sova/schemas/worker-attestation-0.1.0.schema.json +27 -0
- sova/schemas/worker-cleanup-receipt-0.1.0.schema.json +13 -0
- sova/schemas/worker-evidence-report-0.1.0.schema.json +17 -0
- sova/schemas/worker-exact-host-acceptance-receipt-0.1.0.schema.json +31 -0
- sova/schemas/worker-host-preflight-receipt-0.1.0.schema.json +26 -0
- sova/schemas/worker-job-manifest-0.1.0.schema.json +110 -0
- sova/schemas/worker-network-mediator-policy-0.1.0.schema.json +75 -0
- sova/schemas/worker-network-plane-receipt-0.1.0.schema.json +28 -0
- sova/schemas/worker-network-receipt-0.1.0.schema.json +16 -0
- sova/schemas/worker-protocol-message-0.1.0.schema.json +25 -0
- sova/schemas/worker-secret-receipt-0.1.0.schema.json +14 -0
- sova/search/__init__.py +56 -0
- sova/search/demo.py +107 -0
- sova/search/engine.py +484 -0
- sova/search/experience.py +51 -0
- sova/search/model.py +239 -0
- sova/search/phantom.py +179 -0
- sova/search/portable.py +35 -0
- sova/targets/__init__.py +16 -0
- sova/targets/contract.py +163 -0
- sova/trace/__init__.py +33 -0
- sova/trace/integrity.py +329 -0
- sova/trace/kinds.py +105 -0
- sova/trace/otel.py +487 -0
- sova/trace/reader.py +268 -0
- sova/trace/redaction.py +442 -0
- sova/trace/writer.py +696 -0
- sova/validation/__init__.py +99 -0
- sova/validation/adapters.py +243 -0
- sova/validation/contracts.py +295 -0
- sova/validation/gates.py +445 -0
- sova/validation/launch.py +1295 -0
- sova/validation/ledger.py +348 -0
- sova/validation/work_orders.py +88 -0
- sova/worker/__init__.py +154 -0
- sova/worker/alternative_backends.py +102 -0
- sova/worker/attestation.py +152 -0
- sova/worker/brokers.py +348 -0
- sova/worker/cas.py +97 -0
- sova/worker/contracts.py +476 -0
- sova/worker/deployment.py +247 -0
- sova/worker/evidence.py +277 -0
- sova/worker/firecracker.py +409 -0
- sova/worker/host_acceptance.py +213 -0
- sova/worker/host_preflight.py +407 -0
- sova/worker/identity.py +188 -0
- sova/worker/io.py +151 -0
- sova/worker/lifecycle.py +822 -0
- sova/worker/malicious.py +107 -0
- sova/worker/network_plane.py +1076 -0
- sova/worker/protocol.py +314 -0
- sova/worker/service.py +249 -0
- sova/workflows/__init__.py +17 -0
- sova/workflows/case.py +560 -0
- sova/workflows/check.py +287 -0
- sova/workflows/demo.py +248 -0
- sova_oss-0.1.0.dist-info/METADATA +1266 -0
- sova_oss-0.1.0.dist-info/RECORD +381 -0
- sova_oss-0.1.0.dist-info/WHEEL +4 -0
- sova_oss-0.1.0.dist-info/entry_points.txt +2 -0
- sova_oss-0.1.0.dist-info/licenses/LICENSE +201 -0
- sova_oss-0.1.0.dist-info/licenses/NOTICE +20 -0
sova/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""SOVA OSS public Python package."""
|
|
3
|
+
|
|
4
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
5
|
+
|
|
6
|
+
_DISTRIBUTION_NAME = "sova-oss"
|
|
7
|
+
_SOURCE_FALLBACK_VERSION = "0.1.0"
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
__version__ = version(_DISTRIBUTION_NAME)
|
|
11
|
+
except PackageNotFoundError:
|
|
12
|
+
__version__ = _SOURCE_FALLBACK_VERSION
|
|
13
|
+
|
|
14
|
+
__all__ = ["__version__"]
|
sova/__main__.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Executable acceptance and stable-release evidence gates."""
|
|
3
|
+
|
|
4
|
+
from sova.acceptance.io import load_receipts, receipt_from_mapping
|
|
5
|
+
from sova.acceptance.lab import (
|
|
6
|
+
AcceptanceLabArtifacts,
|
|
7
|
+
acceptance_receipt_template,
|
|
8
|
+
run_offline_acceptance_lab,
|
|
9
|
+
)
|
|
10
|
+
from sova.acceptance.model import (
|
|
11
|
+
AcceptanceGate,
|
|
12
|
+
AcceptanceReceipt,
|
|
13
|
+
GateClass,
|
|
14
|
+
GateResult,
|
|
15
|
+
ReleaseReadinessReport,
|
|
16
|
+
default_release_gates,
|
|
17
|
+
evaluate_gate,
|
|
18
|
+
evaluate_release_readiness,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"AcceptanceGate",
|
|
23
|
+
"AcceptanceLabArtifacts",
|
|
24
|
+
"AcceptanceReceipt",
|
|
25
|
+
"GateClass",
|
|
26
|
+
"GateResult",
|
|
27
|
+
"ReleaseReadinessReport",
|
|
28
|
+
"acceptance_receipt_template",
|
|
29
|
+
"default_release_gates",
|
|
30
|
+
"evaluate_gate",
|
|
31
|
+
"evaluate_release_readiness",
|
|
32
|
+
"load_receipts",
|
|
33
|
+
"receipt_from_mapping",
|
|
34
|
+
"run_offline_acceptance_lab",
|
|
35
|
+
]
|
sova/acceptance/io.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Strict acceptance-receipt I/O."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
from sova.acceptance.model import AcceptanceReceipt
|
|
9
|
+
from sova.formats import strict_json_loads
|
|
10
|
+
from sova.formats.errors import FormatError
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Mapping
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
_FIELDS = {
|
|
17
|
+
"artifactType",
|
|
18
|
+
"schemaVersion",
|
|
19
|
+
"gateId",
|
|
20
|
+
"evidenceType",
|
|
21
|
+
"runId",
|
|
22
|
+
"result",
|
|
23
|
+
"producer",
|
|
24
|
+
"organization",
|
|
25
|
+
"environmentId",
|
|
26
|
+
"labels",
|
|
27
|
+
"artifactDigests",
|
|
28
|
+
"independentOfSovaTeam",
|
|
29
|
+
"observedAt",
|
|
30
|
+
"limitations",
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def receipt_from_mapping(value: Mapping[str, Any]) -> AcceptanceReceipt:
|
|
35
|
+
if set(value) != _FIELDS:
|
|
36
|
+
raise FormatError("SOVA-ACCEPTANCE-RECEIPT", "receipt fields must be exact")
|
|
37
|
+
if (
|
|
38
|
+
value.get("artifactType") != "sova.acceptance-receipt"
|
|
39
|
+
or value.get("schemaVersion") != "0.1.0"
|
|
40
|
+
):
|
|
41
|
+
raise FormatError("SOVA-ACCEPTANCE-RECEIPT", "receipt type is unsupported")
|
|
42
|
+
labels = value.get("labels")
|
|
43
|
+
digests = value.get("artifactDigests")
|
|
44
|
+
limitations = value.get("limitations")
|
|
45
|
+
if not isinstance(labels, dict) or not all(
|
|
46
|
+
isinstance(key, str) and isinstance(item, str) for key, item in labels.items()
|
|
47
|
+
):
|
|
48
|
+
raise FormatError("SOVA-ACCEPTANCE-RECEIPT", "receipt labels are malformed")
|
|
49
|
+
if not isinstance(digests, list) or not all(isinstance(item, str) for item in digests):
|
|
50
|
+
raise FormatError("SOVA-ACCEPTANCE-RECEIPT", "receipt digests are malformed")
|
|
51
|
+
if not isinstance(limitations, list) or not all(isinstance(item, str) for item in limitations):
|
|
52
|
+
raise FormatError("SOVA-ACCEPTANCE-RECEIPT", "receipt limitations are malformed")
|
|
53
|
+
strings = (
|
|
54
|
+
"gateId",
|
|
55
|
+
"evidenceType",
|
|
56
|
+
"runId",
|
|
57
|
+
"result",
|
|
58
|
+
"producer",
|
|
59
|
+
"organization",
|
|
60
|
+
"environmentId",
|
|
61
|
+
"observedAt",
|
|
62
|
+
)
|
|
63
|
+
if not all(isinstance(value.get(name), str) for name in strings) or not isinstance(
|
|
64
|
+
value.get("independentOfSovaTeam"), bool
|
|
65
|
+
):
|
|
66
|
+
raise FormatError("SOVA-ACCEPTANCE-RECEIPT", "receipt scalar fields are malformed")
|
|
67
|
+
return AcceptanceReceipt(
|
|
68
|
+
str(value["gateId"]),
|
|
69
|
+
str(value["evidenceType"]),
|
|
70
|
+
str(value["runId"]),
|
|
71
|
+
str(value["result"]),
|
|
72
|
+
str(value["producer"]),
|
|
73
|
+
str(value["organization"]),
|
|
74
|
+
str(value["environmentId"]),
|
|
75
|
+
tuple(sorted((str(key), str(item)) for key, item in labels.items())),
|
|
76
|
+
tuple(str(item) for item in digests),
|
|
77
|
+
bool(value["independentOfSovaTeam"]),
|
|
78
|
+
str(value["observedAt"]),
|
|
79
|
+
tuple(str(item) for item in limitations),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def load_receipts(directory: Path) -> tuple[AcceptanceReceipt, ...]:
|
|
84
|
+
root = directory.resolve()
|
|
85
|
+
if not root.is_dir():
|
|
86
|
+
raise FormatError("SOVA-ACCEPTANCE-DIRECTORY", "receipt directory does not exist")
|
|
87
|
+
receipts: list[AcceptanceReceipt] = []
|
|
88
|
+
for path in sorted(root.glob("*.json")):
|
|
89
|
+
if path.is_symlink() or not path.is_file() or path.stat().st_size > 1024 * 1024:
|
|
90
|
+
raise FormatError("SOVA-ACCEPTANCE-FILE", "receipt must be a bounded regular file")
|
|
91
|
+
value = strict_json_loads(path.read_bytes())
|
|
92
|
+
if not isinstance(value, dict):
|
|
93
|
+
raise FormatError("SOVA-ACCEPTANCE-RECEIPT", "receipt root must be an object")
|
|
94
|
+
receipts.append(receipt_from_mapping(value))
|
|
95
|
+
return tuple(receipts)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
__all__ = ["load_receipts", "receipt_from_mapping"]
|
sova/acceptance/lab.py
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Safe offline acceptance lab and stable-readiness evaluation."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import platform
|
|
7
|
+
import secrets
|
|
8
|
+
import shutil
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from datetime import UTC, datetime
|
|
11
|
+
from typing import TYPE_CHECKING, Any
|
|
12
|
+
|
|
13
|
+
from sova.acceptance.model import (
|
|
14
|
+
AcceptanceReceipt,
|
|
15
|
+
default_release_gates,
|
|
16
|
+
evaluate_release_readiness,
|
|
17
|
+
)
|
|
18
|
+
from sova.detonation import (
|
|
19
|
+
CaptureMode,
|
|
20
|
+
CoverageRequirement,
|
|
21
|
+
OrderingGuarantee,
|
|
22
|
+
SensorCoverageLedger,
|
|
23
|
+
SensorCoveragePolicy,
|
|
24
|
+
SensorDeclaration,
|
|
25
|
+
SensorKind,
|
|
26
|
+
SensorSurface,
|
|
27
|
+
run_sleeper_demo,
|
|
28
|
+
)
|
|
29
|
+
from sova.formats import canonical_json_bytes, sha256_digest
|
|
30
|
+
from sova.formats.errors import FormatError
|
|
31
|
+
from sova.replay import verify_artifact
|
|
32
|
+
|
|
33
|
+
if TYPE_CHECKING:
|
|
34
|
+
from pathlib import Path
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True, slots=True)
|
|
38
|
+
class AcceptanceLabArtifacts:
|
|
39
|
+
root: Path
|
|
40
|
+
report: Path
|
|
41
|
+
sensor_coverage: Path
|
|
42
|
+
readiness: Path
|
|
43
|
+
core_capsule: Path
|
|
44
|
+
core_trace: Path
|
|
45
|
+
status: str
|
|
46
|
+
|
|
47
|
+
def to_mapping(self) -> dict[str, Any]:
|
|
48
|
+
return {
|
|
49
|
+
"status": self.status,
|
|
50
|
+
"root": str(self.root),
|
|
51
|
+
"report": str(self.report),
|
|
52
|
+
"sensorCoverage": str(self.sensor_coverage),
|
|
53
|
+
"readiness": str(self.readiness),
|
|
54
|
+
"coreCapsule": str(self.core_capsule),
|
|
55
|
+
"coreTrace": str(self.core_trace),
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _synthetic_coverage() -> dict[str, Any]:
|
|
60
|
+
declarations = (
|
|
61
|
+
SensorDeclaration(
|
|
62
|
+
"sova-authorization",
|
|
63
|
+
SensorKind.AUTHORIZATION,
|
|
64
|
+
SensorSurface.SOVA,
|
|
65
|
+
"healthy",
|
|
66
|
+
"sova.authorization-kernel/0.1",
|
|
67
|
+
CaptureMode.DIRECT,
|
|
68
|
+
"sova-trace-sequence",
|
|
69
|
+
OrderingGuarantee.LOCAL_TOTAL,
|
|
70
|
+
emitted_events=1,
|
|
71
|
+
),
|
|
72
|
+
SensorDeclaration(
|
|
73
|
+
"sova-containment",
|
|
74
|
+
SensorKind.SAFETY,
|
|
75
|
+
SensorSurface.SOVA,
|
|
76
|
+
"healthy",
|
|
77
|
+
"sova.synthetic-world/0.1",
|
|
78
|
+
CaptureMode.DIRECT,
|
|
79
|
+
"sova-trace-sequence",
|
|
80
|
+
OrderingGuarantee.LOCAL_TOTAL,
|
|
81
|
+
emitted_events=1,
|
|
82
|
+
),
|
|
83
|
+
SensorDeclaration(
|
|
84
|
+
"synthetic-filesystem",
|
|
85
|
+
SensorKind.FILESYSTEM,
|
|
86
|
+
SensorSurface.HOST,
|
|
87
|
+
"healthy",
|
|
88
|
+
"sova.synthetic-filesystem/0.1",
|
|
89
|
+
CaptureMode.DIRECT,
|
|
90
|
+
"sova-world-sequence",
|
|
91
|
+
OrderingGuarantee.PARTIAL,
|
|
92
|
+
emitted_events=1,
|
|
93
|
+
blind_spots=("simulated filesystem only; no native host activity",),
|
|
94
|
+
),
|
|
95
|
+
SensorDeclaration(
|
|
96
|
+
"synthetic-network",
|
|
97
|
+
SensorKind.NETWORK,
|
|
98
|
+
SensorSurface.EXTERNAL,
|
|
99
|
+
"healthy",
|
|
100
|
+
"sova.sink-only-network/0.1",
|
|
101
|
+
CaptureMode.DIRECT,
|
|
102
|
+
"sova-world-sequence",
|
|
103
|
+
OrderingGuarantee.PARTIAL,
|
|
104
|
+
emitted_events=1,
|
|
105
|
+
blind_spots=("sink-only simulation; no packet or third-party service observation",),
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
policy = SensorCoveragePolicy(
|
|
109
|
+
"sova:coverage:synthetic-sleeper/0.1",
|
|
110
|
+
"declared synthetic authorization, safety, filesystem, and sink-only network effects",
|
|
111
|
+
tuple(
|
|
112
|
+
CoverageRequirement(declaration.surface, declaration.kind)
|
|
113
|
+
for declaration in declarations
|
|
114
|
+
),
|
|
115
|
+
)
|
|
116
|
+
return SensorCoverageLedger(declarations).evaluate(policy).to_mapping()
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def run_offline_acceptance_lab(
|
|
120
|
+
destination: Path,
|
|
121
|
+
*,
|
|
122
|
+
receipts: tuple[AcceptanceReceipt, ...] = (),
|
|
123
|
+
) -> AcceptanceLabArtifacts:
|
|
124
|
+
"""Run credential-free core evidence tests and evaluate external stable gates."""
|
|
125
|
+
root = destination.resolve()
|
|
126
|
+
if root.exists():
|
|
127
|
+
raise FormatError("SOVA-ACCEPTANCE-EXISTS", "acceptance destination must not exist")
|
|
128
|
+
temporary = root.with_name(f".{root.name}.partial-{secrets.token_hex(8)}")
|
|
129
|
+
temporary.mkdir(parents=True)
|
|
130
|
+
try:
|
|
131
|
+
core = temporary / "core-workflow"
|
|
132
|
+
demo = run_sleeper_demo(core)
|
|
133
|
+
capsule_verification = verify_artifact(demo.capsule).to_mapping()
|
|
134
|
+
trace_verification = verify_artifact(demo.trace).to_mapping()
|
|
135
|
+
core_pass = bool(
|
|
136
|
+
capsule_verification["state"] in {"verified", "partial"}
|
|
137
|
+
and trace_verification["state"] == "verified"
|
|
138
|
+
and demo.oracle_status == "pass"
|
|
139
|
+
and demo.evidence_closure == "sufficient"
|
|
140
|
+
and demo.cleanup_verified
|
|
141
|
+
)
|
|
142
|
+
coverage = _synthetic_coverage()
|
|
143
|
+
coverage_path = temporary / "sensor-coverage.json"
|
|
144
|
+
coverage_path.write_bytes(canonical_json_bytes(coverage) + b"\n")
|
|
145
|
+
readiness = evaluate_release_readiness(receipts).to_mapping()
|
|
146
|
+
readiness_path = temporary / "stable-readiness.json"
|
|
147
|
+
readiness_path.write_bytes(canonical_json_bytes(readiness) + b"\n")
|
|
148
|
+
status = "pass" if core_pass and coverage["accepted"] else "fail"
|
|
149
|
+
report = {
|
|
150
|
+
"artifactType": "sova.acceptance-lab-report",
|
|
151
|
+
"schemaVersion": "0.1.0",
|
|
152
|
+
"status": status,
|
|
153
|
+
"coreAcceptancePassed": core_pass,
|
|
154
|
+
"stable1Ready": readiness["readyForStable1"],
|
|
155
|
+
"environment": {
|
|
156
|
+
"platform": platform.system().casefold(),
|
|
157
|
+
"machine": platform.machine().casefold(),
|
|
158
|
+
"python": platform.python_version(),
|
|
159
|
+
},
|
|
160
|
+
"artifacts": {
|
|
161
|
+
"capsuleDigest": sha256_digest(demo.capsule.read_bytes()),
|
|
162
|
+
"traceDigest": sha256_digest(demo.trace.read_bytes()),
|
|
163
|
+
"sensorCoverageDigest": sha256_digest(coverage_path.read_bytes()),
|
|
164
|
+
"readinessDigest": sha256_digest(readiness_path.read_bytes()),
|
|
165
|
+
},
|
|
166
|
+
"verification": {
|
|
167
|
+
"capsule": capsule_verification,
|
|
168
|
+
"trace": trace_verification,
|
|
169
|
+
"oracleStatus": demo.oracle_status,
|
|
170
|
+
"evidenceClosure": demo.evidence_closure,
|
|
171
|
+
"cleanupVerified": demo.cleanup_verified,
|
|
172
|
+
},
|
|
173
|
+
"scope": {
|
|
174
|
+
"networkUsed": False,
|
|
175
|
+
"credentialsUsed": False,
|
|
176
|
+
"nativeTargetCodeExecuted": False,
|
|
177
|
+
"externalEvidenceGenerated": False,
|
|
178
|
+
},
|
|
179
|
+
"limitations": [
|
|
180
|
+
"Core acceptance uses SOVA's deterministic synthetic fixture.",
|
|
181
|
+
"The lab does not convert self-generated evidence into external validation.",
|
|
182
|
+
"Stable 1.0 remains blocked until every separate stable gate passes.",
|
|
183
|
+
],
|
|
184
|
+
}
|
|
185
|
+
report["digest"] = sha256_digest(canonical_json_bytes(report))
|
|
186
|
+
report_path = temporary / "report.json"
|
|
187
|
+
report_path.write_bytes(canonical_json_bytes(report) + b"\n")
|
|
188
|
+
temporary.rename(root)
|
|
189
|
+
return AcceptanceLabArtifacts(
|
|
190
|
+
root,
|
|
191
|
+
root / report_path.name,
|
|
192
|
+
root / coverage_path.name,
|
|
193
|
+
root / readiness_path.name,
|
|
194
|
+
root / "core-workflow" / demo.capsule.name,
|
|
195
|
+
root / "core-workflow" / demo.trace.name,
|
|
196
|
+
status,
|
|
197
|
+
)
|
|
198
|
+
except BaseException:
|
|
199
|
+
if temporary.exists():
|
|
200
|
+
shutil.rmtree(temporary)
|
|
201
|
+
raise
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def acceptance_receipt_template(gate_id: str) -> dict[str, Any]:
|
|
205
|
+
gate = next((item for item in default_release_gates() if item.id == gate_id), None)
|
|
206
|
+
if gate is None:
|
|
207
|
+
raise FormatError("SOVA-ACCEPTANCE-GATE", "unknown stable-release gate")
|
|
208
|
+
labels = {name: values[0] for name, values in gate.required_labels if values}
|
|
209
|
+
return {
|
|
210
|
+
"artifactType": "sova.acceptance-receipt",
|
|
211
|
+
"schemaVersion": "0.1.0",
|
|
212
|
+
"gateId": gate.id,
|
|
213
|
+
"evidenceType": gate.evidence_type,
|
|
214
|
+
"runId": "replace-with-stable-run-id",
|
|
215
|
+
"result": "inconclusive",
|
|
216
|
+
"producer": "replace-with-runner-or-reviewer",
|
|
217
|
+
"organization": "replace-with-legal-organization",
|
|
218
|
+
"environmentId": "replace-with-environment-fingerprint",
|
|
219
|
+
"labels": labels,
|
|
220
|
+
"artifactDigests": ["sha256:" + "0" * 64],
|
|
221
|
+
"independentOfSovaTeam": False,
|
|
222
|
+
"observedAt": datetime.now(UTC).isoformat().replace("+00:00", "Z"),
|
|
223
|
+
"limitations": [
|
|
224
|
+
"Template only; replace every placeholder with verified evidence.",
|
|
225
|
+
"A receipt signature does not prove reviewer identity or independence.",
|
|
226
|
+
],
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
__all__ = [
|
|
231
|
+
"AcceptanceLabArtifacts",
|
|
232
|
+
"acceptance_receipt_template",
|
|
233
|
+
"run_offline_acceptance_lab",
|
|
234
|
+
]
|