coreason-manifest 0.5.1__py3-none-any.whl → 0.7.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.
- coreason_manifest/__init__.py +13 -55
- coreason_manifest/definitions/__init__.py +0 -0
- coreason_manifest/definitions/audit.py +7 -0
- coreason_manifest/definitions/simulation.py +19 -0
- coreason_manifest/definitions/topology.py +140 -0
- coreason_manifest/recipes.py +38 -0
- {coreason_manifest-0.5.1.dist-info → coreason_manifest-0.7.0.dist-info}/METADATA +1 -7
- coreason_manifest-0.7.0.dist-info/RECORD +16 -0
- coreason_manifest/engine.py +0 -222
- coreason_manifest/errors.py +0 -53
- coreason_manifest/integrity.py +0 -141
- coreason_manifest/loader.py +0 -271
- coreason_manifest/main.py +0 -17
- coreason_manifest/policies/compliance.rego +0 -81
- coreason_manifest/policies/tbom.json +0 -14
- coreason_manifest/policy.py +0 -138
- coreason_manifest/server.py +0 -123
- coreason_manifest/validator.py +0 -67
- coreason_manifest-0.5.1.dist-info/RECORD +0 -21
- /coreason_manifest/{models.py → definitions/agent.py} +0 -0
- {coreason_manifest-0.5.1.dist-info → coreason_manifest-0.7.0.dist-info}/WHEEL +0 -0
- {coreason_manifest-0.5.1.dist-info → coreason_manifest-0.7.0.dist-info}/licenses/LICENSE +0 -0
- {coreason_manifest-0.5.1.dist-info → coreason_manifest-0.7.0.dist-info}/licenses/NOTICE +0 -0
coreason_manifest/server.py
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
from contextlib import asynccontextmanager
|
|
2
|
-
from importlib import resources
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import AsyncIterator, List, Optional, Union
|
|
5
|
-
|
|
6
|
-
from fastapi import FastAPI, HTTPException, Request, status
|
|
7
|
-
from fastapi.responses import JSONResponse
|
|
8
|
-
from pydantic import BaseModel, Field
|
|
9
|
-
|
|
10
|
-
from coreason_manifest.engine import ManifestConfig, ManifestEngineAsync
|
|
11
|
-
from coreason_manifest.errors import ManifestSyntaxError, PolicyViolationError
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# Response Model
|
|
15
|
-
class ValidationResponse(BaseModel):
|
|
16
|
-
valid: bool
|
|
17
|
-
agent_id: Optional[str] = None
|
|
18
|
-
version: Optional[str] = None
|
|
19
|
-
policy_violations: List[str] = Field(default_factory=list)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@asynccontextmanager
|
|
23
|
-
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
|
24
|
-
# Locate policies
|
|
25
|
-
policy_path: Optional[Path] = None
|
|
26
|
-
tbom_path: Optional[Path] = None
|
|
27
|
-
|
|
28
|
-
# 1. Check local directory (Docker runtime with COPY or relative dev path)
|
|
29
|
-
# In Docker we will COPY to /app/policies/ or ./policies/ relative to WORKDIR
|
|
30
|
-
# We'll check common locations.
|
|
31
|
-
possible_dirs = [
|
|
32
|
-
Path("policies"),
|
|
33
|
-
Path("/app/policies"),
|
|
34
|
-
Path("src/coreason_manifest/policies"), # Dev from root
|
|
35
|
-
]
|
|
36
|
-
|
|
37
|
-
for d in possible_dirs:
|
|
38
|
-
if (d / "compliance.rego").exists():
|
|
39
|
-
policy_path = d / "compliance.rego"
|
|
40
|
-
if (d / "tbom.json").exists():
|
|
41
|
-
tbom_path = d / "tbom.json"
|
|
42
|
-
break
|
|
43
|
-
|
|
44
|
-
# 2. Fallback to package resources
|
|
45
|
-
resource_context = None
|
|
46
|
-
if not policy_path:
|
|
47
|
-
try:
|
|
48
|
-
# Check if it exists as a resource
|
|
49
|
-
ref = resources.files("coreason_manifest.policies").joinpath("compliance.rego")
|
|
50
|
-
if ref.is_file():
|
|
51
|
-
resource_context = resources.as_file(ref)
|
|
52
|
-
policy_path = resource_context.__enter__()
|
|
53
|
-
# Check for TBOM in same dir if possible, or ignore for fallback
|
|
54
|
-
except Exception:
|
|
55
|
-
pass
|
|
56
|
-
|
|
57
|
-
# If still not found, fail.
|
|
58
|
-
if not policy_path:
|
|
59
|
-
raise RuntimeError("Could not locate compliance.rego policy file.")
|
|
60
|
-
|
|
61
|
-
config = ManifestConfig(
|
|
62
|
-
policy_path=policy_path,
|
|
63
|
-
tbom_path=tbom_path,
|
|
64
|
-
opa_path="opa", # Assumes OPA is in PATH (installed via Dockerfile)
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
engine = ManifestEngineAsync(config)
|
|
68
|
-
|
|
69
|
-
try:
|
|
70
|
-
async with engine:
|
|
71
|
-
app.state.engine = engine
|
|
72
|
-
yield
|
|
73
|
-
finally:
|
|
74
|
-
if resource_context:
|
|
75
|
-
resource_context.__exit__(None, None, None)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
app = FastAPI(lifespan=lifespan)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
@app.post("/validate", response_model=ValidationResponse) # type: ignore[misc]
|
|
82
|
-
async def validate_manifest(request: Request) -> Union[ValidationResponse, JSONResponse]:
|
|
83
|
-
engine: ManifestEngineAsync = app.state.engine
|
|
84
|
-
|
|
85
|
-
try:
|
|
86
|
-
raw_body = await request.json()
|
|
87
|
-
except Exception:
|
|
88
|
-
raise HTTPException(status_code=400, detail="Invalid JSON body") from None
|
|
89
|
-
|
|
90
|
-
try:
|
|
91
|
-
agent_def = await engine.validate_manifest_dict(raw_body)
|
|
92
|
-
return ValidationResponse(
|
|
93
|
-
valid=True,
|
|
94
|
-
agent_id=str(agent_def.metadata.id),
|
|
95
|
-
version=agent_def.metadata.version,
|
|
96
|
-
policy_violations=[],
|
|
97
|
-
)
|
|
98
|
-
except ManifestSyntaxError as e:
|
|
99
|
-
# Return 422 with the error
|
|
100
|
-
resp = ValidationResponse(valid=False, policy_violations=[f"Syntax Error: {str(e)}"])
|
|
101
|
-
return JSONResponse(status_code=status.HTTP_422_UNPROCESSABLE_CONTENT, content=resp.model_dump())
|
|
102
|
-
except PolicyViolationError as e:
|
|
103
|
-
resp = ValidationResponse(valid=False, policy_violations=e.violations)
|
|
104
|
-
return JSONResponse(status_code=status.HTTP_422_UNPROCESSABLE_CONTENT, content=resp.model_dump())
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
@app.get("/health") # type: ignore[misc]
|
|
108
|
-
async def health_check() -> dict[str, str]:
|
|
109
|
-
engine: ManifestEngineAsync = app.state.engine
|
|
110
|
-
policy_version = "unknown"
|
|
111
|
-
try:
|
|
112
|
-
import hashlib
|
|
113
|
-
|
|
114
|
-
# policy_path is guaranteed to exist by lifespan check
|
|
115
|
-
policy_path = Path(engine.config.policy_path)
|
|
116
|
-
if policy_path.exists():
|
|
117
|
-
with open(policy_path, "rb") as f:
|
|
118
|
-
digest = hashlib.sha256(f.read()).hexdigest()[:8]
|
|
119
|
-
policy_version = digest
|
|
120
|
-
except Exception:
|
|
121
|
-
pass
|
|
122
|
-
|
|
123
|
-
return {"status": "active", "policy_version": policy_version}
|
coreason_manifest/validator.py
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
# Prosperity-3.0
|
|
2
|
-
"""Schema validation functionality.
|
|
3
|
-
|
|
4
|
-
This module provides the `SchemaValidator` class, which uses JSON Schema to
|
|
5
|
-
validate the structure and types of agent definitions.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
import json
|
|
11
|
-
from importlib.resources import files
|
|
12
|
-
from typing import Any
|
|
13
|
-
|
|
14
|
-
from jsonschema import FormatChecker, ValidationError, validate
|
|
15
|
-
|
|
16
|
-
from coreason_manifest.errors import ManifestSyntaxError
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class SchemaValidator:
|
|
20
|
-
"""Component B: SchemaValidator (The Structural Engineer).
|
|
21
|
-
|
|
22
|
-
Responsibility:
|
|
23
|
-
- Validate the dictionary against the Master JSON Schema.
|
|
24
|
-
- Check required fields, data types, and format constraints.
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
def __init__(self) -> None:
|
|
28
|
-
"""Initialize the validator by loading the schema."""
|
|
29
|
-
self.schema = self._load_schema()
|
|
30
|
-
|
|
31
|
-
def _load_schema(self) -> dict[str, Any]:
|
|
32
|
-
"""Loads the JSON schema from the package resources.
|
|
33
|
-
|
|
34
|
-
Returns:
|
|
35
|
-
The JSON schema dictionary.
|
|
36
|
-
|
|
37
|
-
Raises:
|
|
38
|
-
ManifestSyntaxError: If the schema file cannot be loaded or is invalid.
|
|
39
|
-
"""
|
|
40
|
-
try:
|
|
41
|
-
schema_path = files("coreason_manifest.schemas").joinpath("agent.schema.json")
|
|
42
|
-
with schema_path.open("r", encoding="utf-8") as f:
|
|
43
|
-
schema = json.load(f)
|
|
44
|
-
if not isinstance(schema, dict):
|
|
45
|
-
raise ManifestSyntaxError("Schema file is not a valid JSON object.")
|
|
46
|
-
return schema
|
|
47
|
-
except (IOError, json.JSONDecodeError) as e:
|
|
48
|
-
raise ManifestSyntaxError(f"Failed to load agent schema: {e}") from e
|
|
49
|
-
|
|
50
|
-
def validate(self, data: dict[str, Any]) -> bool:
|
|
51
|
-
"""Validates the given dictionary against the agent schema.
|
|
52
|
-
|
|
53
|
-
Args:
|
|
54
|
-
data: The raw dictionary to validate.
|
|
55
|
-
|
|
56
|
-
Returns:
|
|
57
|
-
True if validation passes.
|
|
58
|
-
|
|
59
|
-
Raises:
|
|
60
|
-
ManifestSyntaxError: If validation fails.
|
|
61
|
-
"""
|
|
62
|
-
try:
|
|
63
|
-
validate(instance=data, schema=self.schema, format_checker=FormatChecker())
|
|
64
|
-
return True
|
|
65
|
-
except ValidationError as e:
|
|
66
|
-
# We treat schema validation errors as syntax errors in the manifest
|
|
67
|
-
raise ManifestSyntaxError(f"Schema validation failed: {e.message}") from e
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
coreason_manifest/__init__.py,sha256=R07xUHw9RWdWQPh7OWbpMT8kkzkEWfEI5hizu_5UNck,1528
|
|
2
|
-
coreason_manifest/engine.py,sha256=ENAkRuGFd1uY_5u4EYEsTZUMrqw5HgijKtkF9lk-E-c,8199
|
|
3
|
-
coreason_manifest/errors.py,sha256=CKFWSucncoPLYUJcsuXtLIfneyr2d89oHRTiWPT4psU,1437
|
|
4
|
-
coreason_manifest/integrity.py,sha256=CMBaa2A8DpC9hDSO-aj-YOzss6if1CajaeLEmTC703c,5344
|
|
5
|
-
coreason_manifest/loader.py,sha256=WET8HAnSw4dgon_zdiZaaU1dIUrsIQPYZzxlp0crTYo,10027
|
|
6
|
-
coreason_manifest/main.py,sha256=YQO98w2wxkfNs-DpSLmiDTs9DtUeGsC48GEfbElXVPk,357
|
|
7
|
-
coreason_manifest/models.py,sha256=EuaE1Wl5T8f_eI9vF1VFp5hd0y9C7E52zAjB52EulKw,7497
|
|
8
|
-
coreason_manifest/policies/compliance.rego,sha256=-drMuno6YkGOXKjvdLWawCZWK8iUxY7OcXpoXa_9Oyo,3035
|
|
9
|
-
coreason_manifest/policies/tbom.json,sha256=rSn4V44_IdFqCC86J3Jc31qQKTV4J5BdmyO0CI4iOu0,167
|
|
10
|
-
coreason_manifest/policy.py,sha256=vvEivq5HSjv-bMSrZ5VMM3eTomYFp39SBtuFajG9RU4,5009
|
|
11
|
-
coreason_manifest/schemas/__init__.py,sha256=9TMs6jWKCIewAKkj-u0tq9c6N_-0CU6b5s9q6MTS6v4,17
|
|
12
|
-
coreason_manifest/schemas/agent.schema.json,sha256=VigUX3ltX7YaW9P7n0DNYGNOf8C6VCuXNy71u3LB9i4,6812
|
|
13
|
-
coreason_manifest/server.py,sha256=ezuk-4sABF92U4cY1ppYJGJf8q6yeoteVlrwnmk7Jis,4253
|
|
14
|
-
coreason_manifest/utils/__init__.py,sha256=Q9gXiBtX3mD9GTu4z0JDHSHkbXC-MRHagrOaOmRH_1Q,435
|
|
15
|
-
coreason_manifest/utils/logger.py,sha256=A7E6Hd_Jk1XDUajNEJQl-WtUv9M2LT76b4_TsbxnILw,1227
|
|
16
|
-
coreason_manifest/validator.py,sha256=v33EzKroRwLEjZeuRRpTB7cqB38op3DV2EZpZhJ80a0,2240
|
|
17
|
-
coreason_manifest-0.5.1.dist-info/METADATA,sha256=7BttvVoqqTsQwYR34ih_iLY2kz1_TxsotrbXwTiGF2k,7421
|
|
18
|
-
coreason_manifest-0.5.1.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
|
|
19
|
-
coreason_manifest-0.5.1.dist-info/licenses/LICENSE,sha256=3tYb7ZQe7sVXcbNmX22fDESFjOSIlCZodUGpZMkuSlk,3063
|
|
20
|
-
coreason_manifest-0.5.1.dist-info/licenses/NOTICE,sha256=tqzUyP9VTCGxoHLgBI0AC1i0G7m_PSyESFL8Jwuw0dA,610
|
|
21
|
-
coreason_manifest-0.5.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|