pixie-lab-dibs 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.
@@ -0,0 +1,253 @@
1
+ Metadata-Version: 2.5
2
+ Name: pixie-lab-dibs
3
+ Version: 0.1.0
4
+ Summary: Call dibs on shared lab machines: see who is using what, claim it, release it
5
+ Project-URL: Homepage, https://github.com/safl/pixie-lab-dibs
6
+ Author-email: "Simon A. F. Lund" <os@safl.dk>
7
+ License: BSD-3-Clause
8
+ License-File: LICENSE
9
+ Keywords: claims,coordination,lab,pixie,reservation
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: System Administrators
13
+ Classifier: License :: OSI Approved :: BSD License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Requires-Python: >=3.11
16
+ Requires-Dist: fastapi>=0.115
17
+ Requires-Dist: httpx>=0.27
18
+ Requires-Dist: pyyaml>=6
19
+ Requires-Dist: tomlkit>=0.12
20
+ Requires-Dist: uvicorn[standard]>=0.30
21
+ Description-Content-Type: text/markdown
22
+
23
+ <!--
24
+ SPDX-FileCopyrightText: Simon A. F. Lund <os@safl.dk>
25
+
26
+ SPDX-License-Identifier: BSD-3-Clause
27
+ -->
28
+
29
+ # dibs
30
+
31
+ [![test](https://github.com/safl/pixie-lab-dibs/actions/workflows/test.yml/badge.svg)](https://github.com/safl/pixie-lab-dibs/actions/workflows/test.yml)
32
+ [![format](https://github.com/safl/pixie-lab-dibs/actions/workflows/format.yml/badge.svg)](https://github.com/safl/pixie-lab-dibs/actions/workflows/format.yml)
33
+ [![PyPI](https://img.shields.io/pypi/v/pixie-lab-dibs)](https://pypi.org/project/pixie-lab-dibs/)
34
+ [![Python](https://img.shields.io/pypi/pyversions/pixie-lab-dibs)](https://pypi.org/project/pixie-lab-dibs/)
35
+ [![License: BSD-3-Clause](https://img.shields.io/badge/license-BSD--3--Clause-blue)](LICENSE)
36
+ [![REUSE status](https://api.reuse.software/badge/github.com/safl/pixie-lab-dibs)](https://api.reuse.software/info/github.com/safl/pixie-lab-dibs)
37
+
38
+ Call dibs on shared lab machines.
39
+
40
+ A lab machine is shared with people, ai-agents and automation-runners.
41
+ dibs lets each of them see who is on a machine before touching it, by
42
+ claiming it. A claim is a note, not a lock: SSH and the console stay
43
+ open to everyone. Everywhere a claim shows up, it reads as one sentence:
44
+
45
+ ```
46
+ 'alice' has claimed 'node-01' for 'xnvme' expires in: 'never'
47
+ ```
48
+
49
+ dibs keeps a list of **things** to claim, mostly machines. It fills the
50
+ list from **sources**: a config file, and any number of
51
+ [pixie](https://github.com/safl/pixie) servers, whose machines show up
52
+ on their own, with their hardware inventory.
53
+
54
+ ## Install
55
+
56
+ ```
57
+ uv tool install pixie-lab-dibs
58
+ ```
59
+
60
+ That gives you the `dibs` command, for both the server and the client.
61
+ Signing in uses `ssh-keygen` from OpenSSH 8.1 or newer.
62
+
63
+ ## Run the server
64
+
65
+ On the host that will run it, list the things in `/etc/dibs/dibs.toml`:
66
+
67
+ ```toml
68
+ [[pixie]]
69
+ url = "http://pixie:8080" # every machine pixie knows becomes a thing
70
+
71
+ [[thing]]
72
+ name = "ryzen-01" # a machine pixie does not boot
73
+ mac = "aa:bb:cc:dd:ee:ff" # any other key is kept as an attribute
74
+ ```
75
+
76
+ Then make it a service and start it:
77
+
78
+ ```
79
+ sudo dibs server install
80
+ ```
81
+
82
+ The command writes a systemd unit for the `dibs` you ran, enables it
83
+ and starts it. `dibs server start`, `stop`, `restart`, `status` and
84
+ `logs` manage it from then on. The service runs as a throwaway system
85
+ user that owns only `/var/lib/dibs`. Without root, `dibs server install --user` installs a per-user service instead. For a quick try,
86
+ `dibs serve` runs the server in the foreground.
87
+
88
+ The system service can only run a `dibs` installed outside your home
89
+ directory, for example with
90
+ `sudo UV_TOOL_DIR=/opt/uv UV_TOOL_BIN_DIR=/usr/local/bin uv tool install pixie-lab-dibs`.
91
+
92
+ ## Sign in
93
+
94
+ Claiming needs a user. Register a name with your SSH public key:
95
+
96
+ ```
97
+ export DIBS_URL=http://dibs:8090
98
+ dibs register alice
99
+ ```
100
+
101
+ The admin approves it on the server host:
102
+
103
+ ```
104
+ sudo dibs admin approve alice
105
+ ```
106
+
107
+ Then you log in once. `dibs` signs a one-time challenge with your key,
108
+ through your ssh-agent if the key lives there, and keeps the token it
109
+ gets back:
110
+
111
+ ```
112
+ dibs login
113
+ ```
114
+
115
+ The token does not expire; `dibs logout` drops it, and
116
+ `dibs admin revoke alice` ends every login alice has. `-i` picks a key
117
+ other than `~/.ssh/id_ed25519.pub`.
118
+
119
+ Over plain HTTP, a token can be read off the network. dibs gives claims
120
+ an identity among people who share a lab in good faith; it is not
121
+ protection against someone on that network. Put HTTPS in front of it if
122
+ the network is not trusted.
123
+
124
+ ## Claim
125
+
126
+ ```
127
+ dibs list [--mine]
128
+ dibs info <thing>
129
+ dibs claim <thing>... --for <purpose> [--expires 2h] [--force]
130
+ dibs release <thing>... | --mine
131
+ ```
132
+
133
+ A claim never expires unless given `--expires`, and an expired claim
134
+ counts as free. Claiming several things is all or nothing: if any of
135
+ them is claimed by someone else, you get none, and the refusal says who
136
+ holds it. `--force` takes or releases someone else's claim, and the
137
+ server's log records that it did.
138
+
139
+ `list` and `info` print for people. Add `--json`, `--yaml` or `--toml`
140
+ to get the answer as data instead; an agent or script should use one of
141
+ those rather than parse the text.
142
+
143
+ The exit status is 0 when done, 1 when refused because someone else
144
+ holds a thing, and 2 for anything else.
145
+
146
+ ### AI-agents
147
+
148
+ Point your agent at this section. An agent claims as its human, and
149
+ names itself the way an `Assisted-by:` trailer does:
150
+
151
+ ```
152
+ export DIBS_ASSISTED_BY="Claude Code:claude-opus-5-5"
153
+ ```
154
+
155
+ The claim then reads `'alice' assisted by 'Claude Code:claude-opus-5-5' has claimed ...`.
156
+
157
+ If you are an agent reading this: before you run anything on a lab
158
+ machine, run `dibs list` and claim the machine with
159
+ `dibs claim <machine> --for <purpose>`. Never use a machine someone else
160
+ has claimed, and never pass `--force`; ask your human instead. Release
161
+ what you claimed with `dibs release --mine` when the work is done, and
162
+ also when it fails or is abandoned. That releases only what you claimed,
163
+ not your human's own claims.
164
+
165
+ ### Automation-runners
166
+
167
+ Give the runner a user of its own: register it with a key made for it,
168
+ approve it, log in once, and store the token as the runner's
169
+ `DIBS_TOKEN` secret. A refused claim exits 1, which a runner can wait
170
+ out; anything else exits 2 and should fail the job. In GitHub Actions:
171
+
172
+ ```yaml
173
+ env:
174
+ DIBS_URL: http://dibs:8090
175
+ DIBS_TOKEN: ${{ secrets.DIBS_TOKEN }}
176
+ steps:
177
+ - name: Claim the machine
178
+ run: |
179
+ until dibs claim node-01 --for "${{ github.workflow }}" --expires 3h; do
180
+ [ $? -eq 1 ] || exit 1
181
+ sleep 60
182
+ done
183
+ - name: Test
184
+ run: ...
185
+ - name: Release the machine
186
+ if: always()
187
+ run: dibs release --mine
188
+ ```
189
+
190
+ The `--expires` is a safety net for a runner that dies before its
191
+ release step.
192
+
193
+ ## See the claim when you log in
194
+
195
+ Install the login hook on each machine. At every interactive login it
196
+ asks dibs for the machine's claim and prints it. It stays silent when
197
+ dibs is unreachable, and does nothing for non-interactive SSH such as
198
+ `scp`. It finds the machine by its MAC addresses, or else its hostname.
199
+
200
+ ```
201
+ curl -fsS http://dibs:8090/login.sh | sudo tee /etc/profile.d/dibs.sh
202
+ ```
203
+
204
+ ## Shell completion
205
+
206
+ ```
207
+ eval "$(dibs completion bash)"
208
+ ```
209
+
210
+ Add that line to `~/.bashrc`, or write the script to
211
+ `/etc/bash_completion.d/dibs`. It completes commands and options, and
212
+ thing names from the server.
213
+
214
+ ## HTTP
215
+
216
+ Anything that can send JSON can use dibs without the client. Reads need
217
+ no login; claim and release take `Authorization: Bearer <token>`.
218
+
219
+ | Route | |
220
+ | -------------------------- | -------------------------------------------------------------------------------------------- |
221
+ | `GET /things` | every thing, with its `sentence` and, while claimed, its `claim` |
222
+ | `GET /things/<name>` | one thing, plus `pixie` when a pixie server knows it |
223
+ | `GET /things/<name>/claim` | the sentence as one line of text |
224
+ | `POST /claims` | `{"things": [...], "purpose": "...", "assisted_by": "", "expires_in": null, "force": false}` |
225
+ | `POST /claims/release` | `{"things": [...], "force": false}`, or `{"mine": true, "assisted_by": ""}` |
226
+ | `POST /auth/register` | `{"user": "...", "pubkey": "ssh-ed25519 ..."}` |
227
+ | `POST /auth/challenge` | `{"user": "..."}` gives a nonce and the message to sign |
228
+ | `POST /auth/login` | `{"user", "nonce", "signature"}` gives a token |
229
+ | `GET /login.sh` | the login hook |
230
+
231
+ A claim or release blocked by someone else's claim answers 409 with
232
+ the blocking claims' sentences in `detail.claimed`.
233
+
234
+ ## Releasing
235
+
236
+ Set the version in `src/dibs/__init__.py`, move the changelog's
237
+ `Unreleased` entries under that version, commit, and push a tag named
238
+ after it:
239
+
240
+ ```
241
+ git tag v0.1.0 && git push origin v0.1.0
242
+ ```
243
+
244
+ The tag runs the publish workflow, which checks the tag matches the
245
+ version, runs the checks, and uploads `pixie-lab-dibs` to PyPI through trusted
246
+ publishing.
247
+
248
+ ## License
249
+
250
+ BSD-3-Clause. The repository follows [REUSE](https://reuse.software):
251
+ every file states its copyright and license, `LICENSES/` holds the
252
+ license text, and `REUSE.toml` covers the files that cannot carry a
253
+ header.
@@ -0,0 +1,12 @@
1
+ dibs/__init__.py,sha256=wbV9LyP-QOvy3h8mxz52ZL-5MbR6hmThKhwFSJkYlaM,520
2
+ dibs/_sources.py,sha256=59gRIXksQUCkaR28MRxNC9yUJlTsZA_Vxn1wJJ6Ra5w,5654
3
+ dibs/_sshsig.py,sha256=pT78XDvA0Fl3fdel4JS8w9wd4VvruFcF4ucN-zbctN0,2811
4
+ dibs/_store.py,sha256=ii6mmkb6ho7knRaRfiWSJxNhJZGsubrjOvSzP5cmALk,12265
5
+ dibs/_users.py,sha256=2MX-lE0xpRv74aVWMQAfMjmb1MbYMDiqoqxZeuHBKSI,9297
6
+ dibs/app.py,sha256=GPhxZnFirO3Q9idhYpzWmQ53qm9cla4WQEW4KtPBonM,13389
7
+ dibs/cli.py,sha256=F3mdcmYXaNzWD4GhBqsaTryV2wHRinT_omdY7BsI0J4,26379
8
+ pixie_lab_dibs-0.1.0.dist-info/METADATA,sha256=5s-Ez8k_V01tIUKCmfRDV6OOl1svFXgrBxVTIzNK72o,9353
9
+ pixie_lab_dibs-0.1.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
10
+ pixie_lab_dibs-0.1.0.dist-info/entry_points.txt,sha256=_-5VulNYH6io4gEuRmH5Omge0nkBZiQbTO-gydfh3S8,39
11
+ pixie_lab_dibs-0.1.0.dist-info/licenses/LICENSE,sha256=k28p1vD0tdx5EqOG2L93SQ6EGqXDQTWn4RMptaUyFm0,1503
12
+ pixie_lab_dibs-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ dibs = dibs.cli:main
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Simon A. F. Lund
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.