@pikku/cli 0.12.125 → 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 (301) hide show
  1. package/CHANGELOG.md +231 -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 +26 -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 +116 -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 +114 -21
  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 +5 -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 +19 -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/schemas/schemas/FabricSecretsListInput.schema.json +1 -1
  178. package/dist/.pikku/schemas/schemas/FabricSecretsRotateInput.schema.json +1 -1
  179. package/dist/.pikku/schemas/schemas/FabricSecretsSetInput.schema.json +1 -1
  180. package/dist/.pikku/schemas/schemas/FabricVariablesGetInput.schema.json +1 -1
  181. package/dist/.pikku/schemas/schemas/FabricVariablesSetInput.schema.json +1 -1
  182. package/dist/.pikku/schemas/schemas/PersonaSecretInput.schema.json +1 -0
  183. package/dist/.pikku/scopes/index.d.ts +1 -1
  184. package/dist/.pikku/scopes/index.js +1 -1
  185. package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
  186. package/dist/.pikku/scopes/pikku-roles.gen.d.ts +1 -1
  187. package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
  188. package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
  189. package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
  190. package/dist/.pikku/secrets/index.d.ts +1 -1
  191. package/dist/.pikku/secrets/index.js +1 -1
  192. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  193. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  194. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  195. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  196. package/dist/.pikku/services/pikku-meta-service.gen.d.ts +1 -1
  197. package/dist/.pikku/services/pikku-meta-service.gen.js +1 -1
  198. package/dist/.pikku/setup/index.d.ts +1 -1
  199. package/dist/.pikku/setup/index.js +1 -1
  200. package/dist/.pikku/setup/pikku-setup-types.gen.d.ts +1 -1
  201. package/dist/.pikku/setup/pikku-setup-types.gen.js +1 -1
  202. package/dist/.pikku/trigger/index.d.ts +1 -1
  203. package/dist/.pikku/trigger/index.js +1 -1
  204. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  205. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  206. package/dist/.pikku/variables/index.d.ts +1 -1
  207. package/dist/.pikku/variables/index.js +1 -1
  208. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  209. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  210. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  211. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  212. package/dist/.pikku/workflow/index.d.ts +1 -1
  213. package/dist/.pikku/workflow/index.js +1 -1
  214. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  215. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  216. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  217. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  218. package/dist/bin/pikku-bin.mjs +2 -2
  219. package/dist/src/cli.wiring.js +6 -1
  220. package/dist/src/deploy/bundler/bun-bundler.js +12 -5
  221. package/dist/src/fabric/fabric-commands.d.ts +153 -15
  222. package/dist/src/fabric/fabric-commands.js +65 -0
  223. package/dist/src/fabric/functions/deploy.function.js +12 -2
  224. package/dist/src/fabric/functions/findings-clear.function.d.ts +12 -0
  225. package/dist/src/fabric/functions/findings-clear.function.js +17 -0
  226. package/dist/src/fabric/functions/findings-flush.function.d.ts +33 -0
  227. package/dist/src/fabric/functions/findings-flush.function.js +36 -0
  228. package/dist/src/fabric/functions/findings-list.function.d.ts +55 -0
  229. package/dist/src/fabric/functions/findings-list.function.js +52 -0
  230. package/dist/src/fabric/functions/report.function.d.ts +121 -0
  231. package/dist/src/fabric/functions/report.function.js +84 -0
  232. package/dist/src/fabric/functions/secrets-list.function.d.ts +4 -4
  233. package/dist/src/fabric/functions/secrets-list.function.js +4 -4
  234. package/dist/src/fabric/functions/secrets-rotate.function.d.ts +4 -4
  235. package/dist/src/fabric/functions/secrets-rotate.function.js +8 -5
  236. package/dist/src/fabric/functions/secrets-set.function.d.ts +4 -4
  237. package/dist/src/fabric/functions/secrets-set.function.js +4 -4
  238. package/dist/src/fabric/functions/validate.function.js +49 -24
  239. package/dist/src/fabric/functions/variables-get.function.d.ts +4 -4
  240. package/dist/src/fabric/functions/variables-get.function.js +4 -4
  241. package/dist/src/fabric/functions/variables-set.function.d.ts +4 -4
  242. package/dist/src/fabric/functions/variables-set.function.js +4 -4
  243. package/dist/src/fabric/lib/blank-comments.d.ts +21 -0
  244. package/dist/src/fabric/lib/blank-comments.js +71 -0
  245. package/dist/src/fabric/lib/blank-scenario-meta.d.ts +1 -0
  246. package/dist/src/fabric/lib/blank-scenario-meta.js +110 -0
  247. package/dist/src/fabric/lib/deployment.d.ts +26 -0
  248. package/dist/src/fabric/lib/deployment.js +35 -0
  249. package/dist/src/fabric/lib/finding-spool.d.ts +56 -0
  250. package/dist/src/fabric/lib/finding-spool.js +105 -0
  251. package/dist/src/fabric/lib/finding.d.ts +92 -0
  252. package/dist/src/fabric/lib/finding.js +156 -0
  253. package/dist/src/fabric/lib/report-environment.d.ts +53 -0
  254. package/dist/src/fabric/lib/report-environment.js +119 -0
  255. package/dist/src/fabric/lib/stage.d.ts +19 -3
  256. package/dist/src/fabric/lib/stage.js +29 -6
  257. package/dist/src/functions/commands/db-reset.js +6 -2
  258. package/dist/src/functions/commands/dev.js +5 -1
  259. package/dist/src/functions/commands/environment.d.ts +5 -0
  260. package/dist/src/functions/commands/persona.d.ts +18 -0
  261. package/dist/src/functions/commands/persona.js +42 -2
  262. package/dist/src/functions/commands/scenario-browser.d.ts +13 -5
  263. package/dist/src/functions/commands/scenario.js +1 -0
  264. package/dist/src/functions/db/check-enums.d.ts +38 -0
  265. package/dist/src/functions/db/check-enums.js +103 -0
  266. package/dist/src/functions/db/db-codegen.js +15 -0
  267. package/dist/src/functions/db/postgres/postgres-introspector.d.ts +14 -0
  268. package/dist/src/functions/db/postgres/postgres-introspector.js +48 -0
  269. package/dist/src/functions/db/sqlite/sqlite-introspector.d.ts +3 -4
  270. package/dist/src/functions/db/sqlite/sqlite-introspector.js +5 -17
  271. package/dist/src/functions/validate/auth-plugin-checks.d.ts +1 -1
  272. package/dist/src/functions/validate/auth-plugin-checks.js +8 -5
  273. package/dist/src/functions/validate/persona-checks.js +8 -6
  274. package/dist/src/functions/wirings/user-admin/pikku-command-user-admin-functions.js +10 -5
  275. package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.d.ts +1 -1
  276. package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.js +3 -3
  277. package/dist/src/functions/wirings/virtual-user/serialize-virtual-user-functions.d.ts +9 -6
  278. package/dist/src/functions/wirings/virtual-user/serialize-virtual-user-functions.js +51 -27
  279. package/dist/src/server/actor-sign-in.d.ts +24 -1
  280. package/dist/src/server/actor-sign-in.js +45 -2
  281. package/dist/src/services.js +9 -0
  282. package/dist/src/utils/persona-credentials.d.ts +23 -2
  283. package/dist/src/utils/persona-credentials.js +55 -2
  284. package/dist/src/utils/pikku-cli-config.d.ts +4 -4
  285. package/dist/src/utils/pikku-cli-config.js +30 -10
  286. package/dist/tsconfig.tsbuildinfo +1 -1
  287. package/package.json +8 -8
  288. package/snippets.json +1 -1
  289. package/surface.json +102 -52
  290. package/console-app/assets/architecture-TIHT7OUA-DmG0bXDT.js +0 -1
  291. package/console-app/assets/channel-BgCT5gon.js +0 -1
  292. package/console-app/assets/chunk-XXDRQBXY-EP2C9tTO.js +0 -1
  293. package/console-app/assets/classDiagram-JCYQIIEL-D9wGqB4J.js +0 -1
  294. package/console-app/assets/classDiagram-v2-OCEON4UE-D9wGqB4J.js +0 -1
  295. package/console-app/assets/eventmodeling-45OFAUF4-NKFCZ8Fj.js +0 -1
  296. package/console-app/assets/flowDiagram-UKHOOZJN-BpdPkmum.js +0 -1
  297. package/console-app/assets/railroad-abnf-AHOZXSZD-B3CYVW4p.js +0 -1
  298. package/console-app/assets/railroad-ebnf-EBAXGLYW-DrZ2yF62.js +0 -1
  299. package/console-app/assets/railroad-peg-LSFZ7HO6-CWAmMyxd.js +0 -1
  300. package/console-app/assets/stateDiagram-v2-UEYNNEHI-Celbgz4u.js +0 -1
  301. package/console-app/assets/swimlanesDiagram-ULZ7WXOC-zxpNaB4U.js +0 -8
@@ -1,11 +1,11 @@
1
1
  import { resolve, dirname } from 'node:path';
2
2
  import { mkdirSync, writeFileSync } from 'node:fs';
3
3
  import { pikkuSessionlessFunc } from '#pikku/function';
4
- import { createHttpPersonas, personaEnvironmentRefusal, roleMismatchMessage, verifyPersonaRoles, } from '@pikku/core/persona';
4
+ import { createHttpPersonas, deriveActorSecret, personaEnvironmentRefusal, roleMismatchMessage, verifyPersonaRoles, } from '@pikku/core/persona';
5
5
  import { personaVirtualUserTarget, runVirtualUser, catalogueClassification, DISPOSITIONS, prepareVirtualUserRun, } from '@pikku/core/virtual-user';
6
6
  import { getSingletonServices, setSingletonServices } from '@pikku/core/state';
7
7
  import { resolvePersonas } from '../../utils/resolve-personas.js';
8
- import { resolvePersonaCredentials } from '../../utils/persona-credentials.js';
8
+ import { ACTOR_SECRET_VARIABLE, PERSONA_SECRETS_VARIABLE, resolvePersonaCredentials, } from '../../utils/persona-credentials.js';
9
9
  import { resolveEnvironment } from './environment.js';
10
10
  import { createDevAgentRunner } from './dev-agent-runner.js';
11
11
  import { formatVirtualUserReport } from './virtual-user-formatter.js';
@@ -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
  });
@@ -191,6 +192,45 @@ export const personaRun = pikkuSessionlessFunc({
191
192
  },
192
193
  });
193
194
  /** Who this app is for, and what each of them wants, without running anything. */
195
+ /**
196
+ * Mint the actor credential for one persona, or for every declared persona.
197
+ *
198
+ * The root secret is entitled to all of them, so nothing that only needs to be
199
+ * one person should ever hold it. What comes out is bound to that persona's
200
+ * address by the target — presenting it for anyone else is refused — so a CI
201
+ * job, a container or a virtual user can be handed exactly the people it is
202
+ * meant to be and no more.
203
+ *
204
+ * Printed as `id=secret` lines, which is the shape PIKKU_PERSONA_SECRETS reads.
205
+ */
206
+ export const personaSecret = pikkuSessionlessFunc({
207
+ func: async ({ logger, config, variables, getInspectorState }, input) => {
208
+ const root = await variables.get(ACTOR_SECRET_VARIABLE);
209
+ if (!root) {
210
+ throw new Error(`${ACTOR_SECRET_VARIABLE} is not set — there is no root to derive from. ` +
211
+ `It lives in the environment of whoever mints credentials, and never in pikku.config.json.`);
212
+ }
213
+ const state = await getInspectorState(true, false, false, true);
214
+ const declared = resolvePersonas(state.personas?.definitions ?? [], config.scenarios?.emailDomain);
215
+ const wanted = input.personas?.length
216
+ ? input.personas
217
+ : Object.keys(declared);
218
+ const unknown = wanted.filter((id) => !declared[id]);
219
+ if (unknown.length > 0) {
220
+ throw new Error(`No persona ${unknown.map((id) => `'${id}'`).join(', ')} is declared. ` +
221
+ `Declared: ${Object.keys(declared).sort().join(', ') || 'none'}.`);
222
+ }
223
+ const minted = [];
224
+ for (const id of wanted) {
225
+ minted.push(`${id}=${await deriveActorSecret(String(root), declared[id].email)}`);
226
+ }
227
+ for (const line of minted) {
228
+ logger.info(line);
229
+ }
230
+ logger.info('');
231
+ logger.info(`Hand these to a run as ${PERSONA_SECRETS_VARIABLE}='${minted.join(',')}'`);
232
+ },
233
+ });
194
234
  export const personaList = pikkuSessionlessFunc({
195
235
  func: async ({ logger, config, getInspectorState }) => {
196
236
  const state = await getInspectorState(true, false, false, true);
@@ -9,12 +9,16 @@
9
9
  */
10
10
  import type { ScenarioArtifact, ScenarioBrowserFailure, ScenarioBrowserProvider } from '@pikku/core/scenario';
11
11
  import type { ResolvedPersona } from '@pikku/core/services';
12
- import type { OperatorSignInOptions } from '@pikku/core/persona';
12
+ import type { ActorSecretResolver, OperatorSignInOptions } from '@pikku/core/persona';
13
13
  /** The default driver, used when a project names no other. */
14
14
  export declare const DEFAULT_BROWSER_DRIVER = "@pikku/playwright";
15
15
  export interface ScenarioBrowserDriverOptions {
16
- /** The actor secret, for a local `pikku dev` target. */
17
- secret?: string;
16
+ /**
17
+ * The root actor secret, for a local `pikku dev` target — each persona's
18
+ * credential is derived from it. A resolver instead when this run was handed
19
+ * credentials for only some personas.
20
+ */
21
+ secret?: string | ActorSecretResolver;
18
22
  /** Fabric operator credentials, for a deployed target. */
19
23
  operator?: OperatorSignInOptions;
20
24
  actors: Record<string, ResolvedPersona>;
@@ -72,8 +76,12 @@ export interface ResolveScenarioBrowserProviderOptions {
72
76
  appUrl?: string;
73
77
  /** Base url per app, for a product whose personas sign into more than one. */
74
78
  appUrls?: Record<string, string>;
75
- /** The actor secret, for a local `pikku dev` target. */
76
- secret?: string;
79
+ /**
80
+ * The root actor secret, for a local `pikku dev` target — each persona's
81
+ * credential is derived from it. A resolver instead when this run was handed
82
+ * credentials for only some personas.
83
+ */
84
+ secret?: string | ActorSecretResolver;
77
85
  /** Fabric operator credentials, for a deployed target. */
78
86
  operator?: OperatorSignInOptions;
79
87
  actors: Record<string, ResolvedPersona>;
@@ -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
  });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * A `CHECK (col IN ('a','b',…))` constraint is an enum by another name, and
3
+ * both introspectors read one back as SQL text: SQLite stores the `CREATE
4
+ * TABLE` verbatim, Postgres hands back a normalised `pg_get_constraintdef`.
5
+ * The parsing they need differs, but the quoting rules do not, so both go
6
+ * through here.
7
+ */
8
+ /**
9
+ * Blank out `--` line comments and `/* … *\/` block comments, leaving a string
10
+ * of the same shape so offsets and line breaks still line up.
11
+ *
12
+ * Quoted text is skipped rather than scanned: `'a--b'` is a value, not a
13
+ * comment. The reverse — reading a comment as SQL — is what makes this
14
+ * necessary at all: an apostrophe in `-- the clinician's copy` opens a string
15
+ * that runs to the next quote in the real list, and a bracket in `-- (see
16
+ * below)` closes the list early. Either way the CHECK survives as a union that
17
+ * is wrong, which is worse than no union.
18
+ */
19
+ export declare function stripSqlComments(sql: string): string;
20
+ /** The single-quoted literals in `text`, with doubled quotes unescaped. */
21
+ export declare function quotedValues(text: string): string[];
22
+ /**
23
+ * Map each column constrained by a `CHECK (col IN (…))` in a `CREATE TABLE`
24
+ * statement to its allowed values. Only the positive `col IN (…)` form is
25
+ * recognised (the convention); `NOT IN`, ranges and boolean expressions are
26
+ * left for the column to stay a plain string.
27
+ */
28
+ export declare function parseCheckEnumsFromDdl(ddl: string): Map<string, string[]>;
29
+ /**
30
+ * The allowed values in a Postgres check constraint, or `undefined` when the
31
+ * constraint is not an enumeration.
32
+ *
33
+ * Postgres does not store the `IN (…)` you wrote — `pg_get_constraintdef`
34
+ * rewrites it as `= ANY (ARRAY[…])`, with each element cast to the column's
35
+ * type. Matching that shape is deliberate: `NOT IN` normalises to `<> ALL
36
+ * (ARRAY[…])` and a range to `>`/`<`, and neither is an enum.
37
+ */
38
+ export declare function parseCheckEnumValues(constraintDef: string): string[] | undefined;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * A `CHECK (col IN ('a','b',…))` constraint is an enum by another name, and
3
+ * both introspectors read one back as SQL text: SQLite stores the `CREATE
4
+ * TABLE` verbatim, Postgres hands back a normalised `pg_get_constraintdef`.
5
+ * The parsing they need differs, but the quoting rules do not, so both go
6
+ * through here.
7
+ */
8
+ /**
9
+ * Blank out `--` line comments and `/* … *\/` block comments, leaving a string
10
+ * of the same shape so offsets and line breaks still line up.
11
+ *
12
+ * Quoted text is skipped rather than scanned: `'a--b'` is a value, not a
13
+ * comment. The reverse — reading a comment as SQL — is what makes this
14
+ * necessary at all: an apostrophe in `-- the clinician's copy` opens a string
15
+ * that runs to the next quote in the real list, and a bracket in `-- (see
16
+ * below)` closes the list early. Either way the CHECK survives as a union that
17
+ * is wrong, which is worse than no union.
18
+ */
19
+ export function stripSqlComments(sql) {
20
+ let out = '';
21
+ let i = 0;
22
+ while (i < sql.length) {
23
+ const c = sql[i];
24
+ if (c === "'" || c === '"') {
25
+ const end = closingQuote(sql, i);
26
+ out += sql.slice(i, end);
27
+ i = end;
28
+ continue;
29
+ }
30
+ if (c === '-' && sql[i + 1] === '-') {
31
+ while (i < sql.length && sql[i] !== '\n') {
32
+ out += ' ';
33
+ i++;
34
+ }
35
+ continue;
36
+ }
37
+ if (c === '/' && sql[i + 1] === '*') {
38
+ const close = sql.indexOf('*/', i + 2);
39
+ const end = close === -1 ? sql.length : close + 2;
40
+ for (let k = i; k < end; k++)
41
+ out += sql[k] === '\n' ? '\n' : ' ';
42
+ i = end;
43
+ continue;
44
+ }
45
+ out += c;
46
+ i++;
47
+ }
48
+ return out;
49
+ }
50
+ /** Index just past the quoted run starting at `start`, doubled quotes included. */
51
+ function closingQuote(sql, start) {
52
+ const quote = sql[start];
53
+ let i = start + 1;
54
+ while (i < sql.length) {
55
+ if (sql[i] === quote) {
56
+ if (sql[i + 1] === quote) {
57
+ i += 2;
58
+ continue;
59
+ }
60
+ return i + 1;
61
+ }
62
+ i++;
63
+ }
64
+ return sql.length;
65
+ }
66
+ /** The single-quoted literals in `text`, with doubled quotes unescaped. */
67
+ export function quotedValues(text) {
68
+ return [...text.matchAll(/'((?:[^']|'')*)'/g)].map((m) => m[1].replace(/''/g, "'"));
69
+ }
70
+ /**
71
+ * Map each column constrained by a `CHECK (col IN (…))` in a `CREATE TABLE`
72
+ * statement to its allowed values. Only the positive `col IN (…)` form is
73
+ * recognised (the convention); `NOT IN`, ranges and boolean expressions are
74
+ * left for the column to stay a plain string.
75
+ */
76
+ export function parseCheckEnumsFromDdl(ddl) {
77
+ const out = new Map();
78
+ const sql = stripSqlComments(ddl);
79
+ const checkIn = /CHECK\s*\(\s*"?(\w+)"?\s+IN\s*\(([^)]*)\)/gi;
80
+ let m;
81
+ while ((m = checkIn.exec(sql))) {
82
+ const values = quotedValues(m[2]);
83
+ if (values.length > 0)
84
+ out.set(m[1], values);
85
+ }
86
+ return out;
87
+ }
88
+ /**
89
+ * The allowed values in a Postgres check constraint, or `undefined` when the
90
+ * constraint is not an enumeration.
91
+ *
92
+ * Postgres does not store the `IN (…)` you wrote — `pg_get_constraintdef`
93
+ * rewrites it as `= ANY (ARRAY[…])`, with each element cast to the column's
94
+ * type. Matching that shape is deliberate: `NOT IN` normalises to `<> ALL
95
+ * (ARRAY[…])` and a range to `>`/`<`, and neither is an enum.
96
+ */
97
+ export function parseCheckEnumValues(constraintDef) {
98
+ const any = /=\s*ANY\s*\(\s*\(?\s*ARRAY\s*\[([^\]]*)\]/i.exec(constraintDef);
99
+ if (!any)
100
+ return undefined;
101
+ const values = quotedValues(any[1]);
102
+ return values.length > 0 ? values : undefined;
103
+ }
@@ -641,6 +641,21 @@ export async function generateSchemaTypes(introspector, options) {
641
641
  const coercionBody = [
642
642
  `// Generated by @pikku/cli — do not edit by hand.`,
643
643
  `// Run \`pikku db migrate\` to refresh.`,
644
+ `//`,
645
+ `// Nothing applies this for you. Attach it where the kysely singleton is`,
646
+ `// created, in createSingletonServices:`,
647
+ `//`,
648
+ `// import { createCoercionPlugin } from '@pikku/kysely'`,
649
+ `// import { coercionMap } from '#pikku/db/coercion.gen.js'`,
650
+ `//`,
651
+ `// kysely: existingServices.kysely.withPlugin(`,
652
+ `// createCoercionPlugin({ map: coercionMap }),`,
653
+ `// )`,
654
+ `//`,
655
+ `// Unwired, this file is invisible locally and fatal deployed: the dev`,
656
+ `// driver hydrates a TEXT date into a Date by itself, a deployed one`,
657
+ `// returns the raw string, and the generated schema types the column`,
658
+ `// \`Date\` either way — so tsc flags nothing and no local test can fail.`,
644
659
  ``,
645
660
  `export const coercionMap = {`,
646
661
  coercionEntries,
@@ -12,6 +12,20 @@ export declare class PostgresIntrospector implements DbIntrospector {
12
12
  connect(): Promise<void>;
13
13
  listTables(): Promise<string[]>;
14
14
  getColumns(table: string): Promise<ColumnInfo[]>;
15
+ /**
16
+ * Columns constrained to a value list by a `CHECK (col IN (…))`, keyed like
17
+ * {@link getAllColumns} then by column name. Postgres has native enums, but
18
+ * a CHECK is the other half of how a schema says "one of these" — and the
19
+ * one an app written against SQLite as well ends up using, since SQLite has
20
+ * no enums at all. Left as plain `string`, every caller narrows it by hand.
21
+ *
22
+ * Only single-column constraints are read: `conkey` naming two columns means
23
+ * neither is restricted to the list on its own.
24
+ *
25
+ * `table` limits the sweep to one table; omitted, it covers the schema. Both
26
+ * are one round-trip — see {@link getAllColumns}.
27
+ */
28
+ private getCheckEnums;
15
29
  getForeignKeys(table: string): Promise<ForeignKeyInfo[]>;
16
30
  getAllColumns(): Promise<Map<string, ColumnInfo[]>>;
17
31
  getAllForeignKeys(): Promise<Map<string, ForeignKeyInfo[]>>;
@@ -1,5 +1,6 @@
1
1
  import { Pool } from 'pg';
2
2
  import { MIGRATION_TRACKING_TABLE } from '../db-migrator.js';
3
+ import { parseCheckEnumValues } from '../check-enums.js';
3
4
  /** Table display name matching `listTables` (schema-qualified unless `public`). */
4
5
  function tableKey(schema, table) {
5
6
  return schema === 'public' ? table : `${schema}.${table}`;
@@ -85,6 +86,8 @@ export class PostgresIntrospector {
85
86
  FROM information_schema.columns c
86
87
  WHERE c.table_schema = $2 AND c.table_name = $1
87
88
  ORDER BY c.ordinal_position`, [tableName, schema]);
89
+ const checkEnums = (await this.getCheckEnums({ schema, name: tableName })).get(table) ??
90
+ new Map();
88
91
  return result.rows.map((r) => ({
89
92
  name: r.column_name,
90
93
  type: resolveColumnType(r.data_type, r.udt_name),
@@ -93,8 +96,51 @@ export class PostgresIntrospector {
93
96
  pk: Boolean(r.is_pk),
94
97
  defaultValue: r.column_default,
95
98
  generated: r.is_generated === 'ALWAYS',
99
+ enumValues: checkEnums.get(r.column_name),
96
100
  }));
97
101
  }
102
+ /**
103
+ * Columns constrained to a value list by a `CHECK (col IN (…))`, keyed like
104
+ * {@link getAllColumns} then by column name. Postgres has native enums, but
105
+ * a CHECK is the other half of how a schema says "one of these" — and the
106
+ * one an app written against SQLite as well ends up using, since SQLite has
107
+ * no enums at all. Left as plain `string`, every caller narrows it by hand.
108
+ *
109
+ * Only single-column constraints are read: `conkey` naming two columns means
110
+ * neither is restricted to the list on its own.
111
+ *
112
+ * `table` limits the sweep to one table; omitted, it covers the schema. Both
113
+ * are one round-trip — see {@link getAllColumns}.
114
+ */
115
+ async getCheckEnums(table) {
116
+ const result = await this.client.query(`SELECT n.nspname AS table_schema,
117
+ cl.relname AS table_name,
118
+ a.attname AS column_name,
119
+ pg_get_constraintdef(co.oid) AS def
120
+ FROM pg_constraint co
121
+ JOIN pg_class cl ON cl.oid = co.conrelid
122
+ JOIN pg_namespace n ON n.oid = cl.relnamespace
123
+ JOIN pg_attribute a ON a.attrelid = co.conrelid AND a.attnum = co.conkey[1]
124
+ WHERE co.contype = 'c'
125
+ AND array_length(co.conkey, 1) = 1
126
+ AND n.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
127
+ AND n.nspname NOT LIKE 'pg_temp_%'
128
+ AND ($1::text IS NULL OR (n.nspname = $1 AND cl.relname = $2))`, [table?.schema ?? null, table?.name ?? null]);
129
+ const byTable = new Map();
130
+ for (const r of result.rows) {
131
+ const values = parseCheckEnumValues(r.def);
132
+ if (!values)
133
+ continue;
134
+ const key = tableKey(r.table_schema, r.table_name);
135
+ let cols = byTable.get(key);
136
+ if (!cols) {
137
+ cols = new Map();
138
+ byTable.set(key, cols);
139
+ }
140
+ cols.set(r.column_name, values);
141
+ }
142
+ return byTable;
143
+ }
98
144
  async getForeignKeys(table) {
99
145
  const dotIdx = table.indexOf('.');
100
146
  const schema = dotIdx >= 0 ? table.slice(0, dotIdx) : 'public';
@@ -153,6 +199,7 @@ export class PostgresIntrospector {
153
199
  WHERE c.table_schema NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
154
200
  AND c.table_schema NOT LIKE 'pg_temp_%'
155
201
  ORDER BY c.table_schema, c.table_name, c.ordinal_position`);
202
+ const checkEnums = await this.getCheckEnums();
156
203
  const byTable = new Map();
157
204
  for (const r of result.rows) {
158
205
  if (isMigrationTracking(r.table_name))
@@ -171,6 +218,7 @@ export class PostgresIntrospector {
171
218
  pk: Boolean(r.is_pk),
172
219
  defaultValue: r.column_default,
173
220
  generated: r.is_generated === 'ALWAYS',
221
+ enumValues: checkEnums.get(key)?.get(r.column_name),
174
222
  });
175
223
  }
176
224
  return byTable;
@@ -7,10 +7,9 @@ export declare class SqliteIntrospector implements DbIntrospector {
7
7
  getColumns(table: string): Promise<ColumnInfo[]>;
8
8
  /**
9
9
  * SQLite has no native enums, but a `CHECK (col IN ('a','b',…))` constraint is
10
- * an enum by another name. Parse the table's stored `CREATE TABLE` DDL and map
11
- * each constrained column to its allowed values so codegen can type it as a
12
- * union. Only the positive `col IN (…)` form is recognised (the convention);
13
- * `NOT IN`, ranges, and boolean expressions are left as plain `string`.
10
+ * an enum by another name. Read back the table's stored `CREATE TABLE` DDL —
11
+ * which SQLite keeps verbatim, comments included — and map each constrained
12
+ * column to its allowed values so codegen can type it as a union.
14
13
  */
15
14
  private parseCheckEnums;
16
15
  getForeignKeys(table: string): Promise<ForeignKeyInfo[]>;
@@ -1,4 +1,5 @@
1
1
  import { MIGRATION_TRACKING_TABLE } from '../db-migrator.js';
2
+ import { parseCheckEnumsFromDdl } from '../check-enums.js';
2
3
  const SKIP_TABLES = new Set(['sqlite_sequence', MIGRATION_TRACKING_TABLE]);
3
4
  export class SqliteIntrospector {
4
5
  db;
@@ -34,28 +35,15 @@ export class SqliteIntrospector {
34
35
  }
35
36
  /**
36
37
  * SQLite has no native enums, but a `CHECK (col IN ('a','b',…))` constraint is
37
- * an enum by another name. Parse the table's stored `CREATE TABLE` DDL and map
38
- * each constrained column to its allowed values so codegen can type it as a
39
- * union. Only the positive `col IN (…)` form is recognised (the convention);
40
- * `NOT IN`, ranges, and boolean expressions are left as plain `string`.
38
+ * an enum by another name. Read back the table's stored `CREATE TABLE` DDL —
39
+ * which SQLite keeps verbatim, comments included — and map each constrained
40
+ * column to its allowed values so codegen can type it as a union.
41
41
  */
42
42
  parseCheckEnums(table) {
43
- const out = new Map();
44
43
  const row = this.db
45
44
  .prepare(`SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?`)
46
45
  .get(table);
47
- const ddl = row?.sql;
48
- if (!ddl)
49
- return out;
50
- const checkIn = /CHECK\s*\(\s*"?(\w+)"?\s+IN\s*\(([^)]*)\)/gi;
51
- let m;
52
- while ((m = checkIn.exec(ddl))) {
53
- const column = m[1];
54
- const values = [...m[2].matchAll(/'((?:[^']|'')*)'/g)].map((q) => q[1].replace(/''/g, "'"));
55
- if (values.length > 0)
56
- out.set(column, values);
57
- }
58
- return out;
46
+ return row?.sql ? parseCheckEnumsFromDdl(row.sql) : new Map();
59
47
  }
60
48
  async getForeignKeys(table) {
61
49
  const escaped = `"${table.replace(/"/g, '""')}"`;
@@ -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,
@@ -12,12 +12,15 @@ export interface VirtualUserGenOutput {
12
12
  * `pikku persona run` does the same thing from a terminal; this is the same run
13
13
  * started over RPC, from CI or from a console, with the result kept.
14
14
  *
15
- * A virtual user is NOT a workflow and NOT a queued job. It explores, so no two
16
- * attempts take the same steps and there is nothing to replay; and the run
17
- * record already carries the progress a queue would only be holding on the way
18
- * here. So `runVirtualUser` writes the record, kicks the run off without
19
- * awaiting it, and returns the id. The one cost is stated on the record: a
20
- * restart mid-run strands it at `running`.
15
+ * A virtual user is still NOT a workflow: it explores, so no two attempts take
16
+ * the same steps and there is nothing to replay. What it does need is a
17
+ * trigger. `runVirtualUser` writes the record and returns the id; the run
18
+ * itself is dispatched onto `pikku-virtual-user-runs`, at one attempt, because
19
+ * a queue is the only dispatch that survives a deployment which puts each
20
+ * function in its own unit — there is no in-process promise to leave running
21
+ * there, and an RPC to a function nothing triggers has nowhere to land. A
22
+ * project with no queue service keeps the in-process dispatch, which is
23
+ * correct for the single process it runs in.
21
24
  *
22
25
  * Emitted as two files. The schemas are zod, and the inspector reads a zod
23
26
  * schema by importing the module that declares it — which it cannot do for the