failproofai 1.0.9-beta.2 → 1.0.10-beta.1

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.
Files changed (144) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +4 -4
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  10. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  11. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
  18. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  21. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  30. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  32. package/.next/standalone/.next/server/app/index.html +1 -1
  33. package/.next/standalone/.next/server/app/index.rsc +14 -14
  34. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
  35. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  36. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  37. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  38. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  41. package/.next/standalone/.next/server/app/policies/page.js +1 -1
  42. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  45. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  48. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  49. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  52. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  55. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  58. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  59. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  60. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  61. package/.next/standalone/.next/server/chunks/src_hooks_1eem5a7._.js +1 -1
  62. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04usis8._.js +2 -2
  63. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__056wjo4._.js +2 -2
  64. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1ox4w55._.js → [root-of-the-server]__0a2-9ht._.js} +2 -2
  65. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0xg95._.js +2 -2
  66. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rwtwpm._.js +2 -2
  67. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11mayhe._.js +2 -2
  68. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15578wp._.js +2 -2
  69. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1m_svbe._.js +2 -2
  70. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pprgri._.js +2 -2
  71. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1q4p5b8._.js +2 -2
  72. package/.next/standalone/.next/server/chunks/ssr/_042cgl1._.js +1 -1
  73. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  74. package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +1 -1
  75. package/.next/standalone/.next/server/chunks/ssr/{_0n6zrjv._.js → _0krq5f0._.js} +3 -3
  76. package/.next/standalone/.next/server/chunks/ssr/_1gb0ifp._.js +2 -2
  77. package/.next/standalone/.next/server/chunks/ssr/{_1pa3k5k._.js → _1n-mym7._.js} +1 -1
  78. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  79. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
  80. package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  82. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  83. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h4._.js +1 -1
  85. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  86. package/.next/standalone/.next/server/pages/404.html +1 -1
  87. package/.next/standalone/.next/server/pages/500.html +1 -1
  88. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  89. package/.next/standalone/.next/server/server-reference-manifest.json +23 -23
  90. package/.next/standalone/.next/static/chunks/0s4cko_weh6pi.js +1 -0
  91. package/.next/standalone/.next/static/chunks/0yclxmfppc_8e.js +1 -0
  92. package/.next/standalone/.next/static/chunks/{30z-240_lrczt.js → 1-k37ijadiv9h.js} +1 -1
  93. package/.next/standalone/.next/static/chunks/{28cmd5molgwa3.js → 18reoqya39rov.js} +1 -1
  94. package/.next/standalone/.next/static/chunks/{2b59i-n9l-4of.js → 2cvvec76j9bwq.js} +1 -1
  95. package/.next/standalone/.next/static/chunks/2o9-3ff26v4yd.js +1 -0
  96. package/.next/standalone/.next/static/chunks/3q8vesnwk_r0i.js +1 -0
  97. package/.next/standalone/.next/static/chunks/3tj1zi4xv-bll.js +1 -0
  98. package/.next/standalone/.next/static/chunks/3vk6jdkxvb7yk.js +6 -0
  99. package/.next/standalone/.next/static/chunks/{1srecm9k-z_i1.js → 3z7mx6me_j7d3.js} +1 -1
  100. package/.next/standalone/.next/static/chunks/{2hg_bp8z_vm2g.js → 3ztf2h_fv6_t9.js} +1 -1
  101. package/.next/standalone/fp-cloud-cli/fp_cli/app.py +4 -0
  102. package/.next/standalone/fp-cloud-cli/fp_cli/auth.py +29 -4
  103. package/.next/standalone/fp-cloud-cli/fp_cli/client.py +57 -14
  104. package/.next/standalone/fp-cloud-cli/fp_cli/errors.py +17 -3
  105. package/.next/standalone/fp-cloud-cli/tests/test_request_id.py +111 -0
  106. package/.next/standalone/fp-cloud-cli/uv.lock +3 -3
  107. package/.next/standalone/hermes-plugin/README.md +83 -10
  108. package/.next/standalone/hermes-plugin/__init__.py +762 -28
  109. package/.next/standalone/hermes-plugin/client.py +4 -2
  110. package/.next/standalone/hermes-plugin/ledger.py +9 -3
  111. package/.next/standalone/hermes-plugin/plugin.yaml +2 -2
  112. package/.next/standalone/package.json +10 -10
  113. package/.next/standalone/sdk/python/failproofai_sdk/evaluator/__init__.py +8 -1
  114. package/.next/standalone/sdk/python/failproofai_sdk/evaluator/client.py +82 -7
  115. package/.next/standalone/sdk/python/failproofai_sdk/evaluator/runtime.py +23 -4
  116. package/.next/standalone/sdk/python/tests/test_evaluator_request_id.py +197 -0
  117. package/.next/standalone/sdk/python/uv.lock +9 -9
  118. package/.next/standalone/sdk/typescript/CHANGELOG.md +39 -0
  119. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +3 -3
  120. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +1 -1
  121. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package-lock.json +16 -113
  122. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package.json +3 -1
  123. package/.next/standalone/server.js +1 -1
  124. package/dist/cli.mjs +235 -117
  125. package/dist/worker.mjs +5 -2
  126. package/hermes-plugin/README.md +83 -10
  127. package/hermes-plugin/__init__.py +762 -28
  128. package/hermes-plugin/client.py +4 -2
  129. package/hermes-plugin/ledger.py +9 -3
  130. package/hermes-plugin/plugin.yaml +2 -2
  131. package/package.json +10 -10
  132. package/src/hooks/daemon-service.ts +14 -1
  133. package/src/hooks/integrations.ts +108 -26
  134. package/src/hooks/safe-config-write.ts +80 -7
  135. package/src/hooks/types.ts +7 -0
  136. package/.next/standalone/.next/static/chunks/0h--izcpk__m9.js +0 -1
  137. package/.next/standalone/.next/static/chunks/2k5vhij_w1g82.js +0 -1
  138. package/.next/standalone/.next/static/chunks/2o1fy-waqn1he.js +0 -6
  139. package/.next/standalone/.next/static/chunks/38gpf5tb_rd0m.js +0 -1
  140. package/.next/standalone/.next/static/chunks/3nyf50dub1vuk.js +0 -1
  141. package/.next/standalone/.next/static/chunks/42-l25bbfo0ec.js +0 -1
  142. /package/.next/standalone/.next/static/{D1BjwOkHNPetPo47DhV4_ → OJTzlkhxVSWnwhlF2Q7m3}/_buildManifest.js +0 -0
  143. /package/.next/standalone/.next/static/{D1BjwOkHNPetPo47DhV4_ → OJTzlkhxVSWnwhlF2Q7m3}/_clientMiddlewareManifest.js +0 -0
  144. /package/.next/standalone/.next/static/{D1BjwOkHNPetPo47DhV4_ → OJTzlkhxVSWnwhlF2Q7m3}/_ssgManifest.js +0 -0
@@ -98,11 +98,13 @@ def evaluate_policy(
98
98
  if len(body) > MAX_REQUEST_BYTES:
99
99
  raise EvaluationError("policy request exceeds the 1 MiB limit")
100
100
 
101
+ # One deadline covers connect, send and read: evaluation_timeout_ms is the
102
+ # longest a tool call can wait here. Connect is bounded by both budgets.
103
+ deadline = time.monotonic() + max(evaluation_timeout_ms, 1) / 1000
101
104
  try:
102
105
  with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
103
- sock.settimeout(max(connect_timeout_ms, 1) / 1000)
106
+ sock.settimeout(min(max(connect_timeout_ms, 1) / 1000, _remaining_timeout(deadline)))
104
107
  sock.connect(str(daemon_socket_path()))
105
- deadline = time.monotonic() + max(evaluation_timeout_ms, 1) / 1000
106
108
  sock.settimeout(_remaining_timeout(deadline))
107
109
  try:
108
110
  sock.sendall(struct.pack(">I", len(body)) + body)
@@ -23,7 +23,11 @@ class InstructionAction:
23
23
 
24
24
 
25
25
  class InstructionLedger:
26
- def __init__(self, path: Path, *, ttl_seconds: int = 3600, max_rounds: int = 2) -> None:
26
+ def __init__(
27
+ self, path: Path | None, *, ttl_seconds: int = 3600, max_rounds: int = 2
28
+ ) -> None:
29
+ # None means the host gave no usable state directory; every use then
30
+ # raises LedgerError, which callers already treat as degraded state.
27
31
  self.path = path
28
32
  self.ttl_seconds = max(60, int(ttl_seconds))
29
33
  self.max_rounds = max(0, int(max_rounds))
@@ -31,7 +35,9 @@ class InstructionLedger:
31
35
  self._initialized = False
32
36
 
33
37
  def _connect(self) -> sqlite3.Connection:
34
- self.path.parent.mkdir(parents=True, exist_ok=True)
38
+ if self.path is None:
39
+ raise LedgerError("instruction state directory is unavailable")
40
+ self.path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
35
41
  connection = sqlite3.connect(self.path, timeout=0.25, isolation_level=None)
36
42
  connection.execute("PRAGMA busy_timeout = 250")
37
43
  connection.execute("PRAGMA journal_mode = WAL")
@@ -70,7 +76,7 @@ class InstructionLedger:
70
76
  ON instruction_deliveries(profile, session_id, task_id, turn_id, expires_at_ms)
71
77
  """
72
78
  )
73
- except sqlite3.Error as exc:
79
+ except (sqlite3.Error, OSError) as exc:
74
80
  raise LedgerError(f"could not initialize instruction state: {exc}") from exc
75
81
  self._initialized = True
76
82
 
@@ -1,5 +1,5 @@
1
1
  name: failproofai
2
- version: 1.0.6-beta.0
2
+ version: 1.0.10-beta.1
3
3
  description: Real-time FailproofAI policy enforcement for Hermes
4
4
  manifest_version: 2
5
5
  api_version: 1
@@ -26,7 +26,7 @@ config_schema:
26
26
  evaluation_timeout_ms:
27
27
  type: int
28
28
  default: 12000
29
- description: Maximum total time allowed for one policy evaluation.
29
+ description: Maximum total time one policy evaluation may take, connect included (capped at 25000).
30
30
  instruction_ttl_seconds:
31
31
  type: int
32
32
  default: 3600
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "failproofai",
3
- "version": "1.0.9-beta.2",
3
+ "version": "1.0.10-beta.1",
4
4
  "description": "Observability and enforcement for AI agent harnesses. 40 built-in policies hooked into 12 of them — Claude Code, Codex, Cursor, Hermes, OpenClaw and more — blocking the tool call before it runs. Local dashboard included, no account needed.",
5
5
  "bin": {
6
6
  "failproofai": "./dist/cli.mjs",
@@ -117,20 +117,20 @@
117
117
  "eslint-plugin-react-hooks": "7.0.1",
118
118
  "vite": "8.0.16",
119
119
  "undici": "7.29.1",
120
- "brace-expansion": "5.0.9",
120
+ "brace-expansion": "5.0.12",
121
121
  "sharp": "0.35.4",
122
122
  "browserslist": "4.28.8"
123
123
  },
124
124
  "optionalDependencies": {
125
- "@failproofai/failproofaid-linux-x64": "1.0.9-beta.2",
126
- "@failproofai/failproofaid-linux-arm64": "1.0.9-beta.2",
127
- "@failproofai/failproofaid-darwin-x64": "1.0.9-beta.2",
128
- "@failproofai/failproofaid-darwin-arm64": "1.0.9-beta.2"
125
+ "@failproofai/failproofaid-linux-x64": "1.0.10-beta.1",
126
+ "@failproofai/failproofaid-linux-arm64": "1.0.10-beta.1",
127
+ "@failproofai/failproofaid-darwin-x64": "1.0.10-beta.1",
128
+ "@failproofai/failproofaid-darwin-arm64": "1.0.10-beta.1"
129
129
  },
130
130
  "failproofaidBinaries": {
131
- "linux-x64": "cd0a7124ae94ae78753cda6ffad985ba30be80443d8bc93d617ce507ba04e211",
132
- "linux-arm64": "925446186bbfa827275356a9dc80b7d5351a6dcce9d926731419bbd91c1f98ba",
133
- "darwin-x64": "cd35a6549f402b6c04848772074edb110a54a242fe7488792e59f8e8a00af475",
134
- "darwin-arm64": "587b045accada4947a556e1bc1d748780a846c2ef95cf8dafb973a23fdbcb173"
131
+ "linux-x64": "868a4978a66e4407b86dac8d6c8af4ad0b2b355da56983fa5530f5d8b5024098",
132
+ "linux-arm64": "8a4603784e43552ed8cf5ed7a1552721c7216be4fb106ed6851daabd18e19ebe",
133
+ "darwin-x64": "b6a59948ad12c06cedc90ebca95492a357430a2a150b76ceaf98930f8b1279c2",
134
+ "darwin-arm64": "8c14361f7274973bb2cf99135ddb4a5a9cdc8b453a33e653156ba6b68354c417"
135
135
  }
136
136
  }
@@ -1556,10 +1556,23 @@ export async function refreshDaemonToCliVersion(
1556
1556
  const prime = deps.prime ?? primeElevation;
1557
1557
  const interactive =
1558
1558
  deps.interactive ?? (() => Boolean(process.stdin.isTTY && process.stdout.isTTY));
1559
- if (status() === "not-installed") {
1559
+ const current = status();
1560
+ if (current === "not-installed") {
1560
1561
  return { ok: true, lines: ["No failproofaid service on this machine; nothing to update."] };
1561
1562
  }
1562
1563
 
1564
+ // Already this version: nothing to install, so nothing to ask root for. The
1565
+ // reinstall below is idempotent, but it needs sudo, so without this every
1566
+ // `update` after the daemon was brought current either prompted for a password
1567
+ // for no reason or — with no TTY to prompt on (a fleet box, CI) — failed with
1568
+ // "root privileges are required" and exited 1 on a machine that was fine.
1569
+ // `VERSION.daemon` is written only after an install succeeds, and the binary
1570
+ // it names must still be on disk.
1571
+ const recorded = readVersionFile()?.daemon;
1572
+ if (current === "running" && recorded === version && existsSync(installedBinaryPath(version))) {
1573
+ return { ok: true, lines: [`failproofaid ${version} is already installed and running; nothing to update.`] };
1574
+ }
1575
+
1563
1576
  // `installDaemonService()`, not a binary fetch plus a restart.
1564
1577
  //
1565
1578
  // The first version of this did the latter, and it did not work: it called
@@ -1178,7 +1178,7 @@ export const opencode: Integration = {
1178
1178
  // (a) Write the shim file. mkdirSync is recursive so the plugins/ dir
1179
1179
  // is created on first install.
1180
1180
  mkdirSync(dirname(pluginPath), { recursive: true });
1181
- writeConfigFileAtomic(pluginPath, buildOpenCodePluginShim(binaryPath, effectiveScope));
1181
+ writeConfigFileAtomic(pluginPath, buildOpenCodePluginShim(binaryPath, effectiveScope), { symlinks: "replace" });
1182
1182
 
1183
1183
  // (b) Merge our entry into the plugin array idempotently. Replace any
1184
1184
  // existing failproofai-marked entry; otherwise append.
@@ -1518,17 +1518,61 @@ function hasAllHermesPluginFiles(dir: string): boolean {
1518
1518
  }
1519
1519
 
1520
1520
  /**
1521
- * Whether `dir` is a FailproofAI `hermes-plugin` directory (or was one: a link
1522
- * whose target vanished during an npm upgrade or uninstall is still ours).
1523
- * The basename is the package layout; the manifest name confirms it when the
1524
- * target is readable, so a link to someone else's plugin is never claimed.
1521
+ * The record FailproofAI keeps beside a link it created:
1522
+ * `<profile>/plugins/.failproofai-link`, holding the link's target. It lives
1523
+ * OUTSIDE the linked directory on purpose — anything inside the target is
1524
+ * content whoever owns that directory controls. Hermes' plugin scan skips it
1525
+ * (a file, not a directory).
1525
1526
  */
1526
- function isFailproofaiHermesPluginSource(dir: string): boolean {
1527
- if (basename(dir) !== HERMES_PLUGIN_SOURCE_DIR) return false;
1528
- if (!existsSync(dir)) return true;
1527
+ const HERMES_LINK_RECORD = ".failproofai-link";
1528
+
1529
+ function hermesLinkRecordPath(pluginPath: string): string {
1530
+ return resolve(dirname(pluginPath), HERMES_LINK_RECORD);
1531
+ }
1532
+
1533
+ function readHermesLinkRecord(pluginPath: string): string | null {
1529
1534
  try {
1530
- const manifest = readFileSync(resolve(dir, "plugin.yaml"), "utf8");
1531
- return /^name:\s*["']?failproofai["']?\s*$/m.test(manifest);
1535
+ const recorded = readFileSync(hermesLinkRecordPath(pluginPath), "utf8").trim();
1536
+ return recorded === "" ? null : resolve(recorded);
1537
+ } catch {
1538
+ return null;
1539
+ }
1540
+ }
1541
+
1542
+ function writeHermesLinkRecord(pluginPath: string, target: string): void {
1543
+ writeConfigFileAtomic(hermesLinkRecordPath(pluginPath), resolve(target) + "\n", { backup: false, symlinks: "replace" });
1544
+ }
1545
+
1546
+ function removeHermesLinkRecord(pluginPath: string): void {
1547
+ rmSync(hermesLinkRecordPath(pluginPath), { force: true });
1548
+ }
1549
+
1550
+ /**
1551
+ * Whether a link at `pluginPath` pointing at `target` is FailproofAI's.
1552
+ *
1553
+ * A directory name and a manifest `name:` are things any plugin can copy, so
1554
+ * neither proves anything. Ownership is one of two verifiable facts:
1555
+ *
1556
+ * 1. our record: the link target equals what `.failproofai-link` says we
1557
+ * linked (every link this build creates is recorded), or
1558
+ * 2. provenance, for links created before the record existed (the 1.0.9
1559
+ * betas): the target IS this package's `hermes-plugin/`, or it is
1560
+ * `…/node_modules/failproofai/hermes-plugin` inside a directory whose
1561
+ * `package.json` names the package `failproofai`.
1562
+ *
1563
+ * Anything else — including a same-named, same-manifest plugin somewhere
1564
+ * else, or a dangling link with no record — is foreign and never touched.
1565
+ */
1566
+ function isOwnedHermesPluginLink(pluginPath: string, target: string): boolean {
1567
+ const recorded = readHermesLinkRecord(pluginPath);
1568
+ if (recorded && resolve(target) === recorded) return true;
1569
+ if (samePath(target, getHermesPluginSourcePath())) return true;
1570
+ const pkgRoot = dirname(resolve(target));
1571
+ if (basename(resolve(target)) !== HERMES_PLUGIN_SOURCE_DIR) return false;
1572
+ if (basename(pkgRoot) !== "failproofai" || basename(dirname(pkgRoot)) !== "node_modules") return false;
1573
+ try {
1574
+ const pkg = JSON.parse(readFileSync(resolve(pkgRoot, "package.json"), "utf8")) as { name?: unknown };
1575
+ return pkg.name === "failproofai";
1532
1576
  } catch {
1533
1577
  return false;
1534
1578
  }
@@ -1578,7 +1622,7 @@ function hermesPluginState(settingsPath: string): HermesPluginState {
1578
1622
  } catch {
1579
1623
  return { kind: "foreign" };
1580
1624
  }
1581
- if (!isFailproofaiHermesPluginSource(target)) return { kind: "foreign" };
1625
+ if (!isOwnedHermesPluginLink(pluginPath, target)) return { kind: "foreign" };
1582
1626
  return {
1583
1627
  kind: "link",
1584
1628
  target,
@@ -1636,7 +1680,18 @@ export function installHermesPlugin(
1636
1680
  `Move it aside or install FailproofAI under a different Hermes profile.`,
1637
1681
  );
1638
1682
  }
1639
- if (existing.kind === "link" && existing.current) return "unchanged";
1683
+ if (existing.kind === "link" && existing.current) {
1684
+ // A link from a 1.0.9 beta was proven ours by provenance; record it now so
1685
+ // ownership no longer depends on where npm keeps the package.
1686
+ if (readHermesLinkRecord(destination) !== resolve(existing.target)) {
1687
+ try {
1688
+ writeHermesLinkRecord(destination, existing.target);
1689
+ } catch {
1690
+ // Provenance still proves it on the next run; not worth failing over.
1691
+ }
1692
+ }
1693
+ return "unchanged";
1694
+ }
1640
1695
 
1641
1696
  mkdirSync(dirname(destination), { recursive: true });
1642
1697
  const suffix = `${process.pid}-${Date.now()}`;
@@ -1673,6 +1728,7 @@ export function installHermesPlugin(
1673
1728
  if (linked && (existing.kind === "absent" || existing.kind === "link")) {
1674
1729
  try {
1675
1730
  renameSync(temporary, destination);
1731
+ writeHermesLinkRecord(destination, source);
1676
1732
  return "linked";
1677
1733
  } catch (err) {
1678
1734
  // Windows cannot always rename a junction over another junction; the
@@ -1695,6 +1751,8 @@ export function installHermesPlugin(
1695
1751
  renameSync(temporary, destination);
1696
1752
  // fs.rm never follows a symlink, so a backed-up link removes only itself.
1697
1753
  if (movedExisting) rmSync(backup, { recursive: true, force: true });
1754
+ if (linked) writeHermesLinkRecord(destination, source);
1755
+ else removeHermesLinkRecord(destination);
1698
1756
  } catch (err) {
1699
1757
  rmSync(temporary, { recursive: true, force: true });
1700
1758
  if (movedExisting && !pathPresent(destination) && pathPresent(backup)) {
@@ -1711,6 +1769,7 @@ function removeManagedHermesPlugin(settingsPath: string): boolean {
1711
1769
  if (state.kind === "link") {
1712
1770
  // Only the link goes; the package directory it points at is npm's.
1713
1771
  unlinkSync(pluginPath);
1772
+ removeHermesLinkRecord(pluginPath);
1714
1773
  return true;
1715
1774
  }
1716
1775
  // The marker is the ownership boundary. Remove even an incomplete managed
@@ -1851,6 +1910,9 @@ export async function migrateHermesProfiles(opts: {
1851
1910
  const results: HermesProfileMigration[] = [];
1852
1911
  let daemonOk: boolean | undefined;
1853
1912
  for (const profile of listHermesProfiles()) {
1913
+ // One profile's surprise (a file removed mid-run, a permission change) is
1914
+ // that profile's failed line — never the end of the report for the rest.
1915
+ try {
1854
1916
  if (!existsSync(profile.home)) continue;
1855
1917
  const settingsPath = resolve(profile.home, "config.yaml");
1856
1918
  const pluginPath = hermesPluginPathForSettings(settingsPath);
@@ -1888,6 +1950,15 @@ export async function migrateHermesProfiles(opts: {
1888
1950
  continue;
1889
1951
  }
1890
1952
  if (plugin.kind === "link" && plugin.current && plugin.complete && config.pluginEnabled && !legacy) {
1953
+ // A link a 1.0.9 beta created was proven ours by provenance; record it
1954
+ // so ownership stops depending on where npm keeps the package.
1955
+ if (readHermesLinkRecord(pluginPath) !== resolve(plugin.target)) {
1956
+ try {
1957
+ writeHermesLinkRecord(pluginPath, plugin.target);
1958
+ } catch {
1959
+ // Provenance still proves it on the next run.
1960
+ }
1961
+ }
1891
1962
  results.push({ ...base, status: "current", detail: "already linked", legacyShellHooksRemain: false });
1892
1963
  continue;
1893
1964
  }
@@ -1902,19 +1973,6 @@ export async function migrateHermesProfiles(opts: {
1902
1973
  });
1903
1974
  continue;
1904
1975
  }
1905
- if (existsSync(settingsPath)) {
1906
- const errors = parseDocument(readFileSync(settingsPath, "utf8")).errors;
1907
- if (errors.length > 0) {
1908
- results.push({
1909
- ...base,
1910
- status: "failed",
1911
- detail: `${settingsPath} does not parse as YAML; left untouched`,
1912
- legacyShellHooksRemain: legacy,
1913
- });
1914
- continue;
1915
- }
1916
- }
1917
-
1918
1976
  if (daemonOk === undefined) daemonOk = await opts.daemonSupportsPolicyEvaluation();
1919
1977
  if (!daemonOk) {
1920
1978
  results.push({
@@ -1935,6 +1993,7 @@ export async function migrateHermesProfiles(opts: {
1935
1993
  const doc = readYamlDoc(settingsPath);
1936
1994
  enableHermesPluginInDoc(doc);
1937
1995
  writeYamlDoc(settingsPath, doc);
1996
+ const reenabledOnly = !legacy && plugin.kind === "link" && plugin.current && mode === "unchanged";
1938
1997
  const from = legacy
1939
1998
  ? "shell hooks"
1940
1999
  : plugin.kind === "copy"
@@ -1943,7 +2002,12 @@ export async function migrateHermesProfiles(opts: {
1943
2002
  ? "old plugin link"
1944
2003
  : "enabled but missing plugin";
1945
2004
  const to = mode === "copied" ? "plugin copy (symlink not possible here)" : "linked plugin";
1946
- results.push({ ...base, status: "migrated", detail: `${from} → ${to}`, legacyShellHooksRemain: false });
2005
+ const detail = reenabledOnly
2006
+ ? config.pluginDisabled
2007
+ ? "plugin re-enabled (was listed in plugins.disabled)"
2008
+ : "plugin enabled in config.yaml"
2009
+ : `${from} → ${to}`;
2010
+ results.push({ ...base, status: "migrated", detail, legacyShellHooksRemain: false });
1947
2011
  } catch (err) {
1948
2012
  results.push({
1949
2013
  ...base,
@@ -1952,6 +2016,15 @@ export async function migrateHermesProfiles(opts: {
1952
2016
  legacyShellHooksRemain: hermesConfigState(settingsPath).legacyShellHookPresent,
1953
2017
  });
1954
2018
  }
2019
+ } catch (err) {
2020
+ results.push({
2021
+ name: profile.name,
2022
+ home: profile.home,
2023
+ status: "failed",
2024
+ detail: `could not inspect this profile (${err instanceof Error ? err.message : String(err)}); left untouched`,
2025
+ legacyShellHooksRemain: false,
2026
+ });
2027
+ }
1955
2028
  }
1956
2029
  return results;
1957
2030
  }
@@ -1974,6 +2047,8 @@ export interface HermesProfileHealth {
1974
2047
  cronUnchecked: boolean;
1975
2048
  /** config.yaml exists but does not parse; failproofai will not touch it. */
1976
2049
  configUnreadable: boolean;
2050
+ /** Another plugin (not provably FailproofAI's) occupies plugins/failproofai. */
2051
+ pluginForeign: boolean;
1977
2052
  healthy: boolean;
1978
2053
  }
1979
2054
 
@@ -1996,6 +2071,7 @@ export function hermesProfileHealth(): HermesProfileHealth[] {
1996
2071
  legacyShellHookPresent: config.legacyShellHookPresent,
1997
2072
  cronUnchecked: config.legacyShellHookPresent && !pluginWorks,
1998
2073
  configUnreadable: config.unreadable === true,
2074
+ pluginForeign: plugin.kind === "foreign",
1999
2075
  healthy: pluginWorks && !config.legacyShellHookPresent && config.unreadable !== true,
2000
2076
  };
2001
2077
  });
@@ -2007,6 +2083,12 @@ export function hermesProfileStatusRows(): Array<[string, string]> {
2007
2083
  .filter((profile) => existsSync(profile.home))
2008
2084
  .map((profile) => {
2009
2085
  const label = "hermes/" + profile.name;
2086
+ if (profile.pluginForeign) {
2087
+ return [
2088
+ label,
2089
+ `UNHEALTHY — another plugin occupies ${resolve(profile.home, "plugins", "failproofai")}; failproofai will not replace it. Move it aside, then run update`,
2090
+ ];
2091
+ }
2010
2092
  if (profile.configUnreadable) {
2011
2093
  return [label, `UNHEALTHY — ${profile.settingsPath} does not parse; failproofai leaves it untouched until it is fixed`];
2012
2094
  }
@@ -29,12 +29,14 @@
29
29
  import {
30
30
  chmodSync,
31
31
  closeSync,
32
+ constants as fsConstants,
32
33
  copyFileSync,
33
34
  existsSync,
34
35
  fsyncSync,
35
36
  lstatSync,
36
37
  mkdirSync,
37
38
  openSync,
39
+ readlinkSync,
38
40
  realpathSync,
39
41
  renameSync,
40
42
  rmSync,
@@ -52,26 +54,97 @@ export function configBackupPath(path: string): string {
52
54
  /** Hooks for tests to simulate an interruption at the one step that matters. */
53
55
  export interface AtomicWriteDeps {
54
56
  rename?: (from: string, to: string) => void;
57
+ /** Keep `<name>.failproofai-backup` of the previous version (default true). */
58
+ backup?: boolean;
59
+ /**
60
+ * What to do when the path is a symlink. `follow` (default) writes through to
61
+ * the target — right for a user's config, which is read and parsed before it
62
+ * is written and may live in a dotfiles checkout. `replace` swaps the link
63
+ * itself for the new file and never touches what it pointed at — right for a
64
+ * file failproofai generates and fully owns (a plugin shim, an ownership
65
+ * record), which is written without being read, so a planted link must not
66
+ * steer the write into another file.
67
+ */
68
+ symlinks?: "follow" | "replace";
55
69
  }
56
70
 
57
- /** A symlinked config is written through to what it points at. */
71
+ /** A config that is a symlink to nothing: writing would either replace the link or create a file somewhere unknown. */
72
+ export class DanglingConfigSymlinkError extends Error {
73
+ constructor(readonly path: string, readonly target: string) {
74
+ super(
75
+ `Refusing to write ${path}: it is a symlink to ${target}, which does not exist. ` +
76
+ `Fix or remove the link, then retry — failproofai will not replace it with a regular file.`,
77
+ );
78
+ this.name = "DanglingConfigSymlinkError";
79
+ }
80
+ }
81
+
82
+ /**
83
+ * A symlinked config is written through to what it points at, so a dotfiles
84
+ * checkout keeps its link. A link whose target does not exist is refused: the
85
+ * rename would replace the link with a regular file (silently detaching the
86
+ * dotfiles), and creating the target instead would write wherever the link
87
+ * says — a path a cloned repository can choose for a project-scoped config.
88
+ */
58
89
  function resolveWriteTarget(path: string): string {
90
+ let isLink = false;
91
+ try {
92
+ isLink = lstatSync(path).isSymbolicLink();
93
+ } catch {
94
+ return path; // absent: a new file at the path as given
95
+ }
96
+ if (!isLink) return path;
97
+ try {
98
+ return realpathSync(path);
99
+ } catch {
100
+ let target = "(unreadable link)";
101
+ try {
102
+ target = readlinkSync(path);
103
+ } catch {
104
+ // keep the placeholder
105
+ }
106
+ throw new DanglingConfigSymlinkError(path, target);
107
+ }
108
+ }
109
+
110
+ function isSymlink(path: string): boolean {
59
111
  try {
60
- if (lstatSync(path).isSymbolicLink()) return realpathSync(path);
112
+ return lstatSync(path).isSymbolicLink();
61
113
  } catch {
62
- // Absent or unreadable: write to the path as given.
114
+ return false;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Keep the previous version beside the file without ever following a link that
120
+ * sits where the backup goes. `copyFileSync` onto `<name>.failproofai-backup`
121
+ * would write THROUGH a symlink planted there — for a project-scoped config
122
+ * inside a cloned repository, into any file the user can write. So the copy
123
+ * goes to a fresh, exclusively created temp file and is renamed over the backup
124
+ * path: a rename replaces a symlink, it does not follow one.
125
+ */
126
+ function writeBackup(target: string, dir: string): void {
127
+ const backup = `${target}.failproofai-backup`;
128
+ const temporary = join(dir, `.${basename(target)}.failproofai-backup-${process.pid}-${randomBytes(4).toString("hex")}.tmp`);
129
+ try {
130
+ copyFileSync(target, temporary, fsConstants.COPYFILE_EXCL);
131
+ renameSync(temporary, backup);
132
+ } catch (err) {
133
+ rmSync(temporary, { force: true });
134
+ throw err;
63
135
  }
64
- return path;
65
136
  }
66
137
 
67
138
  export function writeConfigFileAtomic(path: string, content: string, deps: AtomicWriteDeps = {}): void {
68
- const target = resolveWriteTarget(path);
139
+ const replacingLink = deps.symlinks === "replace" && isSymlink(path);
140
+ const target = deps.symlinks === "replace" ? path : resolveWriteTarget(path);
69
141
  const dir = dirname(target);
70
142
  mkdirSync(dir, { recursive: true });
71
143
 
72
144
  let mode: number | undefined;
73
145
  try {
74
- mode = statSync(target).mode & 0o777;
146
+ // A link being replaced lends nothing: its target's mode is someone else's.
147
+ mode = replacingLink ? undefined : statSync(target).mode & 0o777;
75
148
  } catch {
76
149
  mode = undefined; // a new file: the process umask decides, as writeFileSync would
77
150
  }
@@ -89,7 +162,7 @@ export function writeConfigFileAtomic(path: string, content: string, deps: Atomi
89
162
  // `open` applies the umask; the live file's own bits are what should survive.
90
163
  if (mode !== undefined) chmodSync(temporary, mode);
91
164
 
92
- if (existsSync(target)) copyFileSync(target, `${target}.failproofai-backup`);
165
+ if (deps.backup !== false && !replacingLink && existsSync(target)) writeBackup(target, dir);
93
166
 
94
167
  (deps.rename ?? renameSync)(temporary, target);
95
168
  } catch (err) {
@@ -87,6 +87,10 @@ export const CODEX_TOOL_MAP: Record<string, string> = {
87
87
  // specific tools (skill_view, cronjob, browser_*, memory, session_search,
88
88
  // clarify, process) pass through unchanged so they still appear in the audit,
89
89
  // just unmatched by builtin policies.
90
+ //
91
+ // Hermes 0.21.x renamed three tools (process -> process_manage, cronjob ->
92
+ // cronjob_manage, todo -> todo_list). The new names map to what the old ones
93
+ // produce, so a policy written for one Hermes version still fires on the other.
90
94
  export const HERMES_TOOL_MAP: Record<string, string> = {
91
95
  terminal: "Bash",
92
96
  bash: "Bash",
@@ -97,6 +101,9 @@ export const HERMES_TOOL_MAP: Record<string, string> = {
97
101
  web_extract: "WebFetch",
98
102
  search_files: "Grep",
99
103
  todo: "TodoWrite",
104
+ todo_list: "TodoWrite",
105
+ process_manage: "process",
106
+ cronjob_manage: "cronjob",
100
107
  };
101
108
 
102
109
  // Hermes tool-INPUT key canonicalization, keyed by the *canonical* tool name
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,13644,e=>{"use strict";var t=e.i(95187);let r=(0,t.createServerReference)("00b0b1e41b15389782e3c2352a31388b82d5d66fc6",t.callServer,void 0,t.findSourceMapURL,"getTelemetryConfig");e.s(["getTelemetryConfig",0,r])},53348,e=>{"use strict";var t=e.i(43476),r=e.i(71645),n=e.i(13644),l=e.i(9969);e.s(["default",0,function({error:e,reset:o}){return(0,r.useEffect)(()=>{(0,n.getTelemetryConfig)().then(t=>{(0,l.setClientTelemetryConfig)(t),(0,l.captureClientEvent)("client_error",{error_message:e.message,error_name:e.name,error_digest:e.digest,boundary:"global"})}).catch(()=>{})},[e]),(0,t.jsx)("html",{children:(0,t.jsx)("body",{children:(0,t.jsx)("main",{style:{minHeight:"100vh",display:"flex",alignItems:"center",justifyContent:"center",background:"#031035",color:"#f8fafc",fontFamily:"system-ui, sans-serif"},children:(0,t.jsxs)("div",{style:{textAlign:"center",padding:"2rem",border:"1px solid rgba(239,68,68,0.4)",borderRadius:"0.5rem",maxWidth:"500px"},children:[(0,t.jsx)("h2",{style:{color:"#ef4444",marginBottom:"0.5rem",fontSize:"1.25rem"},children:"Something went wrong"}),(0,t.jsx)("p",{style:{color:"#94a3b8",marginBottom:"1.5rem"},children:e.message||"An unexpected error occurred."}),(0,t.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"})]})})})})}])},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 o.callServer},createServerReference:function(){return u.createServerReference},findSourceMapURL:function(){return a.findSourceMapURL}};for(var l in n)Object.defineProperty(r,l,{enumerable:!0,get:n[l]});let o=e.r(32120),a=e.r(92245),u=e.r(35326)},28298,(e,t,r)=>{"use strict";e.i(47167),Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"useRouterBFCache",{enumerable:!0,get:function(){return l}});let n=e.r(71645);function l(e,t,r){let[l,o]=(0,n.useState)(()=>({tree:e,cacheNode:t,stateKey:r,next:null}));if(l.tree===e)return l;let a={tree:e,cacheNode:t,stateKey:r,next:null},u=1,i=l,s=a;for(;null!==i&&u<1;){if(i.stateKey===r){s.next=i.next;break}{u++;let e={tree:i.tree,cacheNode:i.cacheNode,stateKey:i.stateKey,next:null};s.next=e,s=e}i=i.next}return o(a),a}("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)},47257,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"ClientPageRoot",{enumerable:!0,get:function(){return s}});let n=e.r(43476),l=e.r(8372),o=e.r(71645),a=e.r(33906),u=e.r(61994),i=e.r(15783);function s({Component:e,serverProvidedParams:t}){let r,d;if(null!==t)r=t.searchParams,d=t.params;else{let e=(0,o.use)(l.LayoutRouterContext);d=null!==e?e.parentParams:{},r=(0,a.urlSearchParamsToParsedUrlQuery)((0,o.use)(u.SearchParamsContext))}let c=(0,i.createClientSearchParams)(r),f=(0,i.createClientParams)(d);return(0,n.jsx)(e,{params:f,searchParams:c})}("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)},92825,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"ClientSegmentRoot",{enumerable:!0,get:function(){return u}});let n=e.r(43476),l=e.r(8372),o=e.r(71645),a=e.r(15783);function u({Component:e,slots:t,serverProvidedParams:r}){let i;if(null!==r)i=r.params;else{let e=(0,o.use)(l.LayoutRouterContext);i=null!==e?e.parentParams:{}}let s=(0,a.createClientParams)(i);return(0,n.jsx)(e,{...t,params:s})}("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)},68017,(e,t,r)=>{"use strict";e.i(47167),Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"HTTPAccessFallbackBoundary",{enumerable:!0,get:function(){return d}});let n=e.r(90809),l=e.r(43476),o=n._(e.r(71645)),a=e.r(90373),u=e.r(54394),i=e.r(8372);class s extends o.default.Component{constructor(e){super(e),this.state={triggeredStatus:void 0,previousPathname:e.pathname}}componentDidCatch(){}static getDerivedStateFromError(e){if((0,u.isHTTPAccessFallbackError)(e))return{triggeredStatus:(0,u.getAccessFallbackHTTPStatus)(e)};throw e}static getDerivedStateFromProps(e,t){return e.pathname!==t.previousPathname&&t.triggeredStatus?{triggeredStatus:void 0,previousPathname:e.pathname}:{triggeredStatus:t.triggeredStatus,previousPathname:e.pathname}}render(){let{notFound:e,forbidden:t,unauthorized:r,children:n}=this.props,{triggeredStatus:o}=this.state,a={[u.HTTPAccessErrorStatus.NOT_FOUND]:e,[u.HTTPAccessErrorStatus.FORBIDDEN]:t,[u.HTTPAccessErrorStatus.UNAUTHORIZED]:r};if(o){let i=o===u.HTTPAccessErrorStatus.NOT_FOUND&&e,s=o===u.HTTPAccessErrorStatus.FORBIDDEN&&t,d=o===u.HTTPAccessErrorStatus.UNAUTHORIZED&&r;return i||s||d?(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)("meta",{name:"robots",content:"noindex"}),!1,a[o]]}):n}return n}}function d({notFound:e,forbidden:t,unauthorized:r,children:n}){let u=(0,a.useUntrackedPathname)(),c=(0,o.useContext)(i.MissingSlotContext);return e||t||r?(0,l.jsx)(s,{pathname:u,notFound:e,forbidden:t,unauthorized:r,missingSlots:c,children:n}):(0,l.jsx)(l.Fragment,{children:n})}("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)},22976,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={InstantValidationBoundaryContext:function(){return o},PlaceValidationBoundaryBelowThisLevel:function(){return a},RenderValidationBoundaryAtThisLevel:function(){return u},SlotMarker:function(){return i}};for(var l in n)Object.defineProperty(r,l,{enumerable:!0,get:n[l]});let o=null,a=null,u=null,i=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)},77694,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={InstantValidationBoundaryContext:function(){return o.InstantValidationBoundaryContext},PlaceValidationBoundaryBelowThisLevel:function(){return o.PlaceValidationBoundaryBelowThisLevel},RenderValidationBoundaryAtThisLevel:function(){return o.RenderValidationBoundaryAtThisLevel},SlotMarker:function(){return o.SlotMarker}};for(var l in n)Object.defineProperty(r,l,{enumerable:!0,get:n[l]});let o=e.r(22976);("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)},39756,(e,t,r)=>{"use strict";e.i(47167),Object.defineProperty(r,"__esModule",{value:!0});var n={LoadingBoundaryProvider:function(){return C},default:function(){return S}};for(var l in n)Object.defineProperty(r,l,{enumerable:!0,get:n[l]});let o=e.r(55682),a=e.r(90809),u=e.r(43476),i=a._(e.r(71645)),s=o._(e.r(74080)),d=e.r(8372),c=e.r(1244),f=e.r(72383),p=e.r(91915),m=e.r(58442),y=e.r(68017);e.r(77694);let b=e.r(70725),h=e.r(28298);e.r(74180);let g=e.r(61994),_=e.r(33906),v=e.r(95871);s.default.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function P(e,t,r){let n=e.getClientRects();if(0===n.length)return 0;let l=1/0;for(let e=0;e<n.length;e++){let t=n[e];t.top<l&&(l=t.top)}return l>=r()&&l<=t?1:2}i.default.Component;let j=function(e){let t=i.default.useRef(null);return(0,i.useLayoutEffect)(()=>{let{focusAndScrollRef:r,cacheNode:n}=e,l=r.forceScroll?r.scrollRef:n.scrollRef;if(null===l||!l.current)return;let o=null,a=r.hashFragment;if(a){var u;if(null===(o="top"===(u=a)?document.body:document.getElementById(u)??document.getElementsByName(u)[0]??null)){l.current=!1,r.onlyHashChange=!1,r.hashFragment=null;return}}else o=t.current;if(null===o)return;let i=!1;(0,p.disableSmoothScrollDuringRouteTransition)(()=>{let e=document.documentElement,t=null,r=null,n=null,u=()=>{var r,l;let o,a;return null===n&&(r=e,l=t,n=!Number.isFinite(a=Number.parseFloat(o=getComputedStyle(r).scrollPaddingTop))||a<0?0:o.endsWith("px")?a:o.endsWith("%")?a/100*l:0),n};(a||(t=e.clientHeight,0!==(r=P(o,t,u))))&&((i=!0,l.current=!1,a)?o.scrollIntoView():1!==r&&(e.scrollTop=0,2===P(o,t,u)&&o.scrollIntoView()))},{dontForceLayout:!0,onlyHashChange:r.onlyHashChange}),i&&(r.onlyHashChange=!1,r.hashFragment=null)},void 0),(0,u.jsx)(i.Fragment,{ref:t,children:e.children})};function x({children:e,cacheNode:t}){let r=(0,i.useContext)(d.GlobalLayoutRouterContext);if(!r)throw Object.defineProperty(Error("invariant global layout router not mounted"),"__NEXT_ERROR_CODE",{value:"E473",enumerable:!1,configurable:!0});return(0,u.jsx)(j,{focusAndScrollRef:r.focusAndScrollRef,cacheNode:t,children:e})}function O({tree:e,segmentPath:t,debugNameContext:r,cacheNode:n,params:l,url:o,isActive:a}){let s,f=(0,i.useContext)(d.GlobalLayoutRouterContext);if((0,i.useContext)(g.NavigationPromisesContext),!f)throw Object.defineProperty(Error("invariant global layout router not mounted"),"__NEXT_ERROR_CODE",{value:"E473",enumerable:!1,configurable:!0});let p=null!==n?n:(0,i.use)(c.unresolvedThenable),m=null!==p.prefetchRsc?p.prefetchRsc:p.rsc,y=(0,i.useDeferredValue)(p.rsc,m);if((0,v.isDeferredRsc)(y)){let e=(0,i.use)(y);null===e&&(0,i.use)(c.unresolvedThenable),s=e}else null===y&&(0,i.use)(c.unresolvedThenable),s=y;let b=s;return(0,u.jsx)(d.LayoutRouterContext.Provider,{value:{parentTree:e,parentCacheNode:p,parentSegmentPath:t,parentParams:l,parentLoadingData:null,debugNameContext:r,url:o,isActive:a},children:b})}function C({loading:e,children:t}){let r=(0,i.use)(d.LayoutRouterContext);return null===r?t:(0,u.jsx)(d.LayoutRouterContext.Provider,{value:{parentTree:r.parentTree,parentCacheNode:r.parentCacheNode,parentSegmentPath:r.parentSegmentPath,parentParams:r.parentParams,parentLoadingData:e,debugNameContext:r.debugNameContext,url:r.url,isActive:r.isActive},children:t})}function R({name:e,loading:t,children:r}){if(null!==t){let n=t[0],l=t[1],o=t[2];return(0,u.jsx)(i.Suspense,{name:e,fallback:(0,u.jsxs)(u.Fragment,{children:[l,o,n]}),children:r})}return(0,u.jsx)(u.Fragment,{children:r})}function S({parallelRouterKey:e,error:t,errorStyles:r,errorScripts:n,templateStyles:l,templateScripts:o,template:a,notFound:s,forbidden:p,unauthorized:g,segmentViewBoundaries:v}){let P=(0,i.useContext)(d.LayoutRouterContext);if(!P)throw Object.defineProperty(Error("invariant expected layout router to be mounted"),"__NEXT_ERROR_CODE",{value:"E56",enumerable:!1,configurable:!0});let{parentTree:j,parentCacheNode:C,parentSegmentPath:T,parentParams:M,parentLoadingData:E,url:N,isActive:F,debugNameContext:A}=P,B=j[0],L=null===T?[e]:T.concat([B,e]),D=j[1][e],w=C.slots;(void 0===D||null===w)&&(0,i.use)(c.unresolvedThenable);let H=D[0],k=w[e]??null,U=(0,b.createRouterCacheKey)(H,!0),I=(0,h.useRouterBFCache)(D,k,U),V=[];do{let e=I.tree,i=I.cacheNode,c=I.stateKey,b=e[0],h=M;if(Array.isArray(b)){let e=b[0],t=b[1],r=b[2],n=(0,_.getParamValueFromCacheKey)(t,r);null!==n&&(h={...M,[e]:n})}let v=function(e){if("/"===e)return"/";if("string"==typeof e)if("(__SLOT__)"===e)return;else return e+"/";return e[1]+"/"}(b),P=v??A,j=void 0===v?void 0:A,C=(0,u.jsxs)(x,{cacheNode:i,children:[(0,u.jsx)(f.ErrorBoundary,{errorComponent:t,errorStyles:r,errorScripts:n,children:(0,u.jsx)(R,{name:j,loading:E,children:(0,u.jsx)(y.HTTPAccessFallbackBoundary,{notFound:s,forbidden:p,unauthorized:g,children:(0,u.jsxs)(m.RedirectBoundary,{children:[(0,u.jsx)(O,{url:N,tree:e,params:h,cacheNode:i,segmentPath:L,debugNameContext:P,isActive:F&&c===U}),null]})})})}),null]}),S=(0,u.jsxs)(d.TemplateContext.Provider,{value:C,children:[l,o,a]},c);V.push(S),I=I.next}while(null!==I)return 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)},37457,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"default",{enumerable:!0,get:function(){return u}});let n=e.r(90809),l=e.r(43476),o=n._(e.r(71645)),a=e.r(8372);function u(){let e=(0,o.useContext)(a.TemplateContext);return(0,l.jsx)(l.Fragment,{children:e})}("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)},6831,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createRenderParamsFromClient",{enumerable:!0,get:function(){return l}});let n=new WeakMap;function l(e){let t=n.get(e);if(t)return t;let r=Promise.resolve(e);return n.set(e,r),r}("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)},14193,(e,t,r)=>{"use strict";e.i(47167),Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createRenderParamsFromClient",{enumerable:!0,get:function(){return n}});let n=e.r(6831).createRenderParamsFromClient;("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)},93504,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createRenderSearchParamsFromClient",{enumerable:!0,get:function(){return l}});let n=new WeakMap;function l(e){let t=n.get(e);if(t)return t;let r=Promise.resolve(e);return n.set(e,r),r}("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)},66996,(e,t,r)=>{"use strict";e.i(47167),Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createRenderSearchParamsFromClient",{enumerable:!0,get:function(){return n}});let n=e.r(93504).createRenderSearchParamsFromClient;("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)},15783,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={createClientParams:function(){return o.createRenderParamsFromClient},createClientSearchParams:function(){return a.createRenderSearchParamsFromClient}};for(var l in n)Object.defineProperty(r,l,{enumerable:!0,get:n[l]});let o=e.r(14193),a=e.r(66996);("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)},27201,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"IconMark",{enumerable:!0,get:function(){return l}});let n=e.r(43476),l=()=>"u">typeof window?null:(0,n.jsx)("meta",{name:"«nxt-icon»"})},91915,(e,t,r)=>{"use strict";function n(e,t={}){if(t.onlyHashChange)return void e();let r=document.documentElement;if("smooth"!==r.dataset.scrollBehavior)return void e();let l=r.style.scrollBehavior;r.style.scrollBehavior="auto",t.dontForceLayout||r.getClientRects(),e(),r.style.scrollBehavior=l}e.i(47167),Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"disableSmoothScrollDuringRouteTransition",{enumerable:!0,get:function(){return n}})}]);
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,13644,e=>{"use strict";var t=e.i(95187);let r=(0,t.createServerReference)("00b0b1e41b15389782e3c2352a31388b82d5d66fc6",t.callServer,void 0,t.findSourceMapURL,"getTelemetryConfig");e.s(["getTelemetryConfig",0,r])},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)},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)}])},63780,e=>{"use strict";var t=e.i(43476),r=e.i(22016),n=e.i(18566),o=e.i(66794),a=e.i(71645),i=e.i(56420);let s={name:"git-branch",size:24,node:[["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"}]]};s.node;let l=(0,i.default)(s);var u=e.i(16327);let c={name:"star",size:24,node:[["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"}]]};c.node;let d=(0,i.default)(c),f={name:"book-open",size:24,node:[["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"}]]};f.node;let h=(0,i.default)(f),p={name:"message-circle",size:24,node:[["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"}]]};p.node;let m=(0,i.default)(p),g={name:"messages-square",size:24,node:[["path",{d:"M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z",key:"1n2ejm"}],["path",{d:"M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1",key:"1qfcsi"}]]};g.node;let b=(0,i.default)(g),v={name:"message-square-warning",size:24,node:[["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"}]]};v.node;let y=(0,i.default)(v);var x=e.i(67881);let w="failproofai@exosphere.host",j=[{label:"Star us on GitHub",icon:d,href:"https://github.com/failproofai/failproofai",color:"#f5c842",bg:"rgba(245,200,66,0.08)"},{label:"Documentation",icon:h,href:"https://docs.befailproof.ai/introduction",color:"#60a5fa",bg:"rgba(96,165,250,0.08)"},{label:"Join our Discord",icon:m,href:"https://discord.befailproof.ai/",color:"#5865f2",bg:"rgba(88,101,242,0.08)"},{label:"Join r/failproofai",icon:b,href:"https://www.reddit.com/r/failproofai/",color:"#ff4500",bg:"rgba(255,69,0,0.08)"},{label:"Feedback & Issues",icon:y,href:"https://github.com/FailproofAI/failproofai/issues/new/choose",color:"#34d399",bg:"rgba(52,211,153,0.08)"}],k=()=>{let[e,r]=(0,a.useState)(!1),n=(0,a.useCallback)(()=>r(!1),[]),o=(0,a.useCallback)(e=>{"Escape"===e.key&&r(!1)},[]);return(0,t.jsxs)("div",{className:"relative",onKeyDown:o,children:[e&&(0,t.jsx)("div",{className:"fixed inset-0 z-40",onClick:n,"aria-hidden":"true"}),(0,t.jsxs)(x.Button,{type:"button",variant:"ghost",size:"sm",onClick:()=>r(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)(l,{className:"h-4 w-4"}),(0,t.jsx)("span",{className:"hidden sm:inline text-xs whitespace-nowrap",children:"Reach Us"}),(0,t.jsx)(u.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:j.map(({label:e,icon:r,href:o,color:a,bg:i})=>(0,t.jsxs)("a",{href:o,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:n,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:${w}`,className:"transition-colors",style:{color:"#e879f9"},onMouseEnter:e=>e.currentTarget.style.opacity="0.75",onMouseLeave:e=>e.currentTarget.style.opacity="1",children:w})]})})]})]})},N={name:"refresh-cw",size:24,node:[["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"}]]};N.node;let S=(0,i.default)(N);var C=e.i(47163),E=e.i(85881);let _=[{label:"Off",value:0},{label:"5s",value:5},{label:"10s",value:10},{label:"30s",value:30}];function P({className:e}){let r=(0,n.useRouter)(),[o,i]=(0,a.useTransition)(),{intervalSec:s,setIntervalSec:l}=(0,E.useAutoRefresh)(),u=(0,a.useCallback)(()=>{i(()=>r.refresh())},[r]);(0,a.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,C.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,C.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)(S,{className:(0,C.cn)("w-3.5 h-3.5",o&&"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:_.map(e=>(0,t.jsx)("button",{onClick:()=>l(e.value),"aria-pressed":s===e.value,className:(0,C.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 T=e.i(12344);let R=[{href:"/projects",label:"projects"},{href:"/policies",label:"policies"},{href:"/audit",label:"audit"}];e.s(["Navbar",0,({disabledPages:e=[]})=>{let a=(0,n.usePathname)(),{capture:i}=(0,T.usePostHog)(),s=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:"/logo.svg",alt:"failproof_ai",style:{height:18,display:"block",flexShrink:0}})}),(0,t.jsx)("nav",{className:"tabs",style:{border:"none",padding:0,gap:0},children:R.filter(({href:t})=>{let r=t.slice(1);return!e.includes(r)}).map(({href:e,label:n})=>{let o="/projects"===e?"/projects"===a||a.startsWith("/project/"):a.startsWith(e);return(0,t.jsx)(r.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:n},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.9-beta.2"]}),s&&(0,t.jsx)("span",{className:"h-brand-sep","aria-hidden":"true",children:"·"}),s&&(0,t.jsx)("span",{className:"h-brand-section",children:s})]}),(0,t.jsxs)("div",{className:"h-actions",children:[(0,t.jsx)(P,{}),(0,t.jsx)("span",{style:{width:1,height:18,background:"var(--line)",margin:"0 6px"}}),!e.includes("settings")&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.default,{href:"/settings",className:`h-icon-btn${a.startsWith("/settings")?" is-active":""}`,"aria-label":"settings","aria-current":a.startsWith("/settings")?"page":void 0,title:"settings",children:(0,t.jsx)(o.Settings,{className:"w-3.5 h-3.5",strokeWidth:1.75,"aria-hidden":"true"})}),(0,t.jsx)("span",{style:{width:1,height:18,background:"var(--line)",margin:"0 6px"}})]}),(0,t.jsx)(k,{})]})]})}],63780)},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])},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}])},12344,e=>{"use strict";var t=e.i(43476),r=e.i(71645),n=e.i(18566),o=e.i(13644),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}])},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)},5014,e=>{"use strict";var t=e.i(71645);let r=(...e)=>e.filter((e,t,r)=>!!e&&""!==e.trim()&&r.indexOf(e)===t).join(" ").trim(),n={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"},o=(0,t.createContext)({}),a=(0,t.forwardRef)(({color:e,size:a,width:i,height:s,strokeWidth:l,absoluteStrokeWidth:u,nonScalingStroke:c,className:d="",children:f,iconNode:h=[],icon:p={node:h,aliases:[],size:24},...m},g)=>{let{size:b=24,strokeWidth:v=2,absoluteStrokeWidth:y=!1,nonScalingStroke:x=!1,color:w="currentColor",className:j=""}=(0,t.useContext)(o)??{},k=!!f||(e=>{for(let t in e)if(t.startsWith("aria-")||"role"===t||"title"===t)return!0;return!1})(m),[N,S,C=[]]=function(e,t={}){return function(e,t={}){let o=t.attributeNames??{},a=e=>o[e]??e,i=e.size??e.width??n.width,s=e.size??e.height??n.height,l=e.aliases?.filter(e=>"string"==typeof e&&""!==e.trim()).map(e=>`lucide-${e}`)??[],u=[...e.name?[`lucide-${e.name}`]:[],...l],c=t.className?.split(" ").filter(Boolean)??[],d=!1===t.includeDefaultClasses?r(...c):r("lucide",...u,...c),f=t.absoluteStrokeWidth?Number(t.strokeWidth??n["stroke-width"])*Number(e.size??e.width??n.width)/Number(t.size??t.width??n.width):t.strokeWidth??n["stroke-width"];return["svg",{...Object.entries(n).reduce((e,[t,r])=>(e[a(t)]=r,e),{}),..."color"in t&&t.color&&{[a("stroke")]:t.color},..."size"in t&&null!=t.size&&{[a("width")]:t.size,[a("height")]:t.size},..."width"in t&&null!=t.width&&{[a("width")]:t.width},..."height"in t&&null!=t.height&&{[a("height")]:t.height},[a("stroke-width")]:f,...d&&{[a("class")]:d},[a("viewBox")]:`0 0 ${i} ${s}`,...!1===t.hasA11yProp?{[a("aria-hidden")]:"true"}:{},..."attributes"in t&&t.attributes},e.node.map(e=>{let[r,n,o]=e,i=t.nonScalingStroke?{[a("vector-effect")]:"non-scaling-stroke",...n}:n;return o?[r,i,o]:[r,i]})]}(e,{...t,attributeNames:{...t.attributeNames,class:"className","stroke-width":"strokeWidth","stroke-linecap":"strokeLinecap","stroke-linejoin":"strokeLinejoin","vector-effect":"vectorEffect"}})}(p,{color:e??w,width:i??a??b,height:s??a??b,strokeWidth:l??v,absoluteStrokeWidth:u??y,nonScalingStroke:c??x,className:r(j,d),hasA11yProp:k,attributes:m});return(0,t.createElement)(N,{ref:g,...S},[...C.map(([e,r])=>(0,t.createElement)(e,r)),...Array.isArray(f)?f:[f]])});e.s(["default",0,a],5014)},56420,e=>{"use strict";var t=e.i(71645),r=e.i(5014);e.s(["default",0,function(e,n=[],o=[]){let a,i="string"==typeof e?function(e,t,r=[]){if(null==t)throw Error("[lucide]: iconNode is required when icon name is used");return{name:e?.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),size:24,node:t,...r.length>0?{aliases:r}:{}}}(e,n,o):e,s=(0,t.forwardRef)(({className:e,...n},o)=>(0,t.createElement)(r.default,{ref:o,icon:i,className:e,...n}));return i.name&&(s.displayName=(a=(e=>{let t="",r=!1;for(let n of e){if("-"===n||"_"===n||n<=" "){r=t.length>0;continue}0===t.length?t+=n.toLowerCase():t+=r?n.toUpperCase():n,r=!1}return t})(i.name)).charAt(0).toUpperCase()+a.slice(1)),s}],56420)},16327,e=>{"use strict";var t=e.i(56420);let r={name:"chevron-down",size:24,node:[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]};r.node;let n=(0,t.default)(r);e.s(["ChevronDown",0,n],16327)},66794,e=>{"use strict";var t=e.i(56420);let r={name:"settings",size:24,node:[["path",{d:"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915",key:"1i5ecw"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]};r.node;let n=(0,t.default)(r);e.s(["Settings",0,n],66794)},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)},22016,(e,t,r)=>{"use strict";e.i(47167),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),d=e.r(18967),f=e.r(5550),h=e.r(88540),p=e.r(91949),m=e.r(73668),g=e.r(9396);function b(t){var r;let n,o,a,[b,y]=(0,s.useOptimistic)(p.IDLE_LINK_STATUS),x=(0,s.useRef)(null),{href:w,as:j,children:k,prefetch:N=null,passHref:S,replace:C,shallow:E,scroll:_,onClick:P,onMouseEnter:T,onTouchStart:R,legacyBehavior:O=!1,onNavigate:A,transitionTypes:M,ref:L,unstable_dynamicOnHover:z,...$}=t;n=k,O&&("string"==typeof n||"number"==typeof n)&&(n=(0,i.jsx)("a",{children:n}));let U=s.default.useContext(u.AppRouterContext),I=!1!==N,W=!1===N?"none":!0===N?"full":"auto",B="none"!==W?"auto"===W?g.FetchStrategy.PPR:g.FetchStrategy.Full:g.FetchStrategy.PPR,D="string"==typeof(r=j||w)?r:(0,l.formatUrl)(r);if(O){if(n?.$$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});o=s.default.Children.only(n)}let F=O?o&&"object"==typeof o&&o.ref:L,H,q=s.default.useCallback(e=>(null!==U&&(x.current=(0,p.mountLinkInstance)(e,D,U,B,I,y,H)),()=>{x.current&&((0,p.unmountLinkForCurrentNavigation)(x.current),x.current=null),(0,p.unmountPrefetchableInstance)(e)}),[I,D,U,B,y,H]),K={ref:(0,c.useMergedRef)(q,F),onClick(t){O||"function"!=typeof P||P(t),O&&o.props&&"function"==typeof o.props.onClick&&o.props.onClick(t),!U||t.defaultPrevented||function(t,r,n,o,a,i,l,u="none"){if("u">typeof window){let c,{nodeName:d}=t.currentTarget;if("A"===d.toUpperCase()&&((c=t.currentTarget.getAttribute("target"))&&"_self"!==c||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?h.ScrollBehavior.NoScroll:h.ScrollBehavior.Default,n.current,l,u)})}}(t,D,x,C,_,A,M,W)},onMouseEnter(e){O||"function"!=typeof T||T(e),O&&o.props&&"function"==typeof o.props.onMouseEnter&&o.props.onMouseEnter(e),U&&I&&(0,p.onNavigationIntent)(e.currentTarget,!0===z)},onTouchStart:function(e){O||"function"!=typeof R||R(e),O&&o.props&&"function"==typeof o.props.onTouchStart&&o.props.onTouchStart(e),U&&I&&(0,p.onNavigationIntent)(e.currentTarget,!0===z)}};return(0,d.isAbsoluteUrl)(D)?K.href=D:O&&!S&&("a"!==o.type||"href"in o.props)||(K.href=(0,f.addBasePath)(D)),a=O?s.default.cloneElement(o,K):(0,i.jsx)("a",{...$,...K,children:n}),(0,i.jsx)(v.Provider,{value:b,children:a})}let v=(0,s.createContext)(p.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)},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)},18967,(e,t,r)=>{"use strict";e.i(47167),Object.defineProperty(r,"__esModule",{value:!0});var n={DecodeError:function(){return b},MiddlewareNotFoundError:function(){return w},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 d},getLocationOrigin:function(){return u},getURL:function(){return c},isAbsoluteUrl:function(){return l},isResSent:function(){return f},loadGetInitialProps:function(){return p},normalizeRepeatedSlashes:function(){return h},stringifyError:function(){return j}};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=>{let t=e.charCodeAt(0);return!!(t>=65&&t<=90||t>=97&&t<=122)&&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 d(e){return"string"==typeof e?e:e.displayName||e.name||"Unknown"}function f(e){return e.finished||e.headersSent}function h(e){let t=e.split("?");return t[0].replace(/\\/g,"/").replace(/\/\/+/g,"/")+(t[1]?`?${t.slice(1).join("?")}`:"")}async function p(e,t){let r=t.res||t.ctx&&t.ctx.res;if(!e.getInitialProps)return t.ctx&&t.Component?{pageProps:await p(t.Component,t.ctx)}:{};let n=await e.getInitialProps(t);if(r&&f(r))return n;if(!n)throw Object.defineProperty(Error(`"${d(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 w extends Error{constructor(){super(),this.code="ENOENT",this.message="Cannot find the middleware module"}}function j(e){return JSON.stringify({message:e.message,stack:e.stack})}},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}}},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}},95057,(e,t,r)=>{"use strict";e.i(47167),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)}},18566,(e,t,r)=>{t.exports=e.r(76562)}]);