failproofai 0.0.15 → 1.0.0-beta.0
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.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +9 -9
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +9 -9
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +9 -9
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0id_xf7._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__19120tr._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +4 -4
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0114ewg._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__06b4trb._.js → [root-of-the-server]__0259h38._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r5bgf._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e8sjqm._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lkzqax._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qucxyj._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u02miy._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__170799-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ath6v_._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zj-87g._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zqz4v8._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_0hs_5mh.js → node_modules_html-to-image_es_index_1-upb14.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +11 -11
- package/.next/standalone/.next/static/chunks/{1_v8b8mxhk25s.js → 0ip1n8xmgxarv.js} +1 -1
- package/.next/standalone/.next/static/chunks/{33rm-y-i4uzvv.js → 0u9hc6oxx-gpj.js} +1 -1
- package/.next/standalone/.next/static/chunks/{11qhtpk2cvoxv.js → 1d6ncspjagm53.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2f4mxqkkoa_7d.js → 1grd7y94-igz9.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3m8wmvlhsy1mx.js → 1s-_swlc80y43.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0kf9j0pf_j9-0.js → 29k6ef49zppxj.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2h7vw-ojgr9fz.js → 29ydr-8q0zis6.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1-ng45379-ztb.js → 2vr7aazw6k2-n.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2geh8s7d3ead-.js → 3wrgbih-516uj.js} +1 -1
- package/.next/standalone/Cargo.lock +428 -0
- package/.next/standalone/Cargo.toml +9 -0
- package/.next/standalone/crates/PROTOCOL.md +122 -0
- package/.next/standalone/crates/failproofaid/Cargo.toml +18 -0
- package/.next/standalone/crates/failproofaid/src/lock.rs +81 -0
- package/.next/standalone/crates/failproofaid/src/main.rs +83 -0
- package/.next/standalone/crates/failproofaid/src/paths.rs +172 -0
- package/.next/standalone/crates/failproofaid/src/server.rs +502 -0
- package/.next/standalone/crates/failproofaid/src/worker.rs +400 -0
- package/.next/standalone/crates/failproofaid/tests/daemon_e2e.rs +241 -0
- package/.next/standalone/crates/fpai-ipc/Cargo.toml +16 -0
- package/.next/standalone/crates/fpai-ipc/src/envelope.rs +175 -0
- package/.next/standalone/crates/fpai-ipc/src/framing.rs +177 -0
- package/.next/standalone/crates/fpai-ipc/src/lib.rs +10 -0
- package/.next/standalone/crates/fpai-ipc/src/peer.rs +80 -0
- package/.next/standalone/package.json +5 -3
- package/.next/standalone/rust-toolchain.toml +4 -0
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai-worker.mjs +51 -0
- package/bin/failproofai.mjs +68 -1
- package/bin/failproofaid-shim.mjs +67 -0
- package/dist/cli.mjs +1202 -624
- package/dist/worker.mjs +8441 -0
- package/package.json +5 -3
- package/src/hooks/builtin-policies.ts +37 -13
- package/src/hooks/configure-wizard.ts +73 -1
- package/src/hooks/daemon-client.ts +199 -0
- package/src/hooks/daemon-download.ts +152 -0
- package/src/hooks/daemon-service.ts +449 -0
- package/src/hooks/handler.ts +231 -195
- package/src/hooks/normalize-cli-payload.ts +61 -0
- package/src/hooks/policy-types.ts +15 -0
- package/src/hooks/read-stdin.ts +48 -0
- package/src/hooks/worker-server.ts +154 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1is3glr._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0fopait._.js +0 -3
- /package/.next/standalone/.next/static/{ePKMmXXfXxThNsxwv1EiF → 7Lxtd352rSaHB-pmm6G8M}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{ePKMmXXfXxThNsxwv1EiF → 7Lxtd352rSaHB-pmm6G8M}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{ePKMmXXfXxThNsxwv1EiF → 7Lxtd352rSaHB-pmm6G8M}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "autocfg"
|
|
7
|
+
version = "1.5.1"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "bit-set"
|
|
13
|
+
version = "0.8.0"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
|
|
16
|
+
dependencies = [
|
|
17
|
+
"bit-vec",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[[package]]
|
|
21
|
+
name = "bit-vec"
|
|
22
|
+
version = "0.8.0"
|
|
23
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
24
|
+
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
|
25
|
+
|
|
26
|
+
[[package]]
|
|
27
|
+
name = "bitflags"
|
|
28
|
+
version = "2.13.1"
|
|
29
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
30
|
+
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
|
31
|
+
|
|
32
|
+
[[package]]
|
|
33
|
+
name = "cfg-if"
|
|
34
|
+
version = "1.0.4"
|
|
35
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
36
|
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
37
|
+
|
|
38
|
+
[[package]]
|
|
39
|
+
name = "errno"
|
|
40
|
+
version = "0.3.14"
|
|
41
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
42
|
+
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
|
43
|
+
dependencies = [
|
|
44
|
+
"libc",
|
|
45
|
+
"windows-sys",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[[package]]
|
|
49
|
+
name = "failproofaid"
|
|
50
|
+
version = "1.0.0-beta.0"
|
|
51
|
+
dependencies = [
|
|
52
|
+
"fpai-ipc",
|
|
53
|
+
"libc",
|
|
54
|
+
"serde",
|
|
55
|
+
"serde_json",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[[package]]
|
|
59
|
+
name = "fastrand"
|
|
60
|
+
version = "2.5.0"
|
|
61
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
62
|
+
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
|
63
|
+
|
|
64
|
+
[[package]]
|
|
65
|
+
name = "fnv"
|
|
66
|
+
version = "1.0.7"
|
|
67
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
68
|
+
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
|
69
|
+
|
|
70
|
+
[[package]]
|
|
71
|
+
name = "fpai-ipc"
|
|
72
|
+
version = "1.0.0-beta.0"
|
|
73
|
+
dependencies = [
|
|
74
|
+
"libc",
|
|
75
|
+
"proptest",
|
|
76
|
+
"serde",
|
|
77
|
+
"serde_json",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
[[package]]
|
|
81
|
+
name = "getrandom"
|
|
82
|
+
version = "0.3.4"
|
|
83
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
84
|
+
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
|
85
|
+
dependencies = [
|
|
86
|
+
"cfg-if",
|
|
87
|
+
"libc",
|
|
88
|
+
"r-efi 5.3.0",
|
|
89
|
+
"wasip2",
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
[[package]]
|
|
93
|
+
name = "getrandom"
|
|
94
|
+
version = "0.4.3"
|
|
95
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
96
|
+
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
|
97
|
+
dependencies = [
|
|
98
|
+
"cfg-if",
|
|
99
|
+
"libc",
|
|
100
|
+
"r-efi 6.0.0",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
[[package]]
|
|
104
|
+
name = "itoa"
|
|
105
|
+
version = "1.0.18"
|
|
106
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
107
|
+
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|
108
|
+
|
|
109
|
+
[[package]]
|
|
110
|
+
name = "libc"
|
|
111
|
+
version = "0.2.189"
|
|
112
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
113
|
+
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
|
114
|
+
|
|
115
|
+
[[package]]
|
|
116
|
+
name = "linux-raw-sys"
|
|
117
|
+
version = "0.12.1"
|
|
118
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
119
|
+
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
|
120
|
+
|
|
121
|
+
[[package]]
|
|
122
|
+
name = "memchr"
|
|
123
|
+
version = "2.8.3"
|
|
124
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
125
|
+
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
|
126
|
+
|
|
127
|
+
[[package]]
|
|
128
|
+
name = "num-traits"
|
|
129
|
+
version = "0.2.19"
|
|
130
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
131
|
+
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
|
132
|
+
dependencies = [
|
|
133
|
+
"autocfg",
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
[[package]]
|
|
137
|
+
name = "once_cell"
|
|
138
|
+
version = "1.21.4"
|
|
139
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
140
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
141
|
+
|
|
142
|
+
[[package]]
|
|
143
|
+
name = "ppv-lite86"
|
|
144
|
+
version = "0.2.21"
|
|
145
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
146
|
+
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
|
147
|
+
dependencies = [
|
|
148
|
+
"zerocopy",
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
[[package]]
|
|
152
|
+
name = "proc-macro2"
|
|
153
|
+
version = "1.0.107"
|
|
154
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
155
|
+
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
|
156
|
+
dependencies = [
|
|
157
|
+
"unicode-ident",
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
[[package]]
|
|
161
|
+
name = "proptest"
|
|
162
|
+
version = "1.11.0"
|
|
163
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
164
|
+
checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744"
|
|
165
|
+
dependencies = [
|
|
166
|
+
"bit-set",
|
|
167
|
+
"bit-vec",
|
|
168
|
+
"bitflags",
|
|
169
|
+
"num-traits",
|
|
170
|
+
"rand",
|
|
171
|
+
"rand_chacha",
|
|
172
|
+
"rand_xorshift",
|
|
173
|
+
"regex-syntax",
|
|
174
|
+
"rusty-fork",
|
|
175
|
+
"tempfile",
|
|
176
|
+
"unarray",
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
[[package]]
|
|
180
|
+
name = "quick-error"
|
|
181
|
+
version = "1.2.3"
|
|
182
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
183
|
+
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
|
184
|
+
|
|
185
|
+
[[package]]
|
|
186
|
+
name = "quote"
|
|
187
|
+
version = "1.0.47"
|
|
188
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
189
|
+
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
|
190
|
+
dependencies = [
|
|
191
|
+
"proc-macro2",
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
[[package]]
|
|
195
|
+
name = "r-efi"
|
|
196
|
+
version = "5.3.0"
|
|
197
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
198
|
+
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
|
199
|
+
|
|
200
|
+
[[package]]
|
|
201
|
+
name = "r-efi"
|
|
202
|
+
version = "6.0.0"
|
|
203
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
204
|
+
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
|
205
|
+
|
|
206
|
+
[[package]]
|
|
207
|
+
name = "rand"
|
|
208
|
+
version = "0.9.5"
|
|
209
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
210
|
+
checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
|
|
211
|
+
dependencies = [
|
|
212
|
+
"rand_chacha",
|
|
213
|
+
"rand_core",
|
|
214
|
+
]
|
|
215
|
+
|
|
216
|
+
[[package]]
|
|
217
|
+
name = "rand_chacha"
|
|
218
|
+
version = "0.9.0"
|
|
219
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
220
|
+
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
|
221
|
+
dependencies = [
|
|
222
|
+
"ppv-lite86",
|
|
223
|
+
"rand_core",
|
|
224
|
+
]
|
|
225
|
+
|
|
226
|
+
[[package]]
|
|
227
|
+
name = "rand_core"
|
|
228
|
+
version = "0.9.5"
|
|
229
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
230
|
+
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
|
|
231
|
+
dependencies = [
|
|
232
|
+
"getrandom 0.3.4",
|
|
233
|
+
]
|
|
234
|
+
|
|
235
|
+
[[package]]
|
|
236
|
+
name = "rand_xorshift"
|
|
237
|
+
version = "0.4.0"
|
|
238
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
239
|
+
checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
|
|
240
|
+
dependencies = [
|
|
241
|
+
"rand_core",
|
|
242
|
+
]
|
|
243
|
+
|
|
244
|
+
[[package]]
|
|
245
|
+
name = "regex-syntax"
|
|
246
|
+
version = "0.8.11"
|
|
247
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
248
|
+
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
|
249
|
+
|
|
250
|
+
[[package]]
|
|
251
|
+
name = "rustix"
|
|
252
|
+
version = "1.1.4"
|
|
253
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
254
|
+
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
|
255
|
+
dependencies = [
|
|
256
|
+
"bitflags",
|
|
257
|
+
"errno",
|
|
258
|
+
"libc",
|
|
259
|
+
"linux-raw-sys",
|
|
260
|
+
"windows-sys",
|
|
261
|
+
]
|
|
262
|
+
|
|
263
|
+
[[package]]
|
|
264
|
+
name = "rusty-fork"
|
|
265
|
+
version = "0.3.1"
|
|
266
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
267
|
+
checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2"
|
|
268
|
+
dependencies = [
|
|
269
|
+
"fnv",
|
|
270
|
+
"quick-error",
|
|
271
|
+
"tempfile",
|
|
272
|
+
"wait-timeout",
|
|
273
|
+
]
|
|
274
|
+
|
|
275
|
+
[[package]]
|
|
276
|
+
name = "serde"
|
|
277
|
+
version = "1.0.229"
|
|
278
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
279
|
+
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
|
280
|
+
dependencies = [
|
|
281
|
+
"serde_core",
|
|
282
|
+
"serde_derive",
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
[[package]]
|
|
286
|
+
name = "serde_core"
|
|
287
|
+
version = "1.0.229"
|
|
288
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
289
|
+
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
|
290
|
+
dependencies = [
|
|
291
|
+
"serde_derive",
|
|
292
|
+
]
|
|
293
|
+
|
|
294
|
+
[[package]]
|
|
295
|
+
name = "serde_derive"
|
|
296
|
+
version = "1.0.229"
|
|
297
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
298
|
+
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
|
299
|
+
dependencies = [
|
|
300
|
+
"proc-macro2",
|
|
301
|
+
"quote",
|
|
302
|
+
"syn 3.0.3",
|
|
303
|
+
]
|
|
304
|
+
|
|
305
|
+
[[package]]
|
|
306
|
+
name = "serde_json"
|
|
307
|
+
version = "1.0.151"
|
|
308
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
309
|
+
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
|
310
|
+
dependencies = [
|
|
311
|
+
"itoa",
|
|
312
|
+
"memchr",
|
|
313
|
+
"serde",
|
|
314
|
+
"serde_core",
|
|
315
|
+
"zmij",
|
|
316
|
+
]
|
|
317
|
+
|
|
318
|
+
[[package]]
|
|
319
|
+
name = "syn"
|
|
320
|
+
version = "2.0.119"
|
|
321
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
322
|
+
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
|
323
|
+
dependencies = [
|
|
324
|
+
"proc-macro2",
|
|
325
|
+
"quote",
|
|
326
|
+
"unicode-ident",
|
|
327
|
+
]
|
|
328
|
+
|
|
329
|
+
[[package]]
|
|
330
|
+
name = "syn"
|
|
331
|
+
version = "3.0.3"
|
|
332
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
333
|
+
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
|
|
334
|
+
dependencies = [
|
|
335
|
+
"proc-macro2",
|
|
336
|
+
"quote",
|
|
337
|
+
"unicode-ident",
|
|
338
|
+
]
|
|
339
|
+
|
|
340
|
+
[[package]]
|
|
341
|
+
name = "tempfile"
|
|
342
|
+
version = "3.27.0"
|
|
343
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
344
|
+
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
|
345
|
+
dependencies = [
|
|
346
|
+
"fastrand",
|
|
347
|
+
"getrandom 0.4.3",
|
|
348
|
+
"once_cell",
|
|
349
|
+
"rustix",
|
|
350
|
+
"windows-sys",
|
|
351
|
+
]
|
|
352
|
+
|
|
353
|
+
[[package]]
|
|
354
|
+
name = "unarray"
|
|
355
|
+
version = "0.1.4"
|
|
356
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
357
|
+
checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
|
|
358
|
+
|
|
359
|
+
[[package]]
|
|
360
|
+
name = "unicode-ident"
|
|
361
|
+
version = "1.0.24"
|
|
362
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
363
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
364
|
+
|
|
365
|
+
[[package]]
|
|
366
|
+
name = "wait-timeout"
|
|
367
|
+
version = "0.2.1"
|
|
368
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
369
|
+
checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
|
|
370
|
+
dependencies = [
|
|
371
|
+
"libc",
|
|
372
|
+
]
|
|
373
|
+
|
|
374
|
+
[[package]]
|
|
375
|
+
name = "wasip2"
|
|
376
|
+
version = "1.0.4+wasi-0.2.12"
|
|
377
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
378
|
+
checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
|
|
379
|
+
dependencies = [
|
|
380
|
+
"wit-bindgen",
|
|
381
|
+
]
|
|
382
|
+
|
|
383
|
+
[[package]]
|
|
384
|
+
name = "windows-link"
|
|
385
|
+
version = "0.2.1"
|
|
386
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
387
|
+
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
|
388
|
+
|
|
389
|
+
[[package]]
|
|
390
|
+
name = "windows-sys"
|
|
391
|
+
version = "0.61.2"
|
|
392
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
393
|
+
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
|
394
|
+
dependencies = [
|
|
395
|
+
"windows-link",
|
|
396
|
+
]
|
|
397
|
+
|
|
398
|
+
[[package]]
|
|
399
|
+
name = "wit-bindgen"
|
|
400
|
+
version = "0.57.1"
|
|
401
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
402
|
+
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
|
403
|
+
|
|
404
|
+
[[package]]
|
|
405
|
+
name = "zerocopy"
|
|
406
|
+
version = "0.8.55"
|
|
407
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
408
|
+
checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb"
|
|
409
|
+
dependencies = [
|
|
410
|
+
"zerocopy-derive",
|
|
411
|
+
]
|
|
412
|
+
|
|
413
|
+
[[package]]
|
|
414
|
+
name = "zerocopy-derive"
|
|
415
|
+
version = "0.8.55"
|
|
416
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
417
|
+
checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb"
|
|
418
|
+
dependencies = [
|
|
419
|
+
"proc-macro2",
|
|
420
|
+
"quote",
|
|
421
|
+
"syn 2.0.119",
|
|
422
|
+
]
|
|
423
|
+
|
|
424
|
+
[[package]]
|
|
425
|
+
name = "zmij"
|
|
426
|
+
version = "1.0.23"
|
|
427
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
428
|
+
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# failproofaid wire protocol
|
|
2
|
+
|
|
3
|
+
The contract between the `failproofai` CLI (thin client) and the `failproofaid`
|
|
4
|
+
daemon over a Unix domain socket. This is the same contract every hook
|
|
5
|
+
invocation already has today — see `src/hooks/handler.ts`'s
|
|
6
|
+
`handleHookEvent`: `(argv --hook <Event> --cli <cli>, stdin JSON payload) ->
|
|
7
|
+
(stdout, stderr, exitCode)`. The daemon adds nothing to that contract; it only
|
|
8
|
+
relays it over a socket instead of a fresh process's argv/stdin/stdout.
|
|
9
|
+
|
|
10
|
+
Implemented in `crates/fpai-ipc` (framing + envelope + peer verification) and
|
|
11
|
+
`crates/failproofaid` (the socket server itself). As of Stage 2, the daemon
|
|
12
|
+
answers `ping` and rejects `hook` with a stub "not implemented" error — Stage 3
|
|
13
|
+
wires `hook` up to a real warm Node/Bun worker.
|
|
14
|
+
|
|
15
|
+
## Transport
|
|
16
|
+
|
|
17
|
+
One Unix domain socket, one connection per request. The daemon reads exactly
|
|
18
|
+
one frame, dispatches it, writes exactly one frame back, and lets the
|
|
19
|
+
connection close — there is no request-ID multiplexing because there is never
|
|
20
|
+
more than one logical request in flight per connection.
|
|
21
|
+
|
|
22
|
+
Default path: `~/.failproofai/run/failproofaid.sock`. Overridable via the
|
|
23
|
+
`FAILPROOFAI_DAEMON_SOCKET` env var (used by local dev and tests — never point
|
|
24
|
+
this at a directory failproofaid doesn't own itself; see
|
|
25
|
+
`crates/failproofaid/src/paths.rs`'s `ensure_run_dir`, which refuses to modify
|
|
26
|
+
permissions on a pre-existing directory it didn't create).
|
|
27
|
+
|
|
28
|
+
Permissions: the run directory is `0700` and the socket file `0600` — this is
|
|
29
|
+
the actual access-control boundary (user-scope only, no elevation, same OS
|
|
30
|
+
user only). `crates/fpai-ipc/src/peer.rs`'s `SO_PEERCRED` (Linux) /
|
|
31
|
+
`getpeereid` (macOS) check is defense-in-depth on top of that, not a stronger
|
|
32
|
+
boundary — same-user access can always reach this daemon regardless.
|
|
33
|
+
|
|
34
|
+
## Framing
|
|
35
|
+
|
|
36
|
+
Every message, in both directions, is:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
+----------------------------+------------------------------+
|
|
40
|
+
| length (4 bytes, big-endian u32) | UTF-8 JSON body (length bytes) |
|
|
41
|
+
+----------------------------+------------------------------+
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
A declared length over `MAX_FRAME_LEN` (16 MiB) is rejected without
|
|
45
|
+
allocating a body buffer for it — a hook payload is at most 1 MiB (see
|
|
46
|
+
`handler.ts`'s own stdin cap), so 16 MiB is headroom, not an expected size.
|
|
47
|
+
|
|
48
|
+
## Envelope
|
|
49
|
+
|
|
50
|
+
Tagged JSON, `"type"` as the discriminant, camelCase field names.
|
|
51
|
+
|
|
52
|
+
### Client → daemon (`ClientMessage`)
|
|
53
|
+
|
|
54
|
+
```jsonc
|
|
55
|
+
// Liveness/handshake check.
|
|
56
|
+
{ "type": "ping", "protocolVersion": 1 }
|
|
57
|
+
|
|
58
|
+
// One hook evaluation request — one per `failproofai --hook <Event> --cli <cli>` invocation.
|
|
59
|
+
{
|
|
60
|
+
"type": "hook",
|
|
61
|
+
"protocolVersion": 1,
|
|
62
|
+
"hookEvent": "PreToolUse",
|
|
63
|
+
"cli": "claude",
|
|
64
|
+
"stdin": "<raw stdin payload the calling agent CLI wrote to the one-shot failproofai process, forwarded verbatim>",
|
|
65
|
+
"cwd": "/path/to/session/cwd" // optional; see the note below
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`cwd` must be the *originating* CLI process's cwd, captured by the thin
|
|
70
|
+
client before dispatch — never the daemon's own cwd. The daemon is a single
|
|
71
|
+
long-lived process; its own `cwd` does not vary per request and must never be
|
|
72
|
+
used to resolve project config or custom policies (this is the "process.cwd()
|
|
73
|
+
hazard" the TS-side plan calls out explicitly).
|
|
74
|
+
|
|
75
|
+
### Daemon → client (`ServerMessage`)
|
|
76
|
+
|
|
77
|
+
```jsonc
|
|
78
|
+
{ "type": "pong", "protocolVersion": 1 }
|
|
79
|
+
|
|
80
|
+
{
|
|
81
|
+
"type": "hookResult",
|
|
82
|
+
"protocolVersion": 1,
|
|
83
|
+
"exitCode": 0,
|
|
84
|
+
"stdout": "...",
|
|
85
|
+
"stderr": "..."
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// The daemon accepted the connection and parsed the request, but could not
|
|
89
|
+
// produce a verdict (worker down/hung, or — in Stage 2 — hook evaluation
|
|
90
|
+
// simply isn't wired up yet). Distinct from hookResult so the client can
|
|
91
|
+
// tell "ran and decided" apart from "daemon couldn't evaluate at all" — the
|
|
92
|
+
// latter is what drives the client's fail-closed path.
|
|
93
|
+
{ "type": "error", "protocolVersion": 1, "message": "..." }
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Protocol versioning
|
|
97
|
+
|
|
98
|
+
`protocolVersion` is carried on every message in both directions. A mismatch
|
|
99
|
+
gets an explicit `error` response from the daemon — the client treats *any*
|
|
100
|
+
failure mode (missing socket, refused connection, timeout, malformed
|
|
101
|
+
response, or an explicit version mismatch) identically: fall through to
|
|
102
|
+
whatever the client's fail-closed/in-process policy dictates. There is no
|
|
103
|
+
negotiation, only agree-or-fall-back.
|
|
104
|
+
|
|
105
|
+
## Peer verification
|
|
106
|
+
|
|
107
|
+
Every connection is checked with `SO_PEERCRED`/`getpeereid` before a single
|
|
108
|
+
byte of the request is read. A peer running as a different OS user gets the
|
|
109
|
+
connection dropped with **no response at all** — not even an `error` frame —
|
|
110
|
+
so a connection from the wrong user can't even confirm a daemon is listening
|
|
111
|
+
there.
|
|
112
|
+
|
|
113
|
+
## Malformed input handling
|
|
114
|
+
|
|
115
|
+
- A frame whose declared length exceeds `MAX_FRAME_LEN`: connection closed,
|
|
116
|
+
no response, no allocation attempted for the declared size.
|
|
117
|
+
- A syntactically invalid or truncated frame: connection closed, no response.
|
|
118
|
+
- A well-formed frame with an unrecognized `"type"`: fails to deserialize,
|
|
119
|
+
same as above.
|
|
120
|
+
|
|
121
|
+
None of these crash the daemon or the connection-handling thread — a bad
|
|
122
|
+
frame from one connection has no effect on any other connection.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "failproofaid"
|
|
3
|
+
version.workspace = true
|
|
4
|
+
edition.workspace = true
|
|
5
|
+
license-file.workspace = true
|
|
6
|
+
repository.workspace = true
|
|
7
|
+
description = "Thin Rust supervisor: owns the failproofai IPC socket, service lifecycle, and warm worker process supervision. Carries no policy logic."
|
|
8
|
+
publish = false
|
|
9
|
+
|
|
10
|
+
[[bin]]
|
|
11
|
+
name = "failproofaid"
|
|
12
|
+
path = "src/main.rs"
|
|
13
|
+
|
|
14
|
+
[dependencies]
|
|
15
|
+
fpai-ipc = { path = "../fpai-ipc" }
|
|
16
|
+
serde = { version = "1", features = ["derive"] }
|
|
17
|
+
serde_json = "1"
|
|
18
|
+
libc = "0.2"
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//! Single-instance guard: at most one `failproofaid` per OS user.
|
|
2
|
+
//!
|
|
3
|
+
//! Uses an advisory `flock()` on a dedicated lock file rather than a
|
|
4
|
+
//! PID file — a PID file has to be checked-then-trusted (the PID could
|
|
5
|
+
//! have been reused by an unrelated process since), whereas `flock` is
|
|
6
|
+
//! released automatically by the kernel when the holding process exits or
|
|
7
|
+
//! is killed, for any reason, with no stale-file cleanup required.
|
|
8
|
+
|
|
9
|
+
use std::fs::{File, OpenOptions};
|
|
10
|
+
use std::io;
|
|
11
|
+
use std::os::unix::io::AsRawFd;
|
|
12
|
+
use std::path::Path;
|
|
13
|
+
|
|
14
|
+
pub struct SingletonLock {
|
|
15
|
+
// Held for the guard's lifetime; the flock is released when this File
|
|
16
|
+
// (and its underlying fd) is dropped.
|
|
17
|
+
_file: File,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#[derive(Debug)]
|
|
21
|
+
pub enum LockError {
|
|
22
|
+
Io(io::Error),
|
|
23
|
+
AlreadyRunning,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
impl std::fmt::Display for LockError {
|
|
27
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
28
|
+
match self {
|
|
29
|
+
LockError::Io(e) => write!(f, "io error acquiring daemon lock: {e}"),
|
|
30
|
+
LockError::AlreadyRunning => {
|
|
31
|
+
write!(f, "another failproofaid is already running for this user")
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
impl std::error::Error for LockError {}
|
|
38
|
+
|
|
39
|
+
/// Tries to acquire the singleton lock at `path`, creating the file if
|
|
40
|
+
/// needed. Returns [`LockError::AlreadyRunning`] immediately (non-blocking)
|
|
41
|
+
/// if another live process already holds it.
|
|
42
|
+
pub fn acquire(path: &Path) -> Result<SingletonLock, LockError> {
|
|
43
|
+
let file = OpenOptions::new()
|
|
44
|
+
.create(true)
|
|
45
|
+
.truncate(false)
|
|
46
|
+
.write(true)
|
|
47
|
+
.open(path)
|
|
48
|
+
.map_err(LockError::Io)?;
|
|
49
|
+
|
|
50
|
+
let ret = unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_EX | libc::LOCK_NB) };
|
|
51
|
+
if ret != 0 {
|
|
52
|
+
let err = io::Error::last_os_error();
|
|
53
|
+
return match err.raw_os_error() {
|
|
54
|
+
Some(libc::EWOULDBLOCK) => Err(LockError::AlreadyRunning),
|
|
55
|
+
_ => Err(LockError::Io(err)),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
Ok(SingletonLock { _file: file })
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#[cfg(test)]
|
|
62
|
+
mod tests {
|
|
63
|
+
use super::*;
|
|
64
|
+
|
|
65
|
+
#[test]
|
|
66
|
+
fn a_second_acquire_in_the_same_process_fails_while_the_first_is_held() {
|
|
67
|
+
let tmp = std::env::temp_dir().join(format!(
|
|
68
|
+
"failproofaid-lock-test-{}-{}",
|
|
69
|
+
std::process::id(),
|
|
70
|
+
line!()
|
|
71
|
+
));
|
|
72
|
+
let first = acquire(&tmp).expect("first acquire should succeed");
|
|
73
|
+
let second = acquire(&tmp);
|
|
74
|
+
assert!(matches!(second, Err(LockError::AlreadyRunning)));
|
|
75
|
+
drop(first);
|
|
76
|
+
// Once released, a fresh acquire succeeds again.
|
|
77
|
+
let third = acquire(&tmp);
|
|
78
|
+
assert!(third.is_ok());
|
|
79
|
+
std::fs::remove_file(&tmp).ok();
|
|
80
|
+
}
|
|
81
|
+
}
|