pywrit 0.2.4__tar.gz → 0.2.6__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.
@@ -1,15 +1,23 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pywrit
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Python client + CLI for Writ — the gate before the write
5
- License: MIT
5
+ License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/AvenueDAdmin/pywrit
7
7
  Project-URL: Documentation, https://withwrit.com/docs
8
- Keywords: ai-agents,policy,audit-log,guardrails
9
8
  Requires-Python: >=3.9
10
9
  Description-Content-Type: text/markdown
11
10
  License-File: LICENSE
12
11
  Requires-Dist: httpx>=0.27
12
+ Provides-Extra: polyglot
13
+ Requires-Dist: tree-sitter>=0.23; extra == "polyglot"
14
+ Requires-Dist: tree-sitter-typescript>=0.23; extra == "polyglot"
15
+ Requires-Dist: tree-sitter-javascript>=0.23; extra == "polyglot"
16
+ Provides-Extra: keywords
17
+ Requires-Dist: ai-agents; extra == "keywords"
18
+ Requires-Dist: policy; extra == "keywords"
19
+ Requires-Dist: audit-log; extra == "keywords"
20
+ Requires-Dist: guardrails; extra == "keywords"
13
21
  Dynamic: license-file
14
22
 
15
23
  # pywrit
@@ -32,6 +40,18 @@ pip install pywrit
32
40
 
33
41
  Requires Python 3.9+. Installs the `writ` command and the `pywrit` Python client.
34
42
 
43
+ **JavaScript/TypeScript devs:** run the scanner with no Python setup via npm:
44
+
45
+ ```bash
46
+ npx writ-scan .
47
+ ```
48
+
49
+ The `writ-scan` package wraps the same scanner (including TS/JS support). On
50
+ first run it installs `pywrit[polyglot]` from PyPI using your Python 3.9+
51
+ (one-time); afterwards it starts instantly. See [`npm/`](npm/) for details,
52
+ environment overrides (`WRIT_PYTHON`, `WRIT_SCAN_NO_INSTALL`), and the
53
+ install test.
54
+
35
55
  ## 60-second quickstart: scan → apply → gate
36
56
 
37
57
  **1. Scan.** See which functions write, and how many of them are gated.
@@ -114,13 +134,42 @@ Python (`.py`) files, parsed with the stdlib `ast` (no extra dependencies):
114
134
  calls such as `stripe.Refund.create(...)`, deferred task queues, or shared clients
115
135
  several layers down. The risk report lists these gaps every time.
116
136
 
117
- ### TypeScript / JavaScript: coming soon (not yet released)
137
+ ### TypeScript / JavaScript (scan-only)
138
+
139
+ `writ scan` also finds write sites in TypeScript and JavaScript. It needs the
140
+ optional extra (tree-sitter based):
141
+
142
+ pip install 'pywrit[polyglot]'
143
+ writ scan .
144
+
145
+ Without the extra, the scanner prints a one-line hint and keeps going —
146
+ Python scanning never needs it.
147
+
148
+ TS/JS is **scan-only**: findings are listed with verbs for your policy file,
149
+ but `writ scan --apply` never rewrites TS/JS files — gate those by hand.
150
+ Covered patterns: `fetch`/`axios` writes, `fs` writes, SQL through knex-style
151
+ clients, Prisma writes, and JS SDK calls such as `stripe.refunds.create(...)`.
152
+ (Still not covered: the *Python* SDK equivalents like `stripe.Refund.create(...)`
153
+ — see "Not covered" above.)
154
+
155
+ ![writ scan on a TypeScript agent finds 5 write sites, 1 of 5 gated](https://raw.githubusercontent.com/AvenueDAdmin/pywrit/main/docs/assets/scan-tsjs.gif)
156
+
157
+ ## GitHub Action
158
+
159
+ Scan every pull request for ungated write sites. Findings land as check
160
+ annotations on the exact file and line, plus a Markdown risk report in the
161
+ job summary. The check fails when an ungated finding meets your
162
+ `fail-on-risk` threshold (default: `high`).
118
163
 
119
- > **Not available in `pywrit` 0.2.2 or on PyPI yet.** The current release scans
120
- > Python only. The preview below shows scan-only TS/JS support that is still in
121
- > development; the command it uses is not available yet.
164
+ ```yaml
165
+ - uses: actions/checkout@v4
166
+ - uses: AvenueDAdmin/pywrit@v1
167
+ with:
168
+ fail-on-risk: high # high | medium | low | never
169
+ ```
122
170
 
123
- ![Preview, not yet released: writ scan on a TypeScript agent finds 5 write sites, 1 of 5 gated](https://raw.githubusercontent.com/AvenueDAdmin/pywrit/main/docs/assets/scan-tsjs.gif)
171
+ No API key needed. Full reference: [docs/github-action.md](docs/github-action.md) ·
172
+ example workflow: [examples/github-action/writ-scan.yml](examples/github-action/writ-scan.yml)
124
173
 
125
174
  ## Python client
126
175
 
@@ -185,6 +234,32 @@ writ grant --sponsor acme --agent agent-7 --verb payments.refund \
185
234
  Sponsor-token commands (`revoke`, `reinstate`, `revoked`, `grant`) read
186
235
  `--sponsor-token` or `WRIT_SPONSOR_TOKEN`. Run `writ --help` for the full command list.
187
236
 
237
+ ## README badge
238
+
239
+ Show that your agent's writes are gated by Writ. Two flavors:
240
+
241
+ **Static** (works today, no API key) — same design, no live count:
242
+
243
+ ```md
244
+ [![agent writes gated by Writ](https://cdn.jsdelivr.net/gh/AvenueDAdmin/pywrit@main/badge/writ-gated.svg)](https://withwrit.com)
245
+ ```
246
+
247
+ **Dynamic** (live 30-day gated-write count from your audit log) — mint a badge
248
+ token, then embed the snippet the API returns:
249
+
250
+ ```bash
251
+ curl -s https://api.withwrit.com/v1/badge/tokens \
252
+ -H "Authorization: Bearer writ_..." \
253
+ -H "Content-Type: application/json" \
254
+ -d '{}'
255
+ ```
256
+
257
+ The dynamic endpoint ships with the gate — until it's live, `POST /v1/badge/tokens`
258
+ returns 404 and the static badge above is the one to use.
259
+
260
+ See [`badge/`](badge/) for embed docs and the verification model (what the
261
+ badge proves — and what it doesn't).
262
+
188
263
  ## Docs
189
264
 
190
265
  Full docs: [docs.withwrit.com](https://docs.withwrit.com) ·
@@ -1,17 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: pywrit
3
- Version: 0.2.4
4
- Summary: Python client + CLI for Writ — the gate before the write
5
- License: MIT
6
- Project-URL: Homepage, https://github.com/AvenueDAdmin/pywrit
7
- Project-URL: Documentation, https://withwrit.com/docs
8
- Keywords: ai-agents,policy,audit-log,guardrails
9
- Requires-Python: >=3.9
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: httpx>=0.27
13
- Dynamic: license-file
14
-
15
1
  # pywrit
16
2
 
17
3
  **Find the dangerous writes in your Python agent's code, then gate it.** `pywrit` is the Python
@@ -32,6 +18,18 @@ pip install pywrit
32
18
 
33
19
  Requires Python 3.9+. Installs the `writ` command and the `pywrit` Python client.
34
20
 
21
+ **JavaScript/TypeScript devs:** run the scanner with no Python setup via npm:
22
+
23
+ ```bash
24
+ npx writ-scan .
25
+ ```
26
+
27
+ The `writ-scan` package wraps the same scanner (including TS/JS support). On
28
+ first run it installs `pywrit[polyglot]` from PyPI using your Python 3.9+
29
+ (one-time); afterwards it starts instantly. See [`npm/`](npm/) for details,
30
+ environment overrides (`WRIT_PYTHON`, `WRIT_SCAN_NO_INSTALL`), and the
31
+ install test.
32
+
35
33
  ## 60-second quickstart: scan → apply → gate
36
34
 
37
35
  **1. Scan.** See which functions write, and how many of them are gated.
@@ -114,13 +112,42 @@ Python (`.py`) files, parsed with the stdlib `ast` (no extra dependencies):
114
112
  calls such as `stripe.Refund.create(...)`, deferred task queues, or shared clients
115
113
  several layers down. The risk report lists these gaps every time.
116
114
 
117
- ### TypeScript / JavaScript: coming soon (not yet released)
115
+ ### TypeScript / JavaScript (scan-only)
116
+
117
+ `writ scan` also finds write sites in TypeScript and JavaScript. It needs the
118
+ optional extra (tree-sitter based):
118
119
 
119
- > **Not available in `pywrit` 0.2.2 or on PyPI yet.** The current release scans
120
- > Python only. The preview below shows scan-only TS/JS support that is still in
121
- > development; the command it uses is not available yet.
120
+ pip install 'pywrit[polyglot]'
121
+ writ scan .
122
122
 
123
- ![Preview, not yet released: writ scan on a TypeScript agent finds 5 write sites, 1 of 5 gated](https://raw.githubusercontent.com/AvenueDAdmin/pywrit/main/docs/assets/scan-tsjs.gif)
123
+ Without the extra, the scanner prints a one-line hint and keeps going —
124
+ Python scanning never needs it.
125
+
126
+ TS/JS is **scan-only**: findings are listed with verbs for your policy file,
127
+ but `writ scan --apply` never rewrites TS/JS files — gate those by hand.
128
+ Covered patterns: `fetch`/`axios` writes, `fs` writes, SQL through knex-style
129
+ clients, Prisma writes, and JS SDK calls such as `stripe.refunds.create(...)`.
130
+ (Still not covered: the *Python* SDK equivalents like `stripe.Refund.create(...)`
131
+ — see "Not covered" above.)
132
+
133
+ ![writ scan on a TypeScript agent finds 5 write sites, 1 of 5 gated](https://raw.githubusercontent.com/AvenueDAdmin/pywrit/main/docs/assets/scan-tsjs.gif)
134
+
135
+ ## GitHub Action
136
+
137
+ Scan every pull request for ungated write sites. Findings land as check
138
+ annotations on the exact file and line, plus a Markdown risk report in the
139
+ job summary. The check fails when an ungated finding meets your
140
+ `fail-on-risk` threshold (default: `high`).
141
+
142
+ ```yaml
143
+ - uses: actions/checkout@v4
144
+ - uses: AvenueDAdmin/pywrit@v1
145
+ with:
146
+ fail-on-risk: high # high | medium | low | never
147
+ ```
148
+
149
+ No API key needed. Full reference: [docs/github-action.md](docs/github-action.md) ·
150
+ example workflow: [examples/github-action/writ-scan.yml](examples/github-action/writ-scan.yml)
124
151
 
125
152
  ## Python client
126
153
 
@@ -185,6 +212,32 @@ writ grant --sponsor acme --agent agent-7 --verb payments.refund \
185
212
  Sponsor-token commands (`revoke`, `reinstate`, `revoked`, `grant`) read
186
213
  `--sponsor-token` or `WRIT_SPONSOR_TOKEN`. Run `writ --help` for the full command list.
187
214
 
215
+ ## README badge
216
+
217
+ Show that your agent's writes are gated by Writ. Two flavors:
218
+
219
+ **Static** (works today, no API key) — same design, no live count:
220
+
221
+ ```md
222
+ [![agent writes gated by Writ](https://cdn.jsdelivr.net/gh/AvenueDAdmin/pywrit@main/badge/writ-gated.svg)](https://withwrit.com)
223
+ ```
224
+
225
+ **Dynamic** (live 30-day gated-write count from your audit log) — mint a badge
226
+ token, then embed the snippet the API returns:
227
+
228
+ ```bash
229
+ curl -s https://api.withwrit.com/v1/badge/tokens \
230
+ -H "Authorization: Bearer writ_..." \
231
+ -H "Content-Type: application/json" \
232
+ -d '{}'
233
+ ```
234
+
235
+ The dynamic endpoint ships with the gate — until it's live, `POST /v1/badge/tokens`
236
+ returns 404 and the static badge above is the one to use.
237
+
238
+ See [`badge/`](badge/) for embed docs and the verification model (what the
239
+ badge proves — and what it doesn't).
240
+
188
241
  ## Docs
189
242
 
190
243
  Full docs: [docs.withwrit.com](https://docs.withwrit.com) ·
@@ -4,12 +4,21 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pywrit"
7
- version = "0.2.4"
7
+ version = "0.2.6"
8
8
  description = "Python client + CLI for Writ — the gate before the write"
9
9
  readme = "README.md"
10
- license = { text = "MIT" }
10
+ license = "MIT"
11
11
  requires-python = ">=3.9"
12
12
  dependencies = ["httpx>=0.27"]
13
+
14
+ [project.optional-dependencies]
15
+ # `pip install 'pywrit[polyglot]'`: lets `writ scan` parse TypeScript and
16
+ # JavaScript (scan only). Python scanning never needs it.
17
+ polyglot = [
18
+ "tree-sitter>=0.23",
19
+ "tree-sitter-typescript>=0.23",
20
+ "tree-sitter-javascript>=0.23",
21
+ ]
13
22
  keywords = ["ai-agents", "policy", "audit-log", "guardrails"]
14
23
 
15
24
  [project.urls]
@@ -27,7 +27,7 @@ from .errors import (
27
27
  WritError,
28
28
  )
29
29
 
30
- __version__ = "0.2.4"
30
+ __version__ = "0.2.6"
31
31
 
32
32
  __all__ = [
33
33
  "WritClient",