voyd 0.1.0__py3-none-any.whl

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 (59) hide show
  1. voyd/__init__.py +105 -0
  2. voyd/declare.py +649 -0
  3. voyd/engine/__init__.py +111 -0
  4. voyd/engine/admission/__init__.py +120 -0
  5. voyd/engine/admission/composition.py +120 -0
  6. voyd/engine/admission/core.py +814 -0
  7. voyd/engine/admission/handle.py +69 -0
  8. voyd/engine/admission/lineage.py +241 -0
  9. voyd/engine/admission/marks.py +560 -0
  10. voyd/engine/admission/reads.py +166 -0
  11. voyd/engine/admission/reasons.py +97 -0
  12. voyd/engine/admission/receipts.py +279 -0
  13. voyd/engine/admission/rerank.py +244 -0
  14. voyd/engine/admission/rules.py +895 -0
  15. voyd/engine/admission/sealing.py +256 -0
  16. voyd/engine/admission/spec.py +302 -0
  17. voyd/engine/admission/transforms.py +128 -0
  18. voyd/engine/attest.py +168 -0
  19. voyd/engine/authority.py +240 -0
  20. voyd/engine/capabilities.py +128 -0
  21. voyd/engine/custody.py +426 -0
  22. voyd/engine/errors.py +364 -0
  23. voyd/engine/expiry.py +92 -0
  24. voyd/engine/keyring.py +815 -0
  25. voyd/engine/plan.py +547 -0
  26. voyd/engine/py.typed +1 -0
  27. voyd/engine/search.py +456 -0
  28. voyd/engine/time.py +145 -0
  29. voyd/engine/trait.py +47 -0
  30. voyd/py.typed +1 -0
  31. voyd/wire/__init__.py +37 -0
  32. voyd/wire/__main__.py +19 -0
  33. voyd/wire/bench.py +758 -0
  34. voyd/wire/cascade.py +232 -0
  35. voyd/wire/cli.py +393 -0
  36. voyd/wire/codec.py +292 -0
  37. voyd/wire/ensure.py +179 -0
  38. voyd/wire/health.py +66 -0
  39. voyd/wire/identity.py +190 -0
  40. voyd/wire/metrics.py +552 -0
  41. voyd/wire/plan.py +504 -0
  42. voyd/wire/plan_report.py +347 -0
  43. voyd/wire/policy/__init__.py +97 -0
  44. voyd/wire/policy/erasure.py +137 -0
  45. voyd/wire/policy/guarding.py +460 -0
  46. voyd/wire/policy/handshake.py +110 -0
  47. voyd/wire/policy/reads.py +526 -0
  48. voyd/wire/policy/refusals.py +327 -0
  49. voyd/wire/policy/verbs.py +287 -0
  50. voyd/wire/preflight.py +429 -0
  51. voyd/wire/proxy.py +1149 -0
  52. voyd/wire/report.py +98 -0
  53. voyd/wire/seal.py +631 -0
  54. voyd/wire/upstream.py +277 -0
  55. voyd-0.1.0.dist-info/METADATA +746 -0
  56. voyd-0.1.0.dist-info/RECORD +59 -0
  57. voyd-0.1.0.dist-info/WHEEL +4 -0
  58. voyd-0.1.0.dist-info/entry_points.txt +5 -0
  59. voyd-0.1.0.dist-info/licenses/LICENSE +21 -0
voyd/__init__.py ADDED
@@ -0,0 +1,105 @@
1
+ """VOYD: a retrieval read path that refuses what it has forgotten.
2
+
3
+ Ranking is not permission. A vector index ranks by relevance and is never
4
+ asked the other question -- may this fact reach a prompt? -- so a retrieval
5
+ answers with a confident score and no idea whether the hit was allowed to be
6
+ there: an expired row the sweeper has not reached, a fact somebody revoked, a
7
+ vector from a model that was swapped.
8
+
9
+ VOYD answers that question at the one place every read passes through on the
10
+ way out.
11
+
12
+ **There is one way to use it, and it is not an import.** VOYD is a proxy.
13
+ Declare the rules once, in a file that is not your application::
14
+
15
+ # voydfile.py
16
+ from voyd import guard, deadline, revocable, tenant
17
+
18
+ @guard("notes")
19
+ class Notes:
20
+ expire_at = deadline()
21
+ forgotten = revocable()
22
+ tenant_id = tenant()
23
+
24
+ # then: voyd-wire --config voydfile.py --target localhost:27017
25
+
26
+ No code. Any driver in any language pointed at that port cannot read a
27
+ forgotten fact, because the boundary is not something a caller can forget
28
+ to use -- there is nothing to reach past.
29
+
30
+ What this package exports is the vocabulary above -- ``guard``,
31
+ ``deadline``, ``revocable`` and the rest -- because the proxy loads your
32
+ policy file, and the parts ``--ensure`` and ``--verify`` provision with.
33
+ There is nothing here for an application to import and no handle for it to
34
+ hold: a boundary you can forget to route a read through is not one.
35
+
36
+ The check itself is pure -- no database, no connection, no I/O -- which is
37
+ what lets it run inside a proxy at all. The proxy opens one connection of
38
+ its own, and only when a policy declares ``lineage_field``: making a
39
+ refusal reach what was derived from a fact is a write the caller did not
40
+ issue, so it does not go on the caller's session.
41
+
42
+ The pieces, and everything else is mechanics:
43
+
44
+ **Deadline** -- one ``expire_at``, inherited by every row in the scope and
45
+ collected by one TTL index. Enforced in the *read path* as well as by the
46
+ reaper: MongoDB's TTL monitor runs about once a minute (measured: 60.0s), so
47
+ an expired document lives on disk for a window afterwards, and serving it
48
+ during that window is the whole bug class.
49
+
50
+ **Refusal** -- not a convention each call site remembers, because a rule you
51
+ have to remember to apply is not enforced. ``revoke()`` makes a fact
52
+ unreachable on the next read while its row is still on disk: deletion is a
53
+ storage event, refusal is a retrieval guarantee, and only the second can be
54
+ immediate. Not every refusal is an erasure, and the difference is declared on
55
+ the reason rather than decided by the verb -- one word, ``reversible``, says
56
+ whether ``lift()`` works and whether imposing it schedules the reaper. See
57
+ ``examples/refuse.py``.
58
+
59
+ **A rule is a protocol, not a list.** ``reason`` + ``refuses(doc)`` +
60
+ ``clause()``, and a stranger's rule is a first-class one. That is what makes
61
+ the set-relative reasons possible -- a token budget, a de-duplicator, a
62
+ provenance quota -- which refuse a document because of the *other* documents
63
+ on the page, and which no index filter and no policy engine can express. See
64
+ ``examples/rosetta.py`` and ``examples/portfolio.py``.
65
+
66
+ **Refusal travels.** A collection declaring ``lineage_field`` records what
67
+ each document was made out of, so revoking a source reaches the summary, the
68
+ answer and the embedding built on it -- children marked first, then the
69
+ source, because a crash the other way round leaves a summary of an erased
70
+ fact still answering prompts. The boundary closes a document's ancestry
71
+ transitively when it is written, which is what makes the cascade one query
72
+ at any depth, and refuses an insert that claims a parent it may not reach.
73
+ ``find({"lineage": id})`` answers the question from the other end.
74
+
75
+ **And refusal is not the whole answer, which is said here rather than
76
+ discovered later.** Refusal binds a read path, and a restored snapshot does
77
+ not run it. That is what ``sealed()`` and ``--key-vault`` are for -- a key
78
+ per scope, so destroying it makes every copy unreadable at once, and the
79
+ boundary revokes the documents *first* so the key cache is not a second
80
+ window. See ``examples/shred.py``.
81
+
82
+ Every claim above is asserted by the test suite against a real MongoDB --
83
+ no mock tier, on purpose, because these properties are only true if the
84
+ *queries* are right.
85
+ """
86
+
87
+ from __future__ import annotations
88
+
89
+ from .declare import (auto_embed, budget, clearance, deadline, distinct,
90
+ embedded_with, guard, holdable, restricted_to,
91
+ rerank, revocable, sealed, subjects, tenant, transform)
92
+
93
+ __version__ = "0.1.0"
94
+
95
+ __all__ = [
96
+ # The declarative policy surface -- everything `voydfile.py` needs.
97
+ "guard", "deadline", "revocable", "holdable", "tenant",
98
+ "restricted_to", "clearance", "embedded_with", "budget", "distinct",
99
+ "sealed", "auto_embed", "subjects",
100
+ # Page-shaping, which is not a rule and is exported beside them
101
+ # anyway: it is declared in the same file, and a vocabulary split
102
+ # across two imports is a vocabulary people get wrong.
103
+ "transform", "rerank",
104
+ "__version__",
105
+ ]