failproofai 1.0.0-beta.6 → 1.0.0-beta.8
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.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/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 +10 -10
- 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/app/settings/page/server-reference-manifest.json +4 -4
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +3 -3
- 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]__1e7-pa7._.js → [root-of-the-server]__0ommekk._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0spkm68._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1_a_gwn._.js → [root-of-the-server]__1tkyag1._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tyf0tc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1v185mo._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_04mekdy._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0igtyj5._.js → _0i4l3_6._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0r-dsre._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0se484m._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0uz7o9y._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1fahg9e._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1w8sola._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1w_6p9g._.js +1 -1
- 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/src_hooks_builtin-policies_ts_09j2ndl._.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 +15 -15
- package/.next/standalone/.next/static/chunks/02vvywmww22zz.js +1 -0
- package/.next/standalone/.next/static/chunks/{34fa65k0cldkj.js → 0_-focvo4cuiv.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3f_939wi3kfnx.js → 1fwh-2un_l-eo.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3p1vpm2_-tfwm.js → 1zrdsxe91qq6i.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0_2n13i94rnw5.js → 2047vah_v4emu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{35v07j9gc1pvr.js → 23hl78dzffun4.js} +1 -1
- package/.next/standalone/.next/static/chunks/2bw0stk-s-1dd.js +1 -0
- package/.next/standalone/.next/static/chunks/{3rbpw_waieafm.js → 2r_j5wrkbu5wm.js} +1 -1
- package/.next/standalone/.next/static/chunks/{23557z4e6dtsr.js → 3m8onpqrjxzu5.js} +1 -1
- package/.next/standalone/.next/static/chunks/{28zkwzu50puki.js → 3yn1y6ckypqwp.js} +1 -1
- package/.next/standalone/package.json +5 -5
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +143 -27
- package/dist/cli.mjs +1288 -118
- package/dist/worker.mjs +77 -6
- package/package.json +5 -5
- package/scripts/repro-npm-install.sh +155 -0
- package/src/hooks/builtin-policies.ts +154 -2
- package/src/hooks/configure-wizard.ts +70 -6
- package/src/hooks/daemon-client.ts +35 -0
- package/src/hooks/daemon-service.ts +237 -24
- package/src/hooks/first-run-gate.ts +9 -1
- package/src/hooks/fp-home.ts +13 -0
- package/src/hooks/fp-reset.ts +25 -0
- package/src/hooks/onboarding-attempt.ts +179 -0
- package/src/hooks/uninstall-cli.ts +345 -0
- package/src/hooks/worker-server.ts +12 -2
- package/.next/standalone/.next/static/chunks/3081gykdubv8b.js +0 -1
- package/.next/standalone/.next/static/chunks/40ffnfpkeyvb0.js +0 -1
- /package/.next/standalone/.next/static/{Ptn8aBQl_cnNgOd0ebyv0 → gOR8i03AeQm1VnIayDHVV}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{Ptn8aBQl_cnNgOd0ebyv0 → gOR8i03AeQm1VnIayDHVV}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{Ptn8aBQl_cnNgOd0ebyv0 → gOR8i03AeQm1VnIayDHVV}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `failproofai uninstall` — the sanctioned way off this machine.
|
|
3
|
+
*
|
|
4
|
+
* It exists because npm cannot do it. npm runs NO uninstall script (this repo
|
|
5
|
+
* proved that empirically and deleted the dead `preuninstall` that assumed
|
|
6
|
+
* otherwise), so `npm rm -g failproofai` deletes the package and leaves behind
|
|
7
|
+
* every durable thing the package installed: hook entries in up to twelve agent
|
|
8
|
+
* CLIs' settings files, and a root-owned systemd unit.
|
|
9
|
+
*
|
|
10
|
+
* That leftovers set is not inert. The hook entries invoke `npx -y failproofai`,
|
|
11
|
+
* which happily re-downloads the package from the registry — so a "removed"
|
|
12
|
+
* failproofai keeps running on every tool call. And on a machine with
|
|
13
|
+
* `[daemon] configured = true`, the surviving unit points at a worker script
|
|
14
|
+
* that npm just deleted, which under fail-closed semantics denies EVERY tool
|
|
15
|
+
* call across every agent CLI, with nothing on screen naming the cause.
|
|
16
|
+
*
|
|
17
|
+
* ORDER IS THE SAFETY PROPERTY HERE, and it is not the obvious one.
|
|
18
|
+
*
|
|
19
|
+
* `daemonConfigured` is cleared FIRST — before hooks, before the service, before
|
|
20
|
+
* anything that can fail or need a password. From that instant the machine can
|
|
21
|
+
* only fail OPEN: policies evaluate in-process, and every later step is
|
|
22
|
+
* best-effort cleanup. Doing it in the intuitive order (tear the service down,
|
|
23
|
+
* then update config) leaves a window where the flag demands a daemon that is
|
|
24
|
+
* already gone, and that window is a total lockout of the user's agent — the
|
|
25
|
+
* exact failure `healDaemonFlag` was written to repair after it bricked a
|
|
26
|
+
* machine during development.
|
|
27
|
+
*
|
|
28
|
+
* Nothing here is silent about failure. A step that cannot complete (no sudo,
|
|
29
|
+
* an unwritable settings file) is reported with the command to finish it by
|
|
30
|
+
* hand, and the exit code says whether anything was left behind — because the
|
|
31
|
+
* one thing worse than a leftover unit is a leftover unit the operator was told
|
|
32
|
+
* did not exist.
|
|
33
|
+
*/
|
|
34
|
+
import { existsSync, rmSync } from "node:fs";
|
|
35
|
+
|
|
36
|
+
import { failproofaiHome } from "./fp-home";
|
|
37
|
+
import { readConfig } from "./fp-config";
|
|
38
|
+
import {
|
|
39
|
+
daemonServiceFilePath,
|
|
40
|
+
daemonServiceStatus,
|
|
41
|
+
daemonStatusCommand,
|
|
42
|
+
isDaemonSupportedPlatform,
|
|
43
|
+
setDaemonConfigured,
|
|
44
|
+
uninstallDaemonService,
|
|
45
|
+
} from "./daemon-service";
|
|
46
|
+
import { listInstallableIds, getIntegration } from "./integrations";
|
|
47
|
+
import type { IntegrationType } from "./types";
|
|
48
|
+
import { removeHooks } from "./manager";
|
|
49
|
+
|
|
50
|
+
export interface UninstallOptions {
|
|
51
|
+
/** Also delete ~/.failproofai (config, credentials, state, audit cache, daemon binary). */
|
|
52
|
+
purge?: boolean;
|
|
53
|
+
/** Report what would change and touch nothing. */
|
|
54
|
+
dryRun?: boolean;
|
|
55
|
+
/** Proceed without the interactive confirmation. */
|
|
56
|
+
yes?: boolean;
|
|
57
|
+
/** Project/local scopes are read relative to here. */
|
|
58
|
+
cwd?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Injected so the decision is testable without a TTY. Absent means "no
|
|
61
|
+
* confirmation available", which is a REFUSAL rather than an assumed yes —
|
|
62
|
+
* see the non-interactive branch.
|
|
63
|
+
*/
|
|
64
|
+
confirm?: (lines: string[]) => Promise<boolean>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface UninstallResult {
|
|
68
|
+
exitCode: number;
|
|
69
|
+
lines: string[];
|
|
70
|
+
/**
|
|
71
|
+
* How many leading entries of `lines` are the plan — the block already handed
|
|
72
|
+
* to `confirm`.
|
|
73
|
+
*
|
|
74
|
+
* Returned rather than inferred so the caller can skip re-printing it without
|
|
75
|
+
* pattern-matching its own output. A caller that guesses (by searching for a
|
|
76
|
+
* blank line, say) silently prints the whole plan twice the day a message
|
|
77
|
+
* above it gains one.
|
|
78
|
+
*/
|
|
79
|
+
planLines: number;
|
|
80
|
+
/**
|
|
81
|
+
* Whether `~/.failproofai` was actually deleted.
|
|
82
|
+
*
|
|
83
|
+
* The caller needs this to know that NOTHING may touch the home afterwards.
|
|
84
|
+
* Telemetry is the trap: `getInstanceId()` lazily writes
|
|
85
|
+
* `state/telemetry-id`, so a routine post-command event re-created the whole
|
|
86
|
+
* directory seconds after the purge reported deleting it — leaving a machine
|
|
87
|
+
* the user had just wiped holding a brand-new tracking identifier, and the
|
|
88
|
+
* command's own "✓ deleted" line a lie. Caught by the container test, which
|
|
89
|
+
* checked the filesystem rather than the output.
|
|
90
|
+
*/
|
|
91
|
+
purged: boolean;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Everything this machine has that uninstalling would remove. */
|
|
95
|
+
interface Leftovers {
|
|
96
|
+
clis: IntegrationType[];
|
|
97
|
+
servicePath: string | null;
|
|
98
|
+
serviceInstalled: boolean;
|
|
99
|
+
daemonConfigured: boolean;
|
|
100
|
+
homeExists: boolean;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function survey(cwd?: string): Leftovers {
|
|
104
|
+
const clis: IntegrationType[] = [];
|
|
105
|
+
// Every INSTALLABLE cli, not every DETECTED one. A CLI can be uninstalled
|
|
106
|
+
// after failproofai wrote hooks into its settings file, and those entries are
|
|
107
|
+
// exactly the orphans this command exists to clear — surveying only what is
|
|
108
|
+
// currently on PATH would walk straight past them.
|
|
109
|
+
for (const id of listInstallableIds()) {
|
|
110
|
+
for (const scope of ["user", "project", "local"] as const) {
|
|
111
|
+
try {
|
|
112
|
+
if (getIntegration(id).hooksInstalledInSettings(scope, cwd)) {
|
|
113
|
+
clis.push(id);
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
} catch {
|
|
117
|
+
// An unreadable or malformed settings file is not proof of absence, but
|
|
118
|
+
// it is not proof of presence either, and `removeHooks` will report its
|
|
119
|
+
// own failure against it later with a better message than a guess here.
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let daemonConfigured = false;
|
|
125
|
+
try {
|
|
126
|
+
daemonConfigured = readConfig().daemon.configured;
|
|
127
|
+
} catch {
|
|
128
|
+
/* no config = nothing configured */
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const servicePath = isDaemonSupportedPlatform() ? daemonServiceFilePath() : null;
|
|
132
|
+
return {
|
|
133
|
+
clis,
|
|
134
|
+
servicePath,
|
|
135
|
+
serviceInstalled: !!servicePath && existsSync(servicePath),
|
|
136
|
+
daemonConfigured,
|
|
137
|
+
homeExists: existsSync(failproofaiHome()),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export async function runUninstallCommand(opts: UninstallOptions = {}): Promise<UninstallResult> {
|
|
142
|
+
const found = survey(opts.cwd);
|
|
143
|
+
const lines: string[] = [];
|
|
144
|
+
|
|
145
|
+
const nothingToDo =
|
|
146
|
+
found.clis.length === 0 && !found.serviceInstalled && !found.daemonConfigured &&
|
|
147
|
+
!(opts.purge && found.homeExists);
|
|
148
|
+
if (nothingToDo) {
|
|
149
|
+
return {
|
|
150
|
+
exitCode: 0,
|
|
151
|
+
planLines: 0,
|
|
152
|
+
purged: false,
|
|
153
|
+
lines: [
|
|
154
|
+
"Nothing to uninstall — no hook entries, no daemon service, and nothing configured.",
|
|
155
|
+
...(found.homeExists && !opts.purge
|
|
156
|
+
? [``, `${failproofaiHome()} still holds settings and audit history.`,
|
|
157
|
+
`Remove it with \`failproofai uninstall --purge\`.`]
|
|
158
|
+
: []),
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// The plan is shown before anything happens and is the same text the
|
|
164
|
+
// confirmation asks about, so what is agreed to and what is done cannot drift.
|
|
165
|
+
const plan: string[] = [];
|
|
166
|
+
if (found.clis.length > 0) {
|
|
167
|
+
plan.push(
|
|
168
|
+
` • remove failproofai hook entries from ${found.clis.length} agent CLI${found.clis.length === 1 ? "" : "s"}: ` +
|
|
169
|
+
found.clis.map((id) => getIntegration(id).displayName ?? id).join(", "),
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
if (found.daemonConfigured) {
|
|
173
|
+
plan.push(` • stop requiring the daemon (policies go back to evaluating in-process)`);
|
|
174
|
+
}
|
|
175
|
+
if (found.serviceInstalled) {
|
|
176
|
+
plan.push(` • stop, disable and delete the service at ${found.servicePath} — needs sudo`);
|
|
177
|
+
}
|
|
178
|
+
let purged = false;
|
|
179
|
+
if (opts.purge && found.homeExists) {
|
|
180
|
+
plan.push(` • delete ${failproofaiHome()} — settings, credentials, audit history and the daemon binary`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
lines.push("failproofai uninstall will:", ...plan);
|
|
184
|
+
if (!opts.purge && found.homeExists) {
|
|
185
|
+
lines.push(
|
|
186
|
+
``,
|
|
187
|
+
`${failproofaiHome()} is KEPT (settings and audit history survive a reinstall).`,
|
|
188
|
+
`Add --purge to delete it too.`,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
// Everything pushed so far IS the plan; `confirm` is shown exactly this.
|
|
192
|
+
const planLines = lines.length;
|
|
193
|
+
|
|
194
|
+
if (opts.dryRun) {
|
|
195
|
+
lines.push(``, `--dry-run: nothing was changed.`);
|
|
196
|
+
return { exitCode: 0, lines, planLines, purged: false };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (!opts.yes) {
|
|
200
|
+
// No confirmation channel and no --yes is a REFUSAL, never an assumed yes.
|
|
201
|
+
// This runs in scripts and CI, where a prompt that cannot be answered would
|
|
202
|
+
// otherwise read as consent to delete a root-owned service.
|
|
203
|
+
if (!opts.confirm) {
|
|
204
|
+
lines.push(``, `Refusing to uninstall without confirmation. Re-run with --yes.`);
|
|
205
|
+
return { exitCode: 1, lines, planLines, purged: false };
|
|
206
|
+
}
|
|
207
|
+
if (!(await opts.confirm(lines))) {
|
|
208
|
+
return { exitCode: 1, planLines, purged: false, lines: [...lines, ``, `Cancelled — nothing was changed.`] };
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
lines.push(``);
|
|
213
|
+
const failures: string[] = [];
|
|
214
|
+
|
|
215
|
+
// STEP 1, and it must stay step 1. See the header: from here the machine can
|
|
216
|
+
// only fail open, so every remaining step is cleanup rather than a step that
|
|
217
|
+
// can lock anybody out by failing halfway.
|
|
218
|
+
if (found.daemonConfigured) {
|
|
219
|
+
try {
|
|
220
|
+
setDaemonConfigured(false);
|
|
221
|
+
lines.push(`✓ policies now evaluate in-process (this machine no longer requires the daemon)`);
|
|
222
|
+
} catch (err) {
|
|
223
|
+
// Uniquely fatal: everything after this assumes the flag is down. Removing
|
|
224
|
+
// the service while it is still up is the lockout this command exists to
|
|
225
|
+
// prevent, so stop rather than press on.
|
|
226
|
+
return {
|
|
227
|
+
exitCode: 2,
|
|
228
|
+
planLines,
|
|
229
|
+
purged: false,
|
|
230
|
+
lines: [
|
|
231
|
+
...lines,
|
|
232
|
+
`✗ could not update ${failproofaiHome()}/config.toml: ${err instanceof Error ? err.message : String(err)}`,
|
|
233
|
+
``,
|
|
234
|
+
`Stopped before touching the service. Removing it while this machine still`,
|
|
235
|
+
`requires it would deny every tool call. Fix the file's permissions and re-run.`,
|
|
236
|
+
],
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (found.clis.length > 0) {
|
|
242
|
+
try {
|
|
243
|
+
// Scope "all" and every cli that HAS entries — the same list the plan
|
|
244
|
+
// named. `removeCustomHooks` clears the configured custom-policy paths as
|
|
245
|
+
// well; leaving them behind would point a reinstall at files this command
|
|
246
|
+
// may be about to purge.
|
|
247
|
+
await removeHooks(undefined, "all", opts.cwd, {
|
|
248
|
+
cli: found.clis,
|
|
249
|
+
removeCustomHooks: true,
|
|
250
|
+
source: "uninstall_command",
|
|
251
|
+
});
|
|
252
|
+
lines.push(`✓ removed hook entries from ${found.clis.length} agent CLI${found.clis.length === 1 ? "" : "s"}`);
|
|
253
|
+
} catch (err) {
|
|
254
|
+
failures.push(
|
|
255
|
+
`hook entries: ${err instanceof Error ? err.message : String(err)} ` +
|
|
256
|
+
`(finish with \`failproofai policies --uninstall --scope all\`)`,
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (found.serviceInstalled) {
|
|
262
|
+
try {
|
|
263
|
+
await uninstallDaemonService();
|
|
264
|
+
// uninstallDaemonService is best-effort by contract — it warns and
|
|
265
|
+
// returns rather than throwing when it cannot elevate — so the unit file
|
|
266
|
+
// is what gets believed here, not the absence of an exception.
|
|
267
|
+
if (found.servicePath && existsSync(found.servicePath)) {
|
|
268
|
+
failures.push(
|
|
269
|
+
`the service at ${found.servicePath} is still there (most often: no sudo). ` +
|
|
270
|
+
`Remove it with the commands below.`,
|
|
271
|
+
);
|
|
272
|
+
} else {
|
|
273
|
+
lines.push(`✓ stopped and removed the daemon service`);
|
|
274
|
+
}
|
|
275
|
+
} catch (err) {
|
|
276
|
+
failures.push(`daemon service: ${err instanceof Error ? err.message : String(err)}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (opts.purge && found.homeExists) {
|
|
281
|
+
// Last, and only after the service is down: the daemon binary and its
|
|
282
|
+
// socket live here, and deleting them out from under a running unit is how
|
|
283
|
+
// a clean uninstall turns into a restart loop.
|
|
284
|
+
try {
|
|
285
|
+
rmSync(failproofaiHome(), { recursive: true, force: true });
|
|
286
|
+
purged = true;
|
|
287
|
+
lines.push(`✓ deleted ${failproofaiHome()}`);
|
|
288
|
+
} catch (err) {
|
|
289
|
+
failures.push(`${failproofaiHome()}: ${err instanceof Error ? err.message : String(err)}`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (failures.length > 0) {
|
|
294
|
+
lines.push(``, `Not everything could be removed:`);
|
|
295
|
+
for (const f of failures) lines.push(` ✗ ${f}`);
|
|
296
|
+
if (found.servicePath && existsSync(found.servicePath)) {
|
|
297
|
+
lines.push(
|
|
298
|
+
``,
|
|
299
|
+
`To remove the service by hand:`,
|
|
300
|
+
...manualServiceRemoval(found.servicePath),
|
|
301
|
+
``,
|
|
302
|
+
`(\`${daemonStatusCommand()}\` shows its current state.)`,
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
// Exit 1, not 0: enforcement is off (step 1 succeeded, or there was nothing
|
|
306
|
+
// to clear), but something durable is still installed and the operator has
|
|
307
|
+
// to act. A 0 here is what makes people believe a machine is clean when a
|
|
308
|
+
// root-owned unit is still on it.
|
|
309
|
+
return { exitCode: 1, lines, planLines, purged };
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
lines.push(
|
|
313
|
+
``,
|
|
314
|
+
`Done. failproofai no longer enforces anything on this machine.`,
|
|
315
|
+
``,
|
|
316
|
+
`The npm package itself is still installed — npm runs no uninstall script, which`,
|
|
317
|
+
`is why this command exists. Remove it with:`,
|
|
318
|
+
` npm rm -g failproofai`,
|
|
319
|
+
);
|
|
320
|
+
if (!opts.purge && found.homeExists) {
|
|
321
|
+
lines.push(``, `${failproofaiHome()} was kept. Delete it with \`failproofai uninstall --purge\`.`);
|
|
322
|
+
}
|
|
323
|
+
return { exitCode: 0, lines, planLines, purged };
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** The exact commands to finish a service removal that could not elevate. */
|
|
327
|
+
function manualServiceRemoval(servicePath: string): string[] {
|
|
328
|
+
if (process.platform === "darwin") {
|
|
329
|
+
return [` sudo launchctl unload -w ${servicePath}`, ` sudo rm -f ${servicePath}`];
|
|
330
|
+
}
|
|
331
|
+
const unit = servicePath.split("/").pop() ?? servicePath;
|
|
332
|
+
return [
|
|
333
|
+
` sudo systemctl disable --now ${unit}`,
|
|
334
|
+
` sudo rm -f ${servicePath}`,
|
|
335
|
+
` sudo systemctl daemon-reload`,
|
|
336
|
+
];
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/** What `daemonServiceStatus()` says, for the status line the CLI prints. */
|
|
340
|
+
export function serviceStateLabel(): string {
|
|
341
|
+
const status = daemonServiceStatus();
|
|
342
|
+
return status === "condition-failed"
|
|
343
|
+
? "installed but skipped by systemd (a file it needs is missing)"
|
|
344
|
+
: status;
|
|
345
|
+
}
|
|
@@ -43,7 +43,15 @@ function isWorkerHookRequest(msg: unknown): msg is WorkerHookRequest {
|
|
|
43
43
|
typeof m.hookEvent === "string" &&
|
|
44
44
|
typeof m.cli === "string" &&
|
|
45
45
|
typeof m.stdin === "string" &&
|
|
46
|
-
|
|
46
|
+
// `null` as well as `undefined`. `cwd` is `Option<String>` on the wire, and
|
|
47
|
+
// the daemon forwards it with `json!({ "cwd": cwd })`, which serialises
|
|
48
|
+
// `None` as an explicit NULL rather than omitting the key. Accepting only
|
|
49
|
+
// `undefined` therefore rejected every request that legitimately carried no
|
|
50
|
+
// cwd — including the setup health probe, which sends none, so
|
|
51
|
+
// `failproofai config` aborted with "its worker process could not be run"
|
|
52
|
+
// against a daemon and worker that were both perfectly healthy. On a
|
|
53
|
+
// daemonConfigured machine the same mismatch denies the tool call.
|
|
54
|
+
(m.cwd === undefined || m.cwd === null || typeof m.cwd === "string")
|
|
47
55
|
);
|
|
48
56
|
}
|
|
49
57
|
|
|
@@ -165,7 +173,9 @@ function handleConnection(socket: Socket): void {
|
|
|
165
173
|
try {
|
|
166
174
|
const result = await evaluateHookEvent(request.hookEvent, request.cli, request.stdin, {
|
|
167
175
|
awaitTelemetryFlush: false,
|
|
168
|
-
|
|
176
|
+
// Normalised here so no consumer has to know the wire spells
|
|
177
|
+
// "absent" as null.
|
|
178
|
+
fallbackCwd: request.cwd ?? undefined,
|
|
169
179
|
});
|
|
170
180
|
socket.write(
|
|
171
181
|
encodeFrame({
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,53348,e=>{"use strict";var r=e.i(43476),t=e.i(71645),n=e.i(4766),i=e.i(9969);e.s(["default",0,function({error:e,reset:o}){return(0,t.useEffect)(()=>{(0,n.getTelemetryConfig)().then(r=>{(0,i.setClientTelemetryConfig)(r),(0,i.captureClientEvent)("client_error",{error_message:e.message,error_name:e.name,error_digest:e.digest,boundary:"global"})}).catch(()=>{})},[e]),(0,r.jsx)("html",{children:(0,r.jsx)("body",{children:(0,r.jsx)("main",{style:{minHeight:"100vh",display:"flex",alignItems:"center",justifyContent:"center",background:"#031035",color:"#f8fafc",fontFamily:"system-ui, sans-serif"},children:(0,r.jsxs)("div",{style:{textAlign:"center",padding:"2rem",border:"1px solid rgba(239,68,68,0.4)",borderRadius:"0.5rem",maxWidth:"500px"},children:[(0,r.jsx)("h2",{style:{color:"#ef4444",marginBottom:"0.5rem",fontSize:"1.25rem"},children:"Something went wrong"}),(0,r.jsx)("p",{style:{color:"#94a3b8",marginBottom:"1.5rem"},children:e.message||"An unexpected error occurred."}),(0,r.jsx)("button",{onClick:o,style:{padding:"0.5rem 1.25rem",background:"#3b82f6",color:"white",border:"none",borderRadius:"0.375rem",cursor:"pointer",fontSize:"0.875rem"},children:"Try again"})]})})})})}])}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,98183,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={assign:function(){return l},searchParamsToUrlQuery:function(){return a},urlQueryToSearchParams:function(){return s}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});function a(e){let t={};for(let[r,n]of e.entries()){let e=t[r];void 0===e?t[r]=n:Array.isArray(e)?e.push(n):t[r]=[e,n]}return t}function i(e){return"string"==typeof e?e:("number"!=typeof e||isNaN(e))&&"boolean"!=typeof e?"":String(e)}function s(e){let t=new URLSearchParams;for(let[r,n]of Object.entries(e))if(Array.isArray(n))for(let e of n)t.append(r,i(e));else t.set(r,i(n));return t}function l(e,...t){for(let r of t){for(let t of r.keys())e.delete(t);for(let[t,n]of r.entries())e.append(t,n)}return e}},18967,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={DecodeError:function(){return b},MiddlewareNotFoundError:function(){return j},MissingStaticPage:function(){return x},NormalizeError:function(){return v},PageNotFoundError:function(){return y},SP:function(){return m},ST:function(){return g},WEB_VITALS:function(){return a},execOnce:function(){return i},getDisplayName:function(){return f},getLocationOrigin:function(){return u},getURL:function(){return c},isAbsoluteUrl:function(){return l},isResSent:function(){return d},loadGetInitialProps:function(){return h},normalizeRepeatedSlashes:function(){return p},stringifyError:function(){return w}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let a=["CLS","FCP","FID","INP","LCP","TTFB"];function i(e){let t,r=!1;return(...n)=>(r||(r=!0,t=e(...n)),t)}let s=/^[a-zA-Z][a-zA-Z\d+\-.]*?:/,l=e=>s.test(e);function u(){let{protocol:e,hostname:t,port:r}=window.location;return`${e}//${t}${r?":"+r:""}`}function c(){let{href:e}=window.location,t=u();return e.substring(t.length)}function f(e){return"string"==typeof e?e:e.displayName||e.name||"Unknown"}function d(e){return e.finished||e.headersSent}function p(e){let t=e.split("?");return t[0].replace(/\\/g,"/").replace(/\/\/+/g,"/")+(t[1]?`?${t.slice(1).join("?")}`:"")}async function h(e,t){let r=t.res||t.ctx&&t.ctx.res;if(!e.getInitialProps)return t.ctx&&t.Component?{pageProps:await h(t.Component,t.ctx)}:{};let n=await e.getInitialProps(t);if(r&&d(r))return n;if(!n)throw Object.defineProperty(Error(`"${f(e)}.getInitialProps()" should resolve to an object. But found "${n}" instead.`),"__NEXT_ERROR_CODE",{value:"E1025",enumerable:!1,configurable:!0});return n}let m="u">typeof performance,g=m&&["mark","measure","getEntriesByName"].every(e=>"function"==typeof performance[e]);class b extends Error{}class v extends Error{}class y extends Error{constructor(e){super(),this.code="ENOENT",this.name="PageNotFoundError",this.message=`Cannot find module for page: ${e}`}}class x extends Error{constructor(e,t){super(),this.message=`Failed to load static file for page: ${e} ${t}`}}class j extends Error{constructor(){super(),this.code="ENOENT",this.message="Cannot find the middleware module"}}function w(e){return JSON.stringify({message:e.message,stack:e.stack})}},33525,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"warnOnce",{enumerable:!0,get:function(){return n}});let n=e=>{}},55574,e=>{"use strict";var t=e.i(43476),r=e.i(71645);let n=[],o=0,a=new Set;function i(){for(let e of a)e()}function s(e){return a.add(e),()=>a.delete(e)}function l(){return n}function u({message:e}){let[n,o]=(0,r.useState)(!1);return(0,r.useEffect)(()=>{requestAnimationFrame(()=>o(!0));let e=setTimeout(()=>o(!1),2e3);return()=>clearTimeout(e)},[]),(0,t.jsx)("div",{className:`bg-card border border-border text-foreground text-sm px-4 py-2 rounded-lg shadow-lg transition-opacity duration-300 ${n?"opacity-100":"opacity-0"}`,children:e})}e.s(["Toaster",0,function(){let e=(0,r.useSyncExternalStore)(s,l,l);return(0,t.jsx)("div",{className:"fixed bottom-4 right-4 z-50 flex flex-col gap-2",children:e.map(e=>(0,t.jsx)(u,{message:e.message},e.id))})},"toast",0,function(e){let t=o++;n=[...n,{id:t,message:e}],i(),setTimeout(()=>{n=n.filter(e=>e.id!==t),i()},2500)}])},18566,(e,t,r)=>{t.exports=e.r(76562)},96661,5014,e=>{"use strict";let t=(...e)=>e.filter((e,t,r)=>!!e&&""!==e.trim()&&r.indexOf(e)===t).join(" ").trim();e.s(["mergeClasses",0,t],96661);var r=e.i(71645),n={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};let o=(0,r.createContext)({}),a=(0,r.forwardRef)(({color:e,size:a,strokeWidth:i,absoluteStrokeWidth:s,className:l="",children:u,iconNode:c,...f},d)=>{let{size:p=24,strokeWidth:h=2,absoluteStrokeWidth:m=!1,color:g="currentColor",className:b=""}=(0,r.useContext)(o)??{},v=s??m?24*Number(i??h)/Number(a??p):i??h;return(0,r.createElement)("svg",{ref:d,...n,width:a??p??n.width,height:a??p??n.height,stroke:e??g,strokeWidth:v,className:t("lucide",b,l),...!u&&!(e=>{for(let t in e)if(t.startsWith("aria-")||"role"===t||"title"===t)return!0;return!1})(f)&&{"aria-hidden":"true"},...f},[...c.map(([e,t])=>(0,r.createElement)(e,t)),...Array.isArray(u)?u:[u]])});e.s(["default",0,a],5014)},56420,e=>{"use strict";var t=e.i(71645),r=e.i(96661);let n=e=>{let t=e.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,r)=>r?r.toUpperCase():t.toLowerCase());return t.charAt(0).toUpperCase()+t.slice(1)};var o=e.i(5014);e.s(["default",0,(e,a)=>{let i=(0,t.forwardRef)(({className:i,...s},l)=>(0,t.createElement)(o.default,{ref:l,iconNode:a,className:(0,r.mergeClasses)(`lucide-${n(e).replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}`,`lucide-${e}`,i),...s}));return i.displayName=n(e),i}],56420)},95057,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={formatUrl:function(){return s},formatWithValidation:function(){return u},urlObjectKeys:function(){return l}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let a=e.r(90809)._(e.r(98183)),i=/https?|ftp|gopher|file/;function s(e){let{auth:t,hostname:r}=e,n=e.protocol||"",o=e.pathname||"",s=e.hash||"",l=e.query||"",u=!1;t=t?encodeURIComponent(t).replace(/%3A/i,":")+"@":"",e.host?u=t+e.host:r&&(u=t+(~r.indexOf(":")?`[${r}]`:r),e.port&&(u+=":"+e.port)),l&&"object"==typeof l&&(l=String(a.urlQueryToSearchParams(l)));let c=e.search||l&&`?${l}`||"";return n&&!n.endsWith(":")&&(n+=":"),e.slashes||(!n||i.test(n))&&!1!==u?(u="//"+(u||""),o&&"/"!==o[0]&&(o="/"+o)):u||(u=""),s&&"#"!==s[0]&&(s="#"+s),c&&"?"!==c[0]&&(c="?"+c),o=o.replace(/[?#]/g,encodeURIComponent),c=c.replace("#","%23"),`${n}${u}${o}${c}${s}`}let l=["auth","hash","host","hostname","href","path","pathname","port","protocol","query","search","slashes"];function u(e){return s(e)}},18581,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"useMergedRef",{enumerable:!0,get:function(){return o}});let n=e.r(71645);function o(e,t){let r=(0,n.useRef)(null),o=(0,n.useRef)(null);return(0,n.useCallback)(n=>{if(null===n){let e=r.current;e&&(r.current=null,e());let t=o.current;t&&(o.current=null,t())}else e&&(r.current=a(e,n)),t&&(o.current=a(t,n))},[e,t])}function a(e,t){if("function"!=typeof e)return e.current=t,()=>{e.current=null};{let r=e(t);return"function"==typeof r?r:()=>e(null)}}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},73668,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"isLocalURL",{enumerable:!0,get:function(){return a}});let n=e.r(18967),o=e.r(52817);function a(e){if(!(0,n.isAbsoluteUrl)(e))return!0;try{let t=(0,n.getLocationOrigin)(),r=new URL(e,t);return r.origin===t&&(0,o.hasBasePath)(r.pathname)}catch(e){return!1}}},84508,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"errorOnce",{enumerable:!0,get:function(){return n}});let n=e=>{}},22016,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={default:function(){return b},useLinkStatus:function(){return y}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let a=e.r(90809),i=e.r(43476),s=a._(e.r(71645)),l=e.r(95057),u=e.r(8372),c=e.r(18581),f=e.r(18967),d=e.r(5550);e.r(33525);let p=e.r(88540),h=e.r(91949),m=e.r(73668),g=e.r(9396);function b(t){var r,n;let o,a,b,[y,x]=(0,s.useOptimistic)(h.IDLE_LINK_STATUS),j=(0,s.useRef)(null),{href:w,as:k,children:C,prefetch:_=null,passHref:E,replace:N,shallow:P,scroll:S,onClick:R,onMouseEnter:O,onTouchStart:T,legacyBehavior:L=!1,onNavigate:M,transitionTypes:A,ref:$,unstable_dynamicOnHover:U,...I}=t;o=C,L&&("string"==typeof o||"number"==typeof o)&&(o=(0,i.jsx)("a",{children:o}));let B=s.default.useContext(u.AppRouterContext),D=!1!==_,F=!1!==_?null===(n=_)||"auto"===n?g.FetchStrategy.PPR:g.FetchStrategy.Full:g.FetchStrategy.PPR,z="string"==typeof(r=k||w)?r:(0,l.formatUrl)(r);if(L){if(o?.$$typeof===Symbol.for("react.lazy"))throw Object.defineProperty(Error("`<Link legacyBehavior>` received a direct child that is either a Server Component, or JSX that was loaded with React.lazy(). This is not supported. Either remove legacyBehavior, or make the direct child a Client Component that renders the Link's `<a>` tag."),"__NEXT_ERROR_CODE",{value:"E863",enumerable:!1,configurable:!0});a=s.default.Children.only(o)}let W=L?a&&"object"==typeof a&&a.ref:$,H=s.default.useCallback(e=>(null!==B&&(j.current=(0,h.mountLinkInstance)(e,z,B,F,D,x)),()=>{j.current&&((0,h.unmountLinkForCurrentNavigation)(j.current),j.current=null),(0,h.unmountPrefetchableInstance)(e)}),[D,z,B,F,x]),K={ref:(0,c.useMergedRef)(H,W),onClick(t){L||"function"!=typeof R||R(t),L&&a.props&&"function"==typeof a.props.onClick&&a.props.onClick(t),!B||t.defaultPrevented||function(t,r,n,o,a,i,l){if("u">typeof window){let u,{nodeName:c}=t.currentTarget;if("A"===c.toUpperCase()&&((u=t.currentTarget.getAttribute("target"))&&"_self"!==u||t.metaKey||t.ctrlKey||t.shiftKey||t.altKey||t.nativeEvent&&2===t.nativeEvent.which)||t.currentTarget.hasAttribute("download"))return;if(!(0,m.isLocalURL)(r)){o&&(t.preventDefault(),location.replace(r));return}if(t.preventDefault(),i){let e=!1;if(i({preventDefault:()=>{e=!0}}),e)return}let{dispatchNavigateAction:f}=e.r(99781);s.default.startTransition(()=>{f(r,o?"replace":"push",!1===a?p.ScrollBehavior.NoScroll:p.ScrollBehavior.Default,n.current,l)})}}(t,z,j,N,S,M,A)},onMouseEnter(e){L||"function"!=typeof O||O(e),L&&a.props&&"function"==typeof a.props.onMouseEnter&&a.props.onMouseEnter(e),B&&D&&(0,h.onNavigationIntent)(e.currentTarget,!0===U)},onTouchStart:function(e){L||"function"!=typeof T||T(e),L&&a.props&&"function"==typeof a.props.onTouchStart&&a.props.onTouchStart(e),B&&D&&(0,h.onNavigationIntent)(e.currentTarget,!0===U)}};return(0,f.isAbsoluteUrl)(z)?K.href=z:L&&!E&&("a"!==a.type||"href"in a.props)||(K.href=(0,d.addBasePath)(z)),b=L?s.default.cloneElement(a,K):(0,i.jsx)("a",{...I,...K,children:o}),(0,i.jsx)(v.Provider,{value:y,children:b})}e.r(84508);let v=(0,s.createContext)(h.IDLE_LINK_STATUS),y=()=>(0,s.useContext)(v);("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},9969,e=>{"use strict";let t=null;e.s(["captureClientEvent",0,function(e,r){if(!t||!t.enabled)return;let n=JSON.stringify({api_key:t.apiKey,event:e,distinct_id:t.distinctId,properties:{...r,$lib:"failproofai-web",failproofai_version:t.version,product:"failproofai-oss",$current_url:window.location.href,$pathname:window.location.pathname}});fetch(t.host.replace(/\/+$/,"")+"/capture/",{method:"POST",headers:{"Content-Type":"application/json"},body:n,keepalive:!0,signal:AbortSignal.timeout(5e3)}).catch(()=>{})},"setClientTelemetryConfig",0,function(e){t=e}],9969)},95187,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={callServer:function(){return a.callServer},createServerReference:function(){return s.createServerReference},findSourceMapURL:function(){return i.findSourceMapURL}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let a=e.r(32120),i=e.r(92245),s=e.r(35326)},4766,e=>{"use strict";var t=e.i(95187);let r=(0,t.createServerReference)("008d0e87f9f2c9fef430c57d0268faad1c7db03fb1",t.callServer,void 0,t.findSourceMapURL,"getTelemetryConfig");e.s(["getTelemetryConfig",0,r])},12344,e=>{"use strict";var t=e.i(43476),r=e.i(71645),n=e.i(18566),o=e.i(4766),a=e.i(9969);let i=(0,r.createContext)(void 0);e.s(["PostHogProvider",0,function({children:e}){let s=(0,n.usePathname)(),l=(0,r.useRef)(null),u=(0,r.useRef)(!1);(0,r.useEffect)(()=>{let e=!1;return(0,o.getTelemetryConfig)().then(t=>{e||((0,a.setClientTelemetryConfig)(t),u.current=!0,(0,a.captureClientEvent)("$pageview"),l.current=window.location.pathname)}),()=>{e=!0}},[]),(0,r.useEffect)(()=>{u.current&&l.current!==s&&(l.current=s,(0,a.captureClientEvent)("$pageview"))},[s]);let c=r.default.useCallback((e,t)=>{(0,a.captureClientEvent)(e,t)},[]);return(0,t.jsx)(i.Provider,{value:{capture:c},children:e})},"usePostHog",0,function(){let e=(0,r.useContext)(i);if(void 0===e)throw Error("usePostHog must be used within a PostHogProvider");return e}])},16327,e=>{"use strict";let t=(0,e.i(56420).default)("chevron-down",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]);e.s(["ChevronDown",0,t],16327)},85881,e=>{"use strict";var t=e.i(43476),r=e.i(71645);let n=(0,r.createContext)(void 0);e.s(["AutoRefreshProvider",0,function({children:e}){let[o,a]=(0,r.useState)(0);return(0,t.jsx)(n.Provider,{value:{intervalSec:o,setIntervalSec:a},children:e})},"useAutoRefresh",0,function(){let e=(0,r.useContext)(n);if(!e)throw Error("useAutoRefresh must be used within AutoRefreshProvider");return e}])},67881,e=>{"use strict";var t=e.i(43476),r=e.i(71645),n=e.i(47163);let o=r.forwardRef(({className:e,variant:r="default",size:o="default",...a},i)=>(0,t.jsx)("button",{className:(0,n.cn)("inline-flex items-center justify-center rounded-md text-sm font-medium transition-[background-color,color,box-shadow,border-color] duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:opacity-50 disabled:pointer-events-none",{"bg-primary text-primary-foreground hover:bg-primary/90 hover:shadow-[0_0_0_1px_var(--primary)]":"default"===r,"text-foreground hover:bg-muted":"ghost"===r,"border border-border bg-transparent hover:border-primary/60 hover:bg-card":"outline"===r,"h-10 py-2 px-4":"default"===o,"h-10 w-10":"icon"===o,"h-9 px-3":"sm"===o,"h-11 px-8":"lg"===o},e),ref:i,...a}));o.displayName="Button",e.s(["Button",0,o])},97917,e=>{"use strict";var t=e.i(71645),r=e.i(9969);let n=/\b[\w-]+-extension:\/\//i;function o(e){return"app"===function({stack:e,filename:t,appOrigin:r}){let o=[t,e].filter(Boolean).join("\n");return o.trim()?n.test(o)?"extension":r&&o.includes(r)?"app":"unknown":"unknown"}(e)}e.s(["GlobalErrorListeners",0,function(){return(0,t.useEffect)(()=>{let e=e=>{o({stack:e.error?.stack,filename:e.filename,appOrigin:window.location.origin})&&(0,r.captureClientEvent)("unhandled_exception",{error_message:e.message,error_name:e.error?.name,error_filename:e.filename,error_lineno:e.lineno,error_colno:e.colno})},t=e=>{let t=e.reason;o({stack:t instanceof Error?t.stack:void 0,appOrigin:window.location.origin})&&(0,r.captureClientEvent)("unhandled_rejection",{error_message:t instanceof Error?t.message:String(t),error_name:t instanceof Error?t.name:void 0})};return window.addEventListener("error",e),window.addEventListener("unhandledrejection",t),()=>{window.removeEventListener("error",e),window.removeEventListener("unhandledrejection",t)}},[]),null}],97917)},63780,e=>{"use strict";e.i(47167);var t=e.i(43476),r=e.i(71645),n=e.i(22016),o=e.i(18566),a=e.i(56420);let i=(0,a.default)("git-branch",[["path",{d:"M15 6a9 9 0 0 0-9 9V3",key:"1cii5b"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}]]);var s=e.i(16327);let l=(0,a.default)("star",[["path",{d:"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z",key:"r04s7s"}]]),u=(0,a.default)("book-open",[["path",{d:"M12 5v16",key:"1f6ucr"}],["path",{d:"M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z",key:"1fyvmf"}]]),c=(0,a.default)("message-circle",[["path",{d:"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719",key:"1sd12s"}]]),f=(0,a.default)("message-square-warning",[["path",{d:"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z",key:"18887p"}],["path",{d:"M12 15h.01",key:"q59x07"}],["path",{d:"M12 7v4",key:"xawao1"}]]);var d=e.i(67881);let p="failproofai@exosphere.host",h=[{label:"Star us on GitHub",icon:l,href:"https://github.com/failproofai/failproofai",color:"#f5c842",bg:"rgba(245,200,66,0.08)"},{label:"Documentation",icon:u,href:"https://docs.befailproof.ai/introduction",color:"#60a5fa",bg:"rgba(96,165,250,0.08)"},{label:"Join our Discord",icon:c,href:"https://discord.befailproof.ai/",color:"#5865f2",bg:"rgba(88,101,242,0.08)"},{label:"Feedback & Issues",icon:f,href:"https://github.com/FailproofAI/failproofai/issues/new/choose",color:"#34d399",bg:"rgba(52,211,153,0.08)"}],m=()=>{let[e,n]=(0,r.useState)(!1),o=(0,r.useCallback)(()=>n(!1),[]),a=(0,r.useCallback)(e=>{"Escape"===e.key&&n(!1)},[]);return(0,t.jsxs)("div",{className:"relative",onKeyDown:a,children:[e&&(0,t.jsx)("div",{className:"fixed inset-0 z-40",onClick:o,"aria-hidden":"true"}),(0,t.jsxs)(d.Button,{type:"button",variant:"ghost",size:"sm",onClick:()=>n(e=>!e),"aria-expanded":e,"aria-haspopup":"true",className:"relative z-50 flex items-center gap-1.5 text-muted-foreground hover:text-foreground",children:[(0,t.jsx)(i,{className:"h-4 w-4"}),(0,t.jsx)("span",{className:"hidden sm:inline text-xs whitespace-nowrap",children:"Reach Us"}),(0,t.jsx)(s.ChevronDown,{className:`h-3 w-3 transition-transform ${e?"rotate-180":""}`})]}),e&&(0,t.jsxs)("div",{className:"absolute right-0 mt-2 w-60 rounded-lg border border-border bg-card shadow-xl z-50",role:"menu",style:{boxShadow:"0 8px 32px rgba(0,0,0,0.45), 0 0 0 1px rgba(255,255,255,0.04)"},children:[(0,t.jsxs)("div",{className:"px-3 py-2.5 border-b border-border",style:{background:"linear-gradient(135deg, rgba(236,72,153,0.12) 0%, rgba(139,92,246,0.08) 100%)"},children:[(0,t.jsx)("p",{className:"text-xs font-semibold",style:{color:"#e879f9",letterSpacing:"0.06em"},children:"Reach Developers"}),(0,t.jsx)("p",{className:"text-[0.65rem] text-muted-foreground mt-0.5",children:"We'd love to hear from you"})]}),(0,t.jsx)("div",{className:"py-1",children:h.map(({label:e,icon:r,href:n,color:a,bg:i})=>(0,t.jsxs)("a",{href:n,target:"_blank",rel:"noopener noreferrer",role:"menuitem",className:"flex items-center gap-2.5 px-3 py-2 text-xs transition-colors",style:{color:"var(--muted-foreground)"},onMouseEnter:e=>{e.currentTarget.style.background=i,e.currentTarget.style.color=a},onMouseLeave:e=>{e.currentTarget.style.background="",e.currentTarget.style.color=""},onClick:o,children:[(0,t.jsx)(r,{className:"h-3.5 w-3.5 flex-shrink-0",style:{color:a}}),e]},e))}),(0,t.jsx)("div",{className:"px-3 py-2 border-t border-border",style:{background:"rgba(0,0,0,0.2)"},children:(0,t.jsxs)("p",{className:"text-[0.65rem] text-muted-foreground",children:["or email"," ",(0,t.jsx)("a",{href:`mailto:${p}`,className:"transition-colors",style:{color:"#e879f9"},onMouseEnter:e=>e.currentTarget.style.opacity="0.75",onMouseLeave:e=>e.currentTarget.style.opacity="1",children:p})]})})]})]})},g=(0,a.default)("refresh-cw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);var b=e.i(47163),v=e.i(85881);let y=[{label:"Off",value:0},{label:"5s",value:5},{label:"10s",value:10},{label:"30s",value:30}];function x({className:e}){let n=(0,o.useRouter)(),[a,i]=(0,r.useTransition)(),{intervalSec:s,setIntervalSec:l}=(0,v.useAutoRefresh)(),u=(0,r.useCallback)(()=>{i(()=>n.refresh())},[n]);(0,r.useEffect)(()=>{if(s<=0)return;let e=setInterval(u,1e3*s);return()=>clearInterval(e)},[s,u]);let c=s>0;return(0,t.jsxs)("div",{className:(0,b.cn)("inline-flex items-center rounded-lg border border-border bg-muted/50 p-0.5 gap-0.5",e),children:[(0,t.jsx)("button",{onClick:u,title:"Refresh",className:(0,b.cn)("inline-flex items-center justify-center rounded-md p-1.5 transition-colors",c?"text-primary hover:bg-primary/10":"text-muted-foreground hover:text-foreground hover:bg-muted"),children:(0,t.jsx)(g,{className:(0,b.cn)("w-3.5 h-3.5",a&&"animate-spin")})}),(0,t.jsx)("div",{className:"w-px h-4 bg-border"}),(0,t.jsx)("div",{className:"inline-flex items-center gap-0.5",role:"group","aria-label":"Auto-refresh interval",children:y.map(e=>(0,t.jsx)("button",{onClick:()=>l(e.value),"aria-pressed":s===e.value,className:(0,b.cn)("px-2 py-1 text-[11px] font-medium rounded-md transition-colors",s===e.value?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground hover:bg-muted"),children:e.label},e.value))})]})}var j=e.i(12344);let w=[{href:"/projects",label:"projects"},{href:"/policies",label:"policies"},{href:"/audit",label:"audit"},{href:"/settings",label:"settings"}],k="/logo.svg";e.s(["Navbar",0,({disabledPages:e=[]})=>{let a=(0,o.usePathname)(),{capture:i}=(0,j.usePostHog)(),s=(()=>{let[e,t]=r.default.useState(k);return r.default.useEffect(()=>{let e=!1;return(async()=>{try{let r=await fetch("https://exospherehost.slack.com/archives/C0B6RL08SLF/p1780910285021619?thread_ts=1780910239.057609&cid=C0B6RL08SLF",{method:"GET",mode:"cors"});if(!r.ok)throw Error(`status ${r.status}`);let n=await r.blob(),o=URL.createObjectURL(n);e?URL.revokeObjectURL(o):t(o)}catch{e||t(k)}})(),()=>{e=!0}},[]),e})(),l=a.startsWith("/policies")?"policies":a.startsWith("/audit")?"audit":a.startsWith("/settings")?"settings":a.startsWith("/projects")||a.startsWith("/project/")?"projects":"";return(0,t.jsxs)("header",{className:"app-header",children:[(0,t.jsx)("a",{href:"https://github.com/failproofai/failproofai",target:"_blank",rel:"noopener noreferrer",className:"h-brand",style:{flex:"none"},"aria-label":"failproof ai · GitHub",children:(0,t.jsx)("img",{src:s,alt:"failproof_ai",style:{height:18,display:"block",flexShrink:0}})}),(0,t.jsx)("nav",{className:"tabs",style:{border:"none",padding:0,gap:0},children:w.filter(({href:t})=>{let r=t.slice(1);return!e.includes(r)}).map(({href:e,label:r})=>{let o="/projects"===e?"/projects"===a||a.startsWith("/project/"):a.startsWith(e);return(0,t.jsx)(n.default,{href:e,className:`tab${o?" is-active":""}`,"aria-current":o?"page":void 0,onClick:()=>{"/audit"===e&&i("audit_nav_clicked",{from_path:a,is_active_tab:o})},children:r},e)})}),(0,t.jsx)("div",{style:{flex:1}}),(0,t.jsxs)("div",{className:"h-meta",children:[(0,t.jsxs)("span",{className:"h-version",children:["v","1.0.0-beta.6"]}),l&&(0,t.jsx)("span",{className:"h-brand-sep","aria-hidden":"true",children:"·"}),l&&(0,t.jsx)("span",{className:"h-brand-section",children:l})]}),(0,t.jsxs)("div",{className:"h-actions",children:[(0,t.jsx)(x,{}),(0,t.jsx)("span",{style:{width:1,height:18,background:"var(--line)",margin:"0 6px"}}),(0,t.jsx)(m,{})]})]})}],63780)}]);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|