From aee984d86291da92d8d658379e027002163ffdef Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 16 Jun 2026 04:14:26 -0700 Subject: [PATCH] Version documentation index and contracts --- CLAUDE.md | 4 ++- README.md | 2 ++ docs/COMMAND_REFERENCE.md | 4 +++ docs/INDEX.md | 38 ++++++++++++++++++++++++ docs/ROADMAP.md | 2 +- docs/SCHEMAS.md | 4 +++ docs/VERSION.json | 8 +++++ tests/test_docs_versioning.py | 55 +++++++++++++++++++++++++++++++++++ 8 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 docs/INDEX.md create mode 100644 docs/VERSION.json create mode 100644 tests/test_docs_versioning.py diff --git a/CLAUDE.md b/CLAUDE.md index bb057ce..4769cf1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,7 +23,7 @@ Primary functions: ## Current State Snapshot -As of 2026-06-13, the project is a local-first Linux IDS/IPS/EDR agent at +As of 2026-06-16, the project is a local-first Linux IDS/IPS/EDR agent at package version `0.7.0`. The branch has a working stdlib-only daemon, CLI, HTTPS management console, incident model, response planner, rootcheck, posture checks, file/package integrity checks, push notification backends, and optional @@ -80,6 +80,7 @@ Near-term open work: Start with: - `README.md` for product overview and architecture. +- `docs/INDEX.md` for the versioned documentation entry point. - `docs/SPECIFICATION.md` for the product model and acceptance criteria. - `docs/ROADMAP.md` for sequenced work. - `docs/COMMAND_REFERENCE.md` for CLI contracts. @@ -179,4 +180,5 @@ When changing behavior, update the relevant set: - `docs/THREAT_MODEL.md` for trust-boundary/security-model changes. - `docs/ROADMAP.md` for planned or completed roadmap movement. - `docs/SCHEMAS.md` for stable JSON contracts. +- `docs/VERSION.json` and `docs/INDEX.md` for documentation versioning. - `config/enodia-sentinel.toml` for config knobs. diff --git a/README.md b/README.md index f5a79ce..6f93adb 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ behind reviewed response workflows rather than silent remediation. Project docs: +- [Documentation index](docs/INDEX.md) — versioned entry point for operator, + product, schema, and roadmap documents. - [Specification](docs/SPECIFICATION.md) — product model, current scope, target platform shape, data model, and acceptance criteria. - [Roadmap](docs/ROADMAP.md) — phased work from local sensor to incident, diff --git a/docs/COMMAND_REFERENCE.md b/docs/COMMAND_REFERENCE.md index 6edd85e..83f44bf 100644 --- a/docs/COMMAND_REFERENCE.md +++ b/docs/COMMAND_REFERENCE.md @@ -1,5 +1,9 @@ # Enodia Sentinel Command Reference +Applies to package version: `0.7.0` +Docs version: `0.7` +Schema generation: `v1` + This is the operator-facing command contract for the current local agent. Commands are intentionally plain: they either inspect state, manage baselines, run the daemon, or expose existing evidence. diff --git a/docs/INDEX.md b/docs/INDEX.md new file mode 100644 index 0000000..b07ccd5 --- /dev/null +++ b/docs/INDEX.md @@ -0,0 +1,38 @@ +# Enodia Sentinel Documentation Index + +Applies to package version: `0.7.0` +Docs version: `0.7` +Schema generation: `v1` + +This index is the versioned entry point for local operator documentation. When +the package version changes, update `docs/VERSION.json` and this file in the +same patch as any command, schema, or behavior documentation changes. + +## Operator References + +| Document | Purpose | +|---|---| +| [COMMAND_REFERENCE.md](COMMAND_REFERENCE.md) | Manpage-style CLI and service command contract. | +| [SCHEMAS.md](SCHEMAS.md) | Stable JSON schema IDs and required v1 fields. | +| [OPERATIONS.md](OPERATIONS.md) | Install checks, health checks, alert workflow, baseline hygiene, and evidence export. | +| [RUNBOOKS.md](RUNBOOKS.md) | Incident response playbooks for common Sentinel findings. | +| [RULES.md](RULES.md) | Generated built-in event-rule reference by SID. | + +## Product and Security References + +| Document | Purpose | +|---|---| +| [SPECIFICATION.md](SPECIFICATION.md) | Product model, current scope, data model, and acceptance criteria. | +| [ROADMAP.md](ROADMAP.md) | Release tracks and planned sequencing. | +| [THREAT_MODEL.md](THREAT_MODEL.md) | Trust boundaries, attacker assumptions, and non-goals. | + +## Versioning Rules + +- Documentation tracks the package minor line, not individual commits. +- Additive JSON fields are allowed within a schema generation; required v1 + fields stay stable. +- Command behavior changes must update [COMMAND_REFERENCE.md](COMMAND_REFERENCE.md). +- New operator-facing JSON contracts must update [SCHEMAS.md](SCHEMAS.md) and + compatibility tests. +- Roadmap checkboxes should only be marked complete after code, docs, and tests + all reflect the shipped behavior. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index f48148f..71e794c 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -92,7 +92,7 @@ Purpose: define a stable single-host product. - ✅ Commit to stable JSON schemas for alerts, incidents, status, and response audits. - ✅ Add compatibility tests for schema evolution. -- Add documentation versioning and manpage-style command reference. +- ✅ Add documentation versioning and manpage-style command reference. - Harden packaging for Arch first, then document Debian/RPM install paths. - Add signed release artifacts and checksums. - Improve dashboard from alert browser to local console: diff --git a/docs/SCHEMAS.md b/docs/SCHEMAS.md index e2bf790..36c28ad 100644 --- a/docs/SCHEMAS.md +++ b/docs/SCHEMAS.md @@ -1,5 +1,9 @@ # Enodia Sentinel JSON Schemas +Applies to package version: `0.7.0` +Docs version: `0.7` +Schema generation: `v1` + Sentinel uses stable schema IDs for operator-facing JSON contracts. These IDs are lightweight compatibility markers, not external JSON Schema files. The v1 rule is additive: future releases may add fields, but required v1 fields should diff --git a/docs/VERSION.json b/docs/VERSION.json new file mode 100644 index 0000000..7f484b4 --- /dev/null +++ b/docs/VERSION.json @@ -0,0 +1,8 @@ +{ + "project": "enodia-sentinel", + "package_version": "0.7.0", + "docs_version": "0.7", + "schema_generation": "v1", + "command_reference": "docs/COMMAND_REFERENCE.md", + "schema_reference": "docs/SCHEMAS.md" +} diff --git a/tests/test_docs_versioning.py b/tests/test_docs_versioning.py new file mode 100644 index 0000000..aa0e0f8 --- /dev/null +++ b/tests/test_docs_versioning.py @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-3.0-or-later +"""Docs versioning checks for operator-facing references.""" +import json +import re +import tomllib +import unittest +from pathlib import Path + +from enodia_sentinel import __version__ + + +ROOT = Path(__file__).resolve().parents[1] +DOCS = ROOT / "docs" + + +class TestDocsVersioning(unittest.TestCase): + def test_docs_version_matches_package_metadata(self): + pyproject = tomllib.loads((ROOT / "pyproject.toml").read_text()) + package_version = pyproject["project"]["version"] + docs_version = json.loads((DOCS / "VERSION.json").read_text()) + + self.assertEqual(package_version, __version__) + self.assertEqual(docs_version["project"], "enodia-sentinel") + self.assertEqual(docs_version["package_version"], package_version) + self.assertEqual(docs_version["docs_version"], ".".join(package_version.split(".")[:2])) + self.assertEqual(docs_version["schema_generation"], "v1") + self.assertEqual(docs_version["command_reference"], "docs/COMMAND_REFERENCE.md") + self.assertEqual(docs_version["schema_reference"], "docs/SCHEMAS.md") + + def test_versioned_docs_headers_are_present(self): + version = json.loads((DOCS / "VERSION.json").read_text()) + for name in ("INDEX.md", "COMMAND_REFERENCE.md", "SCHEMAS.md"): + with self.subTest(name=name): + text = (DOCS / name).read_text() + self.assertIn( + f"Applies to package version: `{version['package_version']}`", + text, + ) + self.assertIn(f"Docs version: `{version['docs_version']}`", text) + self.assertIn(f"Schema generation: `{version['schema_generation']}`", text) + + def test_readme_links_versioned_docs_index(self): + text = (ROOT / "README.md").read_text() + self.assertRegex(text, r"\[Documentation index\]\(docs/INDEX\.md\)") + + def test_command_reference_is_manpage_style(self): + text = (DOCS / "COMMAND_REFERENCE.md").read_text() + commands = re.findall(r"^### `([^`]+)`", text, re.M) + self.assertGreaterEqual(len(commands), 8) + for phrase in ("Global options:", "Exit code:", "Expected use:"): + self.assertIn(phrase, text) + + +if __name__ == "__main__": + unittest.main()