@pikku/cli 0.12.126 → 0.12.127

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 (254) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/console-app/assets/{abnfDiagram-N423BO3Z-B2suyn6i.js → abnfDiagram-N423BO3Z-BY2LM8wi.js} +1 -1
  3. package/console-app/assets/architecture-TIHT7OUA-CWwmvxZF.js +1 -0
  4. package/console-app/assets/{architectureDiagram-T3A2C74G-BQ5Dfvpo.js → architectureDiagram-T3A2C74G-CeqjY3Kw.js} +1 -1
  5. package/console-app/assets/{blockDiagram-VBNYF7ZC-D4pVRDiF.js → blockDiagram-VBNYF7ZC-BW5174xj.js} +1 -1
  6. package/console-app/assets/{c4Diagram-5PPSVZJV-Da04jGpq.js → c4Diagram-5PPSVZJV-B7zXAFL0.js} +1 -1
  7. package/console-app/assets/channel-pOkwZ_Ot.js +1 -0
  8. package/console-app/assets/{chunk-2GRJ4B5K-CwODIPP4.js → chunk-2GRJ4B5K-BfRYzQ4t.js} +1 -1
  9. package/console-app/assets/{chunk-4I5QYGJK-Bep4akjR.js → chunk-4I5QYGJK-DBA7-Nu4.js} +1 -1
  10. package/console-app/assets/{chunk-5RXB4S5H-CGyCRU9L.js → chunk-5RXB4S5H-D03lNzwi.js} +1 -1
  11. package/console-app/assets/{chunk-6Q2QTUOP-D0IK0SMT.js → chunk-6Q2QTUOP-DloGRHJZ.js} +1 -1
  12. package/console-app/assets/{chunk-7Z6QIM7H-D12vS1jX.js → chunk-7Z6QIM7H-DH3uHtl2.js} +1 -1
  13. package/console-app/assets/{chunk-GF5L2VYU-kOLwTzIA.js → chunk-GF5L2VYU-Cu252lza.js} +1 -1
  14. package/console-app/assets/{chunk-I66GZJ75-Cb2nDoa3.js → chunk-I66GZJ75-DH54FcuO.js} +1 -1
  15. package/console-app/assets/{chunk-JQJVKLGR-B3a_ctfQ.js → chunk-JQJVKLGR-CeFuTL-V.js} +1 -1
  16. package/console-app/assets/{chunk-KBJHAD2P-DeP2Lqwp.js → chunk-KBJHAD2P-B-prFo0-.js} +1 -1
  17. package/console-app/assets/{chunk-NSK5VX7P-BO8vlGrO.js → chunk-NSK5VX7P-C10iA4GS.js} +1 -1
  18. package/console-app/assets/{chunk-QR6OTTB3-sX5V0Lok.js → chunk-QR6OTTB3-Cd8apAsA.js} +1 -1
  19. package/console-app/assets/{chunk-RYQCIY6F-DoCObEhk.js → chunk-RYQCIY6F-rfPUp2Fj.js} +1 -1
  20. package/console-app/assets/{chunk-UBXNYLIW-BndMXU5r.js → chunk-UBXNYLIW-D25wqJBc.js} +1 -1
  21. package/console-app/assets/{chunk-W5SLKNZC--VrZN8EC.js → chunk-W5SLKNZC-CJvxkxuK.js} +1 -1
  22. package/console-app/assets/{chunk-WRU74C26-DdS0mzXO.js → chunk-WRU74C26-B9Wju92P.js} +1 -1
  23. package/console-app/assets/chunk-XXDRQBXY-BU_UP6f5.js +1 -0
  24. package/console-app/assets/classDiagram-JCYQIIEL-CLBKUuxj.js +1 -0
  25. package/console-app/assets/classDiagram-v2-OCEON4UE-CLBKUuxj.js +1 -0
  26. package/console-app/assets/{cose-bilkent-JH36ORCC-C5EnHkFn.js → cose-bilkent-JH36ORCC-CwA1VCP5.js} +1 -1
  27. package/console-app/assets/{cynefin-VYW2F7L2-9irdkTt4.js → cynefin-VYW2F7L2-C_qsD7eR.js} +1 -1
  28. package/console-app/assets/{cynefinDiagram-MW4NZA55-DY19660c.js → cynefinDiagram-MW4NZA55-CkSLreFW.js} +1 -1
  29. package/console-app/assets/{dagre-VZM6K2ZE-BYFZSaSb.js → dagre-VZM6K2ZE-0ssqLoHs.js} +1 -1
  30. package/console-app/assets/{dagre-nXgDYqvf.js → dagre-WqgBlKb7.js} +1 -1
  31. package/console-app/assets/{diagram-7IWD3JNH-oDftiTp1.js → diagram-7IWD3JNH-DmRL3lmL.js} +1 -1
  32. package/console-app/assets/{diagram-B4RE2ZJO-Cbj-pPbH.js → diagram-B4RE2ZJO-Bsr9wG4I.js} +1 -1
  33. package/console-app/assets/{diagram-LBJQPF4R-Ch53oSKw.js → diagram-LBJQPF4R-DdMw1FSY.js} +1 -1
  34. package/console-app/assets/{diagram-Q27KOJAE-DA7K814v.js → diagram-Q27KOJAE-TPx5TB2B.js} +1 -1
  35. package/console-app/assets/{diagram-UB23O5K3-B-_C-ctS.js → diagram-UB23O5K3-e_1zSlZR.js} +1 -1
  36. package/console-app/assets/{ebnfDiagram-BXEA7PRR-DsOdsKXy.js → ebnfDiagram-BXEA7PRR-BACajh2b.js} +1 -1
  37. package/console-app/assets/{erDiagram-JOGREHBK-XB1mP5_A.js → erDiagram-JOGREHBK-CojomKqL.js} +1 -1
  38. package/console-app/assets/eventmodeling-45OFAUF4-DkN2KCrT.js +1 -0
  39. package/console-app/assets/flowDiagram-UKHOOZJN-DL0M9lBc.js +1 -0
  40. package/console-app/assets/{ganttDiagram-PKOTCBZU-knk0XSHi.js → ganttDiagram-PKOTCBZU-yoOX4Xj2.js} +1 -1
  41. package/console-app/assets/{gitGraph-TEB2WS4Q-COJnK2tM.js → gitGraph-TEB2WS4Q-BcUY5hIc.js} +1 -1
  42. package/console-app/assets/{gitGraphDiagram-DS77QQ5N-sF0v605q.js → gitGraphDiagram-DS77QQ5N-BtuIPjuB.js} +1 -1
  43. package/console-app/assets/{index-DMnbsgzs.js → index-CzWW052c.js} +151 -151
  44. package/console-app/assets/{info-DKCQHKI2-Cbatr0w6.js → info-DKCQHKI2-B-iR9PUz.js} +1 -1
  45. package/console-app/assets/{infoDiagram-6WML65LV-93TFPCu2.js → infoDiagram-6WML65LV-CuXKIFH2.js} +1 -1
  46. package/console-app/assets/{ishikawaDiagram-WSZJBQD7-BBR8_Qms.js → ishikawaDiagram-WSZJBQD7-CSueMFD6.js} +1 -1
  47. package/console-app/assets/{journeyDiagram-NVQOT4AX-zG55yDoc.js → journeyDiagram-NVQOT4AX-kvnKStZp.js} +1 -1
  48. package/console-app/assets/{kanban-definition-27J2QSJJ-DonGcEAY.js → kanban-definition-27J2QSJJ-CGGDEz30.js} +1 -1
  49. package/console-app/assets/{line-D1WdVm1S.js → line-mtMM5-xO.js} +1 -1
  50. package/console-app/assets/{linear-D2GQL4Cm.js → linear-CLSje0O_.js} +1 -1
  51. package/console-app/assets/{mermaid-parser.core-b4yKyO56.js → mermaid-parser.core-Cx6yvn3j.js} +3 -3
  52. package/console-app/assets/{mermaid.core-Cwfec1gr.js → mermaid.core-BebGyklS.js} +4 -4
  53. package/console-app/assets/{mindmap-definition-FAOFIHXS-D0G4yKgw.js → mindmap-definition-FAOFIHXS-C2_WUUJ9.js} +1 -1
  54. package/console-app/assets/{packet-7NZHBO7P-DDa4HL2T.js → packet-7NZHBO7P-Dh5yNCA8.js} +1 -1
  55. package/console-app/assets/{pegDiagram-VL7TDLO6-fPdN5VZs.js → pegDiagram-VL7TDLO6-XgUxesi8.js} +1 -1
  56. package/console-app/assets/{pie-RZYD4A2V-DRHURUqo.js → pie-RZYD4A2V-D2x2RAXI.js} +1 -1
  57. package/console-app/assets/{pieDiagram-7S7Q4E2Y-DMYn8ga_.js → pieDiagram-7S7Q4E2Y-Bbor0KbG.js} +1 -1
  58. package/console-app/assets/{quadrantDiagram-CIZ2JOQS-C190OamC.js → quadrantDiagram-CIZ2JOQS-DZmnMHpM.js} +1 -1
  59. package/console-app/assets/{radar-I7S5WNFK-Djvqzz9A.js → radar-I7S5WNFK-CPeriDtN.js} +1 -1
  60. package/console-app/assets/{railroad-3IZDKUUU-C9YvFeFq.js → railroad-3IZDKUUU-2iKAyaie.js} +1 -1
  61. package/console-app/assets/railroad-abnf-AHOZXSZD-D26xz4MM.js +1 -0
  62. package/console-app/assets/railroad-ebnf-EBAXGLYW-CCAiMPWc.js +1 -0
  63. package/console-app/assets/railroad-peg-LSFZ7HO6-BA1zcisq.js +1 -0
  64. package/console-app/assets/{railroadDiagram-AXF67PYL-IRFg1VrU.js → railroadDiagram-AXF67PYL-DVEqCXoo.js} +1 -1
  65. package/console-app/assets/{requirementDiagram-LRYGKXZP-L-7ubbcT.js → requirementDiagram-LRYGKXZP-CSgSNL8p.js} +1 -1
  66. package/console-app/assets/{sankeyDiagram-W5VNT64P-DBttV6Gt.js → sankeyDiagram-W5VNT64P-CFk11odN.js} +1 -1
  67. package/console-app/assets/{sequenceDiagram-SI44F4Z6-Bg15oKAB.js → sequenceDiagram-SI44F4Z6-Cb5u6FsJ.js} +1 -1
  68. package/console-app/assets/{src-DUC7tLWb.js → src-LceHEY_Q.js} +1 -1
  69. package/console-app/assets/{stateDiagram-OKZ733FA-PWl0XGs5.js → stateDiagram-OKZ733FA-DM1jWlkU.js} +1 -1
  70. package/console-app/assets/stateDiagram-v2-UEYNNEHI-COVnPYic.js +1 -0
  71. package/console-app/assets/{swimlanes-SLNWSIFB-CyXEtGBV.js → swimlanes-SLNWSIFB-DD6MchlE.js} +1 -1
  72. package/console-app/assets/swimlanesDiagram-ULZ7WXOC-B5q8iRCQ.js +8 -0
  73. package/console-app/assets/{timeline-definition-Z64GVDOM-BLA-DhBt.js → timeline-definition-Z64GVDOM-zu5cNnVv.js} +1 -1
  74. package/console-app/assets/{treeView-QDETBFTQ-Bfnmn2UY.js → treeView-QDETBFTQ-D_4IbvCG.js} +1 -1
  75. package/console-app/assets/{treemap-6X3UGDF4-DTA0wveO.js → treemap-6X3UGDF4-DNc6bjUc.js} +1 -1
  76. package/console-app/assets/{vennDiagram-T6HMQDX7-CLXYZln0.js → vennDiagram-T6HMQDX7-DfqoG28f.js} +1 -1
  77. package/console-app/assets/{wardley-OPB4EBWU-zwxqisG0.js → wardley-OPB4EBWU-BqpI2Lx-.js} +1 -1
  78. package/console-app/assets/{wardleyDiagram-T6FBY63Y-hKtKvNlv.js → wardleyDiagram-T6FBY63Y-CLIZSvNi.js} +1 -1
  79. package/console-app/assets/{xychartDiagram-ELKLHX3M-BGf8p4bo.js → xychartDiagram-ELKLHX3M-Cni-XXa6.js} +1 -1
  80. package/console-app/index.html +1 -1
  81. package/dist/.pikku/addon/index.d.ts +1 -1
  82. package/dist/.pikku/addon/index.js +1 -1
  83. package/dist/.pikku/addon/pikku-addon-types.gen.d.ts +1 -1
  84. package/dist/.pikku/addon/pikku-addon-types.gen.js +1 -1
  85. package/dist/.pikku/agent/index.d.ts +1 -1
  86. package/dist/.pikku/agent/index.js +1 -1
  87. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  88. package/dist/.pikku/agent/pikku-model-aliases.gen.js +1 -1
  89. package/dist/.pikku/auth/index.d.ts +1 -1
  90. package/dist/.pikku/auth/index.js +1 -1
  91. package/dist/.pikku/auth/pikku-auth-types.gen.d.ts +1 -1
  92. package/dist/.pikku/auth/pikku-auth-types.gen.js +1 -1
  93. package/dist/.pikku/channel/index.d.ts +1 -1
  94. package/dist/.pikku/channel/index.js +1 -1
  95. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  96. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  97. package/dist/.pikku/cli/index.d.ts +1 -1
  98. package/dist/.pikku/cli/index.js +1 -1
  99. package/dist/.pikku/cli/pikku-cli-channel.js +21 -1
  100. package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
  101. package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
  102. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
  103. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
  104. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.json +103 -0
  105. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  106. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  107. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  108. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +103 -0
  109. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  110. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  111. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  112. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  113. package/dist/.pikku/error/index.d.ts +1 -1
  114. package/dist/.pikku/error/index.js +1 -1
  115. package/dist/.pikku/error/pikku-error-types.gen.d.ts +1 -1
  116. package/dist/.pikku/error/pikku-error-types.gen.js +1 -1
  117. package/dist/.pikku/function/index.d.ts +1 -1
  118. package/dist/.pikku/function/index.js +1 -1
  119. package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
  120. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  121. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  122. package/dist/.pikku/function/pikku-functions-meta.gen.json +79 -3
  123. package/dist/.pikku/function/pikku-functions.gen.js +1 -1
  124. package/dist/.pikku/gateway/index.d.ts +1 -1
  125. package/dist/.pikku/gateway/index.js +1 -1
  126. package/dist/.pikku/gateway/pikku-gateway-types.gen.d.ts +1 -1
  127. package/dist/.pikku/gateway/pikku-gateway-types.gen.js +1 -1
  128. package/dist/.pikku/http/index.d.ts +1 -1
  129. package/dist/.pikku/http/index.js +1 -1
  130. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  131. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  132. package/dist/.pikku/mcp/index.d.ts +1 -1
  133. package/dist/.pikku/mcp/index.js +1 -1
  134. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  135. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  136. package/dist/.pikku/middleware/index.d.ts +1 -1
  137. package/dist/.pikku/middleware/index.js +1 -1
  138. package/dist/.pikku/middleware/pikku-middleware-types.gen.d.ts +1 -1
  139. package/dist/.pikku/middleware/pikku-middleware-types.gen.js +1 -1
  140. package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +1 -1
  141. package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +1 -1
  142. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  143. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  144. package/dist/.pikku/pikku-services.gen.d.ts +1 -1
  145. package/dist/.pikku/queue/index.d.ts +1 -1
  146. package/dist/.pikku/queue/index.js +1 -1
  147. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  148. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  149. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  150. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  151. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  152. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  153. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +4 -0
  154. package/dist/.pikku/scenarios/index.d.ts +1 -1
  155. package/dist/.pikku/scenarios/index.js +1 -1
  156. package/dist/.pikku/scenarios/pikku-personas.gen.js +1 -1
  157. package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
  158. package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
  159. package/dist/.pikku/scenarios/pikku-scenario-types.gen.d.ts +1 -1
  160. package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
  161. package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
  162. package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
  163. package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
  164. package/dist/.pikku/scheduler/index.d.ts +1 -1
  165. package/dist/.pikku/scheduler/index.js +1 -1
  166. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  167. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  168. package/dist/.pikku/schemas/register.gen.js +17 -1
  169. package/dist/.pikku/schemas/schemas/FabricFindingsClearInput.schema.json +1 -0
  170. package/dist/.pikku/schemas/schemas/FabricFindingsClearOutput.schema.json +1 -0
  171. package/dist/.pikku/schemas/schemas/FabricFindingsFlushInput.schema.json +1 -0
  172. package/dist/.pikku/schemas/schemas/FabricFindingsFlushOutput.schema.json +1 -0
  173. package/dist/.pikku/schemas/schemas/FabricFindingsListInput.schema.json +1 -0
  174. package/dist/.pikku/schemas/schemas/FabricFindingsListOutput.schema.json +1 -0
  175. package/dist/.pikku/schemas/schemas/FabricReportInput.schema.json +1 -0
  176. package/dist/.pikku/schemas/schemas/FabricReportOutput.schema.json +1 -0
  177. package/dist/.pikku/scopes/index.d.ts +1 -1
  178. package/dist/.pikku/scopes/index.js +1 -1
  179. package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
  180. package/dist/.pikku/scopes/pikku-roles.gen.d.ts +1 -1
  181. package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
  182. package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
  183. package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
  184. package/dist/.pikku/secrets/index.d.ts +1 -1
  185. package/dist/.pikku/secrets/index.js +1 -1
  186. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  187. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  188. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  189. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  190. package/dist/.pikku/services/pikku-meta-service.gen.d.ts +1 -1
  191. package/dist/.pikku/services/pikku-meta-service.gen.js +1 -1
  192. package/dist/.pikku/setup/index.d.ts +1 -1
  193. package/dist/.pikku/setup/index.js +1 -1
  194. package/dist/.pikku/setup/pikku-setup-types.gen.d.ts +1 -1
  195. package/dist/.pikku/setup/pikku-setup-types.gen.js +1 -1
  196. package/dist/.pikku/trigger/index.d.ts +1 -1
  197. package/dist/.pikku/trigger/index.js +1 -1
  198. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  199. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  200. package/dist/.pikku/variables/index.d.ts +1 -1
  201. package/dist/.pikku/variables/index.js +1 -1
  202. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  203. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  204. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  205. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  206. package/dist/.pikku/workflow/index.d.ts +1 -1
  207. package/dist/.pikku/workflow/index.js +1 -1
  208. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  209. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  210. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  211. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  212. package/dist/bin/pikku-bin.mjs +2 -2
  213. package/dist/src/fabric/fabric-commands.d.ts +138 -0
  214. package/dist/src/fabric/fabric-commands.js +65 -0
  215. package/dist/src/fabric/functions/findings-clear.function.d.ts +12 -0
  216. package/dist/src/fabric/functions/findings-clear.function.js +17 -0
  217. package/dist/src/fabric/functions/findings-flush.function.d.ts +33 -0
  218. package/dist/src/fabric/functions/findings-flush.function.js +36 -0
  219. package/dist/src/fabric/functions/findings-list.function.d.ts +55 -0
  220. package/dist/src/fabric/functions/findings-list.function.js +52 -0
  221. package/dist/src/fabric/functions/report.function.d.ts +121 -0
  222. package/dist/src/fabric/functions/report.function.js +84 -0
  223. package/dist/src/fabric/lib/finding-spool.d.ts +56 -0
  224. package/dist/src/fabric/lib/finding-spool.js +105 -0
  225. package/dist/src/fabric/lib/finding.d.ts +92 -0
  226. package/dist/src/fabric/lib/finding.js +156 -0
  227. package/dist/src/fabric/lib/report-environment.d.ts +53 -0
  228. package/dist/src/fabric/lib/report-environment.js +119 -0
  229. package/dist/src/functions/commands/environment.d.ts +5 -0
  230. package/dist/src/functions/commands/persona.js +1 -0
  231. package/dist/src/functions/commands/scenario.js +1 -0
  232. package/dist/src/functions/validate/auth-plugin-checks.d.ts +1 -1
  233. package/dist/src/functions/validate/auth-plugin-checks.js +8 -5
  234. package/dist/src/functions/validate/persona-checks.js +8 -6
  235. package/dist/src/functions/wirings/user-admin/pikku-command-user-admin-functions.js +10 -5
  236. package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.d.ts +1 -1
  237. package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.js +3 -3
  238. package/dist/src/services.js +9 -0
  239. package/dist/tsconfig.tsbuildinfo +1 -1
  240. package/package.json +8 -8
  241. package/snippets.json +1 -1
  242. package/surface.json +2 -2
  243. package/console-app/assets/architecture-TIHT7OUA-DmG0bXDT.js +0 -1
  244. package/console-app/assets/channel-BgCT5gon.js +0 -1
  245. package/console-app/assets/chunk-XXDRQBXY-EP2C9tTO.js +0 -1
  246. package/console-app/assets/classDiagram-JCYQIIEL-D9wGqB4J.js +0 -1
  247. package/console-app/assets/classDiagram-v2-OCEON4UE-D9wGqB4J.js +0 -1
  248. package/console-app/assets/eventmodeling-45OFAUF4-NKFCZ8Fj.js +0 -1
  249. package/console-app/assets/flowDiagram-UKHOOZJN-BpdPkmum.js +0 -1
  250. package/console-app/assets/railroad-abnf-AHOZXSZD-B3CYVW4p.js +0 -1
  251. package/console-app/assets/railroad-ebnf-EBAXGLYW-DrZ2yF62.js +0 -1
  252. package/console-app/assets/railroad-peg-LSFZ7HO6-CWAmMyxd.js +0 -1
  253. package/console-app/assets/stateDiagram-v2-UEYNNEHI-Celbgz4u.js +0 -1
  254. package/console-app/assets/swimlanesDiagram-ULZ7WXOC-zxpNaB4U.js +0 -8
@@ -0,0 +1,92 @@
1
+ import { z } from 'zod';
2
+ import type { ReportEnvironment } from './report-environment.js';
3
+ export declare const FindingInput: z.ZodObject<{
4
+ title: z.ZodString;
5
+ kind: z.ZodEnum<{
6
+ product: "product";
7
+ harness: "harness";
8
+ }>;
9
+ model: z.ZodString;
10
+ expected: z.ZodString;
11
+ actual: z.ZodString;
12
+ skill: z.ZodOptional<z.ZodString>;
13
+ passage: z.ZodOptional<z.ZodString>;
14
+ command: z.ZodOptional<z.ZodString>;
15
+ error: z.ZodOptional<z.ZodString>;
16
+ repro: z.ZodOptional<z.ZodString>;
17
+ workaround: z.ZodOptional<z.ZodString>;
18
+ proposal: z.ZodOptional<z.ZodString>;
19
+ tried: z.ZodOptional<z.ZodString>;
20
+ unresolved: z.ZodOptional<z.ZodBoolean>;
21
+ area: z.ZodOptional<z.ZodString>;
22
+ surface: z.ZodOptional<z.ZodEnum<{
23
+ local: "local";
24
+ deployed: "deployed";
25
+ both: "both";
26
+ }>>;
27
+ cost: z.ZodOptional<z.ZodString>;
28
+ run: z.ZodOptional<z.ZodString>;
29
+ deployTarget: z.ZodOptional<z.ZodString>;
30
+ }, z.core.$strip>;
31
+ export type FindingInput = z.infer<typeof FindingInput>;
32
+ export type ParsedFinding = {
33
+ finding: FindingInput;
34
+ } | {
35
+ problems: string[];
36
+ };
37
+ /** Shape-check a finding from either path, naming every field that is wrong. */
38
+ export declare function parseFinding(value: unknown): ParsedFinding;
39
+ /**
40
+ * A finding read as JSON rather than assembled out of flags.
41
+ *
42
+ * Half the fields are prose, and prose carries apostrophes, quotes, backticks
43
+ * and newlines — every one of them a shell metacharacter before it is a
44
+ * character in a sentence. An error message pasted into `--error` breaks the
45
+ * command at its first newline; one carrying a backtick runs whatever follows
46
+ * it. JSON has its own escaping, so this path has none of that.
47
+ *
48
+ * Returns the finding or the problems with it, never throws: a malformed
49
+ * payload is a usage mistake worth naming precisely.
50
+ */
51
+ export declare function parseFindingJson(raw: string): ParsedFinding;
52
+ export interface FindingPayload extends Omit<FindingInput, 'run'> {
53
+ runId?: string;
54
+ environment: ReportEnvironment;
55
+ reportedAt: string;
56
+ }
57
+ /**
58
+ * The rules the field set exists to enforce, checked before anything is sent.
59
+ *
60
+ * A usage mistake is the agent's own and is worth failing loudly for — unlike a
61
+ * failed send, which must never surface as a build failure. Every problem is
62
+ * returned at once so a malformed call is fixed in one pass.
63
+ */
64
+ export declare function validateFinding(input: FindingInput): string[];
65
+ export declare function buildFindingPayload(input: FindingInput, environment: ReportEnvironment, now?: Date): FindingPayload;
66
+ /**
67
+ * Best-effort by construction. A finding is worth having and never worth
68
+ * failing a build for, so a refused, slow or unreachable endpoint is reported
69
+ * to the terminal and swallowed.
70
+ */
71
+ export declare function postFinding(opts: {
72
+ apiUrl: string;
73
+ token: string;
74
+ /**
75
+ * Provenance, not a routing key. A finding is about the framework rather
76
+ * than about anyone's project, and the reports worth having most — a
77
+ * scaffold that never produced a config, a first run that went wrong — come
78
+ * from checkouts that have no project to name.
79
+ */
80
+ projectId: string | null;
81
+ payload: FindingPayload;
82
+ timeoutMs?: number;
83
+ }): Promise<{
84
+ sent: boolean;
85
+ reason?: string;
86
+ }>;
87
+ /**
88
+ * The receipt. Nothing is written to disk, so the terminal is the only place
89
+ * the user sees what left their machine. Printed before the request goes out,
90
+ * so it is there whether or not the send succeeds.
91
+ */
92
+ export declare function renderReceipt(payload: FindingPayload): string;
@@ -0,0 +1,156 @@
1
+ import { z } from 'zod';
2
+ export const FindingInput = z.object({
3
+ title: z.string(),
4
+ kind: z.enum(['product', 'harness']),
5
+ model: z.string(),
6
+ expected: z.string(),
7
+ actual: z.string(),
8
+ skill: z.string().optional(),
9
+ passage: z.string().optional(),
10
+ command: z.string().optional(),
11
+ error: z.string().optional(),
12
+ repro: z.string().optional(),
13
+ workaround: z.string().optional(),
14
+ proposal: z.string().optional(),
15
+ tried: z.string().optional(),
16
+ unresolved: z.boolean().optional(),
17
+ area: z.string().optional(),
18
+ surface: z.enum(['local', 'deployed', 'both']).optional(),
19
+ cost: z.string().optional(),
20
+ run: z.string().optional(),
21
+ deployTarget: z.string().optional(),
22
+ });
23
+ /** Shape-check a finding from either path, naming every field that is wrong. */
24
+ export function parseFinding(value) {
25
+ const result = FindingInput.safeParse(value);
26
+ if (result.success)
27
+ return { finding: result.data };
28
+ return {
29
+ problems: result.error.issues.map((issue) => `${issue.path.join('.') || 'finding'}: ${issue.message}`),
30
+ };
31
+ }
32
+ /**
33
+ * A finding read as JSON rather than assembled out of flags.
34
+ *
35
+ * Half the fields are prose, and prose carries apostrophes, quotes, backticks
36
+ * and newlines — every one of them a shell metacharacter before it is a
37
+ * character in a sentence. An error message pasted into `--error` breaks the
38
+ * command at its first newline; one carrying a backtick runs whatever follows
39
+ * it. JSON has its own escaping, so this path has none of that.
40
+ *
41
+ * Returns the finding or the problems with it, never throws: a malformed
42
+ * payload is a usage mistake worth naming precisely.
43
+ */
44
+ export function parseFindingJson(raw) {
45
+ let parsed;
46
+ try {
47
+ parsed = JSON.parse(raw);
48
+ }
49
+ catch (error) {
50
+ return {
51
+ problems: [`--stdin expected a JSON object (${error.message}).`],
52
+ };
53
+ }
54
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
55
+ return { problems: ['--stdin expected a JSON object.'] };
56
+ }
57
+ return parseFinding(parsed);
58
+ }
59
+ /**
60
+ * The rules the field set exists to enforce, checked before anything is sent.
61
+ *
62
+ * A usage mistake is the agent's own and is worth failing loudly for — unlike a
63
+ * failed send, which must never surface as a build failure. Every problem is
64
+ * returned at once so a malformed call is fixed in one pass.
65
+ */
66
+ export function validateFinding(input) {
67
+ const problems = [];
68
+ if (input.kind === 'harness' && !input.skill) {
69
+ problems.push('A harness finding names the skill that misled you — pass --skill (and --passage for the line it contradicts).');
70
+ }
71
+ if (input.unresolved) {
72
+ if (!input.tried) {
73
+ problems.push('An unresolved finding carries what you tried and how each attempt failed — pass --tried.');
74
+ }
75
+ if (input.workaround) {
76
+ problems.push('Unresolved means no workaround was found. Drop --unresolved, or drop --workaround.');
77
+ }
78
+ }
79
+ else if (!input.workaround && !input.proposal) {
80
+ problems.push('A resolved finding carries the workaround you used — pass --workaround, or --unresolved if there was none.');
81
+ }
82
+ return problems;
83
+ }
84
+ export function buildFindingPayload(input, environment, now = new Date()) {
85
+ const { run, ...rest } = input;
86
+ return { ...rest, runId: run, environment, reportedAt: now.toISOString() };
87
+ }
88
+ /**
89
+ * Best-effort by construction. A finding is worth having and never worth
90
+ * failing a build for, so a refused, slow or unreachable endpoint is reported
91
+ * to the terminal and swallowed.
92
+ */
93
+ export async function postFinding(opts) {
94
+ try {
95
+ const response = await fetch(`${opts.apiUrl}/findings`, {
96
+ method: 'POST',
97
+ headers: {
98
+ 'content-type': 'application/json',
99
+ authorization: `Bearer ${opts.token}`,
100
+ },
101
+ body: JSON.stringify({
102
+ projectId: opts.projectId,
103
+ finding: opts.payload,
104
+ }),
105
+ signal: AbortSignal.timeout(opts.timeoutMs ?? 5000),
106
+ });
107
+ if (!response.ok) {
108
+ return { sent: false, reason: `fabric answered ${response.status}` };
109
+ }
110
+ return { sent: true };
111
+ }
112
+ catch (error) {
113
+ return { sent: false, reason: error?.message ?? 'request failed' };
114
+ }
115
+ }
116
+ /**
117
+ * The receipt. Nothing is written to disk, so the terminal is the only place
118
+ * the user sees what left their machine. Printed before the request goes out,
119
+ * so it is there whether or not the send succeeds.
120
+ */
121
+ export function renderReceipt(payload) {
122
+ const lines = [`[fabric] reporting: ${payload.title}`];
123
+ const field = (label, value) => {
124
+ if (value)
125
+ lines.push(` ${label}: ${value}`);
126
+ };
127
+ field('kind', payload.unresolved ? `${payload.kind} (unresolved)` : payload.kind);
128
+ field('area', payload.area);
129
+ field('skill', payload.passage ? `${payload.skill} — ${payload.passage}` : payload.skill);
130
+ field('command', payload.command);
131
+ field('expected', payload.expected);
132
+ field('actual', payload.actual);
133
+ field('error', payload.error);
134
+ field('surface', payload.surface);
135
+ field('cost', payload.cost);
136
+ field('repro', payload.repro);
137
+ field('workaround', payload.workaround);
138
+ field('tried', payload.tried);
139
+ field('proposal', payload.proposal);
140
+ field('model', payload.model);
141
+ field('run', payload.runId);
142
+ field('deploy target', payload.deployTarget);
143
+ field('reported at', payload.reportedAt);
144
+ const env = payload.environment;
145
+ field('versions', env.packages
146
+ .map((p) => `${p.name}@${p.version}${p.linked ? ' (linked)' : ''}`)
147
+ .join(' ') || 'no @pikku/* found');
148
+ if (env.versionSkew) {
149
+ lines.push(' note: the installed @pikku/* versions are not all the same');
150
+ }
151
+ if (env.linkedFramework) {
152
+ lines.push(' note: an @pikku/* resolves to a workspace or link — this app is running framework code that may be modified');
153
+ }
154
+ field('runtime', `node ${env.node} ${env.platform} ${env.packageManager ?? ''}`.trim());
155
+ return lines.join('\n');
156
+ }
@@ -0,0 +1,53 @@
1
+ /** One installed `@pikku/*` package as it actually resolves on disk. */
2
+ export interface PikkuPackageVersion {
3
+ name: string;
4
+ version: string;
5
+ /**
6
+ * Resolved through a symlink — a yarn workspace or a `yarn link`ed checkout
7
+ * rather than a published tarball. The framework is read-only during a build
8
+ * run, so a linked package is code that may already have been modified, and a
9
+ * finding describing it is describing something other than a release.
10
+ */
11
+ linked: boolean;
12
+ }
13
+ export interface ReportEnvironment {
14
+ packages: PikkuPackageVersion[];
15
+ /**
16
+ * The resolved `@pikku/*` versions are not all the same. Pinning the CLI does
17
+ * not pin its `@pikku/*` dependencies, so a mixed tree is a common cause of
18
+ * behaviour that looks like a framework bug.
19
+ */
20
+ versionSkew: boolean;
21
+ /** Any package is `linked` — see {@link PikkuPackageVersion.linked}. */
22
+ linkedFramework: boolean;
23
+ node: string;
24
+ packageManager: string | null;
25
+ platform: string;
26
+ }
27
+ /**
28
+ * Walk up from `startDir` for the first `node_modules/@pikku` that holds
29
+ * packages. A monorepo hoists to the root, an app installs locally, and either
30
+ * way the nearest populated scope is the one that was loaded.
31
+ *
32
+ * Populated means holding something `readPikkuPackages` would read, so the
33
+ * hidden entries it skips cannot qualify a scope either: a stray `.DS_Store` in
34
+ * an empty nested scope would otherwise end the walk there and report a tree
35
+ * with no packages in it.
36
+ */
37
+ export declare function findPikkuScope(startDir: string): Promise<string | null>;
38
+ /**
39
+ * Versions read off the installed tree rather than out of `package.json`. A
40
+ * range like `^0.12.35` says nothing about what ran, and the version that ran
41
+ * is the only one worth reporting.
42
+ */
43
+ export declare function readPikkuPackages(scopeDir: string): Promise<PikkuPackageVersion[]>;
44
+ /**
45
+ * `packageManager` in the nearest manifest is authoritative when it is set;
46
+ * otherwise the lockfile is the only evidence of what installed the tree.
47
+ */
48
+ export declare function detectPackageManager(startDir: string): Promise<string | null>;
49
+ /**
50
+ * Everything about the run a finding needs and no agent should be asked for.
51
+ * All of it is a directory read — no network, no prompting.
52
+ */
53
+ export declare function collectReportEnvironment(startDir?: string): Promise<ReportEnvironment>;
@@ -0,0 +1,119 @@
1
+ import { readFile, lstat, readdir } from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ /**
5
+ * Walk up from `startDir` for the first `node_modules/@pikku` that holds
6
+ * packages. A monorepo hoists to the root, an app installs locally, and either
7
+ * way the nearest populated scope is the one that was loaded.
8
+ *
9
+ * Populated means holding something `readPikkuPackages` would read, so the
10
+ * hidden entries it skips cannot qualify a scope either: a stray `.DS_Store` in
11
+ * an empty nested scope would otherwise end the walk there and report a tree
12
+ * with no packages in it.
13
+ */
14
+ export async function findPikkuScope(startDir) {
15
+ let dir = startDir;
16
+ while (true) {
17
+ const candidate = join(dir, 'node_modules', '@pikku');
18
+ if (existsSync(candidate)) {
19
+ const entries = await readdir(candidate).catch(() => []);
20
+ if (entries.some((entry) => !entry.startsWith('.')))
21
+ return candidate;
22
+ }
23
+ const parent = dirname(dir);
24
+ if (parent === dir)
25
+ return null;
26
+ dir = parent;
27
+ }
28
+ }
29
+ /**
30
+ * Versions read off the installed tree rather than out of `package.json`. A
31
+ * range like `^0.12.35` says nothing about what ran, and the version that ran
32
+ * is the only one worth reporting.
33
+ */
34
+ export async function readPikkuPackages(scopeDir) {
35
+ const entries = await readdir(scopeDir).catch(() => []);
36
+ const packages = [];
37
+ for (const entry of entries.sort()) {
38
+ if (entry.startsWith('.'))
39
+ continue;
40
+ const packageDir = join(scopeDir, entry);
41
+ const manifest = join(packageDir, 'package.json');
42
+ const raw = await readFile(manifest, 'utf8').catch(() => null);
43
+ if (!raw)
44
+ continue;
45
+ let version;
46
+ try {
47
+ version = JSON.parse(raw).version;
48
+ }
49
+ catch {
50
+ continue;
51
+ }
52
+ if (typeof version !== 'string')
53
+ continue;
54
+ const stats = await lstat(packageDir).catch(() => null);
55
+ packages.push({
56
+ name: `@pikku/${entry}`,
57
+ version,
58
+ linked: stats?.isSymbolicLink() ?? false,
59
+ });
60
+ }
61
+ return packages;
62
+ }
63
+ const LOCKFILES = [
64
+ ['yarn.lock', 'yarn'],
65
+ ['pnpm-lock.yaml', 'pnpm'],
66
+ ['bun.lockb', 'bun'],
67
+ ['bun.lock', 'bun'],
68
+ ['package-lock.json', 'npm'],
69
+ ];
70
+ /**
71
+ * `packageManager` in the nearest manifest is authoritative when it is set;
72
+ * otherwise the lockfile is the only evidence of what installed the tree.
73
+ */
74
+ export async function detectPackageManager(startDir) {
75
+ let dir = startDir;
76
+ while (true) {
77
+ const manifest = join(dir, 'package.json');
78
+ if (existsSync(manifest)) {
79
+ const raw = await readFile(manifest, 'utf8').catch(() => null);
80
+ if (raw) {
81
+ try {
82
+ const declared = JSON.parse(raw)
83
+ .packageManager;
84
+ if (typeof declared === 'string' && declared.length > 0) {
85
+ return declared;
86
+ }
87
+ }
88
+ catch {
89
+ // An unparseable manifest tells us nothing; keep walking up.
90
+ }
91
+ }
92
+ }
93
+ for (const [lockfile, manager] of LOCKFILES) {
94
+ if (existsSync(join(dir, lockfile)))
95
+ return manager;
96
+ }
97
+ const parent = dirname(dir);
98
+ if (parent === dir)
99
+ return null;
100
+ dir = parent;
101
+ }
102
+ }
103
+ /**
104
+ * Everything about the run a finding needs and no agent should be asked for.
105
+ * All of it is a directory read — no network, no prompting.
106
+ */
107
+ export async function collectReportEnvironment(startDir = process.cwd()) {
108
+ const scope = await findPikkuScope(startDir);
109
+ const packages = scope ? await readPikkuPackages(scope) : [];
110
+ const versions = new Set(packages.map((p) => p.version));
111
+ return {
112
+ packages,
113
+ versionSkew: versions.size > 1,
114
+ linkedFramework: packages.some((p) => p.linked),
115
+ node: process.version,
116
+ packageManager: await detectPackageManager(startDir),
117
+ platform: `${process.platform}-${process.arch}`,
118
+ };
119
+ }
@@ -11,6 +11,11 @@
11
11
  export interface PikkuEnvironment {
12
12
  apiUrl: string;
13
13
  signInPath?: string;
14
+ /**
15
+ * Where the session and its roles are read back, for a stage that reports
16
+ * them somewhere other than `get-session` under the sign-in path's own mount.
17
+ */
18
+ sessionPath?: string;
14
19
  rpcPath?: string;
15
20
  appUrl?: string;
16
21
  /**
@@ -115,6 +115,7 @@ export const personaRun = pikkuSessionlessFunc({
115
115
  ...credentials,
116
116
  personas,
117
117
  signInPath: env.signInPath,
118
+ sessionPath: env.sessionPath,
118
119
  rpcPath: env.rpcPath,
119
120
  model: resolvedModel,
120
121
  });
@@ -176,6 +176,7 @@ export const scenarioRun = pikkuSessionlessFunc({
176
176
  ...credentials,
177
177
  personas: scenarioActors,
178
178
  signInPath: env.signInPath,
179
+ sessionPath: env.sessionPath,
179
180
  rpcPath: env.rpcPath,
180
181
  model: config.scenarios?.model,
181
182
  });
@@ -10,7 +10,7 @@ export type AuthPluginCheckConfig = {
10
10
  * running two authorization models and projecting one onto the other. The
11
11
  * inspector refuses it outright at prebuild; this reports the same thing
12
12
  * without one, and additionally catches the quieter half of the migration, an
13
- * app that dropped `admin()` and never wired `ban()`, which keeps its ban
13
+ * app that dropped `admin()` and never wired `pikkuBan()`, which keeps its ban
14
14
  * columns and its ban UI while silently enforcing nothing.
15
15
  */
16
16
  export declare const runAuthPluginChecks: (root: string, config: AuthPluginCheckConfig | null) => Promise<ValidateFinding[]>;
@@ -113,7 +113,7 @@ const configuresPlugin = (text, module, exported) => {
113
113
  * running two authorization models and projecting one onto the other. The
114
114
  * inspector refuses it outright at prebuild; this reports the same thing
115
115
  * without one, and additionally catches the quieter half of the migration, an
116
- * app that dropped `admin()` and never wired `ban()`, which keeps its ban
116
+ * app that dropped `admin()` and never wired `pikkuBan()`, which keeps its ban
117
117
  * columns and its ban UI while silently enforcing nothing.
118
118
  */
119
119
  export const runAuthPluginChecks = async (root, config) => {
@@ -131,7 +131,10 @@ export const runAuthPluginChecks = async (root, config) => {
131
131
  continue;
132
132
  if (configuresPlugin(text, 'better-auth/plugins', 'admin'))
133
133
  adminFiles.push(file);
134
- if (configuresPlugin(text, '@pikku/better-auth', 'ban'))
134
+ // `pikkuBan` is the current export; `ban` is the deprecated alias, which
135
+ // configures exactly the same plugin and so must satisfy the check too.
136
+ if (configuresPlugin(text, '@pikku/better-auth', 'pikkuBan') ||
137
+ configuresPlugin(text, '@pikku/better-auth', 'ban'))
135
138
  bansAnywhere = true;
136
139
  }
137
140
  for (const file of adminFiles) {
@@ -140,7 +143,7 @@ export const runAuthPluginChecks = async (root, config) => {
140
143
  severity: 'error',
141
144
  message: "better-auth's admin() plugin is not supported — it authorizes against a user.role column while pikku authorizes on scopes, so one has to be projected onto the other",
142
145
  path: file,
143
- fixHint: lines('Replace it with ban(), which keeps the one capability admin() had that', 'pikku cannot supply from outside better-auth — refusing a banned user a', 'session:', " import { ban } from '@pikku/better-auth'", ' betterAuth({ plugins: [ban()] })', 'User management is already scoped RPCs in @pikku/addon-admin: list,', 'create, ban, remove, revoke sessions and set password.'),
146
+ fixHint: lines('Replace it with pikkuBan(), which keeps the one capability admin() had', 'that pikku cannot supply from outside better-auth — refusing a banned', 'user a session:', " import { pikkuBan } from '@pikku/better-auth'", ' betterAuth({ plugins: [pikkuBan()] })', 'User management is already scoped RPCs in @pikku/addon-admin: list,', 'create, ban, remove, revoke sessions and set password.'),
144
147
  });
145
148
  }
146
149
  if (!bansAnywhere && adminFiles.length === 0) {
@@ -153,9 +156,9 @@ export const runAuthPluginChecks = async (root, config) => {
153
156
  findings.push({
154
157
  id: 'better-auth-no-ban-plugin',
155
158
  severity: 'warn',
156
- message: 'better-auth is configured without ban() — the banned/banReason/banExpires columns do not exist, so banning a user through @pikku/addon-admin has nothing to write and nothing refuses their next sign-in',
159
+ message: 'better-auth is configured without pikkuBan() — the banned/banReason/banExpires columns do not exist, so banning a user through @pikku/addon-admin has nothing to write and nothing refuses their next sign-in',
157
160
  path: file,
158
- fixHint: lines(" import { ban } from '@pikku/better-auth'", ' betterAuth({ plugins: [ban()] })', 'Wire it wherever the rest of your plugins are, then run', '`pikku db migrate` to add the columns.'),
161
+ fixHint: lines(" import { pikkuBan } from '@pikku/better-auth'", ' betterAuth({ plugins: [pikkuBan()] })', 'Wire it wherever the rest of your plugins are, then run', '`pikku db migrate` to add the columns.'),
159
162
  });
160
163
  break;
161
164
  }
@@ -81,17 +81,19 @@ const countPersonas = async (root, config, sourceFiles) => {
81
81
  /**
82
82
  * Whether a persona can actually sign in.
83
83
  *
84
- * Two shapes count. `actor()` from `@pikku/better-auth` is the one the scaffold
85
- * wires, and a hand-rolled `/sign-in/actor` route is the one a project that does
86
- * not use better-auth ends up with. Both terminate at the same endpoint, so
87
- * either satisfies the check.
84
+ * Two shapes count. `pikkuActor()` from `@pikku/better-auth` is the one the
85
+ * scaffold wires, and a hand-rolled `/sign-in/actor` route is the one a project
86
+ * that does not use better-auth ends up with. Both terminate at the same
87
+ * endpoint, so either satisfies the check. The deprecated `actor()` alias is
88
+ * matched too — it is the same plugin under its old name.
88
89
  */
89
90
  const hasActorSignIn = async (sourceFiles) => {
90
91
  for (const file of sourceFiles) {
91
92
  const text = await readTextSafe(file);
92
93
  if (!text)
93
94
  continue;
94
- const wiresPlugin = /@pikku\/better-auth/.test(text) && /\bactor\s*\(/.test(text);
95
+ const wiresPlugin = /@pikku\/better-auth/.test(text) &&
96
+ /(^|[^\w$.])(pikkuActor|actor)\s*\(/.test(text);
95
97
  if (wiresPlugin || /sign-in\/actor/.test(text))
96
98
  return true;
97
99
  }
@@ -123,7 +125,7 @@ export const runPersonaChecks = async (root, config) => {
123
125
  return findings;
124
126
  }
125
127
  if (!(await hasActorSignIn(sourceFiles))) {
126
- w('personas-no-actor-sign-in', `${personas} persona${personas === 1 ? ' is' : 's are'} declared, but nothing wires actor sign-in — a scenario run signs in over POST /auth/sign-in/actor, so every persona fails to acquire a session`, pikkuConfigPath, lines('Wire the actor plugin where better-auth is configured:', " import { actor } from '@pikku/better-auth'", ' plugins: [actor({ secret: SCENARIO_ACTOR_SECRET })]', '`pikku dev` turns the endpoint on and mints the secret itself, so there', 'is nothing to configure locally. A deployed stage that must run', 'scenarios opts in with', 'PIKKU_ALLOW_ACTOR_SIGN_IN=passwordless-actor-sign-in; everywhere else', 'the endpoint stays off whatever the environment happens to contain.'));
128
+ w('personas-no-actor-sign-in', `${personas} persona${personas === 1 ? ' is' : 's are'} declared, but nothing wires actor sign-in — a scenario run signs in over POST /auth/sign-in/actor, so every persona fails to acquire a session`, pikkuConfigPath, lines('Wire the actor plugin where better-auth is configured:', " import { pikkuActor } from '@pikku/better-auth'", ' plugins: [pikkuActor({ secret: SCENARIO_ACTOR_SECRET })]', '`pikku dev` turns the endpoint on and mints the secret itself, so there', 'is nothing to configure locally. A deployed stage that must run', 'scenarios opts in with', 'PIKKU_ALLOW_ACTOR_SIGN_IN=passwordless-actor-sign-in; everywhere else', 'the endpoint stays off whatever the environment happens to contain.'));
127
129
  }
128
130
  const environments = config?.environments;
129
131
  const hasEnvironment = typeof environments === 'object' &&
@@ -28,12 +28,17 @@ export const pikkuUserAdminFunctions = pikkuSessionlessFunc({
28
28
  // Ban is the one capability with a schema requirement of its own, and it is
29
29
  // only one of the six — a warning rather than a failure, so an app that
30
30
  // never bans anyone is not forced to carry the columns.
31
- if (!definition.plugins.includes('ban')) {
32
- logger.warn(`"scaffold.userAdmin" is enabled but better-auth is configured without the ban() plugin, ` +
31
+ // The plugin ids here are the callee names read off the `plugins: [...]`
32
+ // array, so both the current `pikkuBan()` and the deprecated `ban()` alias
33
+ // have to count as wired.
34
+ const bansUsers = definition.plugins.includes('pikkuBan') ||
35
+ definition.plugins.includes('ban');
36
+ if (!bansUsers) {
37
+ logger.warn(`"scaffold.userAdmin" is enabled but better-auth is configured without the pikkuBan() plugin, ` +
33
38
  `so the banned/banReason/banExpires columns do not exist and setUserBanned will fail.\n` +
34
- `Fix: add ban() to the plugins array in ${definition.sourceFile}:\n` +
35
- ` import { ban } from '@pikku/better-auth'\n` +
36
- ` betterAuth({ plugins: [ban()] })`);
39
+ `Fix: add pikkuBan() to the plugins array in ${definition.sourceFile}:\n` +
40
+ ` import { pikkuBan } from '@pikku/better-auth'\n` +
41
+ ` betterAuth({ plugins: [pikkuBan()] })`);
37
42
  }
38
43
  const leaf = (name) => getLeafImportPath(config.userAdminFunctionsFile, name, config);
39
44
  const { schemas, functions } = serializeUserAdminFunctions(leaf);
@@ -13,7 +13,7 @@ export interface UserAdminGenOutput {
13
13
  * codegen on conflicting declarations.
14
14
  *
15
15
  * Each function is gated on its own `admin:users:*` scope, and works through
16
- * better-auth's internal adapter. Banning additionally needs the `ban()` plugin
16
+ * better-auth's internal adapter. Banning additionally needs the `pikkuBan()` plugin
17
17
  * from `@pikku/better-auth` for the columns it writes to exist.
18
18
  *
19
19
  * Emitted as two files. The schemas are zod, and the inspector reads a zod
@@ -9,7 +9,7 @@
9
9
  * codegen on conflicting declarations.
10
10
  *
11
11
  * Each function is gated on its own `admin:users:*` scope, and works through
12
- * better-auth's internal adapter. Banning additionally needs the `ban()` plugin
12
+ * better-auth's internal adapter. Banning additionally needs the `pikkuBan()` plugin
13
13
  * from `@pikku/better-auth` for the columns it writes to exist.
14
14
  *
15
15
  * Emitted as two files. The schemas are zod, and the inspector reads a zod
@@ -27,7 +27,7 @@ import { z } from 'zod'
27
27
 
28
28
  /**
29
29
  * A user, as the directory sees one. Ban state is optional because those
30
- * columns belong to the \`ban()\` plugin: a host without it reports no ban state
30
+ * columns belong to the \`pikkuBan()\` plugin: a host without it reports no ban state
31
31
  * at all, which a client can render as "unknown" rather than as a misleading
32
32
  * "not banned".
33
33
  */
@@ -224,7 +224,7 @@ export const pikkuAdminSetUserBanned = pikkuFunc({
224
224
  tags: ['pikku'],
225
225
  title: 'Ban or Unban User',
226
226
  description:
227
- 'Bans a user — revoking their sessions and blocking sign-in — or lifts an existing ban. An expiry lets the ban lapse on its own; without one it holds until it is lifted. Requires better-auth wired with the \`ban()\` plugin.',
227
+ 'Bans a user — revoking their sessions and blocking sign-in — or lifts an existing ban. An expiry lets the ban lapse on its own; without one it holds until it is lifted. Requires better-auth wired with the \`pikkuBan()\` plugin.',
228
228
  expose: true,
229
229
  scopes: ['admin:users:ban'],
230
230
  input: SetUserBannedInput,
@@ -71,12 +71,21 @@ export const defaultCLIRenderer = pikkuCLIRender((_services, data) => {
71
71
  * `skills install` writes agent skills into a repo that has no pikku.config.json
72
72
  * yet — that is the whole point of it — so it cannot require one to start, and
73
73
  * `doc` answers from the surface shipped inside the CLI rather than the project.
74
+ * `fabric report` files a finding about pikku itself: a scaffold that never
75
+ * produced a config, or a command run from the wrong directory, is exactly the
76
+ * kind of thing worth reporting, so demanding a config would refuse the finding
77
+ * at the moment it is most worth having.
74
78
  */
75
79
  const CONFIG_FREE_COMMANDS = new Set([
76
80
  'skills',
77
81
  'skills.list',
78
82
  'skills.install',
79
83
  'doc',
84
+ 'fabric.report',
85
+ 'fabric.findings',
86
+ 'fabric.findings.list',
87
+ 'fabric.findings.flush',
88
+ 'fabric.findings.clear',
80
89
  ]);
81
90
  export const createConfig = async (_variablesService, data, commandPath = []) => {
82
91
  // Determine log level based on CLI flags with precedence: