sayfirst-cli 0.2.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.
- sayfirst_cli/__init__.py +2 -0
- sayfirst_cli/approvals.py +127 -0
- sayfirst_cli/ask.py +167 -0
- sayfirst_cli/evidence.py +668 -0
- sayfirst_cli/exit_codes.py +88 -0
- sayfirst_cli/explain.py +35 -0
- sayfirst_cli/instrument/__init__.py +14 -0
- sayfirst_cli/instrument/commands.py +191 -0
- sayfirst_cli/instrument/engine.py +396 -0
- sayfirst_cli/instrument/harness.py +1162 -0
- sayfirst_cli/instrument/launch.py +417 -0
- sayfirst_cli/instrument/manifest.py +409 -0
- sayfirst_cli/instrument/verify.py +553 -0
- sayfirst_cli/main.py +78 -0
- sayfirst_cli/packs/__init__.py +10 -0
- sayfirst_cli/packs/database/NOTE.md +4 -0
- sayfirst_cli/packs/database/interpose.py +85 -0
- sayfirst_cli/packs/database/pack.toml +13 -0
- sayfirst_cli/packs/http-client/NOTE.md +4 -0
- sayfirst_cli/packs/http-client/interpose.py +72 -0
- sayfirst_cli/packs/http-client/pack.toml +13 -0
- sayfirst_cli/packs/subprocess/NOTE.md +4 -0
- sayfirst_cli/packs/subprocess/interpose.py +90 -0
- sayfirst_cli/packs/subprocess/pack.toml +13 -0
- sayfirst_cli/packs_cmd.py +115 -0
- sayfirst_cli/pages.py +87 -0
- sayfirst_cli/reads.py +254 -0
- sayfirst_cli/render.py +138 -0
- sayfirst_cli/trace.py +88 -0
- sayfirst_cli-0.2.0.dist-info/METADATA +297 -0
- sayfirst_cli-0.2.0.dist-info/RECORD +35 -0
- sayfirst_cli-0.2.0.dist-info/WHEEL +4 -0
- sayfirst_cli-0.2.0.dist-info/entry_points.txt +2 -0
- sayfirst_cli-0.2.0.dist-info/licenses/LICENSE +202 -0
- sayfirst_cli-0.2.0.dist-info/licenses/NOTICE +13 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: sayfirst-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: The product command-line interface of the sayfirst control plane
|
|
5
|
+
Project-URL: Repository, https://github.com/fredaime/sayfirst-cli
|
|
6
|
+
Project-URL: Documentation, https://github.com/fredaime/sayfirst-cli/blob/main/README.md
|
|
7
|
+
Project-URL: Changelog, https://github.com/fredaime/sayfirst-cli/blob/main/CHANGELOG.md
|
|
8
|
+
Author-email: fredaime <frederic.aime@gmail.com>
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
License-File: NOTICE
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Requires-Python: <3.15,>=3.12
|
|
18
|
+
Requires-Dist: sayfirst-boundary==0.2.0
|
|
19
|
+
Requires-Dist: sayfirst-contract==0.2.0
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
23
|
+
# `sayfirst` command-line interface
|
|
24
|
+
|
|
25
|
+
The open-source command-line interface of the `sayfirst` control plane: the
|
|
26
|
+
product CLI a user installs to connect an existing program to the boundary, to
|
|
27
|
+
read what was decided, and to verify it afterwards. [`QUICKSTART.md`](QUICKSTART.md)
|
|
28
|
+
installs it beside its daemon and walks one governed decision end to end — every
|
|
29
|
+
command on that page was run before it was written down.
|
|
30
|
+
|
|
31
|
+
Its content arrives as the partition of the private CLI, by copy with a
|
|
32
|
+
provenance review, slice by slice. The first slice is here and it runs:
|
|
33
|
+
[`docs/PARTITION.md`](docs/PARTITION.md) says what crosses and what is still
|
|
34
|
+
open, and [`docs/PROVENANCE.md`](docs/PROVENANCE.md) says what arrived by copy
|
|
35
|
+
— today, nothing, and why that is the right answer rather than an omission.
|
|
36
|
+
|
|
37
|
+
## Three directions
|
|
38
|
+
|
|
39
|
+
A client of this control plane does **three** things, and this repository ships
|
|
40
|
+
all three.
|
|
41
|
+
|
|
42
|
+
**Before an effect, it asks.** One question — a capability, a scope — put to the
|
|
43
|
+
daemon over a socket whose peer it verified, and one answer rendered as it was
|
|
44
|
+
given: allow, deny or suspend, and "could not ask" when the daemon could not be
|
|
45
|
+
reached. That is `sayfirst ask`, and it is what the first slice implements.
|
|
46
|
+
|
|
47
|
+
**It puts the boundary in front of somebody else's program.** `sayfirst
|
|
48
|
+
instrument run --pack DIR … -- <program>` runs a program with the named effects
|
|
49
|
+
asked about first, reversibly and with nothing written anywhere; `sayfirst
|
|
50
|
+
instrument verify` runs it again under the interpreter's own audit hook and
|
|
51
|
+
proves, from that and the scope's evidence chain alone, that every effect of a
|
|
52
|
+
named kind was preceded by a decision; `sayfirst instrument apply` is reserved
|
|
53
|
+
for the committed code modification and refuses, saying so. `sayfirst packs
|
|
54
|
+
list` prints the convenience packs this distribution ships, one line each with
|
|
55
|
+
the path `--pack` accepts, and `sayfirst packs check PATH` reads one the way the
|
|
56
|
+
engine will before anything runs with it.
|
|
57
|
+
[`docs/PACKS.md`](docs/PACKS.md) is the whole of it.
|
|
58
|
+
|
|
59
|
+
**Afterwards, it reads and verifies.** Every read *from the daemon* names its
|
|
60
|
+
scope explicitly (`--scope`) — the writer's `local` default does not apply. The
|
|
61
|
+
two offline checks name a path instead and take no scope at all: `evidence audit
|
|
62
|
+
--file` checks one saved bundle and `evidence exports` a directory of them, and
|
|
63
|
+
both refuse `--scope`, because the file says which scope it holds. This is a
|
|
64
|
+
surface rather than a list, and it grows by slices; what it answers today is
|
|
65
|
+
below, and `sayfirst --help` is the claim that is kept in the dispatch itself.
|
|
66
|
+
|
|
67
|
+
`sayfirst trace` reads back the record of one decision and follows it into the
|
|
68
|
+
evidence that holds it: the record itself, and where it sits in the chain,
|
|
69
|
+
bounded to the pages the read walks.
|
|
70
|
+
|
|
71
|
+
`sayfirst explain` reads the reason the control plane gave for a decision — the
|
|
72
|
+
rule it applied and the policy version it ran under — in the plane's own words,
|
|
73
|
+
adding none of its own.
|
|
74
|
+
|
|
75
|
+
`sayfirst evidence history` and `sayfirst evidence audit` page through scoped
|
|
76
|
+
evidence: `history` renders what each page holds, `audit` puts the served
|
|
77
|
+
verdict beside a local check and names a finding wherever the two disagree;
|
|
78
|
+
`--file` checks an already-saved bundle offline, without opening a socket.
|
|
79
|
+
|
|
80
|
+
`sayfirst evidence export` saves a bundle a third party can verify with the
|
|
81
|
+
contract distribution alone, offline, no server code and no daemon; `--out`
|
|
82
|
+
names where it is saved. A bundle taken while the daemon's current epoch is
|
|
83
|
+
still open verifies with coverage `unknown` rather than `complete` — the honest
|
|
84
|
+
answer, not a failure. `sayfirst evidence exports` lists and re-verifies every
|
|
85
|
+
`*.json` bundle saved in a directory.
|
|
86
|
+
|
|
87
|
+
`sayfirst approvals show` reads where one suspended wait stands: its state,
|
|
88
|
+
when it was asked, when it ends, and — once a person has acted — when and why.
|
|
89
|
+
`sayfirst approvals approve` and `sayfirst approvals reject` end that wait
|
|
90
|
+
exactly once, an optional `--reason` and all, and render the same record
|
|
91
|
+
`show` would: one person's act, and nothing that counts signatures or names a
|
|
92
|
+
designation (article 12). These three follow the exit codes below, with no case
|
|
93
|
+
of their own: an approval already resolved, asked again, answers
|
|
94
|
+
`approval_resolved`, which the registry classifies as a refusal — so it is the
|
|
95
|
+
`3` below, like every other refusal, and this client special-cases nothing.
|
|
96
|
+
|
|
97
|
+
`trace`, `explain` and `evidence history` exit `0` on a read, whatever the
|
|
98
|
+
record's own outcome. `evidence audit`, `evidence export` and `evidence exports`
|
|
99
|
+
exit with the local check's result instead: `0` when it holds, `6` when it finds
|
|
100
|
+
what the plane did not say, `7` when it cannot conclude — which is the ordinary
|
|
101
|
+
answer for a bundle taken while the epoch is still open, and why
|
|
102
|
+
`sayfirst evidence export && …` is not how to script one. A chain the verifier
|
|
103
|
+
could not judge — an entry declaring a recipe this generation holds no reader
|
|
104
|
+
for, a range assembled out of order, an instant outside the calendar — is `7`
|
|
105
|
+
as well, with the sequence it stopped at: the answer arrived and the check could
|
|
106
|
+
not conclude, which is neither a failure to obtain the answer nor a finding
|
|
107
|
+
against the chain. Every command that reads from the control plane exits `3`
|
|
108
|
+
when the request was refused, `4` when the plane could not be read from or the
|
|
109
|
+
answer itself could not be read at all, and `64` on a misused invocation; a
|
|
110
|
+
usage error the parser catches exits `2` everywhere.
|
|
111
|
+
|
|
112
|
+
`sayfirst instrument verify` uses the same two local-check codes for the proof
|
|
113
|
+
it makes: `0` only when every point of every designated pack was `governed` and
|
|
114
|
+
no effect went unjudged, `6` for an effect no decision preceded — a finding this
|
|
115
|
+
client made, never a denial the plane gave — and `7` when the check could not
|
|
116
|
+
conclude, which includes a path the run never walked and an effect this proof
|
|
117
|
+
could not judge. A run that concluded nothing at all says which of its endings
|
|
118
|
+
happened, and answers with that ending's own code: `4` when the chain could not
|
|
119
|
+
be read, before the program started or while it ran, and when the verifier never
|
|
120
|
+
saw the program's own code start; `64` when the invocation was refused before it
|
|
121
|
+
began; `7` when findings arrived and would not read. `sayfirst instrument run`
|
|
122
|
+
owns none of these: it passes the governed program's own ending through
|
|
123
|
+
untouched, and answers `64` only for mistakes in the invocation. `sayfirst packs
|
|
124
|
+
list` exits `64` when a pack this distribution ships will not read — it names it,
|
|
125
|
+
prints the rest of the list anyway, and never ends in a traceback.
|
|
126
|
+
|
|
127
|
+
The operator closed Q-A on 2026-09-05: this repository owed the evidence
|
|
128
|
+
surface, and its promise to read and verify became a commitment with a date on
|
|
129
|
+
it — kept, as of this slice. [`docs/PARTITION.md`](docs/PARTITION.md) records
|
|
130
|
+
the decision; [`docs/EVIDENCE-SURFACE.md`](docs/EVIDENCE-SURFACE.md) records
|
|
131
|
+
what shipped and the contract support it used. Export verification uses the
|
|
132
|
+
recipe and vectors from the contract distribution, without importing server
|
|
133
|
+
code.
|
|
134
|
+
|
|
135
|
+
None of the three defines control semantics or derives a decision. A client
|
|
136
|
+
"explains and invokes" control semantics; it "never defines them, never keeps a
|
|
137
|
+
decision past the lifetime the
|
|
138
|
+
control plane gave it, and never derives an answer the control plane did not
|
|
139
|
+
give" (article 1). Asking, instrumenting and reading are three ways of carrying
|
|
140
|
+
an answer someone else made — the third of them, the verifier, reads the
|
|
141
|
+
interpreter and the chain and reaches no verdict of its own about policy — and
|
|
142
|
+
that is why all three belong to a client.
|
|
143
|
+
|
|
144
|
+
## The first slice
|
|
145
|
+
|
|
146
|
+
One command, end to end, against the open control plane's contract
|
|
147
|
+
distribution: `sayfirst ask` puts one question to the daemon and renders its
|
|
148
|
+
answer.
|
|
149
|
+
|
|
150
|
+
```console
|
|
151
|
+
$ sayfirst ask --capability example.effect --scope local --socket /run/user/1000/sayfirst.sock
|
|
152
|
+
verified: true (server_uid 1000, expected 1000)
|
|
153
|
+
outcome: allow
|
|
154
|
+
reason: policy_allows
|
|
155
|
+
capability: example.effect in scope local
|
|
156
|
+
decision: decision-1 at 2026-09-04T20:11:45.929523+00:00
|
|
157
|
+
policy version: sha256:44d91909ffe6283e67c73bad39d698448aa5e8bbdc1b5aa64a635a604e12f7e1
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
When the daemon cannot be reached, it says that, and it says it as its own
|
|
161
|
+
result rather than as a refusal:
|
|
162
|
+
|
|
163
|
+
```console
|
|
164
|
+
$ sayfirst ask --capability example.effect --socket /run/user/1000/absent.sock
|
|
165
|
+
verified: false (server_uid not stated, expected not stated)
|
|
166
|
+
could not ask: unreachable: [Errno 2] No such file or directory
|
|
167
|
+
retryable: true
|
|
168
|
+
$ echo $?
|
|
169
|
+
4
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
It exits `0` on `allow`, `1` on `deny`, `5` on `suspend`, `3` when the request
|
|
173
|
+
was refused and `4` when the control plane could not be asked — because
|
|
174
|
+
article 1 requires that "denied" and "could not ask" never read as each other.
|
|
175
|
+
There is no `--url` and nothing that takes a token: the boundary says who the
|
|
176
|
+
caller is, and it says so from the socket (article 6).
|
|
177
|
+
|
|
178
|
+
## The gate
|
|
179
|
+
|
|
180
|
+
`scripts/gate.sh` is the whole gate: format, lint, tests, and the guard that
|
|
181
|
+
installs this distribution into an empty environment and reads back everything
|
|
182
|
+
that arrived with it. That last one is article 13 made mechanical rather than
|
|
183
|
+
promised — and it proves on every run that it can fail, by planting a web
|
|
184
|
+
framework into the environment that has just passed and requiring the check to
|
|
185
|
+
reject it.
|
|
186
|
+
|
|
187
|
+
`sayfirst-contract` is on no index, because article 0 forbids publishing
|
|
188
|
+
anything until the marks are filed. So the gate is told where a checkout of the
|
|
189
|
+
control plane's repository is:
|
|
190
|
+
|
|
191
|
+
```console
|
|
192
|
+
$ SAYFIRST_CONTRACT_SOURCE=../sf-control-plane-lt ./scripts/gate.sh
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
It fails, rather than skipping, when it is not told. A skipped guard is a guard
|
|
196
|
+
that cannot fail.
|
|
197
|
+
|
|
198
|
+
## What binds here
|
|
199
|
+
|
|
200
|
+
The constitution of the open control plane —
|
|
201
|
+
[`CONSTITUTION.md`](https://github.com/fredaime/sayfirst-control-plane/blob/main/CONSTITUTION.md),
|
|
202
|
+
in that repository — binds this repository too. Its article 0 says so: it binds
|
|
203
|
+
"this repository and every other open repository of the project", and an open
|
|
204
|
+
repository adopts it **by pointer, never by copy, because a copy drifts**.
|
|
205
|
+
|
|
206
|
+
**That pointer became a link in the act that published this repository, and was
|
|
207
|
+
not one before.** The open control plane is published as a repository created
|
|
208
|
+
fresh (article 0), and until it existed the only URL this document could have
|
|
209
|
+
carried was the one repository the project has decided never to publish — a link
|
|
210
|
+
that would have resolved for nobody from the first public minute, in the
|
|
211
|
+
document a newcomer reads first. `docs/publication-checklist.md` orders the
|
|
212
|
+
control plane before this client for that reason, and
|
|
213
|
+
`tests/test_pointers_survive_publication.py` still reddens on any reader-facing
|
|
214
|
+
link to the repository that is never published — it is what kept the promise
|
|
215
|
+
from being made early. The same applies to `TRADEMARKS.md`, which is why this
|
|
216
|
+
repository carries one that points rather than one that copies.
|
|
217
|
+
|
|
218
|
+
The articles this repository will answer to first:
|
|
219
|
+
|
|
220
|
+
- **article 1** — a client explains and invokes control semantics; it never
|
|
221
|
+
defines them, never keeps a decision past the lifetime it was given, and never
|
|
222
|
+
derives an answer the control plane did not give;
|
|
223
|
+
- **article 13** — the client depends on the contract distribution and never on
|
|
224
|
+
the server distribution, so installing it never installs a web framework or a
|
|
225
|
+
database layer;
|
|
226
|
+
- **article 14** — nothing here imports, names or is shaped by a private
|
|
227
|
+
product; files that arrive from a private repository arrive by copy with a
|
|
228
|
+
provenance review;
|
|
229
|
+
- **article 15** — Apache-2.0, contributions under the Developer Certificate of
|
|
230
|
+
Origin, read on every pull request by
|
|
231
|
+
`scripts/check_developer_certificate_of_origin.py`, which refuses a commit
|
|
232
|
+
carrying no well-formed sign-off and refuses a range it cannot read rather
|
|
233
|
+
than reporting it as passing.
|
|
234
|
+
|
|
235
|
+
## The name
|
|
236
|
+
|
|
237
|
+
The product and the command are **`sayfirst`**, decided by the operator on
|
|
238
|
+
2026-09-04. Every
|
|
239
|
+
distribution the open side publishes takes it as a prefix, the way the retired
|
|
240
|
+
placeholder always said they would: this CLI as `sayfirst-cli`, and the plane as
|
|
241
|
+
`sayfirst-control-plane` where the plane is named. *Which* distributions this
|
|
242
|
+
repository ships is a different question — that is the partition, and it is not
|
|
243
|
+
decided.
|
|
244
|
+
|
|
245
|
+
### Who holds the command — decided, 2026-09-05
|
|
246
|
+
|
|
247
|
+
This repository claims the distribution `sayfirst-cli`, the import package
|
|
248
|
+
`sayfirst_cli` and the console script `sayfirst`. Until 2026-09-05 that was an
|
|
249
|
+
assumption, stated as one: the control plane's repository claimed the same three
|
|
250
|
+
names for its operator surface, each repository's guard read its own manifest
|
|
251
|
+
and passed, and no test anywhere could see the other tree. The operator settled
|
|
252
|
+
it on 2026-09-05, and all three names in all three forms belong to the product
|
|
253
|
+
command-line interface, which is this repository.
|
|
254
|
+
|
|
255
|
+
The control plane's repository is giving them up: its operator surface — the
|
|
256
|
+
commands that inspect its daemon — takes the daemon's own form of the product
|
|
257
|
+
name instead, the conventional Unix shape in which the daemon and the commands
|
|
258
|
+
that inspect it share one binary. That change is on a branch there, dated
|
|
259
|
+
2026-09-05 and not merged, so until it merges both trees still declare the three
|
|
260
|
+
names. Nothing had been published under either claim (article 0), so the
|
|
261
|
+
collision was a fact about two source trees and never about an installed
|
|
262
|
+
environment. [`docs/PARTITION.md`](docs/PARTITION.md) records
|
|
263
|
+
the question and its answer as Q-D.
|
|
264
|
+
|
|
265
|
+
Deciding the name did **not** unblock publishing on its own. Article 0 forbids
|
|
266
|
+
publishing anything under it — no package on an index, no public repository, no
|
|
267
|
+
announcement — until three conditions hold together:
|
|
268
|
+
|
|
269
|
+
1. **the name is decided** — met, 2026-09-04;
|
|
270
|
+
2. **the marks are filed** — no file here can read a registry, so this
|
|
271
|
+
repository asserts nothing about it and a session reading this file must not
|
|
272
|
+
read the decided name as evidence of it. The date the filing was made and the
|
|
273
|
+
reference it produced are recorded on `docs/publication-checklist.md`, and
|
|
274
|
+
article 0 puts that act before any public repository of this project;
|
|
275
|
+
3. **every occurrence of the placeholder is replaced** — done here; the
|
|
276
|
+
condition is project-wide, and the other repositories' occurrences are not
|
|
277
|
+
this repository's to change.
|
|
278
|
+
|
|
279
|
+
## What is still not decided
|
|
280
|
+
|
|
281
|
+
- **The partition.** Which parts of the private CLI cross, and what is renamed
|
|
282
|
+
on the way, is measured privately and executed slice by slice.
|
|
283
|
+
[`docs/PARTITION.md`](docs/PARTITION.md) proposes the open command surface,
|
|
284
|
+
names the three questions it does not close, and says plainly which of its
|
|
285
|
+
lines is a decision and which is a choice it made to keep moving. Two of its
|
|
286
|
+
questions are now answered — Q-D, the name collision, and Q-A, the evidence
|
|
287
|
+
surface — and both stay in the document, marked closed and dated.
|
|
288
|
+
|
|
289
|
+
## Boundary with the control plane
|
|
290
|
+
|
|
291
|
+
The control plane's operator surface keeps `status`, `doctor`,
|
|
292
|
+
`policy show|history` and `plugins list`, which inspect its daemon's own state.
|
|
293
|
+
`systems {register,retire}` also stays there pending its separate question.
|
|
294
|
+
The 2026-09-05 decision assigns `trace`, `explain` and
|
|
295
|
+
`evidence {audit,history,exports,export}` to this product client: they read the
|
|
296
|
+
decisions and evidence the plane supplied. Q-B, Q-C and Q-E remain open; Q-D
|
|
297
|
+
was already closed.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
sayfirst_cli/__init__.py,sha256=8zgvziBPj_nkJGMyux6TNzilJB98tKmFWxMvdfI8ywA,112
|
|
2
|
+
sayfirst_cli/approvals.py,sha256=RDhFSO9OtJcJW1jEoZiUCXsnh_mIHBDCix8-bWyOY08,5486
|
|
3
|
+
sayfirst_cli/ask.py,sha256=wMvFQ5OF4AzKQ4m3Yx-c_UBJ2DgwlPrXIDZo9ZisD9A,7024
|
|
4
|
+
sayfirst_cli/evidence.py,sha256=ce5z98Jk32W5snUx9NL8QMKOdz6F86LeFhw7Y4XNgcM,30378
|
|
5
|
+
sayfirst_cli/exit_codes.py,sha256=8OswtauKZRSzFbsWBM3uRMbeSC3pRfjElbDLgaO1AJY,4269
|
|
6
|
+
sayfirst_cli/explain.py,sha256=dMS-2--dbakoqGrvftFNU4aYoa6F5roiZ2B-bbLOOhU,1206
|
|
7
|
+
sayfirst_cli/main.py,sha256=oumnv_oM0PDVxA-DMgFE7HlO3ybsmdaTUliRQZFPCAk,3185
|
|
8
|
+
sayfirst_cli/packs_cmd.py,sha256=CU-oWDNzPHiNbpQZ7-_qAQXPcBDL7UIx32YvPjFGHe0,4936
|
|
9
|
+
sayfirst_cli/pages.py,sha256=u5q8AiSAYA0FRZHj03lUtxkJokyzBQCcckk8pwUX0FU,4135
|
|
10
|
+
sayfirst_cli/reads.py,sha256=cxuJ55woWlk5w33098ZofFpuMxlML9ITkB-_7YsH-N0,10511
|
|
11
|
+
sayfirst_cli/render.py,sha256=3iokEciq6GYbF3aSBFkldUTU4EAB71WRuc2QB_P-ztc,5725
|
|
12
|
+
sayfirst_cli/trace.py,sha256=W25lDI2ms55EIhT3EGavvBnJR5f_driZj-NAvcgLZMc,3733
|
|
13
|
+
sayfirst_cli/instrument/__init__.py,sha256=XaUxOjGVni0ky3TMUAz0wVsbYajYX1GqBVzXj82aDas,778
|
|
14
|
+
sayfirst_cli/instrument/commands.py,sha256=tXeAxFzMTLuIjF_97IcsSO0Ue9nfI4ZTERP7urXt0dI,8722
|
|
15
|
+
sayfirst_cli/instrument/engine.py,sha256=ZjGKneNTo2vi8grrRVLZ4VmWJovYV0uiLZ9aIAg28tU,18300
|
|
16
|
+
sayfirst_cli/instrument/harness.py,sha256=5sOw3eo_ZtIcWUh9MFj75jtoWc_RK_oEs7lcBpbSQh0,55202
|
|
17
|
+
sayfirst_cli/instrument/launch.py,sha256=1O5DhLFMJIVQrXDH6pVg9gpxzvXVgeeEDdZjwQ7pjrA,19935
|
|
18
|
+
sayfirst_cli/instrument/manifest.py,sha256=ESMCZQUmQIAa9cV7QtAjvs6jgBc677vKI6S9z8LHqOI,18367
|
|
19
|
+
sayfirst_cli/instrument/verify.py,sha256=VLRoZw8hgr6GBsAOlFjIZLOWCmVB2FzahHO5uK0hC8Y,24651
|
|
20
|
+
sayfirst_cli/packs/__init__.py,sha256=BKoZs2tFDTLr6vHx_jX0-jPKURL47lQt3ZxILtPz8CU,579
|
|
21
|
+
sayfirst_cli/packs/database/NOTE.md,sha256=EDV00TSw6YR5USwmyCXWZAbQIWaZPNTDuSoHZQlOlhA,264
|
|
22
|
+
sayfirst_cli/packs/database/interpose.py,sha256=gQwjIzbXSn7vg6XBt9IfGuPr9wJLocv3bu-rA3GMM4I,4308
|
|
23
|
+
sayfirst_cli/packs/database/pack.toml,sha256=yJI5For50MJjMwMIkBWzvTblbbQr1jW19NYpTOm-ZYo,259
|
|
24
|
+
sayfirst_cli/packs/http-client/NOTE.md,sha256=VmHzo9bfolFrf6YClRLk_Uc_q6W4e4_sz53-dH4nS1Q,271
|
|
25
|
+
sayfirst_cli/packs/http-client/interpose.py,sha256=egTSO1lyFxv0cIULV9PmMBeyuutYTYfcVGbYOjMbJrg,3221
|
|
26
|
+
sayfirst_cli/packs/http-client/pack.toml,sha256=3zFrhCZB9dwHnzFBIpUEYSSluoSMz0UZ5QXSOOOozkw,260
|
|
27
|
+
sayfirst_cli/packs/subprocess/NOTE.md,sha256=nTwLjZqUNNoNB-pPye0bDARFWtVC2BpF26KjM-vH10o,278
|
|
28
|
+
sayfirst_cli/packs/subprocess/interpose.py,sha256=tsbiz5kyxZkVL_NlQ4uz1iRDKIf_5x4L1TGp_Yc91ho,3955
|
|
29
|
+
sayfirst_cli/packs/subprocess/pack.toml,sha256=2aKVEL2G_VSoH-frHPBcw--vL-3p23vsY3jIIdv0EBw,259
|
|
30
|
+
sayfirst_cli-0.2.0.dist-info/METADATA,sha256=1gQvQ37L55XYGu8Ck4xuKl_NvJ7Qg3K6yN4RrP55GZI,16243
|
|
31
|
+
sayfirst_cli-0.2.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
32
|
+
sayfirst_cli-0.2.0.dist-info/entry_points.txt,sha256=U5lrZxS9GCMN19c-MiO6TaHgVCiS-6XF51WnQ0JTAm4,51
|
|
33
|
+
sayfirst_cli-0.2.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
34
|
+
sayfirst_cli-0.2.0.dist-info/licenses/NOTICE,sha256=MCkBvwpULbgh40rntVwPX_vjsx9LZIDYA8t6wGIXiMc,620
|
|
35
|
+
sayfirst_cli-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
sayfirst command-line interface
|
|
2
|
+
Copyright 2026 Frédéric Aime
|
|
3
|
+
|
|
4
|
+
This product is licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use these files except in compliance with the License. A copy of the
|
|
6
|
+
License is in the LICENSE file at the root of this repository.
|
|
7
|
+
|
|
8
|
+
Distributions that incorporate this software must reproduce the attribution
|
|
9
|
+
notices this file carries (Apache License 2.0, section 4(d)).
|
|
10
|
+
|
|
11
|
+
The Apache License grants no rights in the names and marks of this project; see
|
|
12
|
+
the TRADEMARKS.md file at the root of this repository, which states where the
|
|
13
|
+
project's one marks policy lives.
|