projectwrap 202604.1__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Fredrik Håård
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.
@@ -0,0 +1,279 @@
1
+ Metadata-Version: 2.3
2
+ Name: projectwrap
3
+ Version: 202604.1
4
+ Summary: Isolated project environments with bubblewrap sandboxing
5
+ License: MIT
6
+ Keywords: sandbox,bubblewrap,bwrap,isolation,development,security
7
+ Author: Fredrik Håård
8
+ Author-email: fredrik@haard.se
9
+ Requires-Python: >=3.11,<4.0
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
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.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Security
20
+ Classifier: Topic :: System :: Systems Administration
21
+ Project-URL: Homepage, https://github.com/haard/project-wrap
22
+ Project-URL: Repository, https://github.com/haard/project-wrap
23
+ Description-Content-Type: text/markdown
24
+
25
+ # pwrap
26
+
27
+ pwrap wraps project shell environments in bubblewrap sandboxes, and aims to
28
+ _limit the blast radius_ of e.g. supply chain attacks and protect your production
29
+ infrastructure from your sloppy side project.
30
+
31
+
32
+
33
+ **Why**
34
+ I got tired of my ad-hoc fish bwrap scripts, and I'm increasingly worried about supply chain attacks.
35
+
36
+ If every side project feels like a potential vector — one [npm|pip|cargo] install away from pwned AWS credentials,
37
+ and custom-wrapping with bwrap and some vault product feels too fragile or too much work, pwrap might help.
38
+
39
+ **Status**
40
+ pwrap _works_ but has not been tested by anyone but me, and has not been
41
+ reviewed/audited by anyone except Opus 4.6 and codestral. pwrap comes with
42
+ _absolutely no warranty_.
43
+
44
+
45
+ **Does:**
46
+ - Launches sandboxed shells with per-project filesystem isolation
47
+ - Hides sensitive paths (credentials, configs, SSH keys) via tmpfs overlays
48
+ - Exposes only what each project needs (whitelisting)
49
+ - Mounts gocryptfs encrypted volumes inside isolated namespaces
50
+ - Runs init scripts for env vars, venv activation, aliases
51
+
52
+ **Doesn't do:**
53
+ - Network filtering (it's all-or-nothing via `unshare_net`)
54
+ - Container-level isolation (no cgroups, no seccomp, no resource limits)
55
+ - Do package management or dependency resolution
56
+ - Protect you from your own misconfiguration
57
+
58
+ **Dependencies:** Python 3.11+ (stdlib only, no pip dependencies),
59
+ [bubblewrap](https://github.com/containers/bubblewrap) for sandboxing,
60
+ [gocryptfs](https://nuetzlich.net/gocryptfs/) for encrypted volumes.
61
+
62
+ **Design principles:**
63
+ - **Reviewable** — small codebase, no pip dependencies, no magic
64
+ - **Fail fast** — invalid config is an error, not a warning
65
+ - **Explicit over convenient** — no implicit defaults that hide security decisions
66
+ - **Init scripts as the extension point** — env vars, venv, aliases all go there,
67
+ not in config schema
68
+
69
+ ## Installation
70
+
71
+ pwrap has no pip dependencies — only the standard library. For a security tool,
72
+ installing from source lets you audit what you're running:
73
+
74
+ ```bash
75
+ git clone https://github.com/haard/projectwrap
76
+ cd projectwrap
77
+ pip install --no-deps .
78
+ ```
79
+
80
+ Or from PyPI if you prefer convenience: `pipx install projectwrap`
81
+
82
+ Check optional dependencies with `pwrap --check-deps`.
83
+
84
+ ## Quick Start
85
+
86
+ ```bash
87
+ pwrap --new ~/projects/myproject # creates config + init script
88
+ # edit ~/.config/pwrap/myproject/project.toml and init script
89
+ pwrap myproject # launch sandboxed shell
90
+ ```
91
+
92
+ On first run, `--new` creates editable templates in `~/.config/pwrap/`. Edit them
93
+ to set your defaults, then run `--new` again.
94
+
95
+ ## Examples
96
+
97
+ ### Basic sandboxed project
98
+
99
+ `~/.config/pwrap/myproject/project.toml`:
100
+ ```toml
101
+ [project]
102
+ name = "myproject"
103
+ dir = "~/projects/myproject"
104
+ shell = "/usr/bin/fish"
105
+
106
+ [sandbox]
107
+ enabled = true
108
+ blacklist = [
109
+ "~/.kube",
110
+ "~/.aws",
111
+ "~/.ssh",
112
+ ]
113
+ whitelist = [
114
+ "~/.kube/myproject",
115
+ "~/.ssh/myproject_ed25519",
116
+ "~/.ssh/known_hosts",
117
+ ]
118
+ ```
119
+
120
+ `~/.config/pwrap/myproject/init.fish`:
121
+ ```fish
122
+ source .venv/bin/activate.fish
123
+ set -gx KUBECONFIG ~/.kube/myproject/config
124
+ set -gx GIT_SSH_COMMAND "ssh -i ~/.ssh/myproject_ed25519 -o IdentitiesOnly=yes"
125
+ ```
126
+
127
+ The config directory (`~/.config/pwrap`) is always blacklisted automatically — code
128
+ inside the sandbox cannot read other project configs.
129
+
130
+ ### Encrypted AI chat history
131
+
132
+ Keep aichat/Claude chat history encrypted at rest, decrypted only inside the sandbox.
133
+ Uses gocryptfs mounted in an isolated namespace (invisible on host).
134
+
135
+ **Setup:**
136
+ ```bash
137
+ # Initialize encrypted directory (once, prompts for password)
138
+ mkdir -p ~/.config/pwrap/myproject/encrypted
139
+ gocryptfs -init ~/.config/pwrap/myproject/encrypted
140
+ ```
141
+
142
+ **Config** (`project.toml`):
143
+ ```toml
144
+ [project]
145
+ name = "myproject"
146
+ dir = "~/projects/myproject"
147
+ shell = "/usr/bin/fish"
148
+
149
+ [sandbox]
150
+ enabled = true
151
+
152
+ [encrypted]
153
+ cipherdir = "encrypted"
154
+ mountpoint = "~/.local/share/aichat"
155
+ ```
156
+
157
+ **Init script** (`init.fish`):
158
+ ```fish
159
+ set -gx AICHAT_CONFIG_DIR ~/.local/share/aichat
160
+ # For Claude Code:
161
+ # set -gx CLAUDE_CONFIG_DIR ~/.local/share/claude
162
+ ```
163
+
164
+ On `pwrap myproject`, gocryptfs prompts for the password, mounts the decrypted
165
+ volume inside an isolated mount namespace, and launches the sandboxed shell.
166
+ The decrypted files are invisible to host processes and disappear when the shell
167
+ exits.
168
+
169
+ If you enter the wrong password, gocryptfs re-prompts up to its own retry limit
170
+ and then exits non-zero. pwrap aborts on that failure without launching the
171
+ sandbox — no shell starts, no partial mount is left behind. Re-run `pwrap
172
+ myproject` to try again.
173
+
174
+ **`PWRAP_VAULT_DIR`**: inside any sandbox with an `[encrypted]` section, pwrap
175
+ exports `PWRAP_VAULT_DIR` pointing at the mountpoint. Use it from init scripts
176
+ or app configs to redirect history/state into the vault without hardcoding the
177
+ path per project (e.g. `set savehist-file (expand-file-name "history" "$PWRAP_VAULT_DIR/emacs")`).
178
+
179
+ **You will appear as root inside encrypted projects.** Mounting gocryptfs
180
+ unprivileged requires `unshare --user --map-root-user`, so inside the sandbox
181
+ `whoami` reports `root` and `id -u` reports `0`. This is a user-namespace
182
+ remapping only — you have no real privileges on the host, cannot read
183
+ root-owned files outside the namespace, and cannot escalate. Your real files
184
+ (project dir, home bind-mounts, the vault mountpoint itself) remain owned by
185
+ your real uid. Scripts that gate on `[ "$UID" = 0 ]` will misbehave; prefer
186
+ `[ "$USER" = root ]` checks or, better, check the presence of
187
+ `$PROJECT_WRAP` / `$PWRAP_VAULT_DIR`.
188
+
189
+ **Multiple terminals** (`shared = false`, default): each terminal gets an
190
+ independent gocryptfs mount. Writes to different files merge on next session;
191
+ writes to the same file from two sessions may lose the first session's changes.
192
+ pwrap warns and prompts for confirmation when a concurrent session is detected.
193
+
194
+ **Shared mode** (`shared = true`): the first terminal becomes the **primary**
195
+ session. It mounts gocryptfs, prints a vault token, and stays in the
196
+ foreground of the terminal that launched it (no background daemon — the
197
+ serve process is a normal child of your shell). Additional terminals running
198
+ `pwrap myproject` prompt for the token and attach as children of the primary.
199
+ Inside the sandbox, `echo $PWRAP_VAULT_TOKEN` retrieves the token. When the
200
+ primary exits (shell exit, Ctrl-C, or closing its terminal), all attached
201
+ terminals are terminated and the mount is released — keep the primary
202
+ terminal open for the duration of the session.
203
+
204
+ ### GUI apps in sandbox (WSL2)
205
+
206
+ To run emacs or other GUI apps inside the sandbox on WSL2:
207
+
208
+ ```toml
209
+ [sandbox]
210
+ writable = [
211
+ "/tmp/.X11-unix", # X11 display socket
212
+ "/mnt/wslg/runtime-dir", # Wayland + PulseAudio
213
+ ]
214
+ ```
215
+
216
+ ## Configuration
217
+
218
+ `pwrap --new` generates a `project.toml` template with all options documented.
219
+ The three config sections:
220
+
221
+ | Section | Purpose |
222
+ |---|---|
223
+ | `[project]` | name, dir, shell |
224
+ | `[sandbox]` | blacklist, whitelist, writable, namespace options |
225
+ | `[encrypted]` | gocryptfs cipherdir, mountpoint, shared mode |
226
+
227
+ Init scripts (`init.fish` or `init.sh`) run inside the sandbox for env vars,
228
+ venv activation, aliases, and tool version switching.
229
+
230
+ ## Usage
231
+
232
+ ```bash
233
+ pwrap # list projects
234
+ pwrap myproject # launch project
235
+ pwrap -v myproject # verbose output
236
+ pwrap --new ~/projects/myproject # create config (name from dir)
237
+ pwrap --new ~/projects/myproject custom # create with explicit name
238
+ pwrap --new --shell /bin/bash ~/projects/x # specify shell
239
+ pwrap --check-deps # check optional dependencies
240
+ pwrap --version # show version
241
+ ```
242
+
243
+ ## Security Defaults
244
+
245
+ When sandboxing is enabled:
246
+
247
+ - Home is **read-only**; only the project directory is writable
248
+ - Config directory (`~/.config/pwrap`) is always blacklisted
249
+ - PID and IPC namespaces are isolated
250
+ - TIOCSTI injection blocked automatically on kernels < 6.2
251
+ - XDG runtime directory isolated
252
+ - Sandbox dies with parent process
253
+ - Encrypted volumes mount in isolated namespace (invisible on host)
254
+ - All paths in shell commands are quoted to prevent injection
255
+
256
+ ## Shell Completions
257
+
258
+ ```bash
259
+ # Fish
260
+ cp completions/project.fish ~/.config/fish/completions/pwrap.fish
261
+ # Bash
262
+ cp completions/project.bash /etc/bash_completion.d/pwrap
263
+ # Zsh
264
+ cp completions/_project ~/.local/share/zsh/site-functions/_pwrap
265
+ ```
266
+
267
+ ## Development
268
+
269
+ ```bash
270
+ poetry install # install with dev dependencies
271
+ poetry run pytest # run tests
272
+ poetry run ruff check src/ # lint
273
+ poetry run mypy src/ # type check
274
+ ```
275
+
276
+ ## License
277
+
278
+ MIT
279
+
@@ -0,0 +1,254 @@
1
+ # pwrap
2
+
3
+ pwrap wraps project shell environments in bubblewrap sandboxes, and aims to
4
+ _limit the blast radius_ of e.g. supply chain attacks and protect your production
5
+ infrastructure from your sloppy side project.
6
+
7
+
8
+
9
+ **Why**
10
+ I got tired of my ad-hoc fish bwrap scripts, and I'm increasingly worried about supply chain attacks.
11
+
12
+ If every side project feels like a potential vector — one [npm|pip|cargo] install away from pwned AWS credentials,
13
+ and custom-wrapping with bwrap and some vault product feels too fragile or too much work, pwrap might help.
14
+
15
+ **Status**
16
+ pwrap _works_ but has not been tested by anyone but me, and has not been
17
+ reviewed/audited by anyone except Opus 4.6 and codestral. pwrap comes with
18
+ _absolutely no warranty_.
19
+
20
+
21
+ **Does:**
22
+ - Launches sandboxed shells with per-project filesystem isolation
23
+ - Hides sensitive paths (credentials, configs, SSH keys) via tmpfs overlays
24
+ - Exposes only what each project needs (whitelisting)
25
+ - Mounts gocryptfs encrypted volumes inside isolated namespaces
26
+ - Runs init scripts for env vars, venv activation, aliases
27
+
28
+ **Doesn't do:**
29
+ - Network filtering (it's all-or-nothing via `unshare_net`)
30
+ - Container-level isolation (no cgroups, no seccomp, no resource limits)
31
+ - Do package management or dependency resolution
32
+ - Protect you from your own misconfiguration
33
+
34
+ **Dependencies:** Python 3.11+ (stdlib only, no pip dependencies),
35
+ [bubblewrap](https://github.com/containers/bubblewrap) for sandboxing,
36
+ [gocryptfs](https://nuetzlich.net/gocryptfs/) for encrypted volumes.
37
+
38
+ **Design principles:**
39
+ - **Reviewable** — small codebase, no pip dependencies, no magic
40
+ - **Fail fast** — invalid config is an error, not a warning
41
+ - **Explicit over convenient** — no implicit defaults that hide security decisions
42
+ - **Init scripts as the extension point** — env vars, venv, aliases all go there,
43
+ not in config schema
44
+
45
+ ## Installation
46
+
47
+ pwrap has no pip dependencies — only the standard library. For a security tool,
48
+ installing from source lets you audit what you're running:
49
+
50
+ ```bash
51
+ git clone https://github.com/haard/projectwrap
52
+ cd projectwrap
53
+ pip install --no-deps .
54
+ ```
55
+
56
+ Or from PyPI if you prefer convenience: `pipx install projectwrap`
57
+
58
+ Check optional dependencies with `pwrap --check-deps`.
59
+
60
+ ## Quick Start
61
+
62
+ ```bash
63
+ pwrap --new ~/projects/myproject # creates config + init script
64
+ # edit ~/.config/pwrap/myproject/project.toml and init script
65
+ pwrap myproject # launch sandboxed shell
66
+ ```
67
+
68
+ On first run, `--new` creates editable templates in `~/.config/pwrap/`. Edit them
69
+ to set your defaults, then run `--new` again.
70
+
71
+ ## Examples
72
+
73
+ ### Basic sandboxed project
74
+
75
+ `~/.config/pwrap/myproject/project.toml`:
76
+ ```toml
77
+ [project]
78
+ name = "myproject"
79
+ dir = "~/projects/myproject"
80
+ shell = "/usr/bin/fish"
81
+
82
+ [sandbox]
83
+ enabled = true
84
+ blacklist = [
85
+ "~/.kube",
86
+ "~/.aws",
87
+ "~/.ssh",
88
+ ]
89
+ whitelist = [
90
+ "~/.kube/myproject",
91
+ "~/.ssh/myproject_ed25519",
92
+ "~/.ssh/known_hosts",
93
+ ]
94
+ ```
95
+
96
+ `~/.config/pwrap/myproject/init.fish`:
97
+ ```fish
98
+ source .venv/bin/activate.fish
99
+ set -gx KUBECONFIG ~/.kube/myproject/config
100
+ set -gx GIT_SSH_COMMAND "ssh -i ~/.ssh/myproject_ed25519 -o IdentitiesOnly=yes"
101
+ ```
102
+
103
+ The config directory (`~/.config/pwrap`) is always blacklisted automatically — code
104
+ inside the sandbox cannot read other project configs.
105
+
106
+ ### Encrypted AI chat history
107
+
108
+ Keep aichat/Claude chat history encrypted at rest, decrypted only inside the sandbox.
109
+ Uses gocryptfs mounted in an isolated namespace (invisible on host).
110
+
111
+ **Setup:**
112
+ ```bash
113
+ # Initialize encrypted directory (once, prompts for password)
114
+ mkdir -p ~/.config/pwrap/myproject/encrypted
115
+ gocryptfs -init ~/.config/pwrap/myproject/encrypted
116
+ ```
117
+
118
+ **Config** (`project.toml`):
119
+ ```toml
120
+ [project]
121
+ name = "myproject"
122
+ dir = "~/projects/myproject"
123
+ shell = "/usr/bin/fish"
124
+
125
+ [sandbox]
126
+ enabled = true
127
+
128
+ [encrypted]
129
+ cipherdir = "encrypted"
130
+ mountpoint = "~/.local/share/aichat"
131
+ ```
132
+
133
+ **Init script** (`init.fish`):
134
+ ```fish
135
+ set -gx AICHAT_CONFIG_DIR ~/.local/share/aichat
136
+ # For Claude Code:
137
+ # set -gx CLAUDE_CONFIG_DIR ~/.local/share/claude
138
+ ```
139
+
140
+ On `pwrap myproject`, gocryptfs prompts for the password, mounts the decrypted
141
+ volume inside an isolated mount namespace, and launches the sandboxed shell.
142
+ The decrypted files are invisible to host processes and disappear when the shell
143
+ exits.
144
+
145
+ If you enter the wrong password, gocryptfs re-prompts up to its own retry limit
146
+ and then exits non-zero. pwrap aborts on that failure without launching the
147
+ sandbox — no shell starts, no partial mount is left behind. Re-run `pwrap
148
+ myproject` to try again.
149
+
150
+ **`PWRAP_VAULT_DIR`**: inside any sandbox with an `[encrypted]` section, pwrap
151
+ exports `PWRAP_VAULT_DIR` pointing at the mountpoint. Use it from init scripts
152
+ or app configs to redirect history/state into the vault without hardcoding the
153
+ path per project (e.g. `set savehist-file (expand-file-name "history" "$PWRAP_VAULT_DIR/emacs")`).
154
+
155
+ **You will appear as root inside encrypted projects.** Mounting gocryptfs
156
+ unprivileged requires `unshare --user --map-root-user`, so inside the sandbox
157
+ `whoami` reports `root` and `id -u` reports `0`. This is a user-namespace
158
+ remapping only — you have no real privileges on the host, cannot read
159
+ root-owned files outside the namespace, and cannot escalate. Your real files
160
+ (project dir, home bind-mounts, the vault mountpoint itself) remain owned by
161
+ your real uid. Scripts that gate on `[ "$UID" = 0 ]` will misbehave; prefer
162
+ `[ "$USER" = root ]` checks or, better, check the presence of
163
+ `$PROJECT_WRAP` / `$PWRAP_VAULT_DIR`.
164
+
165
+ **Multiple terminals** (`shared = false`, default): each terminal gets an
166
+ independent gocryptfs mount. Writes to different files merge on next session;
167
+ writes to the same file from two sessions may lose the first session's changes.
168
+ pwrap warns and prompts for confirmation when a concurrent session is detected.
169
+
170
+ **Shared mode** (`shared = true`): the first terminal becomes the **primary**
171
+ session. It mounts gocryptfs, prints a vault token, and stays in the
172
+ foreground of the terminal that launched it (no background daemon — the
173
+ serve process is a normal child of your shell). Additional terminals running
174
+ `pwrap myproject` prompt for the token and attach as children of the primary.
175
+ Inside the sandbox, `echo $PWRAP_VAULT_TOKEN` retrieves the token. When the
176
+ primary exits (shell exit, Ctrl-C, or closing its terminal), all attached
177
+ terminals are terminated and the mount is released — keep the primary
178
+ terminal open for the duration of the session.
179
+
180
+ ### GUI apps in sandbox (WSL2)
181
+
182
+ To run emacs or other GUI apps inside the sandbox on WSL2:
183
+
184
+ ```toml
185
+ [sandbox]
186
+ writable = [
187
+ "/tmp/.X11-unix", # X11 display socket
188
+ "/mnt/wslg/runtime-dir", # Wayland + PulseAudio
189
+ ]
190
+ ```
191
+
192
+ ## Configuration
193
+
194
+ `pwrap --new` generates a `project.toml` template with all options documented.
195
+ The three config sections:
196
+
197
+ | Section | Purpose |
198
+ |---|---|
199
+ | `[project]` | name, dir, shell |
200
+ | `[sandbox]` | blacklist, whitelist, writable, namespace options |
201
+ | `[encrypted]` | gocryptfs cipherdir, mountpoint, shared mode |
202
+
203
+ Init scripts (`init.fish` or `init.sh`) run inside the sandbox for env vars,
204
+ venv activation, aliases, and tool version switching.
205
+
206
+ ## Usage
207
+
208
+ ```bash
209
+ pwrap # list projects
210
+ pwrap myproject # launch project
211
+ pwrap -v myproject # verbose output
212
+ pwrap --new ~/projects/myproject # create config (name from dir)
213
+ pwrap --new ~/projects/myproject custom # create with explicit name
214
+ pwrap --new --shell /bin/bash ~/projects/x # specify shell
215
+ pwrap --check-deps # check optional dependencies
216
+ pwrap --version # show version
217
+ ```
218
+
219
+ ## Security Defaults
220
+
221
+ When sandboxing is enabled:
222
+
223
+ - Home is **read-only**; only the project directory is writable
224
+ - Config directory (`~/.config/pwrap`) is always blacklisted
225
+ - PID and IPC namespaces are isolated
226
+ - TIOCSTI injection blocked automatically on kernels < 6.2
227
+ - XDG runtime directory isolated
228
+ - Sandbox dies with parent process
229
+ - Encrypted volumes mount in isolated namespace (invisible on host)
230
+ - All paths in shell commands are quoted to prevent injection
231
+
232
+ ## Shell Completions
233
+
234
+ ```bash
235
+ # Fish
236
+ cp completions/project.fish ~/.config/fish/completions/pwrap.fish
237
+ # Bash
238
+ cp completions/project.bash /etc/bash_completion.d/pwrap
239
+ # Zsh
240
+ cp completions/_project ~/.local/share/zsh/site-functions/_pwrap
241
+ ```
242
+
243
+ ## Development
244
+
245
+ ```bash
246
+ poetry install # install with dev dependencies
247
+ poetry run pytest # run tests
248
+ poetry run ruff check src/ # lint
249
+ poetry run mypy src/ # type check
250
+ ```
251
+
252
+ ## License
253
+
254
+ MIT
@@ -0,0 +1,57 @@
1
+ [tool.poetry]
2
+ name = "projectwrap"
3
+ version = "202604.1"
4
+ description = "Isolated project environments with bubblewrap sandboxing"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ authors = ["Fredrik Håård <fredrik@haard.se>"]
8
+ keywords = ["sandbox", "bubblewrap", "bwrap", "isolation", "development", "security"]
9
+ classifiers = [
10
+ "Development Status :: 4 - Beta",
11
+ "Environment :: Console",
12
+ "Intended Audience :: Developers",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Operating System :: POSIX :: Linux",
15
+ "Programming Language :: Python :: 3",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Topic :: Security",
20
+ "Topic :: System :: Systems Administration",
21
+ ]
22
+ packages = [{ include = "project_wrap", from = "src" }]
23
+
24
+ [tool.poetry.dependencies]
25
+ python = "^3.11"
26
+
27
+ [tool.poetry.group.dev.dependencies]
28
+ pytest = "^8.0"
29
+ pytest-cov = "^4.0"
30
+ ruff = "^0.4"
31
+ mypy = "^1.0"
32
+
33
+ [tool.poetry.scripts]
34
+ pwrap = "project_wrap.cli:main"
35
+
36
+ [tool.poetry.urls]
37
+ Homepage = "https://github.com/haard/project-wrap"
38
+ Repository = "https://github.com/haard/project-wrap"
39
+
40
+ [build-system]
41
+ requires = ["poetry-core>=1.0.0"]
42
+ build-backend = "poetry.core.masonry.api"
43
+
44
+ [tool.ruff]
45
+ target-version = "py311"
46
+ line-length = 100
47
+
48
+ [tool.ruff.lint]
49
+ select = ["E", "F", "I", "N", "W", "UP"]
50
+
51
+ [tool.mypy]
52
+ python_version = "3.11"
53
+ strict = true
54
+
55
+ [tool.pytest.ini_options]
56
+ testpaths = ["tests"]
57
+ addopts = "-v"
@@ -0,0 +1,3 @@
1
+ """project-wrap: Isolated project environments with bubblewrap sandboxing."""
2
+
3
+ __version__ = "202604.1"