@pikku/cli 0.12.126 → 0.12.128
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 +157 -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 +31 -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 +124 -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 +140 -1
- 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 +120 -8
- 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 +6 -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 +23 -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/schemas/schemas/FabricSecretsDeleteInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricSecretsDeleteOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuDistInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuNewAddonInput.schema.json +1 -1
- 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/cli.wiring.js +16 -1
- package/dist/src/fabric/fabric-commands.d.ts +163 -0
- package/dist/src/fabric/fabric-commands.js +78 -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/functions/secrets-delete.function.d.ts +36 -0
- package/dist/src/fabric/functions/secrets-delete.function.js +51 -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/dev.js +2 -1
- package/dist/src/functions/commands/dist.d.ts +28 -0
- package/dist/src/functions/commands/dist.js +58 -0
- package/dist/src/functions/commands/environment.d.ts +5 -0
- package/dist/src/functions/commands/new-addon.d.ts +30 -0
- package/dist/src/functions/commands/new-addon.js +81 -3
- package/dist/src/functions/commands/persona-sync.d.ts +5 -4
- package/dist/src/functions/commands/persona-sync.js +6 -5
- package/dist/src/functions/commands/persona.js +7 -2
- 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 +9 -5
- package/dist/src/functions/validate/persona-checks.js +9 -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/src/utils/persona-credentials.d.ts +0 -2
- package/dist/src/utils/persona-credentials.js +1 -8
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/snippets.json +1 -1
- package/surface.json +1292 -4907
- 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,52 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { pikkuSessionlessFunc } from '../../../.pikku/function/index.js';
|
|
3
|
+
import { readSpool } from '../lib/finding-spool.js';
|
|
4
|
+
import { dim, table } from '../lib/output.js';
|
|
5
|
+
export const FabricFindingsListInput = z.object({});
|
|
6
|
+
export const FabricFindingsListOutput = z.object({
|
|
7
|
+
findings: z.array(z.object({
|
|
8
|
+
title: z.string(),
|
|
9
|
+
kind: z.string(),
|
|
10
|
+
reason: z.string(),
|
|
11
|
+
reportedAt: z.string(),
|
|
12
|
+
projectId: z.string().nullable(),
|
|
13
|
+
file: z.string(),
|
|
14
|
+
})),
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* What is waiting to be sent. Without this the spool is invisible, and an
|
|
18
|
+
* agent has no way to tell a finding that reached fabric from one still
|
|
19
|
+
* sitting on the machine.
|
|
20
|
+
*/
|
|
21
|
+
export const FabricFindingsList = pikkuSessionlessFunc({
|
|
22
|
+
description: 'List the findings queued locally, waiting to be sent.',
|
|
23
|
+
input: FabricFindingsListInput,
|
|
24
|
+
output: FabricFindingsListOutput,
|
|
25
|
+
func: async () => ({
|
|
26
|
+
findings: (await readSpool()).map((entry) => ({
|
|
27
|
+
title: entry.payload.title,
|
|
28
|
+
kind: entry.payload.kind,
|
|
29
|
+
reason: entry.reason,
|
|
30
|
+
reportedAt: entry.payload.reportedAt,
|
|
31
|
+
projectId: entry.projectId,
|
|
32
|
+
file: entry.file,
|
|
33
|
+
})),
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
export const renderFindingsList = (_s, { findings }) => {
|
|
37
|
+
console.log('');
|
|
38
|
+
if (findings.length === 0) {
|
|
39
|
+
console.log(dim(' Nothing queued — every finding you filed was sent.'));
|
|
40
|
+
console.log('');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
console.log(table(['REPORTED', 'KIND', 'HELD BECAUSE', 'TITLE'], findings.map((f) => [
|
|
44
|
+
f.reportedAt.slice(0, 16).replace('T', ' '),
|
|
45
|
+
f.kind,
|
|
46
|
+
f.reason,
|
|
47
|
+
f.title,
|
|
48
|
+
])));
|
|
49
|
+
console.log('');
|
|
50
|
+
console.log(dim(' `pikku fabric findings flush` sends them.'));
|
|
51
|
+
console.log('');
|
|
52
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Every field is optional here and the strictness lives in `FindingInput`,
|
|
4
|
+
* because `--stdin` supplies the whole finding at once and the flags then
|
|
5
|
+
* carry nothing. Whichever path was used, the same schema decides whether a
|
|
6
|
+
* finding is well-formed.
|
|
7
|
+
*/
|
|
8
|
+
export declare const FabricReportInput: z.ZodObject<{
|
|
9
|
+
title: z.ZodOptional<z.ZodString>;
|
|
10
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
11
|
+
product: "product";
|
|
12
|
+
harness: "harness";
|
|
13
|
+
}>>;
|
|
14
|
+
model: z.ZodOptional<z.ZodString>;
|
|
15
|
+
expected: z.ZodOptional<z.ZodString>;
|
|
16
|
+
actual: z.ZodOptional<z.ZodString>;
|
|
17
|
+
skill: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
18
|
+
passage: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
19
|
+
command: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
20
|
+
error: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
21
|
+
repro: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
22
|
+
workaround: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
23
|
+
proposal: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
24
|
+
tried: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
25
|
+
unresolved: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
|
|
26
|
+
area: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
27
|
+
surface: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
|
|
28
|
+
local: "local";
|
|
29
|
+
deployed: "deployed";
|
|
30
|
+
both: "both";
|
|
31
|
+
}>>>;
|
|
32
|
+
cost: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
33
|
+
run: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
34
|
+
deployTarget: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
35
|
+
stdin: z.ZodOptional<z.ZodBoolean>;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
export declare const FabricReportOutput: z.ZodObject<{
|
|
38
|
+
sent: z.ZodBoolean;
|
|
39
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
40
|
+
spooled: z.ZodBoolean;
|
|
41
|
+
queued: z.ZodNumber;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
export declare const FabricReport: import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<{
|
|
44
|
+
title?: string | undefined;
|
|
45
|
+
kind?: "product" | "harness" | undefined;
|
|
46
|
+
model?: string | undefined;
|
|
47
|
+
expected?: string | undefined;
|
|
48
|
+
actual?: string | undefined;
|
|
49
|
+
skill?: string | undefined;
|
|
50
|
+
passage?: string | undefined;
|
|
51
|
+
command?: string | undefined;
|
|
52
|
+
error?: string | undefined;
|
|
53
|
+
repro?: string | undefined;
|
|
54
|
+
workaround?: string | undefined;
|
|
55
|
+
proposal?: string | undefined;
|
|
56
|
+
tried?: string | undefined;
|
|
57
|
+
unresolved?: boolean | undefined;
|
|
58
|
+
area?: string | undefined;
|
|
59
|
+
surface?: "local" | "deployed" | "both" | undefined;
|
|
60
|
+
cost?: string | undefined;
|
|
61
|
+
run?: string | undefined;
|
|
62
|
+
deployTarget?: string | undefined;
|
|
63
|
+
stdin?: boolean | undefined;
|
|
64
|
+
}, {
|
|
65
|
+
sent: boolean;
|
|
66
|
+
spooled: boolean;
|
|
67
|
+
queued: number;
|
|
68
|
+
reason?: string | undefined;
|
|
69
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionSessionless<{
|
|
70
|
+
title?: string | undefined;
|
|
71
|
+
kind?: "product" | "harness" | undefined;
|
|
72
|
+
model?: string | undefined;
|
|
73
|
+
expected?: string | undefined;
|
|
74
|
+
actual?: string | undefined;
|
|
75
|
+
skill?: string | undefined;
|
|
76
|
+
passage?: string | undefined;
|
|
77
|
+
command?: string | undefined;
|
|
78
|
+
error?: string | undefined;
|
|
79
|
+
repro?: string | undefined;
|
|
80
|
+
workaround?: string | undefined;
|
|
81
|
+
proposal?: string | undefined;
|
|
82
|
+
tried?: string | undefined;
|
|
83
|
+
unresolved?: boolean | undefined;
|
|
84
|
+
area?: string | undefined;
|
|
85
|
+
surface?: "local" | "deployed" | "both" | undefined;
|
|
86
|
+
cost?: string | undefined;
|
|
87
|
+
run?: string | undefined;
|
|
88
|
+
deployTarget?: string | undefined;
|
|
89
|
+
stdin?: boolean | undefined;
|
|
90
|
+
}, {
|
|
91
|
+
sent: boolean;
|
|
92
|
+
spooled: boolean;
|
|
93
|
+
queued: number;
|
|
94
|
+
reason?: string | undefined;
|
|
95
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown> | import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunction<{
|
|
96
|
+
title?: string | undefined;
|
|
97
|
+
kind?: "product" | "harness" | undefined;
|
|
98
|
+
model?: string | undefined;
|
|
99
|
+
expected?: string | undefined;
|
|
100
|
+
actual?: string | undefined;
|
|
101
|
+
skill?: string | undefined;
|
|
102
|
+
passage?: string | undefined;
|
|
103
|
+
command?: string | undefined;
|
|
104
|
+
error?: string | undefined;
|
|
105
|
+
repro?: string | undefined;
|
|
106
|
+
workaround?: string | undefined;
|
|
107
|
+
proposal?: string | undefined;
|
|
108
|
+
tried?: string | undefined;
|
|
109
|
+
unresolved?: boolean | undefined;
|
|
110
|
+
area?: string | undefined;
|
|
111
|
+
surface?: "local" | "deployed" | "both" | undefined;
|
|
112
|
+
cost?: string | undefined;
|
|
113
|
+
run?: string | undefined;
|
|
114
|
+
deployTarget?: string | undefined;
|
|
115
|
+
stdin?: boolean | undefined;
|
|
116
|
+
}, {
|
|
117
|
+
sent: boolean;
|
|
118
|
+
spooled: boolean;
|
|
119
|
+
queued: number;
|
|
120
|
+
reason?: string | undefined;
|
|
121
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices>, undefined, undefined>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { pikkuSessionlessFunc } from '../../../.pikku/function/index.js';
|
|
3
|
+
import { resolveApiContext } from '../lib/config.js';
|
|
4
|
+
import { collectReportEnvironment } from '../lib/report-environment.js';
|
|
5
|
+
import { FindingInput, buildFindingPayload, parseFinding, parseFindingJson, postFinding, renderReceipt, validateFinding, } from '../lib/finding.js';
|
|
6
|
+
import { flushSpool, readSpool, spoolFinding } from '../lib/finding-spool.js';
|
|
7
|
+
/**
|
|
8
|
+
* Every field is optional here and the strictness lives in `FindingInput`,
|
|
9
|
+
* because `--stdin` supplies the whole finding at once and the flags then
|
|
10
|
+
* carry nothing. Whichever path was used, the same schema decides whether a
|
|
11
|
+
* finding is well-formed.
|
|
12
|
+
*/
|
|
13
|
+
export const FabricReportInput = FindingInput.partial().extend({
|
|
14
|
+
stdin: z.boolean().optional(),
|
|
15
|
+
});
|
|
16
|
+
export const FabricReportOutput = z.object({
|
|
17
|
+
sent: z.boolean(),
|
|
18
|
+
reason: z.string().optional(),
|
|
19
|
+
spooled: z.boolean(),
|
|
20
|
+
queued: z.number(),
|
|
21
|
+
});
|
|
22
|
+
const readStdin = async () => {
|
|
23
|
+
if (process.stdin.isTTY) {
|
|
24
|
+
throw new Error('--stdin expects the finding as JSON on standard input, and nothing was piped in.');
|
|
25
|
+
}
|
|
26
|
+
const chunks = [];
|
|
27
|
+
for await (const chunk of process.stdin)
|
|
28
|
+
chunks.push(Buffer.from(chunk));
|
|
29
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Every path that cannot send holds the finding instead. The states that stop
|
|
33
|
+
* a send — logged out, fabric unreachable — are the states a finding is most
|
|
34
|
+
* likely to be describing, so dropping it loses exactly the reports worth
|
|
35
|
+
* having.
|
|
36
|
+
*/
|
|
37
|
+
const hold = async (payload, reason, projectId, message) => {
|
|
38
|
+
await spoolFinding({ payload, reason, projectId });
|
|
39
|
+
const queued = (await readSpool()).length;
|
|
40
|
+
console.log(`[fabric] ${message} — finding queued (${queued} waiting, sent on your next report)`);
|
|
41
|
+
return { sent: false, reason, spooled: true, queued };
|
|
42
|
+
};
|
|
43
|
+
export const FabricReport = pikkuSessionlessFunc({
|
|
44
|
+
description: 'Report a finding — something about pikku that cost time — to fabric.',
|
|
45
|
+
input: FabricReportInput,
|
|
46
|
+
output: FabricReportOutput,
|
|
47
|
+
func: async (_services, { stdin, ...flags }) => {
|
|
48
|
+
const parsed = stdin
|
|
49
|
+
? parseFindingJson(await readStdin())
|
|
50
|
+
: parseFinding(flags);
|
|
51
|
+
if ('problems' in parsed) {
|
|
52
|
+
throw new Error(parsed.problems.join('\n'));
|
|
53
|
+
}
|
|
54
|
+
const problems = validateFinding(parsed.finding);
|
|
55
|
+
if (problems.length > 0) {
|
|
56
|
+
throw new Error(problems.join('\n'));
|
|
57
|
+
}
|
|
58
|
+
const payload = buildFindingPayload(parsed.finding, await collectReportEnvironment());
|
|
59
|
+
console.log(renderReceipt(payload));
|
|
60
|
+
const ctx = await resolveApiContext();
|
|
61
|
+
if (!ctx.token) {
|
|
62
|
+
return hold(payload, 'not-logged-in', ctx.projectId, 'not logged in');
|
|
63
|
+
}
|
|
64
|
+
const flushed = await flushSpool({
|
|
65
|
+
apiUrl: ctx.apiUrl,
|
|
66
|
+
token: ctx.token,
|
|
67
|
+
projectId: ctx.projectId,
|
|
68
|
+
});
|
|
69
|
+
if (flushed.sent > 0) {
|
|
70
|
+
console.log(`[fabric] sent ${flushed.sent} finding(s) held from earlier`);
|
|
71
|
+
}
|
|
72
|
+
const result = await postFinding({
|
|
73
|
+
apiUrl: ctx.apiUrl,
|
|
74
|
+
token: ctx.token,
|
|
75
|
+
projectId: ctx.projectId,
|
|
76
|
+
payload,
|
|
77
|
+
});
|
|
78
|
+
if (!result.sent) {
|
|
79
|
+
return hold(payload, result.reason ?? 'send-failed', ctx.projectId, `fabric did not accept it (${result.reason})`);
|
|
80
|
+
}
|
|
81
|
+
console.log('[fabric] finding sent');
|
|
82
|
+
return { sent: true, spooled: false, queued: flushed.remaining };
|
|
83
|
+
},
|
|
84
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const FabricSecretsDeleteInput: z.ZodObject<{
|
|
3
|
+
name: z.ZodString;
|
|
4
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
5
|
+
force: z.ZodOptional<z.ZodBoolean>;
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
export declare const FabricSecretsDeleteOutput: z.ZodObject<{
|
|
8
|
+
name: z.ZodString;
|
|
9
|
+
runId: z.ZodNullable<z.ZodString>;
|
|
10
|
+
deploymentId: z.ZodNullable<z.ZodString>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export declare const FabricSecretsDelete: import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<{
|
|
13
|
+
name: string;
|
|
14
|
+
branch?: string | undefined;
|
|
15
|
+
force?: boolean | undefined;
|
|
16
|
+
}, {
|
|
17
|
+
name: string;
|
|
18
|
+
runId: string | null;
|
|
19
|
+
deploymentId: string | null;
|
|
20
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionSessionless<{
|
|
21
|
+
name: string;
|
|
22
|
+
branch?: string | undefined;
|
|
23
|
+
force?: boolean | undefined;
|
|
24
|
+
}, {
|
|
25
|
+
name: string;
|
|
26
|
+
runId: string | null;
|
|
27
|
+
deploymentId: string | null;
|
|
28
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown> | import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunction<{
|
|
29
|
+
name: string;
|
|
30
|
+
branch?: string | undefined;
|
|
31
|
+
force?: boolean | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
name: string;
|
|
34
|
+
runId: string | null;
|
|
35
|
+
deploymentId: string | null;
|
|
36
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices>, undefined, undefined>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { pikkuSessionlessFunc } from '../../../.pikku/function/index.js';
|
|
3
|
+
import { resolveApiContext } from '../lib/config.js';
|
|
4
|
+
import { getFabricRPC } from '../lib/http.js';
|
|
5
|
+
import { promptConfirm } from '../lib/prompt.js';
|
|
6
|
+
import { resolveStage } from '../lib/stage.js';
|
|
7
|
+
export const FabricSecretsDeleteInput = z.object({
|
|
8
|
+
name: z.string(),
|
|
9
|
+
branch: z.string().optional(),
|
|
10
|
+
force: z.boolean().optional(),
|
|
11
|
+
});
|
|
12
|
+
export const FabricSecretsDeleteOutput = z.object({
|
|
13
|
+
name: z.string(),
|
|
14
|
+
runId: z.string().nullable(),
|
|
15
|
+
deploymentId: z.string().nullable(),
|
|
16
|
+
});
|
|
17
|
+
export const FabricSecretsDelete = pikkuSessionlessFunc({
|
|
18
|
+
description: 'Remove a single stage-scoped secret. Unlike `secrets rotate`, the rest of the stage keeps its sealing key and its other secrets.',
|
|
19
|
+
input: FabricSecretsDeleteInput,
|
|
20
|
+
output: FabricSecretsDeleteOutput,
|
|
21
|
+
func: async (_services, { name, branch: requested, force }) => {
|
|
22
|
+
const ctx = await resolveApiContext();
|
|
23
|
+
if (!ctx.token)
|
|
24
|
+
throw new Error('Not logged in. Run `pikku fabric login` first.');
|
|
25
|
+
if (!ctx.projectId)
|
|
26
|
+
throw new Error('No fabric project linked. Run `pikku fabric link` first.');
|
|
27
|
+
// Resolved before the prompt so the confirmation names the stage that
|
|
28
|
+
// would actually lose the secret, not an argument that may be absent.
|
|
29
|
+
const rpc = getFabricRPC({ apiUrl: ctx.apiUrl, token: ctx.token });
|
|
30
|
+
const { stageId, branch } = await resolveStage(rpc, ctx.projectId, requested);
|
|
31
|
+
if (!force) {
|
|
32
|
+
if (!process.stdin.isTTY) {
|
|
33
|
+
throw new Error(`Refusing to delete ${name} from ${branch} without confirmation — re-run with --force to delete non-interactively.`);
|
|
34
|
+
}
|
|
35
|
+
// Fabric cannot read the sealed value back, so this is not recoverable
|
|
36
|
+
// by re-reading it — the plaintext has to be supplied again.
|
|
37
|
+
if (!(await promptConfirm(`Delete ${name} from ${branch}? It cannot be recovered — the value must be set again.`))) {
|
|
38
|
+
throw new Error('Delete aborted.');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const result = await rpc.invoke('deleteStageSecret', { stageId, name });
|
|
42
|
+
console.log(`[fabric] deleted ${result.name} from ${branch}`);
|
|
43
|
+
if (result.runId) {
|
|
44
|
+
console.log(`[fabric] republishing the stage as run ${result.runId} — units serve the old value until it lands`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log('[fabric] deploy the stage to stop its units serving the old value');
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
},
|
|
51
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type FindingPayload } from './finding.js';
|
|
2
|
+
/**
|
|
3
|
+
* A finding that could not be sent when it was filed, held until it can be.
|
|
4
|
+
*
|
|
5
|
+
* The cases that keep a finding from leaving — no token, no linked project, a
|
|
6
|
+
* fabric that is down — are the same cases the finding is most likely to be
|
|
7
|
+
* about: a scaffold that never got far enough to log in is exactly the thing
|
|
8
|
+
* worth hearing about, and printing it and dropping it loses it. The spool
|
|
9
|
+
* lives in `~/.fabric`, not the repo, so nothing goes stale on an abandoned
|
|
10
|
+
* branch and git never sees it.
|
|
11
|
+
*/
|
|
12
|
+
export interface SpooledFinding {
|
|
13
|
+
file: string;
|
|
14
|
+
spooledAt: string;
|
|
15
|
+
reason: string;
|
|
16
|
+
projectId: string | null;
|
|
17
|
+
payload: FindingPayload;
|
|
18
|
+
}
|
|
19
|
+
/** Oldest entries past this are dropped, so a logged-out machine stays bounded. */
|
|
20
|
+
export declare const SPOOL_LIMIT = 100;
|
|
21
|
+
export declare function spoolDir(): string;
|
|
22
|
+
export declare function spoolFinding(entry: {
|
|
23
|
+
payload: FindingPayload;
|
|
24
|
+
reason: string;
|
|
25
|
+
projectId: string | null;
|
|
26
|
+
}): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Chronological, by the timestamp inside each finding rather than the one its
|
|
29
|
+
* name carries — the name is for a human reading the directory, and ordering
|
|
30
|
+
* the queue by it would make the send order a property of how a filename
|
|
31
|
+
* happens to sort. A file that no longer parses is skipped rather than thrown
|
|
32
|
+
* for: one corrupt entry is not a reason to lose the rest, or to fail the
|
|
33
|
+
* command that happened to notice.
|
|
34
|
+
*/
|
|
35
|
+
export declare function readSpool(): Promise<SpooledFinding[]>;
|
|
36
|
+
export declare function clearSpool(): Promise<number>;
|
|
37
|
+
export interface FlushResult {
|
|
38
|
+
sent: number;
|
|
39
|
+
remaining: number;
|
|
40
|
+
reason?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Drain the spool oldest-first, stopping at the first entry fabric does not
|
|
44
|
+
* accept — a refusal usually means the next one will be refused too, and
|
|
45
|
+
* hammering an endpoint that just said no is the wrong thing for a command
|
|
46
|
+
* whose real job is something else.
|
|
47
|
+
*
|
|
48
|
+
* An entry keeps the project it was filed against; one spooled before the repo
|
|
49
|
+
* was linked adopts the project linked now, and sends without one if there is
|
|
50
|
+
* still none.
|
|
51
|
+
*/
|
|
52
|
+
export declare function flushSpool(ctx: {
|
|
53
|
+
apiUrl: string;
|
|
54
|
+
token: string;
|
|
55
|
+
projectId: string | null;
|
|
56
|
+
}): Promise<FlushResult>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { randomBytes } from 'node:crypto';
|
|
6
|
+
import { postFinding } from './finding.js';
|
|
7
|
+
/** Oldest entries past this are dropped, so a logged-out machine stays bounded. */
|
|
8
|
+
export const SPOOL_LIMIT = 100;
|
|
9
|
+
export function spoolDir() {
|
|
10
|
+
return (process.env.FABRIC_FINDINGS_DIR ?? join(homedir(), '.fabric', 'findings'));
|
|
11
|
+
}
|
|
12
|
+
export async function spoolFinding(entry) {
|
|
13
|
+
const dir = spoolDir();
|
|
14
|
+
await mkdir(dir, { recursive: true });
|
|
15
|
+
const stamp = entry.payload.reportedAt.replace(/[:.]/g, '-');
|
|
16
|
+
const file = join(dir, `${stamp}-${randomBytes(3).toString('hex')}.json`);
|
|
17
|
+
await writeFile(file, JSON.stringify({
|
|
18
|
+
spooledAt: new Date().toISOString(),
|
|
19
|
+
reason: entry.reason,
|
|
20
|
+
projectId: entry.projectId,
|
|
21
|
+
payload: entry.payload,
|
|
22
|
+
}, null, 2) + '\n', { encoding: 'utf8', mode: 0o600 });
|
|
23
|
+
await pruneSpool();
|
|
24
|
+
return file;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Chronological, by the timestamp inside each finding rather than the one its
|
|
28
|
+
* name carries — the name is for a human reading the directory, and ordering
|
|
29
|
+
* the queue by it would make the send order a property of how a filename
|
|
30
|
+
* happens to sort. A file that no longer parses is skipped rather than thrown
|
|
31
|
+
* for: one corrupt entry is not a reason to lose the rest, or to fail the
|
|
32
|
+
* command that happened to notice.
|
|
33
|
+
*/
|
|
34
|
+
export async function readSpool() {
|
|
35
|
+
const dir = spoolDir();
|
|
36
|
+
if (!existsSync(dir))
|
|
37
|
+
return [];
|
|
38
|
+
const names = (await readdir(dir)).filter((n) => n.endsWith('.json'));
|
|
39
|
+
const entries = [];
|
|
40
|
+
for (const name of names) {
|
|
41
|
+
const file = join(dir, name);
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(await readFile(file, 'utf8'));
|
|
44
|
+
if (!parsed?.payload)
|
|
45
|
+
continue;
|
|
46
|
+
entries.push({
|
|
47
|
+
file,
|
|
48
|
+
spooledAt: parsed.spooledAt ?? '',
|
|
49
|
+
reason: parsed.reason ?? 'unknown',
|
|
50
|
+
projectId: parsed.projectId ?? null,
|
|
51
|
+
payload: parsed.payload,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return entries.sort((a, b) => a.payload.reportedAt.localeCompare(b.payload.reportedAt) ||
|
|
59
|
+
a.file.localeCompare(b.file));
|
|
60
|
+
}
|
|
61
|
+
export async function clearSpool() {
|
|
62
|
+
const entries = await readSpool();
|
|
63
|
+
for (const entry of entries)
|
|
64
|
+
await rm(entry.file, { force: true });
|
|
65
|
+
return entries.length;
|
|
66
|
+
}
|
|
67
|
+
async function pruneSpool() {
|
|
68
|
+
const entries = await readSpool();
|
|
69
|
+
const excess = Math.max(0, entries.length - SPOOL_LIMIT);
|
|
70
|
+
for (const entry of entries.slice(0, excess)) {
|
|
71
|
+
await rm(entry.file, { force: true });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Drain the spool oldest-first, stopping at the first entry fabric does not
|
|
76
|
+
* accept — a refusal usually means the next one will be refused too, and
|
|
77
|
+
* hammering an endpoint that just said no is the wrong thing for a command
|
|
78
|
+
* whose real job is something else.
|
|
79
|
+
*
|
|
80
|
+
* An entry keeps the project it was filed against; one spooled before the repo
|
|
81
|
+
* was linked adopts the project linked now, and sends without one if there is
|
|
82
|
+
* still none.
|
|
83
|
+
*/
|
|
84
|
+
export async function flushSpool(ctx) {
|
|
85
|
+
const entries = await readSpool();
|
|
86
|
+
let sent = 0;
|
|
87
|
+
for (const [index, entry] of entries.entries()) {
|
|
88
|
+
const result = await postFinding({
|
|
89
|
+
apiUrl: ctx.apiUrl,
|
|
90
|
+
token: ctx.token,
|
|
91
|
+
projectId: entry.projectId ?? ctx.projectId,
|
|
92
|
+
payload: entry.payload,
|
|
93
|
+
});
|
|
94
|
+
if (!result.sent) {
|
|
95
|
+
return {
|
|
96
|
+
sent,
|
|
97
|
+
remaining: entries.length - index,
|
|
98
|
+
reason: result.reason,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
await rm(entry.file, { force: true });
|
|
102
|
+
sent++;
|
|
103
|
+
}
|
|
104
|
+
return { sent, remaining: 0 };
|
|
105
|
+
}
|
|
@@ -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;
|