@pikku/cli 0.12.126 → 0.12.127
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/console-app/assets/{abnfDiagram-N423BO3Z-B2suyn6i.js → abnfDiagram-N423BO3Z-BY2LM8wi.js} +1 -1
- package/console-app/assets/architecture-TIHT7OUA-CWwmvxZF.js +1 -0
- package/console-app/assets/{architectureDiagram-T3A2C74G-BQ5Dfvpo.js → architectureDiagram-T3A2C74G-CeqjY3Kw.js} +1 -1
- package/console-app/assets/{blockDiagram-VBNYF7ZC-D4pVRDiF.js → blockDiagram-VBNYF7ZC-BW5174xj.js} +1 -1
- package/console-app/assets/{c4Diagram-5PPSVZJV-Da04jGpq.js → c4Diagram-5PPSVZJV-B7zXAFL0.js} +1 -1
- package/console-app/assets/channel-pOkwZ_Ot.js +1 -0
- package/console-app/assets/{chunk-2GRJ4B5K-CwODIPP4.js → chunk-2GRJ4B5K-BfRYzQ4t.js} +1 -1
- package/console-app/assets/{chunk-4I5QYGJK-Bep4akjR.js → chunk-4I5QYGJK-DBA7-Nu4.js} +1 -1
- package/console-app/assets/{chunk-5RXB4S5H-CGyCRU9L.js → chunk-5RXB4S5H-D03lNzwi.js} +1 -1
- package/console-app/assets/{chunk-6Q2QTUOP-D0IK0SMT.js → chunk-6Q2QTUOP-DloGRHJZ.js} +1 -1
- package/console-app/assets/{chunk-7Z6QIM7H-D12vS1jX.js → chunk-7Z6QIM7H-DH3uHtl2.js} +1 -1
- package/console-app/assets/{chunk-GF5L2VYU-kOLwTzIA.js → chunk-GF5L2VYU-Cu252lza.js} +1 -1
- package/console-app/assets/{chunk-I66GZJ75-Cb2nDoa3.js → chunk-I66GZJ75-DH54FcuO.js} +1 -1
- package/console-app/assets/{chunk-JQJVKLGR-B3a_ctfQ.js → chunk-JQJVKLGR-CeFuTL-V.js} +1 -1
- package/console-app/assets/{chunk-KBJHAD2P-DeP2Lqwp.js → chunk-KBJHAD2P-B-prFo0-.js} +1 -1
- package/console-app/assets/{chunk-NSK5VX7P-BO8vlGrO.js → chunk-NSK5VX7P-C10iA4GS.js} +1 -1
- package/console-app/assets/{chunk-QR6OTTB3-sX5V0Lok.js → chunk-QR6OTTB3-Cd8apAsA.js} +1 -1
- package/console-app/assets/{chunk-RYQCIY6F-DoCObEhk.js → chunk-RYQCIY6F-rfPUp2Fj.js} +1 -1
- package/console-app/assets/{chunk-UBXNYLIW-BndMXU5r.js → chunk-UBXNYLIW-D25wqJBc.js} +1 -1
- package/console-app/assets/{chunk-W5SLKNZC--VrZN8EC.js → chunk-W5SLKNZC-CJvxkxuK.js} +1 -1
- package/console-app/assets/{chunk-WRU74C26-DdS0mzXO.js → chunk-WRU74C26-B9Wju92P.js} +1 -1
- package/console-app/assets/chunk-XXDRQBXY-BU_UP6f5.js +1 -0
- package/console-app/assets/classDiagram-JCYQIIEL-CLBKUuxj.js +1 -0
- package/console-app/assets/classDiagram-v2-OCEON4UE-CLBKUuxj.js +1 -0
- package/console-app/assets/{cose-bilkent-JH36ORCC-C5EnHkFn.js → cose-bilkent-JH36ORCC-CwA1VCP5.js} +1 -1
- package/console-app/assets/{cynefin-VYW2F7L2-9irdkTt4.js → cynefin-VYW2F7L2-C_qsD7eR.js} +1 -1
- package/console-app/assets/{cynefinDiagram-MW4NZA55-DY19660c.js → cynefinDiagram-MW4NZA55-CkSLreFW.js} +1 -1
- package/console-app/assets/{dagre-VZM6K2ZE-BYFZSaSb.js → dagre-VZM6K2ZE-0ssqLoHs.js} +1 -1
- package/console-app/assets/{dagre-nXgDYqvf.js → dagre-WqgBlKb7.js} +1 -1
- package/console-app/assets/{diagram-7IWD3JNH-oDftiTp1.js → diagram-7IWD3JNH-DmRL3lmL.js} +1 -1
- package/console-app/assets/{diagram-B4RE2ZJO-Cbj-pPbH.js → diagram-B4RE2ZJO-Bsr9wG4I.js} +1 -1
- package/console-app/assets/{diagram-LBJQPF4R-Ch53oSKw.js → diagram-LBJQPF4R-DdMw1FSY.js} +1 -1
- package/console-app/assets/{diagram-Q27KOJAE-DA7K814v.js → diagram-Q27KOJAE-TPx5TB2B.js} +1 -1
- package/console-app/assets/{diagram-UB23O5K3-B-_C-ctS.js → diagram-UB23O5K3-e_1zSlZR.js} +1 -1
- package/console-app/assets/{ebnfDiagram-BXEA7PRR-DsOdsKXy.js → ebnfDiagram-BXEA7PRR-BACajh2b.js} +1 -1
- package/console-app/assets/{erDiagram-JOGREHBK-XB1mP5_A.js → erDiagram-JOGREHBK-CojomKqL.js} +1 -1
- package/console-app/assets/eventmodeling-45OFAUF4-DkN2KCrT.js +1 -0
- package/console-app/assets/flowDiagram-UKHOOZJN-DL0M9lBc.js +1 -0
- package/console-app/assets/{ganttDiagram-PKOTCBZU-knk0XSHi.js → ganttDiagram-PKOTCBZU-yoOX4Xj2.js} +1 -1
- package/console-app/assets/{gitGraph-TEB2WS4Q-COJnK2tM.js → gitGraph-TEB2WS4Q-BcUY5hIc.js} +1 -1
- package/console-app/assets/{gitGraphDiagram-DS77QQ5N-sF0v605q.js → gitGraphDiagram-DS77QQ5N-BtuIPjuB.js} +1 -1
- package/console-app/assets/{index-DMnbsgzs.js → index-CzWW052c.js} +151 -151
- package/console-app/assets/{info-DKCQHKI2-Cbatr0w6.js → info-DKCQHKI2-B-iR9PUz.js} +1 -1
- package/console-app/assets/{infoDiagram-6WML65LV-93TFPCu2.js → infoDiagram-6WML65LV-CuXKIFH2.js} +1 -1
- package/console-app/assets/{ishikawaDiagram-WSZJBQD7-BBR8_Qms.js → ishikawaDiagram-WSZJBQD7-CSueMFD6.js} +1 -1
- package/console-app/assets/{journeyDiagram-NVQOT4AX-zG55yDoc.js → journeyDiagram-NVQOT4AX-kvnKStZp.js} +1 -1
- package/console-app/assets/{kanban-definition-27J2QSJJ-DonGcEAY.js → kanban-definition-27J2QSJJ-CGGDEz30.js} +1 -1
- package/console-app/assets/{line-D1WdVm1S.js → line-mtMM5-xO.js} +1 -1
- package/console-app/assets/{linear-D2GQL4Cm.js → linear-CLSje0O_.js} +1 -1
- package/console-app/assets/{mermaid-parser.core-b4yKyO56.js → mermaid-parser.core-Cx6yvn3j.js} +3 -3
- package/console-app/assets/{mermaid.core-Cwfec1gr.js → mermaid.core-BebGyklS.js} +4 -4
- package/console-app/assets/{mindmap-definition-FAOFIHXS-D0G4yKgw.js → mindmap-definition-FAOFIHXS-C2_WUUJ9.js} +1 -1
- package/console-app/assets/{packet-7NZHBO7P-DDa4HL2T.js → packet-7NZHBO7P-Dh5yNCA8.js} +1 -1
- package/console-app/assets/{pegDiagram-VL7TDLO6-fPdN5VZs.js → pegDiagram-VL7TDLO6-XgUxesi8.js} +1 -1
- package/console-app/assets/{pie-RZYD4A2V-DRHURUqo.js → pie-RZYD4A2V-D2x2RAXI.js} +1 -1
- package/console-app/assets/{pieDiagram-7S7Q4E2Y-DMYn8ga_.js → pieDiagram-7S7Q4E2Y-Bbor0KbG.js} +1 -1
- package/console-app/assets/{quadrantDiagram-CIZ2JOQS-C190OamC.js → quadrantDiagram-CIZ2JOQS-DZmnMHpM.js} +1 -1
- package/console-app/assets/{radar-I7S5WNFK-Djvqzz9A.js → radar-I7S5WNFK-CPeriDtN.js} +1 -1
- package/console-app/assets/{railroad-3IZDKUUU-C9YvFeFq.js → railroad-3IZDKUUU-2iKAyaie.js} +1 -1
- package/console-app/assets/railroad-abnf-AHOZXSZD-D26xz4MM.js +1 -0
- package/console-app/assets/railroad-ebnf-EBAXGLYW-CCAiMPWc.js +1 -0
- package/console-app/assets/railroad-peg-LSFZ7HO6-BA1zcisq.js +1 -0
- package/console-app/assets/{railroadDiagram-AXF67PYL-IRFg1VrU.js → railroadDiagram-AXF67PYL-DVEqCXoo.js} +1 -1
- package/console-app/assets/{requirementDiagram-LRYGKXZP-L-7ubbcT.js → requirementDiagram-LRYGKXZP-CSgSNL8p.js} +1 -1
- package/console-app/assets/{sankeyDiagram-W5VNT64P-DBttV6Gt.js → sankeyDiagram-W5VNT64P-CFk11odN.js} +1 -1
- package/console-app/assets/{sequenceDiagram-SI44F4Z6-Bg15oKAB.js → sequenceDiagram-SI44F4Z6-Cb5u6FsJ.js} +1 -1
- package/console-app/assets/{src-DUC7tLWb.js → src-LceHEY_Q.js} +1 -1
- package/console-app/assets/{stateDiagram-OKZ733FA-PWl0XGs5.js → stateDiagram-OKZ733FA-DM1jWlkU.js} +1 -1
- package/console-app/assets/stateDiagram-v2-UEYNNEHI-COVnPYic.js +1 -0
- package/console-app/assets/{swimlanes-SLNWSIFB-CyXEtGBV.js → swimlanes-SLNWSIFB-DD6MchlE.js} +1 -1
- package/console-app/assets/swimlanesDiagram-ULZ7WXOC-B5q8iRCQ.js +8 -0
- package/console-app/assets/{timeline-definition-Z64GVDOM-BLA-DhBt.js → timeline-definition-Z64GVDOM-zu5cNnVv.js} +1 -1
- package/console-app/assets/{treeView-QDETBFTQ-Bfnmn2UY.js → treeView-QDETBFTQ-D_4IbvCG.js} +1 -1
- package/console-app/assets/{treemap-6X3UGDF4-DTA0wveO.js → treemap-6X3UGDF4-DNc6bjUc.js} +1 -1
- package/console-app/assets/{vennDiagram-T6HMQDX7-CLXYZln0.js → vennDiagram-T6HMQDX7-DfqoG28f.js} +1 -1
- package/console-app/assets/{wardley-OPB4EBWU-zwxqisG0.js → wardley-OPB4EBWU-BqpI2Lx-.js} +1 -1
- package/console-app/assets/{wardleyDiagram-T6FBY63Y-hKtKvNlv.js → wardleyDiagram-T6FBY63Y-CLIZSvNi.js} +1 -1
- package/console-app/assets/{xychartDiagram-ELKLHX3M-BGf8p4bo.js → xychartDiagram-ELKLHX3M-Cni-XXa6.js} +1 -1
- package/console-app/index.html +1 -1
- package/dist/.pikku/addon/index.d.ts +1 -1
- package/dist/.pikku/addon/index.js +1 -1
- package/dist/.pikku/addon/pikku-addon-types.gen.d.ts +1 -1
- package/dist/.pikku/addon/pikku-addon-types.gen.js +1 -1
- package/dist/.pikku/agent/index.d.ts +1 -1
- package/dist/.pikku/agent/index.js +1 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/agent/pikku-model-aliases.gen.js +1 -1
- package/dist/.pikku/auth/index.d.ts +1 -1
- package/dist/.pikku/auth/index.js +1 -1
- package/dist/.pikku/auth/pikku-auth-types.gen.d.ts +1 -1
- package/dist/.pikku/auth/pikku-auth-types.gen.js +1 -1
- package/dist/.pikku/channel/index.d.ts +1 -1
- package/dist/.pikku/channel/index.js +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/index.d.ts +1 -1
- package/dist/.pikku/cli/index.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +21 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.json +103 -0
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +103 -0
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/error/index.d.ts +1 -1
- package/dist/.pikku/error/index.js +1 -1
- package/dist/.pikku/error/pikku-error-types.gen.d.ts +1 -1
- package/dist/.pikku/error/pikku-error-types.gen.js +1 -1
- package/dist/.pikku/function/index.d.ts +1 -1
- package/dist/.pikku/function/index.js +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +79 -3
- package/dist/.pikku/function/pikku-functions.gen.js +1 -1
- package/dist/.pikku/gateway/index.d.ts +1 -1
- package/dist/.pikku/gateway/index.js +1 -1
- package/dist/.pikku/gateway/pikku-gateway-types.gen.d.ts +1 -1
- package/dist/.pikku/gateway/pikku-gateway-types.gen.js +1 -1
- package/dist/.pikku/http/index.d.ts +1 -1
- package/dist/.pikku/http/index.js +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
- package/dist/.pikku/mcp/index.d.ts +1 -1
- package/dist/.pikku/mcp/index.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
- package/dist/.pikku/middleware/index.d.ts +1 -1
- package/dist/.pikku/middleware/index.js +1 -1
- package/dist/.pikku/middleware/pikku-middleware-types.gen.d.ts +1 -1
- package/dist/.pikku/middleware/pikku-middleware-types.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +1 -1
- package/dist/.pikku/queue/index.d.ts +1 -1
- package/dist/.pikku/queue/index.js +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +4 -0
- package/dist/.pikku/scenarios/index.d.ts +1 -1
- package/dist/.pikku/scenarios/index.js +1 -1
- package/dist/.pikku/scenarios/pikku-personas.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-types.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
- package/dist/.pikku/scheduler/index.d.ts +1 -1
- package/dist/.pikku/scheduler/index.js +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +17 -1
- package/dist/.pikku/schemas/schemas/FabricFindingsClearInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricFindingsClearOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricFindingsFlushInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricFindingsFlushOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricFindingsListInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricFindingsListOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricReportInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricReportOutput.schema.json +1 -0
- package/dist/.pikku/scopes/index.d.ts +1 -1
- package/dist/.pikku/scopes/index.js +1 -1
- package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-roles.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
- package/dist/.pikku/secrets/index.d.ts +1 -1
- package/dist/.pikku/secrets/index.js +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
- package/dist/.pikku/services/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/services/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/setup/index.d.ts +1 -1
- package/dist/.pikku/setup/index.js +1 -1
- package/dist/.pikku/setup/pikku-setup-types.gen.d.ts +1 -1
- package/dist/.pikku/setup/pikku-setup-types.gen.js +1 -1
- package/dist/.pikku/trigger/index.d.ts +1 -1
- package/dist/.pikku/trigger/index.js +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
- package/dist/.pikku/variables/index.d.ts +1 -1
- package/dist/.pikku/variables/index.js +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
- package/dist/.pikku/workflow/index.d.ts +1 -1
- package/dist/.pikku/workflow/index.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/bin/pikku-bin.mjs +2 -2
- package/dist/src/fabric/fabric-commands.d.ts +138 -0
- package/dist/src/fabric/fabric-commands.js +65 -0
- package/dist/src/fabric/functions/findings-clear.function.d.ts +12 -0
- package/dist/src/fabric/functions/findings-clear.function.js +17 -0
- package/dist/src/fabric/functions/findings-flush.function.d.ts +33 -0
- package/dist/src/fabric/functions/findings-flush.function.js +36 -0
- package/dist/src/fabric/functions/findings-list.function.d.ts +55 -0
- package/dist/src/fabric/functions/findings-list.function.js +52 -0
- package/dist/src/fabric/functions/report.function.d.ts +121 -0
- package/dist/src/fabric/functions/report.function.js +84 -0
- package/dist/src/fabric/lib/finding-spool.d.ts +56 -0
- package/dist/src/fabric/lib/finding-spool.js +105 -0
- package/dist/src/fabric/lib/finding.d.ts +92 -0
- package/dist/src/fabric/lib/finding.js +156 -0
- package/dist/src/fabric/lib/report-environment.d.ts +53 -0
- package/dist/src/fabric/lib/report-environment.js +119 -0
- package/dist/src/functions/commands/environment.d.ts +5 -0
- package/dist/src/functions/commands/persona.js +1 -0
- package/dist/src/functions/commands/scenario.js +1 -0
- package/dist/src/functions/validate/auth-plugin-checks.d.ts +1 -1
- package/dist/src/functions/validate/auth-plugin-checks.js +8 -5
- package/dist/src/functions/validate/persona-checks.js +8 -6
- package/dist/src/functions/wirings/user-admin/pikku-command-user-admin-functions.js +10 -5
- package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.d.ts +1 -1
- package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.js +3 -3
- package/dist/src/services.js +9 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/snippets.json +1 -1
- package/surface.json +2 -2
- package/console-app/assets/architecture-TIHT7OUA-DmG0bXDT.js +0 -1
- package/console-app/assets/channel-BgCT5gon.js +0 -1
- package/console-app/assets/chunk-XXDRQBXY-EP2C9tTO.js +0 -1
- package/console-app/assets/classDiagram-JCYQIIEL-D9wGqB4J.js +0 -1
- package/console-app/assets/classDiagram-v2-OCEON4UE-D9wGqB4J.js +0 -1
- package/console-app/assets/eventmodeling-45OFAUF4-NKFCZ8Fj.js +0 -1
- package/console-app/assets/flowDiagram-UKHOOZJN-BpdPkmum.js +0 -1
- package/console-app/assets/railroad-abnf-AHOZXSZD-B3CYVW4p.js +0 -1
- package/console-app/assets/railroad-ebnf-EBAXGLYW-DrZ2yF62.js +0 -1
- package/console-app/assets/railroad-peg-LSFZ7HO6-CWAmMyxd.js +0 -1
- package/console-app/assets/stateDiagram-v2-UEYNNEHI-Celbgz4u.js +0 -1
- package/console-app/assets/swimlanesDiagram-ULZ7WXOC-zxpNaB4U.js +0 -8
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ReportEnvironment } from './report-environment.js';
|
|
3
|
+
export declare const FindingInput: z.ZodObject<{
|
|
4
|
+
title: z.ZodString;
|
|
5
|
+
kind: z.ZodEnum<{
|
|
6
|
+
product: "product";
|
|
7
|
+
harness: "harness";
|
|
8
|
+
}>;
|
|
9
|
+
model: z.ZodString;
|
|
10
|
+
expected: z.ZodString;
|
|
11
|
+
actual: z.ZodString;
|
|
12
|
+
skill: z.ZodOptional<z.ZodString>;
|
|
13
|
+
passage: z.ZodOptional<z.ZodString>;
|
|
14
|
+
command: z.ZodOptional<z.ZodString>;
|
|
15
|
+
error: z.ZodOptional<z.ZodString>;
|
|
16
|
+
repro: z.ZodOptional<z.ZodString>;
|
|
17
|
+
workaround: z.ZodOptional<z.ZodString>;
|
|
18
|
+
proposal: z.ZodOptional<z.ZodString>;
|
|
19
|
+
tried: z.ZodOptional<z.ZodString>;
|
|
20
|
+
unresolved: z.ZodOptional<z.ZodBoolean>;
|
|
21
|
+
area: z.ZodOptional<z.ZodString>;
|
|
22
|
+
surface: z.ZodOptional<z.ZodEnum<{
|
|
23
|
+
local: "local";
|
|
24
|
+
deployed: "deployed";
|
|
25
|
+
both: "both";
|
|
26
|
+
}>>;
|
|
27
|
+
cost: z.ZodOptional<z.ZodString>;
|
|
28
|
+
run: z.ZodOptional<z.ZodString>;
|
|
29
|
+
deployTarget: z.ZodOptional<z.ZodString>;
|
|
30
|
+
}, z.core.$strip>;
|
|
31
|
+
export type FindingInput = z.infer<typeof FindingInput>;
|
|
32
|
+
export type ParsedFinding = {
|
|
33
|
+
finding: FindingInput;
|
|
34
|
+
} | {
|
|
35
|
+
problems: string[];
|
|
36
|
+
};
|
|
37
|
+
/** Shape-check a finding from either path, naming every field that is wrong. */
|
|
38
|
+
export declare function parseFinding(value: unknown): ParsedFinding;
|
|
39
|
+
/**
|
|
40
|
+
* A finding read as JSON rather than assembled out of flags.
|
|
41
|
+
*
|
|
42
|
+
* Half the fields are prose, and prose carries apostrophes, quotes, backticks
|
|
43
|
+
* and newlines — every one of them a shell metacharacter before it is a
|
|
44
|
+
* character in a sentence. An error message pasted into `--error` breaks the
|
|
45
|
+
* command at its first newline; one carrying a backtick runs whatever follows
|
|
46
|
+
* it. JSON has its own escaping, so this path has none of that.
|
|
47
|
+
*
|
|
48
|
+
* Returns the finding or the problems with it, never throws: a malformed
|
|
49
|
+
* payload is a usage mistake worth naming precisely.
|
|
50
|
+
*/
|
|
51
|
+
export declare function parseFindingJson(raw: string): ParsedFinding;
|
|
52
|
+
export interface FindingPayload extends Omit<FindingInput, 'run'> {
|
|
53
|
+
runId?: string;
|
|
54
|
+
environment: ReportEnvironment;
|
|
55
|
+
reportedAt: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The rules the field set exists to enforce, checked before anything is sent.
|
|
59
|
+
*
|
|
60
|
+
* A usage mistake is the agent's own and is worth failing loudly for — unlike a
|
|
61
|
+
* failed send, which must never surface as a build failure. Every problem is
|
|
62
|
+
* returned at once so a malformed call is fixed in one pass.
|
|
63
|
+
*/
|
|
64
|
+
export declare function validateFinding(input: FindingInput): string[];
|
|
65
|
+
export declare function buildFindingPayload(input: FindingInput, environment: ReportEnvironment, now?: Date): FindingPayload;
|
|
66
|
+
/**
|
|
67
|
+
* Best-effort by construction. A finding is worth having and never worth
|
|
68
|
+
* failing a build for, so a refused, slow or unreachable endpoint is reported
|
|
69
|
+
* to the terminal and swallowed.
|
|
70
|
+
*/
|
|
71
|
+
export declare function postFinding(opts: {
|
|
72
|
+
apiUrl: string;
|
|
73
|
+
token: string;
|
|
74
|
+
/**
|
|
75
|
+
* Provenance, not a routing key. A finding is about the framework rather
|
|
76
|
+
* than about anyone's project, and the reports worth having most — a
|
|
77
|
+
* scaffold that never produced a config, a first run that went wrong — come
|
|
78
|
+
* from checkouts that have no project to name.
|
|
79
|
+
*/
|
|
80
|
+
projectId: string | null;
|
|
81
|
+
payload: FindingPayload;
|
|
82
|
+
timeoutMs?: number;
|
|
83
|
+
}): Promise<{
|
|
84
|
+
sent: boolean;
|
|
85
|
+
reason?: string;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* The receipt. Nothing is written to disk, so the terminal is the only place
|
|
89
|
+
* the user sees what left their machine. Printed before the request goes out,
|
|
90
|
+
* so it is there whether or not the send succeeds.
|
|
91
|
+
*/
|
|
92
|
+
export declare function renderReceipt(payload: FindingPayload): string;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const FindingInput = z.object({
|
|
3
|
+
title: z.string(),
|
|
4
|
+
kind: z.enum(['product', 'harness']),
|
|
5
|
+
model: z.string(),
|
|
6
|
+
expected: z.string(),
|
|
7
|
+
actual: z.string(),
|
|
8
|
+
skill: z.string().optional(),
|
|
9
|
+
passage: z.string().optional(),
|
|
10
|
+
command: z.string().optional(),
|
|
11
|
+
error: z.string().optional(),
|
|
12
|
+
repro: z.string().optional(),
|
|
13
|
+
workaround: z.string().optional(),
|
|
14
|
+
proposal: z.string().optional(),
|
|
15
|
+
tried: z.string().optional(),
|
|
16
|
+
unresolved: z.boolean().optional(),
|
|
17
|
+
area: z.string().optional(),
|
|
18
|
+
surface: z.enum(['local', 'deployed', 'both']).optional(),
|
|
19
|
+
cost: z.string().optional(),
|
|
20
|
+
run: z.string().optional(),
|
|
21
|
+
deployTarget: z.string().optional(),
|
|
22
|
+
});
|
|
23
|
+
/** Shape-check a finding from either path, naming every field that is wrong. */
|
|
24
|
+
export function parseFinding(value) {
|
|
25
|
+
const result = FindingInput.safeParse(value);
|
|
26
|
+
if (result.success)
|
|
27
|
+
return { finding: result.data };
|
|
28
|
+
return {
|
|
29
|
+
problems: result.error.issues.map((issue) => `${issue.path.join('.') || 'finding'}: ${issue.message}`),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A finding read as JSON rather than assembled out of flags.
|
|
34
|
+
*
|
|
35
|
+
* Half the fields are prose, and prose carries apostrophes, quotes, backticks
|
|
36
|
+
* and newlines — every one of them a shell metacharacter before it is a
|
|
37
|
+
* character in a sentence. An error message pasted into `--error` breaks the
|
|
38
|
+
* command at its first newline; one carrying a backtick runs whatever follows
|
|
39
|
+
* it. JSON has its own escaping, so this path has none of that.
|
|
40
|
+
*
|
|
41
|
+
* Returns the finding or the problems with it, never throws: a malformed
|
|
42
|
+
* payload is a usage mistake worth naming precisely.
|
|
43
|
+
*/
|
|
44
|
+
export function parseFindingJson(raw) {
|
|
45
|
+
let parsed;
|
|
46
|
+
try {
|
|
47
|
+
parsed = JSON.parse(raw);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return {
|
|
51
|
+
problems: [`--stdin expected a JSON object (${error.message}).`],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
55
|
+
return { problems: ['--stdin expected a JSON object.'] };
|
|
56
|
+
}
|
|
57
|
+
return parseFinding(parsed);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The rules the field set exists to enforce, checked before anything is sent.
|
|
61
|
+
*
|
|
62
|
+
* A usage mistake is the agent's own and is worth failing loudly for — unlike a
|
|
63
|
+
* failed send, which must never surface as a build failure. Every problem is
|
|
64
|
+
* returned at once so a malformed call is fixed in one pass.
|
|
65
|
+
*/
|
|
66
|
+
export function validateFinding(input) {
|
|
67
|
+
const problems = [];
|
|
68
|
+
if (input.kind === 'harness' && !input.skill) {
|
|
69
|
+
problems.push('A harness finding names the skill that misled you — pass --skill (and --passage for the line it contradicts).');
|
|
70
|
+
}
|
|
71
|
+
if (input.unresolved) {
|
|
72
|
+
if (!input.tried) {
|
|
73
|
+
problems.push('An unresolved finding carries what you tried and how each attempt failed — pass --tried.');
|
|
74
|
+
}
|
|
75
|
+
if (input.workaround) {
|
|
76
|
+
problems.push('Unresolved means no workaround was found. Drop --unresolved, or drop --workaround.');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (!input.workaround && !input.proposal) {
|
|
80
|
+
problems.push('A resolved finding carries the workaround you used — pass --workaround, or --unresolved if there was none.');
|
|
81
|
+
}
|
|
82
|
+
return problems;
|
|
83
|
+
}
|
|
84
|
+
export function buildFindingPayload(input, environment, now = new Date()) {
|
|
85
|
+
const { run, ...rest } = input;
|
|
86
|
+
return { ...rest, runId: run, environment, reportedAt: now.toISOString() };
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Best-effort by construction. A finding is worth having and never worth
|
|
90
|
+
* failing a build for, so a refused, slow or unreachable endpoint is reported
|
|
91
|
+
* to the terminal and swallowed.
|
|
92
|
+
*/
|
|
93
|
+
export async function postFinding(opts) {
|
|
94
|
+
try {
|
|
95
|
+
const response = await fetch(`${opts.apiUrl}/findings`, {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
headers: {
|
|
98
|
+
'content-type': 'application/json',
|
|
99
|
+
authorization: `Bearer ${opts.token}`,
|
|
100
|
+
},
|
|
101
|
+
body: JSON.stringify({
|
|
102
|
+
projectId: opts.projectId,
|
|
103
|
+
finding: opts.payload,
|
|
104
|
+
}),
|
|
105
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? 5000),
|
|
106
|
+
});
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
return { sent: false, reason: `fabric answered ${response.status}` };
|
|
109
|
+
}
|
|
110
|
+
return { sent: true };
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
return { sent: false, reason: error?.message ?? 'request failed' };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* The receipt. Nothing is written to disk, so the terminal is the only place
|
|
118
|
+
* the user sees what left their machine. Printed before the request goes out,
|
|
119
|
+
* so it is there whether or not the send succeeds.
|
|
120
|
+
*/
|
|
121
|
+
export function renderReceipt(payload) {
|
|
122
|
+
const lines = [`[fabric] reporting: ${payload.title}`];
|
|
123
|
+
const field = (label, value) => {
|
|
124
|
+
if (value)
|
|
125
|
+
lines.push(` ${label}: ${value}`);
|
|
126
|
+
};
|
|
127
|
+
field('kind', payload.unresolved ? `${payload.kind} (unresolved)` : payload.kind);
|
|
128
|
+
field('area', payload.area);
|
|
129
|
+
field('skill', payload.passage ? `${payload.skill} — ${payload.passage}` : payload.skill);
|
|
130
|
+
field('command', payload.command);
|
|
131
|
+
field('expected', payload.expected);
|
|
132
|
+
field('actual', payload.actual);
|
|
133
|
+
field('error', payload.error);
|
|
134
|
+
field('surface', payload.surface);
|
|
135
|
+
field('cost', payload.cost);
|
|
136
|
+
field('repro', payload.repro);
|
|
137
|
+
field('workaround', payload.workaround);
|
|
138
|
+
field('tried', payload.tried);
|
|
139
|
+
field('proposal', payload.proposal);
|
|
140
|
+
field('model', payload.model);
|
|
141
|
+
field('run', payload.runId);
|
|
142
|
+
field('deploy target', payload.deployTarget);
|
|
143
|
+
field('reported at', payload.reportedAt);
|
|
144
|
+
const env = payload.environment;
|
|
145
|
+
field('versions', env.packages
|
|
146
|
+
.map((p) => `${p.name}@${p.version}${p.linked ? ' (linked)' : ''}`)
|
|
147
|
+
.join(' ') || 'no @pikku/* found');
|
|
148
|
+
if (env.versionSkew) {
|
|
149
|
+
lines.push(' note: the installed @pikku/* versions are not all the same');
|
|
150
|
+
}
|
|
151
|
+
if (env.linkedFramework) {
|
|
152
|
+
lines.push(' note: an @pikku/* resolves to a workspace or link — this app is running framework code that may be modified');
|
|
153
|
+
}
|
|
154
|
+
field('runtime', `node ${env.node} ${env.platform} ${env.packageManager ?? ''}`.trim());
|
|
155
|
+
return lines.join('\n');
|
|
156
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** One installed `@pikku/*` package as it actually resolves on disk. */
|
|
2
|
+
export interface PikkuPackageVersion {
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
/**
|
|
6
|
+
* Resolved through a symlink — a yarn workspace or a `yarn link`ed checkout
|
|
7
|
+
* rather than a published tarball. The framework is read-only during a build
|
|
8
|
+
* run, so a linked package is code that may already have been modified, and a
|
|
9
|
+
* finding describing it is describing something other than a release.
|
|
10
|
+
*/
|
|
11
|
+
linked: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface ReportEnvironment {
|
|
14
|
+
packages: PikkuPackageVersion[];
|
|
15
|
+
/**
|
|
16
|
+
* The resolved `@pikku/*` versions are not all the same. Pinning the CLI does
|
|
17
|
+
* not pin its `@pikku/*` dependencies, so a mixed tree is a common cause of
|
|
18
|
+
* behaviour that looks like a framework bug.
|
|
19
|
+
*/
|
|
20
|
+
versionSkew: boolean;
|
|
21
|
+
/** Any package is `linked` — see {@link PikkuPackageVersion.linked}. */
|
|
22
|
+
linkedFramework: boolean;
|
|
23
|
+
node: string;
|
|
24
|
+
packageManager: string | null;
|
|
25
|
+
platform: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Walk up from `startDir` for the first `node_modules/@pikku` that holds
|
|
29
|
+
* packages. A monorepo hoists to the root, an app installs locally, and either
|
|
30
|
+
* way the nearest populated scope is the one that was loaded.
|
|
31
|
+
*
|
|
32
|
+
* Populated means holding something `readPikkuPackages` would read, so the
|
|
33
|
+
* hidden entries it skips cannot qualify a scope either: a stray `.DS_Store` in
|
|
34
|
+
* an empty nested scope would otherwise end the walk there and report a tree
|
|
35
|
+
* with no packages in it.
|
|
36
|
+
*/
|
|
37
|
+
export declare function findPikkuScope(startDir: string): Promise<string | null>;
|
|
38
|
+
/**
|
|
39
|
+
* Versions read off the installed tree rather than out of `package.json`. A
|
|
40
|
+
* range like `^0.12.35` says nothing about what ran, and the version that ran
|
|
41
|
+
* is the only one worth reporting.
|
|
42
|
+
*/
|
|
43
|
+
export declare function readPikkuPackages(scopeDir: string): Promise<PikkuPackageVersion[]>;
|
|
44
|
+
/**
|
|
45
|
+
* `packageManager` in the nearest manifest is authoritative when it is set;
|
|
46
|
+
* otherwise the lockfile is the only evidence of what installed the tree.
|
|
47
|
+
*/
|
|
48
|
+
export declare function detectPackageManager(startDir: string): Promise<string | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Everything about the run a finding needs and no agent should be asked for.
|
|
51
|
+
* All of it is a directory read — no network, no prompting.
|
|
52
|
+
*/
|
|
53
|
+
export declare function collectReportEnvironment(startDir?: string): Promise<ReportEnvironment>;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { readFile, lstat, readdir } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* Walk up from `startDir` for the first `node_modules/@pikku` that holds
|
|
6
|
+
* packages. A monorepo hoists to the root, an app installs locally, and either
|
|
7
|
+
* way the nearest populated scope is the one that was loaded.
|
|
8
|
+
*
|
|
9
|
+
* Populated means holding something `readPikkuPackages` would read, so the
|
|
10
|
+
* hidden entries it skips cannot qualify a scope either: a stray `.DS_Store` in
|
|
11
|
+
* an empty nested scope would otherwise end the walk there and report a tree
|
|
12
|
+
* with no packages in it.
|
|
13
|
+
*/
|
|
14
|
+
export async function findPikkuScope(startDir) {
|
|
15
|
+
let dir = startDir;
|
|
16
|
+
while (true) {
|
|
17
|
+
const candidate = join(dir, 'node_modules', '@pikku');
|
|
18
|
+
if (existsSync(candidate)) {
|
|
19
|
+
const entries = await readdir(candidate).catch(() => []);
|
|
20
|
+
if (entries.some((entry) => !entry.startsWith('.')))
|
|
21
|
+
return candidate;
|
|
22
|
+
}
|
|
23
|
+
const parent = dirname(dir);
|
|
24
|
+
if (parent === dir)
|
|
25
|
+
return null;
|
|
26
|
+
dir = parent;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Versions read off the installed tree rather than out of `package.json`. A
|
|
31
|
+
* range like `^0.12.35` says nothing about what ran, and the version that ran
|
|
32
|
+
* is the only one worth reporting.
|
|
33
|
+
*/
|
|
34
|
+
export async function readPikkuPackages(scopeDir) {
|
|
35
|
+
const entries = await readdir(scopeDir).catch(() => []);
|
|
36
|
+
const packages = [];
|
|
37
|
+
for (const entry of entries.sort()) {
|
|
38
|
+
if (entry.startsWith('.'))
|
|
39
|
+
continue;
|
|
40
|
+
const packageDir = join(scopeDir, entry);
|
|
41
|
+
const manifest = join(packageDir, 'package.json');
|
|
42
|
+
const raw = await readFile(manifest, 'utf8').catch(() => null);
|
|
43
|
+
if (!raw)
|
|
44
|
+
continue;
|
|
45
|
+
let version;
|
|
46
|
+
try {
|
|
47
|
+
version = JSON.parse(raw).version;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (typeof version !== 'string')
|
|
53
|
+
continue;
|
|
54
|
+
const stats = await lstat(packageDir).catch(() => null);
|
|
55
|
+
packages.push({
|
|
56
|
+
name: `@pikku/${entry}`,
|
|
57
|
+
version,
|
|
58
|
+
linked: stats?.isSymbolicLink() ?? false,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return packages;
|
|
62
|
+
}
|
|
63
|
+
const LOCKFILES = [
|
|
64
|
+
['yarn.lock', 'yarn'],
|
|
65
|
+
['pnpm-lock.yaml', 'pnpm'],
|
|
66
|
+
['bun.lockb', 'bun'],
|
|
67
|
+
['bun.lock', 'bun'],
|
|
68
|
+
['package-lock.json', 'npm'],
|
|
69
|
+
];
|
|
70
|
+
/**
|
|
71
|
+
* `packageManager` in the nearest manifest is authoritative when it is set;
|
|
72
|
+
* otherwise the lockfile is the only evidence of what installed the tree.
|
|
73
|
+
*/
|
|
74
|
+
export async function detectPackageManager(startDir) {
|
|
75
|
+
let dir = startDir;
|
|
76
|
+
while (true) {
|
|
77
|
+
const manifest = join(dir, 'package.json');
|
|
78
|
+
if (existsSync(manifest)) {
|
|
79
|
+
const raw = await readFile(manifest, 'utf8').catch(() => null);
|
|
80
|
+
if (raw) {
|
|
81
|
+
try {
|
|
82
|
+
const declared = JSON.parse(raw)
|
|
83
|
+
.packageManager;
|
|
84
|
+
if (typeof declared === 'string' && declared.length > 0) {
|
|
85
|
+
return declared;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// An unparseable manifest tells us nothing; keep walking up.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
for (const [lockfile, manager] of LOCKFILES) {
|
|
94
|
+
if (existsSync(join(dir, lockfile)))
|
|
95
|
+
return manager;
|
|
96
|
+
}
|
|
97
|
+
const parent = dirname(dir);
|
|
98
|
+
if (parent === dir)
|
|
99
|
+
return null;
|
|
100
|
+
dir = parent;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Everything about the run a finding needs and no agent should be asked for.
|
|
105
|
+
* All of it is a directory read — no network, no prompting.
|
|
106
|
+
*/
|
|
107
|
+
export async function collectReportEnvironment(startDir = process.cwd()) {
|
|
108
|
+
const scope = await findPikkuScope(startDir);
|
|
109
|
+
const packages = scope ? await readPikkuPackages(scope) : [];
|
|
110
|
+
const versions = new Set(packages.map((p) => p.version));
|
|
111
|
+
return {
|
|
112
|
+
packages,
|
|
113
|
+
versionSkew: versions.size > 1,
|
|
114
|
+
linkedFramework: packages.some((p) => p.linked),
|
|
115
|
+
node: process.version,
|
|
116
|
+
packageManager: await detectPackageManager(startDir),
|
|
117
|
+
platform: `${process.platform}-${process.arch}`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
export interface PikkuEnvironment {
|
|
12
12
|
apiUrl: string;
|
|
13
13
|
signInPath?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Where the session and its roles are read back, for a stage that reports
|
|
16
|
+
* them somewhere other than `get-session` under the sign-in path's own mount.
|
|
17
|
+
*/
|
|
18
|
+
sessionPath?: string;
|
|
14
19
|
rpcPath?: string;
|
|
15
20
|
appUrl?: string;
|
|
16
21
|
/**
|
|
@@ -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 `
|
|
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 `
|
|
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
|
-
|
|
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
|
|
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
|
|
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 {
|
|
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. `
|
|
85
|
-
* wires, and a hand-rolled `/sign-in/actor` route is the one a project
|
|
86
|
-
* not use better-auth ends up with. Both terminate at the same
|
|
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) &&
|
|
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 {
|
|
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
|
-
|
|
32
|
-
|
|
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
|
|
35
|
-
` import {
|
|
36
|
-
` betterAuth({ plugins: [
|
|
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 `
|
|
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 `
|
|
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 \`
|
|
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 \`
|
|
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,
|
package/dist/src/services.js
CHANGED
|
@@ -71,12 +71,21 @@ export const defaultCLIRenderer = pikkuCLIRender((_services, data) => {
|
|
|
71
71
|
* `skills install` writes agent skills into a repo that has no pikku.config.json
|
|
72
72
|
* yet — that is the whole point of it — so it cannot require one to start, and
|
|
73
73
|
* `doc` answers from the surface shipped inside the CLI rather than the project.
|
|
74
|
+
* `fabric report` files a finding about pikku itself: a scaffold that never
|
|
75
|
+
* produced a config, or a command run from the wrong directory, is exactly the
|
|
76
|
+
* kind of thing worth reporting, so demanding a config would refuse the finding
|
|
77
|
+
* at the moment it is most worth having.
|
|
74
78
|
*/
|
|
75
79
|
const CONFIG_FREE_COMMANDS = new Set([
|
|
76
80
|
'skills',
|
|
77
81
|
'skills.list',
|
|
78
82
|
'skills.install',
|
|
79
83
|
'doc',
|
|
84
|
+
'fabric.report',
|
|
85
|
+
'fabric.findings',
|
|
86
|
+
'fabric.findings.list',
|
|
87
|
+
'fabric.findings.flush',
|
|
88
|
+
'fabric.findings.clear',
|
|
80
89
|
]);
|
|
81
90
|
export const createConfig = async (_variablesService, data, commandPath = []) => {
|
|
82
91
|
// Determine log level based on CLI flags with precedence:
|