forked from phasespace-labs/palinode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
146 lines (137 loc) · 6.36 KB
/
Copy pathpyproject.toml
File metadata and controls
146 lines (137 loc) · 6.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
[build-system]
requires = ["setuptools>=61.0.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "palinode"
version = "0.14.0"
description = "The memory substrate for AI agents and developer tools. Git-versioned, file-native, MCP-first."
authors = [
{name = "Paul Kyle", email = "paul@phasespace.co"}
]
readme = "README.md"
license = {text = "MIT"}
requires-python = ">=3.11"
keywords = ["ai", "agents", "memory", "mcp", "llm", "rag", "knowledge-management"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Topic :: Software Development :: Libraries :: Python Modules",
]
dependencies = [
# Lower bounds set to versions that exclude all known CVEs against these packages
# as of 2026-04-30. See PR description for CVE-to-version mapping.
"sqlite-vec>=0.1.6", # CVE-2024-46488 fixed in 0.1.6
"watchdog>=4.0",
"pyyaml>=6.0,<7.0", # 5.x has multiple RCE/parser CVEs
"httpx>=0.27", # older versions had input-validation CVEs
"python-frontmatter>=1.1",
"fastapi>=0.115,<0.137", # older: CSRF/ReDoS CVEs. Cap <0.137: 0.137.1 regressed include_router (routes not added to app → routeless API). 0.136.x is the last good line.
"uvicorn>=0.32", # 0.11.x had log-injection / response-splitting CVEs
"pydantic>=2.7,<3.0", # 1.x and pre-2.4 had ReDoS / infinity-loop CVEs
# Upper bound is load-bearing: mcp 2.0.0 (2026-07-28) removed both
# Server.list_tools and Server.call_tool, the decorators palinode/mcp.py is
# built on, so an uncapped range installs a server that cannot start.
# Lower bound: earlier versions carry DNS rebinding / FastMCP DoS /
# Streamable HTTP DoS CVEs. Lift the cap only with the 2.x migration.
"mcp>=2,<3", # 2.x server API. Upper bound is deliberate: 1.10 was
# declared unbounded and pip resolved it to a 2.0 that
# removed the decorators, breaking every fresh install.
"rich>=13.7",
"click>=8.1",
"jinja2>=3.1.5", # provenance UI templating; 3.1.5 fixes sandbox-escape CVEs
"markdown-it-py>=3.0", # provenance UI: render memory bodies (html disabled)
"nh3>=0.2.18", # provenance UI: HTML sanitizer (ammonia); XSS backstop
]
[project.urls]
"Homepage" = "https://github.com/phasespace-labs/palinode"
"Documentation" = "https://github.com/phasespace-labs/palinode/tree/main/docs"
"Repository" = "https://github.com/phasespace-labs/palinode"
"Issues" = "https://github.com/phasespace-labs/palinode/issues"
"Changelog" = "https://github.com/phasespace-labs/palinode/blob/main/docs/CHANGELOG.md"
"Privacy" = "https://github.com/phasespace-labs/palinode/blob/main/PRIVACY.md"
[project.scripts]
palinode-watcher = "palinode.indexer.watcher:main"
palinode-api = "palinode.api.server:main"
palinode = "palinode.cli:main"
palinode-mcp = "palinode.mcp:main"
palinode-mcp-http = "palinode.mcp:main_http"
palinode-mcp-sse = "palinode.mcp:main_sse" # deprecated alias for main_http
[project.optional-dependencies]
dev = [
"pytest",
"pytest-asyncio",
"pytest-timeout",
"ruff",
"bandit"
]
[tool.ruff.lint]
# Deliberately narrow: bug-classes only, no formatting opinions. CI runs
# `ruff check palinode/ tests/ scripts/` and gates on it, so this set has to
# stay at zero — every rule here is one that catches a defect, not a style.
#
# F pyflakes — undefined names, unused imports/vars (found the
# `palinode config edit` NameError this config landed with)
# B bugbear — mutable defaults, loop-variable closures, zip() misuse
# E7 statements — bare `except:`, ambiguous names like `l`
# E9 runtime — syntax/IO errors that break collection
#
# NOT enabled, with reasons — revisit deliberately, not by widening `select`:
# E501 line-too-long (1373 hits) — this codebase uses long lines for MCP
# schema descriptions on purpose; a formatter's job, not a linter's.
# I001 unsorted-imports (220) — pure churn; would collide with the
# `merge=union` CHANGELOG/diff discipline for no defect caught.
# W291/W293 whitespace (253) — same; belongs to `ruff format` if adopted.
# E402 import-not-at-top (43) — several are deliberate lazy imports that
# keep CLI startup fast.
# UP pyupgrade (~100) — modernization, not correctness. Separate PR.
select = ["F", "B", "E7", "E9"]
# B904 (raise ... from err) is 39 sites needing per-site judgment about which
# exceptions to chain. Worth doing; not worth blocking this PR on.
ignore = ["B904"]
[tool.bandit]
# Bandit static security analysis configuration. CI runs `bandit -r palinode/ -ll`
# (medium+ severity); these settings make local-invocation behavior match CI.
# All in-tree findings are triaged inline with `# nosec B<rule>: <rationale>` —
# do NOT add wholesale rule skips here without a specific justification.
exclude_dirs = ["tests", ".venv", "build", "dist"]
[tool.pytest.ini_options]
testpaths = ["tests"]
# Exclude live tests from default runs (they need a running server)
addopts = "--ignore=tests/live"
pythonpath = ["."]
markers = [
"slow: marks tests that need Ollama or take >5s",
"doctor_real_search_roots: allow a test to exercise doctor's built-in filesystem root discovery",
]
asyncio_mode = "strict"
timeout = 60
timeout_method = "thread"
[tool.setuptools]
packages = [
"palinode",
"palinode.api",
"palinode.api.routers",
"palinode.api.ui",
"palinode.cli",
"palinode.consolidation",
"palinode.core",
"palinode.diagnostics",
"palinode.diagnostics.checks",
"palinode.import_",
"palinode.indexer",
"palinode.ingest",
"palinode.lint",
"palinode.migration",
]
[tool.setuptools.package-data]
# Ship the provenance UI's Jinja2 templates and static assets inside the wheel
# (offline-first — no CDN). Without this, an installed wheel has the UI Python
# but no templates/CSS and the router 500s at first render.
"palinode.api.ui" = ["templates/*.html", "static/*.css"]