@pyric/cli 0.1.0-alpha.20 → 0.1.0-alpha.22

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 (502) hide show
  1. package/README.md +64 -89
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts +238 -1
  3. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  4. package/dist/assurance/.generated/conformance-verdicts.js +238 -1
  5. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  6. package/dist/bridge/client/dispatch.d.ts +25 -19
  7. package/dist/bridge/client/dispatch.d.ts.map +1 -1
  8. package/dist/bridge/client/dispatch.js +41 -48
  9. package/dist/bridge/client/dispatch.js.map +1 -1
  10. package/dist/bridge/client/tool-family-factories.d.ts +26 -0
  11. package/dist/bridge/client/tool-family-factories.d.ts.map +1 -0
  12. package/dist/bridge/client/tool-family-factories.js +10 -0
  13. package/dist/bridge/client/tool-family-factories.js.map +1 -0
  14. package/dist/bridge/server/mcp-contract.d.ts +7 -6
  15. package/dist/bridge/server/mcp-contract.d.ts.map +1 -1
  16. package/dist/bridge/server/mcp-contract.js +9 -48
  17. package/dist/bridge/server/mcp-contract.js.map +1 -1
  18. package/dist/bridge/server/peer.d.ts +11 -1
  19. package/dist/bridge/server/peer.d.ts.map +1 -1
  20. package/dist/bridge/server/peer.js +22 -1
  21. package/dist/bridge/server/peer.js.map +1 -1
  22. package/dist/bridge/server/tool-family-factories.d.ts +30 -0
  23. package/dist/bridge/server/tool-family-factories.d.ts.map +1 -0
  24. package/dist/bridge/server/tool-family-factories.js +22 -0
  25. package/dist/bridge/server/tool-family-factories.js.map +1 -0
  26. package/dist/bridge/server/tool-metadata.d.ts +17 -18
  27. package/dist/bridge/server/tool-metadata.d.ts.map +1 -1
  28. package/dist/bridge/server/tool-metadata.js +24 -59
  29. package/dist/bridge/server/tool-metadata.js.map +1 -1
  30. package/dist/bridge/tool-families.d.ts +48 -0
  31. package/dist/bridge/tool-families.d.ts.map +1 -0
  32. package/dist/bridge/tool-families.generated.d.ts +32 -0
  33. package/dist/bridge/tool-families.generated.d.ts.map +1 -0
  34. package/dist/bridge/tool-families.generated.js +15 -0
  35. package/dist/bridge/tool-families.generated.js.map +1 -0
  36. package/dist/bridge/tool-families.js +51 -0
  37. package/dist/bridge/tool-families.js.map +1 -0
  38. package/dist/bridge/tool-family-records/conformance.d.ts +7 -0
  39. package/dist/bridge/tool-family-records/conformance.d.ts.map +1 -0
  40. package/dist/bridge/tool-family-records/conformance.js +6 -0
  41. package/dist/bridge/tool-family-records/conformance.js.map +1 -0
  42. package/dist/bridge/tool-family-records/firestore-data.d.ts +7 -0
  43. package/dist/bridge/tool-family-records/firestore-data.d.ts.map +1 -0
  44. package/dist/bridge/tool-family-records/firestore-data.js +15 -0
  45. package/dist/bridge/tool-family-records/firestore-data.js.map +1 -0
  46. package/dist/bridge/tool-family-records/firestore-inspect.d.ts +7 -0
  47. package/dist/bridge/tool-family-records/firestore-inspect.d.ts.map +1 -0
  48. package/dist/bridge/tool-family-records/firestore-inspect.js +6 -0
  49. package/dist/bridge/tool-family-records/firestore-inspect.js.map +1 -0
  50. package/dist/bridge/tool-family-records/firestore-rules.d.ts +7 -0
  51. package/dist/bridge/tool-family-records/firestore-rules.d.ts.map +1 -0
  52. package/dist/bridge/tool-family-records/firestore-rules.js +15 -0
  53. package/dist/bridge/tool-family-records/firestore-rules.js.map +1 -0
  54. package/dist/bridge/tool-family-records/firestore-simulator.d.ts +7 -0
  55. package/dist/bridge/tool-family-records/firestore-simulator.d.ts.map +1 -0
  56. package/dist/bridge/tool-family-records/firestore-simulator.js +16 -0
  57. package/dist/bridge/tool-family-records/firestore-simulator.js.map +1 -0
  58. package/dist/bridge/tool-family-records/rtdb-inspection.d.ts +7 -0
  59. package/dist/bridge/tool-family-records/rtdb-inspection.d.ts.map +1 -0
  60. package/dist/bridge/tool-family-records/rtdb-inspection.js +6 -0
  61. package/dist/bridge/tool-family-records/rtdb-inspection.js.map +1 -0
  62. package/dist/bundler/externals.d.ts +37 -0
  63. package/dist/bundler/externals.d.ts.map +1 -0
  64. package/dist/bundler/externals.js +52 -0
  65. package/dist/bundler/externals.js.map +1 -0
  66. package/dist/bundler/index.d.ts +17 -0
  67. package/dist/bundler/index.d.ts.map +1 -0
  68. package/dist/bundler/index.js +17 -0
  69. package/dist/bundler/index.js.map +1 -0
  70. package/dist/cli/inlined-sdk-scanner.d.ts +6 -0
  71. package/dist/cli/inlined-sdk-scanner.d.ts.map +1 -0
  72. package/dist/cli/inlined-sdk-scanner.js +82 -0
  73. package/dist/cli/inlined-sdk-scanner.js.map +1 -0
  74. package/dist/cli/sandbox-interlock.d.ts +97 -0
  75. package/dist/cli/sandbox-interlock.d.ts.map +1 -0
  76. package/dist/cli/sandbox-interlock.js +112 -0
  77. package/dist/cli/sandbox-interlock.js.map +1 -0
  78. package/dist/cli/sandbox-runner.d.ts +20 -12
  79. package/dist/cli/sandbox-runner.d.ts.map +1 -1
  80. package/dist/cli/sandbox-runner.js +24 -21
  81. package/dist/cli/sandbox-runner.js.map +1 -1
  82. package/dist/cli/serve.d.ts +6 -10
  83. package/dist/cli/serve.d.ts.map +1 -1
  84. package/dist/cli/serve.js +57 -77
  85. package/dist/cli/serve.js.map +1 -1
  86. package/dist/cli/unsupported-runtime.d.ts +27 -0
  87. package/dist/cli/unsupported-runtime.d.ts.map +1 -0
  88. package/dist/cli/unsupported-runtime.js +63 -0
  89. package/dist/cli/unsupported-runtime.js.map +1 -0
  90. package/dist/conformance/.generated/can-i-use-browser.d.ts +1 -1
  91. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  92. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  93. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  94. package/dist/conformance/.generated/can-i-use.d.ts +1 -1
  95. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  96. package/dist/conformance/.generated/can-i-use.js +1 -1
  97. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  98. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  99. package/dist/conformance/.generated/conformance-docs.js +1 -1
  100. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  101. package/dist/functions-rtdb/child.d.ts +37 -0
  102. package/dist/functions-rtdb/child.d.ts.map +1 -1
  103. package/dist/functions-rtdb/child.js +90 -21
  104. package/dist/functions-rtdb/child.js.map +1 -1
  105. package/dist/functions-rtdb/development-runtime.d.ts +3 -0
  106. package/dist/functions-rtdb/development-runtime.d.ts.map +1 -1
  107. package/dist/functions-rtdb/development-runtime.js +1 -0
  108. package/dist/functions-rtdb/development-runtime.js.map +1 -1
  109. package/dist/google-endpoints.d.ts +67 -0
  110. package/dist/google-endpoints.d.ts.map +1 -0
  111. package/dist/google-endpoints.js +119 -0
  112. package/dist/google-endpoints.js.map +1 -0
  113. package/dist/next/runtime-env.d.ts.map +1 -1
  114. package/dist/next/runtime-env.js +5 -0
  115. package/dist/next/runtime-env.js.map +1 -1
  116. package/dist/next/with-pyric.d.ts +1 -1
  117. package/dist/next/with-pyric.js +1 -1
  118. package/dist/register/beacon.d.ts +69 -0
  119. package/dist/register/beacon.d.ts.map +1 -0
  120. package/dist/register/beacon.js +199 -0
  121. package/dist/register/beacon.js.map +1 -0
  122. package/dist/register/index.d.ts.map +1 -1
  123. package/dist/register/index.js +65 -6
  124. package/dist/register/index.js.map +1 -1
  125. package/dist/register/net-guard.d.ts +110 -0
  126. package/dist/register/net-guard.d.ts.map +1 -0
  127. package/dist/register/net-guard.js +462 -0
  128. package/dist/register/net-guard.js.map +1 -0
  129. package/dist/serve/ai-diagnostics-relay.d.ts +63 -0
  130. package/dist/serve/ai-diagnostics-relay.d.ts.map +1 -0
  131. package/dist/serve/ai-diagnostics-relay.js +125 -0
  132. package/dist/serve/ai-diagnostics-relay.js.map +1 -0
  133. package/dist/serve/ai-proxy.d.ts +92 -0
  134. package/dist/serve/ai-proxy.d.ts.map +1 -0
  135. package/dist/serve/ai-proxy.js +269 -0
  136. package/dist/serve/ai-proxy.js.map +1 -0
  137. package/dist/serve/ai-status.d.ts +44 -0
  138. package/dist/serve/ai-status.d.ts.map +1 -0
  139. package/dist/serve/ai-status.js +77 -0
  140. package/dist/serve/ai-status.js.map +1 -0
  141. package/dist/serve/ai-terminal-blocks.d.ts +97 -0
  142. package/dist/serve/ai-terminal-blocks.d.ts.map +1 -0
  143. package/dist/serve/ai-terminal-blocks.js +128 -0
  144. package/dist/serve/ai-terminal-blocks.js.map +1 -0
  145. package/dist/serve/ai-terminal-text.d.ts +36 -0
  146. package/dist/serve/ai-terminal-text.d.ts.map +1 -0
  147. package/dist/serve/ai-terminal-text.js +48 -0
  148. package/dist/serve/ai-terminal-text.js.map +1 -0
  149. package/dist/serve/beacon-route.d.ts +53 -0
  150. package/dist/serve/beacon-route.d.ts.map +1 -0
  151. package/dist/serve/beacon-route.js +101 -0
  152. package/dist/serve/beacon-route.js.map +1 -0
  153. package/dist/serve/entries/active-auth-registry.d.ts +16 -0
  154. package/dist/serve/entries/active-auth-registry.d.ts.map +1 -0
  155. package/dist/serve/entries/active-auth-registry.js +48 -0
  156. package/dist/serve/entries/active-auth-registry.js.map +1 -0
  157. package/dist/serve/entries/active-auth.d.ts +18 -0
  158. package/dist/serve/entries/active-auth.d.ts.map +1 -0
  159. package/dist/serve/entries/active-auth.js +84 -0
  160. package/dist/serve/entries/active-auth.js.map +1 -0
  161. package/dist/serve/entries/auth-helper-core.d.ts +1 -0
  162. package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
  163. package/dist/serve/entries/auth-helper-core.js +4 -0
  164. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  165. package/dist/serve/entries/auth-helper-dom.d.ts.map +1 -1
  166. package/dist/serve/entries/auth-helper-dom.js +28 -2
  167. package/dist/serve/entries/auth-helper-dom.js.map +1 -1
  168. package/dist/serve/entries/auth.d.ts.map +1 -1
  169. package/dist/serve/entries/auth.js +8 -0
  170. package/dist/serve/entries/auth.js.map +1 -1
  171. package/dist/serve/entries/bridge-url.d.ts +1 -1
  172. package/dist/serve/entries/bridge-url.js +1 -1
  173. package/dist/serve/entries/init.d.ts.map +1 -1
  174. package/dist/serve/entries/init.js +70 -4
  175. package/dist/serve/entries/init.js.map +1 -1
  176. package/dist/serve/entries/runtime.d.ts.map +1 -1
  177. package/dist/serve/entries/runtime.js +9 -0
  178. package/dist/serve/entries/runtime.js.map +1 -1
  179. package/dist/serve/namespace.d.ts +14 -5
  180. package/dist/serve/namespace.d.ts.map +1 -1
  181. package/dist/serve/namespace.js +57 -124
  182. package/dist/serve/namespace.js.map +1 -1
  183. package/dist/serve/runtime/chip-config.d.ts.map +1 -1
  184. package/dist/serve/runtime/chip-config.js +16 -2
  185. package/dist/serve/runtime/chip-config.js.map +1 -1
  186. package/dist/serve/runtime/chip-dialog.d.ts +18 -0
  187. package/dist/serve/runtime/chip-dialog.d.ts.map +1 -0
  188. package/dist/serve/runtime/chip-dialog.js +315 -0
  189. package/dist/serve/runtime/chip-dialog.js.map +1 -0
  190. package/dist/serve/runtime/chip-install.d.ts +2 -0
  191. package/dist/serve/runtime/chip-install.d.ts.map +1 -1
  192. package/dist/serve/runtime/chip-install.js +9 -4
  193. package/dist/serve/runtime/chip-install.js.map +1 -1
  194. package/dist/serve/runtime/chip-user-search.d.ts +16 -0
  195. package/dist/serve/runtime/chip-user-search.d.ts.map +1 -0
  196. package/dist/serve/runtime/chip-user-search.js +354 -0
  197. package/dist/serve/runtime/chip-user-search.js.map +1 -0
  198. package/dist/serve/runtime/chip.d.ts +10 -0
  199. package/dist/serve/runtime/chip.d.ts.map +1 -1
  200. package/dist/serve/runtime/chip.js +118 -15
  201. package/dist/serve/runtime/chip.js.map +1 -1
  202. package/dist/serve/runtime/identity.d.ts +17 -0
  203. package/dist/serve/runtime/identity.d.ts.map +1 -0
  204. package/dist/serve/runtime/identity.js +10 -0
  205. package/dist/serve/runtime/identity.js.map +1 -0
  206. package/dist/serve/sandbox-session.d.ts +7 -0
  207. package/dist/serve/sandbox-session.d.ts.map +1 -1
  208. package/dist/serve/sandbox-session.js +2 -0
  209. package/dist/serve/sandbox-session.js.map +1 -1
  210. package/dist/serve/site-ui/_astro/{RulesCodeEditor.XtDmHOlN.js → RulesCodeEditor.DsTAsKIa.js} +1 -1
  211. package/dist/serve/site-ui/_astro/app.CMmTxyhL.js +1 -0
  212. package/dist/serve/site-ui/_astro/app.DhALsVii.js +115 -0
  213. package/dist/serve/site-ui/_astro/{chess-showcase.B72XYeoh.js → chess-showcase.Bn_pP6UJ.js} +2 -2
  214. package/dist/serve/site-ui/_astro/{example-runtime.C25_lx6Z.js → example-runtime.CXopTGv7.js} +1 -1
  215. package/dist/serve/site-ui/_astro/sandbox-controls.rOuZTOUG.js +510 -0
  216. package/dist/serve/site-ui/_astro/{seed.Co0yUJY5.js → seed.lywYbXZ0.js} +2 -2
  217. package/dist/serve/site-ui/_astro/writes.BsPBG3dp.js +653 -0
  218. package/dist/serve/site-ui/auth/index.html +1 -1
  219. package/dist/serve/site-ui/docs/_rhythm/index.html +1 -1
  220. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +1 -1
  221. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +1 -1
  222. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +1 -1
  223. package/dist/serve/site-ui/docs/ai-compat/index.html +1 -1
  224. package/dist/serve/site-ui/docs/api-reference/index.html +8 -1
  225. package/dist/serve/site-ui/docs/api-reference.md +7 -0
  226. package/dist/serve/site-ui/docs/app-compat/index.html +1 -1
  227. package/dist/serve/site-ui/docs/auth-compat/index.html +3 -3
  228. package/dist/serve/site-ui/docs/auth-compat.md +2 -2
  229. package/dist/serve/site-ui/docs/build/ai-logic/index.html +6 -1
  230. package/dist/serve/site-ui/docs/build/ai-logic.md +6 -0
  231. package/dist/serve/site-ui/docs/build/authentication/index.html +2 -2
  232. package/dist/serve/site-ui/docs/build/authentication.md +1 -1
  233. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +4 -2
  234. package/dist/serve/site-ui/docs/build/cloud-firestore.md +4 -0
  235. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +1 -1
  236. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +1 -1
  237. package/dist/serve/site-ui/docs/build/realtime-database/index.html +1 -1
  238. package/dist/serve/site-ui/docs/conformance-scores/index.html +14 -2
  239. package/dist/serve/site-ui/docs/conformance-scores.md +13 -1
  240. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +1 -1
  241. package/dist/serve/site-ui/docs/database-compat/index.html +44 -44
  242. package/dist/serve/site-ui/docs/database-compat.md +43 -43
  243. package/dist/serve/site-ui/docs/examples/chess/index.html +1 -1
  244. package/dist/serve/site-ui/docs/examples/index.html +1 -1
  245. package/dist/serve/site-ui/docs/firestore-compat/index.html +4 -4
  246. package/dist/serve/site-ui/docs/firestore-compat.md +3 -3
  247. package/dist/serve/site-ui/docs/firestore-flutter-compat/index.html +319 -0
  248. package/dist/serve/site-ui/docs/firestore-flutter-compat.md +344 -0
  249. package/dist/serve/site-ui/docs/firestore-kotlin-compat/index.html +319 -0
  250. package/dist/serve/site-ui/docs/firestore-kotlin-compat.md +344 -0
  251. package/dist/serve/site-ui/docs/firestore-swift-compat/index.html +490 -0
  252. package/dist/serve/site-ui/docs/firestore-swift-compat.md +517 -0
  253. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +1 -1
  254. package/dist/serve/site-ui/docs/get-started/backend-bundlers/index.html +105 -0
  255. package/dist/serve/site-ui/docs/get-started/backend-bundlers.md +165 -0
  256. package/dist/serve/site-ui/docs/get-started/flutter/index.html +98 -0
  257. package/dist/serve/site-ui/docs/get-started/flutter.md +105 -0
  258. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +1 -1
  259. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +1 -1
  260. package/dist/serve/site-ui/docs/get-started/start-building/index.html +1 -1
  261. package/dist/serve/site-ui/docs/get-started/vite/index.html +1 -1
  262. package/dist/serve/site-ui/docs/index.json +3211 -1471
  263. package/dist/serve/site-ui/docs/messaging-compat/index.html +1 -1
  264. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +4 -3
  265. package/dist/serve/site-ui/docs/observe/resolve-runtime-status.md +3 -1
  266. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +1 -1
  267. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +1 -1
  268. package/dist/serve/site-ui/docs/observe/switch-and-impersonate-identities/index.html +110 -0
  269. package/dist/serve/site-ui/docs/observe/switch-and-impersonate-identities.md +134 -0
  270. package/dist/serve/site-ui/docs/overview/index.html +1 -1
  271. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +1 -1
  272. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
  273. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +1 -1
  274. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +1 -1
  275. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +1 -1
  276. package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +1 -1
  277. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +1 -1
  278. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +1 -1
  279. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
  280. package/dist/serve/site-ui/docs/pyric-analytics-reference-api/index.html +124 -0
  281. package/dist/serve/site-ui/docs/pyric-analytics-reference-api.md +287 -0
  282. package/dist/serve/site-ui/docs/pyric-app-check-reference-api/index.html +87 -0
  283. package/dist/serve/site-ui/docs/pyric-app-check-reference-api.md +199 -0
  284. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +1 -1
  285. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +6 -2
  286. package/dist/serve/site-ui/docs/pyric-auth-reference-api.md +2 -1
  287. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
  288. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
  289. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +2 -2
  290. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api.md +1 -1
  291. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
  292. package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api/index.html +56 -0
  293. package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api.md +72 -0
  294. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +4 -1
  295. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api.md +3 -0
  296. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
  297. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +4 -1
  298. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api.md +3 -0
  299. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
  300. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
  301. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +2 -2
  302. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +1 -1
  303. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +1 -1
  304. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
  305. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +34 -9
  306. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api.md +16 -8
  307. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +133 -93
  308. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +61 -1
  309. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +2 -2
  310. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api.md +1 -1
  311. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +2 -2
  312. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api.md +2 -2
  313. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +2 -2
  314. package/dist/serve/site-ui/docs/pyric-database-reference-api.md +1 -1
  315. package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api/index.html +559 -0
  316. package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api.md +1240 -0
  317. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +40 -11
  318. package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +18 -8
  319. package/dist/serve/site-ui/docs/pyric-functions-reference-api/index.html +67 -0
  320. package/dist/serve/site-ui/docs/pyric-functions-reference-api.md +149 -0
  321. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +1 -1
  322. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
  323. package/dist/serve/site-ui/docs/pyric-performance-reference-api/index.html +35 -0
  324. package/dist/serve/site-ui/docs/pyric-performance-reference-api.md +69 -0
  325. package/dist/serve/site-ui/docs/pyric-remote-config-reference-api/index.html +132 -0
  326. package/dist/serve/site-ui/docs/pyric-remote-config-reference-api.md +307 -0
  327. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +1 -1
  328. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +52 -17
  329. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +48 -9
  330. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
  331. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +239 -49
  332. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +148 -31
  333. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +22 -4
  334. package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +25 -3
  335. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +26 -96
  336. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api.md +20 -51
  337. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
  338. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +2 -2
  339. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api.md +1 -1
  340. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
  341. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
  342. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
  343. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +2 -2
  344. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api.md +1 -1
  345. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +124 -26
  346. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api.md +58 -5
  347. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
  348. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
  349. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +1 -1
  350. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
  351. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +4 -5
  352. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +3 -4
  353. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
  354. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
  355. package/dist/serve/site-ui/docs/reference/cli/index.html +6 -3
  356. package/dist/serve/site-ui/docs/reference/cli.md +8 -2
  357. package/dist/serve/site-ui/docs/rules-compat/index.html +10 -2
  358. package/dist/serve/site-ui/docs/rules-compat.md +9 -1
  359. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +1 -1
  360. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +1 -1
  361. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +1 -1
  362. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
  363. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +1 -1
  364. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +1 -1
  365. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +1 -1
  366. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
  367. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +1 -1
  368. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +1 -1
  369. package/dist/serve/site-ui/docs/storage-compat/index.html +13 -13
  370. package/dist/serve/site-ui/docs/storage-compat.md +12 -12
  371. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
  372. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +1 -1
  373. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
  374. package/dist/serve/site-ui/docs/tutorial/index.html +1 -1
  375. package/dist/serve/site-ui/examples/chess/index.html +1 -1
  376. package/dist/serve/site-ui/firestore/index.html +1 -1
  377. package/dist/serve/site-ui/llms.txt +13 -0
  378. package/dist/serve/site-ui/rtdb/index.html +1 -1
  379. package/dist/serve/site-ui/settings/index.html +1 -1
  380. package/dist/serve/site-ui/storage/index.html +1 -1
  381. package/dist/serve/site-ui/studio/index.html +1 -1
  382. package/dist/serve/site-ui/traffic/index.html +1 -1
  383. package/dist/serve/studio/disk-workspace.d.ts.map +1 -1
  384. package/dist/serve/studio/disk-workspace.js +64 -2
  385. package/dist/serve/studio/disk-workspace.js.map +1 -1
  386. package/dist/serve/vite-plugin.d.ts +7 -7
  387. package/dist/serve/vite-plugin.js +1 -1
  388. package/dist/serve/vite-plugin.js.map +1 -1
  389. package/dist/serve/vite-sandbox-generation.d.ts.map +1 -1
  390. package/dist/serve/vite-sandbox-generation.js +12 -0
  391. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  392. package/dist/serve/worker/client/auth.js +1 -2
  393. package/dist/serve/worker/client/auth.js.map +1 -1
  394. package/dist/serve/worker/client/core.d.ts +21 -1
  395. package/dist/serve/worker/client/core.d.ts.map +1 -1
  396. package/dist/serve/worker/client/core.js +79 -3
  397. package/dist/serve/worker/client/core.js.map +1 -1
  398. package/dist/serve/worker/client.d.ts +1 -1
  399. package/dist/serve/worker/client.d.ts.map +1 -1
  400. package/dist/serve/worker/client.js +1 -1
  401. package/dist/serve/worker/client.js.map +1 -1
  402. package/dist/serve/worker/context-resolver.d.ts +30 -0
  403. package/dist/serve/worker/context-resolver.d.ts.map +1 -0
  404. package/dist/serve/worker/context-resolver.js +44 -0
  405. package/dist/serve/worker/context-resolver.js.map +1 -0
  406. package/dist/serve/worker/entry.js +23 -19
  407. package/dist/serve/worker/entry.js.map +1 -1
  408. package/dist/serve/worker/host/core.d.ts +1 -0
  409. package/dist/serve/worker/host/core.d.ts.map +1 -1
  410. package/dist/serve/worker/host/core.js +12 -6
  411. package/dist/serve/worker/host/core.js.map +1 -1
  412. package/dist/serve/worker/host/storage.js +2 -2
  413. package/dist/serve/worker/host-auth.js +1 -2
  414. package/dist/serve/worker/host-auth.js.map +1 -1
  415. package/dist/serve/worker/index.d.ts +1 -1
  416. package/dist/serve/worker/index.d.ts.map +1 -1
  417. package/dist/serve/worker/index.js +2 -2
  418. package/dist/serve/worker/index.js.map +1 -1
  419. package/dist/serve/worker/port-lifecycle.d.ts +18 -0
  420. package/dist/serve/worker/port-lifecycle.d.ts.map +1 -0
  421. package/dist/serve/worker/port-lifecycle.js +28 -0
  422. package/dist/serve/worker/port-lifecycle.js.map +1 -0
  423. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  424. package/dist/serve/worker/serve-init.js +8 -2
  425. package/dist/serve/worker/serve-init.js.map +1 -1
  426. package/dist/verify/fixture.d.ts +1 -1
  427. package/package.json +16 -5
  428. package/src/assurance/.generated/conformance-verdicts.ts +238 -1
  429. package/src/bridge/client/dispatch.ts +52 -56
  430. package/src/bridge/client/tool-family-factories.ts +34 -0
  431. package/src/bridge/server/mcp-contract.ts +15 -59
  432. package/src/bridge/server/peer.ts +24 -1
  433. package/src/bridge/server/tool-family-factories.ts +40 -0
  434. package/src/bridge/server/tool-metadata.ts +29 -61
  435. package/src/bridge/tool-families.generated.ts +17 -0
  436. package/src/bridge/tool-families.ts +87 -0
  437. package/src/bridge/tool-family-records/conformance.ts +6 -0
  438. package/src/bridge/tool-family-records/firestore-data.ts +15 -0
  439. package/src/bridge/tool-family-records/firestore-inspect.ts +6 -0
  440. package/src/bridge/tool-family-records/firestore-rules.ts +15 -0
  441. package/src/bridge/tool-family-records/firestore-simulator.ts +16 -0
  442. package/src/bridge/tool-family-records/rtdb-inspection.ts +6 -0
  443. package/src/bundler/externals.ts +55 -0
  444. package/src/bundler/index.ts +21 -0
  445. package/src/cli/cli.test.ts +0 -44
  446. package/src/cli/inlined-sdk-scanner.ts +77 -0
  447. package/src/cli/sandbox-interlock.ts +167 -0
  448. package/src/cli/sandbox-runner.ts +37 -26
  449. package/src/cli/serve.ts +68 -69
  450. package/src/cli/unsupported-runtime.ts +68 -0
  451. package/src/conformance/.generated/can-i-use-browser.ts +2 -2
  452. package/src/conformance/.generated/can-i-use.ts +2 -2
  453. package/src/conformance/.generated/conformance-docs.ts +1 -1
  454. package/src/functions-rtdb/child.ts +115 -21
  455. package/src/functions-rtdb/development-runtime.ts +4 -0
  456. package/src/google-endpoints.ts +155 -0
  457. package/src/next/runtime-env.ts +5 -0
  458. package/src/next/with-pyric.ts +1 -1
  459. package/src/register/beacon.ts +232 -0
  460. package/src/register/index.ts +68 -6
  461. package/src/register/net-guard.ts +567 -0
  462. package/src/serve/ai-diagnostics-relay.ts +243 -0
  463. package/src/serve/ai-proxy.ts +327 -0
  464. package/src/serve/ai-status.ts +109 -0
  465. package/src/serve/ai-terminal-blocks.ts +210 -0
  466. package/src/serve/ai-terminal-text.ts +52 -0
  467. package/src/serve/beacon-route.ts +141 -0
  468. package/src/serve/entries/active-auth-registry.ts +56 -0
  469. package/src/serve/entries/active-auth.ts +100 -0
  470. package/src/serve/entries/auth-helper-core.ts +5 -0
  471. package/src/serve/entries/auth-helper-dom.ts +26 -2
  472. package/src/serve/entries/auth.ts +8 -0
  473. package/src/serve/entries/bridge-url.ts +1 -1
  474. package/src/serve/entries/init.ts +78 -3
  475. package/src/serve/entries/runtime.ts +10 -0
  476. package/src/serve/namespace.ts +73 -140
  477. package/src/serve/runtime/chip-config.ts +16 -2
  478. package/src/serve/runtime/chip-dialog.ts +366 -0
  479. package/src/serve/runtime/chip-install.ts +10 -4
  480. package/src/serve/runtime/chip-user-search.ts +391 -0
  481. package/src/serve/runtime/chip.ts +140 -15
  482. package/src/serve/runtime/identity.ts +26 -0
  483. package/src/serve/sandbox-session.ts +9 -0
  484. package/src/serve/studio/disk-workspace.ts +76 -2
  485. package/src/serve/vite-plugin.ts +8 -8
  486. package/src/serve/vite-sandbox-generation.ts +15 -0
  487. package/src/serve/worker/client/auth.ts +1 -1
  488. package/src/serve/worker/client/core.ts +80 -3
  489. package/src/serve/worker/client.ts +1 -1
  490. package/src/serve/worker/context-resolver.ts +60 -0
  491. package/src/serve/worker/entry.ts +22 -18
  492. package/src/serve/worker/host/core.ts +9 -7
  493. package/src/serve/worker/host/storage.ts +2 -2
  494. package/src/serve/worker/host-auth.ts +1 -1
  495. package/src/serve/worker/index.ts +4 -1
  496. package/src/serve/worker/port-lifecycle.ts +45 -0
  497. package/src/serve/worker/serve-init.ts +9 -2
  498. package/src/verify/fixture.ts +1 -1
  499. package/dist/serve/site-ui/_astro/app.B52xr-DK.js +0 -1
  500. package/dist/serve/site-ui/_astro/app.DWBraPUw.js +0 -12
  501. package/dist/serve/site-ui/_astro/sandbox-controls.DEpnKg-O.js +0 -1169
  502. package/dist/serve/site-ui/_astro/writes.rpjrFzmu.js +0 -102
@@ -0,0 +1,391 @@
1
+ import type { AuthUserRecord } from 'pyric/auth';
2
+
3
+ export interface UserSearchOptions {
4
+ container: HTMLElement;
5
+ onSelect: (user: AuthUserRecord) => void;
6
+ }
7
+
8
+ export interface UserSearchController {
9
+ setUsers(users: AuthUserRecord[]): void;
10
+ reset(): void;
11
+ focus(): void;
12
+ }
13
+
14
+ export function userDisplayLabel(user: AuthUserRecord): string {
15
+ if (user.displayName && user.displayName.trim().length > 0) {
16
+ return user.displayName.trim();
17
+ }
18
+ if (user.email && user.email.trim().length > 0) {
19
+ return user.email.trim();
20
+ }
21
+ return user.uid;
22
+ }
23
+
24
+ export function extractTenantFromUser(user: AuthUserRecord): string {
25
+ const claims = user.customClaims ?? {};
26
+ if (typeof claims.tenant === 'string') return claims.tenant;
27
+ if (claims.firebase && typeof (claims.firebase as Record<string, unknown>).tenant === 'string') {
28
+ return (claims.firebase as Record<string, unknown>).tenant as string;
29
+ }
30
+ return '';
31
+ }
32
+
33
+ export function getUserProviders(user: AuthUserRecord): string[] {
34
+ const providers = (user.providerUserInfo ?? [])
35
+ .map((p) => p.providerId)
36
+ .filter((id): id is string => typeof id === 'string' && id.length > 0);
37
+ if (user.isAnonymous && !providers.includes('anonymous')) {
38
+ providers.push('anonymous');
39
+ }
40
+ return providers;
41
+ }
42
+
43
+ function isAdminUser(user: AuthUserRecord): boolean {
44
+ const claims = user.customClaims ?? {};
45
+ return claims.admin === true || claims.role === 'admin';
46
+ }
47
+
48
+ export function filterUsers(
49
+ users: AuthUserRecord[],
50
+ query: string,
51
+ filter: string | null,
52
+ ): AuthUserRecord[] {
53
+ let list = users.filter((user) => user.disabled !== true);
54
+ if (filter) {
55
+ const f = filter.toLowerCase();
56
+ if (f === 'admin') {
57
+ list = list.filter(isAdminUser);
58
+ } else if (f === 'tenants') {
59
+ list = list.filter((u) => Boolean(extractTenantFromUser(u)));
60
+ } else {
61
+ list = list.filter((u) => getUserProviders(u).includes(f));
62
+ }
63
+ }
64
+
65
+ const q = query.trim().toLowerCase();
66
+ if (!q) return list;
67
+
68
+ return list.filter((u) => {
69
+ if (q.startsWith('provider:')) {
70
+ const target = q.slice(9).trim();
71
+ return getUserProviders(u).some((p) => p.toLowerCase().includes(target));
72
+ }
73
+ if (q.startsWith('role:')) {
74
+ const target = q.slice(5).trim();
75
+ const c = u.customClaims ?? {};
76
+ const role = String(c.role ?? '').toLowerCase();
77
+ return role.includes(target);
78
+ }
79
+ if (q.startsWith('tenant:')) {
80
+ const target = q.slice(7).trim();
81
+ const tenant = extractTenantFromUser(u).toLowerCase();
82
+ return tenant.includes(target);
83
+ }
84
+ if (q.startsWith('claim:')) {
85
+ const spec = q.slice(6).trim();
86
+ const delimiter = spec.includes('=') ? '=' : ':';
87
+ const [key, val] = spec.split(delimiter).map((s) => s.trim());
88
+ const c = u.customClaims ?? {};
89
+ if (key && val !== undefined) {
90
+ return String(c[key] ?? '').toLowerCase().includes(val);
91
+ }
92
+ return Object.keys(c).some((k) => k.toLowerCase().includes(spec));
93
+ }
94
+ if (q.includes(':') || q.includes('=')) {
95
+ const delimiter = q.includes('=') ? '=' : ':';
96
+ const [key, val] = q.split(delimiter).map((s) => s.trim());
97
+ const c = u.customClaims ?? {};
98
+ if (key && c[key] !== undefined && val !== undefined) {
99
+ return String(c[key]).toLowerCase().includes(val);
100
+ }
101
+ }
102
+
103
+ const name = (u.displayName ?? '').toLowerCase();
104
+ const email = (u.email ?? '').toLowerCase();
105
+ const uid = u.uid.toLowerCase();
106
+ const tenant = extractTenantFromUser(u).toLowerCase();
107
+ const providers = getUserProviders(u).join(' ').toLowerCase();
108
+ const claims = JSON.stringify(u.customClaims ?? {}).toLowerCase();
109
+
110
+ return (
111
+ name.includes(q)
112
+ || email.includes(q)
113
+ || uid.includes(q)
114
+ || tenant.includes(q)
115
+ || providers.includes(q)
116
+ || claims.includes(q)
117
+ );
118
+ });
119
+ }
120
+
121
+ export function createUserSearchController(options: UserSearchOptions): UserSearchController {
122
+ const { container, onSelect } = options;
123
+ const documentLike = container.ownerDocument;
124
+
125
+ container.innerHTML = `
126
+ <div class="user-search-box">
127
+ <span class="user-search-icon" aria-hidden="true">⌕</span>
128
+ <input
129
+ type="text"
130
+ class="user-search-input"
131
+ data-user-search-input
132
+ placeholder="Search name, uid, provider:google, role:admin..."
133
+ autocomplete="off"
134
+ role="combobox"
135
+ aria-label="Search sandbox users"
136
+ aria-autocomplete="list"
137
+ aria-expanded="false"
138
+ aria-controls="user-search-listbox"
139
+ />
140
+ <button type="button" class="user-search-clear-btn" data-search-clear-btn aria-label="Clear search" style="display: none;">✕</button>
141
+ </div>
142
+ <div class="filter-chips" data-filter-chips></div>
143
+ <ul
144
+ id="user-search-listbox"
145
+ class="user-search-listbox"
146
+ data-user-search-listbox
147
+ role="listbox"
148
+ aria-label="Matching users"
149
+ ></ul>
150
+ `;
151
+
152
+ const input = container.querySelector<HTMLInputElement>('[data-user-search-input]')!;
153
+ const clearBtn = container.querySelector<HTMLButtonElement>('[data-search-clear-btn]')!;
154
+ const filterChipsEl = container.querySelector<HTMLElement>('[data-filter-chips]')!;
155
+ const listbox = container.querySelector<HTMLUListElement>('[data-user-search-listbox]')!;
156
+
157
+ let cachedUsers: AuthUserRecord[] = [];
158
+ let currentMatches: AuthUserRecord[] = [];
159
+ let activeFilter: string | null = null;
160
+ let highlightedIndex = -1;
161
+
162
+ const updateHighlight = (index: number): void => {
163
+ highlightedIndex = index;
164
+ const items = Array.from(listbox.querySelectorAll<HTMLElement>('.user-search-item'));
165
+ items.forEach((item, idx) => {
166
+ if (idx === highlightedIndex) {
167
+ item.classList.add('highlighted');
168
+ item.setAttribute('aria-selected', 'true');
169
+ input.setAttribute('aria-activedescendant', item.id);
170
+ item.scrollIntoView?.({ block: 'nearest' });
171
+ } else {
172
+ item.classList.remove('highlighted');
173
+ item.setAttribute('aria-selected', 'false');
174
+ }
175
+ });
176
+ if (highlightedIndex < 0) {
177
+ input.removeAttribute('aria-activedescendant');
178
+ }
179
+ };
180
+
181
+ const renderFilterChips = (): void => {
182
+ if (cachedUsers.length === 0) {
183
+ filterChipsEl.innerHTML = '';
184
+ return;
185
+ }
186
+ const categories: Array<{ id: string | null; label: string }> = [
187
+ { id: null, label: 'All' },
188
+ ];
189
+ const hasAdmins = cachedUsers.some(isAdminUser);
190
+ if (hasAdmins) categories.push({ id: 'admin', label: 'Admins' });
191
+
192
+ const hasTenants = cachedUsers.some((u) => Boolean(extractTenantFromUser(u)));
193
+ if (hasTenants) categories.push({ id: 'tenants', label: 'Tenants' });
194
+
195
+ const providerSet = new Set<string>();
196
+ cachedUsers.forEach((u) => getUserProviders(u).forEach((p) => providerSet.add(p)));
197
+ providerSet.forEach((p) => categories.push({ id: p, label: p }));
198
+
199
+ filterChipsEl.replaceChildren();
200
+ for (const category of categories) {
201
+ const button = documentLike.createElement('button');
202
+ button.type = 'button';
203
+ button.className = 'filter-chip';
204
+ const isSelected = activeFilter === category.id;
205
+ if (isSelected) button.classList.add('selected');
206
+ button.setAttribute('aria-pressed', String(isSelected));
207
+ button.dataset.filter = category.id ?? '';
208
+ button.textContent = category.label;
209
+ filterChipsEl.append(button);
210
+ }
211
+ };
212
+
213
+ const renderMatches = (): void => {
214
+ currentMatches = filterUsers(cachedUsers, input.value, activeFilter);
215
+ highlightedIndex = -1;
216
+ input.removeAttribute('aria-activedescendant');
217
+
218
+ if (currentMatches.length === 0) {
219
+ const empty = documentLike.createElement('li');
220
+ empty.className = 'user-search-empty';
221
+ empty.setAttribute('role', 'presentation');
222
+ empty.textContent = 'No matching users found in sandbox';
223
+ listbox.replaceChildren(empty);
224
+ input.setAttribute('aria-expanded', 'true');
225
+ return;
226
+ }
227
+
228
+ const items = currentMatches.map((user, index) => {
229
+ const label = userDisplayLabel(user);
230
+ const tenant = extractTenantFromUser(user);
231
+ const providers = getUserProviders(user);
232
+ const claims = user.customClaims ?? {};
233
+ let claimsSummary = '';
234
+ if (Object.keys(claims).length > 0) {
235
+ claimsSummary = JSON.stringify(claims).slice(0, 40);
236
+ }
237
+
238
+ const item = documentLike.createElement('li');
239
+ item.id = `user-search-item-${index}`;
240
+ item.className = 'user-search-item';
241
+ item.setAttribute('role', 'option');
242
+ item.setAttribute('aria-selected', 'false');
243
+ item.dataset.userIndex = String(index);
244
+
245
+ const main = documentLike.createElement('div');
246
+ main.className = 'user-item-main';
247
+ const name = documentLike.createElement('span');
248
+ name.className = 'user-item-name';
249
+ name.textContent = label;
250
+ main.append(name);
251
+ if (user.email && user.email !== label) {
252
+ const email = documentLike.createElement('span');
253
+ email.className = 'user-item-email';
254
+ email.textContent = user.email;
255
+ main.append(email);
256
+ }
257
+ const uid = documentLike.createElement('span');
258
+ uid.className = 'user-item-uid';
259
+ uid.textContent = user.uid;
260
+ main.append(uid);
261
+
262
+ const badges = documentLike.createElement('div');
263
+ badges.className = 'user-item-badges';
264
+ for (const provider of providers) {
265
+ const badge = documentLike.createElement('span');
266
+ badge.className = 'badge badge-provider';
267
+ badge.textContent = provider;
268
+ badges.append(badge);
269
+ }
270
+ if (tenant) {
271
+ const badge = documentLike.createElement('span');
272
+ badge.className = 'badge badge-tenant';
273
+ badge.textContent = tenant;
274
+ badges.append(badge);
275
+ }
276
+ if (claimsSummary) {
277
+ const badge = documentLike.createElement('span');
278
+ badge.className = 'badge badge-claims';
279
+ badge.title = claimsSummary;
280
+ badge.textContent = claimsSummary;
281
+ badges.append(badge);
282
+ }
283
+
284
+ item.append(main, badges);
285
+ return item;
286
+ });
287
+ listbox.replaceChildren(...items);
288
+
289
+ listbox.style.display = 'block';
290
+ input.setAttribute('aria-expanded', 'true');
291
+ };
292
+
293
+ input.addEventListener('input', () => {
294
+ clearBtn.style.display = input.value.length > 0 ? 'inline-block' : 'none';
295
+ renderMatches();
296
+ });
297
+
298
+ input.addEventListener('focus', () => {
299
+ renderMatches();
300
+ });
301
+
302
+ clearBtn.addEventListener('click', (e) => {
303
+ e.stopPropagation();
304
+ input.value = '';
305
+ clearBtn.style.display = 'none';
306
+ renderMatches();
307
+ input.focus();
308
+ });
309
+
310
+ input.addEventListener('keydown', (e: KeyboardEvent) => {
311
+ if (listbox.style.display === 'none') {
312
+ if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
313
+ renderMatches();
314
+ e.preventDefault();
315
+ return;
316
+ }
317
+ }
318
+
319
+ const items = Array.from(listbox.querySelectorAll<HTMLElement>('.user-search-item'));
320
+ if (items.length === 0) return;
321
+
322
+ if (e.key === 'ArrowDown') {
323
+ e.preventDefault();
324
+ const next = (highlightedIndex + 1) % items.length;
325
+ updateHighlight(next);
326
+ } else if (e.key === 'ArrowUp') {
327
+ e.preventDefault();
328
+ const prev = (highlightedIndex - 1 + items.length) % items.length;
329
+ updateHighlight(prev);
330
+ } else if (e.key === 'Enter') {
331
+ if (highlightedIndex >= 0 && highlightedIndex < currentMatches.length) {
332
+ e.preventDefault();
333
+ const selected = currentMatches[highlightedIndex];
334
+ onSelect(selected);
335
+ }
336
+ } else if (e.key === 'Escape') {
337
+ if (input.value) {
338
+ e.stopPropagation();
339
+ input.value = '';
340
+ clearBtn.style.display = 'none';
341
+ renderMatches();
342
+ }
343
+ }
344
+ });
345
+
346
+ filterChipsEl.addEventListener('click', (e: MouseEvent) => {
347
+ e.stopPropagation();
348
+ const target = (e.target as HTMLElement).closest<HTMLElement>('.filter-chip');
349
+ if (!target) return;
350
+ const filterVal = target.getAttribute('data-filter') || null;
351
+ if (filterVal === null) {
352
+ activeFilter = null;
353
+ } else {
354
+ activeFilter = activeFilter === filterVal ? null : filterVal;
355
+ }
356
+ renderFilterChips();
357
+ renderMatches();
358
+ });
359
+
360
+ listbox.addEventListener('click', (e: MouseEvent) => {
361
+ e.stopPropagation();
362
+ const target = (e.target as HTMLElement).closest<HTMLElement>('.user-search-item');
363
+ if (!target) return;
364
+ const idx = Number(target.getAttribute('data-user-index'));
365
+ if (!Number.isNaN(idx) && currentMatches[idx]) {
366
+ const selected = currentMatches[idx];
367
+ onSelect(selected);
368
+ }
369
+ });
370
+
371
+ return {
372
+ setUsers(users: AuthUserRecord[]) {
373
+ cachedUsers = users;
374
+ renderFilterChips();
375
+ renderMatches();
376
+ },
377
+ reset() {
378
+ input.value = '';
379
+ clearBtn.style.display = 'none';
380
+ activeFilter = null;
381
+ highlightedIndex = -1;
382
+ input.setAttribute('aria-expanded', 'false');
383
+ input.removeAttribute('aria-activedescendant');
384
+ renderFilterChips();
385
+ renderMatches();
386
+ },
387
+ focus() {
388
+ input.focus();
389
+ },
390
+ };
391
+ }
@@ -1,8 +1,20 @@
1
+ import type { AuthLens } from 'pyric/sandbox';
1
2
  import type {
2
3
  PyricRuntimeError,
3
4
  PyricRuntimeSnapshot,
4
5
  PyricRuntimeStatus,
5
6
  } from './status.js';
7
+ import {
8
+ createChipDialogController,
9
+ DIALOG_STYLES,
10
+ type ChipDialogController,
11
+ } from './chip-dialog.js';
12
+ import type { RuntimeIdentity, RuntimeIdentityBindings } from './identity.js';
13
+ import {
14
+ getLens as defaultGetLens,
15
+ setLens as defaultSetLens,
16
+ subscribeLens as defaultSubscribeLens,
17
+ } from '../worker/client/core.js';
6
18
 
7
19
  export interface PyricRuntimeChipOptions {
8
20
  runtime: PyricRuntimeStatus;
@@ -11,6 +23,14 @@ export interface PyricRuntimeChipOptions {
11
23
  initiallyOpen?: boolean;
12
24
  /** Override Studio availability. Omitted uses the runtime manifest URL. */
13
25
  studioUrl?: string | null;
26
+ /** Optional identity integration. Missing operations use lens/no-op fallbacks. */
27
+ identity?: Partial<RuntimeIdentityBindings>;
28
+ /** Injectable lens getter (defaults to worker client getLens). */
29
+ getLens?: () => AuthLens | undefined;
30
+ /** Injectable lens setter (defaults to worker client setLens). */
31
+ setLens?: (lens: AuthLens | undefined) => void;
32
+ /** Injectable lens subscription (defaults to worker client subscribeLens). */
33
+ subscribeLens?: (listener: (lens: AuthLens | undefined) => void) => () => void;
14
34
  }
15
35
 
16
36
  export interface PyricRuntimeChip {
@@ -89,9 +109,14 @@ const styles = `
89
109
  .brand-label { font-size: 11px; }
90
110
  .signals { color: var(--pyric-muted); font-size: 10px; gap: 8px; }
91
111
  .signal { gap: 4px; white-space: nowrap; }
112
+ .signal[data-identity-badge] {
113
+ max-width: 140px;
114
+ overflow: hidden;
115
+ text-overflow: ellipsis;
116
+ }
92
117
  .dot { background: var(--pyric-accent); border-radius: 50%; height: 8px; width: 8px; }
93
- .dot.error { background: var(--pyric-error); box-shadow: 0 0 0 3px rgba(240,160,160,.12); }
94
118
  .signal.update { color: var(--pyric-warning); }
119
+ .signal.bypass { color: #8f7fe8; font-weight: 500; }
95
120
  .chevron { color: var(--pyric-muted); height: 14px; width: 14px; }
96
121
  .panel {
97
122
  background: var(--pyric-bg);
@@ -133,7 +158,7 @@ const styles = `
133
158
  .error-body code { color: #d7d7df; display: block; font-size: 11px; line-height: 1.55; overflow-wrap: anywhere; white-space: pre-wrap; }
134
159
  .error-meta { color: var(--pyric-muted); font: 9px/1.4 ui-monospace, monospace; margin-top: 4px; overflow-wrap: anywhere; }
135
160
  .empty { align-items: center; color: var(--pyric-muted); display: flex; font: 11px/1.5 ui-monospace, monospace; min-height: 57px; padding: 12px; }
136
- .actions { display: grid; gap: 8px; grid-template-columns: 1fr 1fr; min-height: 56px; padding: 10px 12px; }
161
+ .actions { display: grid; gap: 8px; grid-template-columns: repeat(3, 1fr); min-height: 56px; padding: 10px 12px; }
137
162
  .button { align-items: center; background: transparent; border: 1px solid var(--pyric-border-soft); border-radius: 4px; color: var(--pyric-muted); display: inline-flex; font-size: 10px; justify-content: center; letter-spacing: .06em; min-height: 34px; padding: 6px 8px; text-decoration: none; text-transform: uppercase; }
138
163
  button.button { cursor: pointer; }
139
164
  .button:hover:not(:disabled):not([aria-disabled="true"]), a.button:hover { border-color: #3a3a48; color: var(--pyric-text); }
@@ -150,6 +175,8 @@ const styles = `
150
175
  .chip, .panel { animation: pyric-enter 120ms ease-out; transform-origin: bottom right; }
151
176
  @keyframes pyric-enter { from { opacity: 0; transform: translateY(4px) scale(.98); } }
152
177
  }
178
+
179
+ ${DIALOG_STYLES}
153
180
  `;
154
181
 
155
182
  const icons = {
@@ -161,7 +188,7 @@ const icons = {
161
188
  };
162
189
 
163
190
  function escapeAttribute(value: string): string {
164
- return value.replaceAll('&', '&amp;').replaceAll('"', '&quot;').replaceAll('<', '&lt;');
191
+ return value.replaceAll('&', '&amp;').replaceAll('"', '&quot;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');
165
192
  }
166
193
 
167
194
  export function formatPyricRuntimeError(error: PyricRuntimeError): string {
@@ -189,7 +216,19 @@ function renderErrors(snapshot: PyricRuntimeSnapshot, canCopy: boolean): string
189
216
  /** Mount the framework-independent runtime chip in an isolated shadow root. */
190
217
  export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRuntimeChip {
191
218
  const documentLike = options.document ?? document;
192
- const host = documentLike.createElement('div');
219
+ const existingHost = documentLike.querySelector<HTMLElement>(
220
+ '[data-pyric-runtime-chip-host], pyric-runtime-chip',
221
+ );
222
+ if (existingHost) {
223
+ existingHost.remove();
224
+ }
225
+
226
+ let host: HTMLElement;
227
+ try {
228
+ host = documentLike.createElement('pyric-runtime-chip');
229
+ } catch {
230
+ host = documentLike.createElement('div');
231
+ }
193
232
  host.setAttribute('data-pyric-runtime-chip-host', '');
194
233
  const root = host.attachShadow({ mode: 'open' });
195
234
  root.innerHTML = `<style>${styles}</style><div class="announcer" role="status" aria-live="polite" aria-atomic="true"></div><div data-view></div>`;
@@ -203,6 +242,50 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
203
242
  let open = options.initiallyOpen ?? false;
204
243
  let snapshot = options.runtime.getSnapshot();
205
244
 
245
+ const getLensFn = options.getLens ?? defaultGetLens;
246
+ const setLensFn = options.setLens ?? defaultSetLens;
247
+ const subscribeLensFn = options.subscribeLens ?? defaultSubscribeLens;
248
+ const providedIdentity = options.identity;
249
+ let clientUser: RuntimeIdentity | null = null;
250
+ const readCurrentUser = (): RuntimeIdentity | null => {
251
+ if (providedIdentity?.getCurrentUser) return providedIdentity.getCurrentUser();
252
+ return clientUser;
253
+ };
254
+ clientUser = readCurrentUser();
255
+
256
+ const identity: RuntimeIdentityBindings = {
257
+ listUsers: providedIdentity?.listUsers ?? (() => []),
258
+ switchUser: async (uid) => {
259
+ if (providedIdentity?.switchUser) await providedIdentity.switchUser(uid);
260
+ else setLensFn({ mode: 'as', uid });
261
+ clientUser = readCurrentUser();
262
+ render();
263
+ },
264
+ signOut: async () => {
265
+ if (providedIdentity?.signOut) await providedIdentity.signOut();
266
+ else setLensFn(undefined);
267
+ clientUser = null;
268
+ render();
269
+ },
270
+ openCreateUser: providedIdentity?.openCreateUser ?? (() => {}),
271
+ getCurrentUser: readCurrentUser,
272
+ subscribeAuth: providedIdentity?.subscribeAuth ?? (() => () => {}),
273
+ };
274
+
275
+ const dialogController: ChipDialogController = createChipDialogController({
276
+ shadowRoot: root,
277
+ identity,
278
+ onToggleAdminBypass: (enable) => {
279
+ if (enable) {
280
+ setLensFn({ mode: 'admin' });
281
+ } else {
282
+ setLensFn(undefined);
283
+ }
284
+ render();
285
+ },
286
+ getLens: () => getLensFn(),
287
+ });
288
+
206
289
  const render = (next = snapshot): void => {
207
290
  const active = root.activeElement;
208
291
  const oldViewport = view.querySelector<HTMLElement>('[data-error-viewport]');
@@ -213,7 +296,7 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
213
296
  }
214
297
  : null;
215
298
  const activeCopyId = active?.getAttribute('data-copy-error');
216
- const activeControl = ['data-expand', 'data-collapse', 'data-update-worker', 'data-open-studio']
299
+ const activeControl = ['data-expand', 'data-collapse', 'data-update-worker', 'data-open-studio', 'data-open-impersonate']
217
300
  .find((attribute) => active?.hasAttribute(attribute));
218
301
  const focusToken = activeCopyId !== null && activeCopyId !== undefined
219
302
  ? { attribute: 'data-copy-error', value: activeCopyId }
@@ -228,41 +311,60 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
228
311
  ? 'Sandbox starting'
229
312
  : snapshot.mode === 'in-page'
230
313
  ? 'In-page sandbox'
231
- : 'Worker current';
314
+ : 'Worker version';
232
315
  const epochs = snapshot.updateAvailable
233
316
  ? `${snapshot.runningEpoch?.slice(0, 8) ?? 'unknown'} → ${snapshot.servedEpoch?.slice(0, 8) ?? 'unknown'}`
234
317
  : snapshot.runningEpoch?.slice(0, 8) ?? '';
235
318
  const aiState = aiEngineState();
236
319
 
320
+ const lens = getLensFn();
321
+ const user = readCurrentUser();
322
+ const isAdmin = lens?.mode === 'admin';
323
+ const activeUid = lens?.mode === 'as' ? lens.uid : user?.uid;
324
+
325
+ const identitySignals: string[] = [];
326
+ let identityStateHtml = '<span class="epochs" data-identity-state>App session</span>';
327
+ if (activeUid) {
328
+ identitySignals.push(`<span class="signal" data-identity-badge title="as: ${escapeAttribute(activeUid)}">as: ${escapeAttribute(activeUid)}</span>`);
329
+ identityStateHtml = `<span class="epochs" data-identity-state data-identity-badge title="as: ${escapeAttribute(activeUid)}">as: ${escapeAttribute(activeUid)}</span>`;
330
+ }
331
+ if (isAdmin) {
332
+ identitySignals.push('<span class="signal bypass" data-identity-badge>bypass rules</span>');
333
+ }
334
+ const identitySignalHtml = identitySignals.join('');
335
+
237
336
  view.innerHTML = `${open ? `
238
- <section class="panel" role="dialog" aria-label="Pyric runtime">
337
+ <section class="panel" role="dialog" aria-label="pyric">
239
338
  <header class="panel-header">
240
- <div class="panel-title"><span class="brand-mark">&gt;_</span><strong>Pyric runtime</strong>${errorCount > 0 ? `<span class="count">${errorCount} ${errorCount === 1 ? 'error' : 'errors'}</span><button class="clear-button" type="button" data-clear-errors aria-label="Clear all errors">Clear</button>` : ''}</div>
339
+ <div class="panel-title"><span class="brand-mark">&gt;_</span><strong>pyric</strong>${errorCount > 0 ? `<span class="count">${errorCount} ${errorCount === 1 ? 'error' : 'errors'}</span><button class="clear-button" type="button" data-clear-errors aria-label="Clear all errors">Clear</button>` : ''}</div>
241
340
  <div class="panel-controls">
242
- <button class="icon-button" type="button" data-collapse aria-label="Minimize Pyric runtime">${icons.minimize}</button>
243
- <button class="icon-button" type="button" data-dismiss-chip aria-label="Dismiss Pyric runtime from page">${icons.close}</button>
341
+ <button class="icon-button" type="button" data-collapse aria-label="Minimize pyric">${icons.minimize}</button>
342
+ <button class="icon-button" type="button" data-dismiss-chip aria-label="Dismiss pyric from page">${icons.close}</button>
244
343
  </div>
245
344
  </header>
246
- <div class="worker-state"><span class="state-label${snapshot.updateAvailable ? ' available' : ''}"><span class="mini-dot"></span>${workerLabel}</span><span class="epochs">${epochs}</span></div>
345
+ <div class="worker-state"><span class="state-label${snapshot.updateAvailable ? ' available' : ''}">${workerLabel}</span><span class="epochs">${epochs}</span></div>
247
346
  <div class="worker-state-col" data-ai-status>
248
347
  <div class="worker-state-row">
249
- <span class="state-label"><span class="mini-dot"></span>AI engine</span>
348
+ <span class="state-label">AI engine</span>
250
349
  <span class="epochs">${aiState.primary}</span>
251
350
  </div>
252
351
  ${aiState.subline ? `<div class="worker-state-subline">${aiState.subline}</div>` : ''}
253
352
  </div>
353
+ <div class="worker-state"><span class="state-label">Rules</span><span class="epochs" style="${isAdmin ? 'color: #8f7fe8; font-weight: 500;' : ''}">${isAdmin ? 'bypassed' : 'enforced'}</span></div>
354
+ <div class="worker-state"><span class="state-label">Identity</span>${identityStateHtml}</div>
254
355
  <div class="errors" data-error-viewport>${renderErrors(snapshot, Boolean(clipboard))}</div>
255
356
  <div class="actions">
256
357
  <button class="button update" type="button" data-update-worker ${snapshot.updateAvailable ? '' : 'disabled'} aria-disabled="${snapshot.updateAvailable && !snapshot.updatingWorker ? 'false' : 'true'}">${snapshot.updatingWorker ? 'Updating…' : 'Update worker'}</button>
358
+ <button class="button" type="button" data-open-impersonate>Identity</button>
257
359
  ${studioUrl
258
360
  ? `<a class="button" data-open-studio href="${escapeAttribute(studioUrl)}" target="_blank" rel="noopener noreferrer">Studio${icons.external}</a>`
259
361
  : `<span class="button" data-open-studio aria-disabled="true" title="Pyric Studio is disabled">Studio${icons.external}</span>`}
260
362
  </div>
261
363
  </section>
262
364
  ` : `
263
- <button class="chip" type="button" data-expand aria-label="Open Pyric runtime" aria-expanded="false">
264
- <span class="brand"><span class="dot${errorCount > 0 ? ' error' : ''}"></span><span class="brand-label">Pyric</span></span>
265
- <span class="signals">${snapshot.updateAvailable ? '<span class="signal update">update</span>' : ''}${errorCount > 0 ? `<span class="signal">${errorCount} ${errorCount === 1 ? 'error' : 'errors'}</span>` : '<span class="signal">ready</span>'}${icons.chevron}</span>
365
+ <button class="chip" type="button" data-expand aria-label="Open pyric" aria-expanded="false">
366
+ <span class="brand"><span class="dot${errorCount > 0 ? ' error' : ''}"></span><span class="brand-label">pyric</span></span>
367
+ <span class="signals">${identitySignalHtml}${snapshot.updateAvailable ? '<span class="signal update">update</span>' : ''}${errorCount > 0 ? `<span class="signal">${errorCount} ${errorCount === 1 ? 'error' : 'errors'}</span>` : ''}${icons.chevron}</span>
266
368
  </button>
267
369
  `}`;
268
370
 
@@ -302,6 +404,9 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
302
404
  if (!snapshot.updateAvailable || snapshot.updatingWorker) return;
303
405
  void options.runtime.updateWorker().catch(() => { /* status records and renders the failure */ });
304
406
  });
407
+ root.querySelector('[data-open-impersonate]')?.addEventListener('click', (e) => {
408
+ void dialogController.open(e.currentTarget as HTMLElement);
409
+ });
305
410
  for (const button of root.querySelectorAll<HTMLButtonElement>('[data-copy-error]')) {
306
411
  button.addEventListener('click', () => {
307
412
  const error = snapshot.errors.find((item) => item.id === button.dataset.copyError);
@@ -329,11 +434,31 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
329
434
  };
330
435
 
331
436
  documentLike.body.append(host);
437
+ const reattachAfterAstroSwap = (): void => {
438
+ if (!host.isConnected) documentLike.body.append(host);
439
+ };
440
+ documentLike.addEventListener('astro:after-swap', reattachAfterAstroSwap);
332
441
  const unsubscribe = options.runtime.subscribe(render);
442
+
443
+ const unsubLens = subscribeLensFn(() => {
444
+ render();
445
+ });
446
+
447
+ const unsubAuth = identity.subscribeAuth((user) => {
448
+ clientUser = user;
449
+ render();
450
+ });
451
+
452
+ render();
453
+
333
454
  return {
334
455
  element: host,
335
456
  dispose() {
336
457
  unsubscribe();
458
+ unsubLens();
459
+ unsubAuth();
460
+ documentLike.removeEventListener('astro:after-swap', reattachAfterAstroSwap);
461
+ dialogController.dispose();
337
462
  host.remove();
338
463
  },
339
464
  };