app.py is the Streamlit entrypoint for CAPRA. Layer 1 parsing, schema, graph, and export logic lives under capra/layer1/; Layer 2 attack-operator modeling lives under capra/layer2/. Repository-level assets include README.md, examples/, and demo.mp4. Keep reusable logic in the appropriate layer rather than expanding app.py.
Install dependencies with pip install -r requirements.txt. Run the app locally with streamlit run app.py. For quick syntax validation, use python -m py_compile app.py capra/layer1/*.py capra/layer1/parsers/*.py capra/layer1/utils/*.py. If you add third-party packages or new setup steps, update README.md in the same change.
Follow PEP 8 with 4-space indentation and snake_case for functions, variables, and module names. Keep Streamlit UI text in app.py; keep parsing, scoring, graph, and export logic in small helper functions under capra/layer1/. Prefer explicit dictionary keys only when matching existing data contracts. Add short comments only where the control flow or parsing rule is not obvious from the code.
Add targeted tests for new parsing or graph logic under tests/. Prefer pytest, with files named tests/test_<module>.py. At minimum, validate:
- Grype JSON/SARIF parsing with representative fixtures
- CVE-to-node mapping behavior
- Draw.io node/edge fact extraction with a small sample
Run pytest once tests exist, and keep sample inputs small enough to review in the repository.
Recent history mixes concise English subjects and generic Japanese messages such as 変更; use clearer imperative subjects going forward, for example Add Grype severity normalization. Keep commits focused on one change. PRs should include a short problem statement, the main implementation notes, local verification steps, and screenshots for Streamlit UI changes. Link the related issue or task when one exists.
Never commit API keys, report data with secrets, or large temporary analysis outputs. Sanitize vulnerability samples before adding them as fixtures or documentation examples.
Layer 1 is fact-only normalization. Do not add Attack Operator generation, NVD access, LLM use, path search, exploitability/success decisions, risk or Bayesian scoring, payload generation, or execution. Draw.io and cross-cloud dependency inputs remain optional. Keep important assets as goal_candidate; set is_goal only from an explicit analysis selection. Preserve source provenance and stable IDs, recursively redact secrets/tokens/credentials in raw evidence, and keep the Layer 1 JSON directly loadable by Layer 2.
Layer 2 is deterministic, rule-based modeling: do not use an LLM, execute attacks, validate a live target, run Bayesian updates, or fetch/store exploit code. Keep Hound semantics isolated by adapter; IAMHoundDog uses bounded same-source multi-edge patterns, while direct attack edges are converted only by their source-specific adapter. Never connect Operators from node equality alone; require matching effects/preconditions or subject-specific produces/requires capabilities. Emit only forward enables connections; keep requires on the dependent Operator instead of generating a reverse edge. Preserve fact provenance and unresolved data, generate stable IDs from canonical inputs, and recursively redact secrets/tokens from evidence, output, and logs. Runtime validation belongs to Layer 3.