voyd 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.
Files changed (109) hide show
  1. voyd-0.1.0/.dockerignore +48 -0
  2. voyd-0.1.0/.github/workflows/policy-plan.yml +55 -0
  3. voyd-0.1.0/.github/workflows/test.yml +168 -0
  4. voyd-0.1.0/.gitignore +234 -0
  5. voyd-0.1.0/Dockerfile +72 -0
  6. voyd-0.1.0/LICENSE +21 -0
  7. voyd-0.1.0/PKG-INFO +746 -0
  8. voyd-0.1.0/README.md +709 -0
  9. voyd-0.1.0/action.yml +312 -0
  10. voyd-0.1.0/blog.md +415 -0
  11. voyd-0.1.0/docker-compose.yml +139 -0
  12. voyd-0.1.0/docs/cosine.md +228 -0
  13. voyd-0.1.0/docs/ranking-is-not-permission.md +250 -0
  14. voyd-0.1.0/docs/why-not-native.md +304 -0
  15. voyd-0.1.0/ethos.md +202 -0
  16. voyd-0.1.0/examples/_boundary.py +112 -0
  17. voyd-0.1.0/examples/clearance.py +207 -0
  18. voyd-0.1.0/examples/drift.py +188 -0
  19. voyd-0.1.0/examples/embed.py +187 -0
  20. voyd-0.1.0/examples/portfolio.py +259 -0
  21. voyd-0.1.0/examples/refuse.py +125 -0
  22. voyd-0.1.0/examples/rosetta.py +197 -0
  23. voyd-0.1.0/examples/seal.py +192 -0
  24. voyd-0.1.0/examples/shadow.py +174 -0
  25. voyd-0.1.0/examples/shred.py +175 -0
  26. voyd-0.1.0/examples/tenancy.py +165 -0
  27. voyd-0.1.0/examples/wire.py +143 -0
  28. voyd-0.1.0/genius.md +258 -0
  29. voyd-0.1.0/pyproject.toml +184 -0
  30. voyd-0.1.0/quickstart.md +258 -0
  31. voyd-0.1.0/scanner/README.md +272 -0
  32. voyd-0.1.0/scanner/pyproject.toml +45 -0
  33. voyd-0.1.0/scanner/voyd_scan/__init__.py +1026 -0
  34. voyd-0.1.0/scanner/voyd_scan/__main__.py +24 -0
  35. voyd-0.1.0/tests/__init__.py +0 -0
  36. voyd-0.1.0/tests/conftest.py +348 -0
  37. voyd-0.1.0/tests/test_a_change_stream_is_not_a_way_around_this.py +162 -0
  38. voyd-0.1.0/tests/test_a_plan_can_still_be_believed_next_year.py +347 -0
  39. voyd-0.1.0/tests/test_a_plan_says_what_a_change_would_admit.py +798 -0
  40. voyd-0.1.0/tests/test_a_real_driver_through_a_real_boundary.py +324 -0
  41. voyd-0.1.0/tests/test_a_refusal_reaches_what_was_made_of_the_fact.py +186 -0
  42. voyd-0.1.0/tests/test_a_transform_cannot_widen_a_read.py +422 -0
  43. voyd-0.1.0/tests/test_every_decision_the_boundary_makes.py +501 -0
  44. voyd-0.1.0/tests/test_the_boundary_refuses.py +541 -0
  45. voyd-0.1.0/tests/test_the_codebase_tells_the_truth_about_itself.py +374 -0
  46. voyd-0.1.0/tests/test_the_codec_round_trips.py +273 -0
  47. voyd-0.1.0/tests/test_the_codec_survives_hostile_bytes.py +187 -0
  48. voyd-0.1.0/tests/test_the_erasure_refusal_cannot_perform.py +669 -0
  49. voyd-0.1.0/tests/test_the_policy_file_is_the_configuration.py +433 -0
  50. voyd-0.1.0/tests/test_the_reranker_is_a_transform_like_any_other.py +299 -0
  51. voyd-0.1.0/tests/test_the_shipped_action_runs_its_own_shell.py +256 -0
  52. voyd-0.1.0/tests/test_the_suite_cleans_up_after_itself.py +92 -0
  53. voyd-0.1.0/tests/test_the_wire_survives_a_real_client.py +472 -0
  54. voyd-0.1.0/uv.lock +1059 -0
  55. voyd-0.1.0/voyd/__init__.py +105 -0
  56. voyd-0.1.0/voyd/declare.py +649 -0
  57. voyd-0.1.0/voyd/engine/__init__.py +111 -0
  58. voyd-0.1.0/voyd/engine/admission/__init__.py +120 -0
  59. voyd-0.1.0/voyd/engine/admission/composition.py +120 -0
  60. voyd-0.1.0/voyd/engine/admission/core.py +814 -0
  61. voyd-0.1.0/voyd/engine/admission/handle.py +69 -0
  62. voyd-0.1.0/voyd/engine/admission/lineage.py +241 -0
  63. voyd-0.1.0/voyd/engine/admission/marks.py +560 -0
  64. voyd-0.1.0/voyd/engine/admission/reads.py +166 -0
  65. voyd-0.1.0/voyd/engine/admission/reasons.py +97 -0
  66. voyd-0.1.0/voyd/engine/admission/receipts.py +279 -0
  67. voyd-0.1.0/voyd/engine/admission/rerank.py +244 -0
  68. voyd-0.1.0/voyd/engine/admission/rules.py +895 -0
  69. voyd-0.1.0/voyd/engine/admission/sealing.py +256 -0
  70. voyd-0.1.0/voyd/engine/admission/spec.py +302 -0
  71. voyd-0.1.0/voyd/engine/admission/transforms.py +128 -0
  72. voyd-0.1.0/voyd/engine/attest.py +168 -0
  73. voyd-0.1.0/voyd/engine/authority.py +240 -0
  74. voyd-0.1.0/voyd/engine/capabilities.py +128 -0
  75. voyd-0.1.0/voyd/engine/custody.py +426 -0
  76. voyd-0.1.0/voyd/engine/errors.py +364 -0
  77. voyd-0.1.0/voyd/engine/expiry.py +92 -0
  78. voyd-0.1.0/voyd/engine/keyring.py +815 -0
  79. voyd-0.1.0/voyd/engine/plan.py +547 -0
  80. voyd-0.1.0/voyd/engine/py.typed +1 -0
  81. voyd-0.1.0/voyd/engine/search.py +456 -0
  82. voyd-0.1.0/voyd/engine/time.py +145 -0
  83. voyd-0.1.0/voyd/engine/trait.py +47 -0
  84. voyd-0.1.0/voyd/py.typed +1 -0
  85. voyd-0.1.0/voyd/wire/__init__.py +37 -0
  86. voyd-0.1.0/voyd/wire/__main__.py +19 -0
  87. voyd-0.1.0/voyd/wire/bench.py +758 -0
  88. voyd-0.1.0/voyd/wire/cascade.py +232 -0
  89. voyd-0.1.0/voyd/wire/cli.py +393 -0
  90. voyd-0.1.0/voyd/wire/codec.py +292 -0
  91. voyd-0.1.0/voyd/wire/ensure.py +179 -0
  92. voyd-0.1.0/voyd/wire/health.py +66 -0
  93. voyd-0.1.0/voyd/wire/identity.py +190 -0
  94. voyd-0.1.0/voyd/wire/metrics.py +552 -0
  95. voyd-0.1.0/voyd/wire/plan.py +504 -0
  96. voyd-0.1.0/voyd/wire/plan_report.py +347 -0
  97. voyd-0.1.0/voyd/wire/policy/__init__.py +97 -0
  98. voyd-0.1.0/voyd/wire/policy/erasure.py +137 -0
  99. voyd-0.1.0/voyd/wire/policy/guarding.py +460 -0
  100. voyd-0.1.0/voyd/wire/policy/handshake.py +110 -0
  101. voyd-0.1.0/voyd/wire/policy/reads.py +526 -0
  102. voyd-0.1.0/voyd/wire/policy/refusals.py +327 -0
  103. voyd-0.1.0/voyd/wire/policy/verbs.py +287 -0
  104. voyd-0.1.0/voyd/wire/preflight.py +429 -0
  105. voyd-0.1.0/voyd/wire/proxy.py +1149 -0
  106. voyd-0.1.0/voyd/wire/report.py +98 -0
  107. voyd-0.1.0/voyd/wire/seal.py +631 -0
  108. voyd-0.1.0/voyd/wire/upstream.py +277 -0
  109. voyd-0.1.0/voydfile.py +20 -0
@@ -0,0 +1,48 @@
1
+ # Without this file, `COPY . .` in the Dockerfile copies the whole working
2
+ # directory into the image. Three of those things must never be in there:
3
+ #
4
+ # .env real credentials, baked into a layer that anyone who pulls the
5
+ # image can read. This is the one that matters.
6
+ # .venv 248MB of host-built binaries, copied *over* the venv `uv sync`
7
+ # just created one layer earlier -- so the image was both enormous
8
+ # and holding an environment linked against the wrong machine.
9
+ # .git the full history, including anything ever committed to it.
10
+ #
11
+ # Everything the build actually needs is copied explicitly before this point
12
+ # (pyproject.toml, uv.lock, README.md, voyd/) or is source that `COPY . .` is
13
+ # there to pick up (voydfile.py, examples/, tests/, scanner/).
14
+
15
+ # Secrets. Every suffixed variant, because the one that leaks is always the
16
+ # one nobody thought to list.
17
+ .env
18
+ .env.*
19
+
20
+ # Environments and build output -- recreated inside the image.
21
+ .venv/
22
+ dist/
23
+ build/
24
+ *.egg-info/
25
+
26
+ # History and CI, which the runtime has no use for.
27
+ .git/
28
+ .github/
29
+ .gitignore
30
+
31
+ # Caches, none of which are portable across machines.
32
+ __pycache__/
33
+ *.py[cod]
34
+ .ruff_cache/
35
+ .pytest_cache/
36
+ .mypy_cache/
37
+
38
+ # Editor, agent and OS noise.
39
+ .DS_Store
40
+ .claude/
41
+ .idea/
42
+ .vscode/
43
+ *.swp
44
+
45
+ # Compose files: the image is a build artifact, not the orchestration.
46
+ docker-compose*.yml
47
+ Dockerfile
48
+ .dockerignore
@@ -0,0 +1,55 @@
1
+ name: policy-plan
2
+
3
+ # This repository runs the check it ships. `voydfile.py` at the root is
4
+ # the example policy, and a pull request that edits it gets the same
5
+ # report a user's would -- which is the only way the action stays true:
6
+ # a delivery mechanism nobody exercises rots exactly like a man page.
7
+ #
8
+ # No cluster and no secret here. The structural half needs neither, and
9
+ # it is the half that carries `guard_removed` and `tenant_removed` --
10
+ # the findings a reviewer is least equipped to spot in a diff.
11
+
12
+ on:
13
+ pull_request:
14
+ paths:
15
+ - voydfile.py
16
+ - action.yml
17
+ - voyd/engine/plan.py
18
+ - voyd/wire/plan.py
19
+
20
+ permissions:
21
+ contents: read
22
+ pull-requests: write
23
+
24
+ concurrency:
25
+ group: policy-plan-${{ github.ref }}
26
+ cancel-in-progress: true
27
+
28
+ jobs:
29
+ plan:
30
+ runs-on: ubuntu-latest
31
+ timeout-minutes: 5
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+ with:
35
+ # The action reads the policy in force out of git, so the base
36
+ # commit has to be in the clone. A shallow one would send it
37
+ # looking for an object that is not there and report the change
38
+ # as "the first voydfile", which is the wrong answer in the
39
+ # admitting direction.
40
+ fetch-depth: 0
41
+
42
+ - uses: ./
43
+ id: plan
44
+ with:
45
+ policy: voydfile.py
46
+
47
+ # The artifact is the half a terminal cannot give you: what the
48
+ # check said, tied to the digest of the exact policy files it said
49
+ # it about, kept after the runner is gone.
50
+ - uses: actions/upload-artifact@v4
51
+ if: always()
52
+ with:
53
+ name: voyd-plan-attestation
54
+ path: ${{ steps.plan.outputs.attestation }}
55
+ if-no-files-found: error
@@ -0,0 +1,168 @@
1
+ name: test
2
+
3
+ # Small on purpose. The suite is the foundation the rewrite stands on, not a
4
+ # census, and it is split by what a test *needs* rather than by how many
5
+ # there are -- a number in a comment is wrong one commit after somebody
6
+ # writes it, which this repository has now been bitten by twice.
7
+ #
8
+ # Most of it needs no database. The per-document check, every decision in
9
+ # the policy package, the wire codec and the custody rungs are pure, which
10
+ # is what lets the same check run inside a proxy in the first place. What
11
+ # needs a real `mongod` says so with `needs_mongo` and gets one, because
12
+ # those claims are about queries and bytes and a mock would only prove the
13
+ # mock was filtered.
14
+
15
+ on:
16
+ push:
17
+ branches: [main]
18
+ pull_request:
19
+
20
+ concurrency:
21
+ group: test-${{ github.ref }}
22
+ cancel-in-progress: true
23
+
24
+ jobs:
25
+ test:
26
+ runs-on: ubuntu-latest
27
+ timeout-minutes: 10
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+
31
+ - name: Start Atlas Local (mongod + mongot)
32
+ run: docker compose up -d --wait mongo
33
+
34
+ - name: Start the three-node replica set
35
+ # Fan-out is the one claim Atlas Local cannot test: it is a
36
+ # single-node set, so every routing assertion against it would pass
37
+ # by having nowhere else to send a read. This rig also enables
38
+ # `configureFailPoint`, which is how replication lag gets *caused*
39
+ # rather than waited for.
40
+ run: docker compose up -d --wait rs
41
+
42
+ - uses: astral-sh/setup-uv@v6
43
+ with:
44
+ python-version: "3.11"
45
+
46
+ - name: Sync
47
+ run: uv sync --all-extras
48
+
49
+ - name: Lint
50
+ run: uv run --no-sync ruff check voyd/ tests/ examples/ scanner/
51
+
52
+ - name: Types, because the wheel ships py.typed
53
+ # `voyd/py.typed` tells every downstream checker that these
54
+ # annotations are load-bearing. That is a promise made in the
55
+ # artifact, so it is checked here rather than trusted.
56
+ run: uv run --no-sync mypy
57
+
58
+ - name: The core needs no database
59
+ # If this step ever needs `services:`, the boundary has stopped being
60
+ # pure -- and a per-document check that cannot run without a database
61
+ # is one that cannot move to a wire, a browser, or anywhere else.
62
+ #
63
+ # Selected by marker rather than by filename, so a new pure file is
64
+ # covered the moment it is written and a new *impure* one has to
65
+ # declare itself `needs_mongo` to be skipped here. A list of paths
66
+ # silently stops covering whatever was added after it.
67
+ run: |
68
+ uv run --no-sync pytest -q -m 'not needs_mongo'
69
+
70
+ - name: The container is the deployment story, so it is built and run
71
+ # The deployment path is a claim like any other and gets the same
72
+ # treatment. It builds, it runs as a non-root uid, it answers
73
+ # --version, and its HEALTHCHECK command fails when there is
74
+ # nothing to be healthy about.
75
+ run: |
76
+ docker build -t voyd:ci .
77
+ test "$(docker run --rm --entrypoint id -u voyd:ci)" != "0"
78
+ docker run --rm voyd:ci --version
79
+ docker run --rm --entrypoint voyd-wire-health voyd:ci --port 1 \
80
+ && { echo "health passed with nothing listening"; exit 1; } \
81
+ || echo "health correctly failed"
82
+ # And it serves: a sidecar-shaped run, a client on the container's
83
+ # own loopback, an expired row refused and a delete become a
84
+ # revocation with every row still on disk.
85
+ docker run -d --name voyd-ci --network host voyd:ci \
86
+ --config voydfile.py --listen 27099 --metrics 27100 \
87
+ --target 127.0.0.1:27018
88
+ for _ in $(seq 30); do
89
+ docker exec voyd-ci voyd-wire-health && break || sleep 1
90
+ done
91
+ docker exec voyd-ci voyd-wire-health
92
+ docker rm -f voyd-ci
93
+
94
+ - name: The scanner runs on a machine with nothing installed
95
+ # It is the first thing a stranger runs and the only thing here that
96
+ # judges code nobody on this side has seen, so the claim that it
97
+ # needs no install is tested by uninstalling everything: a bare
98
+ # interpreter, no `uv sync`, no `pip install`, no PYTHONPATH.
99
+ run: python3 scanner/voyd_scan --strict voyd/ scanner/
100
+
101
+ - name: Importing voyd is the policy vocabulary and one driver
102
+ run: |
103
+ uv run --no-sync python -c "
104
+ import sys, voyd
105
+ assert 'guard' in voyd.__all__ and 'Engine' not in voyd.__all__
106
+ third = {m.split('.')[0] for m in sys.modules
107
+ if not m.startswith(('_', 'voyd'))} - sys.stdlib_module_names
108
+ unexpected = third - {'pymongo', 'bson', 'gridfs', 'dns',
109
+ 'pymongocrypt', 'cryptography'}
110
+ assert not unexpected, f'importing voyd pulled {sorted(unexpected)}'
111
+ print('clean:', sorted(voyd.__all__))"
112
+
113
+ - name: The wheel builds, ships the proxy, and exposes no handle
114
+ run: |
115
+ uv build
116
+ uv venv /tmp/wheelcheck
117
+ VIRTUAL_ENV=/tmp/wheelcheck uv pip install dist/*.whl
118
+ /tmp/wheelcheck/bin/python -c "
119
+ import voyd, voyd.engine
120
+ from voyd import guard, deadline, revocable
121
+ # There is one way to use this and it is not an import. An
122
+ # application-facing handle re-exported from either module would
123
+ # be a second door onto the guarantee, added silently, and a
124
+ # wheel built from a dirty tree is where that would show up.
125
+ for name in ('Engine', 'Model'):
126
+ assert not hasattr(voyd, name), f'voyd.{name} is in the wheel'
127
+ assert not hasattr(voyd.engine, name), f'voyd.engine.{name} is in the wheel'
128
+ # And the product is *in* the wheel. The other half of the same
129
+ # assertion: a distribution shipping the vocabulary to write a
130
+ # policy and nothing that can serve one is not the artifact.
131
+ import voyd.wire, voyd.wire.proxy, voyd.wire.seal, voyd.wire.cascade
132
+ import voyd.wire.cli, voyd.wire.upstream, voyd.wire.identity
133
+ assert callable(voyd.wire.cli.main)
134
+ print('wheel: the policy vocabulary imports, the proxy ships')"
135
+ test -x /tmp/wheelcheck/bin/voyd-wire
136
+ /tmp/wheelcheck/bin/voyd-wire --help > /dev/null
137
+
138
+ - name: End to end, real driver through a real boundary
139
+ # Atlas Local is a real mongod and a real mongot, not a mock.
140
+ #
141
+ # `-m ""` clears the default deselection. The one `slow` test it
142
+ # lets in needs a cluster that has registered an embedding model:
143
+ # Atlas Local *declines* an `auto_embed` declaration rather than
144
+ # honouring it, and a run that accepted the fallback would assert
145
+ # the opposite of what it claims.
146
+ #
147
+ # So the secret is passed through if the repository has one and
148
+ # the test skips by name if it does not -- a fork's CI is green
149
+ # for a reason it can read, rather than red for one it cannot fix.
150
+ # `-rs` prints every skip, because a claim that quietly stopped
151
+ # being checked is the failure this suite exists to notice.
152
+ env:
153
+ VOYD_TEST_MONGO_URI: mongodb://localhost:27018/?directConnection=true
154
+ VOYD_ATLAS_URI: ${{ secrets.VOYD_ATLAS_URI }}
155
+ run: uv run --no-sync pytest -q -rs -m "" tests/
156
+
157
+ - name: The examples are the documentation, so they have to run
158
+ env:
159
+ VOYD_MONGO_URI: mongodb://localhost:27018/?directConnection=true
160
+ run: |
161
+ for f in examples/*.py; do
162
+ echo "--- $f"
163
+ uv run --no-sync python "$f" > /dev/null || exit 1
164
+ done
165
+
166
+ - name: Mongo logs on failure
167
+ if: failure()
168
+ run: docker compose logs mongo | tail -100
voyd-0.1.0/.gitignore ADDED
@@ -0,0 +1,234 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ #
152
+ # ``.env`` alone is not enough: it leaves ``.env.local``, ``.env.production``
153
+ # and every other suffixed variant committable, and the one that leaks is
154
+ # always the one nobody thought to list. So the rule is every ``.env.*``,
155
+ # which is the same fail-closed direction the read path takes, applied to the
156
+ # repository. A tracked template would need an explicit ``!`` exception here.
157
+ .env
158
+ .env.*
159
+ .envrc
160
+ .venv
161
+ env/
162
+ venv/
163
+ ENV/
164
+ env.bak/
165
+ venv.bak/
166
+
167
+ # Spyder project settings
168
+ .spyderproject
169
+ .spyproject
170
+
171
+ # Rope project settings
172
+ .ropeproject
173
+
174
+ # mkdocs documentation
175
+ /site
176
+
177
+ # mypy
178
+ .mypy_cache/
179
+ .dmypy.json
180
+ dmypy.json
181
+
182
+ # Pyre type checker
183
+ .pyre/
184
+
185
+ # pytype static type analyzer
186
+ .pytype/
187
+
188
+ # Cython debug symbols
189
+ cython_debug/
190
+
191
+ # PyCharm
192
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
193
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
194
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
195
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
196
+ # .idea/
197
+
198
+ # Abstra
199
+ # Abstra is an AI-powered process automation framework.
200
+ # Ignore directories containing user credentials, local state, and settings.
201
+ # Learn more at https://abstra.io/docs
202
+ .abstra/
203
+
204
+ # Visual Studio Code
205
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
206
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
207
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
208
+ # you could uncomment the following to ignore the entire vscode folder
209
+ # .vscode/
210
+ # Temporary file for partial code execution
211
+ tempCodeRunnerFile.py
212
+
213
+ # Ruff stuff:
214
+ .ruff_cache/
215
+
216
+ # PyPI configuration file
217
+ .pypirc
218
+
219
+ # Marimo
220
+ marimo/_static/
221
+ marimo/_lsp/
222
+ __marimo__/
223
+
224
+ # Streamlit
225
+ .streamlit/secrets.toml
226
+
227
+ # Local agent/editor state. Per-machine permissions and paths, not project
228
+ # configuration -- committing it shares one person's local allowlist with
229
+ # everybody who clones.
230
+ .claude/
231
+
232
+ # Written by `voyd-bench` when no --policy is given, so it appears
233
+ # after any suite run that exercises the benchmark. Generated, never edited.
234
+ .voyd_bench_policy.py
voyd-0.1.0/Dockerfile ADDED
@@ -0,0 +1,72 @@
1
+ FROM python:3.11-slim
2
+
3
+ COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
4
+
5
+ WORKDIR /app
6
+
7
+ # Dependency metadata first, so a code change does not invalidate the layer
8
+ # that resolved and installed the environment. README.md is here because
9
+ # pyproject declares it as the package readme and the build reads it.
10
+ COPY pyproject.toml uv.lock* README.md ./
11
+
12
+ # The package itself, before `uv sync`, because this project is installed
13
+ # rather than merely depended on -- hatchling needs `voyd/` present to build
14
+ # the wheel it then installs.
15
+ COPY voyd/ voyd/
16
+
17
+ # The boundary needs a MongoDB driver and nothing else. `all` adds the one
18
+ # extra there is -- `crypto`, for the `sealed()` and `--key-vault` path -- so
19
+ # the image can serve a policy that seals a field without being rebuilt.
20
+ RUN uv sync --extra all --frozen --no-dev || uv sync --extra all --no-dev
21
+
22
+ # The policy file, the proxy and the examples. Last, because they change most
23
+ # often and nothing above depends on them.
24
+ COPY . .
25
+
26
+ # Not root. The boundary opens one listening socket above 1024, reads a
27
+ # policy file and forwards bytes; nothing it does needs privilege, and a
28
+ # process that holds a database's front door is the last one that should
29
+ # have any. `--chown` because `uv sync` wrote the venv as root.
30
+ RUN useradd --uid 10001 --no-create-home --shell /usr/sbin/nologin voyd \
31
+ && chown -R 10001:10001 /app
32
+ USER 10001
33
+
34
+ # Where `uv sync` put the interpreter, so the entry point is the console
35
+ # script rather than `uv run` -- which re-resolves the environment on every
36
+ # container start and needs a writable cache it no longer has.
37
+ ENV PATH="/app/.venv/bin:$PATH"
38
+
39
+ # The wire boundary, not an HTTP service: what comes out of 27099 is the
40
+ # MongoDB protocol. Mount your own `voydfile.py` over the example one and
41
+ # point `--target` at your cluster.
42
+ #
43
+ # **Run it as a sidecar**, sharing a network namespace with the
44
+ # application -- a Kubernetes pod, or `--network container:<app>`. That is
45
+ # not a workaround, it is the strongest shape available: the application
46
+ # reaches the boundary on `localhost`, nothing else on the network can
47
+ # reach it at all, and there is no route around it to bypass.
48
+ #
49
+ # It is also the only shape that works everywhere. Without `--tls-cert`
50
+ # the listener binds loopback, deliberately -- a plaintext boundary
51
+ # reachable from a network would carry in the clear every document it had
52
+ # just refused to serve. Publishing 27099 with `-p` happens to work on
53
+ # Docker Desktop, whose forwarder runs inside the namespace, and does not
54
+ # on Linux, whose DNAT targets the container's own address. Cross a
55
+ # network with `--tls-cert`, not with a port mapping.
56
+ #
57
+ # 27100 is different and is meant to be published: `/metrics` for a
58
+ # scrape and `/health` for a probe, both cross-pod by nature.
59
+ EXPOSE 27100
60
+
61
+ # Readiness, not liveness, and the distinction is the point: this asks
62
+ # whether the *upstream* is reachable, because a bound socket answers yes
63
+ # while the deployment behind it is gone. Orchestrators that read this
64
+ # label get it for free; Kubernetes wants it spelled out in the manifest,
65
+ # where the same URL is the readinessProbe.
66
+ HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=3 \
67
+ CMD ["voyd-wire-health"]
68
+
69
+ ENTRYPOINT ["voyd-wire"]
70
+ CMD ["--config", "voydfile.py", "--listen", "27099", \
71
+ "--metrics", "27100", "--metrics-bind", "0.0.0.0", \
72
+ "--target", "host.docker.internal:27017"]
voyd-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fabian Valle
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.