mnemosyne-guard 0.1.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.
Files changed (65) hide show
  1. mnemosyne_guard-0.1.0/.github/CODEOWNERS +8 -0
  2. mnemosyne_guard-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +43 -0
  3. mnemosyne_guard-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  4. mnemosyne_guard-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +33 -0
  5. mnemosyne_guard-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +23 -0
  6. mnemosyne_guard-0.1.0/.github/dependabot.yml +22 -0
  7. mnemosyne_guard-0.1.0/.github/workflows/ci.yml +83 -0
  8. mnemosyne_guard-0.1.0/.github/workflows/release.yml +47 -0
  9. mnemosyne_guard-0.1.0/.gitignore +45 -0
  10. mnemosyne_guard-0.1.0/.pre-commit-config.yaml +39 -0
  11. mnemosyne_guard-0.1.0/CHANGELOG.md +47 -0
  12. mnemosyne_guard-0.1.0/CITATION.cff +29 -0
  13. mnemosyne_guard-0.1.0/CODE_OF_CONDUCT.md +53 -0
  14. mnemosyne_guard-0.1.0/CONTRIBUTING.md +80 -0
  15. mnemosyne_guard-0.1.0/Dockerfile +44 -0
  16. mnemosyne_guard-0.1.0/LICENSE +202 -0
  17. mnemosyne_guard-0.1.0/Makefile +39 -0
  18. mnemosyne_guard-0.1.0/PKG-INFO +336 -0
  19. mnemosyne_guard-0.1.0/README.md +293 -0
  20. mnemosyne_guard-0.1.0/SECURITY.md +55 -0
  21. mnemosyne_guard-0.1.0/docker-compose.yml +26 -0
  22. mnemosyne_guard-0.1.0/docs/ARCHITECTURE.md +110 -0
  23. mnemosyne_guard-0.1.0/docs/NIST_CONTROL_MAPPING.md +149 -0
  24. mnemosyne_guard-0.1.0/docs/THREAT_MODEL.md +148 -0
  25. mnemosyne_guard-0.1.0/examples/README.md +19 -0
  26. mnemosyne_guard-0.1.0/examples/langchain_memory_guard.py +140 -0
  27. mnemosyne_guard-0.1.0/examples/quickstart.py +119 -0
  28. mnemosyne_guard-0.1.0/pyproject.toml +93 -0
  29. mnemosyne_guard-0.1.0/scripts/gen_nist_doc.py +81 -0
  30. mnemosyne_guard-0.1.0/src/mnemosyne/__init__.py +36 -0
  31. mnemosyne_guard-0.1.0/src/mnemosyne/api/__init__.py +1 -0
  32. mnemosyne_guard-0.1.0/src/mnemosyne/api/main.py +136 -0
  33. mnemosyne_guard-0.1.0/src/mnemosyne/cli.py +79 -0
  34. mnemosyne_guard-0.1.0/src/mnemosyne/core/__init__.py +38 -0
  35. mnemosyne_guard-0.1.0/src/mnemosyne/core/config.py +79 -0
  36. mnemosyne_guard-0.1.0/src/mnemosyne/core/exceptions.py +30 -0
  37. mnemosyne_guard-0.1.0/src/mnemosyne/core/gateway.py +417 -0
  38. mnemosyne_guard-0.1.0/src/mnemosyne/core/models.py +198 -0
  39. mnemosyne_guard-0.1.0/src/mnemosyne/detectors/__init__.py +62 -0
  40. mnemosyne_guard-0.1.0/src/mnemosyne/detectors/anomaly.py +161 -0
  41. mnemosyne_guard-0.1.0/src/mnemosyne/detectors/base.py +51 -0
  42. mnemosyne_guard-0.1.0/src/mnemosyne/detectors/injection.py +166 -0
  43. mnemosyne_guard-0.1.0/src/mnemosyne/detectors/obfuscation.py +168 -0
  44. mnemosyne_guard-0.1.0/src/mnemosyne/detectors/secrets_pii.py +111 -0
  45. mnemosyne_guard-0.1.0/src/mnemosyne/integrity/__init__.py +13 -0
  46. mnemosyne_guard-0.1.0/src/mnemosyne/integrity/audit.py +115 -0
  47. mnemosyne_guard-0.1.0/src/mnemosyne/integrity/signer.py +72 -0
  48. mnemosyne_guard-0.1.0/src/mnemosyne/nist/__init__.py +186 -0
  49. mnemosyne_guard-0.1.0/src/mnemosyne/policy/__init__.py +5 -0
  50. mnemosyne_guard-0.1.0/src/mnemosyne/policy/default_policy.yaml +64 -0
  51. mnemosyne_guard-0.1.0/src/mnemosyne/policy/engine.py +161 -0
  52. mnemosyne_guard-0.1.0/src/mnemosyne/py.typed +0 -0
  53. mnemosyne_guard-0.1.0/src/mnemosyne/store/__init__.py +17 -0
  54. mnemosyne_guard-0.1.0/src/mnemosyne/store/base.py +102 -0
  55. mnemosyne_guard-0.1.0/src/mnemosyne/store/sqlite.py +76 -0
  56. mnemosyne_guard-0.1.0/src/mnemosyne/telemetry/__init__.py +111 -0
  57. mnemosyne_guard-0.1.0/tests/conftest.py +27 -0
  58. mnemosyne_guard-0.1.0/tests/test_api.py +151 -0
  59. mnemosyne_guard-0.1.0/tests/test_detectors.py +187 -0
  60. mnemosyne_guard-0.1.0/tests/test_gateway.py +193 -0
  61. mnemosyne_guard-0.1.0/tests/test_integrity.py +60 -0
  62. mnemosyne_guard-0.1.0/tests/test_nist.py +65 -0
  63. mnemosyne_guard-0.1.0/tests/test_policy.py +198 -0
  64. mnemosyne_guard-0.1.0/tests/test_redteam_corpus.py +247 -0
  65. mnemosyne_guard-0.1.0/tests/test_store.py +119 -0
@@ -0,0 +1,8 @@
1
+ # Default owner for everything in the repo
2
+ * @rsh1k
3
+
4
+ # Security-critical surfaces deserve explicit review
5
+ /src/mnemosyne/policy/ @rsh1k
6
+ /src/mnemosyne/integrity/ @rsh1k
7
+ /src/mnemosyne/detectors/ @rsh1k
8
+ /SECURITY.md @rsh1k
@@ -0,0 +1,43 @@
1
+ name: Bug report
2
+ description: Report a defect in Mnemosyne
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for filing a bug. **Do not report security vulnerabilities here** —
9
+ see [SECURITY.md](../../SECURITY.md) for private disclosure.
10
+ - type: textarea
11
+ id: what-happened
12
+ attributes:
13
+ label: What happened?
14
+ description: A clear description of the bug and what you expected instead.
15
+ validations:
16
+ required: true
17
+ - type: textarea
18
+ id: repro
19
+ attributes:
20
+ label: Steps to reproduce
21
+ description: Minimal code or commands that reproduce the issue.
22
+ render: python
23
+ validations:
24
+ required: true
25
+ - type: input
26
+ id: version
27
+ attributes:
28
+ label: Mnemosyne version
29
+ placeholder: "0.1.0"
30
+ validations:
31
+ required: true
32
+ - type: input
33
+ id: python
34
+ attributes:
35
+ label: Python version
36
+ placeholder: "3.12"
37
+ validations:
38
+ required: true
39
+ - type: textarea
40
+ id: logs
41
+ attributes:
42
+ label: Relevant logs / traceback
43
+ render: shell
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Report a security vulnerability
4
+ url: https://github.com/rsh1k/mnemosyne/security/advisories/new
5
+ about: Please disclose vulnerabilities privately — do not open a public issue.
@@ -0,0 +1,33 @@
1
+ name: Feature request
2
+ description: Suggest a capability or improvement
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes:
8
+ label: Problem / threat
9
+ description: What gap or ASI06 attack vector does this address?
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: proposal
14
+ attributes:
15
+ label: Proposed solution
16
+ description: What should Mnemosyne do? Include detector/policy/API impact if relevant.
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: alternatives
21
+ attributes:
22
+ label: Alternatives considered
23
+ - type: checkboxes
24
+ id: scope
25
+ attributes:
26
+ label: Area
27
+ options:
28
+ - label: Detector
29
+ - label: Policy engine
30
+ - label: Integrity / audit
31
+ - label: Store / segmentation
32
+ - label: API / CLI
33
+ - label: Docs / NIST mapping
@@ -0,0 +1,23 @@
1
+ ## Summary
2
+
3
+ <!-- What does this change and why? Reference any related issue. -->
4
+
5
+ ## Type of change
6
+
7
+ - [ ] Bug fix
8
+ - [ ] New feature (detector / policy / endpoint)
9
+ - [ ] Refactor / internal
10
+ - [ ] Docs / NIST mapping
11
+
12
+ ## Security considerations
13
+
14
+ <!-- Does this touch a trust boundary? If it changes the policy, the cardinal
15
+ INSTRUCTION-surface invariant, or any detector, explain the threat rationale. -->
16
+
17
+ ## Checklist
18
+
19
+ - [ ] `make all` passes locally (ruff, mypy, bandit, pytest)
20
+ - [ ] Added/updated tests; security-relevant changes extend the red-team corpus
21
+ - [ ] The cardinal invariant (untrusted content never reaches `INSTRUCTION`) is intact
22
+ - [ ] Updated docs and, if the control catalog changed, ran `python scripts/gen_nist_doc.py`
23
+ - [ ] Updated `CHANGELOG.md`
@@ -0,0 +1,22 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "pip"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ groups:
8
+ python-dependencies:
9
+ patterns: ["*"]
10
+ labels: ["dependencies"]
11
+
12
+ - package-ecosystem: "github-actions"
13
+ directory: "/"
14
+ schedule:
15
+ interval: "weekly"
16
+ labels: ["dependencies", "ci"]
17
+
18
+ - package-ecosystem: "docker"
19
+ directory: "/"
20
+ schedule:
21
+ interval: "weekly"
22
+ labels: ["dependencies", "docker"]
@@ -0,0 +1,83 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ci-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ quality:
18
+ name: Lint, type-check & security
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: "3.12"
27
+ cache: pip
28
+
29
+ - name: Install
30
+ run: |
31
+ python -m pip install --upgrade pip
32
+ pip install -e ".[api,dev]"
33
+
34
+ - name: Ruff (lint)
35
+ run: ruff check src tests
36
+
37
+ - name: Mypy (type-check)
38
+ run: mypy
39
+
40
+ - name: Bandit (static security scan)
41
+ run: bandit -q -r src -c pyproject.toml
42
+
43
+ - name: pip-audit (dependency vulnerabilities)
44
+ run: pip-audit
45
+
46
+ - name: NIST doc is in sync with catalog
47
+ run: |
48
+ python scripts/gen_nist_doc.py
49
+ git diff --exit-code docs/NIST_CONTROL_MAPPING.md \
50
+ || (echo "::error::docs/NIST_CONTROL_MAPPING.md is stale; run 'make docs'" && exit 1)
51
+
52
+ test:
53
+ name: Tests (py${{ matrix.python-version }})
54
+ runs-on: ubuntu-latest
55
+ strategy:
56
+ fail-fast: false
57
+ matrix:
58
+ python-version: ["3.10", "3.11", "3.12"]
59
+ steps:
60
+ - uses: actions/checkout@v4
61
+
62
+ - name: Set up Python ${{ matrix.python-version }}
63
+ uses: actions/setup-python@v5
64
+ with:
65
+ python-version: ${{ matrix.python-version }}
66
+ cache: pip
67
+
68
+ - name: Install
69
+ run: |
70
+ python -m pip install --upgrade pip
71
+ pip install -e ".[api,dev]"
72
+
73
+ - name: Run tests
74
+ run: pytest -q
75
+
76
+ docker:
77
+ name: Build container image
78
+ runs-on: ubuntu-latest
79
+ needs: [quality, test]
80
+ steps:
81
+ - uses: actions/checkout@v4
82
+ - name: Build image
83
+ run: docker build -t mnemosyne-guard:ci .
@@ -0,0 +1,47 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ build:
13
+ name: Build distributions
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.12"
20
+ - name: Build sdist and wheel
21
+ run: |
22
+ python -m pip install --upgrade pip build
23
+ python -m build
24
+ - name: Check metadata
25
+ run: |
26
+ pip install twine
27
+ twine check dist/*
28
+ - uses: actions/upload-artifact@v4
29
+ with:
30
+ name: dist
31
+ path: dist/
32
+
33
+ publish:
34
+ name: Publish to PyPI
35
+ needs: build
36
+ runs-on: ubuntu-latest
37
+ # Requires a configured PyPI "Trusted Publisher" for this repo + environment.
38
+ environment: release
39
+ permissions:
40
+ id-token: write # OIDC for trusted publishing; no API token needed
41
+ steps:
42
+ - uses: actions/download-artifact@v4
43
+ with:
44
+ name: dist
45
+ path: dist/
46
+ - name: Publish
47
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,45 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .eggs/
11
+ *.egg
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ env/
17
+ ENV/
18
+
19
+ # Test / coverage / type-check caches
20
+ .pytest_cache/
21
+ .ruff_cache/
22
+ .mypy_cache/
23
+ .coverage
24
+ .coverage.*
25
+ htmlcov/
26
+ coverage.xml
27
+
28
+ # Runtime artifacts
29
+ *.db
30
+ *.sqlite
31
+ *.sqlite3
32
+ *.log
33
+ audit.jsonl
34
+
35
+ # Secrets / local env (never commit)
36
+ .env
37
+ .env.*
38
+ *.pem
39
+ *.key
40
+
41
+ # Editor / OS
42
+ .idea/
43
+ .vscode/
44
+ *.swp
45
+ .DS_Store
@@ -0,0 +1,39 @@
1
+ # Mnemosyne pre-commit hooks. Install with: pre-commit install
2
+ # Mirrors the CI quality gate so issues are caught before they are pushed.
3
+ minimum_pre_commit_version: "3.5.0"
4
+
5
+ repos:
6
+ - repo: https://github.com/pre-commit/pre-commit-hooks
7
+ rev: v4.6.0
8
+ hooks:
9
+ - id: trailing-whitespace
10
+ - id: end-of-file-fixer
11
+ - id: check-yaml
12
+ - id: check-toml
13
+ - id: check-added-large-files
14
+ - id: check-merge-conflict
15
+ - id: detect-private-key
16
+
17
+ - repo: https://github.com/astral-sh/ruff-pre-commit
18
+ rev: v0.6.9
19
+ hooks:
20
+ - id: ruff
21
+ args: [--fix]
22
+ - id: ruff-format
23
+
24
+ - repo: https://github.com/pre-commit/mirrors-mypy
25
+ rev: v1.11.2
26
+ hooks:
27
+ - id: mypy
28
+ additional_dependencies:
29
+ - pydantic>=2
30
+ - pydantic-settings
31
+ args: ["--config-file=pyproject.toml"]
32
+ pass_filenames: false
33
+
34
+ - repo: https://github.com/PyCQA/bandit
35
+ rev: 1.7.10
36
+ hooks:
37
+ - id: bandit
38
+ args: ["-c", "pyproject.toml", "-r", "src"]
39
+ pass_filenames: false
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format is based on
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
5
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2026-06-13
10
+
11
+ ### Added
12
+ - **Memory-integrity gateway** with two guarded operations, `guard_write` and
13
+ `guard_read`, enforcing the cardinal ASI06 invariant: content below the
14
+ `TRUSTED` tier can never reach an `INSTRUCTION` (control-plane) surface.
15
+ - **Provenance → trust-tier** resolution and **surface**-aware policy
16
+ (`INSTRUCTION` / `KNOWLEDGE` / `EPISODIC` / `SCRATCH`).
17
+ - **Detectors:**
18
+ - `injection` — instruction-override, role-reassignment, persistence,
19
+ tooling/config manipulation, exfiltration, delimiter smuggling, and
20
+ **delayed/conditional execution** (Gemini-style "delayed tool invocation").
21
+ - `secrets_pii` — cloud/provider keys, JWTs, private keys, and PII with
22
+ Luhn-checked card detection; redaction helper.
23
+ - `anomaly` — size/entropy checks plus a per-writer behavioral baseline with a
24
+ robust MAD z-score for gradual-erosion ("sleeper agent") detection.
25
+ - `obfuscation` — invisible-Unicode smuggling: Unicode Tag characters,
26
+ bidirectional overrides (Trojan Source), and zero-width interleaving, with
27
+ emoji-ZWJ awareness and a `strip()` sanitiser.
28
+ - **Declarative YAML policy engine** (most-restrictive-wins) with a secure
29
+ default policy.
30
+ - **Integrity:** HMAC-SHA256 record signing (constant-time verify, KMS/HSM hook)
31
+ and a hash-chained, tamper-evident audit log with chain verification.
32
+ - **Storage:** `MemoryStore` / `QuarantineStore` protocols with in-memory and
33
+ SQLite backends; namespace segmentation; human-in-the-loop quarantine
34
+ promotion that elevates trust to the target surface's requirement.
35
+ - **FastAPI sidecar** (bearer auth) and `mnemosyne` **CLI** (`scan`/`nist`/`version`).
36
+ - **NIST/OWASP control catalog** (MN-01…MN-11) mapping to NIST SP 800-53 Rev 5,
37
+ SP 800-218A, AI 600-1, and CSF 2.0; surfaced via `GET /v1/compliance`,
38
+ `mnemosyne nist`, and a generated `docs/NIST_CONTROL_MAPPING.md`.
39
+ - **Telemetry:** structured JSON logging and Prometheus metrics.
40
+ - **Tests:** 131 tests including a red-team corpus that asserts 100% detection
41
+ of the bundled ASI06 payloads and a 0% false-positive rate on benign writes.
42
+ - **Tooling & ops:** ruff, mypy, bandit, pip-audit, pre-commit, GitHub Actions
43
+ CI (lint/type/security/test matrix + doc-sync check), Dockerfile,
44
+ docker-compose, and a release workflow.
45
+
46
+ [Unreleased]: https://github.com/rsh1k/mnemosyne/compare/v0.1.0...HEAD
47
+ [0.1.0]: https://github.com/rsh1k/mnemosyne/releases/tag/v0.1.0
@@ -0,0 +1,29 @@
1
+ cff-version: 1.2.0
2
+ title: "Mnemosyne: A NIST-aligned Memory Integrity & Context-Provenance Firewall for Agentic AI"
3
+ message: "If you use this software, please cite it using these metadata."
4
+ type: software
5
+ authors:
6
+ - name: "rsh1k"
7
+ alias: rsh1k
8
+ repository-code: "https://github.com/rsh1k/mnemosyne"
9
+ url: "https://github.com/rsh1k/mnemosyne"
10
+ abstract: >-
11
+ Mnemosyne is a defense-in-depth library and gateway service that protects the
12
+ persistent memory and context surfaces of agentic AI systems against OWASP
13
+ ASI06 (Memory & Context Poisoning). It enforces a provenance-to-trust-tier
14
+ invariant that prevents untrusted content from reaching instruction
15
+ (control-plane) surfaces, runs pluggable detectors (injection, secrets/PII,
16
+ statistical anomaly, and invisible-Unicode obfuscation), signs records with
17
+ HMAC-SHA256, keeps a hash-chained tamper-evident audit log, and maps its
18
+ controls to NIST SP 800-53, SP 800-218A, AI 600-1, and CSF 2.0.
19
+ keywords:
20
+ - ai-security
21
+ - agentic-ai
22
+ - owasp
23
+ - asi06
24
+ - memory-poisoning
25
+ - prompt-injection
26
+ - nist
27
+ license: Apache-2.0
28
+ version: 0.1.0
29
+ date-released: "2026-06-13"
@@ -0,0 +1,53 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment include
18
+ demonstrating empathy and kindness, being respectful of differing opinions,
19
+ giving and gracefully accepting constructive feedback, accepting responsibility
20
+ and apologizing to those affected by our mistakes, and focusing on what is best
21
+ for the overall community.
22
+
23
+ Unacceptable behavior includes the use of sexualized language or imagery,
24
+ trolling, insulting or derogatory comments, public or private harassment,
25
+ publishing others' private information without explicit permission, and other
26
+ conduct which could reasonably be considered inappropriate in a professional
27
+ setting.
28
+
29
+ ## Enforcement Responsibilities
30
+
31
+ Community leaders are responsible for clarifying and enforcing our standards and
32
+ will take appropriate and fair corrective action in response to any behavior
33
+ they deem inappropriate, threatening, offensive, or harmful.
34
+
35
+ ## Scope
36
+
37
+ This Code of Conduct applies within all community spaces and also applies when
38
+ an individual is officially representing the community in public spaces.
39
+
40
+ ## Enforcement
41
+
42
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
43
+ reported to the community leaders responsible for enforcement via the contact
44
+ listed in the repository profile. All complaints will be reviewed and
45
+ investigated promptly and fairly.
46
+
47
+ ## Attribution
48
+
49
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
50
+ version 2.1, available at
51
+ <https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>.
52
+
53
+ [homepage]: https://www.contributor-covenant.org
@@ -0,0 +1,80 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest in improving Mnemosyne. This project guards a security
4
+ boundary, so contributions are held to a high bar for tests and clarity.
5
+
6
+ ## Development setup
7
+
8
+ ```bash
9
+ git clone https://github.com/rsh1k/mnemosyne.git
10
+ cd mnemosyne
11
+ python -m venv .venv && source .venv/bin/activate
12
+ pip install -e ".[api,dev]"
13
+ pre-commit install
14
+ ```
15
+
16
+ ## The golden rule
17
+
18
+ Every change is checked by `make all` (lint, type-check, security scan, tests).
19
+ CI runs the same targets. Run it locally before opening a PR:
20
+
21
+ ```bash
22
+ make all
23
+ ```
24
+
25
+ Individual targets:
26
+
27
+ ```bash
28
+ make test # pytest
29
+ make lint # ruff
30
+ make typecheck # mypy
31
+ make security # bandit + pip-audit
32
+ ```
33
+
34
+ ## Tests are mandatory
35
+
36
+ - New detectors, policy rules, or gateway behaviour **must** come with tests.
37
+ - Security-relevant changes should extend the **red-team corpus**
38
+ (`tests/test_redteam_corpus.py`). If you add a detection capability, add the
39
+ attack payloads it catches; if you relax something, prove benign writes still
40
+ pass. The aggregate detection-rate / false-positive-rate assertions must stay
41
+ green.
42
+ - The cardinal invariant (untrusted content never reaches the `INSTRUCTION`
43
+ surface) is sacred. A PR that weakens it will not be merged without an
44
+ explicit, documented security rationale.
45
+
46
+ ## Adding a detector
47
+
48
+ 1. Implement the `Detector` protocol in `src/mnemosyne/detectors/`.
49
+ 2. Return a `ScanResult` of `Finding`s with a `severity`, a `score` in `[0,1]`,
50
+ and a `metadata["kind"]` (use `secret`/`pii` only for sensitive-data findings
51
+ — the policy engine routes those through the dedicated secrets rule).
52
+ 3. Register it in `default_registry()` (or document it as opt-in).
53
+ 4. Add unit tests and, where relevant, corpus entries.
54
+
55
+ ## Changing policy
56
+
57
+ The default posture lives in `src/mnemosyne/policy/default_policy.yaml`. It is
58
+ security-critical configuration — explain the threat rationale in the PR. Keep
59
+ "most restrictive wins" intact.
60
+
61
+ ## Updating the NIST mapping
62
+
63
+ The catalog in `src/mnemosyne/nist/__init__.py` is the single source of truth.
64
+ After editing it, regenerate the doc:
65
+
66
+ ```bash
67
+ python scripts/gen_nist_doc.py
68
+ ```
69
+
70
+ ## Style
71
+
72
+ - Code is formatted/linted by `ruff` (line length 100) and type-checked by
73
+ `mypy`. Public functions get type hints and a docstring explaining the *why*.
74
+ - Prefer clarity over cleverness; this is security code that will be audited.
75
+
76
+ ## Commit / PR hygiene
77
+
78
+ - Small, focused PRs with a clear description of the threat or behaviour changed.
79
+ - Reference any related issue.
80
+ - By contributing you agree your contributions are licensed under Apache-2.0.
@@ -0,0 +1,44 @@
1
+ # syntax=docker/dockerfile:1
2
+
3
+ # ---- builder ---------------------------------------------------------------
4
+ FROM python:3.12-slim AS builder
5
+
6
+ ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
7
+ PIP_NO_CACHE_DIR=1
8
+
9
+ WORKDIR /build
10
+ COPY pyproject.toml README.md ./
11
+ COPY src ./src
12
+
13
+ # Build a wheel so the runtime image installs a clean, pinned artifact.
14
+ RUN pip install --upgrade pip build && python -m build --wheel --outdir /dist
15
+
16
+ # ---- runtime ---------------------------------------------------------------
17
+ FROM python:3.12-slim AS runtime
18
+
19
+ ENV PYTHONDONTWRITEBYTECODE=1 \
20
+ PYTHONUNBUFFERED=1 \
21
+ PIP_DISABLE_PIP_VERSION_CHECK=1 \
22
+ PIP_NO_CACHE_DIR=1
23
+
24
+ # Create an unprivileged user to run the service.
25
+ RUN groupadd --system mnemosyne && useradd --system --gid mnemosyne --create-home mnemosyne
26
+
27
+ WORKDIR /app
28
+ COPY --from=builder /dist/*.whl /tmp/
29
+ RUN pip install /tmp/*.whl "mnemosyne-guard[api]" && rm -f /tmp/*.whl
30
+
31
+ # Drop privileges.
32
+ USER mnemosyne
33
+
34
+ EXPOSE 8000
35
+
36
+ # NOTE: provide a real key at runtime, e.g.
37
+ # docker run -e MNEMOSYNE_INTEGRITY_KEY=... -e MNEMOSYNE_API_KEYS=... ...
38
+ ENV MNEMOSYNE_LOG_JSON=true
39
+
40
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
41
+ CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/healthz').status==200 else 1)"
42
+
43
+ ENTRYPOINT ["uvicorn", "mnemosyne.api.main:factory", "--factory", \
44
+ "--host", "0.0.0.0", "--port", "8000"]