Licence and ethics audit¶
Prepared 22 Oct 2026 at commit 4e6fbc4 for the capstone hand-in, and updated 27 Oct 2026 for the Phase 12 release (the dependency table now includes the documentation group, and section 5 covers the new scripts; section 6, on the release files, the public history and the GitHub Actions, is new; the former section 6 is now section 7). It covers every dataset and dependency, what the repository redistributes, and a final review that the repository describes how detectors decay and not how to evade them. It is an engineering audit, not legal advice; the researcher decides before anything is published.
1. This repository¶
Item |
Licence |
Evidence |
|---|---|---|
DriftWatch code and documentation |
MIT ( |
|
Distribution name |
|
|
pyproject.toml still carries the classifier Private :: Do Not Upload, which makes any upload to PyPI fail on purpose. It is removed only in the release commit, on the researcher’s explicit go (ADR-0003, docs/RELEASING.md). Nothing in this audit authorises a release.
The public repository will be Yathindra25KB/driftwatch-lifetime, created from a filtered copy of the development history (section 3). The development repository Yathindra25KB/Driftwatch- stays private as the archive.
2. Datasets¶
Dataset |
Licence as stated |
Used here |
Redistributed |
|---|---|---|---|
LAMDA (Haque et al.) |
MIT, per the dataset card ( |
Feature files for Android, 2013 to 2025 |
No |
BODMAS (Yang et al.) |
BSD-2-Clause for the repository code; no separate licence is stated for the dataset files ( |
Feature vectors for Windows PE |
No |
EMBER2024 (Joyce et al.) |
Apache-2.0, confirmed on the dataset card on 20 Oct 2026 [L-30] |
Not used (Tier 3 was not run) |
No |
AndroZoo |
Academic key; redistribution forbidden |
Not used |
No |
SOREL-20M |
Own terms, not verified |
Not used (excluded in the build guide) |
No |
Decision of 22 Oct 2026: the BODMAS dataset files carry no stated licence. The repository says only “used as published by its authors”: it does not redistribute them, and the build downloads them from their own source into data/, which is not committed. The authors were not asked; doing so is optional.
3. What the repository redistributes¶
Only the synthetic fixture, plus one two-row aggregate table of its run (
src/driftwatch/_golden/smoke_table1.csv, shipped in the wheel so thatdriftwatch smokeworks without a clone; a test keeps it equal to the locked golden file). The fixture (tests/fixtures/synthetic/, generated byscripts/make_fixture.py, seeded).tests/test_fixture_regenerates.pychecks that it is what the generator writes and that it stays under 1 MB.data/andresults/are git-ignored; the guard hook blocksgit addof either, andtests/test_repo_invariants.pyfails if any file under them is tracked (apart fromdata/manifest.json, which holds hashes and source URLs, not data).Process documents:
docs/source/(the build guide, the implementation plan and the phase prompts: two PDFs and one Markdown file) is no longer tracked: it was removed from the index and added to.gitignoreon 22 Oct 2026 at the researcher’s decision, because no licence is stated for those documents. The files stay on the researcher’s disk, and the repository’s history still contains them until it is rewritten, which was not done..claude/(hooks, agent definitions, rules) stays tracked as evidence of the guardrails.Tables under
reports/tables/are aggregates of the study’s own predictions (per-arm A-AUT, counts, intervals), not dataset rows.The report quotes short passages (a phrase or a sentence) from abstracts, each with its source and access date in the claims ledger (rows L-01 to L-33); no paper is reproduced.
4. Dependencies¶
Read from the installed metadata of every package in uv.lock by scripts/list_licences.py (no network; rerun with uv run python scripts/list_licences.py). 84 packages (85 entries in the lock, the project itself excluded): 11 direct runtime, 4 direct development, 4 direct documentation (the docs group, used only to build the site and never part of the wheel), the rest transitive. The runtime dependencies are the only ones a user of the wheel installs.
Package |
Version |
Licence |
Read from |
Kind |
|---|---|---|---|---|
accessible-pygments |
0.0.5 |
BSD-3-Clause |
License |
transitive |
alabaster |
1.0.0 |
BSD License |
classifier |
transitive |
anyio |
4.15.1 |
MIT |
License-Expression |
transitive |
babel |
2.18.0 |
BSD-3-Clause |
License |
transitive |
beautifulsoup4 |
4.15.0 |
MIT License |
License |
transitive |
certifi |
2026.10.23 |
MPL-2.0 |
License |
transitive |
cfgv |
3.5.0 |
MIT |
License |
transitive |
charset-normalizer |
3.5.2 |
MIT |
License |
transitive |
click |
8.5.0 |
BSD-3-Clause |
License-Expression |
transitive |
cloudpickle |
3.1.2 |
BSD-3-Clause |
License |
transitive |
colorama |
0.4.6 |
BSD License |
classifier |
transitive |
contourpy |
1.4.0 |
BSD-3-Clause |
License-Expression |
transitive |
cycler |
0.12.1 |
BSD License |
classifier |
transitive |
distlib |
0.4.4 |
PSF-2.0 |
License |
transitive |
docutils |
0.22.4 |
Public Domain; BSD-2-Clause (installed files) |
reviewed (docs/licence_audit.md) |
transitive |
filelock |
4.2.4 |
MIT |
License-Expression |
transitive |
fonttools |
4.67.0 |
MIT |
License |
transitive |
fsspec |
2026.9.0 |
BSD-3-Clause |
License-Expression |
transitive |
furo |
2025.12.19 |
MIT License |
classifier |
direct, documentation |
gdown |
6.4.2 |
MIT |
License |
direct, runtime |
h11 |
0.16.0 |
MIT |
License |
transitive |
hf-xet |
1.7.0 |
Apache-2.0 |
License-Expression |
transitive |
httpcore2 |
2.16.0 |
BSD-3-Clause |
License-Expression |
transitive |
httpx2 |
2.16.0 |
BSD-3-Clause |
License-Expression |
transitive |
httpx2-jsfetch |
not installed |
UNKNOWN |
- |
transitive |
huggingface-hub |
2.3.0 |
Apache-2.0 |
License |
direct, runtime |
hypothesis |
6.170.12 |
MPL-2.0 |
License-Expression |
direct, development |
identify |
2.6.20 |
MIT |
License |
transitive |
idna |
3.20 |
BSD-3-Clause |
License-Expression |
transitive |
imagesize |
2.0.1 |
MIT |
License-Expression |
transitive |
iniconfig |
2.3.1 |
MIT |
License-Expression |
transitive |
jinja2 |
3.1.6 |
BSD License |
classifier |
transitive |
joblib |
1.6.0 |
BSD-3-Clause |
License-Expression |
transitive |
kiwisolver |
1.5.1 |
BSD License |
classifier |
transitive |
lightgbm |
4.7.0 |
MIT |
License-Expression |
direct, runtime |
markdown-it-py |
4.2.0 |
MIT License |
classifier |
transitive |
markupsafe |
3.0.4 |
BSD-3-Clause |
License-Expression |
transitive |
matplotlib |
3.11.2 |
Python Software Foundation License |
classifier |
direct, runtime |
mdit-py-plugins |
0.6.1 |
MIT License |
classifier |
transitive |
mdurl |
0.1.2 |
MIT License |
classifier |
transitive |
myst-parser |
5.1.0 |
MIT License |
classifier |
direct, documentation |
narwhals |
2.28.0 |
MIT |
License-Expression |
transitive |
nodeenv |
1.11.0 |
BSD |
License |
transitive |
numpy |
2.5.4 |
BSD-3-Clause AND 0BSD AND MIT AND Zlib AND CC0-1.0 |
License-Expression |
direct, runtime |
packaging |
26.3 |
Apache-2.0 OR BSD-2-Clause |
License-Expression |
transitive |
pandas |
3.1.0 |
BSD-3-Clause |
License-Expression |
direct, runtime |
pillow |
13.0.0 |
MIT-CMU |
License-Expression |
transitive |
platformdirs |
4.13.6 |
MIT |
License-Expression |
transitive |
pluggy |
1.7.0 |
MIT |
License |
transitive |
pre-commit |
4.7.0 |
MIT |
License |
direct, development |
psutil |
7.2.2 |
BSD-3-Clause |
License |
direct, runtime |
pyarrow |
26.0.0 |
Apache-2.0 |
License-Expression |
direct, runtime |
pygments |
2.21.0 |
BSD-2-Clause |
License-Expression |
transitive |
pyparsing |
3.3.3 |
MIT |
License-Expression |
transitive |
pysocks |
1.7.1 |
BSD |
License |
transitive |
pytest |
9.1.1 |
MIT |
License-Expression |
direct, development |
python-dateutil |
3.0.0 |
Dual License |
License |
transitive |
python-discovery |
1.6.5 |
MIT |
License-Expression |
transitive |
pyyaml |
6.0.3 |
MIT |
License |
direct, runtime |
requests |
2.34.2 |
Apache-2.0 |
License |
transitive |
roman-numerals |
4.1.0 |
0BSD OR CC0-1.0 |
License-Expression |
transitive |
ruff |
0.17.3 |
MIT |
License-Expression |
direct, development |
scikit-learn |
1.9.1 |
BSD-3-Clause |
License-Expression |
direct, runtime |
scipy |
1.18.1 |
BSD License |
classifier |
direct, runtime |
six |
1.17.0 |
MIT |
License |
transitive |
snowballstemmer |
3.1.1 |
BSD-3-Clause |
License |
transitive |
sortedcontainers |
2.4.0 |
Apache 2.0 |
License |
transitive |
soupsieve |
3.0.4 |
MIT |
License-Expression |
transitive |
sphinx |
9.1.1 |
BSD-2-Clause |
License-Expression |
direct, documentation |
sphinx-basic-ng |
1.0.0b2 |
MIT License |
classifier |
transitive |
sphinxcontrib-applehelp |
2.0.0 |
BSD License |
classifier |
transitive |
sphinxcontrib-devhelp |
2.0.0 |
BSD License |
classifier |
transitive |
sphinxcontrib-htmlhelp |
2.1.0 |
BSD License |
classifier |
transitive |
sphinxcontrib-jsmath |
2.0.0 |
BSD License |
classifier |
transitive |
sphinxcontrib-mermaid |
2.1.1 |
BSD-2-Clause |
License-Expression |
direct, documentation |
sphinxcontrib-qthelp |
2.0.0 |
BSD License |
classifier |
transitive |
sphinxcontrib-serializinghtml |
2.0.0 |
BSD License |
classifier |
transitive |
threadpoolctl |
3.7.0 |
BSD-3-Clause |
License-Expression |
transitive |
tqdm |
4.70.1 |
MPL-2.0 AND MIT |
License |
transitive |
truststore |
0.10.5 |
MIT |
License-Expression |
transitive |
typing-extensions |
4.16.0 |
PSF-2.0 |
License-Expression |
transitive |
tzdata |
2026.5 |
Apache-2.0 |
License |
transitive |
urllib3 |
2.8.0 |
MIT |
License-Expression |
transitive |
virtualenv |
21.15.0 |
MIT |
License-Expression |
transitive |
Notes:
httpx2-jsfetchis locked only for theemscripten(Pyodide) platform, so it is never installed on Windows or Linux and has no local metadata. Its licence was read by hand from its PyPI record on 22 Oct 2026: BSD-3-Clause.Weak copyleft (MPL-2.0): certifi, hypothesis, tqdm.
hypothesisis a development dependency. MPL-2.0 is file-level copyleft; none of these packages is modified or bundled into a distribution by this repository, which installs them from PyPI.Composite or dual expressions (for example
numpy: BSD-3-Clause AND 0BSD AND MIT AND Zlib AND CC0-1.0;packaging: Apache-2.0 OR BSD-2-Clause;python-dateutil: “Dual License”, BSD-3-Clause or Apache-2.0 per its own text) are as the packages state them.No package is GPL or AGPL, as installed. One metadata label needed a human reading, and the lister carries a version-pinned override for it (
REVIEWEDinscripts/list_licences.py, tied to the exact version, so a new version is read from its metadata again):docutils0.22.4 reports “Public Domain; BSD License; GNU General Public License (GPL)” because its source tarball ships one GPL-3 file (tools/editors/emacs/rst.el, an Emacs mode) that is not part of the installed package; the files that are installed are public domain or BSD-2-Clause (itsCOPYING.rst, read 27 Oct 2026).docutilsis a documentation-build dependency only.Vague labels, read on 27 Oct 2026:
nodeenv1.11.0 ships a BSD-style three-clause licence text;python-dateutilships an Apache-2.0 licence for newer contributions and a BSD-3-Clause licence that applies to all code (its own “dual license” text; read for 2.9.0.post0 on 27 Oct 2026 and again for 3.0.0, the version the 28 Oct 2026 dependency refresh resolves to, with the same structure);PySocks1.7.1 states “BSD” in its metadata and ships no licence file (read from metadata only). All three are permissive; none is bundled into the wheel.Runtime fetch of Mermaid. The documentation site draws its diagrams with Mermaid (MIT), which the page loads from
cdn.jsdelivr.netat view time (version pinned bysphinxcontrib-mermaid). It is not vendored in the repository or the wheel; offline, the diagrams show as their source text.
5. Ethics review¶
Checked on 22 Oct 2026 against docs/ETHICS.md and CLAUDE.md hard rules 1 and 12:
Check |
Result |
|---|---|
No malware, binary or decompiled code is downloaded, opened, run or redistributed |
The code reads pre-extracted feature files only; the only data committed is the synthetic fixture |
No evasion tooling and no adversarial-example generation |
A case-insensitive search of |
No network use beyond fetching datasets, checking references and the maintenance scripts |
Checked 27 Oct 2026 by searching |
The search for evasion terms, repeated on the release files |
Case-insensitive search of |
The issue forms and the contribution policy refuse evasion requests |
|
The text describes decay, not defeat |
Chapter 4 section 4.4 describes adversaries at survey level, says the study does not model an adaptive adversary, and contains no recipe; chapter 8 section 8.4 and |
Dual use |
Knowing how fast a detector decays and when retraining pays could in principle help an adversary time an attack; the study measures natural drift on public datasets, reports aggregate effects, and offers no method to cause drift. A sentence on this was added to chapter 8.4 on 22 Oct 2026 at the researcher’s decision. |
Labels |
LAMDA’s labels are antivirus-based with an unpublished scan date [D-16]; BODMAS’s labelling is not described on its project page [D-17]; both are stated as limits in chapter 8 |
Personal data |
None: the feature files describe software, not people |
AI-assistance disclosure |
Stated in |
6. Release files and tools (Phase 12)¶
What a release contains. The wheel and the source archive are built by uv build; scripts/check_release.py (run in the release workflow and by a slow test) opens both and fails on any file under data/, results/, docs/source/, .claude-state/, .venv/ or .cache/, any .env or local settings file, any dataset-shaped file (.parquet, .npz, .npy, .zip) outside the synthetic fixture, any key or certificate, a wheel over one megabyte and a source archive over five. The only data-shaped files that may ship are the synthetic fixture (source archive only) and smoke_table1.csv, a two-row aggregate table of the fixture run that the wheel carries so that driftwatch smoke works without a clone. Built on 26 Oct 2026: wheel 203 kB, source archive 163 kB.
The public repository’s history. The development history contains docs/source/ (course PDFs and phase prompts with no stated licence), which was untracked on 22 Oct 2026 but remains in old commits. The public repository is therefore created from a filtered copy of the history made with git filter-repo --path docs/source --invert-paths, followed by checks that git log --all -- docs/source is empty, that no blob is larger than ten megabytes, and that no secret pattern is present; the mapping from old to new commit hashes is committed (docs/commit_map.csv) so the commits cited in docs/CLAIMS.md stay findable. The step is part of the researcher-gated release procedure and has not been done.
GitHub Actions used by the workflows, pinned to commit hashes with the version in a comment. Licences read from each repository on 27 Oct 2026:
Action |
Licence |
Used in |
|---|---|---|
|
MIT |
CI, docs, release, audit |
|
MIT |
CI, docs, release |
|
MIT |
release, clean room, arXiv audit |
|
MIT |
release, docs, clean room, arXiv audit |
|
BSD-3-Clause |
release (Trusted Publishing; no token stored) |
Services. PyPI, TestPyPI, GitHub (Actions, Pages, Releases), Zenodo and its sandbox are used under their free terms; no secret is stored in the repository (Trusted Publishing uses short-lived OpenID Connect tokens). A Zenodo DOI cannot be deleted, so the release workflow creates the GitHub Release as a draft and the researcher publishes it by hand.
7. Not done here¶
No upload to any package index, no DOI, no change of repository visibility, no filtered public history, no tag, no pending publisher registered. Each of those needs the researcher’s explicit go (docs/RELEASING.md).