tibet-continuityd 0.3.3__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.
- tibet_continuityd-0.3.3/PKG-INFO +128 -0
- tibet_continuityd-0.3.3/README.md +95 -0
- tibet_continuityd-0.3.3/pyproject.toml +62 -0
- tibet_continuityd-0.3.3/setup.cfg +4 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/__init__.py +105 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/__main__.py +7 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/backpressure.py +185 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/coalesce.py +143 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/daemon.py +698 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/police.py +281 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/seal.py +227 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/sniff.py +242 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/trust_kernel.py +364 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/verify_fork.py +306 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd/watch.py +203 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd.egg-info/PKG-INFO +128 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd.egg-info/SOURCES.txt +27 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd.egg-info/dependency_links.txt +1 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd.egg-info/entry_points.txt +2 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd.egg-info/requires.txt +10 -0
- tibet_continuityd-0.3.3/src/tibet_continuityd.egg-info/top_level.txt +1 -0
- tibet_continuityd-0.3.3/tests/test_backpressure.py +213 -0
- tibet_continuityd-0.3.3/tests/test_coalesce.py +62 -0
- tibet_continuityd-0.3.3/tests/test_daemon.py +367 -0
- tibet_continuityd-0.3.3/tests/test_police.py +255 -0
- tibet_continuityd-0.3.3/tests/test_seal.py +347 -0
- tibet_continuityd-0.3.3/tests/test_sniff.py +150 -0
- tibet_continuityd-0.3.3/tests/test_trust_kernel.py +223 -0
- tibet_continuityd-0.3.3/tests/test_verify_fork.py +411 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tibet-continuityd
|
|
3
|
+
Version: 0.3.3
|
|
4
|
+
Summary: Continuous integrity system daemon for the Distributed Continuity OS — Watch, Sniff, Coalesce, Verify, Fork, Trust, Seal, Police, Backpressure across 3 modes (passive/active/strict).
|
|
5
|
+
Author-email: Jasper van de Meent <info@humotica.com>, Root AI <root_idd@humotica.nl>, Codex <codex@humotica.nl>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://humotica.com
|
|
8
|
+
Project-URL: Spec, https://github.com/Humotica/tibet-continuityd/blob/main/SPEC.md
|
|
9
|
+
Keywords: tibet,continuity,daemon,audit,trust,inotify,libmagic,icc,tbz,ssm,phantom,distributed-continuity-os,humotica
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: System Administrators
|
|
12
|
+
Classifier: Intended Audience :: Information Technology
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Security :: Cryptography
|
|
21
|
+
Classifier: Topic :: System :: Monitoring
|
|
22
|
+
Classifier: Topic :: System :: Logging
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
Provides-Extra: verify
|
|
26
|
+
Requires-Dist: tibet-drop>=0.1.0; extra == "verify"
|
|
27
|
+
Requires-Dist: tibet-phantom>=0.2.0; extra == "verify"
|
|
28
|
+
Provides-Extra: full
|
|
29
|
+
Requires-Dist: tibet-drop>=0.1.0; extra == "full"
|
|
30
|
+
Requires-Dist: tibet-phantom>=0.2.0; extra == "full"
|
|
31
|
+
Requires-Dist: cryptography>=41.0; extra == "full"
|
|
32
|
+
Requires-Dist: cbor2>=5.4; extra == "full"
|
|
33
|
+
|
|
34
|
+
# tibet-continuityd
|
|
35
|
+
|
|
36
|
+
> **Continuous Integrity System Daemon for the Distributed Continuity OS.**
|
|
37
|
+
|
|
38
|
+
A residential trust-guardian that runs in the background of every
|
|
39
|
+
machine where TIBET cryptographic discipline must be continuously
|
|
40
|
+
enforced.
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Watch → Sniff → Verify → Fork → Triage → Reseal
|
|
44
|
+
inotify libmagic Ed25519 forward quarant periodic
|
|
45
|
+
+chain causal -ine
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Design axiom
|
|
49
|
+
|
|
50
|
+
> **Name is hint. Content is truth. Arrival is event.**
|
|
51
|
+
>
|
|
52
|
+
> — Codex, 9 May 2026
|
|
53
|
+
|
|
54
|
+
## v0.1 scope (this release)
|
|
55
|
+
|
|
56
|
+
- ✅ `Watch` — inotify on a single inbox lane
|
|
57
|
+
- ✅ `Sniff` — magic-byte recognition (TBZ + executables + PDF + JSON)
|
|
58
|
+
- ✅ Disposition classification per Codex' intake policy table
|
|
59
|
+
- ✅ Audit JSONL log + journald-friendly stderr logging
|
|
60
|
+
- ✅ Mode 1 (Passive Guardian): observe + log + advise
|
|
61
|
+
- ✅ systemd unit ready for deployment
|
|
62
|
+
- ⏭ v0.2 will add: `Verify` (cryptographic) + `Fork` (via phantom.icc)
|
|
63
|
+
- ⏭ v0.3 will add: `Seal` (continuous reseal) + `Police` (unpacked detect)
|
|
64
|
+
|
|
65
|
+
## Install
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install tibet-continuityd
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Run (development)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
TIBET_CONTINUITYD_INBOX=/tmp/inbox \
|
|
75
|
+
TIBET_CONTINUITYD_AUDIT=/tmp/audit.jsonl \
|
|
76
|
+
python3 -m tibet_continuityd
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Drop a TBZ-prefixed file into `/tmp/inbox/`:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
printf 'TBZ\x01\x00\x00\x00' > /tmp/inbox/sample.claude.tza
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
You will see:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
arrival: 'sample.claude.tza' → sealed-tbz (trusted-candidate, 7B)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Run (production, systemd)
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
sudo cp tibet-continuityd.service /etc/systemd/system/
|
|
95
|
+
sudo useradd -r -s /usr/sbin/nologin tibet
|
|
96
|
+
sudo mkdir -p /var/lib/tibet/{inbox,quarantine,triage,materialized}
|
|
97
|
+
sudo mkdir -p /var/log/tibet
|
|
98
|
+
sudo chown -R tibet:tibet /var/lib/tibet /var/log/tibet
|
|
99
|
+
sudo systemctl daemon-reload
|
|
100
|
+
sudo systemctl enable --now tibet-continuityd
|
|
101
|
+
journalctl -u tibet-continuityd -f
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Disposition table (v0.1)
|
|
105
|
+
|
|
106
|
+
| Intake class | Trigger | Disposition |
|
|
107
|
+
|-------------------------|------------------------------------------|----------------------|
|
|
108
|
+
| `sealed-tbz` | TBZ magic + recognized vendor extension | trusted-candidate |
|
|
109
|
+
| `sealed-tbz-no-ext` | TBZ magic, no/unknown extension | trusted-candidate |
|
|
110
|
+
| `disguised` | Vendor extension, no TBZ magic | triage-disguised |
|
|
111
|
+
| `executable` | ELF / PE binary | quarantine |
|
|
112
|
+
| `pdf` | PDF magic | reject |
|
|
113
|
+
| `json-text` | Plain JSON state in sealed-only zone | reseal-candidate |
|
|
114
|
+
| `unknown` | Anything else | quarantine |
|
|
115
|
+
| `empty` | Zero-byte file | reject |
|
|
116
|
+
|
|
117
|
+
v0.1 logs the disposition only. v0.2+ will act on it
|
|
118
|
+
(Verify + Fork or Quarantine + Triage).
|
|
119
|
+
|
|
120
|
+
## Architecture & spec
|
|
121
|
+
|
|
122
|
+
- Spec: [`tibet-continuityd-spec.md`](https://humotica.com/specs/continuityd)
|
|
123
|
+
- Companion intake guide (Codex):
|
|
124
|
+
[`tibet-continuity-guardian.md`](https://humotica.com/specs/continuity-guardian)
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
MIT — Humotica + Root AI + Codex (2026)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# tibet-continuityd
|
|
2
|
+
|
|
3
|
+
> **Continuous Integrity System Daemon for the Distributed Continuity OS.**
|
|
4
|
+
|
|
5
|
+
A residential trust-guardian that runs in the background of every
|
|
6
|
+
machine where TIBET cryptographic discipline must be continuously
|
|
7
|
+
enforced.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Watch → Sniff → Verify → Fork → Triage → Reseal
|
|
11
|
+
inotify libmagic Ed25519 forward quarant periodic
|
|
12
|
+
+chain causal -ine
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Design axiom
|
|
16
|
+
|
|
17
|
+
> **Name is hint. Content is truth. Arrival is event.**
|
|
18
|
+
>
|
|
19
|
+
> — Codex, 9 May 2026
|
|
20
|
+
|
|
21
|
+
## v0.1 scope (this release)
|
|
22
|
+
|
|
23
|
+
- ✅ `Watch` — inotify on a single inbox lane
|
|
24
|
+
- ✅ `Sniff` — magic-byte recognition (TBZ + executables + PDF + JSON)
|
|
25
|
+
- ✅ Disposition classification per Codex' intake policy table
|
|
26
|
+
- ✅ Audit JSONL log + journald-friendly stderr logging
|
|
27
|
+
- ✅ Mode 1 (Passive Guardian): observe + log + advise
|
|
28
|
+
- ✅ systemd unit ready for deployment
|
|
29
|
+
- ⏭ v0.2 will add: `Verify` (cryptographic) + `Fork` (via phantom.icc)
|
|
30
|
+
- ⏭ v0.3 will add: `Seal` (continuous reseal) + `Police` (unpacked detect)
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install tibet-continuityd
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Run (development)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
TIBET_CONTINUITYD_INBOX=/tmp/inbox \
|
|
42
|
+
TIBET_CONTINUITYD_AUDIT=/tmp/audit.jsonl \
|
|
43
|
+
python3 -m tibet_continuityd
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Drop a TBZ-prefixed file into `/tmp/inbox/`:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
printf 'TBZ\x01\x00\x00\x00' > /tmp/inbox/sample.claude.tza
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
You will see:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
arrival: 'sample.claude.tza' → sealed-tbz (trusted-candidate, 7B)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Run (production, systemd)
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
sudo cp tibet-continuityd.service /etc/systemd/system/
|
|
62
|
+
sudo useradd -r -s /usr/sbin/nologin tibet
|
|
63
|
+
sudo mkdir -p /var/lib/tibet/{inbox,quarantine,triage,materialized}
|
|
64
|
+
sudo mkdir -p /var/log/tibet
|
|
65
|
+
sudo chown -R tibet:tibet /var/lib/tibet /var/log/tibet
|
|
66
|
+
sudo systemctl daemon-reload
|
|
67
|
+
sudo systemctl enable --now tibet-continuityd
|
|
68
|
+
journalctl -u tibet-continuityd -f
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Disposition table (v0.1)
|
|
72
|
+
|
|
73
|
+
| Intake class | Trigger | Disposition |
|
|
74
|
+
|-------------------------|------------------------------------------|----------------------|
|
|
75
|
+
| `sealed-tbz` | TBZ magic + recognized vendor extension | trusted-candidate |
|
|
76
|
+
| `sealed-tbz-no-ext` | TBZ magic, no/unknown extension | trusted-candidate |
|
|
77
|
+
| `disguised` | Vendor extension, no TBZ magic | triage-disguised |
|
|
78
|
+
| `executable` | ELF / PE binary | quarantine |
|
|
79
|
+
| `pdf` | PDF magic | reject |
|
|
80
|
+
| `json-text` | Plain JSON state in sealed-only zone | reseal-candidate |
|
|
81
|
+
| `unknown` | Anything else | quarantine |
|
|
82
|
+
| `empty` | Zero-byte file | reject |
|
|
83
|
+
|
|
84
|
+
v0.1 logs the disposition only. v0.2+ will act on it
|
|
85
|
+
(Verify + Fork or Quarantine + Triage).
|
|
86
|
+
|
|
87
|
+
## Architecture & spec
|
|
88
|
+
|
|
89
|
+
- Spec: [`tibet-continuityd-spec.md`](https://humotica.com/specs/continuityd)
|
|
90
|
+
- Companion intake guide (Codex):
|
|
91
|
+
[`tibet-continuity-guardian.md`](https://humotica.com/specs/continuity-guardian)
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT — Humotica + Root AI + Codex (2026)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "tibet-continuityd"
|
|
7
|
+
version = "0.3.3"
|
|
8
|
+
description = "Continuous integrity system daemon for the Distributed Continuity OS — Watch, Sniff, Coalesce, Verify, Fork, Trust, Seal, Police, Backpressure across 3 modes (passive/active/strict)."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Jasper van de Meent", email = "info@humotica.com"},
|
|
14
|
+
{name = "Root AI", email = "root_idd@humotica.nl"},
|
|
15
|
+
{name = "Codex", email = "codex@humotica.nl"},
|
|
16
|
+
]
|
|
17
|
+
keywords = [
|
|
18
|
+
"tibet", "continuity", "daemon", "audit", "trust",
|
|
19
|
+
"inotify", "libmagic", "icc", "tbz", "ssm", "phantom",
|
|
20
|
+
"distributed-continuity-os", "humotica",
|
|
21
|
+
]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 4 - Beta",
|
|
24
|
+
"Intended Audience :: System Administrators",
|
|
25
|
+
"Intended Audience :: Information Technology",
|
|
26
|
+
"License :: OSI Approved :: MIT License",
|
|
27
|
+
"Operating System :: POSIX :: Linux",
|
|
28
|
+
"Programming Language :: Python :: 3",
|
|
29
|
+
"Programming Language :: Python :: 3.10",
|
|
30
|
+
"Programming Language :: Python :: 3.11",
|
|
31
|
+
"Programming Language :: Python :: 3.12",
|
|
32
|
+
"Programming Language :: Python :: 3.13",
|
|
33
|
+
"Topic :: Security :: Cryptography",
|
|
34
|
+
"Topic :: System :: Monitoring",
|
|
35
|
+
"Topic :: System :: Logging",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
# v0.3 has zero hard runtime dependencies; uses ctypes for inotify
|
|
39
|
+
# and an in-package magic-byte table. Optional dependencies enable
|
|
40
|
+
# cryptographic verify, pack, and reseal stages.
|
|
41
|
+
dependencies = []
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
# Verify + Fork + Seal stages with cryptographic discipline
|
|
45
|
+
verify = [
|
|
46
|
+
"tibet-drop>=0.1.0",
|
|
47
|
+
"tibet-phantom>=0.2.0",
|
|
48
|
+
]
|
|
49
|
+
# Full stack including phantom-icc bridge
|
|
50
|
+
full = [
|
|
51
|
+
"tibet-drop>=0.1.0",
|
|
52
|
+
"tibet-phantom>=0.2.0",
|
|
53
|
+
"cryptography>=41.0",
|
|
54
|
+
"cbor2>=5.4",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[project.scripts]
|
|
58
|
+
tibet-continuityd = "tibet_continuityd.daemon:main"
|
|
59
|
+
|
|
60
|
+
[project.urls]
|
|
61
|
+
Homepage = "https://humotica.com"
|
|
62
|
+
Spec = "https://github.com/Humotica/tibet-continuityd/blob/main/SPEC.md"
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""
|
|
2
|
+
tibet-continuityd — Continuous Integrity System Daemon
|
|
3
|
+
=======================================================
|
|
4
|
+
|
|
5
|
+
A residential trust guardian that runs in the background of
|
|
6
|
+
every machine where TIBET cryptographic discipline must be
|
|
7
|
+
continuously enforced.
|
|
8
|
+
|
|
9
|
+
Watch → inotify
|
|
10
|
+
Sniff → libmagic / TBZ magic-byte recognition
|
|
11
|
+
Verify → (v0.2) cryptographic verification
|
|
12
|
+
Fork → (v0.2) forward-causal materialize via phantom.icc
|
|
13
|
+
Triage → (v0.2) quarantine on mismatch
|
|
14
|
+
Reseal → (v0.3) periodic reseal of materialized state
|
|
15
|
+
|
|
16
|
+
Three operating modes:
|
|
17
|
+
Mode 1 Passive Guardian observe + log + advise
|
|
18
|
+
Mode 2 Sealing Guardian auto-reseal + active intake
|
|
19
|
+
Mode 3 Strict Continuity zero-trust, ICC/TBZ only
|
|
20
|
+
|
|
21
|
+
Spec: /srv/jtel-stack/hersenspinsels/tibet-continuityd-spec.md
|
|
22
|
+
Plus: /srv/jtel-stack/hersenspinsels/tibet-continuity-guardian.md
|
|
23
|
+
(Codex' parallel intake-discipline guide)
|
|
24
|
+
|
|
25
|
+
"Name is hint. Content is truth. Arrival is event."
|
|
26
|
+
— Codex, 9 mei 2026
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
__version__ = "0.3.3"
|
|
30
|
+
__author__ = "Jasper van de Meent, Root AI, Codex"
|
|
31
|
+
|
|
32
|
+
# Core stages — pure stdlib, always available
|
|
33
|
+
from tibet_continuityd.backpressure import (
|
|
34
|
+
BackpressureMonitor,
|
|
35
|
+
BackpressureSnapshot,
|
|
36
|
+
BackpressureState,
|
|
37
|
+
)
|
|
38
|
+
from tibet_continuityd.police import (
|
|
39
|
+
FindingSeverity,
|
|
40
|
+
PoliceAction,
|
|
41
|
+
PoliceFinding,
|
|
42
|
+
PoliceScanner,
|
|
43
|
+
apply_action,
|
|
44
|
+
)
|
|
45
|
+
from tibet_continuityd.sniff import IntakeClass, sniff_payload
|
|
46
|
+
from tibet_continuityd.trust_kernel import (
|
|
47
|
+
TrustQuery,
|
|
48
|
+
TrustVerdict,
|
|
49
|
+
apply_verdict_to_disposition,
|
|
50
|
+
load_policies,
|
|
51
|
+
query_trust_kernel,
|
|
52
|
+
)
|
|
53
|
+
from tibet_continuityd.watch import LaneWatcher, WatchEvent
|
|
54
|
+
|
|
55
|
+
# Verify + Fork + Seal — require tibet-drop (install via [verify] extra)
|
|
56
|
+
# Defensive imports: core daemon works without these.
|
|
57
|
+
try:
|
|
58
|
+
from tibet_continuityd.verify_fork import (
|
|
59
|
+
CausalIDs,
|
|
60
|
+
VerifyForkResult,
|
|
61
|
+
verify_and_fork,
|
|
62
|
+
)
|
|
63
|
+
from tibet_continuityd.seal import SealEngine, SealResult
|
|
64
|
+
from tibet_continuityd.daemon import ContinuityDaemon
|
|
65
|
+
_HAS_VERIFY = True
|
|
66
|
+
except ImportError:
|
|
67
|
+
# tibet-drop not on sys.path — verify/fork/seal/daemon unavailable.
|
|
68
|
+
# Core sniff/police/trust_kernel/watch/backpressure still work.
|
|
69
|
+
CausalIDs = None # type: ignore
|
|
70
|
+
VerifyForkResult = None # type: ignore
|
|
71
|
+
verify_and_fork = None # type: ignore
|
|
72
|
+
SealEngine = None # type: ignore
|
|
73
|
+
SealResult = None # type: ignore
|
|
74
|
+
ContinuityDaemon = None # type: ignore
|
|
75
|
+
_HAS_VERIFY = False
|
|
76
|
+
|
|
77
|
+
__all__ = [
|
|
78
|
+
# Core (always available)
|
|
79
|
+
"LaneWatcher",
|
|
80
|
+
"WatchEvent",
|
|
81
|
+
"IntakeClass",
|
|
82
|
+
"sniff_payload",
|
|
83
|
+
"TrustQuery",
|
|
84
|
+
"TrustVerdict",
|
|
85
|
+
"query_trust_kernel",
|
|
86
|
+
"apply_verdict_to_disposition",
|
|
87
|
+
"load_policies",
|
|
88
|
+
"PoliceFinding",
|
|
89
|
+
"PoliceScanner",
|
|
90
|
+
"PoliceAction",
|
|
91
|
+
"FindingSeverity",
|
|
92
|
+
"apply_action",
|
|
93
|
+
"BackpressureMonitor",
|
|
94
|
+
"BackpressureSnapshot",
|
|
95
|
+
"BackpressureState",
|
|
96
|
+
# Verify-stage (None when tibet-drop unavailable)
|
|
97
|
+
"ContinuityDaemon",
|
|
98
|
+
"CausalIDs",
|
|
99
|
+
"VerifyForkResult",
|
|
100
|
+
"verify_and_fork",
|
|
101
|
+
"SealEngine",
|
|
102
|
+
"SealResult",
|
|
103
|
+
# Capability flag
|
|
104
|
+
"_HAS_VERIFY",
|
|
105
|
+
]
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""
|
|
2
|
+
backpressure.py — Backpressure / circuit-breaker (v0.3.2, axe 3).
|
|
3
|
+
|
|
4
|
+
Per Jaspers prompt 9 mei 2026:
|
|
5
|
+
|
|
6
|
+
"MUX 500 files/sec, sniff/verify 100/sec. Inbox > 5000 onverwerkt
|
|
7
|
+
→ daemon signaleert MUX/network 'Halt' of TCP-windowing-stijl
|
|
8
|
+
backpressure. Geen self-inflicted DoS."
|
|
9
|
+
|
|
10
|
+
This module implements that protection: monitor the inbox depth
|
|
11
|
+
and emit state-transition audit events when pressure rises or
|
|
12
|
+
falls. The daemon itself does NOT throttle its own work-rate
|
|
13
|
+
(that would worsen things) — it signals UPSTREAM that producer
|
|
14
|
+
should slow down.
|
|
15
|
+
|
|
16
|
+
State machine:
|
|
17
|
+
|
|
18
|
+
NORMAL depth < low_water
|
|
19
|
+
│
|
|
20
|
+
│ depth ≥ low_water
|
|
21
|
+
▼
|
|
22
|
+
PRESSURE_RISING low_water ≤ depth < high_water
|
|
23
|
+
│
|
|
24
|
+
│ depth ≥ high_water
|
|
25
|
+
▼
|
|
26
|
+
OVERLOADED depth ≥ high_water
|
|
27
|
+
│
|
|
28
|
+
│ depth < low_water (hysteresis)
|
|
29
|
+
▼
|
|
30
|
+
RECOVERING transitional state
|
|
31
|
+
│
|
|
32
|
+
│ depth stable < low_water
|
|
33
|
+
▼
|
|
34
|
+
NORMAL
|
|
35
|
+
|
|
36
|
+
Hysteresis: NORMAL → OVERLOADED requires high_water,
|
|
37
|
+
OVERLOADED → NORMAL requires going back below
|
|
38
|
+
low_water (not just back below high_water).
|
|
39
|
+
This prevents oscillation at the boundary.
|
|
40
|
+
|
|
41
|
+
Signal mechanism (v0.3.2 minimal):
|
|
42
|
+
emit "backpressure" audit-record at every state-transition
|
|
43
|
+
(= upstream consumers can read audit-stream and react)
|
|
44
|
+
|
|
45
|
+
Future v0.3.x extensions:
|
|
46
|
+
- write signal-file at /var/lib/tibet/backpressure-state
|
|
47
|
+
- HTTP endpoint POST to mux upstream
|
|
48
|
+
- TIBET token emission for cross-host signaling
|
|
49
|
+
"""
|
|
50
|
+
from __future__ import annotations
|
|
51
|
+
|
|
52
|
+
import time
|
|
53
|
+
from dataclasses import dataclass, field
|
|
54
|
+
from enum import Enum
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
from typing import Optional
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class BackpressureState(Enum):
|
|
60
|
+
"""Daemon's current capacity state."""
|
|
61
|
+
NORMAL = "normal" # depth < low_water
|
|
62
|
+
PRESSURE_RISING = "pressure-rising" # low ≤ depth < high
|
|
63
|
+
OVERLOADED = "overloaded" # depth ≥ high_water
|
|
64
|
+
RECOVERING = "recovering" # was overloaded, depth dropping
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass
|
|
68
|
+
class BackpressureSnapshot:
|
|
69
|
+
"""One observation of inbox depth + current state."""
|
|
70
|
+
state: BackpressureState
|
|
71
|
+
inbox_depth: int # number of unprocessed files
|
|
72
|
+
low_water: int # threshold for "rising"
|
|
73
|
+
high_water: int # threshold for "overloaded"
|
|
74
|
+
transitioned: bool # state changed since last check
|
|
75
|
+
prev_state: Optional[BackpressureState] = None
|
|
76
|
+
ts_unix: float = field(default_factory=time.time)
|
|
77
|
+
|
|
78
|
+
def to_dict(self) -> dict:
|
|
79
|
+
return {
|
|
80
|
+
"state": self.state.value,
|
|
81
|
+
"inbox_depth": self.inbox_depth,
|
|
82
|
+
"low_water": self.low_water,
|
|
83
|
+
"high_water": self.high_water,
|
|
84
|
+
"transitioned": self.transitioned,
|
|
85
|
+
"prev_state": self.prev_state.value
|
|
86
|
+
if self.prev_state else None,
|
|
87
|
+
"ts_unix": self.ts_unix,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass
|
|
92
|
+
class BackpressureMonitor:
|
|
93
|
+
"""Track inbox depth and compute state transitions.
|
|
94
|
+
|
|
95
|
+
Usage:
|
|
96
|
+
monitor = BackpressureMonitor(
|
|
97
|
+
lane=Path("/var/lib/tibet/inbox"),
|
|
98
|
+
low_water=2000,
|
|
99
|
+
high_water=5000,
|
|
100
|
+
)
|
|
101
|
+
snapshot = monitor.check()
|
|
102
|
+
if snapshot.transitioned:
|
|
103
|
+
# emit audit, optionally signal upstream
|
|
104
|
+
...
|
|
105
|
+
"""
|
|
106
|
+
lane: Path
|
|
107
|
+
low_water: int = 2000
|
|
108
|
+
high_water: int = 5000
|
|
109
|
+
_state: BackpressureState = BackpressureState.NORMAL
|
|
110
|
+
|
|
111
|
+
def __post_init__(self):
|
|
112
|
+
if self.low_water >= self.high_water:
|
|
113
|
+
raise ValueError(
|
|
114
|
+
f"low_water ({self.low_water}) must be < "
|
|
115
|
+
f"high_water ({self.high_water})"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def _measure_depth(self) -> int:
|
|
119
|
+
"""Count files in lane (excluding subdirectories)."""
|
|
120
|
+
if not self.lane.exists() or not self.lane.is_dir():
|
|
121
|
+
return 0
|
|
122
|
+
try:
|
|
123
|
+
return sum(1 for entry in self.lane.iterdir()
|
|
124
|
+
if entry.is_file())
|
|
125
|
+
except OSError:
|
|
126
|
+
return 0
|
|
127
|
+
|
|
128
|
+
def _classify_state(self, depth: int) -> BackpressureState:
|
|
129
|
+
"""Compute target state from depth WITHOUT hysteresis logic.
|
|
130
|
+
|
|
131
|
+
Hysteresis is applied in check() — this is the raw mapping.
|
|
132
|
+
"""
|
|
133
|
+
if depth >= self.high_water:
|
|
134
|
+
return BackpressureState.OVERLOADED
|
|
135
|
+
if depth >= self.low_water:
|
|
136
|
+
return BackpressureState.PRESSURE_RISING
|
|
137
|
+
return BackpressureState.NORMAL
|
|
138
|
+
|
|
139
|
+
def check(self) -> BackpressureSnapshot:
|
|
140
|
+
"""Measure depth and update state with hysteresis."""
|
|
141
|
+
depth = self._measure_depth()
|
|
142
|
+
prev = self._state
|
|
143
|
+
target = self._classify_state(depth)
|
|
144
|
+
|
|
145
|
+
# Hysteresis: OVERLOADED can ONLY drop to RECOVERING (not
|
|
146
|
+
# straight to NORMAL via PRESSURE_RISING). This prevents
|
|
147
|
+
# oscillation when depth hovers near low_water.
|
|
148
|
+
new_state = target
|
|
149
|
+
if prev == BackpressureState.OVERLOADED and \
|
|
150
|
+
target != BackpressureState.OVERLOADED:
|
|
151
|
+
# transition out of overloaded → recovering first
|
|
152
|
+
if target == BackpressureState.NORMAL:
|
|
153
|
+
new_state = BackpressureState.RECOVERING
|
|
154
|
+
# else: target is PRESSURE_RISING, accept it
|
|
155
|
+
elif prev == BackpressureState.RECOVERING:
|
|
156
|
+
# In RECOVERING, stay until depth is fully back under
|
|
157
|
+
# low_water (= NORMAL target).
|
|
158
|
+
if target == BackpressureState.NORMAL:
|
|
159
|
+
new_state = BackpressureState.NORMAL
|
|
160
|
+
elif target == BackpressureState.OVERLOADED:
|
|
161
|
+
new_state = BackpressureState.OVERLOADED
|
|
162
|
+
else:
|
|
163
|
+
new_state = BackpressureState.RECOVERING
|
|
164
|
+
|
|
165
|
+
transitioned = (new_state != prev)
|
|
166
|
+
self._state = new_state
|
|
167
|
+
|
|
168
|
+
return BackpressureSnapshot(
|
|
169
|
+
state=new_state,
|
|
170
|
+
inbox_depth=depth,
|
|
171
|
+
low_water=self.low_water,
|
|
172
|
+
high_water=self.high_water,
|
|
173
|
+
transitioned=transitioned,
|
|
174
|
+
prev_state=prev if transitioned else None,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# ─── Public API ─────────────────────────────────────────────────
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
__all__ = [
|
|
182
|
+
"BackpressureMonitor",
|
|
183
|
+
"BackpressureSnapshot",
|
|
184
|
+
"BackpressureState",
|
|
185
|
+
]
|