descry-codegraph 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.
- descry_codegraph-0.1.0/.github/workflows/ci.yml +76 -0
- descry_codegraph-0.1.0/.github/workflows/release.yml +123 -0
- descry_codegraph-0.1.0/.gitignore +23 -0
- descry_codegraph-0.1.0/CHANGELOG.md +30 -0
- descry_codegraph-0.1.0/CLAUDE.md +69 -0
- descry_codegraph-0.1.0/LICENSE +21 -0
- descry_codegraph-0.1.0/PKG-INFO +345 -0
- descry_codegraph-0.1.0/README.md +280 -0
- descry_codegraph-0.1.0/SECURITY.md +27 -0
- descry_codegraph-0.1.0/justfile +47 -0
- descry_codegraph-0.1.0/pi-extension/README.md +55 -0
- descry_codegraph-0.1.0/pi-extension/descry-cli.py +250 -0
- descry_codegraph-0.1.0/pi-extension/descry-tools.ts +441 -0
- descry_codegraph-0.1.0/pyproject.toml +65 -0
- descry_codegraph-0.1.0/src/descry/__init__.py +4 -0
- descry_codegraph-0.1.0/src/descry/_env.py +30 -0
- descry_codegraph-0.1.0/src/descry/_graph.py +36 -0
- descry_codegraph-0.1.0/src/descry/ast_grep.py +382 -0
- descry_codegraph-0.1.0/src/descry/cli.py +457 -0
- descry_codegraph-0.1.0/src/descry/cross_lang.py +404 -0
- descry_codegraph-0.1.0/src/descry/embeddings.py +593 -0
- descry_codegraph-0.1.0/src/descry/generate.py +3579 -0
- descry_codegraph-0.1.0/src/descry/git_history.py +1631 -0
- descry_codegraph-0.1.0/src/descry/handlers.py +1907 -0
- descry_codegraph-0.1.0/src/descry/mcp_server.py +355 -0
- descry_codegraph-0.1.0/src/descry/query.py +2345 -0
- descry_codegraph-0.1.0/src/descry/scip/__init__.py +0 -0
- descry_codegraph-0.1.0/src/descry/scip/cache.py +1047 -0
- descry_codegraph-0.1.0/src/descry/scip/parser.py +531 -0
- descry_codegraph-0.1.0/src/descry/scip/pb2.py +92 -0
- descry_codegraph-0.1.0/src/descry/scip/support.py +174 -0
- descry_codegraph-0.1.0/src/descry/tree_sitter_parser.py +356 -0
- descry_codegraph-0.1.0/src/descry/web/__init__.py +0 -0
- descry_codegraph-0.1.0/src/descry/web/server.py +1457 -0
- descry_codegraph-0.1.0/src/descry/web/web/index.html +2444 -0
- descry_codegraph-0.1.0/src/descry/web/web/style.css +1791 -0
- descry_codegraph-0.1.0/tests/__init__.py +0 -0
- descry_codegraph-0.1.0/tests/conftest.py +29 -0
- descry_codegraph-0.1.0/tests/fixtures/small_graph.json +131 -0
- descry_codegraph-0.1.0/tests/test_cli.py +66 -0
- descry_codegraph-0.1.0/tests/test_config.py +393 -0
- descry_codegraph-0.1.0/tests/test_generate.py +859 -0
- descry_codegraph-0.1.0/tests/test_git_history.py +223 -0
- descry_codegraph-0.1.0/tests/test_handlers.py +253 -0
- descry_codegraph-0.1.0/tests/test_hardening.py +346 -0
- descry_codegraph-0.1.0/tests/test_mcp.py +96 -0
- descry_codegraph-0.1.0/tests/test_query.py +809 -0
- descry_codegraph-0.1.0/tests/test_scip.py +319 -0
- descry_codegraph-0.1.0/tests/test_tree_sitter_parser.py +125 -0
- descry_codegraph-0.1.0/tests/test_web_server.py +210 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
# Default to least-privilege; jobs that need more must opt in explicitly.
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
lint:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
18
|
+
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
19
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
- run: uv pip install --system ruff
|
|
23
|
+
- run: ruff check src/ tests/
|
|
24
|
+
- run: ruff format --check src/ tests/
|
|
25
|
+
|
|
26
|
+
test:
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
strategy:
|
|
29
|
+
matrix:
|
|
30
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
33
|
+
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
34
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
35
|
+
with:
|
|
36
|
+
python-version: ${{ matrix.python-version }}
|
|
37
|
+
- run: uv venv .venv
|
|
38
|
+
- run: . .venv/bin/activate && uv pip install -e ".[dev]"
|
|
39
|
+
env:
|
|
40
|
+
DESCRY_NO_EMBEDDINGS: "1"
|
|
41
|
+
- run: . .venv/bin/activate && python -m pytest tests/ -v
|
|
42
|
+
env:
|
|
43
|
+
DESCRY_NO_EMBEDDINGS: "1"
|
|
44
|
+
DESCRY_NO_SCIP: "1"
|
|
45
|
+
|
|
46
|
+
build:
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
50
|
+
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
51
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
52
|
+
with:
|
|
53
|
+
python-version: "3.12"
|
|
54
|
+
- run: uv build
|
|
55
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
56
|
+
with:
|
|
57
|
+
name: dist
|
|
58
|
+
path: dist/
|
|
59
|
+
|
|
60
|
+
audit:
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
64
|
+
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
65
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
66
|
+
with:
|
|
67
|
+
python-version: "3.12"
|
|
68
|
+
- name: Install descry[all] + pip-audit
|
|
69
|
+
run: |
|
|
70
|
+
uv venv .venv
|
|
71
|
+
. .venv/bin/activate
|
|
72
|
+
uv pip install -e ".[all]" pip-audit
|
|
73
|
+
- name: Audit resolved environment
|
|
74
|
+
run: |
|
|
75
|
+
. .venv/bin/activate
|
|
76
|
+
pip-audit --skip-editable
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
target:
|
|
10
|
+
description: "Publish target"
|
|
11
|
+
type: choice
|
|
12
|
+
required: true
|
|
13
|
+
default: testpypi
|
|
14
|
+
options:
|
|
15
|
+
- testpypi
|
|
16
|
+
- pypi
|
|
17
|
+
|
|
18
|
+
# Default to least-privilege. Only the publish jobs opt into id-token: write
|
|
19
|
+
# for OIDC trusted publishing.
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
build:
|
|
25
|
+
name: Build distributions
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
29
|
+
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
30
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.12"
|
|
33
|
+
- name: Verify tag matches pyproject version
|
|
34
|
+
if: github.event_name == 'push'
|
|
35
|
+
env:
|
|
36
|
+
GIT_TAG: ${{ github.ref_name }}
|
|
37
|
+
run: |
|
|
38
|
+
PKG_VERSION=$(python -c "import tomllib; print(tomllib.loads(open('pyproject.toml','rb').read().decode())['project']['version'])")
|
|
39
|
+
TAG_VERSION="${GIT_TAG#v}"
|
|
40
|
+
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
|
|
41
|
+
echo "::error::tag $GIT_TAG does not match pyproject version $PKG_VERSION"
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
- name: Build sdist + wheel
|
|
45
|
+
run: uv build
|
|
46
|
+
- name: Check distributions with twine
|
|
47
|
+
run: |
|
|
48
|
+
uv pip install --system twine
|
|
49
|
+
twine check --strict dist/*
|
|
50
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
51
|
+
with:
|
|
52
|
+
name: dist
|
|
53
|
+
path: dist/
|
|
54
|
+
|
|
55
|
+
audit:
|
|
56
|
+
name: Security audit
|
|
57
|
+
needs: build
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
61
|
+
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
62
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
63
|
+
with:
|
|
64
|
+
python-version: "3.12"
|
|
65
|
+
- name: Install descry[all] + pip-audit
|
|
66
|
+
run: |
|
|
67
|
+
uv venv .venv
|
|
68
|
+
. .venv/bin/activate
|
|
69
|
+
uv pip install -e ".[all]" pip-audit
|
|
70
|
+
- name: Audit resolved environment
|
|
71
|
+
run: |
|
|
72
|
+
. .venv/bin/activate
|
|
73
|
+
pip-audit --skip-editable
|
|
74
|
+
|
|
75
|
+
publish-testpypi:
|
|
76
|
+
name: Publish to TestPyPI
|
|
77
|
+
needs: [build, audit]
|
|
78
|
+
if: github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'testpypi'
|
|
79
|
+
runs-on: ubuntu-latest
|
|
80
|
+
environment:
|
|
81
|
+
name: testpypi
|
|
82
|
+
url: https://test.pypi.org/p/descry-codegraph
|
|
83
|
+
permissions:
|
|
84
|
+
id-token: write
|
|
85
|
+
steps:
|
|
86
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
87
|
+
with:
|
|
88
|
+
name: dist
|
|
89
|
+
path: dist/
|
|
90
|
+
- name: Publish to TestPyPI via OIDC
|
|
91
|
+
# NOTE: this is a Docker container action — its GHCR image is only
|
|
92
|
+
# tagged with release refs, never commit SHAs. Pinning to a commit
|
|
93
|
+
# SHA here fails with "manifest unknown" because no image at that
|
|
94
|
+
# digest exists. Pinning to the version tag is the documented
|
|
95
|
+
# approach; PyPA controls this tag and tag mutation would be a
|
|
96
|
+
# notable event we'd catch via the trusted-publisher audit log.
|
|
97
|
+
uses: pypa/gh-action-pypi-publish@v1.14.0
|
|
98
|
+
with:
|
|
99
|
+
repository-url: https://test.pypi.org/legacy/
|
|
100
|
+
|
|
101
|
+
publish-pypi:
|
|
102
|
+
name: Publish to PyPI
|
|
103
|
+
needs: [build, audit]
|
|
104
|
+
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'pypi')
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
environment:
|
|
107
|
+
name: pypi
|
|
108
|
+
url: https://pypi.org/p/descry-codegraph
|
|
109
|
+
permissions:
|
|
110
|
+
id-token: write
|
|
111
|
+
steps:
|
|
112
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
113
|
+
with:
|
|
114
|
+
name: dist
|
|
115
|
+
path: dist/
|
|
116
|
+
- name: Publish to PyPI via OIDC
|
|
117
|
+
# NOTE: this is a Docker container action — its GHCR image is only
|
|
118
|
+
# tagged with release refs, never commit SHAs. Pinning to a commit
|
|
119
|
+
# SHA here fails with "manifest unknown" because no image at that
|
|
120
|
+
# digest exists. Pinning to the version tag is the documented
|
|
121
|
+
# approach; PyPA controls this tag and tag mutation would be a
|
|
122
|
+
# notable event we'd catch via the trusted-publisher audit log.
|
|
123
|
+
uses: pypa/gh-action-pypi-publish@v1.14.0
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
*.egg-info/
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
.eggs/
|
|
9
|
+
*.egg
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
env/
|
|
13
|
+
.env
|
|
14
|
+
.descry_cache/
|
|
15
|
+
.codegraph_cache/
|
|
16
|
+
*.scip
|
|
17
|
+
target/
|
|
18
|
+
node_modules/
|
|
19
|
+
.pytest_cache/
|
|
20
|
+
.ruff_cache/
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
uv.lock
|
|
23
|
+
.playwright-mcp/
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Descry will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to pre-1.0 semver (minor-version bumps may include breaking changes; see README versioning stance).
|
|
6
|
+
|
|
7
|
+
## [0.1.0] — 2026-04-16
|
|
8
|
+
|
|
9
|
+
Initial public PyPI release. Descry is a polyglot codebase knowledge graph toolkit with three interfaces: CLI (`descry`), MCP server (`descry-mcp`), and local web UI (`descry-web`).
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
- **Indexer**: Parses Rust, Python, TypeScript, JavaScript, and Svelte into a cached knowledge graph of symbols (functions, classes, constants) and edges (calls, imports, defines).
|
|
14
|
+
- **SCIP integration**: Optional type-aware call resolution via `rust-analyzer` and `scip-typescript`; regex fallback otherwise.
|
|
15
|
+
- **Semantic search**: Optional embeddings via sentence-transformers (Jina code embeddings by default; model pinned by revision).
|
|
16
|
+
- **18 MCP tools**: search, callers, callees, context, flow, path, impls, structure, flatten, cross-lang (preview), churn, evolution, changes, semantic, quick, index, status, ensure, health.
|
|
17
|
+
- **Web UI**: Starlette + Alpine.js; 20+ UI panels for browsing the graph visually.
|
|
18
|
+
- **Configuration**: `.descry.toml` + env-var overrides for cache dir, timeouts, embedding model, SCIP toolchain, excluded dirs.
|
|
19
|
+
|
|
20
|
+
### Security
|
|
21
|
+
|
|
22
|
+
- Git argument injection hardening on all user-controlled inputs (commit ranges, symbol names, file paths, pathspecs).
|
|
23
|
+
- Safe embedding-cache storage (JSON sidecar + safe-mode numpy load) with atomic writes and content-addressed cache keys.
|
|
24
|
+
- Default embedding model revision pinned for supply-chain integrity; `trust_remote_code` defaults to `False` for user-supplied models.
|
|
25
|
+
- TOML-sourced subprocess args (scip toolchain, extra args, embedding model path) are validated.
|
|
26
|
+
- Subprocess env sanitized against known credential patterns.
|
|
27
|
+
- Web UI path traversal containment on `/api/source` + regular-file / size / text-file checks.
|
|
28
|
+
- MCP `descry_index(path=...)` restricted to project root.
|
|
29
|
+
- Graph JSON carries `schema_version`; mismatched graphs are rejected with an actionable error.
|
|
30
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
Development uses `uv` + `just`. The `justfile` wraps all common tasks — prefer it over raw commands:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
just install # uv venv .venv + uv pip install -e ".[dev]"
|
|
11
|
+
just test # pytest tests/
|
|
12
|
+
just test-v # pytest tests/ -v
|
|
13
|
+
just lint # ruff check src/ tests/
|
|
14
|
+
just fmt # ruff format src/ tests/
|
|
15
|
+
just clean # remove .descry_cache, dist, caches, __pycache__
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Run a single test or filter:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
just test tests/test_handlers.py # one file
|
|
22
|
+
just test tests/test_handlers.py::test_index # one test
|
|
23
|
+
just test -k "cross_lang and not slow" # by expression
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Python 3.11+ required (enforced by `pyproject.toml`). Pre-commit gate: `just lint && just fmt && just test` all pass (195 tests currently — a drop is a regression signal).
|
|
27
|
+
|
|
28
|
+
Invoke the tool while developing:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
just index # descry index on current project
|
|
32
|
+
just health # descry health
|
|
33
|
+
just web # descry-web, http://127.0.0.1:8787
|
|
34
|
+
just mcp # descry-mcp (stdio transport)
|
|
35
|
+
just search <query>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Packaging: `pyproject.toml` defines four console scripts — `descry`, `descry-mcp`, `descry-generate`, `descry-web` — each a thin entry point into `src/descry/`.
|
|
39
|
+
|
|
40
|
+
## Architecture
|
|
41
|
+
|
|
42
|
+
**One service, three interfaces.** `DescryService` in `src/descry/handlers.py` owns all business logic. `cli.py`, `mcp_server.py`, and `web/server.py` are thin wrappers that parse their protocol's input, call a service method, and format the output. When adding a feature, implement it as a service method first — the interfaces then expose it with minimal glue.
|
|
43
|
+
|
|
44
|
+
**Two graph phases:**
|
|
45
|
+
|
|
46
|
+
1. **Generate** (`generate.py`, invoked via `descry index` or `descry-generate`) — walks the project, parses source files with regex + AST + optional ast-grep, optionally runs SCIP indexers (rust-analyzer, scip-typescript) for type-aware call resolution, optionally builds embeddings. Writes `.descry_cache/codebase_graph.json`.
|
|
47
|
+
2. **Query** (`query.py` → `GraphQuerier`) — loads the cached graph and answers callers/callees/flow/path/context queries. All service methods lazy-load the querier; freshness is tracked by graph file mtime.
|
|
48
|
+
|
|
49
|
+
**Graph schema is versioned.** `src/descry/_graph.py` exports `CURRENT_SCHEMA` (currently `1`) and `load_graph_with_schema()`. Every graph-consuming code path must load via this helper — it raises `GraphSchemaError` on mismatch so stale graphs are rejected rather than silently producing wrong results. If you change the graph shape in a breaking way, bump `CURRENT_SCHEMA`.
|
|
50
|
+
|
|
51
|
+
**Config is layered.** `DescryConfig.from_env()` builds config in three ordered steps: `auto_detect()` walks up from cwd looking for project markers (`.git`, `Cargo.toml`, `package.json`, `pyproject.toml`, `.descry.toml`) → `_apply_toml()` merges `.descry.toml` → env vars (`DESCRY_CACHE_DIR`, `DESCRY_NO_SCIP`, `DESCRY_NO_EMBEDDINGS`, `DESCRY_LOG_LEVEL`) override. All four entry points (CLI, MCP, web, `descry-generate`) construct config this way — don't add an alternate path.
|
|
52
|
+
|
|
53
|
+
**Optional modules degrade gracefully.** `scip/`, `embeddings.py`, `cross_lang.py`, and `git_history.py` are all imported via `_try_import_*` helpers in `handlers.py`. Missing optional deps (e.g. `sentence-transformers`, `scip-typescript` binary) must never crash the service — the feature becomes unavailable instead. Preserve this when touching imports.
|
|
54
|
+
|
|
55
|
+
**MCP transport uses stdout.** `mcp_server.py` logs to `stderr` only; never `print()` or log to stdout from anything reachable by the MCP server, or you will corrupt the protocol stream. The `_fenced()` helper wraps verbatim repo content in a nonce-tagged XML envelope to defend against prompt-injection via indexed docstrings — preserve this behavior when returning source content from new tools.
|
|
56
|
+
|
|
57
|
+
## Security invariants
|
|
58
|
+
|
|
59
|
+
These are load-bearing — see `SECURITY.md` and the `## Security` section of `CHANGELOG.md`. Do not weaken without a review:
|
|
60
|
+
|
|
61
|
+
- **Subprocess env sanitization.** Every subprocess call (git, rust-analyzer, scip-typescript, ast-grep, `descry-generate`) must pass `env=safe_env()` from `src/descry/_env.py`, which filters credential-shaped env vars by regex.
|
|
62
|
+
- **TOML-sourced subprocess args are validated.** `_validate_toolchain`, `_validate_scip_extra_arg`, `_validate_embedding_model` in `handlers.py` reject short flags, shell metacharacters, and out-of-root local paths. New TOML → subprocess plumbing must validate.
|
|
63
|
+
- **Web UI is local-only by design.** `descry-web` binds `127.0.0.1`, has no auth, and allows CORS `*`. `/api/source` enforces project-root containment, rejects non-regular files / non-text content / >10 MiB, and uses `O_NOFOLLOW` on the final open. `/api/index` (and `/api/index/stream`) take no path parameter (always indexes the configured root). Don't add a `--host 0.0.0.0` flag or expose network listeners.
|
|
64
|
+
- **MCP `index(path=...)`** is restricted to the configured project root.
|
|
65
|
+
- **Embedding cache** uses numpy safe-mode load + JSON sidecar + atomic writes + content-addressed keys. Default embedding model revision is pinned for supply-chain integrity; `trust_remote_code` defaults to `False` for user-supplied models.
|
|
66
|
+
|
|
67
|
+
## Versioning
|
|
68
|
+
|
|
69
|
+
Pre-1.0. The only stable public API is `descry.__version__`. Submodules (`descry.handlers`, `descry.query`, etc.) are **not** stable — refactor freely. Minor bumps (`0.1.x` → `0.2.x`) may break the library API, graph schema, CLI, or MCP tool signatures; patch bumps won't.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Christian Haynes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|