diaspore 0.2.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.
- diaspore-0.2.0/.gitignore +29 -0
- diaspore-0.2.0/LICENSE +21 -0
- diaspore-0.2.0/PKG-INFO +150 -0
- diaspore-0.2.0/README.md +130 -0
- diaspore-0.2.0/docs/dspb.md +97 -0
- diaspore-0.2.0/docs/security.md +94 -0
- diaspore-0.2.0/docs/spec.md +714 -0
- diaspore-0.2.0/pyproject.toml +68 -0
- diaspore-0.2.0/src/diaspore/__init__.py +69 -0
- diaspore-0.2.0/src/diaspore/cli.py +326 -0
- diaspore-0.2.0/src/diaspore/compiler.py +1289 -0
- diaspore-0.2.0/src/diaspore/dspb.py +704 -0
- diaspore-0.2.0/src/diaspore/encoding.py +143 -0
- diaspore-0.2.0/src/diaspore/ir.py +464 -0
- diaspore-0.2.0/src/diaspore/py.typed +0 -0
- diaspore-0.2.0/src/diaspore/stdlib/_pyparse.py +1749 -0
- diaspore-0.2.0/src/diaspore/stdlib/_pyunparse.py +253 -0
- diaspore-0.2.0/src/diaspore/stdlib/ast.py +1338 -0
- diaspore-0.2.0/src/diaspore/stdlib/asyncio.py +127 -0
- diaspore-0.2.0/src/diaspore/stdlib/base64.py +128 -0
- diaspore-0.2.0/src/diaspore/stdlib/binascii.py +44 -0
- diaspore-0.2.0/src/diaspore/stdlib/collections/__init__.py +182 -0
- diaspore-0.2.0/src/diaspore/stdlib/collections/abc.py +110 -0
- diaspore-0.2.0/src/diaspore/stdlib/contextlib.py +116 -0
- diaspore-0.2.0/src/diaspore/stdlib/copy.py +72 -0
- diaspore-0.2.0/src/diaspore/stdlib/dataclasses.py +312 -0
- diaspore-0.2.0/src/diaspore/stdlib/fractions.py +101 -0
- diaspore-0.2.0/src/diaspore/stdlib/functools.py +78 -0
- diaspore-0.2.0/src/diaspore/stdlib/gc.py +11 -0
- diaspore-0.2.0/src/diaspore/stdlib/gzip.py +105 -0
- diaspore-0.2.0/src/diaspore/stdlib/hashlib.py +187 -0
- diaspore-0.2.0/src/diaspore/stdlib/io.py +55 -0
- diaspore-0.2.0/src/diaspore/stdlib/itertools.py +174 -0
- diaspore-0.2.0/src/diaspore/stdlib/operator.py +188 -0
- diaspore-0.2.0/src/diaspore/stdlib/os/__init__.py +82 -0
- diaspore-0.2.0/src/diaspore/stdlib/os/path.py +122 -0
- diaspore-0.2.0/src/diaspore/stdlib/pathlib.py +361 -0
- diaspore-0.2.0/src/diaspore/stdlib/queue.py +107 -0
- diaspore-0.2.0/src/diaspore/stdlib/socket.py +241 -0
- diaspore-0.2.0/src/diaspore/stdlib/string.py +54 -0
- diaspore-0.2.0/src/diaspore/stdlib/threading.py +268 -0
- diaspore-0.2.0/src/diaspore/stdlib/types.py +86 -0
- diaspore-0.2.0/src/diaspore/stdlib/unittest.py +295 -0
- diaspore-0.2.0/src/diaspore/stdlib/weakref.py +76 -0
- diaspore-0.2.0/src/diaspore/stdlib/zlib.py +380 -0
- diaspore-0.2.0/src/diaspore/validator.py +315 -0
- diaspore-0.2.0/src/diaspore/vm.py +3905 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
.venv/
|
|
3
|
+
__pycache__/
|
|
4
|
+
*.pyc
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
.ruff_cache/
|
|
7
|
+
|
|
8
|
+
# Node
|
|
9
|
+
node_modules/
|
|
10
|
+
runtimes/ts/dist/
|
|
11
|
+
runtimes/ts/LICENSE
|
|
12
|
+
runtimes/ts/*.tgz
|
|
13
|
+
|
|
14
|
+
# Build output (see `make generate`, `make build` and `make site`)
|
|
15
|
+
build/
|
|
16
|
+
*.dsp.json
|
|
17
|
+
*.dsp.json.gz
|
|
18
|
+
*.dspb
|
|
19
|
+
*.dspb.gz
|
|
20
|
+
*.flow.json
|
|
21
|
+
site/diaspore.wasm
|
|
22
|
+
site/wasm_exec.js
|
|
23
|
+
site/stdlib.json
|
|
24
|
+
site/build.json
|
|
25
|
+
site/ir.schema.json
|
|
26
|
+
tests/fuzz_failures/
|
|
27
|
+
runtimes/go/dspc/stdlib.json.gz
|
|
28
|
+
runtimes/ts/stdlib/
|
|
29
|
+
runtimes/ts/.stdlib-stamp
|
diaspore-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 diaspore contributors
|
|
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.
|
diaspore-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: diaspore
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Compile a Python subset to portable JSON for Python, Go, TypeScript, and Lua runtimes
|
|
5
|
+
Project-URL: Homepage, https://radkawar.github.io/diaspore
|
|
6
|
+
Project-URL: Repository, https://github.com/radkawar/diaspore
|
|
7
|
+
License: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: compiler,interpreter,portable,python,sandbox
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Software Development :: Compilers
|
|
17
|
+
Classifier: Topic :: Software Development :: Interpreters
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Diaspore
|
|
22
|
+
|
|
23
|
+
Write Python. Ship JSON. Run it anywhere, sandboxed.
|
|
24
|
+
|
|
25
|
+
Diaspore compiles a large subset of Python into a portable JSON bundle and runs
|
|
26
|
+
it with identical output on four runtimes: Python, Go, TypeScript and Lua. A
|
|
27
|
+
bundle has no ambient authority, runs on a fuel budget, and can pause itself
|
|
28
|
+
into a JSON snapshot that any other runtime can resume.
|
|
29
|
+
|
|
30
|
+
[Playground](https://radkawar.github.io/diaspore) |
|
|
31
|
+
[Specification](https://github.com/radkawar/diaspore/blob/main/docs/spec.md) | [Security model](https://github.com/radkawar/diaspore/blob/main/docs/security.md) |
|
|
32
|
+
[Examples](https://github.com/radkawar/diaspore/blob/main/examples) | [Releases](https://github.com/radkawar/diaspore/releases)
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
diaspore build app.py -o app.dsp.json # compile once
|
|
36
|
+
diaspore run app.dsp.json # Python
|
|
37
|
+
diaspore-go run app.dsp.json # Go
|
|
38
|
+
npx diaspore-ts run app.dsp.json # TypeScript
|
|
39
|
+
lua5.4 runtimes/lua/cli.lua run app.dsp.json # Lua
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- **Portable.** One JSON artifact: diffable, signable, storable in a database
|
|
45
|
+
column, validated before it runs.
|
|
46
|
+
- **Sandboxed.** Network, file system and task spawning are denied unless
|
|
47
|
+
granted. `--max-steps` caps CPU; exhausting it is an uncatchable trap.
|
|
48
|
+
- **Embeddable.** Hosts expose functions as an importable module and call into
|
|
49
|
+
the sandbox. Python, Go, TypeScript and Lua hosts share one model.
|
|
50
|
+
- **Durable.** `flow.suspend()` pauses a program into a snapshot. Resume it
|
|
51
|
+
later, in another process, on another runtime.
|
|
52
|
+
- **Self-hosted.** The compiler is written in the subset it compiles. The Go and
|
|
53
|
+
TypeScript runtimes embed it, so they build Python without Python, and so does
|
|
54
|
+
the [browser playground](https://radkawar.github.io/diaspore).
|
|
55
|
+
- **Conformant.** Every corpus program must match CPython byte for byte on every
|
|
56
|
+
runtime, backed by differential fuzzing.
|
|
57
|
+
|
|
58
|
+
## Runtimes
|
|
59
|
+
|
|
60
|
+
| Runtime | Install | Notes |
|
|
61
|
+
| --- | --- | --- |
|
|
62
|
+
| diaspore-py | `uv tool install diaspore` | Reference VM, compiler and CLI |
|
|
63
|
+
| diaspore-go | [Release binaries](https://github.com/radkawar/diaspore/releases); library: `go get github.com/radkawar/diaspore/runtimes/go` | Near CPython speed; also compiles to WebAssembly |
|
|
64
|
+
| diaspore-ts | [`npm install diaspore`](https://www.npmjs.com/package/diaspore) | Node 22+, no runtime dependencies |
|
|
65
|
+
| diaspore-lua | [Release tarball](https://github.com/radkawar/diaspore/releases) | Pure Lua 5.4; no tasks, regex or big integers |
|
|
66
|
+
|
|
67
|
+
Sources: [src/diaspore](https://github.com/radkawar/diaspore/blob/main/src/diaspore), [runtimes/go](https://github.com/radkawar/diaspore/blob/main/runtimes/go),
|
|
68
|
+
[runtimes/ts](https://github.com/radkawar/diaspore/blob/main/runtimes/ts), [runtimes/lua](https://github.com/radkawar/diaspore/blob/main/runtimes/lua).
|
|
69
|
+
|
|
70
|
+
## Getting started
|
|
71
|
+
|
|
72
|
+
Install the compiler and reference runtime with
|
|
73
|
+
[uv](https://docs.astral.sh/uv/):
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
uv tool install diaspore
|
|
77
|
+
diaspore build main.py -o main.dsp.json
|
|
78
|
+
diaspore run main.dsp.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Run the same bundle from Node, or embed it:
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
npm install diaspore
|
|
85
|
+
npx diaspore-ts run main.dsp.json
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
To build everything from source you need Go 1.26+; Node 23.6+ and Lua 5.4 are
|
|
89
|
+
needed only for their runtimes.
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
git clone https://github.com/radkawar/diaspore && cd diaspore
|
|
93
|
+
uv sync
|
|
94
|
+
make build # embedded compiler + build/diaspore-go
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Then try the [examples](https://github.com/radkawar/diaspore/blob/main/examples), starting with
|
|
98
|
+
[embedding](https://github.com/radkawar/diaspore/blob/main/examples/embedding): one sandboxed plugin hosted from all four
|
|
99
|
+
languages.
|
|
100
|
+
|
|
101
|
+
## Embedding
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from diaspore import Machine, compile_bundle
|
|
105
|
+
|
|
106
|
+
bundle = compile_bundle("plugin.py", extra_modules={"host"})
|
|
107
|
+
vm = Machine(bundle, bindings={"host": {"lookup": lookup}}, max_steps=1_000_000)
|
|
108
|
+
vm.run()
|
|
109
|
+
price = vm.call("plugin", "price", order)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The same pattern in [Go](https://github.com/radkawar/diaspore/blob/main/runtimes/go#embedding),
|
|
113
|
+
[TypeScript](https://github.com/radkawar/diaspore/blob/main/runtimes/ts#embedding) and [Lua](https://github.com/radkawar/diaspore/blob/main/runtimes/lua#embedding).
|
|
114
|
+
|
|
115
|
+
## Language
|
|
116
|
+
|
|
117
|
+
Functions, closures, classes with multiple inheritance, generators,
|
|
118
|
+
`async`/`await`, exceptions including `except*`, `match`, comprehensions,
|
|
119
|
+
f-strings, arbitrary-precision integers, multi-module packages, and a portable
|
|
120
|
+
standard library (`json`, `math`, `re`, `time`, `random`, `collections`,
|
|
121
|
+
`itertools`, `functools` and more). Unsupported syntax is a compile error with a
|
|
122
|
+
`file:line`, never a silent runtime failure. The exact surface is in
|
|
123
|
+
[docs/spec.md](https://github.com/radkawar/diaspore/blob/main/docs/spec.md).
|
|
124
|
+
|
|
125
|
+
## Repository
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
src/diaspore/ compiler, reference VM, CLI, standard library
|
|
129
|
+
selfhost/ dspc, the self-hosted compiler
|
|
130
|
+
runtimes/ go, ts and lua runtimes
|
|
131
|
+
examples/ runnable examples for every runtime
|
|
132
|
+
site/ playground and project site
|
|
133
|
+
docs/ specification, security model, binary format
|
|
134
|
+
tests/ conformance corpus and test suites
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Development
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
make test # every suite on every runtime
|
|
141
|
+
make lint # ruff, go vet, staticcheck, gofmt, tsc
|
|
142
|
+
make fuzz # differential fuzzing against CPython
|
|
143
|
+
make serve # build and serve the site on localhost:8000
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Run `make help` for the full list.
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
[MIT](https://github.com/radkawar/diaspore/blob/main/LICENSE)
|
diaspore-0.2.0/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Diaspore
|
|
2
|
+
|
|
3
|
+
Write Python. Ship JSON. Run it anywhere, sandboxed.
|
|
4
|
+
|
|
5
|
+
Diaspore compiles a large subset of Python into a portable JSON bundle and runs
|
|
6
|
+
it with identical output on four runtimes: Python, Go, TypeScript and Lua. A
|
|
7
|
+
bundle has no ambient authority, runs on a fuel budget, and can pause itself
|
|
8
|
+
into a JSON snapshot that any other runtime can resume.
|
|
9
|
+
|
|
10
|
+
[Playground](https://radkawar.github.io/diaspore) |
|
|
11
|
+
[Specification](https://github.com/radkawar/diaspore/blob/main/docs/spec.md) | [Security model](https://github.com/radkawar/diaspore/blob/main/docs/security.md) |
|
|
12
|
+
[Examples](https://github.com/radkawar/diaspore/blob/main/examples) | [Releases](https://github.com/radkawar/diaspore/releases)
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
diaspore build app.py -o app.dsp.json # compile once
|
|
16
|
+
diaspore run app.dsp.json # Python
|
|
17
|
+
diaspore-go run app.dsp.json # Go
|
|
18
|
+
npx diaspore-ts run app.dsp.json # TypeScript
|
|
19
|
+
lua5.4 runtimes/lua/cli.lua run app.dsp.json # Lua
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- **Portable.** One JSON artifact: diffable, signable, storable in a database
|
|
25
|
+
column, validated before it runs.
|
|
26
|
+
- **Sandboxed.** Network, file system and task spawning are denied unless
|
|
27
|
+
granted. `--max-steps` caps CPU; exhausting it is an uncatchable trap.
|
|
28
|
+
- **Embeddable.** Hosts expose functions as an importable module and call into
|
|
29
|
+
the sandbox. Python, Go, TypeScript and Lua hosts share one model.
|
|
30
|
+
- **Durable.** `flow.suspend()` pauses a program into a snapshot. Resume it
|
|
31
|
+
later, in another process, on another runtime.
|
|
32
|
+
- **Self-hosted.** The compiler is written in the subset it compiles. The Go and
|
|
33
|
+
TypeScript runtimes embed it, so they build Python without Python, and so does
|
|
34
|
+
the [browser playground](https://radkawar.github.io/diaspore).
|
|
35
|
+
- **Conformant.** Every corpus program must match CPython byte for byte on every
|
|
36
|
+
runtime, backed by differential fuzzing.
|
|
37
|
+
|
|
38
|
+
## Runtimes
|
|
39
|
+
|
|
40
|
+
| Runtime | Install | Notes |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| diaspore-py | `uv tool install diaspore` | Reference VM, compiler and CLI |
|
|
43
|
+
| diaspore-go | [Release binaries](https://github.com/radkawar/diaspore/releases); library: `go get github.com/radkawar/diaspore/runtimes/go` | Near CPython speed; also compiles to WebAssembly |
|
|
44
|
+
| diaspore-ts | [`npm install diaspore`](https://www.npmjs.com/package/diaspore) | Node 22+, no runtime dependencies |
|
|
45
|
+
| diaspore-lua | [Release tarball](https://github.com/radkawar/diaspore/releases) | Pure Lua 5.4; no tasks, regex or big integers |
|
|
46
|
+
|
|
47
|
+
Sources: [src/diaspore](https://github.com/radkawar/diaspore/blob/main/src/diaspore), [runtimes/go](https://github.com/radkawar/diaspore/blob/main/runtimes/go),
|
|
48
|
+
[runtimes/ts](https://github.com/radkawar/diaspore/blob/main/runtimes/ts), [runtimes/lua](https://github.com/radkawar/diaspore/blob/main/runtimes/lua).
|
|
49
|
+
|
|
50
|
+
## Getting started
|
|
51
|
+
|
|
52
|
+
Install the compiler and reference runtime with
|
|
53
|
+
[uv](https://docs.astral.sh/uv/):
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
uv tool install diaspore
|
|
57
|
+
diaspore build main.py -o main.dsp.json
|
|
58
|
+
diaspore run main.dsp.json
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Run the same bundle from Node, or embed it:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
npm install diaspore
|
|
65
|
+
npx diaspore-ts run main.dsp.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
To build everything from source you need Go 1.26+; Node 23.6+ and Lua 5.4 are
|
|
69
|
+
needed only for their runtimes.
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
git clone https://github.com/radkawar/diaspore && cd diaspore
|
|
73
|
+
uv sync
|
|
74
|
+
make build # embedded compiler + build/diaspore-go
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Then try the [examples](https://github.com/radkawar/diaspore/blob/main/examples), starting with
|
|
78
|
+
[embedding](https://github.com/radkawar/diaspore/blob/main/examples/embedding): one sandboxed plugin hosted from all four
|
|
79
|
+
languages.
|
|
80
|
+
|
|
81
|
+
## Embedding
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from diaspore import Machine, compile_bundle
|
|
85
|
+
|
|
86
|
+
bundle = compile_bundle("plugin.py", extra_modules={"host"})
|
|
87
|
+
vm = Machine(bundle, bindings={"host": {"lookup": lookup}}, max_steps=1_000_000)
|
|
88
|
+
vm.run()
|
|
89
|
+
price = vm.call("plugin", "price", order)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The same pattern in [Go](https://github.com/radkawar/diaspore/blob/main/runtimes/go#embedding),
|
|
93
|
+
[TypeScript](https://github.com/radkawar/diaspore/blob/main/runtimes/ts#embedding) and [Lua](https://github.com/radkawar/diaspore/blob/main/runtimes/lua#embedding).
|
|
94
|
+
|
|
95
|
+
## Language
|
|
96
|
+
|
|
97
|
+
Functions, closures, classes with multiple inheritance, generators,
|
|
98
|
+
`async`/`await`, exceptions including `except*`, `match`, comprehensions,
|
|
99
|
+
f-strings, arbitrary-precision integers, multi-module packages, and a portable
|
|
100
|
+
standard library (`json`, `math`, `re`, `time`, `random`, `collections`,
|
|
101
|
+
`itertools`, `functools` and more). Unsupported syntax is a compile error with a
|
|
102
|
+
`file:line`, never a silent runtime failure. The exact surface is in
|
|
103
|
+
[docs/spec.md](https://github.com/radkawar/diaspore/blob/main/docs/spec.md).
|
|
104
|
+
|
|
105
|
+
## Repository
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
src/diaspore/ compiler, reference VM, CLI, standard library
|
|
109
|
+
selfhost/ dspc, the self-hosted compiler
|
|
110
|
+
runtimes/ go, ts and lua runtimes
|
|
111
|
+
examples/ runnable examples for every runtime
|
|
112
|
+
site/ playground and project site
|
|
113
|
+
docs/ specification, security model, binary format
|
|
114
|
+
tests/ conformance corpus and test suites
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Development
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
make test # every suite on every runtime
|
|
121
|
+
make lint # ruff, go vet, staticcheck, gofmt, tsc
|
|
122
|
+
make fuzz # differential fuzzing against CPython
|
|
123
|
+
make serve # build and serve the site on localhost:8000
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Run `make help` for the full list.
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
[MIT](https://github.com/radkawar/diaspore/blob/main/LICENSE)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# DSPB: the optional binary bundle container
|
|
2
|
+
|
|
3
|
+
DSPB encodes the same semantic model as a JSON bundle in a compact binary
|
|
4
|
+
container. JSON remains the canonical form and default output. Every DSPB
|
|
5
|
+
implementation MUST preserve this invariant:
|
|
6
|
+
|
|
7
|
+
decode(encode(bundle)) == compact(bundle) (exact structural equality)
|
|
8
|
+
|
|
9
|
+
Digests (`bundle_digest`), validation, and all semantics operate on the
|
|
10
|
+
decoded model, so containers never affect meaning. Loaders sniff by magic
|
|
11
|
+
bytes; `.dspb.gz` (gzip over DSPB) is valid - gzip decoding re-sniffs its
|
|
12
|
+
payload. Reference implementation: `src/diaspore/dspb.py` (normative where this
|
|
13
|
+
document is ambiguous). Round-trip conformance: `tests/test_dspb.py`.
|
|
14
|
+
|
|
15
|
+
## Primitives
|
|
16
|
+
|
|
17
|
+
- varint - unsigned LEB128 (7 bits per byte, high bit = continuation).
|
|
18
|
+
- str-ref - varint index into the string table.
|
|
19
|
+
- byte - one raw byte.
|
|
20
|
+
|
|
21
|
+
## Layout
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
magic 6 bytes "DSPB01"
|
|
25
|
+
strtab varint count, then per string: varint byte-length + UTF-8 bytes
|
|
26
|
+
semver varint (1 - same value as JSON's "diaspore" field)
|
|
27
|
+
main str-ref
|
|
28
|
+
modules varint count, then per module:
|
|
29
|
+
name str-ref, file str-ref,
|
|
30
|
+
src-flag byte (0|1), if 1: str-list (varint count + str-refs)
|
|
31
|
+
body node-list
|
|
32
|
+
node-list varint count + that many nodes
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Nodes
|
|
36
|
+
|
|
37
|
+
Every node: opcode byte (index into the OPS table below), flags byte
|
|
38
|
+
(bit 0 = `ln` present -> varint follows; higher bits are the op's optional
|
|
39
|
+
fields in the listed order), then fields in fixed order.
|
|
40
|
+
|
|
41
|
+
Enum tables (indices are normative):
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
OPS = const name attr index slicelit starred call binop unary boolop
|
|
45
|
+
compare cond list tuple set dict fstring func funcexpr yield
|
|
46
|
+
yieldfrom namedexpr expr assign augassign if while for break
|
|
47
|
+
continue pass return class raise try with import importfrom del
|
|
48
|
+
BIN_KINDS = add sub mul div floordiv mod pow lshift rshift bitand bitor
|
|
49
|
+
bitxor matmul
|
|
50
|
+
CMP_KINDS = eq ne lt le gt ge in notin is isnot
|
|
51
|
+
UNARY = neg pos not invert
|
|
52
|
+
CONST = int float str bytes bool none ellipsis complex
|
|
53
|
+
CONV = (none) r s a
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Flag-bit optionals per op (bit 1 upward): `slicelit`: lower, upper, step;
|
|
57
|
+
`yield`/`return`: v; `raise`: exc, cause; `import`: alias.
|
|
58
|
+
|
|
59
|
+
Per-op payloads (after flags/ln). `N` = node, `L` = node-list,
|
|
60
|
+
`S` = str-ref, `SL` = varint count + str-refs:
|
|
61
|
+
|
|
62
|
+
| op | payload |
|
|
63
|
+
|---|---|
|
|
64
|
+
| const | kind byte; int/float/str/bytes -> S; complex -> S re, S im (float-strings); bool -> byte 0/1; none/ellipsis -> nothing |
|
|
65
|
+
| name | S id |
|
|
66
|
+
| attr | N o, S n |
|
|
67
|
+
| index | N o, N k |
|
|
68
|
+
| slicelit | optional N lower/upper/step per flags |
|
|
69
|
+
| starred / yieldfrom / expr | N v |
|
|
70
|
+
| call | N f, L args, varint kw-count x (byte named? [1 -> S name], N v) |
|
|
71
|
+
| binop | kind byte, N l, N r |
|
|
72
|
+
| augassign | kind byte, N target, N v |
|
|
73
|
+
| unary | kind byte, N v |
|
|
74
|
+
| boolop | byte (0=and, 1=or), L values |
|
|
75
|
+
| compare | N left, varint count x kind byte, L comps |
|
|
76
|
+
| cond | N test, N then, N else |
|
|
77
|
+
| list / tuple / set | L elts |
|
|
78
|
+
| dict | varint count x (byte has-key? [1 -> N k], N v) |
|
|
79
|
+
| fstring | varint count x part: byte flag (0 = text -> S; else bit0=value: N v, conv byte, bit1 -> N spec) |
|
|
80
|
+
| func / funcexpr | S name, byte flags (bit0 gen, bit1 coro), byte pflags (bit0 vararg, bit1 kwarg), SL args, L defaults, [S vararg], SL kwonly, varint kwdefault-count x (byte present? [1 -> N]), [S kwarg], SL locals, SL gdecl, SL ndecl, L body |
|
|
81
|
+
| yield / return | [N v] per flags |
|
|
82
|
+
| namedexpr | N target, N v |
|
|
83
|
+
| assign | L targets, N v |
|
|
84
|
+
| if / while | N test, L then/body, L orelse |
|
|
85
|
+
| for | N target, N iter, L body, L orelse |
|
|
86
|
+
| break / continue / pass | nothing |
|
|
87
|
+
| class | S name, byte kwflag, [kwargs: varint count x (byte named? [1->S n], N v)], L bases, L body |
|
|
88
|
+
| raise | [N exc], [N cause] per flags |
|
|
89
|
+
| try | byte star, L body, varint handler-count x (byte hflags: bit0 t, bit1 name; [N t], [S name], L body), L orelse, L finalbody |
|
|
90
|
+
| with | varint item-count x (byte has-name, N ctx, [N name]), L body |
|
|
91
|
+
| import | S module, byte bind (0 absent, 1 root, 2 none), [S alias] per flags |
|
|
92
|
+
| importfrom | S module, varint count x (S n, S alias) |
|
|
93
|
+
| del | L targets |
|
|
94
|
+
|
|
95
|
+
Decoding materializes the compact JSON form (spec section 2.2): empty lists,
|
|
96
|
+
false `gen`/`coro`/`star`, and absent optionals are omitted from the produced
|
|
97
|
+
dicts. Key order does not affect structural equality.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Diaspore security model
|
|
2
|
+
|
|
3
|
+
Diaspore runs Python-subset programs with explicit capabilities and resource
|
|
4
|
+
limits. The threat model assumes an adversary controls source code or a bundle,
|
|
5
|
+
but not the runtime, host process, embedding code, or deployment configuration.
|
|
6
|
+
The runtime must prevent access to host objects and authority not granted by the
|
|
7
|
+
host. Resource isolation also requires operating-system controls.
|
|
8
|
+
|
|
9
|
+
## Untrusted inputs
|
|
10
|
+
|
|
11
|
+
The compiler is not a security boundary. Treat bundles as untrusted data even
|
|
12
|
+
when they were produced by `dspc` (`selfhost/dspc.py`). The typed IR is defined in
|
|
13
|
+
`src/diaspore/ir.py`; generate its JSON Schema with `diaspore schema` or
|
|
14
|
+
`make schema`, or use the [published schema](https://radkawar.github.io/diaspore/ir.schema.json).
|
|
15
|
+
Schema validation does not establish that a program is safe or will terminate.
|
|
16
|
+
Apply input-size limits to source, bundles, compressed containers, and snapshots
|
|
17
|
+
before loading them.
|
|
18
|
+
|
|
19
|
+
## Capabilities and bindings
|
|
20
|
+
|
|
21
|
+
Without grants, programs can compute, allocate, use the configured standard
|
|
22
|
+
streams, inspect supplied arguments, and call available native modules such as
|
|
23
|
+
`math`, `json`, `random`, `time`, and `re`. Clock access and randomness do not
|
|
24
|
+
require capabilities. Standard input is also available through `input()`.
|
|
25
|
+
|
|
26
|
+
| Capability | Authority | Scoped grants |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `net` | TCP listeners and outbound connections | `--allow-net listen:HOST:PORT` or `connect:HOST:PORT`; `*` matches any host or port |
|
|
29
|
+
| `fs` | File access through `open` | `--allow-fs read:PATH` or `write:PATH`; resolved-path prefix matching |
|
|
30
|
+
| `spawn` | Tasks, channels, and locks | `--allow-spawn`; concurrency model in [spec section 11.9](spec.md#11-native-modules) |
|
|
31
|
+
|
|
32
|
+
A bare grant permits all operations covered by that capability. Scoped grants
|
|
33
|
+
deny operations not listed. Denied operations raise `PermissionError`.
|
|
34
|
+
Availability of native modules and capabilities differs by runtime; consult the
|
|
35
|
+
runtime README before deploying a policy.
|
|
36
|
+
|
|
37
|
+
Filesystem checks resolve symlinks before matching paths. They are not a
|
|
38
|
+
replacement for isolated mounts, especially where another process can modify
|
|
39
|
+
the filesystem between checking and opening a path. Network policy matches the
|
|
40
|
+
requested address, not a pinned DNS result. Use IP-based policies or a binding
|
|
41
|
+
that enforces destination policy when DNS changes are a concern.
|
|
42
|
+
|
|
43
|
+
Environment access, subprocesses, and FFI are not exposed as native sandbox APIs.
|
|
44
|
+
Where supported, `exec`, `eval`, and `compile` compile Diaspore-subset code and
|
|
45
|
+
execute it inside the VM; they do not execute arbitrary host Python.
|
|
46
|
+
|
|
47
|
+
Host bindings run with host privileges. Validate their inputs, keep their
|
|
48
|
+
interfaces narrow, and expose only the authority the program needs. A binding
|
|
49
|
+
can invalidate the sandbox's isolation if it evaluates input as host code or
|
|
50
|
+
performs unrestricted file or network operations.
|
|
51
|
+
|
|
52
|
+
## Resource limits
|
|
53
|
+
|
|
54
|
+
- Fuel (`--max-steps`) meters statements, calls, and selected bulk operations.
|
|
55
|
+
Exhaustion is an uncatchable trap with exit code 3.
|
|
56
|
+
- Recursion depth (`--max-depth`, default 1000) raises a catchable
|
|
57
|
+
`RecursionError` when exceeded.
|
|
58
|
+
- Fuel does not bound peak memory, time blocked in I/O or host bindings, or open
|
|
59
|
+
descriptors. Set process memory and CPU limits, descriptor limits, and an
|
|
60
|
+
external timeout for hostile workloads. Limit compiler resources as well as
|
|
61
|
+
runtime resources.
|
|
62
|
+
|
|
63
|
+
## Runtime isolation
|
|
64
|
+
|
|
65
|
+
The four runtimes are diaspore-py, diaspore-go, diaspore-ts, and diaspore-lua.
|
|
66
|
+
Their implementations and trusted dependencies differ. The Python reference VM
|
|
67
|
+
uses allowlisted operations on CPython values; Go, TypeScript, and Lua implement
|
|
68
|
+
sandbox values and operations within their respective host environments.
|
|
69
|
+
Memory safety and allowlists do not prove that an interpreter is escape-free.
|
|
70
|
+
|
|
71
|
+
For untrusted multi-tenant workloads, run each tenant in a separate restricted
|
|
72
|
+
process or container. Grant minimal filesystem and network access to that
|
|
73
|
+
process, regardless of which runtime it uses. Do not rely on an interpreter bug
|
|
74
|
+
being limited to a wrong result or a controlled crash.
|
|
75
|
+
|
|
76
|
+
## Durable flows and nondeterminism
|
|
77
|
+
|
|
78
|
+
Durable mode forbids `net`, `fs`, and `spawn` capabilities. Supported effects,
|
|
79
|
+
including host-binding results, are journaled for replay; snapshots contain JSON
|
|
80
|
+
data rather than interpreter internals (see [spec section 14](spec.md#14-durable-flows-suspend--resume)).
|
|
81
|
+
|
|
82
|
+
Snapshots contain effect results and can therefore contain secrets. Protect
|
|
83
|
+
their confidentiality and integrity. The bundle digest binds a snapshot to a
|
|
84
|
+
program; it does not authenticate the journal or its author. Accept snapshots
|
|
85
|
+
only from trusted storage or authenticate them at the application boundary.
|
|
86
|
+
|
|
87
|
+
Clock values, randomness, set iteration order, object identities, and allocation
|
|
88
|
+
behavior can be observable. Diaspore does not provide timing-side-channel
|
|
89
|
+
isolation. Durable programs must remain deterministic between journaled effects.
|
|
90
|
+
|
|
91
|
+
## Reporting
|
|
92
|
+
|
|
93
|
+
Report vulnerabilities by opening a
|
|
94
|
+
[GitHub security advisory](https://github.com/radkawar/diaspore/security/advisories/new).
|