evidentia-api 0.6.0__tar.gz
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.
- evidentia_api-0.6.0/.gitignore +95 -0
- evidentia_api-0.6.0/PKG-INFO +95 -0
- evidentia_api-0.6.0/README.md +66 -0
- evidentia_api-0.6.0/hatch_build.py +127 -0
- evidentia_api-0.6.0/pyproject.toml +54 -0
- evidentia_api-0.6.0/src/evidentia_api/__init__.py +21 -0
- evidentia_api-0.6.0/src/evidentia_api/app.py +236 -0
- evidentia_api-0.6.0/src/evidentia_api/cli.py +123 -0
- evidentia_api-0.6.0/src/evidentia_api/deps.py +25 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/__init__.py +5 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/collectors.py +151 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/config.py +74 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/doctor.py +204 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/explain.py +99 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/frameworks.py +92 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/gaps.py +190 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/health.py +46 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/init_wizard.py +67 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/integrations.py +200 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/llm_status.py +62 -0
- evidentia_api-0.6.0/src/evidentia_api/routers/risks.py +206 -0
- evidentia_api-0.6.0/src/evidentia_api/schemas.py +192 -0
- evidentia_api-0.6.0/src/evidentia_api/static/.gitkeep +6 -0
- evidentia_api-0.6.0/src/evidentia_api/static/assets/index-BfU73xHx.js +126 -0
- evidentia_api-0.6.0/src/evidentia_api/static/assets/index-BfU73xHx.js.map +1 -0
- evidentia_api-0.6.0/src/evidentia_api/static/assets/index-CFl0YLQ6.css +1 -0
- evidentia_api-0.6.0/src/evidentia_api/static/index.html +19 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# v0.4.0 — frontend build output lands in the Python package's static
|
|
2
|
+
# directory at wheel-assembly time via the hatchling build hook. The
|
|
3
|
+
# .gitkeep file in static/ is tracked; everything else is regenerated.
|
|
4
|
+
packages/evidentia-api/src/evidentia_api/static/assets/
|
|
5
|
+
packages/evidentia-api/src/evidentia_api/static/index.html
|
|
6
|
+
packages/evidentia-api/src/evidentia_api/static/*.js
|
|
7
|
+
packages/evidentia-api/src/evidentia_api/static/*.css
|
|
8
|
+
|
|
9
|
+
# Python
|
|
10
|
+
__pycache__/
|
|
11
|
+
*.py[cod]
|
|
12
|
+
*$py.class
|
|
13
|
+
*.so
|
|
14
|
+
.Python
|
|
15
|
+
build/
|
|
16
|
+
develop-eggs/
|
|
17
|
+
dist/
|
|
18
|
+
downloads/
|
|
19
|
+
eggs/
|
|
20
|
+
.eggs/
|
|
21
|
+
lib/
|
|
22
|
+
lib64/
|
|
23
|
+
parts/
|
|
24
|
+
sdist/
|
|
25
|
+
var/
|
|
26
|
+
wheels/
|
|
27
|
+
# NB: `lib/` and `lib64/` above would otherwise also match
|
|
28
|
+
# packages/evidentia-ui/src/lib/ (TypeScript utils). Scope to top-level
|
|
29
|
+
# only — there's no real Python-venv lib/ we'd fail to ignore because
|
|
30
|
+
# .venv/ and venv/ below cover that case.
|
|
31
|
+
!packages/evidentia-ui/src/lib/
|
|
32
|
+
*.egg-info/
|
|
33
|
+
.installed.cfg
|
|
34
|
+
*.egg
|
|
35
|
+
MANIFEST
|
|
36
|
+
|
|
37
|
+
# Virtual environments
|
|
38
|
+
.venv/
|
|
39
|
+
venv/
|
|
40
|
+
ENV/
|
|
41
|
+
env/
|
|
42
|
+
|
|
43
|
+
# uv
|
|
44
|
+
# NOTE: uv.lock is committed for reproducible builds.
|
|
45
|
+
# https://docs.astral.sh/uv/concepts/projects/sync/#locking-dependencies
|
|
46
|
+
|
|
47
|
+
# Testing
|
|
48
|
+
.pytest_cache/
|
|
49
|
+
.coverage
|
|
50
|
+
.coverage.*
|
|
51
|
+
htmlcov/
|
|
52
|
+
.tox/
|
|
53
|
+
.cache
|
|
54
|
+
coverage.xml
|
|
55
|
+
*.cover
|
|
56
|
+
.hypothesis/
|
|
57
|
+
|
|
58
|
+
# mypy
|
|
59
|
+
.mypy_cache/
|
|
60
|
+
.dmypy.json
|
|
61
|
+
dmypy.json
|
|
62
|
+
|
|
63
|
+
# Ruff
|
|
64
|
+
.ruff_cache/
|
|
65
|
+
|
|
66
|
+
# IDE
|
|
67
|
+
.vscode/
|
|
68
|
+
.idea/
|
|
69
|
+
*.swp
|
|
70
|
+
*.swo
|
|
71
|
+
*~
|
|
72
|
+
.DS_Store
|
|
73
|
+
|
|
74
|
+
# Claude Code local state
|
|
75
|
+
.claude/
|
|
76
|
+
|
|
77
|
+
# Evidentia runtime — user project state (NOT bundled examples).
|
|
78
|
+
# `.controlbridge/` and `/controlbridge.yaml` are kept ignored for the
|
|
79
|
+
# lifetime of the shim (through v0.7.0) so legacy project workspaces
|
|
80
|
+
# authored against v0.1.0 – v0.5.0 don't start leaking into git.
|
|
81
|
+
.evidentia/
|
|
82
|
+
.controlbridge/
|
|
83
|
+
/evidentia.yaml
|
|
84
|
+
/controlbridge.yaml
|
|
85
|
+
*.local.yaml
|
|
86
|
+
evidence/
|
|
87
|
+
reports/
|
|
88
|
+
risks/
|
|
89
|
+
|
|
90
|
+
# Generated reports from examples (keep source files, ignore generated ones)
|
|
91
|
+
examples/**/report.json
|
|
92
|
+
examples/**/report.csv
|
|
93
|
+
examples/**/report.md
|
|
94
|
+
examples/**/report.oscal.json
|
|
95
|
+
examples/**/risks.json
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: evidentia-api
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: FastAPI REST server + bundled React web UI for Evidentia
|
|
5
|
+
Project-URL: Homepage, https://github.com/allenfbyrd/evidentia
|
|
6
|
+
Project-URL: Repository, https://github.com/allenfbyrd/evidentia
|
|
7
|
+
Project-URL: Issues, https://github.com/allenfbyrd/evidentia/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/allenfbyrd/evidentia/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Allen Byrd <allen@allenfbyrd.com>
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
Keywords: compliance,fastapi,grc,oscal,rest-api,web-ui
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Framework :: FastAPI
|
|
14
|
+
Classifier: Intended Audience :: Information Technology
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
19
|
+
Classifier: Topic :: Security
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Requires-Dist: evidentia-ai<0.7.0,>=0.6.0
|
|
23
|
+
Requires-Dist: evidentia-core<0.7.0,>=0.6.0
|
|
24
|
+
Requires-Dist: fastapi>=0.115
|
|
25
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
26
|
+
Requires-Dist: sse-starlette>=2.1
|
|
27
|
+
Requires-Dist: uvicorn[standard]>=0.30
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# evidentia-api
|
|
31
|
+
|
|
32
|
+
FastAPI REST server and bundled React web UI for **Evidentia**, the open-source GRC tool.
|
|
33
|
+
|
|
34
|
+
This package is not typically installed directly. The preferred way is via the `[gui]` extra on the meta-package:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv tool install "evidentia[gui]"
|
|
38
|
+
# or
|
|
39
|
+
pip install "evidentia[gui]"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then run:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
evidentia serve
|
|
46
|
+
# -> FastAPI + React UI at http://127.0.0.1:8000
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## What's inside
|
|
50
|
+
|
|
51
|
+
- **FastAPI app** (`evidentia_api.app:app`) — REST endpoints mirroring every CLI capability.
|
|
52
|
+
- **SPA** — React/Vite/shadcn/ui frontend, bundled as static assets inside the wheel under `evidentia_api/static/`.
|
|
53
|
+
- **SSE streaming** — long-running LLM calls (`risk generate`, `explain`) stream progress to the browser without blocking.
|
|
54
|
+
|
|
55
|
+
## REST surface
|
|
56
|
+
|
|
57
|
+
Every endpoint is typed with Pydantic models reused from `evidentia-core`. All endpoints bind to `127.0.0.1` by default; `--host 0.0.0.0` emits a security warning.
|
|
58
|
+
|
|
59
|
+
| Method | Path | Purpose |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| GET | `/api/health` | Health probe |
|
|
62
|
+
| GET | `/api/version` | Evidentia version info |
|
|
63
|
+
| GET | `/api/doctor` | Diagnostic summary |
|
|
64
|
+
| POST | `/api/doctor/check-air-gap` | Air-gap validator |
|
|
65
|
+
| GET | `/api/config` | Read `evidentia.yaml` |
|
|
66
|
+
| PUT | `/api/config` | Write `evidentia.yaml` |
|
|
67
|
+
| GET | `/api/frameworks` | List all 82 bundled catalogs |
|
|
68
|
+
| GET | `/api/frameworks/{id}` | Framework detail |
|
|
69
|
+
| GET | `/api/frameworks/{id}/controls/{control_id}` | Single control |
|
|
70
|
+
| POST | `/api/gap/analyze` | Run GapAnalyzer, save to gap store |
|
|
71
|
+
| GET | `/api/gap/reports` | List saved reports |
|
|
72
|
+
| GET | `/api/gap/reports/{key}` | Load a saved report |
|
|
73
|
+
| POST | `/api/gap/diff` | Compute diff between two reports |
|
|
74
|
+
| POST | `/api/risk/generate` | SSE: per-gap risk statement generation |
|
|
75
|
+
| POST | `/api/explain/{framework}/{control_id}` | Plain-English control explanation |
|
|
76
|
+
| POST | `/api/init/wizard` | Generate starter YAML files |
|
|
77
|
+
| GET | `/api/llm-status` | LLM provider configuration state |
|
|
78
|
+
|
|
79
|
+
## Air-gapped mode
|
|
80
|
+
|
|
81
|
+
Running `evidentia serve --offline` wires the air-gap guard into every `/api/*` call. LLM features gracefully degrade with a pointer to Ollama. See [`docs/air-gapped.md`](../../docs/air-gapped.md).
|
|
82
|
+
|
|
83
|
+
## Development
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# From the repo root:
|
|
87
|
+
uv sync --all-packages
|
|
88
|
+
cd packages/evidentia-ui && npm install && npm run dev # Vite dev server at :5173
|
|
89
|
+
# In another terminal:
|
|
90
|
+
evidentia serve --dev # FastAPI at :8000 proxies /api/* to itself, / to Vite :5173
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
Apache-2.0 — see [`LICENSE`](../../LICENSE).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# evidentia-api
|
|
2
|
+
|
|
3
|
+
FastAPI REST server and bundled React web UI for **Evidentia**, the open-source GRC tool.
|
|
4
|
+
|
|
5
|
+
This package is not typically installed directly. The preferred way is via the `[gui]` extra on the meta-package:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv tool install "evidentia[gui]"
|
|
9
|
+
# or
|
|
10
|
+
pip install "evidentia[gui]"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
evidentia serve
|
|
17
|
+
# -> FastAPI + React UI at http://127.0.0.1:8000
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What's inside
|
|
21
|
+
|
|
22
|
+
- **FastAPI app** (`evidentia_api.app:app`) — REST endpoints mirroring every CLI capability.
|
|
23
|
+
- **SPA** — React/Vite/shadcn/ui frontend, bundled as static assets inside the wheel under `evidentia_api/static/`.
|
|
24
|
+
- **SSE streaming** — long-running LLM calls (`risk generate`, `explain`) stream progress to the browser without blocking.
|
|
25
|
+
|
|
26
|
+
## REST surface
|
|
27
|
+
|
|
28
|
+
Every endpoint is typed with Pydantic models reused from `evidentia-core`. All endpoints bind to `127.0.0.1` by default; `--host 0.0.0.0` emits a security warning.
|
|
29
|
+
|
|
30
|
+
| Method | Path | Purpose |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| GET | `/api/health` | Health probe |
|
|
33
|
+
| GET | `/api/version` | Evidentia version info |
|
|
34
|
+
| GET | `/api/doctor` | Diagnostic summary |
|
|
35
|
+
| POST | `/api/doctor/check-air-gap` | Air-gap validator |
|
|
36
|
+
| GET | `/api/config` | Read `evidentia.yaml` |
|
|
37
|
+
| PUT | `/api/config` | Write `evidentia.yaml` |
|
|
38
|
+
| GET | `/api/frameworks` | List all 82 bundled catalogs |
|
|
39
|
+
| GET | `/api/frameworks/{id}` | Framework detail |
|
|
40
|
+
| GET | `/api/frameworks/{id}/controls/{control_id}` | Single control |
|
|
41
|
+
| POST | `/api/gap/analyze` | Run GapAnalyzer, save to gap store |
|
|
42
|
+
| GET | `/api/gap/reports` | List saved reports |
|
|
43
|
+
| GET | `/api/gap/reports/{key}` | Load a saved report |
|
|
44
|
+
| POST | `/api/gap/diff` | Compute diff between two reports |
|
|
45
|
+
| POST | `/api/risk/generate` | SSE: per-gap risk statement generation |
|
|
46
|
+
| POST | `/api/explain/{framework}/{control_id}` | Plain-English control explanation |
|
|
47
|
+
| POST | `/api/init/wizard` | Generate starter YAML files |
|
|
48
|
+
| GET | `/api/llm-status` | LLM provider configuration state |
|
|
49
|
+
|
|
50
|
+
## Air-gapped mode
|
|
51
|
+
|
|
52
|
+
Running `evidentia serve --offline` wires the air-gap guard into every `/api/*` call. LLM features gracefully degrade with a pointer to Ollama. See [`docs/air-gapped.md`](../../docs/air-gapped.md).
|
|
53
|
+
|
|
54
|
+
## Development
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# From the repo root:
|
|
58
|
+
uv sync --all-packages
|
|
59
|
+
cd packages/evidentia-ui && npm install && npm run dev # Vite dev server at :5173
|
|
60
|
+
# In another terminal:
|
|
61
|
+
evidentia serve --dev # FastAPI at :8000 proxies /api/* to itself, / to Vite :5173
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## License
|
|
65
|
+
|
|
66
|
+
Apache-2.0 — see [`LICENSE`](../../LICENSE).
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Hatchling build hook — bundle the Vite-built React SPA into the wheel.
|
|
2
|
+
|
|
3
|
+
Runs before wheel packaging when ``uv build`` (or ``python -m build``) is
|
|
4
|
+
invoked for the ``evidentia-api`` package:
|
|
5
|
+
|
|
6
|
+
1. Checks if ``packages/evidentia-ui/dist/`` exists and is non-empty.
|
|
7
|
+
2. If yes, copies ``dist/*`` into ``src/evidentia_api/static/``.
|
|
8
|
+
3. If no, runs ``npm ci && npm run build`` in the UI directory to produce
|
|
9
|
+
``dist/`` first, then copies. Gracefully skips with a warning if Node
|
|
10
|
+
isn't installed on the build machine — for Python-only contributors
|
|
11
|
+
who only touch backend code.
|
|
12
|
+
|
|
13
|
+
The hook is a no-op on machines that set the ``EVIDENTIA_SKIP_FRONTEND_BUILD``
|
|
14
|
+
environment variable — convenient for CI matrices that separate concerns
|
|
15
|
+
between Python tests and frontend builds.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import logging
|
|
21
|
+
import os
|
|
22
|
+
import shutil
|
|
23
|
+
import subprocess
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import Any
|
|
26
|
+
|
|
27
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger("hatch.build.evidentia-api")
|
|
30
|
+
|
|
31
|
+
# Paths are resolved relative to the evidentia-api package root at
|
|
32
|
+
# build time. The UI sits one directory up.
|
|
33
|
+
_PKG_ROOT = Path(__file__).parent
|
|
34
|
+
_UI_DIR = (_PKG_ROOT.parent / "evidentia-ui").resolve()
|
|
35
|
+
_UI_DIST = _UI_DIR / "dist"
|
|
36
|
+
_STATIC_DEST = _PKG_ROOT / "src" / "evidentia_api" / "static"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class FrontendBundleHook(BuildHookInterface):
|
|
40
|
+
"""Copies the React SPA build output into the Python package tree."""
|
|
41
|
+
|
|
42
|
+
PLUGIN_NAME = "evidentia-frontend"
|
|
43
|
+
|
|
44
|
+
def initialize(self, version: str, build_data: dict[str, Any]) -> None:
|
|
45
|
+
"""Invoked by hatchling before the wheel/sdist is assembled."""
|
|
46
|
+
del version, build_data # unused
|
|
47
|
+
|
|
48
|
+
if os.environ.get("EVIDENTIA_SKIP_FRONTEND_BUILD"):
|
|
49
|
+
logger.info(
|
|
50
|
+
"EVIDENTIA_SKIP_FRONTEND_BUILD set; leaving static/ untouched."
|
|
51
|
+
)
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
if not _UI_DIR.is_dir():
|
|
55
|
+
logger.warning(
|
|
56
|
+
"Frontend dir %s not found; skipping static bundle. "
|
|
57
|
+
"The wheel will serve a dev-placeholder page.",
|
|
58
|
+
_UI_DIR,
|
|
59
|
+
)
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
# If the user hasn't run `npm run build` yet, try to do it now.
|
|
63
|
+
if (not _UI_DIST.is_dir() or not any(_UI_DIST.iterdir())) and not _try_npm_build():
|
|
64
|
+
# Node unavailable or build failed. Ship without the SPA.
|
|
65
|
+
logger.warning(
|
|
66
|
+
"Frontend build unavailable; static/ will remain empty. "
|
|
67
|
+
"The wheel will serve a dev-placeholder page."
|
|
68
|
+
)
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
self._copy_dist_to_static()
|
|
72
|
+
|
|
73
|
+
def _copy_dist_to_static(self) -> None:
|
|
74
|
+
"""Sync ``dist/*`` -> ``static/``. Wipes stale assets first."""
|
|
75
|
+
_STATIC_DEST.mkdir(parents=True, exist_ok=True)
|
|
76
|
+
|
|
77
|
+
# Clear stale assets but keep the .gitkeep file so the directory
|
|
78
|
+
# is preserved even when fresh checkouts haven't built yet.
|
|
79
|
+
for item in _STATIC_DEST.iterdir():
|
|
80
|
+
if item.name == ".gitkeep":
|
|
81
|
+
continue
|
|
82
|
+
if item.is_file() or item.is_symlink():
|
|
83
|
+
item.unlink()
|
|
84
|
+
else:
|
|
85
|
+
shutil.rmtree(item)
|
|
86
|
+
|
|
87
|
+
for src in _UI_DIST.iterdir():
|
|
88
|
+
dest = _STATIC_DEST / src.name
|
|
89
|
+
if src.is_dir():
|
|
90
|
+
shutil.copytree(src, dest)
|
|
91
|
+
else:
|
|
92
|
+
shutil.copy2(src, dest)
|
|
93
|
+
|
|
94
|
+
logger.info("Copied frontend bundle from %s -> %s", _UI_DIST, _STATIC_DEST)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _try_npm_build() -> bool:
|
|
98
|
+
"""Attempt ``npm install && npm run build`` in the UI dir. Return True on success.
|
|
99
|
+
|
|
100
|
+
Uses ``npm ci`` when ``package-lock.json`` already exists (faster + deterministic)
|
|
101
|
+
and falls back to ``npm install`` when it doesn't — this covers fresh checkouts
|
|
102
|
+
where the lockfile hasn't been committed yet.
|
|
103
|
+
"""
|
|
104
|
+
npm = shutil.which("npm")
|
|
105
|
+
if npm is None:
|
|
106
|
+
logger.warning(
|
|
107
|
+
"`npm` not found on PATH; cannot auto-build frontend. "
|
|
108
|
+
"Install Node 20+ or run `npm install && npm run build` manually "
|
|
109
|
+
"in packages/evidentia-ui/ before `uv build`."
|
|
110
|
+
)
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
lockfile = _UI_DIR / "package-lock.json"
|
|
114
|
+
install_cmd = (
|
|
115
|
+
[npm, "ci", "--no-audit", "--no-fund"]
|
|
116
|
+
if lockfile.is_file()
|
|
117
|
+
else [npm, "install", "--no-audit", "--no-fund"]
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
for cmd in (install_cmd, [npm, "run", "build"]):
|
|
121
|
+
logger.info("Running: %s (cwd=%s)", " ".join(cmd), _UI_DIR)
|
|
122
|
+
try:
|
|
123
|
+
subprocess.run(cmd, cwd=_UI_DIR, check=True)
|
|
124
|
+
except subprocess.CalledProcessError as e:
|
|
125
|
+
logger.error("Frontend build step failed: %s", e)
|
|
126
|
+
return False
|
|
127
|
+
return True
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "evidentia-api"
|
|
3
|
+
version = "0.6.0"
|
|
4
|
+
description = "FastAPI REST server + bundled React web UI for Evidentia"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{name = "Allen Byrd", email = "allen@allenfbyrd.com"}]
|
|
7
|
+
license = "Apache-2.0"
|
|
8
|
+
requires-python = ">=3.12"
|
|
9
|
+
keywords = ["grc", "compliance", "fastapi", "web-ui", "oscal", "rest-api"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"Intended Audience :: Information Technology",
|
|
13
|
+
"License :: OSI Approved :: Apache Software License",
|
|
14
|
+
"Operating System :: OS Independent",
|
|
15
|
+
"Programming Language :: Python :: 3.12",
|
|
16
|
+
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
|
|
17
|
+
"Topic :: Security",
|
|
18
|
+
"Framework :: FastAPI",
|
|
19
|
+
"Typing :: Typed",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"evidentia-core>=0.6.0,<0.7.0",
|
|
23
|
+
"evidentia-ai>=0.6.0,<0.7.0",
|
|
24
|
+
"fastapi>=0.115",
|
|
25
|
+
"uvicorn[standard]>=0.30",
|
|
26
|
+
"python-multipart>=0.0.9",
|
|
27
|
+
"sse-starlette>=2.1",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://github.com/allenfbyrd/evidentia"
|
|
32
|
+
Repository = "https://github.com/allenfbyrd/evidentia"
|
|
33
|
+
Issues = "https://github.com/allenfbyrd/evidentia/issues"
|
|
34
|
+
Changelog = "https://github.com/allenfbyrd/evidentia/blob/main/CHANGELOG.md"
|
|
35
|
+
|
|
36
|
+
[build-system]
|
|
37
|
+
requires = ["hatchling"]
|
|
38
|
+
build-backend = "hatchling.build"
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.wheel]
|
|
41
|
+
packages = ["src/evidentia_api"]
|
|
42
|
+
# The static/ subdirectory is populated at build time by the custom
|
|
43
|
+
# hatchling build hook (hatch_build.py). The hook runs `npm run build`
|
|
44
|
+
# in packages/evidentia-ui/ and copies dist/* into
|
|
45
|
+
# src/evidentia_api/static/ before wheel assembly. Set the env var
|
|
46
|
+
# EVIDENTIA_SKIP_FRONTEND_BUILD=1 to bypass the hook in Python-only
|
|
47
|
+
# build environments.
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.hooks.custom]
|
|
50
|
+
path = "hatch_build.py"
|
|
51
|
+
|
|
52
|
+
[tool.uv.sources]
|
|
53
|
+
evidentia-core = { workspace = true }
|
|
54
|
+
evidentia-ai = { workspace = true }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Evidentia API: FastAPI REST server + bundled React web UI.
|
|
2
|
+
|
|
3
|
+
The FastAPI application is exposed as :data:`evidentia_api.app.app` and
|
|
4
|
+
can be served directly with uvicorn:
|
|
5
|
+
|
|
6
|
+
uvicorn evidentia_api.app:app --host 127.0.0.1 --port 8000
|
|
7
|
+
|
|
8
|
+
Typical users reach it via the CLI:
|
|
9
|
+
|
|
10
|
+
evidentia serve [--host HOST] [--port PORT] [--offline]
|
|
11
|
+
|
|
12
|
+
which is a thin Typer wrapper around :func:`evidentia_api.cli.serve`.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from importlib.metadata import PackageNotFoundError
|
|
16
|
+
from importlib.metadata import version as _pkg_version
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
__version__ = _pkg_version("evidentia-api")
|
|
20
|
+
except PackageNotFoundError: # pragma: no cover — only hit in editable repos without install
|
|
21
|
+
__version__ = "0.0.0+unknown"
|