@pikku/cli 0.12.96 → 0.12.99

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 (271) hide show
  1. package/console-app/assets/abnfDiagram-VRR7QNED-CytV-CG1.js +1 -0
  2. package/console-app/assets/arc-C5PvmnaA.js +1 -0
  3. package/console-app/assets/architecture-TIHT7OUA-C1_ScvPX.js +1 -0
  4. package/console-app/assets/architectureDiagram-ZJ3FMSHR-CJ2xb7C-.js +36 -0
  5. package/console-app/assets/array-BifhSqXX.js +1 -0
  6. package/console-app/assets/blockDiagram-677ZJIJ3-CCecrBrk.js +132 -0
  7. package/console-app/assets/c4Diagram-LMCZKHZV-CBnpukvQ.js +10 -0
  8. package/console-app/assets/channel-CwDOkXGI.js +1 -0
  9. package/console-app/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  10. package/console-app/assets/chunk-32BRIVSS-D8qWWZRQ.js +1 -0
  11. package/console-app/assets/chunk-52WLFC77-BEpXHMsp.js +10 -0
  12. package/console-app/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  13. package/console-app/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
  14. package/console-app/assets/chunk-C7G6YPKG-DsHUMkOp.js +1 -0
  15. package/console-app/assets/chunk-EX3LRPZG-mM7TjVx9.js +231 -0
  16. package/console-app/assets/chunk-FWX5IMBZ-CndRAn18.js +2 -0
  17. package/console-app/assets/chunk-HOUHSVGY-D1kT8umn.js +1 -0
  18. package/console-app/assets/chunk-ICXQ74PX-CeSaGyro.js +2 -0
  19. package/console-app/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  20. package/console-app/assets/chunk-KEIR6QF5-DNzq6p3w.js +161 -0
  21. package/console-app/assets/chunk-MOJQB5TN-CaZOCHYr.js +88 -0
  22. package/console-app/assets/chunk-OGEWGWER-CnB1CsPt.js +1 -0
  23. package/console-app/assets/chunk-PUDLZKDR-BbGulHJm.js +156 -0
  24. package/console-app/assets/chunk-Q4XR5HBZ-BywwzeeR.js +70 -0
  25. package/console-app/assets/chunk-RYQCIY6F-CV0R1Adv.js +1 -0
  26. package/console-app/assets/chunk-V7JOEXUC-DGFaAWzB.js +206 -0
  27. package/console-app/assets/chunk-VAUOI2AC-DxPUd8Yb.js +1 -0
  28. package/console-app/assets/chunk-VR4S4FIN-D4-UaW_J.js +1 -0
  29. package/console-app/assets/chunk-WYO6CB5R-D_TFN0d9.js +127 -0
  30. package/console-app/assets/chunk-XXDRQBXY-BzVuweA_.js +1 -0
  31. package/console-app/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  32. package/console-app/assets/chunk-ZGVPDNZ5-C6hdkGQb.js +62 -0
  33. package/console-app/assets/chunk-ZIRB5QZD-H-kepumB.js +32 -0
  34. package/console-app/assets/classDiagram-OUVF2IWQ-CTYJkTT0.js +1 -0
  35. package/console-app/assets/classDiagram-v2-EOCWNBFH-CTYJkTT0.js +1 -0
  36. package/console-app/assets/cose-bilkent-JH36ORCC-B6ZPxN6v.js +1 -0
  37. package/console-app/assets/cynefin-VYW2F7L2-D_nmxNz_.js +1 -0
  38. package/console-app/assets/cynefinDiagram-TSTJHNR4-CHy5QN0S.js +62 -0
  39. package/console-app/assets/cytoscape.esm-h6BdjjI9.js +321 -0
  40. package/console-app/assets/dagre-CXRCoUWR.js +1 -0
  41. package/console-app/assets/dagre-VKFMJZFB-DYfukM34.js +4 -0
  42. package/console-app/assets/defaultLocale-C8Fc0cco.js +1 -0
  43. package/console-app/assets/diagram-FQU43EPY-Dgb9TPSB.js +3 -0
  44. package/console-app/assets/diagram-G47NLZAW-CnFNZs9Z.js +24 -0
  45. package/console-app/assets/diagram-NH7WQ7WH-DN7h2DU-.js +24 -0
  46. package/console-app/assets/diagram-OA4YK3LP-RLaQaNtK.js +30 -0
  47. package/console-app/assets/diagram-WEI45ONY-DxHWhVGd.js +41 -0
  48. package/console-app/assets/dist-BaJNIo4I.js +1 -0
  49. package/console-app/assets/ebnfDiagram-CCIWWBDH-UN3Z81-l.js +1 -0
  50. package/console-app/assets/erDiagram-Q63AITRT-C9lGAY3i.js +85 -0
  51. package/console-app/assets/eventmodeling-45OFAUF4-Dc5wNSSK.js +1 -0
  52. package/console-app/assets/flowDiagram-23GEKE2U-zPyGHMi4.js +1 -0
  53. package/console-app/assets/ganttDiagram-NO4QXBWP-CvBjBcdK.js +292 -0
  54. package/console-app/assets/gitGraph-TEB2WS4Q-Cs5Z9jMo.js +1 -0
  55. package/console-app/assets/gitGraphDiagram-IHSO6WYX-B0i_IJ5r.js +106 -0
  56. package/console-app/assets/graphlib-B8gBHxth.js +1 -0
  57. package/console-app/assets/{index-CeQodYfg.js → index-71U8EEj7.js} +155 -153
  58. package/console-app/assets/{index-CyYHTGWZ.css → index-BXMjqLQ5.css} +1 -1
  59. package/console-app/assets/info-DKCQHKI2-DHL0afNl.js +1 -0
  60. package/console-app/assets/infoDiagram-FWYZ7A6U-CBWykodX.js +2 -0
  61. package/console-app/assets/init-D6jRqBbL.js +1 -0
  62. package/console-app/assets/ishikawaDiagram-FXEZZL3T-DM377eW_.js +70 -0
  63. package/console-app/assets/journeyDiagram-5HDEW3XC-BpX_-Cns.js +139 -0
  64. package/console-app/assets/kanban-definition-HUTT4EX6-D3xFsQkO.js +89 -0
  65. package/console-app/assets/katex-Vhh-h91d.js +257 -0
  66. package/console-app/assets/line-CTSKHTE0.js +1 -0
  67. package/console-app/assets/linear-R5GlBvXT.js +1 -0
  68. package/console-app/assets/map-DsCK-0Cs.js +1 -0
  69. package/console-app/assets/mermaid-parser.core-CkHk4BPi.js +7 -0
  70. package/console-app/assets/mermaid.core-CcjGXuV6.js +11 -0
  71. package/console-app/assets/mindmap-definition-LN4V7U3C-CtolazqQ.js +96 -0
  72. package/console-app/assets/ordinal-hYBb2elL.js +1 -0
  73. package/console-app/assets/packet-7NZHBO7P-BxSOj_Ny.js +1 -0
  74. package/console-app/assets/path-BWPyau1x.js +1 -0
  75. package/console-app/assets/pegDiagram-2B236MQR-BNsMtxsM.js +1 -0
  76. package/console-app/assets/pie-RZYD4A2V-BbkKQBA5.js +1 -0
  77. package/console-app/assets/pieDiagram-ENE6RG2P-BAZLIz2f.js +39 -0
  78. package/console-app/assets/quadrantDiagram-ABIIQ3AL-Dpvn-1Fs.js +7 -0
  79. package/console-app/assets/radar-I7S5WNFK-B-uKXIAH.js +1 -0
  80. package/console-app/assets/railroad-3IZDKUUU-BHXXK04t.js +1 -0
  81. package/console-app/assets/railroad-abnf-AHOZXSZD-tXSQaBvY.js +1 -0
  82. package/console-app/assets/railroad-ebnf-EBAXGLYW-DG3aohR0.js +1 -0
  83. package/console-app/assets/railroad-peg-LSFZ7HO6-DY_gBA-x.js +1 -0
  84. package/console-app/assets/railroadDiagram-RFXS5EU6-DfUApEQj.js +1 -0
  85. package/console-app/assets/requirementDiagram-TGXJPOKE-B2zX0jqo.js +84 -0
  86. package/console-app/assets/rough.esm-CSKSodPl.js +1 -0
  87. package/console-app/assets/sankeyDiagram-HTMAVEWB-CbQ2zc7z.js +40 -0
  88. package/console-app/assets/sequenceDiagram-DBY2YBRQ-BLT8PXI_.js +162 -0
  89. package/console-app/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
  90. package/console-app/assets/src-BLuPUFWW.js +1 -0
  91. package/console-app/assets/stateDiagram-2N3HPSRC-BvEyVp85.js +1 -0
  92. package/console-app/assets/stateDiagram-v2-6OUMAXLB-RGKS9iU4.js +1 -0
  93. package/console-app/assets/swimlanes-5IMT3BWC-1AZ459s6.js +2 -0
  94. package/console-app/assets/swimlanesDiagram-G3AALYLV-Ck_0-rfN.js +8 -0
  95. package/console-app/assets/timeline-definition-FHXFAJF6-dLuvH4s2.js +120 -0
  96. package/console-app/assets/treeView-QDETBFTQ-xL2msjo2.js +1 -0
  97. package/console-app/assets/treemap-6X3UGDF4-C98ichVP.js +1 -0
  98. package/console-app/assets/vennDiagram-L72KCM5P-HbUmidhv.js +34 -0
  99. package/console-app/assets/wardley-OPB4EBWU-C4gJS-m2.js +1 -0
  100. package/console-app/assets/wardleyDiagram-EHGQE667-B7b-LB02.js +78 -0
  101. package/console-app/assets/xychartDiagram-FW5EYKEG-Cm03zUGy.js +7 -0
  102. package/console-app/index.html +2 -2
  103. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  104. package/dist/.pikku/auth/auth.types.d.ts +1 -1
  105. package/dist/.pikku/auth/auth.types.js +1 -1
  106. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  107. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  108. package/dist/.pikku/cli/pikku-cli-channel.js +1 -6
  109. package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
  110. package/dist/.pikku/cli/pikku-cli-client.gen.js +36 -9
  111. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
  112. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
  113. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  114. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  115. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  116. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +7 -8
  117. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  118. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  119. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  120. package/dist/.pikku/cli/pikku-cli.gen.js +18 -2
  121. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  122. package/dist/.pikku/function/pikku-function-types.gen.d.ts +12 -6
  123. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  124. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  125. package/dist/.pikku/function/pikku-functions-meta.gen.json +39 -30
  126. package/dist/.pikku/function/pikku-functions.gen.js +3 -3
  127. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  128. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  129. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  130. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  131. package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +1 -1
  132. package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +1 -1
  133. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  134. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  135. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  136. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  137. package/dist/.pikku/pikku-services.gen.d.ts +2 -1
  138. package/dist/.pikku/pikku-services.gen.js +1 -0
  139. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  140. package/dist/.pikku/pikku-types.gen.js +1 -1
  141. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  142. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  143. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  144. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  145. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  146. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  147. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +1 -1
  148. package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
  149. package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
  150. package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
  151. package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
  152. package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
  153. package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
  154. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  155. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  156. package/dist/.pikku/schemas/register.gen.js +3 -3
  157. package/dist/.pikku/schemas/schemas/DbResetInput.schema.json +1 -1
  158. package/dist/.pikku/schemas/schemas/{DbSeedInput.schema.json → PikkuVirtualUserFunctionsOutput.schema.json} +1 -1
  159. package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
  160. package/dist/.pikku/scopes/pikku-roles.gen.d.ts +1 -1
  161. package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
  162. package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
  163. package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
  164. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  165. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  166. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  167. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  168. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  169. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  170. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  171. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  172. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  173. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  174. package/dist/.pikku/workflow/meta/allWorkflow.gen.json +20 -14
  175. package/dist/.pikku/workflow/pikku-personas.gen.js +1 -1
  176. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +6 -6
  177. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  178. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  179. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  180. package/dist/bin/pikku-bin.mjs +2 -2
  181. package/dist/src/cli.wiring.js +8 -7
  182. package/dist/src/fabric/functions/validate.function.js +76 -176
  183. package/dist/src/functions/commands/all.d.ts +1 -1
  184. package/dist/src/functions/commands/bootstrap.d.ts +1 -1
  185. package/dist/src/functions/commands/db-audit.js +1 -1
  186. package/dist/src/functions/commands/db-baseline.js +1 -1
  187. package/dist/src/functions/commands/db-check.js +6 -5
  188. package/dist/src/functions/commands/db-codegen.js +1 -1
  189. package/dist/src/functions/commands/db-generate.js +1 -1
  190. package/dist/src/functions/commands/db-migrate.js +1 -1
  191. package/dist/src/functions/commands/db-reset.d.ts +15 -1
  192. package/dist/src/functions/commands/db-reset.js +18 -6
  193. package/dist/src/functions/commands/db-shared.d.ts +14 -0
  194. package/dist/src/functions/commands/deploy-info.d.ts +1 -1
  195. package/dist/src/functions/commands/dev.js +1 -1
  196. package/dist/src/functions/commands/enable.d.ts +8 -8
  197. package/dist/src/functions/commands/new-addon.js +2 -2
  198. package/dist/src/functions/commands/persona-sync.d.ts +1 -1
  199. package/dist/src/functions/commands/persona-sync.js +1 -1
  200. package/dist/src/functions/commands/persona.js +16 -18
  201. package/dist/src/functions/commands/scenario-ladder.js +1 -1
  202. package/dist/src/functions/commands/scenario.js +4 -2
  203. package/dist/src/functions/commands/scopes-shared.d.ts +4 -0
  204. package/dist/src/functions/commands/scopes-shared.js +1 -1
  205. package/dist/src/functions/commands/serve.js +1 -1
  206. package/dist/src/functions/commands/versions-check.js +3 -3
  207. package/dist/src/functions/db/annotation-parser.d.ts +14 -0
  208. package/dist/src/functions/db/annotation-parser.js +50 -2
  209. package/dist/src/functions/db/better-auth-schema.js +2 -1
  210. package/dist/src/functions/db/db-codegen.d.ts +12 -0
  211. package/dist/src/functions/db/db-codegen.js +149 -16
  212. package/dist/src/functions/db/local-db.d.ts +87 -6
  213. package/dist/src/functions/db/local-db.js +202 -35
  214. package/dist/src/functions/db/sqlite/dev-seed.d.ts +12 -0
  215. package/dist/src/functions/db/sqlite/dev-seed.js +23 -0
  216. package/dist/src/functions/db/sqlite/sqlite-runtime-bun.js +1 -1
  217. package/dist/src/functions/validate/bootstrap-checks.d.ts +19 -0
  218. package/dist/src/functions/validate/bootstrap-checks.js +90 -0
  219. package/dist/src/functions/validate/persona-checks.d.ts +24 -0
  220. package/dist/src/functions/validate/persona-checks.js +136 -0
  221. package/dist/src/functions/validate/scenario-file-checks.d.ts +17 -0
  222. package/dist/src/functions/validate/scenario-file-checks.js +123 -0
  223. package/dist/src/functions/validate/shared-checks.d.ts +59 -0
  224. package/dist/src/functions/validate/shared-checks.js +311 -0
  225. package/dist/src/functions/validate/workspace-validate.d.ts +1 -2
  226. package/dist/src/functions/validate/workspace-validate.js +4 -196
  227. package/dist/src/functions/wirings/auth/serialize-auth-gen.js +16 -1
  228. package/dist/src/functions/wirings/auth/serialize-auth-types.d.ts +3 -1
  229. package/dist/src/functions/wirings/auth/serialize-auth-types.js +3 -1
  230. package/dist/src/functions/wirings/channels/pikku-channels.d.ts +1 -1
  231. package/dist/src/functions/wirings/channels/serialize-typed-channel-map.js +10 -2
  232. package/dist/src/functions/wirings/cli/pikku-command-cli-entry.js +9 -4
  233. package/dist/src/functions/wirings/cli/serialize-channel-cli-client.js +32 -10
  234. package/dist/src/functions/wirings/cli/serialize-cli-entrypoint-guard.d.ts +12 -0
  235. package/dist/src/functions/wirings/cli/serialize-cli-entrypoint-guard.js +28 -0
  236. package/dist/src/functions/wirings/cli/serialize-local-cli-bootstrap.js +4 -1
  237. package/dist/src/functions/wirings/console/serialize-console-functions.js +1 -1
  238. package/dist/src/functions/wirings/functions/serialize-addon-types.js +1 -1
  239. package/dist/src/functions/wirings/functions/serialize-function-types.js +19 -5
  240. package/dist/src/functions/wirings/package/pikku-command-package-types.d.ts +3 -3
  241. package/dist/src/functions/wirings/personas/personas-secrets-file.d.ts +8 -0
  242. package/dist/src/functions/wirings/personas/personas-secrets-file.js +9 -0
  243. package/dist/src/functions/wirings/personas/pikku-command-personas.js +14 -0
  244. package/dist/src/functions/wirings/personas/serialize-personas-secrets.d.ts +16 -0
  245. package/dist/src/functions/wirings/personas/serialize-personas-secrets.js +34 -0
  246. package/dist/src/functions/wirings/queue/serialize-queue-map.js +2 -1
  247. package/dist/src/functions/wirings/queue/serialize-queue-wrapper.js +2 -1
  248. package/dist/src/functions/wirings/virtual-user/pikku-command-virtual-user-functions.d.ts +1 -0
  249. package/dist/src/functions/wirings/virtual-user/pikku-command-virtual-user-functions.js +42 -0
  250. package/dist/src/functions/wirings/virtual-user/serialize-virtual-user-functions.d.ts +28 -0
  251. package/dist/src/functions/wirings/virtual-user/serialize-virtual-user-functions.js +439 -0
  252. package/dist/src/functions/wirings/workflow/serialize-scenario-step-map.js +2 -2
  253. package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +5 -11
  254. package/dist/src/functions/workflows/all.workflow.js +49 -16
  255. package/dist/src/server/bun-server-runner.d.ts +2 -2
  256. package/dist/src/server/bun-server-runner.js +5 -1
  257. package/dist/src/services/cli-logger.service.d.ts +28 -16
  258. package/dist/src/services/cli-logger.service.js +25 -16
  259. package/dist/src/services.js +8 -0
  260. package/dist/src/utils/file-import-path.js +9 -0
  261. package/dist/src/utils/pikku-cli-config.js +7 -0
  262. package/dist/src/utils/resolve-personas.d.ts +4 -9
  263. package/dist/src/utils/resolve-personas.js +4 -15
  264. package/dist/tsconfig.tsbuildinfo +1 -1
  265. package/package.json +11 -11
  266. package/dist/.pikku/schemas/schemas/BootstrapInput.schema.json +0 -1
  267. package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +0 -1
  268. package/dist/src/functions/commands/db-seed.d.ts +0 -1
  269. package/dist/src/functions/commands/db-seed.js +0 -24
  270. package/dist/src/functions/db/sqlite/seed.d.ts +0 -11
  271. package/dist/src/functions/db/sqlite/seed.js +0 -22
@@ -261,9 +261,15 @@
261
261
  "User admin functions": {
262
262
  "nodeId": "User admin functions",
263
263
  "rpcName": "pikkuUserAdminFunctions",
264
- "next": "Events scaffold",
264
+ "next": "Virtual user functions",
265
265
  "stepHash": "831f37173651"
266
266
  },
267
+ "Virtual user functions": {
268
+ "nodeId": "Virtual user functions",
269
+ "rpcName": "pikkuVirtualUserFunctions",
270
+ "next": "Events scaffold",
271
+ "stepHash": "4f96c6158127"
272
+ },
267
273
  "Events scaffold": {
268
274
  "nodeId": "Events scaffold",
269
275
  "rpcName": "pikkuEventsScaffold",
@@ -345,25 +351,25 @@
345
351
  "Re-inspect after agents": {
346
352
  "nodeId": "Re-inspect after agents",
347
353
  "flow": "inline",
348
- "next": "Secrets (post-auth)"
354
+ "next": "Secrets (post-scaffold)"
349
355
  },
350
- "Secrets (post-auth)": {
351
- "nodeId": "Secrets (post-auth)",
356
+ "Secrets (post-scaffold)": {
357
+ "nodeId": "Secrets (post-scaffold)",
352
358
  "rpcName": "pikkuSecrets",
353
- "next": "Credentials (post-auth)",
354
- "stepHash": "f263e11ae304"
359
+ "next": "Credentials (post-scaffold)",
360
+ "stepHash": "39dc613ab885"
355
361
  },
356
- "Credentials (post-auth)": {
357
- "nodeId": "Credentials (post-auth)",
362
+ "Credentials (post-scaffold)": {
363
+ "nodeId": "Credentials (post-scaffold)",
358
364
  "rpcName": "pikkuCredentials",
359
- "next": "Variables (post-auth)",
360
- "stepHash": "ab2438dcbd2b"
365
+ "next": "Variables (post-scaffold)",
366
+ "stepHash": "c9c202f0bf70"
361
367
  },
362
- "Variables (post-auth)": {
363
- "nodeId": "Variables (post-auth)",
368
+ "Variables (post-scaffold)": {
369
+ "nodeId": "Variables (post-scaffold)",
364
370
  "rpcName": "pikkuVariables",
365
371
  "next": "Schemas",
366
- "stepHash": "df261a647c97"
372
+ "stepHash": "047ea7a92357"
367
373
  },
368
374
  "Schemas": {
369
375
  "nodeId": "Schemas",
@@ -628,5 +634,5 @@
628
634
  "entryNodeIds": [
629
635
  "Bootstrap inspect"
630
636
  ],
631
- "graphHash": "a29b47e4387d"
637
+ "graphHash": "c8f162576369"
632
638
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * This file was generated by @pikku/cli@0.12.96
2
+ * This file was generated by @pikku/cli@0.12.99
3
3
  */
4
4
  /** Personas declared with definePersonas() */
5
5
  import { createHttpPersonas } from '@pikku/core/persona';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * This file was generated by @pikku/cli@0.12.96
2
+ * This file was generated by @pikku/cli@0.12.99
3
3
  */
4
4
  import { WorkflowCancelledException } from '@pikku/core/workflow';
5
5
  import { template } from '@pikku/core/workflow';
@@ -20,12 +20,12 @@ export interface TypedWorkflow extends PikkuWorkflowWire {
20
20
  do<T>(stepName: string, fn: () => T | Promise<T>, options?: WorkflowStepOptions): Promise<T>;
21
21
  }
22
22
  /**
23
- * The typed half of a scenario wire: `step` and its `given`/`when`/`then`
24
- * sugar, narrowed to the names declared by `pikkuScenarioStep` in this project.
25
- * The phase only changes the prose the reporter renders.
23
+ * The typed half of a scenario wire: `given`/`when`/`then`, narrowed to the
24
+ * names declared by `pikkuScenarioStep` in this project. `given` and `when`
25
+ * differ only in the prose the reporter renders; `then` additionally makes the
26
+ * step's bindings witnesses rather than alternatives.
26
27
  */
27
28
  export interface TypedScenarioSteps {
28
- step<K extends keyof FlattenedScenarioStepMap>(stepName: string, stepFunc: K, data?: FlattenedScenarioStepMap[K]['input'], options?: ScenarioStepOptions): Promise<FlattenedScenarioStepMap[K]['output']>;
29
29
  given<K extends keyof FlattenedScenarioStepMap>(stepName: string, stepFunc: K, data?: FlattenedScenarioStepMap[K]['input'], options?: ScenarioStepOptions): Promise<FlattenedScenarioStepMap[K]['output']>;
30
30
  when<K extends keyof FlattenedScenarioStepMap>(stepName: string, stepFunc: K, data?: FlattenedScenarioStepMap[K]['input'], options?: ScenarioStepOptions): Promise<FlattenedScenarioStepMap[K]['output']>;
31
31
  then<K extends keyof FlattenedScenarioStepMap>(stepName: string, stepFunc: K, data?: FlattenedScenarioStepMap[K]['input'], options?: ScenarioStepOptions): Promise<FlattenedScenarioStepMap[K]['output']>;
@@ -180,7 +180,7 @@ export declare function pikkuFeature<const Scenarios extends readonly unknown[]>
180
180
  */
181
181
  export type PikkuFunctionScenarioStep<In = unknown, Out = never, Surface extends 'browser' | 'cli' | 'default' = 'default'> = PikkuFunctionSessionless<In, Out, Surface extends 'default' ? 'scenarioStep' : 'scenarioStep' | Surface>;
182
182
  export type PikkuScenarioStepConfigWithSchema<InputSchema extends StandardSchemaV1 | undefined = undefined, OutputSchema extends StandardSchemaV1 | undefined = undefined> = {
183
- /** Registered name — this is the string `scenario.step()` references. */
183
+ /** Registered name — this is the string `scenario.given()` references. */
184
184
  name: string;
185
185
  /**
186
186
  * What this step does, for the console and for whoever reads the source. It
@@ -1,5 +1,5 @@
1
1
  /**
2
- * This file was generated by @pikku/cli@0.12.96
2
+ * This file was generated by @pikku/cli@0.12.99
3
3
  */
4
4
  import { WorkflowCancelledException } from '@pikku/core/workflow';
5
5
  import { template } from '@pikku/core/workflow';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * This file was generated by @pikku/cli@0.12.96
2
+ * This file was generated by @pikku/cli@0.12.99
3
3
  */
4
4
  import { pikkuState } from '@pikku/core/internal';
5
5
  import allWorkflowMeta from './meta/allWorkflow.gen.json' with { type: 'json' };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * This file was generated by @pikku/cli@0.12.96
2
+ * This file was generated by @pikku/cli@0.12.99
3
3
  */
4
4
  import { addWorkflow } from '@pikku/core/workflow';
5
5
  import './pikku-workflow-wirings-meta.gen.js';
@@ -11,8 +11,8 @@ async function checkForUpdate() {
11
11
  })
12
12
  if (!res.ok) return
13
13
  const { version: latest } = await res.json()
14
- if (latest !== '0.12.96') {
15
- process.stderr.write(`\n Update available 0.12.96 → ${latest}\n brew upgrade pikku or npm install -g @pikku/cli\n\n`)
14
+ if (latest !== '0.12.99') {
15
+ process.stderr.write(`\n Update available 0.12.99 → ${latest}\n brew upgrade pikku or npm install -g @pikku/cli\n\n`)
16
16
  }
17
17
  } catch {}
18
18
  }
@@ -22,7 +22,6 @@ import { dbCodegen } from './functions/commands/db-codegen.js';
22
22
  import { dbCheck } from './functions/commands/db-check.js';
23
23
  import { dbBaseline } from './functions/commands/db-baseline.js';
24
24
  import { dbExport } from './functions/commands/db-export.js';
25
- import { dbSeed } from './functions/commands/db-seed.js';
26
25
  import { dbReset } from './functions/commands/db-reset.js';
27
26
  import { dbAudit } from './functions/commands/db-audit.js';
28
27
  import { scopesAudit } from './functions/commands/scopes-audit.js';
@@ -34,7 +33,7 @@ import { workspaceValidate, renderWorkspaceValidate, } from './functions/command
34
33
  import { knowledgeValidate, renderKnowledgeValidate, } from './functions/commands/knowledge-validate.js';
35
34
  import { knowledgeIndex, renderKnowledgeIndex, } from './functions/commands/knowledge-index.js';
36
35
  import { scenarioRun, scenarioList } from './functions/commands/scenario.js';
37
- import { personaList, personaRun, } from './functions/commands/persona.js';
36
+ import { personaList, personaRun } from './functions/commands/persona.js';
38
37
  import { personaSync } from './functions/commands/persona-sync.js';
39
38
  import { pikkuVersionsInit } from './functions/commands/versions-init.js';
40
39
  import { pikkuEmailsInit } from './functions/commands/emails-init.js';
@@ -351,13 +350,15 @@ wireCLI({
351
350
  func: dbExport,
352
351
  description: "Publish this package's schema so projects consuming it as an addon can create its tables",
353
352
  }),
354
- seed: pikkuCLICommand({
355
- func: dbSeed,
356
- description: 'Apply db/seed.sql to the dev database',
357
- }),
358
353
  reset: pikkuCLICommand({
359
354
  func: dbReset,
360
- description: 'Wipe and recreate the dev database (migrate + seed)',
355
+ description: 'Wipe and recreate the dev database: migrate, then apply db/<engine>-dev-seed.sql. Dev only — it refuses to run in production',
356
+ options: {
357
+ noSeed: {
358
+ description: 'Stop after migrating, leaving the database empty. For working on an empty-state or onboarding flow the test data would hide',
359
+ default: false,
360
+ },
361
+ },
361
362
  }),
362
363
  audit: pikkuCLICommand({
363
364
  func: dbAudit,
@@ -6,7 +6,7 @@ import { createRequire } from 'node:module';
6
6
  import { pikkuSessionlessFunc } from '../../../.pikku/pikku-types.gen.js';
7
7
  import { added, changed, removed, dim } from '../lib/output.js';
8
8
  import { typeCheckFrontends } from '../lib/frontend-typecheck.js';
9
- import { runKnowledgeValidate } from '@pikku/knowledge';
9
+ import { readJsonSafe, readTextSafe, runSharedProjectChecks, } from '../../functions/validate/shared-checks.js';
10
10
  const FindingSchema = z.object({
11
11
  id: z.string(),
12
12
  severity: z.enum(['error', 'warn', 'info']),
@@ -47,26 +47,6 @@ async function findProjectRoot(startDir) {
47
47
  dir = parent;
48
48
  }
49
49
  }
50
- async function readJsonSafe(path) {
51
- if (!existsSync(path))
52
- return null;
53
- try {
54
- return JSON.parse(await readFile(path, 'utf8'));
55
- }
56
- catch {
57
- return null;
58
- }
59
- }
60
- async function readTextSafe(path) {
61
- if (!existsSync(path))
62
- return null;
63
- try {
64
- return await readFile(path, 'utf8');
65
- }
66
- catch {
67
- return null;
68
- }
69
- }
70
50
  // List .ts/.tsx source files under a directory (skips node_modules). Used to
71
51
  // scan an app for raw @mantine/core imports and i18n usage.
72
52
  async function listSourceFiles(dir) {
@@ -141,6 +121,23 @@ const SINGLETON_SENSITIVE_PKGS = [
141
121
  'react',
142
122
  'react-dom',
143
123
  ];
124
+ // A file whose name says "this is the login surface". Used to decide whether an
125
+ // app needs the actor quick-login control — an app with no login screen has
126
+ // nothing to attach it to. Matched against the path relative to the app root, so
127
+ // it covers src/pages/LoginPage.tsx as well as Next's app/login/page.tsx.
128
+ const LOGIN_FILE_PATTERN = /(?:^|\/)[\w[\]-]*(?:login|sign-?in)[\w[\]-]*(?:\/|\.)/i;
129
+ // Fingerprints of the dev-only "Sign in as …" quick login (the actor switcher):
130
+ // one click signs in as a declared scenario persona, no password. Any one of
131
+ // these means the app actually wires actor sign-in — the component's own
132
+ // definition is excluded, since defining it without rendering it locks the
133
+ // reviewer out just as thoroughly.
134
+ // Canonical implementation: starter-template's DevActorSwitcher, rendered from
135
+ // LoginPage and backed by signInAsActor() → POST /auth/sign-in/actor.
136
+ const ACTOR_QUICK_LOGIN_PATTERNS = [
137
+ /<\s*DevActorSwitcher\b/,
138
+ /(?<!function\s)\bsignInAsActor\s*\(/,
139
+ /\/auth\/sign-in\/actor/,
140
+ ];
144
141
  // Minimum @pikku/* versions Fabric requires. The pikku packages are versioned
145
142
  // independently (e.g. @pikku/cli moves faster than @pikku/core), so this is a
146
143
  // per-package floor map, not a single number. Only listed packages are
@@ -202,6 +199,19 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
202
199
  findings.push({ id, severity: 'info', message, path, fixHint });
203
200
  };
204
201
  const lines = (...parts) => parts.join('\n');
202
+ // ── everything true of any pikku project ───────────────────────────────
203
+ // Fabric validate is workspace validate plus the deploy-shaped checks. The
204
+ // two used to be separate walks over the same project that duplicated sixteen
205
+ // findings verbatim, and each carried checks the other lacked for no reason
206
+ // anyone could name.
207
+ //
208
+ // knowledge: decisions/internals/one-project-shape-check-two-validators.md
209
+ const shared = await runSharedProjectChecks(root);
210
+ findings.push(...shared.findings);
211
+ const { pikkuConfig, dbEngine } = shared;
212
+ const pikkuConfigPath = join(root, 'pikku.config.json');
213
+ const rootPkgPath = join(root, 'package.json');
214
+ const rootPkg = await readJsonSafe(rootPkgPath);
205
215
  // ── pikkufabric.config.json ────────────────────────────────────────────
206
216
  // Not required to run validate — downgraded to info so any pikku project
207
217
  // can be checked for compatibility before it is linked to a fabric account.
@@ -216,69 +226,6 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
216
226
  else if (fabricConfig.projectId === '__PROJECT_ID__') {
217
227
  info('fabric-config-placeholder-project-id', 'pikkufabric.config.json has a placeholder projectId ("__PROJECT_ID__") — project is not linked', fabricConfigPath, lines('The file exists but still contains the placeholder project id.', 'Run `pikku fabric link` to replace it automatically, or edit the file and set:', '"projectId": "<real-project-id>"'));
218
228
  }
219
- // ── root pikku.config.json ─────────────────────────────────────────────
220
- const pikkuConfigPath = join(root, 'pikku.config.json');
221
- const pikkuConfig = await readJsonSafe(pikkuConfigPath);
222
- if (!pikkuConfig) {
223
- e('pikku-config-missing', 'pikku.config.json not found at project root', pikkuConfigPath, lines('Create `pikku.config.json` at the repo root.', 'Minimum useful shape:', '{', ' "srcDirectories": ["packages/functions/src"],', ' "outDir": "packages/functions/.pikku",', ' "clientFiles": {', ' "rpcMapDeclarationFile": "packages/functions-sdk/src/pikku/rpc-map.gen.d.ts",', ' "reactQueryFile": "packages/functions-sdk/src/pikku/api.gen.ts"', ' }', '}'));
224
- }
225
- else {
226
- if (!pikkuConfig.srcDirectories) {
227
- e('pikku-config-no-src-dirs', 'pikku.config.json missing "srcDirectories"', pikkuConfigPath, 'Add "srcDirectories": ["packages/functions/src"] to pikku.config.json');
228
- }
229
- if (!pikkuConfig.outDir) {
230
- e('pikku-config-no-out-dir', 'pikku.config.json missing "outDir"', pikkuConfigPath, 'Add "outDir": "packages/functions/.pikku" to pikku.config.json');
231
- }
232
- if (!pikkuConfig.clientFiles) {
233
- info('pikku-config-no-client-files', 'pikku.config.json missing "clientFiles" — generated RPC client files and React Query hooks will not be written', pikkuConfigPath, lines('Add a `clientFiles` block to `pikku.config.json`.', 'Recommended values:', '"clientFiles": {', ' "rpcMapDeclarationFile": "packages/functions-sdk/src/pikku/rpc-map.gen.d.ts",', ' "reactQueryFile": "packages/functions-sdk/src/pikku/api.gen.ts"', '}', 'Those files should live in `packages/functions-sdk/src/pikku/` and are generated by Pikku.'));
234
- }
235
- // Each scaffold key gates generation of a public surface the Fabric console
236
- // calls. Missing one means those endpoints are never generated, so the
237
- // console 404s even though the functions/agents/workflows are wired. The
238
- // generated file paths auto-derive from the flag (see pikku-cli-config), so
239
- // setting the flag is sufficient. console/rpc/agent/workflow gate HTTP/RPC
240
- // endpoints the console hits directly → error; events gates the realtime
241
- // channel (feature-dependent, no template ships it yet) → warn.
242
- const REQUIRED_SCAFFOLD = [
243
- {
244
- key: 'console',
245
- severity: 'error',
246
- surface: 'app introspection (console:getFunctionsMeta and friends) — the sandbox builder shows no functions',
247
- value: 'true',
248
- },
249
- {
250
- key: 'rpc',
251
- severity: 'error',
252
- surface: 'the generic /rpc/:name endpoint',
253
- value: 'true',
254
- },
255
- {
256
- key: 'agent',
257
- severity: 'error',
258
- surface: 'the agent endpoints (/rpc/agent/:agentName) — the agent playground 404s',
259
- value: 'true',
260
- },
261
- {
262
- key: 'workflow',
263
- severity: 'error',
264
- surface: 'the workflow endpoints (/workflow/:workflowName/start) — triggering a workflow 404s',
265
- value: 'true',
266
- },
267
- {
268
- key: 'events',
269
- severity: 'warn',
270
- surface: 'the realtime events channel',
271
- value: 'true',
272
- },
273
- ];
274
- for (const s of REQUIRED_SCAFFOLD) {
275
- if (pikkuConfig.scaffold?.[s.key])
276
- continue;
277
- const report = s.severity === 'error' ? e : w;
278
- report(`pikku-config-no-scaffold-${s.key}`, `pikku.config.json scaffold is missing "${s.key}" — ${s.surface} is never generated, so the Fabric console 404s for it`, pikkuConfigPath, lines(`Add "${s.key}" to the scaffold block in pikku.config.json:`, '"scaffold": {', ' "pikkuDir": "packages/functions/src/scaffold",', ` "${s.key}": ${s.value}`, '}', 'Then re-run codegen (`pikku all`) and restart the dev server.'));
279
- }
280
- }
281
- const dbEngine = pikkuConfig?.db?.engine ?? 'sqlite';
282
229
  // ── .gitignore must ignore generated/runtime artifacts ─────────────────
283
230
  // These are regenerated on every dev boot / scaffold / codegen. Committing
284
231
  // them lets a stale copy shadow the freshly generated one — a committed
@@ -318,45 +265,6 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
318
265
  w(`missing-required-file-${relPath.replace(/[^a-z0-9]/gi, '-')}`, `${relPath} is missing — this file must be committed to the project`, join(root, relPath), lines(`Create ${relPath} and commit it.`, 'The starter-template ships a stub you can copy as a starting point.'));
319
266
  }
320
267
  }
321
- // ── knowledge base ─────────────────────────────────────────────────────
322
- // Delegated to the shared checker rather than asserting a list of filenames.
323
- // The three flat files this used to require (design-language.md, security.md,
324
- // technology.md) are not a knowledge base — they are three documents nothing
325
- // can link into, and the profile now organises the same content into sections
326
- // of notes. Fabric adds decisions/design/ on top of what is checked here.
327
- const knowledge = await runKnowledgeValidate(root, join(root, typeof pikkuConfig?.outDir === 'string' ? pikkuConfig.outDir : '.pikku'));
328
- for (const finding of knowledge.findings) {
329
- findings.push({ ...finding, path: join(root, finding.path) });
330
- }
331
- const rootPkgPath = join(root, 'package.json');
332
- const rootPkg = await readJsonSafe(rootPkgPath);
333
- if (!rootPkg) {
334
- e('root-package-missing', 'root package.json not found', rootPkgPath, 'Create a root package.json with workspaces: {"workspaces": ["packages/*", "apps/*"]}');
335
- }
336
- else {
337
- if (!rootPkg.workspaces) {
338
- w('root-package-no-workspaces', 'root package.json missing "workspaces"', rootPkgPath, 'Add "workspaces": ["packages/*", "apps/*"] to enable yarn workspaces');
339
- }
340
- const allDeps = {
341
- ...rootPkg.dependencies,
342
- ...rootPkg.devDependencies,
343
- };
344
- if (!allDeps['@pikku/core']) {
345
- e('missing-core', '@pikku/core not in dependencies', rootPkgPath, 'Add "@pikku/core": "file:./vendor/pikku-core.tgz" to dependencies');
346
- }
347
- // Vendor tgz presence — only check file: deps that reference a vendor/ path
348
- for (const [pkg, spec] of Object.entries(allDeps)) {
349
- if (typeof spec !== 'string' || !spec.startsWith('file:'))
350
- continue;
351
- const relPath = spec.slice(5); // strip 'file:'
352
- if (!relPath.includes('vendor'))
353
- continue;
354
- const absPath = join(root, relPath);
355
- if (!existsSync(absPath)) {
356
- w(`vendor-missing-${pkg.replace(/[@/]/g, '-')}`, `Vendor file missing for ${pkg}: ${relPath}`, absPath, `Run \`pikku pack\` in the pikku source repo and copy the output to ${relPath}`);
357
- }
358
- }
359
- }
360
268
  // ── @pikku/* minimum versions ──────────────────────────────────────────
361
269
  // Scan every workspace manifest for @pikku/* deps below the required floor.
362
270
  // A stale @pikku/cli hangs `pikku dev`; a stale @pikku/core duplicates
@@ -589,16 +497,12 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
589
497
  const functionsSdkPkgName = (await readJsonSafe(join(root, 'packages', 'functions-sdk', 'package.json')))?.name;
590
498
  const themePkgName = (await readJsonSafe(join(root, 'packages', 'mantine-theme', 'package.json')))?.name;
591
499
  const componentsPkgName = (await readJsonSafe(join(root, 'packages', 'components', 'package.json')))?.name;
592
- if (!existsSync(fnDir)) {
593
- e('functions-pkg-missing', 'packages/functions/ directory not found', fnDir, 'Create packages/functions/ as a yarn workspace containing pikku.config.json, src/, and db/sqlite/');
594
- }
595
- else {
500
+ // packages/functions/ presence, its package.json, ESM, zod and layout are all
501
+ // asserted by runSharedProjectChecks everything below is Fabric-specific.
502
+ if (existsSync(fnDir)) {
596
503
  const fnPkgPath = join(fnDir, 'package.json');
597
504
  const fnPkg = await readJsonSafe(fnPkgPath);
598
505
  if (fnPkg) {
599
- if (fnPkg.type !== 'module') {
600
- w('functions-pkg-no-esm', 'packages/functions/package.json is missing "type": "module"', fnPkgPath, 'Add "type": "module" to packages/functions/package.json — Cloudflare Workers require ES modules');
601
- }
602
506
  // #pikku bare import — required by the injected fabric-telemetry.wiring.ts
603
507
  if (!fnPkg.imports?.['#pikku']) {
604
508
  e('functions-pkg-missing-pikku-import', 'packages/functions/package.json is missing a bare "#pikku" entry in "imports" — the Fabric-injected telemetry middleware imports from "#pikku" and will fail to bundle without it', fnPkgPath, 'Add to "imports": { "#pikku": "./.pikku/pikku-types.gen.ts", "#pikku/*": "./.pikku/*" }');
@@ -660,13 +564,11 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
660
564
  e('missing-ai-sdk-core', 'Project declares agent units but `ai` (the Vercel AI SDK) is not in packages/functions dependencies — it is a peer dependency of @pikku/ai-vercel and is not installed automatically', fnPkgPath, 'Run `yarn add ai` in packages/functions — must be in dependencies, not devDependencies');
661
565
  }
662
566
  }
663
- // services.ts
567
+ // services.ts — its absence is reported by runSharedProjectChecks; what
568
+ // Fabric adds is which dialect it builds and whether it reads process.env.
664
569
  const servicesPath = join(fnDir, 'src', 'services.ts');
665
570
  const servicesText = await readTextSafe(servicesPath);
666
- if (!servicesText) {
667
- w('services-missing', 'packages/functions/src/services.ts not found', servicesPath, 'Create services.ts using pikkuServices() with LibsqlWebDialect from @pikku/kysely-sqlite — fabric injects DATABASE_URL at runtime');
668
- }
669
- else {
571
+ if (servicesText) {
670
572
  const usesKysely = /\bKysely\b/.test(servicesText);
671
573
  const usesLibsql = servicesText.includes('@pikku/kysely-sqlite') ||
672
574
  servicesText.includes('LibsqlWebDialect');
@@ -785,13 +687,6 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
785
687
  if (m)
786
688
  nums.push(parseInt(m[1], 10));
787
689
  }
788
- for (let idx = 1; idx < nums.length; idx++) {
789
- if (nums[idx] !== nums[idx - 1] + 1) {
790
- const missing = `${nums[idx - 1] + 1}..${nums[idx] - 1}`;
791
- e('migration-gap', `Migration numbering gap: IDs ${missing} are missing`, migrationsDir, 'Migrations must be consecutive. Add the missing .sql file or renumber if not yet applied.');
792
- break;
793
- }
794
- }
795
690
  if (dbEngine !== 'postgres') {
796
691
  // Check for PostgreSQL-specific syntax — Fabric uses Turso (SQLite/libSQL)
797
692
  for (const f of files) {
@@ -809,13 +704,13 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
809
704
  // readdir failure — skip
810
705
  }
811
706
  }
812
- const seedPath = join(root, 'db', dbEngine === 'postgres' ? 'postgres-seed.sql' : 'sqlite-seed.sql');
813
- if (!existsSync(seedPath)) {
814
- e('seed-sql-missing', dbEngine === 'postgres'
815
- ? 'db/postgres-seed.sql not found'
816
- : 'db/sqlite-seed.sql not found', seedPath, dbEngine === 'postgres'
817
- ? lines('Create `db/postgres-seed.sql`.', 'Use idempotent INSERT statements suitable for local/dev/test setup.', 'Keep it safe to re-run.')
818
- : lines('Create `db/sqlite-seed.sql`.', 'Use idempotent `INSERT OR IGNORE` statements for local/dev/test data.', 'Keep it safe to re-run.'));
707
+ const devSeedPath = join(root, 'db', dbEngine === 'postgres' ? 'postgres-dev-seed.sql' : 'sqlite-dev-seed.sql');
708
+ if (!existsSync(devSeedPath)) {
709
+ e('dev-seed-sql-missing', dbEngine === 'postgres'
710
+ ? 'db/postgres-dev-seed.sql not found'
711
+ : 'db/sqlite-dev-seed.sql not found', devSeedPath, dbEngine === 'postgres'
712
+ ? lines('Create `db/postgres-dev-seed.sql`.', 'Use idempotent INSERT statements suitable for local/dev/test setup.', 'Keep it safe to re-run.')
713
+ : lines('Create `db/sqlite-dev-seed.sql`.', 'Use idempotent `INSERT OR IGNORE` statements for local/dev/test data.', 'Keep it safe to re-run.'));
819
714
  }
820
715
  // audit table — info if not present (optional feature)
821
716
  if (existsSync(migrationsDir)) {
@@ -831,27 +726,6 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
831
726
  // readdir failure — skip
832
727
  }
833
728
  }
834
- // db.types.ts — should only re-export from .pikku
835
- const dbTypesPath = join(fnDir, 'src', 'types', 'db.types.ts');
836
- const dbTypesText = await readTextSafe(dbTypesPath);
837
- if (dbTypesText) {
838
- const isReexport = dbTypesText.includes('.pikku/db/schema') ||
839
- dbTypesText.includes('.pikku\\db\\schema');
840
- const hasInlineTypes = /(?:^|\n)\s*(?:export\s+)?(?:interface\s+\w|type\s+\w+\s*=)/.test(dbTypesText);
841
- if (hasInlineTypes && !isReexport) {
842
- w('db-types-hand-edited', 'src/types/db.types.ts contains inline type definitions — it should only re-export from .pikku', dbTypesPath, "Replace the file with a single line: export type { DB } from '../../.pikku/db/schema.gen.js' then run `yarn db:types` to regenerate");
843
- }
844
- }
845
- // Structure: src/functions/, src/wirings/, src/config.ts
846
- if (!existsSync(join(fnDir, 'src', 'functions'))) {
847
- info('functions-dir-missing', 'packages/functions/src/functions/ not found', join(fnDir, 'src', 'functions'), 'Create src/functions/ to hold pikkuSessionlessFunc definitions (one function per file)');
848
- }
849
- if (!existsSync(join(fnDir, 'src', 'wirings'))) {
850
- info('wirings-dir-missing', 'packages/functions/src/wirings/ not found', join(fnDir, 'src', 'wirings'), 'Create src/wirings/ for transport bindings: *.http.ts, *.queue.ts, *.schedule.ts, *.channel.ts, *.cli.ts');
851
- }
852
- if (!existsSync(join(fnDir, 'src', 'config.ts'))) {
853
- info('config-missing', 'packages/functions/src/config.ts not found', join(fnDir, 'src', 'config.ts'), "Create src/config.ts: export const createConfig = pikkuConfig(async () => ({ sqliteDb: '.pikku-runtime/dev.db' }))");
854
- }
855
729
  }
856
730
  // ── declared frontends ────────────────────────────────────────────────
857
731
  // pikkufabric.config.json is unvalidated JSON, so every field below is a
@@ -957,7 +831,7 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
957
831
  const rel = file.slice(appPath.length + 1);
958
832
  const norm = rel.replace(/\\/g, '/');
959
833
  // Paraglide usage: the reactive useLocale() hook or an import from the
960
- // local `@/i18n` scaffold (messages `m`, mKey/mList) — either means
834
+ // local `@/i18n` scaffold (the typed `m` namespace) — either means
961
835
  // strings flow through compiled messages.
962
836
  if (/\buseLocale\s*\(/.test(text) ||
963
837
  /from\s+['"]@\/i18n(?:\/[\w-]+)?['"]/.test(text)) {
@@ -1009,6 +883,37 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
1009
883
  ? [` …and ${rawMantineFiles.length - 10} more`]
1010
884
  : []), 'Keep "@mantine/core/styles.css", @mantine/hooks and @mantine/notifications imports as-is.'));
1011
885
  }
886
+ // ── one-click actor sign-in (the "Sign in as …" quick login) ────────
887
+ // Any frontend that ships a login screen must also ship the dev-only
888
+ // actor switcher, so the app can be reviewed as each scenario persona
889
+ // without knowing a password. Without it the reviewer is locked out of
890
+ // their own sandbox. Only fires when a login surface exists — an app
891
+ // with no auth has nothing to attach the control to.
892
+ // Next.js keeps its routes outside src/, so scan app/ and pages/ too.
893
+ const isNextApp = !!appAllDeps['next'];
894
+ const uiFiles = isNextApp
895
+ ? [
896
+ ...srcFiles,
897
+ ...(await listSourceFiles(join(appPath, 'app'))),
898
+ ...(await listSourceFiles(join(appPath, 'pages'))),
899
+ ]
900
+ : srcFiles;
901
+ const loginFiles = [];
902
+ let hasQuickLogin = false;
903
+ for (const file of uiFiles) {
904
+ const text = await readTextSafe(file);
905
+ if (!text)
906
+ continue;
907
+ const rel = file.slice(appPath.length + 1).replace(/\\/g, '/');
908
+ if (LOGIN_FILE_PATTERN.test(rel))
909
+ loginFiles.push(rel);
910
+ if (ACTOR_QUICK_LOGIN_PATTERNS.some((p) => p.test(text))) {
911
+ hasQuickLogin = true;
912
+ }
913
+ }
914
+ if (loginFiles.length > 0 && !hasQuickLogin) {
915
+ e(`app-missing-actor-quick-login-${name}`, `apps/${name} has a login screen (${loginFiles[0]}) but no one-click actor sign-in — nobody can view the app as a scenario persona without a password`, join(appPath, loginFiles[0]), lines('Add the dev-only "Sign in as …" switcher and render it from the login screen:', '1. lib/auth: devActors() reading the DEV_ACTORS env var, and', ' signInAsActor(email) → POST `${apiUrl()}/auth/sign-in/actor`', ' with { email, secret } and credentials: "include".', '2. components/DevActorSwitcher.tsx: a Menu of the declared actors,', ' each Menu.Item signing in as that persona. Render null when', ' devActors() is empty, so it disappears in production.', `3. Render <DevActorSwitcher /> from ${loginFiles[0]}.`, 'Reference: templates/starter-template/apps/app/src/components/DevActorSwitcher.tsx.'));
916
+ }
1012
917
  }
1013
918
  }
1014
919
  // ── singleton-sensitive deps must resolve to ONE physical copy ─────────
@@ -1155,11 +1060,6 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
1155
1060
  if (!existsSync(join(root, 'packages', 'components'))) {
1156
1061
  info('components-missing', 'packages/components/ not found — Fabric design features require a components package', join(root, 'packages', 'components'), `Create packages/components/ with your shared UI components. See ${designDocUrl}`);
1157
1062
  }
1158
- // ── packages/functions-sdk/ ───────────────────────────────────────────
1159
- const sdkDir = join(root, 'packages', 'functions-sdk');
1160
- if (!existsSync(sdkDir)) {
1161
- info('functions-sdk-missing', 'packages/functions-sdk/ not found — generated RPC client and React Query hooks will not be available', sdkDir, lines('Create a workspace at `packages/functions-sdk/`.', 'Minimum structure:', '- packages/functions-sdk/package.json', '- packages/functions-sdk/src/pikku/', 'Point `pikku.config.json` clientFiles to:', '- packages/functions-sdk/src/pikku/rpc-map.gen.d.ts', '- packages/functions-sdk/src/pikku/api.gen.ts', 'This package is the home for generated client artifacts, not handwritten server code.'));
1162
- }
1163
1063
  // ── frontend type-check (what the build container actually runs) ───────
1164
1064
  // Every check above is a heuristic standing in for this compile. The build
1165
1065
  // container type-checks each deployable frontend and aborts the deploy on a
@@ -1 +1 @@
1
- export declare const all: import("#pikku").PikkuFunctionConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
1
+ export declare const all: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
@@ -1 +1 @@
1
- export declare const bootstrap: import("#pikku").PikkuFunctionConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
1
+ export declare const bootstrap: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
@@ -7,7 +7,7 @@ export const dbAudit = pikkuSessionlessFunc({
7
7
  const userConfig = await loadUserConfigForDb({ config, logger });
8
8
  if (!userConfig)
9
9
  return;
10
- const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
10
+ const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir, config.db);
11
11
  if (!resolved) {
12
12
  logger.error('pikku db audit: no database configured — set sqliteDb or postgresUrl in your createConfig.');
13
13
  throw new Error('no database configured');
@@ -19,7 +19,7 @@ export const dbBaseline = pikkuSessionlessFunc({
19
19
  const userConfig = await loadUserConfigForDb({ config, logger });
20
20
  if (!userConfig)
21
21
  return;
22
- const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
22
+ const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir, config.db);
23
23
  if (!resolved) {
24
24
  logger.error('pikku db baseline: no database configured — set sqliteDb or postgresUrl in your createConfig.');
25
25
  throw new Error('no database configured');
@@ -18,17 +18,18 @@ export const dbCheck = pikkuSessionlessFunc({
18
18
  const userConfig = await loadUserConfigForDb({ config, logger });
19
19
  if (!userConfig)
20
20
  return;
21
- const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
21
+ const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir, config.db);
22
22
  if (!resolved) {
23
23
  logger.error('pikku db check: no database configured — set sqliteDb or postgresUrl in your createConfig.');
24
24
  throw new Error('no database configured');
25
25
  }
26
26
  const drift = await computeSchemaDrift(resolved, config.rootDir, config.srcDirectories, logger);
27
- // Table names elide the `public` schema, which reads as ambiguous in a
28
- // report whose whole point can be a second copy of `app.orders` sitting in
29
- // `public`. Put the schema back for display only.
27
+ // Table names elide the schema they landed in, which reads as ambiguous in
28
+ // a report whose whole point can be a second copy of `app.orders` sitting
29
+ // in `public`. Put the schema back for display only — the configured one
30
+ // when there is one, since that is where these tables belong.
30
31
  const qualify = (table) => resolved.dialect === 'postgres' && !table.includes('.')
31
- ? `public.${table}`
32
+ ? `${resolved.schema ?? 'public'}.${table}`
32
33
  : table;
33
34
  if (drift.runtimeTables.length) {
34
35
  logger.info(`db check: ${drift.runtimeTables.length} table(s) the pikku runtime created at boot, which no migration records:`);
@@ -17,7 +17,7 @@ export const dbCodegen = pikkuSessionlessFunc({
17
17
  const userConfig = await loadUserConfigForDb({ config, logger });
18
18
  if (!userConfig)
19
19
  return;
20
- const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
20
+ const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir, config.db);
21
21
  if (!resolved) {
22
22
  logger.error('pikku db codegen: no database configured — set sqliteDb or postgresUrl in your createConfig.');
23
23
  throw new Error('no database configured');
@@ -7,7 +7,7 @@ export const dbGenerate = pikkuSessionlessFunc({
7
7
  const userConfig = await loadUserConfigForDb({ config, logger });
8
8
  if (!userConfig)
9
9
  return;
10
- const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
10
+ const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir, config.db);
11
11
  if (!resolved) {
12
12
  logger.error('pikku db generate: no database configured — set sqliteDb or postgresUrl in your createConfig.');
13
13
  throw new Error('no database configured');
@@ -7,7 +7,7 @@ export const dbMigrate = pikkuSessionlessFunc({
7
7
  const userConfig = await loadUserConfigForDb({ config, logger });
8
8
  if (!userConfig)
9
9
  return;
10
- const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
10
+ const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir, config.db);
11
11
  if (!resolved) {
12
12
  logger.error('pikku db migrate: no database configured — set sqliteDb or postgresUrl in your createConfig.');
13
13
  throw new Error('no database configured');