onbuzz 4.6.4 → 4.7.0
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/bin/cli.js +8 -0
- package/package.json +1 -1
- package/src/__tests__/autoUpdateConfig.test.js +44 -0
- package/src/__tests__/releaseWorkflow.test.js +72 -0
- package/src/interfaces/__tests__/accountRoutes.test.js +429 -0
- package/src/interfaces/__tests__/apiKeyManagerContract.test.js +39 -0
- package/src/interfaces/__tests__/authRoutes.test.js +8 -8
- package/src/interfaces/accountRoutes.js +250 -0
- package/src/interfaces/webServer.js +63 -10
- package/src/services/__tests__/apiKeyManager.test.js +4 -6
- package/src/services/__tests__/authCacheStore.test.js +118 -0
- package/src/services/apiKeyManager.js +12 -99
- package/src/services/authCacheStore.js +140 -0
- package/src/tools/__tests__/webTool.e2e.test.js +9 -1
- package/src/tools/webTool.js +20 -4
- package/src/utilities/__tests__/secretsCipher.test.js +97 -0
- package/src/utilities/__tests__/updateNotifier.test.js +139 -0
- package/src/utilities/secretsCipher.js +116 -0
- package/src/utilities/updateNotifier.js +140 -0
- package/web-ui/build/index.html +2 -2
- package/web-ui/build/static/1c-D_MLuenD.js +1 -0
- package/web-ui/build/static/abap-BNvFMksw.js +1 -0
- package/web-ui/build/static/abnf-WlnRJIp2.js +1 -0
- package/web-ui/build/static/abnf-mx1Wbtnp.js +1 -0
- package/web-ui/build/static/accesslog-CJumJuuV.js +1 -0
- package/web-ui/build/static/actionscript-B6CbK7n7.js +1 -0
- package/web-ui/build/static/actionscript-DZ5xfmPr.js +1 -0
- package/web-ui/build/static/ada-CCVAXM0c.js +1 -0
- package/web-ui/build/static/ada-DtGkgqC4.js +1 -0
- package/web-ui/build/static/agda-gMFRTChb.js +1 -0
- package/web-ui/build/static/al-88fYQh4r.js +1 -0
- package/web-ui/build/static/angelscript-Bibc8YWJ.js +1 -0
- package/web-ui/build/static/antlr4-DgibPJaJ.js +1 -0
- package/web-ui/build/static/apache-_pZ-s8l6.js +1 -0
- package/web-ui/build/static/apacheconf-YDldOH3Q.js +1 -0
- package/web-ui/build/static/apex-CIj23tyF.js +1 -0
- package/web-ui/build/static/apl-DtRSC0Xv.js +1 -0
- package/web-ui/build/static/applescript-CKhcPsla.js +1 -0
- package/web-ui/build/static/applescript-DuJeHJ1r.js +1 -0
- package/web-ui/build/static/aql-BgmI8Ors.js +1 -0
- package/web-ui/build/static/arcade-BX83978b.js +1 -0
- package/web-ui/build/static/arduino-BVdatcJb.js +1 -0
- package/web-ui/build/static/arduino-h6ifuWka.js +1 -0
- package/web-ui/build/static/arff-DHmbMeIA.js +1 -0
- package/web-ui/build/static/armasm-DiDgI5h5.js +1 -0
- package/web-ui/build/static/asciidoc-CBro7xXU.js +1 -0
- package/web-ui/build/static/asciidoc-DRC2X4bq.js +1 -0
- package/web-ui/build/static/asm6502-53VLu0lq.js +1 -0
- package/web-ui/build/static/asmatmel-DlRHdXes.js +1 -0
- package/web-ui/build/static/aspectj-DTSWMNl9.js +1 -0
- package/web-ui/build/static/aspnet-DEUO05ai.js +1 -0
- package/web-ui/build/static/autohotkey-3gt8xVo-.js +1 -0
- package/web-ui/build/static/autohotkey-BWcbMbe_.js +1 -0
- package/web-ui/build/static/autoit-CackGf4X.js +1 -0
- package/web-ui/build/static/autoit-Dyf0FSt2.js +1 -0
- package/web-ui/build/static/avisynth-DfCuxmn5.js +1 -0
- package/web-ui/build/static/avrasm-DdDiRWhx.js +1 -0
- package/web-ui/build/static/avro-idl-DppsvvwR.js +1 -0
- package/web-ui/build/static/awk-Cjk3U-Y4.js +1 -0
- package/web-ui/build/static/axapta-WwnY3TVf.js +1 -0
- package/web-ui/build/static/bash-C5Xkqken.js +1 -0
- package/web-ui/build/static/bash-ckPXa-RG.js +1 -0
- package/web-ui/build/static/basic-BCVHqHd2.js +1 -0
- package/web-ui/build/static/basic-D0dZbGrs.js +1 -0
- package/web-ui/build/static/batch-DUo60tbI.js +1 -0
- package/web-ui/build/static/bbcode-BVzBKrPV.js +1 -0
- package/web-ui/build/static/bicep-DkTjKL2N.js +1 -0
- package/web-ui/build/static/birb-C0rKI0h6.js +1 -0
- package/web-ui/build/static/bison-ChzwcDVc.js +1 -0
- package/web-ui/build/static/bnf-COhTgjpr.js +1 -0
- package/web-ui/build/static/bnf-DUYKVI2p.js +1 -0
- package/web-ui/build/static/brainfuck-BBJLbMxW.js +1 -0
- package/web-ui/build/static/brainfuck-DufOqE73.js +1 -0
- package/web-ui/build/static/brightscript-DXhkwfCc.js +1 -0
- package/web-ui/build/static/bro-BOFEsT-K.js +1 -0
- package/web-ui/build/static/bsl-ClV9GpNm.js +1 -0
- package/web-ui/build/static/c-Cl_3N1WB.js +1 -0
- package/web-ui/build/static/c-D0hFoAJ3.js +1 -0
- package/web-ui/build/static/c-like-D4BQ8VhL.js +1 -0
- package/web-ui/build/static/cal-CVIQ5DKG.js +1 -0
- package/web-ui/build/static/capnproto-l7oAqnCr.js +1 -0
- package/web-ui/build/static/ceylon-BEhCsFMw.js +1 -0
- package/web-ui/build/static/cfscript-DMh-xvVk.js +1 -0
- package/web-ui/build/static/chaiscript-DCvDoIGS.js +1 -0
- package/web-ui/build/static/cil-Ccn-j3TB.js +1 -0
- package/web-ui/build/static/clean-CjrEwcC-.js +1 -0
- package/web-ui/build/static/clojure-Dgo-8qFd.js +1 -0
- package/web-ui/build/static/clojure-M1AknfQi.js +1 -0
- package/web-ui/build/static/clojure-repl-BY1VLOSH.js +1 -0
- package/web-ui/build/static/cmake-CdHJ7Mp0.js +1 -0
- package/web-ui/build/static/cmake-DDGvi7kU.js +1 -0
- package/web-ui/build/static/cobol-BdrXYRxi.js +1 -0
- package/web-ui/build/static/coffeescript-BMDvMAy2.js +1 -0
- package/web-ui/build/static/coffeescript-CAYcMTRg.js +1 -0
- package/web-ui/build/static/concurnas-B8vcX0ec.js +1 -0
- package/web-ui/build/static/coq-CqvluN1S.js +1 -0
- package/web-ui/build/static/coq-vhnnRdWb.js +1 -0
- package/web-ui/build/static/cos-DY4p0y_u.js +1 -0
- package/web-ui/build/static/cpp-C3m_aEUX.js +1 -0
- package/web-ui/build/static/cpp-DRs9bbEm.js +1 -0
- package/web-ui/build/static/crmsh-CY6InunC.js +1 -0
- package/web-ui/build/static/crystal-Cwk1figA.js +1 -0
- package/web-ui/build/static/crystal-DeCJ5Pz7.js +1 -0
- package/web-ui/build/static/csharp-WmvubeKF.js +1 -0
- package/web-ui/build/static/csharp-zL1j7hXr.js +1 -0
- package/web-ui/build/static/cshtml-CbvGCaf_.js +1 -0
- package/web-ui/build/static/csp-BH2nxxKs.js +1 -0
- package/web-ui/build/static/csp-CHlC7KoB.js +1 -0
- package/web-ui/build/static/css-_X0ZO87y.js +1 -0
- package/web-ui/build/static/css-extras-wgFh56PY.js +1 -0
- package/web-ui/build/static/csv-momqe7r6.js +1 -0
- package/web-ui/build/static/cypher-hOeHFCfk.js +1 -0
- package/web-ui/build/static/d-B3d-tfyQ.js +1 -0
- package/web-ui/build/static/d-C6iyl9wX.js +1 -0
- package/web-ui/build/static/dart-BDKSE6LE.js +1 -0
- package/web-ui/build/static/dart-Bjchg8qI.js +1 -0
- package/web-ui/build/static/dataweave-ZgvdD-pH.js +1 -0
- package/web-ui/build/static/dax-yfGYNpUh.js +1 -0
- package/web-ui/build/static/delphi-CRLCdiTE.js +1 -0
- package/web-ui/build/static/dhall-yl1p1XUr.js +1 -0
- package/web-ui/build/static/diff-5SMtcFK7.js +1 -0
- package/web-ui/build/static/diff-y2RTBWsQ.js +1 -0
- package/web-ui/build/static/django-CtjG6w9L.js +1 -0
- package/web-ui/build/static/django-DNXOxI3v.js +1 -0
- package/web-ui/build/static/dns-D7Czwn_S.js +1 -0
- package/web-ui/build/static/dns-zone-file-D3yPxpjz.js +1 -0
- package/web-ui/build/static/docker-CWC5NqQQ.js +1 -0
- package/web-ui/build/static/dockerfile-CKFBVY9d.js +1 -0
- package/web-ui/build/static/dos-B7gYphQ-.js +1 -0
- package/web-ui/build/static/dot-BsisNMX4.js +1 -0
- package/web-ui/build/static/dsconfig-CEWwz7T6.js +1 -0
- package/web-ui/build/static/dts-UM5u5dMt.js +1 -0
- package/web-ui/build/static/dust-DlPmuh4d.js +1 -0
- package/web-ui/build/static/ebnf-BE6vq-fo.js +1 -0
- package/web-ui/build/static/ebnf-Czd8moGp.js +1 -0
- package/web-ui/build/static/editorconfig-Ctn83uRn.js +1 -0
- package/web-ui/build/static/eiffel-CZP01HVF.js +1 -0
- package/web-ui/build/static/ejs-BAXhrtLI.js +1 -0
- package/web-ui/build/static/elixir-C9PFjTwP.js +1 -0
- package/web-ui/build/static/elixir-DMjZPYCh.js +1 -0
- package/web-ui/build/static/elm-BH_KfOxJ.js +1 -0
- package/web-ui/build/static/elm-DRnNerE2.js +1 -0
- package/web-ui/build/static/erb-BhzUuTTy.js +1 -0
- package/web-ui/build/static/erb-DNbmX3N2.js +1 -0
- package/web-ui/build/static/erlang-BBPIw_V_.js +1 -0
- package/web-ui/build/static/erlang-BWdcSiKs.js +1 -0
- package/web-ui/build/static/erlang-repl-DQ9I6Dh_.js +1 -0
- package/web-ui/build/static/etlua-BeVNUecy.js +1 -0
- package/web-ui/build/static/excel-DYFvX5ms.js +1 -0
- package/web-ui/build/static/excel-formula-BtiqixBz.js +1 -0
- package/web-ui/build/static/factor-BCHyN6XZ.js +1 -0
- package/web-ui/build/static/false-UDWS0Dzk.js +1 -0
- package/web-ui/build/static/firestore-security-rules-B1-wJ42j.js +1 -0
- package/web-ui/build/static/fix-DrXU-V21.js +1 -0
- package/web-ui/build/static/flix-BjF0RPW9.js +1 -0
- package/web-ui/build/static/flow-DovuDACs.js +1 -0
- package/web-ui/build/static/fortran-DOqQP_9c.js +1 -0
- package/web-ui/build/static/fortran-DPASe5gH.js +1 -0
- package/web-ui/build/static/fsharp-Ckup0uPw.js +1 -0
- package/web-ui/build/static/fsharp-DyfRmGjn.js +1 -0
- package/web-ui/build/static/ftl-Coj24bDj.js +1 -0
- package/web-ui/build/static/gams-GwREZQh1.js +1 -0
- package/web-ui/build/static/gap-B7d6Bkmk.js +1 -0
- package/web-ui/build/static/gauss-DrLvPj5Z.js +1 -0
- package/web-ui/build/static/gcode-40iTJ2U1.js +1 -0
- package/web-ui/build/static/gcode-CISHXDj4.js +1 -0
- package/web-ui/build/static/gdscript-DmopCB0R.js +1 -0
- package/web-ui/build/static/gedcom-LiECv7gg.js +1 -0
- package/web-ui/build/static/gherkin-CYp_kcve.js +1 -0
- package/web-ui/build/static/gherkin-C_QgMjxf.js +1 -0
- package/web-ui/build/static/git-CfTT-600.js +1 -0
- package/web-ui/build/static/glsl-DRFMhvlG.js +1 -0
- package/web-ui/build/static/glsl-PNmpuSn0.js +1 -0
- package/web-ui/build/static/gml-3qmqfrt3.js +1 -0
- package/web-ui/build/static/gml-BTCmr4y5.js +1 -0
- package/web-ui/build/static/gn-BX0L2dQ-.js +1 -0
- package/web-ui/build/static/go-BXYOf5mS.js +1 -0
- package/web-ui/build/static/go-BnvPVHID.js +1 -0
- package/web-ui/build/static/go-module-BsPBvEmG.js +1 -0
- package/web-ui/build/static/golo-B6l7i4bX.js +1 -0
- package/web-ui/build/static/gradle-9DvvuDBJ.js +1 -0
- package/web-ui/build/static/graphql-OcCfd-Bc.js +1 -0
- package/web-ui/build/static/groovy-B33LZAt0.js +1 -0
- package/web-ui/build/static/groovy-Uyg0ruyE.js +1 -0
- package/web-ui/build/static/haml-D_FDAM6q.js +1 -0
- package/web-ui/build/static/haml-DjG31i1A.js +1 -0
- package/web-ui/build/static/handlebars-BKPDMksf.js +1 -0
- package/web-ui/build/static/handlebars-PP4M-qJ8.js +1 -0
- package/web-ui/build/static/haskell-HD9Gv3Wo.js +1 -0
- package/web-ui/build/static/haskell-nUf9ckz5.js +1 -0
- package/web-ui/build/static/haxe-BSsJNrQU.js +1 -0
- package/web-ui/build/static/haxe-D7yTwhdv.js +1 -0
- package/web-ui/build/static/hcl-_dqjptFs.js +1 -0
- package/web-ui/build/static/hlsl-DKixrsyy.js +1 -0
- package/web-ui/build/static/hoon-Di28eQfV.js +1 -0
- package/web-ui/build/static/hpkp-CXYG9zoQ.js +1 -0
- package/web-ui/build/static/hsp-lYl9KN6o.js +1 -0
- package/web-ui/build/static/hsts-CaYq9R8-.js +1 -0
- package/web-ui/build/static/htmlbars-eoY2PWS6.js +1 -0
- package/web-ui/build/static/http-2DXUmN2h.js +1 -0
- package/web-ui/build/static/http-Yjic3oWm.js +1 -0
- package/web-ui/build/static/hy-DVImg5uG.js +1 -0
- package/web-ui/build/static/ichigojam-Bdk-szlv.js +1 -0
- package/web-ui/build/static/icon-BEs9UbI_.js +1 -0
- package/web-ui/build/static/icu-message-format-DMfiLVs5.js +1 -0
- package/web-ui/build/static/idris-meksg0Ce.js +1 -0
- package/web-ui/build/static/iecst-DMPBiTmw.js +1 -0
- package/web-ui/build/static/ignore-BOQ9ZPvw.js +1 -0
- package/web-ui/build/static/index-BSEOP86D.js +1 -0
- package/web-ui/build/static/index-Be9WvMkI.js +1162 -0
- package/web-ui/build/static/index-Cr9q1fNq.css +1 -0
- package/web-ui/build/static/index-CuZ_erP9.js +13 -0
- package/web-ui/build/static/inform7-CNqu8FhU.js +1 -0
- package/web-ui/build/static/inform7-Cvfrdb0X.js +1 -0
- package/web-ui/build/static/ini-4DHUSW37.js +1 -0
- package/web-ui/build/static/ini-BgZ18Nk6.js +1 -0
- package/web-ui/build/static/io-c519ulw2.js +1 -0
- package/web-ui/build/static/irpf90-Kzq81vn5.js +1 -0
- package/web-ui/build/static/isbl-CeBN_o-W.js +1 -0
- package/web-ui/build/static/j-BmSuFx5E.js +1 -0
- package/web-ui/build/static/java-BezG0JQd.js +1 -0
- package/web-ui/build/static/java-BxBhTA1D.js +1 -0
- package/web-ui/build/static/javadoc-b96LRy9-.js +1 -0
- package/web-ui/build/static/javadoclike-BTNVp6pR.js +1 -0
- package/web-ui/build/static/javascript-B75gzQUI.js +1 -0
- package/web-ui/build/static/javastacktrace-D4xVOdoe.js +1 -0
- package/web-ui/build/static/jboss-cli-DH30pghK.js +1 -0
- package/web-ui/build/static/jexl-DF2RGmtX.js +1 -0
- package/web-ui/build/static/jolie-BlwO_Eyn.js +1 -0
- package/web-ui/build/static/jq-C7YhIw1G.js +1 -0
- package/web-ui/build/static/js-extras-JVZxoi4Q.js +1 -0
- package/web-ui/build/static/js-templates-D1CnsXgJ.js +1 -0
- package/web-ui/build/static/jsdoc-vf63NOxo.js +1 -0
- package/web-ui/build/static/json-CiKwLA5O.js +1 -0
- package/web-ui/build/static/json-pgLQeaes.js +1 -0
- package/web-ui/build/static/json5-_HMAYh1c.js +1 -0
- package/web-ui/build/static/jsonp-BeHQpb2r.js +1 -0
- package/web-ui/build/static/jsstacktrace-nw21JEtY.js +1 -0
- package/web-ui/build/static/jsx-Nxt_XhcW.js +1 -0
- package/web-ui/build/static/julia-BFczE4HB.js +1 -0
- package/web-ui/build/static/julia-DeDNID0K.js +1 -0
- package/web-ui/build/static/julia-repl-CoPTZMue.js +1 -0
- package/web-ui/build/static/keepalived-DP1sFl1b.js +1 -0
- package/web-ui/build/static/keyman-CCQVTHgo.js +1 -0
- package/web-ui/build/static/kotlin-CdZP58gi.js +1 -0
- package/web-ui/build/static/kotlin-CzNKVbXq.js +1 -0
- package/web-ui/build/static/kumir-lPok55sq.js +1 -0
- package/web-ui/build/static/kusto-oLek_zqj.js +1 -0
- package/web-ui/build/static/lasso-BFOYENIx.js +1 -0
- package/web-ui/build/static/latex-BH6YJXW6.js +1 -0
- package/web-ui/build/static/latex-IweVcDOS.js +1 -0
- package/web-ui/build/static/latte-Cmzytj93.js +1 -0
- package/web-ui/build/static/ldif-Bp4o5m10.js +1 -0
- package/web-ui/build/static/leaf-BFbMre84.js +1 -0
- package/web-ui/build/static/less-BVpV_iBx.js +1 -0
- package/web-ui/build/static/less-vdx-pGtM.js +1 -0
- package/web-ui/build/static/lilypond-Da6mCtwg.js +1 -0
- package/web-ui/build/static/liquid-RVC3EWUf.js +1 -0
- package/web-ui/build/static/lisp-Bgt-EmTk.js +1 -0
- package/web-ui/build/static/lisp-E8gUigGo.js +1 -0
- package/web-ui/build/static/livecodeserver-DDFQieJg.js +1 -0
- package/web-ui/build/static/livescript-C7FEDmfm.js +1 -0
- package/web-ui/build/static/livescript-Cc5SDmvx.js +1 -0
- package/web-ui/build/static/llvm-C22gmUEJ.js +1 -0
- package/web-ui/build/static/llvm-CjnVIiX4.js +1 -0
- package/web-ui/build/static/log-duIQICZV.js +1 -0
- package/web-ui/build/static/lolcode-Chrz9tTZ.js +1 -0
- package/web-ui/build/static/lsl-D1sdqECW.js +1 -0
- package/web-ui/build/static/lua-BFoJUb0S.js +1 -0
- package/web-ui/build/static/lua-D8RyRvqw.js +1 -0
- package/web-ui/build/static/magma-Cb3OhPkH.js +1 -0
- package/web-ui/build/static/makefile-BoVTcm8r.js +1 -0
- package/web-ui/build/static/makefile-LpYbnzZi.js +1 -0
- package/web-ui/build/static/markdown-CtQc_FZV.js +1 -0
- package/web-ui/build/static/markdown-DKz9qNdH.js +1 -0
- package/web-ui/build/static/markup-templating-D4EP19Lc.js +1 -0
- package/web-ui/build/static/mathematica-CIjlHVkd.js +1 -0
- package/web-ui/build/static/matlab-2b895p29.js +1 -0
- package/web-ui/build/static/matlab-BuluE4GS.js +1 -0
- package/web-ui/build/static/maxima-BGR8Puew.js +1 -0
- package/web-ui/build/static/maxscript-B429y77A.js +1 -0
- package/web-ui/build/static/mel-CYh_3LnF.js +1 -0
- package/web-ui/build/static/mel-CbYDscql.js +1 -0
- package/web-ui/build/static/mercury-DOee0RcU.js +1 -0
- package/web-ui/build/static/mermaid-Bgnlfred.js +1 -0
- package/web-ui/build/static/mipsasm-CB-uene8.js +1 -0
- package/web-ui/build/static/mizar-7qF42uX5.js +1 -0
- package/web-ui/build/static/mizar-Clogrskx.js +1 -0
- package/web-ui/build/static/mojolicious-BSIpTTKj.js +1 -0
- package/web-ui/build/static/mongodb--rWzrKDS.js +1 -0
- package/web-ui/build/static/monkey-C0lS2_fv.js +1 -0
- package/web-ui/build/static/monkey-DvqsFbfK.js +1 -0
- package/web-ui/build/static/moonscript-D6zFHk1D.js +1 -0
- package/web-ui/build/static/moonscript-JTxm8n_4.js +1 -0
- package/web-ui/build/static/n1ql-BwY55fjF.js +1 -0
- package/web-ui/build/static/n1ql-D8h3fDkJ.js +1 -0
- package/web-ui/build/static/n4js-5XIl8zQT.js +1 -0
- package/web-ui/build/static/nand2tetris-hdl-C4b_TExX.js +1 -0
- package/web-ui/build/static/naniscript-h2vnytgY.js +1 -0
- package/web-ui/build/static/nasm-SJmR3Ebn.js +1 -0
- package/web-ui/build/static/neon-B7dnnKEh.js +1 -0
- package/web-ui/build/static/nevod-zunhA02o.js +1 -0
- package/web-ui/build/static/nginx-BR_D0je7.js +1 -0
- package/web-ui/build/static/nginx-Cf7oQt-G.js +1 -0
- package/web-ui/build/static/nim-D-MjIxvw.js +1 -0
- package/web-ui/build/static/nim-D6YOyDC-.js +1 -0
- package/web-ui/build/static/nix-DCZEZqSO.js +1 -0
- package/web-ui/build/static/nix-Dx16U5rS.js +1 -0
- package/web-ui/build/static/node-repl-P-vGpiQ7.js +1 -0
- package/web-ui/build/static/nsis-CjyZMgjR.js +1 -0
- package/web-ui/build/static/nsis-X8NQeZjE.js +1 -0
- package/web-ui/build/static/objectivec-BejNoH7m.js +1 -0
- package/web-ui/build/static/objectivec-CGy2F8n6.js +1 -0
- package/web-ui/build/static/ocaml-C15hcRxR.js +1 -0
- package/web-ui/build/static/ocaml-U7N8L5Z7.js +1 -0
- package/web-ui/build/static/opencl-Bkm-SovU.js +1 -0
- package/web-ui/build/static/openqasm-BOc5975b.js +1 -0
- package/web-ui/build/static/openscad-CRpFnhV_.js +1 -0
- package/web-ui/build/static/oxygene-eHBZbxHy.js +1 -0
- package/web-ui/build/static/oz-B6RWw36L.js +1 -0
- package/web-ui/build/static/parigp-rifRy-ff.js +1 -0
- package/web-ui/build/static/parser-C0HBjZDk.js +1 -0
- package/web-ui/build/static/parser3-DSK81uS5.js +1 -0
- package/web-ui/build/static/pascal-BWha02r-.js +1 -0
- package/web-ui/build/static/pascaligo-B5sQ2hGz.js +1 -0
- package/web-ui/build/static/pcaxis-B1HLYPhm.js +1 -0
- package/web-ui/build/static/peoplecode-C4FPD4Yt.js +1 -0
- package/web-ui/build/static/perl-CyNx_mIa.js +1 -0
- package/web-ui/build/static/perl-rKxEWgtc.js +1 -0
- package/web-ui/build/static/pf-DbL4T2HZ.js +1 -0
- package/web-ui/build/static/pgsql-BKrwbRTY.js +1 -0
- package/web-ui/build/static/php-Cbd5TyJ-.js +1 -0
- package/web-ui/build/static/php-extras-DoVpsRj3.js +1 -0
- package/web-ui/build/static/php-template-DvdLavxo.js +1 -0
- package/web-ui/build/static/php-wYQJLv7J.js +1 -0
- package/web-ui/build/static/phpdoc-DTzZ5d0C.js +1 -0
- package/web-ui/build/static/plaintext-BRfzJjyj.js +1 -0
- package/web-ui/build/static/plsql-BLiE3aGC.js +1 -0
- package/web-ui/build/static/pony-CzLDxYVb.js +1 -0
- package/web-ui/build/static/powerquery-BdGgwM1a.js +1 -0
- package/web-ui/build/static/powershell-Cxl47yK_.js +1 -0
- package/web-ui/build/static/powershell-DrOFoqBE.js +1 -0
- package/web-ui/build/static/processing-9GbETrF_.js +1 -0
- package/web-ui/build/static/processing-M8gRGxck.js +1 -0
- package/web-ui/build/static/profile-CpNlvCnw.js +1 -0
- package/web-ui/build/static/prolog-CKZzbIr9.js +1 -0
- package/web-ui/build/static/prolog-mmIPeMRS.js +1 -0
- package/web-ui/build/static/promql-sDn1PHGN.js +1 -0
- package/web-ui/build/static/properties-CMFMCgWo.js +1 -0
- package/web-ui/build/static/properties-DQUf7KOp.js +1 -0
- package/web-ui/build/static/protobuf-CeY2Q-pH.js +1 -0
- package/web-ui/build/static/protobuf-WpfASK2n.js +1 -0
- package/web-ui/build/static/psl-D2GfEOkk.js +1 -0
- package/web-ui/build/static/pug-OMqhtHt8.js +1 -0
- package/web-ui/build/static/puppet-B68-xib8.js +1 -0
- package/web-ui/build/static/puppet-DEWzLqRg.js +1 -0
- package/web-ui/build/static/pure-C_CchY8g.js +1 -0
- package/web-ui/build/static/purebasic-D6vSqsja.js +1 -0
- package/web-ui/build/static/purebasic-Dy_z6LTs.js +1 -0
- package/web-ui/build/static/purescript-1f1OoM-A.js +1 -0
- package/web-ui/build/static/python-BssLWmNd.js +1 -0
- package/web-ui/build/static/python-CbOivp-X.js +1 -0
- package/web-ui/build/static/python-repl-Dsbi7aBP.js +1 -0
- package/web-ui/build/static/q-BC6w8B4U.js +1 -0
- package/web-ui/build/static/q-Brd1mf_C.js +1 -0
- package/web-ui/build/static/qml-BG4KN74g.js +1 -0
- package/web-ui/build/static/qml-BW-AE2Ma.js +1 -0
- package/web-ui/build/static/qore-m870d7ZA.js +1 -0
- package/web-ui/build/static/qsharp-BC9vEXOd.js +1 -0
- package/web-ui/build/static/r-BQySF8sO.js +1 -0
- package/web-ui/build/static/r-Cur0B9lo.js +1 -0
- package/web-ui/build/static/racket-CiJlajVU.js +1 -0
- package/web-ui/build/static/reason-C3VZcXa9.js +1 -0
- package/web-ui/build/static/reasonml-CpaxZwMO.js +1 -0
- package/web-ui/build/static/regex-bY-o17az.js +1 -0
- package/web-ui/build/static/rego-WPkEW7us.js +1 -0
- package/web-ui/build/static/renpy-DQr5LC4O.js +1 -0
- package/web-ui/build/static/rest-qmfCQ86m.js +1 -0
- package/web-ui/build/static/rib-DYzEblkc.js +1 -0
- package/web-ui/build/static/rip-D-NWUqHZ.js +1 -0
- package/web-ui/build/static/roboconf-CVmdy543.js +1 -0
- package/web-ui/build/static/roboconf-Ray0NGMb.js +1 -0
- package/web-ui/build/static/robotframework-DlxPBTF_.js +1 -0
- package/web-ui/build/static/routeros-S_f-nuVM.js +1 -0
- package/web-ui/build/static/rsl-CHtR71Pc.js +1 -0
- package/web-ui/build/static/ruby-ByuU-3cy.js +1 -0
- package/web-ui/build/static/ruby-DOin939S.js +1 -0
- package/web-ui/build/static/ruleslanguage-zhFrFxeU.js +1 -0
- package/web-ui/build/static/rust-B606UvZv.js +1 -0
- package/web-ui/build/static/rust-BJMuS7if.js +1 -0
- package/web-ui/build/static/sas-Bzk_0rOu.js +1 -0
- package/web-ui/build/static/sas-C-C55Hy4.js +1 -0
- package/web-ui/build/static/sass-DKkkoHtH.js +1 -0
- package/web-ui/build/static/scala-BKlnHttP.js +1 -0
- package/web-ui/build/static/scala-IsJjjIKA.js +1 -0
- package/web-ui/build/static/scheme-Bq_tfrRE.js +1 -0
- package/web-ui/build/static/scheme-DiXFvLKG.js +1 -0
- package/web-ui/build/static/scilab-DVyT87si.js +1 -0
- package/web-ui/build/static/scss-BtDpAVzH.js +1 -0
- package/web-ui/build/static/scss-D8cn4aNM.js +1 -0
- package/web-ui/build/static/shell-YROU1_yo.js +1 -0
- package/web-ui/build/static/shell-session-D06UXOLk.js +1 -0
- package/web-ui/build/static/smali-B1Wl_1dD.js +1 -0
- package/web-ui/build/static/smali-D2R-11j_.js +1 -0
- package/web-ui/build/static/smalltalk-M2S1lL6Z.js +1 -0
- package/web-ui/build/static/smalltalk-OWg84676.js +1 -0
- package/web-ui/build/static/smarty-l1m-zZmR.js +1 -0
- package/web-ui/build/static/sml-B6gSTHMm.js +1 -0
- package/web-ui/build/static/sml-BKURhRNM.js +1 -0
- package/web-ui/build/static/solidity-BcrqESJt.js +1 -0
- package/web-ui/build/static/solution-file-BYpCOi9k.js +1 -0
- package/web-ui/build/static/soy-DOQhQ7Di.js +1 -0
- package/web-ui/build/static/sparql-BwiIX_wO.js +1 -0
- package/web-ui/build/static/splunk-spl-DuIl6XxN.js +1 -0
- package/web-ui/build/static/sqf-8cYPidUR.js +1 -0
- package/web-ui/build/static/sqf-n8nRTmXc.js +1 -0
- package/web-ui/build/static/sql-D0WSLeXV.js +1 -0
- package/web-ui/build/static/sql-D8KWxFl_.js +1 -0
- package/web-ui/build/static/sql_more-D3ozDsf6.js +1 -0
- package/web-ui/build/static/squirrel-C4U4fAL5.js +1 -0
- package/web-ui/build/static/stan-BbFEvT-l.js +1 -0
- package/web-ui/build/static/stan-CJ4ny6dZ.js +1 -0
- package/web-ui/build/static/stata-BKEkbqzD.js +1 -0
- package/web-ui/build/static/step21-52PURHjy.js +1 -0
- package/web-ui/build/static/stylus-buszfxDg.js +1 -0
- package/web-ui/build/static/stylus-y0WOYXDO.js +1 -0
- package/web-ui/build/static/subunit-DU_iInw0.js +1 -0
- package/web-ui/build/static/swift-1VeEUHZi.js +1 -0
- package/web-ui/build/static/swift-Iw0x_Dum.js +1 -0
- package/web-ui/build/static/systemd-BT_5EOz8.js +1 -0
- package/web-ui/build/static/t4-cs-DlHeFrua.js +1 -0
- package/web-ui/build/static/t4-templating-Bz3RFfzp.js +1 -0
- package/web-ui/build/static/t4-vb-BMG0Q3qg.js +1 -0
- package/web-ui/build/static/taggerscript-CxwafGpT.js +1 -0
- package/web-ui/build/static/tap-6QugbkZA.js +1 -0
- package/web-ui/build/static/tap-SB1ST166.js +1 -0
- package/web-ui/build/static/tcl-CpV5bsKx.js +1 -0
- package/web-ui/build/static/tcl-Dikgd33H.js +1 -0
- package/web-ui/build/static/textile-aPmNtrkM.js +1 -0
- package/web-ui/build/static/thrift-B4Snltg5.js +1 -0
- package/web-ui/build/static/toml-B8SfswHQ.js +1 -0
- package/web-ui/build/static/tp-CdO-cn9g.js +1 -0
- package/web-ui/build/static/tremor-CqqCLe4A.js +1 -0
- package/web-ui/build/static/tsx-Ck0ZDqEy.js +1 -0
- package/web-ui/build/static/tt2-BrqZXSkJ.js +1 -0
- package/web-ui/build/static/turtle-DpnSIzmN.js +1 -0
- package/web-ui/build/static/twig-B5Et_eTY.js +1 -0
- package/web-ui/build/static/twig-C3vsy99c.js +1 -0
- package/web-ui/build/static/typescript-DH7tzpeO.js +1 -0
- package/web-ui/build/static/typescript-s1qBbHGm.js +1 -0
- package/web-ui/build/static/typoscript-DD8499cq.js +1 -0
- package/web-ui/build/static/unrealscript-C1zerCVR.js +1 -0
- package/web-ui/build/static/uorazor-CtRNfzg2.js +1 -0
- package/web-ui/build/static/uri-CAfIv8vn.js +1 -0
- package/web-ui/build/static/v-B6_f9ZGJ.js +1 -0
- package/web-ui/build/static/vala-BIpejmrf.js +1 -0
- package/web-ui/build/static/vala-BYLjm9ih.js +1 -0
- package/web-ui/build/static/vbnet-DEW7adbx.js +1 -0
- package/web-ui/build/static/vbnet-D_CuPCaz.js +1 -0
- package/web-ui/build/static/vbscript-Do9hsQ_u.js +1 -0
- package/web-ui/build/static/vbscript-html-4bMQ0-FJ.js +1 -0
- package/web-ui/build/static/velocity-CQjo2-fz.js +1 -0
- package/web-ui/build/static/verilog-C-Xvd__o.js +1 -0
- package/web-ui/build/static/verilog-Dn1ZGsRG.js +1 -0
- package/web-ui/build/static/vhdl-DZ-dTOLA.js +1 -0
- package/web-ui/build/static/vhdl-bDNJfpa7.js +1 -0
- package/web-ui/build/static/vim-BDAo5YHC.js +1 -0
- package/web-ui/build/static/vim-ClkOafc3.js +1 -0
- package/web-ui/build/static/visual-basic-DXIeLZZ8.js +1 -0
- package/web-ui/build/static/warpscript-f7veA-3J.js +1 -0
- package/web-ui/build/static/wasm-TToDlmNk.js +1 -0
- package/web-ui/build/static/web-idl-CrrjMFQT.js +1 -0
- package/web-ui/build/static/wiki-aicisDW2.js +1 -0
- package/web-ui/build/static/wolfram-C_A80rAh.js +1 -0
- package/web-ui/build/static/wren-DkVyeDoy.js +1 -0
- package/web-ui/build/static/x86asm-fx1o_ltw.js +1 -0
- package/web-ui/build/static/xeora-D-uaDMXn.js +1 -0
- package/web-ui/build/static/xl-Dnyvb9_S.js +1 -0
- package/web-ui/build/static/xml-BGV0zG9K.js +1 -0
- package/web-ui/build/static/xml-doc-DOGLcenw.js +1 -0
- package/web-ui/build/static/xojo-B3Qgvb5A.js +1 -0
- package/web-ui/build/static/xquery-C-B5-0Q9.js +1 -0
- package/web-ui/build/static/xquery-KbuiAVhj.js +1 -0
- package/web-ui/build/static/yaml-CBWBoq6m.js +1 -0
- package/web-ui/build/static/yaml-IghlDZf6.js +1 -0
- package/web-ui/build/static/yang-CArp62P5.js +1 -0
- package/web-ui/build/static/zephir-DMLTJ9_9.js +1 -0
- package/web-ui/build/static/zig-CWG2311v.js +1 -0
- package/web-ui/build/static/1c-4BRB87En.js +0 -1
- package/web-ui/build/static/abap-BXIqiAfL.js +0 -1
- package/web-ui/build/static/abnf-0gk1i0eD.js +0 -1
- package/web-ui/build/static/abnf-jcv7vN9a.js +0 -1
- package/web-ui/build/static/accesslog-bXE2aOZl.js +0 -1
- package/web-ui/build/static/actionscript-CF-bqawj.js +0 -1
- package/web-ui/build/static/actionscript-CodwLKar.js +0 -1
- package/web-ui/build/static/ada-BBEDI84F.js +0 -1
- package/web-ui/build/static/ada-Kb6JvaxP.js +0 -1
- package/web-ui/build/static/agda-UvnMXUUo.js +0 -1
- package/web-ui/build/static/al-D5QZ0ijQ.js +0 -1
- package/web-ui/build/static/angelscript-RpvZxbeT.js +0 -1
- package/web-ui/build/static/antlr4-BPyUvfii.js +0 -1
- package/web-ui/build/static/apache-CtM2pGik.js +0 -1
- package/web-ui/build/static/apacheconf-D-i9eISH.js +0 -1
- package/web-ui/build/static/apex-Dhn_SJi4.js +0 -1
- package/web-ui/build/static/apl-HWtdSaYy.js +0 -1
- package/web-ui/build/static/applescript-Br9NrmTP.js +0 -1
- package/web-ui/build/static/applescript-DLL0TuGw.js +0 -1
- package/web-ui/build/static/aql-MjCgNRUX.js +0 -1
- package/web-ui/build/static/arcade--DFvEPVv.js +0 -1
- package/web-ui/build/static/arduino-Cqw5W_fL.js +0 -1
- package/web-ui/build/static/arduino-DIDBbB7R.js +0 -1
- package/web-ui/build/static/arff-GGvbnOhc.js +0 -1
- package/web-ui/build/static/armasm-DKLRDLs1.js +0 -1
- package/web-ui/build/static/asciidoc-CN5qfm0K.js +0 -1
- package/web-ui/build/static/asciidoc-CeQEWYOj.js +0 -1
- package/web-ui/build/static/asm6502-B1l2Hc9j.js +0 -1
- package/web-ui/build/static/asmatmel-BAojNNWJ.js +0 -1
- package/web-ui/build/static/aspectj-DqZFhwdh.js +0 -1
- package/web-ui/build/static/aspnet-C0kQPqSr.js +0 -1
- package/web-ui/build/static/autohotkey-DY25td-Z.js +0 -1
- package/web-ui/build/static/autohotkey-DlqXINgk.js +0 -1
- package/web-ui/build/static/autoit-By7J2Y34.js +0 -1
- package/web-ui/build/static/autoit-nsu9sBga.js +0 -1
- package/web-ui/build/static/avisynth-DmhvVsr-.js +0 -1
- package/web-ui/build/static/avrasm-CHfBwwoQ.js +0 -1
- package/web-ui/build/static/avro-idl-BKgIWEIF.js +0 -1
- package/web-ui/build/static/awk-CpAb4d4E.js +0 -1
- package/web-ui/build/static/axapta-CM4aTfCZ.js +0 -1
- package/web-ui/build/static/bash-D1KTDlk-.js +0 -1
- package/web-ui/build/static/bash-DShkskxb.js +0 -1
- package/web-ui/build/static/basic-C4CfKvhg.js +0 -1
- package/web-ui/build/static/basic-CkQS4VwL.js +0 -1
- package/web-ui/build/static/batch-DZtrClI1.js +0 -1
- package/web-ui/build/static/bbcode-CY2FsfaO.js +0 -1
- package/web-ui/build/static/bicep-BeSEpm_3.js +0 -1
- package/web-ui/build/static/birb-huu22Mwu.js +0 -1
- package/web-ui/build/static/bison-CmbxfR57.js +0 -1
- package/web-ui/build/static/bnf-c2l_4HXN.js +0 -1
- package/web-ui/build/static/bnf-wucEDTqY.js +0 -1
- package/web-ui/build/static/brainfuck-CzWBg5U7.js +0 -1
- package/web-ui/build/static/brainfuck-I_YQ4sma.js +0 -1
- package/web-ui/build/static/brightscript-LOkD4eYW.js +0 -1
- package/web-ui/build/static/bro-CLJ7Afqo.js +0 -1
- package/web-ui/build/static/bsl-DbUgC2FQ.js +0 -1
- package/web-ui/build/static/c-C0S2D2ge.js +0 -1
- package/web-ui/build/static/c-KH25O_pL.js +0 -1
- package/web-ui/build/static/c-like-DtAFxyl_.js +0 -1
- package/web-ui/build/static/cal-uGiVJBNC.js +0 -1
- package/web-ui/build/static/capnproto-DSLchjOW.js +0 -1
- package/web-ui/build/static/ceylon-Bbxk66YL.js +0 -1
- package/web-ui/build/static/cfscript-CjDdgKbl.js +0 -1
- package/web-ui/build/static/chaiscript-CnRXaMae.js +0 -1
- package/web-ui/build/static/cil-CM9ygF3R.js +0 -1
- package/web-ui/build/static/clean-ppAH0SYy.js +0 -1
- package/web-ui/build/static/clojure-C5LVccGq.js +0 -1
- package/web-ui/build/static/clojure-DtLXiuuC.js +0 -1
- package/web-ui/build/static/clojure-repl-fSdrYuup.js +0 -1
- package/web-ui/build/static/cmake-AD1fuzSY.js +0 -1
- package/web-ui/build/static/cmake-D-o08Yta.js +0 -1
- package/web-ui/build/static/cobol-bDh1KHf9.js +0 -1
- package/web-ui/build/static/coffeescript-D8InK8kf.js +0 -1
- package/web-ui/build/static/coffeescript-MKWUOXb5.js +0 -1
- package/web-ui/build/static/concurnas-CR56nj6R.js +0 -1
- package/web-ui/build/static/coq-DDLBsBJu.js +0 -1
- package/web-ui/build/static/coq-WbhtANeW.js +0 -1
- package/web-ui/build/static/cos-Bfmre3op.js +0 -1
- package/web-ui/build/static/cpp-Cdy6A7gI.js +0 -1
- package/web-ui/build/static/cpp-De2KZejr.js +0 -1
- package/web-ui/build/static/crmsh-uf3vbKnN.js +0 -1
- package/web-ui/build/static/crystal-BHMyEVPP.js +0 -1
- package/web-ui/build/static/crystal-DXAQwftg.js +0 -1
- package/web-ui/build/static/csharp-Ci2MRG6L.js +0 -1
- package/web-ui/build/static/csharp-D8MV2a7f.js +0 -1
- package/web-ui/build/static/cshtml-kVj3v3uY.js +0 -1
- package/web-ui/build/static/csp-B83CCdVc.js +0 -1
- package/web-ui/build/static/csp-DUO7zlPh.js +0 -1
- package/web-ui/build/static/css-BWsx7mtO.js +0 -1
- package/web-ui/build/static/css-extras-oHch2Y5C.js +0 -1
- package/web-ui/build/static/csv-DIf0iNlc.js +0 -1
- package/web-ui/build/static/cypher-B1rOF_f3.js +0 -1
- package/web-ui/build/static/d-BUgLS87u.js +0 -1
- package/web-ui/build/static/d-ClM8XTCr.js +0 -1
- package/web-ui/build/static/dart-D5rVGtrb.js +0 -1
- package/web-ui/build/static/dart-Oal__k4m.js +0 -1
- package/web-ui/build/static/dataweave-B0uxnNDC.js +0 -1
- package/web-ui/build/static/dax-B9z6d1P6.js +0 -1
- package/web-ui/build/static/delphi-KMlx8q8A.js +0 -1
- package/web-ui/build/static/dhall-DLWFgSR8.js +0 -1
- package/web-ui/build/static/diff-DDMGnyhE.js +0 -1
- package/web-ui/build/static/diff-yg1oXq3U.js +0 -1
- package/web-ui/build/static/django-BDtkIu_c.js +0 -1
- package/web-ui/build/static/django-Bkn9HlyQ.js +0 -1
- package/web-ui/build/static/dns-Bx1VHfo6.js +0 -1
- package/web-ui/build/static/dns-zone-file-Bgn5zn_J.js +0 -1
- package/web-ui/build/static/docker-CTdrZJHc.js +0 -1
- package/web-ui/build/static/dockerfile-B7ziWbf_.js +0 -1
- package/web-ui/build/static/dos-cbBC5Icj.js +0 -1
- package/web-ui/build/static/dot-JXSVTLEH.js +0 -1
- package/web-ui/build/static/dsconfig-sEua2C2o.js +0 -1
- package/web-ui/build/static/dts-Zem_gT_O.js +0 -1
- package/web-ui/build/static/dust-B-dZ6-uQ.js +0 -1
- package/web-ui/build/static/ebnf-CXfeZoXF.js +0 -1
- package/web-ui/build/static/ebnf-raQs4FpT.js +0 -1
- package/web-ui/build/static/editorconfig-hp8ARbHf.js +0 -1
- package/web-ui/build/static/eiffel-tO3jaG00.js +0 -1
- package/web-ui/build/static/ejs-BGmD5Rvl.js +0 -1
- package/web-ui/build/static/elixir-CF0JDN9L.js +0 -1
- package/web-ui/build/static/elixir-CFSil_Ou.js +0 -1
- package/web-ui/build/static/elm-As6XaD-g.js +0 -1
- package/web-ui/build/static/elm-pw5GpqTZ.js +0 -1
- package/web-ui/build/static/erb-BrpCJIyN.js +0 -1
- package/web-ui/build/static/erb-D2_eJU9C.js +0 -1
- package/web-ui/build/static/erlang-5rSv6NMZ.js +0 -1
- package/web-ui/build/static/erlang-RCAxVMBd.js +0 -1
- package/web-ui/build/static/erlang-repl-BN0h_6XR.js +0 -1
- package/web-ui/build/static/etlua-BMtMnKtv.js +0 -1
- package/web-ui/build/static/excel-CRNS57iM.js +0 -1
- package/web-ui/build/static/excel-formula-BNw56R2m.js +0 -1
- package/web-ui/build/static/factor-7lsloWTf.js +0 -1
- package/web-ui/build/static/false-CQUvGnfd.js +0 -1
- package/web-ui/build/static/firestore-security-rules-WC1PabFS.js +0 -1
- package/web-ui/build/static/fix-Cs6kLeYV.js +0 -1
- package/web-ui/build/static/flix-1fdMgw2I.js +0 -1
- package/web-ui/build/static/flow-CRPduKSH.js +0 -1
- package/web-ui/build/static/fortran-C-3TUt5R.js +0 -1
- package/web-ui/build/static/fortran-CA4bbZCj.js +0 -1
- package/web-ui/build/static/fsharp-BScjCFae.js +0 -1
- package/web-ui/build/static/fsharp-BtHWuW4o.js +0 -1
- package/web-ui/build/static/ftl-Re-S2zvF.js +0 -1
- package/web-ui/build/static/gams-Cr12l-cM.js +0 -1
- package/web-ui/build/static/gap-H0O9-Zju.js +0 -1
- package/web-ui/build/static/gauss-CW8jwURx.js +0 -1
- package/web-ui/build/static/gcode-CIxfYtg9.js +0 -1
- package/web-ui/build/static/gcode-CVqRWYeB.js +0 -1
- package/web-ui/build/static/gdscript-BltZCaKl.js +0 -1
- package/web-ui/build/static/gedcom-nMT5ety_.js +0 -1
- package/web-ui/build/static/gherkin-B4M7CGOo.js +0 -1
- package/web-ui/build/static/gherkin-DumuqAQF.js +0 -1
- package/web-ui/build/static/git-BBiBlZ5H.js +0 -1
- package/web-ui/build/static/glsl-D8ckiRVo.js +0 -1
- package/web-ui/build/static/glsl-Z4VdDyPa.js +0 -1
- package/web-ui/build/static/gml-BHuSndHE.js +0 -1
- package/web-ui/build/static/gml-DZpfN_A4.js +0 -1
- package/web-ui/build/static/gn-BjpAHNh_.js +0 -1
- package/web-ui/build/static/go-BeZ9IgZB.js +0 -1
- package/web-ui/build/static/go-HEXrcgIc.js +0 -1
- package/web-ui/build/static/go-module-BGdPb7sP.js +0 -1
- package/web-ui/build/static/golo-Cr70KUbI.js +0 -1
- package/web-ui/build/static/gradle-C7MXrDnB.js +0 -1
- package/web-ui/build/static/graphql-CJK0wQjf.js +0 -1
- package/web-ui/build/static/groovy-Bwe7hkFG.js +0 -1
- package/web-ui/build/static/groovy-Dc6WDoKa.js +0 -1
- package/web-ui/build/static/haml-BSsAjltt.js +0 -1
- package/web-ui/build/static/haml-CZih7X_4.js +0 -1
- package/web-ui/build/static/handlebars-CN8hCpsy.js +0 -1
- package/web-ui/build/static/handlebars-XBLc7i13.js +0 -1
- package/web-ui/build/static/haskell-BH9WhK10.js +0 -1
- package/web-ui/build/static/haskell-Djf2J1vd.js +0 -1
- package/web-ui/build/static/haxe-BllD-W9e.js +0 -1
- package/web-ui/build/static/haxe-DY8Hyn7u.js +0 -1
- package/web-ui/build/static/hcl-CfktAP2o.js +0 -1
- package/web-ui/build/static/hlsl-B2JSOD9d.js +0 -1
- package/web-ui/build/static/hoon-BILyDobB.js +0 -1
- package/web-ui/build/static/hpkp-Bb8rXx4p.js +0 -1
- package/web-ui/build/static/hsp-BmjeJC21.js +0 -1
- package/web-ui/build/static/hsts-DJhW57Fu.js +0 -1
- package/web-ui/build/static/htmlbars-CJe_ZLjw.js +0 -1
- package/web-ui/build/static/http-D7SlABvQ.js +0 -1
- package/web-ui/build/static/http-DEUJqmEm.js +0 -1
- package/web-ui/build/static/hy-DVfsgEbr.js +0 -1
- package/web-ui/build/static/ichigojam-CPdz2bOt.js +0 -1
- package/web-ui/build/static/icon-DYK9RbU9.js +0 -1
- package/web-ui/build/static/icu-message-format-HiZB_alB.js +0 -1
- package/web-ui/build/static/idris-Clk3tJIE.js +0 -1
- package/web-ui/build/static/iecst-D7wkeksq.js +0 -1
- package/web-ui/build/static/ignore-GSm-L3jG.js +0 -1
- package/web-ui/build/static/index-BJe5td0v.js +0 -13
- package/web-ui/build/static/index-BYvljeMN.js +0 -1
- package/web-ui/build/static/index-CLelJq9j.js +0 -1156
- package/web-ui/build/static/index-f5UnFSsY.css +0 -1
- package/web-ui/build/static/inform7-D3gc0hSc.js +0 -1
- package/web-ui/build/static/inform7-DLdvZTxX.js +0 -1
- package/web-ui/build/static/ini-CVcWx1TA.js +0 -1
- package/web-ui/build/static/ini-CxYBdsvZ.js +0 -1
- package/web-ui/build/static/io-D760QF0i.js +0 -1
- package/web-ui/build/static/irpf90-DfkXdZut.js +0 -1
- package/web-ui/build/static/isbl-Bl3W-krY.js +0 -1
- package/web-ui/build/static/j-DyJj9FSc.js +0 -1
- package/web-ui/build/static/java-CLw1cH97.js +0 -1
- package/web-ui/build/static/java-vXaHBzP4.js +0 -1
- package/web-ui/build/static/javadoc-p5hIe48g.js +0 -1
- package/web-ui/build/static/javadoclike-OXi-sQ0q.js +0 -1
- package/web-ui/build/static/javascript-CTSqES8o.js +0 -1
- package/web-ui/build/static/javastacktrace-PC9-3moA.js +0 -1
- package/web-ui/build/static/jboss-cli-CxOZKDLi.js +0 -1
- package/web-ui/build/static/jexl-C4kSXhD1.js +0 -1
- package/web-ui/build/static/jolie-CntM8cWx.js +0 -1
- package/web-ui/build/static/jq-D_4bTCm0.js +0 -1
- package/web-ui/build/static/js-extras-Cx9VAZJd.js +0 -1
- package/web-ui/build/static/js-templates-BqyJUDxJ.js +0 -1
- package/web-ui/build/static/jsdoc-CNHLgAph.js +0 -1
- package/web-ui/build/static/json-BXIFrbVC.js +0 -1
- package/web-ui/build/static/json-DRUrJL_F.js +0 -1
- package/web-ui/build/static/json5-EsTrOpXr.js +0 -1
- package/web-ui/build/static/jsonp-RijEuTJY.js +0 -1
- package/web-ui/build/static/jsstacktrace-dM13uE1y.js +0 -1
- package/web-ui/build/static/jsx-Cf0j02DZ.js +0 -1
- package/web-ui/build/static/julia-BLrtj5Dj.js +0 -1
- package/web-ui/build/static/julia-D0PJgQhi.js +0 -1
- package/web-ui/build/static/julia-repl-BLnLCve4.js +0 -1
- package/web-ui/build/static/keepalived-SvzEYloD.js +0 -1
- package/web-ui/build/static/keyman-B5l2mmmE.js +0 -1
- package/web-ui/build/static/kotlin-B_6COR1e.js +0 -1
- package/web-ui/build/static/kotlin-vd1Xdz6D.js +0 -1
- package/web-ui/build/static/kumir-8mIZWgJQ.js +0 -1
- package/web-ui/build/static/kusto-CoV2oHqt.js +0 -1
- package/web-ui/build/static/lasso-BjjUNa_o.js +0 -1
- package/web-ui/build/static/latex-C9KOfuFk.js +0 -1
- package/web-ui/build/static/latex-DhLttY-I.js +0 -1
- package/web-ui/build/static/latte-CaYNaOoK.js +0 -1
- package/web-ui/build/static/ldif-DFxnpH3G.js +0 -1
- package/web-ui/build/static/leaf-DrMpC83a.js +0 -1
- package/web-ui/build/static/less-DUoYpEFn.js +0 -1
- package/web-ui/build/static/less-nh0XCcut.js +0 -1
- package/web-ui/build/static/lilypond-BlqjLr3W.js +0 -1
- package/web-ui/build/static/liquid-BVGHSG0T.js +0 -1
- package/web-ui/build/static/lisp-CEK8BtYQ.js +0 -1
- package/web-ui/build/static/lisp-D_jGHxhc.js +0 -1
- package/web-ui/build/static/livecodeserver-CFUDw_SK.js +0 -1
- package/web-ui/build/static/livescript-C5xzpiLM.js +0 -1
- package/web-ui/build/static/livescript-CKoPcK0c.js +0 -1
- package/web-ui/build/static/llvm-BBOVIeTl.js +0 -1
- package/web-ui/build/static/llvm-ioC5bCUB.js +0 -1
- package/web-ui/build/static/log-CPYTqm4T.js +0 -1
- package/web-ui/build/static/lolcode-BkT93adT.js +0 -1
- package/web-ui/build/static/lsl-M98YPNRW.js +0 -1
- package/web-ui/build/static/lua-D7Lum5n9.js +0 -1
- package/web-ui/build/static/lua-DHyr0QwE.js +0 -1
- package/web-ui/build/static/magma-BwMFjwQu.js +0 -1
- package/web-ui/build/static/makefile-BFYZ-SfG.js +0 -1
- package/web-ui/build/static/makefile-D6oyR2lD.js +0 -1
- package/web-ui/build/static/markdown-6jtg6KZm.js +0 -1
- package/web-ui/build/static/markdown-DTLtPgeP.js +0 -1
- package/web-ui/build/static/markup-templating-K8uoAIqY.js +0 -1
- package/web-ui/build/static/mathematica-cW5hOuB2.js +0 -1
- package/web-ui/build/static/matlab-CwSNWEq8.js +0 -1
- package/web-ui/build/static/matlab-MQ972BY-.js +0 -1
- package/web-ui/build/static/maxima-CMSFLri-.js +0 -1
- package/web-ui/build/static/maxscript-BzcoS2KA.js +0 -1
- package/web-ui/build/static/mel-Cd20pAs-.js +0 -1
- package/web-ui/build/static/mel-KWG5N49g.js +0 -1
- package/web-ui/build/static/mercury-eW1ljJh0.js +0 -1
- package/web-ui/build/static/mermaid-D3zeCM84.js +0 -1
- package/web-ui/build/static/mipsasm-B5g6Ndra.js +0 -1
- package/web-ui/build/static/mizar-C_nZ0Ts9.js +0 -1
- package/web-ui/build/static/mizar-CuTNEv2t.js +0 -1
- package/web-ui/build/static/mojolicious-C1Xq--lT.js +0 -1
- package/web-ui/build/static/mongodb-C_3giArw.js +0 -1
- package/web-ui/build/static/monkey-DQ1olPd-.js +0 -1
- package/web-ui/build/static/monkey-n4Tbrep7.js +0 -1
- package/web-ui/build/static/moonscript-CmnQJuIL.js +0 -1
- package/web-ui/build/static/moonscript-DXgmWjLy.js +0 -1
- package/web-ui/build/static/n1ql-531a3W-1.js +0 -1
- package/web-ui/build/static/n1ql-BYH9EvME.js +0 -1
- package/web-ui/build/static/n4js-Cy0LcM-V.js +0 -1
- package/web-ui/build/static/nand2tetris-hdl-CKOztBDD.js +0 -1
- package/web-ui/build/static/naniscript-oLFpxBGE.js +0 -1
- package/web-ui/build/static/nasm-DLPnwFkM.js +0 -1
- package/web-ui/build/static/neon-Cn03wGUR.js +0 -1
- package/web-ui/build/static/nevod-C_VRvbdf.js +0 -1
- package/web-ui/build/static/nginx-60SpLv4t.js +0 -1
- package/web-ui/build/static/nginx-DZLHid-q.js +0 -1
- package/web-ui/build/static/nim-BnrHdqGC.js +0 -1
- package/web-ui/build/static/nim-Ds3pmwtE.js +0 -1
- package/web-ui/build/static/nix-Dl-dS0w4.js +0 -1
- package/web-ui/build/static/nix-jL62FzTz.js +0 -1
- package/web-ui/build/static/node-repl-BAuDzNZd.js +0 -1
- package/web-ui/build/static/nsis-CEnFjfNr.js +0 -1
- package/web-ui/build/static/nsis-CcCz6HIu.js +0 -1
- package/web-ui/build/static/objectivec-CZXfVowS.js +0 -1
- package/web-ui/build/static/objectivec-CuaFU-Ef.js +0 -1
- package/web-ui/build/static/ocaml-BGAzfwAx.js +0 -1
- package/web-ui/build/static/ocaml-BoO1lU26.js +0 -1
- package/web-ui/build/static/opencl-DAnD5xP-.js +0 -1
- package/web-ui/build/static/openqasm-CO7gdVj9.js +0 -1
- package/web-ui/build/static/openscad-B2wMEMQR.js +0 -1
- package/web-ui/build/static/oxygene-1erv93gF.js +0 -1
- package/web-ui/build/static/oz-D3334gi7.js +0 -1
- package/web-ui/build/static/parigp-rQZTN8zi.js +0 -1
- package/web-ui/build/static/parser-B4ZSZ1ig.js +0 -1
- package/web-ui/build/static/parser3-CCCjkYLG.js +0 -1
- package/web-ui/build/static/pascal-DeC9Pvom.js +0 -1
- package/web-ui/build/static/pascaligo-CT2u6UpO.js +0 -1
- package/web-ui/build/static/pcaxis-CvlRg6t4.js +0 -1
- package/web-ui/build/static/peoplecode-BYahULz2.js +0 -1
- package/web-ui/build/static/perl-CKgvyY59.js +0 -1
- package/web-ui/build/static/perl-E7sx7Izv.js +0 -1
- package/web-ui/build/static/pf-D9wnFBt7.js +0 -1
- package/web-ui/build/static/pgsql-CrlBdRAn.js +0 -1
- package/web-ui/build/static/php-D2O-B3y7.js +0 -1
- package/web-ui/build/static/php-extras-BKqZuzgt.js +0 -1
- package/web-ui/build/static/php-nfXl9WfB.js +0 -1
- package/web-ui/build/static/php-template-Cg8ERLNQ.js +0 -1
- package/web-ui/build/static/phpdoc-Z1u90OwH.js +0 -1
- package/web-ui/build/static/plaintext-DkNVeXWx.js +0 -1
- package/web-ui/build/static/plsql-DO5fJNhS.js +0 -1
- package/web-ui/build/static/pony-DXIqq5Bk.js +0 -1
- package/web-ui/build/static/powerquery-B2ovxJZi.js +0 -1
- package/web-ui/build/static/powershell-BVeqqari.js +0 -1
- package/web-ui/build/static/powershell-CskV4qWh.js +0 -1
- package/web-ui/build/static/processing-D90SJpnq.js +0 -1
- package/web-ui/build/static/processing-DP2mf97Z.js +0 -1
- package/web-ui/build/static/profile-H6zk8v_f.js +0 -1
- package/web-ui/build/static/prolog-AUfxYiJV.js +0 -1
- package/web-ui/build/static/prolog-Dz2WdsVN.js +0 -1
- package/web-ui/build/static/promql-CloMJmMW.js +0 -1
- package/web-ui/build/static/properties-CTl3mnrP.js +0 -1
- package/web-ui/build/static/properties-D2RfteTZ.js +0 -1
- package/web-ui/build/static/protobuf-Be9oqQCu.js +0 -1
- package/web-ui/build/static/protobuf-BgG8zUnY.js +0 -1
- package/web-ui/build/static/psl-Bqx8iN9e.js +0 -1
- package/web-ui/build/static/pug-CHfFC0Wg.js +0 -1
- package/web-ui/build/static/puppet-__1ifzZS.js +0 -1
- package/web-ui/build/static/puppet-pbtRCMgd.js +0 -1
- package/web-ui/build/static/pure-B9STuf4F.js +0 -1
- package/web-ui/build/static/purebasic-7ADyn-Ce.js +0 -1
- package/web-ui/build/static/purebasic-Bc06YQcD.js +0 -1
- package/web-ui/build/static/purescript-CU-dDebr.js +0 -1
- package/web-ui/build/static/python-BEsXrEbi.js +0 -1
- package/web-ui/build/static/python-CZFrgH2X.js +0 -1
- package/web-ui/build/static/python-repl-CI9GmJce.js +0 -1
- package/web-ui/build/static/q-E7xvTGRo.js +0 -1
- package/web-ui/build/static/q-hvg9aQoY.js +0 -1
- package/web-ui/build/static/qml-DkZWcxEv.js +0 -1
- package/web-ui/build/static/qml-DpdWla8G.js +0 -1
- package/web-ui/build/static/qore-Dsm7ACR_.js +0 -1
- package/web-ui/build/static/qsharp-BBec6MJR.js +0 -1
- package/web-ui/build/static/r-CTVkq_Ky.js +0 -1
- package/web-ui/build/static/r-DHGNCupF.js +0 -1
- package/web-ui/build/static/racket-hoSh4YPx.js +0 -1
- package/web-ui/build/static/reason-CQPUIbsm.js +0 -1
- package/web-ui/build/static/reasonml-BXtFFSTZ.js +0 -1
- package/web-ui/build/static/regex-BNkF_ufb.js +0 -1
- package/web-ui/build/static/rego-BXHrjItC.js +0 -1
- package/web-ui/build/static/renpy-CBQvK_5t.js +0 -1
- package/web-ui/build/static/rest-Bf8hzmF1.js +0 -1
- package/web-ui/build/static/rib-D0a4KzlP.js +0 -1
- package/web-ui/build/static/rip-DchN4BQN.js +0 -1
- package/web-ui/build/static/roboconf-HXnyGNTm.js +0 -1
- package/web-ui/build/static/roboconf-zfK6mgmU.js +0 -1
- package/web-ui/build/static/robotframework-DnP-vXyd.js +0 -1
- package/web-ui/build/static/routeros-CDirYxZY.js +0 -1
- package/web-ui/build/static/rsl-BCK_msc-.js +0 -1
- package/web-ui/build/static/ruby--mXX6GNK.js +0 -1
- package/web-ui/build/static/ruby-BIdQYq0Y.js +0 -1
- package/web-ui/build/static/ruleslanguage-BD07s5RU.js +0 -1
- package/web-ui/build/static/rust-Bgni9V7U.js +0 -1
- package/web-ui/build/static/rust-OywmQ2ox.js +0 -1
- package/web-ui/build/static/sas-B6-82htH.js +0 -1
- package/web-ui/build/static/sas-k9XEScbR.js +0 -1
- package/web-ui/build/static/sass-BOvNBStT.js +0 -1
- package/web-ui/build/static/scala-At07fmMd.js +0 -1
- package/web-ui/build/static/scala-DUOfqSaU.js +0 -1
- package/web-ui/build/static/scheme-B87lC0bK.js +0 -1
- package/web-ui/build/static/scheme-BS7OzWRX.js +0 -1
- package/web-ui/build/static/scilab-Bmn4jjcu.js +0 -1
- package/web-ui/build/static/scss-DTeB95yE.js +0 -1
- package/web-ui/build/static/scss-xilnl6Dx.js +0 -1
- package/web-ui/build/static/shell-CKetyy4y.js +0 -1
- package/web-ui/build/static/shell-session-B6rat2c7.js +0 -1
- package/web-ui/build/static/smali-C9O9CXOD.js +0 -1
- package/web-ui/build/static/smali-CBkgbinS.js +0 -1
- package/web-ui/build/static/smalltalk-CuUjFHiz.js +0 -1
- package/web-ui/build/static/smalltalk-D0xhFL9b.js +0 -1
- package/web-ui/build/static/smarty-CY0N0d5x.js +0 -1
- package/web-ui/build/static/sml-BVAw3fjB.js +0 -1
- package/web-ui/build/static/sml-CO9XB1ax.js +0 -1
- package/web-ui/build/static/solidity-BNixD4Dx.js +0 -1
- package/web-ui/build/static/solution-file-DHyGXf2y.js +0 -1
- package/web-ui/build/static/soy-Cxgjntsl.js +0 -1
- package/web-ui/build/static/sparql-CDLqu9vy.js +0 -1
- package/web-ui/build/static/splunk-spl-Cmkl_Xmw.js +0 -1
- package/web-ui/build/static/sqf-CIGKolw3.js +0 -1
- package/web-ui/build/static/sqf-Cfp_lC6-.js +0 -1
- package/web-ui/build/static/sql-DHOGwYxe.js +0 -1
- package/web-ui/build/static/sql-QIw1Q2yi.js +0 -1
- package/web-ui/build/static/sql_more-C0b3-InT.js +0 -1
- package/web-ui/build/static/squirrel-DASToo1F.js +0 -1
- package/web-ui/build/static/stan-DHMkcFZg.js +0 -1
- package/web-ui/build/static/stan-No3nsdnQ.js +0 -1
- package/web-ui/build/static/stata-Brkzu5Nv.js +0 -1
- package/web-ui/build/static/step21-D2l5M5Ml.js +0 -1
- package/web-ui/build/static/stylus-Bx6FaZN_.js +0 -1
- package/web-ui/build/static/stylus-CVkTaPns.js +0 -1
- package/web-ui/build/static/subunit-CDrsAMuL.js +0 -1
- package/web-ui/build/static/swift-BSw_pS-l.js +0 -1
- package/web-ui/build/static/swift-BWyqwIo8.js +0 -1
- package/web-ui/build/static/systemd-BwqpYcJK.js +0 -1
- package/web-ui/build/static/t4-cs-CwsJLOxV.js +0 -1
- package/web-ui/build/static/t4-templating-BfxY01xf.js +0 -1
- package/web-ui/build/static/t4-vb-BhsKKFhp.js +0 -1
- package/web-ui/build/static/taggerscript-Bkew95or.js +0 -1
- package/web-ui/build/static/tap-DHovcHbS.js +0 -1
- package/web-ui/build/static/tap-DPl9uPo4.js +0 -1
- package/web-ui/build/static/tcl-BeozHO-f.js +0 -1
- package/web-ui/build/static/tcl-Df_8ItQH.js +0 -1
- package/web-ui/build/static/textile-B3m_f58b.js +0 -1
- package/web-ui/build/static/thrift-D20n-HpW.js +0 -1
- package/web-ui/build/static/toml-C-fTAonK.js +0 -1
- package/web-ui/build/static/tp-hGbXe5Eo.js +0 -1
- package/web-ui/build/static/tremor-BaVOtRFz.js +0 -1
- package/web-ui/build/static/tsx-ChPInNl0.js +0 -1
- package/web-ui/build/static/tt2-DAIJ8cpz.js +0 -1
- package/web-ui/build/static/turtle-B7z_y-PK.js +0 -1
- package/web-ui/build/static/twig-TUEkve6W.js +0 -1
- package/web-ui/build/static/twig-stKDItz7.js +0 -1
- package/web-ui/build/static/typescript-BPdM-QOM.js +0 -1
- package/web-ui/build/static/typescript-DjSY4MvL.js +0 -1
- package/web-ui/build/static/typoscript-BQHgQtEL.js +0 -1
- package/web-ui/build/static/unrealscript-g8yNPQQ5.js +0 -1
- package/web-ui/build/static/uorazor-CnuMiQz9.js +0 -1
- package/web-ui/build/static/uri-CfioiemU.js +0 -1
- package/web-ui/build/static/v-B69Oau14.js +0 -1
- package/web-ui/build/static/vala-C0PjlK3l.js +0 -1
- package/web-ui/build/static/vala-COgjD3gU.js +0 -1
- package/web-ui/build/static/vbnet-CklOnyuR.js +0 -1
- package/web-ui/build/static/vbnet-MxHUC5Mz.js +0 -1
- package/web-ui/build/static/vbscript-BxQnA97w.js +0 -1
- package/web-ui/build/static/vbscript-html-DOtde7dD.js +0 -1
- package/web-ui/build/static/velocity-l8B9m66X.js +0 -1
- package/web-ui/build/static/verilog-DF6dF-Vp.js +0 -1
- package/web-ui/build/static/verilog-Dgb9SDRX.js +0 -1
- package/web-ui/build/static/vhdl-0GarU_AK.js +0 -1
- package/web-ui/build/static/vhdl-BfPQnOdI.js +0 -1
- package/web-ui/build/static/vim-Likg_-II.js +0 -1
- package/web-ui/build/static/vim-k53Sj7A3.js +0 -1
- package/web-ui/build/static/visual-basic-BNVZCzlV.js +0 -1
- package/web-ui/build/static/warpscript-BkLK5iuW.js +0 -1
- package/web-ui/build/static/wasm-CQhA1ece.js +0 -1
- package/web-ui/build/static/web-idl-DmNsI0kE.js +0 -1
- package/web-ui/build/static/wiki-B3z4pmra.js +0 -1
- package/web-ui/build/static/wolfram-Dsf21d_g.js +0 -1
- package/web-ui/build/static/wren-BZXZlzrL.js +0 -1
- package/web-ui/build/static/x86asm-DpWGZhJU.js +0 -1
- package/web-ui/build/static/xeora-8xPZN4DH.js +0 -1
- package/web-ui/build/static/xl-XkdWYMGl.js +0 -1
- package/web-ui/build/static/xml-BBdROEWt.js +0 -1
- package/web-ui/build/static/xml-doc-Cjs4OpTe.js +0 -1
- package/web-ui/build/static/xojo-nCen1FPx.js +0 -1
- package/web-ui/build/static/xquery-CBFkAxo1.js +0 -1
- package/web-ui/build/static/xquery-Dwsc1weX.js +0 -1
- package/web-ui/build/static/yaml-DzSAh6jl.js +0 -1
- package/web-ui/build/static/yaml-Lg8gnEUU.js +0 -1
- package/web-ui/build/static/yang-Bd-v2b0k.js +0 -1
- package/web-ui/build/static/zephir-wbJOizIa.js +0 -1
- package/web-ui/build/static/zig-Cz384XjE.js +0 -1
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encrypted persistence for `webServer.lastAuthResult`.
|
|
3
|
+
*
|
|
4
|
+
* Purpose:
|
|
5
|
+
* - Survive local-server restarts without losing the OAuth JWT.
|
|
6
|
+
* - Without this, every restart wipes the in-memory auth cache, so
|
|
7
|
+
* the FE polling fallback at `/api/auth/status` returns
|
|
8
|
+
* `{ user: null, jwt: null }` and any frontend that didn't already
|
|
9
|
+
* capture the JWT in its own localStorage (page reload after a
|
|
10
|
+
* server bounce, fresh browser, incognito tab) gets 401s on every
|
|
11
|
+
* marketplace publish/install/rate call.
|
|
12
|
+
*
|
|
13
|
+
* Why encrypted:
|
|
14
|
+
* - The cache row carries a raw JWT — a bearer credential. Storing it
|
|
15
|
+
* in plaintext on disk would let any local process with file-read
|
|
16
|
+
* access impersonate the user against the marketplace service.
|
|
17
|
+
*
|
|
18
|
+
* Storage: `<userDataDir>/settings/auth-cache.enc`. Cipher and key
|
|
19
|
+
* derivation are shared with `apiKeyManager` via
|
|
20
|
+
* `utilities/secretsCipher.js` — DRY by design.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { promises as fs } from 'fs';
|
|
24
|
+
import path from 'path';
|
|
25
|
+
import { getUserDataPaths, ensureUserDataDirs } from '../utilities/userDataDir.js';
|
|
26
|
+
import {
|
|
27
|
+
getOrCreateEncryptionKey,
|
|
28
|
+
encrypt,
|
|
29
|
+
decrypt,
|
|
30
|
+
} from '../utilities/secretsCipher.js';
|
|
31
|
+
|
|
32
|
+
const FILE_NAME = 'auth-cache.enc';
|
|
33
|
+
const SCHEMA_VERSION = 1;
|
|
34
|
+
|
|
35
|
+
class AuthCacheStore {
|
|
36
|
+
constructor(logger) {
|
|
37
|
+
this.logger = logger;
|
|
38
|
+
this.persistenceFile = null;
|
|
39
|
+
this.encryptionKey = null;
|
|
40
|
+
this.initialized = false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Resolve the encrypted file path and derive (or load) the AES key.
|
|
45
|
+
* Idempotent. Failures are non-fatal — the store then behaves as a
|
|
46
|
+
* no-op (load returns null, save silently swallows), so a broken
|
|
47
|
+
* disk doesn't crash the server boot.
|
|
48
|
+
*/
|
|
49
|
+
async initialize() {
|
|
50
|
+
if (this.initialized) return;
|
|
51
|
+
try {
|
|
52
|
+
await ensureUserDataDirs();
|
|
53
|
+
const paths = getUserDataPaths();
|
|
54
|
+
this.persistenceFile = path.join(paths.settings, FILE_NAME);
|
|
55
|
+
this.encryptionKey = await getOrCreateEncryptionKey(paths.settings, this.logger);
|
|
56
|
+
this.initialized = true;
|
|
57
|
+
this.logger?.info?.('[AuthCacheStore] Initialized');
|
|
58
|
+
} catch (error) {
|
|
59
|
+
this.logger?.warn?.('[AuthCacheStore] init failed, running in memory-only mode', {
|
|
60
|
+
error: error.message,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Load and decrypt the persisted cache row.
|
|
67
|
+
* Returns null when the file is missing, corrupted, schema-mismatched,
|
|
68
|
+
* or the store failed to initialize. Never throws.
|
|
69
|
+
*
|
|
70
|
+
* @returns {Promise<Object|null>} the `lastAuthResult`-shaped object
|
|
71
|
+
* ({ user, hasApiKey, jwt, timestamp }) or null.
|
|
72
|
+
*/
|
|
73
|
+
async load() {
|
|
74
|
+
if (!this.initialized) return null;
|
|
75
|
+
try {
|
|
76
|
+
const ciphertext = await fs.readFile(this.persistenceFile, 'utf8');
|
|
77
|
+
const decoded = decrypt(ciphertext, this.encryptionKey);
|
|
78
|
+
const data = JSON.parse(decoded);
|
|
79
|
+
if (data?.version !== SCHEMA_VERSION || !data.cache) {
|
|
80
|
+
this.logger?.warn?.('[AuthCacheStore] schema mismatch, ignoring on-disk cache', {
|
|
81
|
+
version: data?.version,
|
|
82
|
+
});
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return data.cache;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (error.code !== 'ENOENT') {
|
|
88
|
+
this.logger?.warn?.('[AuthCacheStore] load failed', { error: error.message });
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Persist a cache row. Passing null clears the file (delegate to
|
|
96
|
+
* clear() for clarity; this is a convenience for the webServer
|
|
97
|
+
* call site that always wants "make disk match memory").
|
|
98
|
+
*
|
|
99
|
+
* @param {Object|null} cache
|
|
100
|
+
*/
|
|
101
|
+
async save(cache) {
|
|
102
|
+
if (!this.initialized) return;
|
|
103
|
+
if (cache === null || cache === undefined) {
|
|
104
|
+
await this.clear();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const payload = {
|
|
109
|
+
version: SCHEMA_VERSION,
|
|
110
|
+
savedAt: new Date().toISOString(),
|
|
111
|
+
cache,
|
|
112
|
+
};
|
|
113
|
+
const ciphertext = encrypt(JSON.stringify(payload), this.encryptionKey);
|
|
114
|
+
await fs.writeFile(this.persistenceFile, ciphertext, { mode: 0o600 });
|
|
115
|
+
this.logger?.debug?.('[AuthCacheStore] saved', {
|
|
116
|
+
hasUser: !!cache.user,
|
|
117
|
+
hasJwt: !!cache.jwt,
|
|
118
|
+
});
|
|
119
|
+
} catch (error) {
|
|
120
|
+
this.logger?.warn?.('[AuthCacheStore] save failed', { error: error.message });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Delete the on-disk cache. No-op when the file is already absent.
|
|
126
|
+
*/
|
|
127
|
+
async clear() {
|
|
128
|
+
if (!this.initialized) return;
|
|
129
|
+
try {
|
|
130
|
+
await fs.unlink(this.persistenceFile);
|
|
131
|
+
this.logger?.info?.('[AuthCacheStore] cleared');
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (error.code !== 'ENOENT') {
|
|
134
|
+
this.logger?.warn?.('[AuthCacheStore] clear failed', { error: error.message });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export default AuthCacheStore;
|
|
@@ -12,7 +12,15 @@
|
|
|
12
12
|
* Run with: npm run test:e2e
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { describe, test, expect, beforeAll, afterAll } from '@jest/globals';
|
|
15
|
+
import { describe, test, expect, beforeAll, afterAll, jest } from '@jest/globals';
|
|
16
|
+
|
|
17
|
+
// Real-network tests against example.com / iana.org are inherently
|
|
18
|
+
// flaky on TCP / DNS / target-server hiccups. The contract under test
|
|
19
|
+
// is "the WebTool chain machinery works", not "example.com is always
|
|
20
|
+
// up", so we tolerate up to 2 retries before declaring failure.
|
|
21
|
+
// If a test fails 3 times in a row, that's a real signal worth
|
|
22
|
+
// investigating; transient flakes get absorbed silently.
|
|
23
|
+
jest.retryTimes(2, { logErrorsBeforeRetry: true });
|
|
16
24
|
import os from 'os';
|
|
17
25
|
import fs from 'fs';
|
|
18
26
|
|
package/src/tools/webTool.js
CHANGED
|
@@ -1193,14 +1193,30 @@ If blocked (CAPTCHA, access denied), use stealthLevel: "maximum" (visible browse
|
|
|
1193
1193
|
const fetchStatus = fetchResponse ? fetchResponse.status() : null;
|
|
1194
1194
|
|
|
1195
1195
|
if (fetchStatus && fetchStatus >= 400) {
|
|
1196
|
+
// A page that returned 4xx/5xx did NOT give the agent what it
|
|
1197
|
+
// asked for. We used to return `success: true` here on the
|
|
1198
|
+
// theory that "the fetch itself executed"; downstream agents
|
|
1199
|
+
// then ignored the warning and treated the error page as
|
|
1200
|
+
// content. Switching to `success: false` matches the rest of
|
|
1201
|
+
// the tool contract (operation either achieved its purpose
|
|
1202
|
+
// or it didn't) AND surfaces the diagnostic via the standard
|
|
1203
|
+
// `error` field that callers already inspect.
|
|
1204
|
+
const reason =
|
|
1205
|
+
fetchStatus >= 500 ? 'server error' :
|
|
1206
|
+
fetchStatus === 404 ? 'page not found' :
|
|
1207
|
+
fetchStatus === 403 ? 'access forbidden' :
|
|
1208
|
+
fetchStatus === 401 ? 'authentication required' :
|
|
1209
|
+
'client error';
|
|
1196
1210
|
const errorResult = {
|
|
1197
|
-
success:
|
|
1211
|
+
success: false,
|
|
1198
1212
|
url,
|
|
1199
1213
|
httpStatus: fetchStatus,
|
|
1200
|
-
|
|
1201
|
-
|
|
1214
|
+
error: `HTTP ${fetchStatus}: ${reason}`,
|
|
1215
|
+
diagnostic: `Page returned HTTP ${fetchStatus} (${reason})`,
|
|
1216
|
+
warning: `HTTP ${fetchStatus} — the page loaded but returned an error status. Content may still be available.`,
|
|
1202
1217
|
};
|
|
1203
|
-
// Still try to get title for context
|
|
1218
|
+
// Still try to get title for context — error pages often have
|
|
1219
|
+
// useful titles like "404 - Not Found".
|
|
1204
1220
|
try { errorResult.title = await page.title(); } catch {}
|
|
1205
1221
|
// Don't close page here — finally block handles it
|
|
1206
1222
|
return errorResult;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the shared cipher primitives used by both
|
|
3
|
+
* `services/apiKeyManager.js` (api-keys.enc) and
|
|
4
|
+
* `services/authCacheStore.js` (auth-cache.enc).
|
|
5
|
+
*
|
|
6
|
+
* Covers:
|
|
7
|
+
* - key derivation: persistence across calls, identity vs different salts
|
|
8
|
+
* - round-trip: encrypt then decrypt returns the original
|
|
9
|
+
* - constants stability: KEY_DERIVATION_DOMAIN is part of the on-disk
|
|
10
|
+
* contract and must not change without a migration
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
|
|
14
|
+
import { promises as fs } from 'fs';
|
|
15
|
+
import path from 'path';
|
|
16
|
+
import os from 'os';
|
|
17
|
+
import crypto from 'crypto';
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
encrypt,
|
|
21
|
+
decrypt,
|
|
22
|
+
getOrCreateEncryptionKey,
|
|
23
|
+
KEY_DERIVATION_DOMAIN,
|
|
24
|
+
SALT_FILENAME,
|
|
25
|
+
SALT_LENGTH,
|
|
26
|
+
KEY_LENGTH,
|
|
27
|
+
} from '../secretsCipher.js';
|
|
28
|
+
|
|
29
|
+
const tmpDir = path.join(os.tmpdir(), 'secretsCipher-test-' + crypto.randomBytes(6).toString('hex'));
|
|
30
|
+
|
|
31
|
+
beforeEach(async () => { await fs.mkdir(tmpDir, { recursive: true }); });
|
|
32
|
+
afterEach(async () => { try { await fs.rm(tmpDir, { recursive: true, force: true }); } catch { /* ok */ } });
|
|
33
|
+
|
|
34
|
+
describe('secretsCipher', () => {
|
|
35
|
+
test('KEY_DERIVATION_DOMAIN is the documented value — changing this invalidates all stored credentials', () => {
|
|
36
|
+
// Tripwire: this constant is part of the on-disk contract.
|
|
37
|
+
// If you intentionally need to rotate it, also write a migration.
|
|
38
|
+
expect(KEY_DERIVATION_DOMAIN).toBe('loxia-api-key-encryption-v1');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('getOrCreateEncryptionKey creates a salt file on first call', async () => {
|
|
42
|
+
await getOrCreateEncryptionKey(tmpDir, null);
|
|
43
|
+
const saltFile = path.join(tmpDir, SALT_FILENAME);
|
|
44
|
+
const buf = await fs.readFile(saltFile);
|
|
45
|
+
expect(buf.length).toBe(SALT_LENGTH);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('getOrCreateEncryptionKey reuses the existing salt on subsequent calls', async () => {
|
|
49
|
+
const key1 = await getOrCreateEncryptionKey(tmpDir, null);
|
|
50
|
+
const key2 = await getOrCreateEncryptionKey(tmpDir, null);
|
|
51
|
+
expect(key1.equals(key2)).toBe(true);
|
|
52
|
+
expect(key1.length).toBe(KEY_LENGTH);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('different salt directories yield different keys', async () => {
|
|
56
|
+
const dirA = path.join(tmpDir, 'a');
|
|
57
|
+
const dirB = path.join(tmpDir, 'b');
|
|
58
|
+
await fs.mkdir(dirA); await fs.mkdir(dirB);
|
|
59
|
+
const keyA = await getOrCreateEncryptionKey(dirA, null);
|
|
60
|
+
const keyB = await getOrCreateEncryptionKey(dirB, null);
|
|
61
|
+
expect(keyA.equals(keyB)).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('encrypt then decrypt round-trips the plaintext', async () => {
|
|
65
|
+
const key = await getOrCreateEncryptionKey(tmpDir, null);
|
|
66
|
+
const plaintext = JSON.stringify({ jwt: 'eyJ.test.jwt', user: { id: 'u-1' } });
|
|
67
|
+
const ct = encrypt(plaintext, key);
|
|
68
|
+
expect(typeof ct).toBe('string');
|
|
69
|
+
expect(ct).not.toContain('eyJ'); // not plaintext
|
|
70
|
+
expect(decrypt(ct, key)).toBe(plaintext);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('encrypt produces different ciphertext each call (random IV)', async () => {
|
|
74
|
+
const key = await getOrCreateEncryptionKey(tmpDir, null);
|
|
75
|
+
const ct1 = encrypt('same', key);
|
|
76
|
+
const ct2 = encrypt('same', key);
|
|
77
|
+
expect(ct1).not.toBe(ct2);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('decrypt throws with a clear message when no key supplied', () => {
|
|
81
|
+
expect(() => decrypt('anything', null)).toThrow('Encryption key not initialized');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('encrypt throws with a clear message when no key supplied', () => {
|
|
85
|
+
expect(() => encrypt('anything', null)).toThrow('Encryption key not initialized');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('decrypt fails on tampered ciphertext (GCM authTag check)', async () => {
|
|
89
|
+
const key = await getOrCreateEncryptionKey(tmpDir, null);
|
|
90
|
+
const ct = encrypt('payload', key);
|
|
91
|
+
// Flip a byte in the middle of the buffer
|
|
92
|
+
const buf = Buffer.from(ct, 'base64');
|
|
93
|
+
buf[Math.floor(buf.length / 2)] ^= 0xff;
|
|
94
|
+
const tampered = buf.toString('base64');
|
|
95
|
+
expect(() => decrypt(tampered, key)).toThrow();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for src/utilities/updateNotifier.js — the CLI banner wrapper.
|
|
3
|
+
*
|
|
4
|
+
* The helper has four kill-switch paths and two normal paths. We
|
|
5
|
+
* test each so a regression doesn't either spam users or silently
|
|
6
|
+
* stop checking.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, test, expect, jest } from '@jest/globals';
|
|
10
|
+
import {
|
|
11
|
+
runUpdateCheck,
|
|
12
|
+
isUpdateCheckDisabled,
|
|
13
|
+
loadPackageJson,
|
|
14
|
+
} from '../updateNotifier.js';
|
|
15
|
+
|
|
16
|
+
describe('isUpdateCheckDisabled', () => {
|
|
17
|
+
test('returns false on an empty env', () => {
|
|
18
|
+
expect(isUpdateCheckDisabled({})).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('honors LOXIA_DISABLE_UPDATE_CHECK', () => {
|
|
22
|
+
expect(isUpdateCheckDisabled({ LOXIA_DISABLE_UPDATE_CHECK: '1' })).toBe(true);
|
|
23
|
+
expect(isUpdateCheckDisabled({ LOXIA_DISABLE_UPDATE_CHECK: 'true' })).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('honors NO_UPDATE_NOTIFIER (package convention)', () => {
|
|
27
|
+
expect(isUpdateCheckDisabled({ NO_UPDATE_NOTIFIER: '1' })).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('honors CI=true (avoids banner in pipelines)', () => {
|
|
31
|
+
expect(isUpdateCheckDisabled({ CI: 'true' })).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('treats "0" and "false" as not-disabled (escape hatch for misuse)', () => {
|
|
35
|
+
expect(isUpdateCheckDisabled({ LOXIA_DISABLE_UPDATE_CHECK: '0' })).toBe(false);
|
|
36
|
+
expect(isUpdateCheckDisabled({ LOXIA_DISABLE_UPDATE_CHECK: 'false' })).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('loadPackageJson', () => {
|
|
41
|
+
test('finds the CLI package.json by walking up from a starting dir', () => {
|
|
42
|
+
// The helper looks for a pkg.json with `bin` OR `@loxia-labs/` name —
|
|
43
|
+
// both true of this repo's root pkg.json.
|
|
44
|
+
const pkg = loadPackageJson();
|
|
45
|
+
expect(pkg).not.toBeNull();
|
|
46
|
+
expect(pkg.name).toMatch(/loxia/i);
|
|
47
|
+
expect(typeof pkg.version).toBe('string');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('returns null when no qualifying package.json exists in the chain', () => {
|
|
51
|
+
// Inject a stub that always returns ENOENT.
|
|
52
|
+
const fs = {
|
|
53
|
+
readFileSync: () => { throw Object.assign(new Error('nope'), { code: 'ENOENT' }); },
|
|
54
|
+
};
|
|
55
|
+
expect(loadPackageJson({ startDir: '/tmp', fs })).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('runUpdateCheck — kill-switches', () => {
|
|
60
|
+
test('returns null when disabled by env', async () => {
|
|
61
|
+
const importImpl = jest.fn();
|
|
62
|
+
const r = await runUpdateCheck({
|
|
63
|
+
env: { LOXIA_DISABLE_UPDATE_CHECK: '1' },
|
|
64
|
+
pkg: { name: 'x', version: '1.0.0' },
|
|
65
|
+
importImpl,
|
|
66
|
+
});
|
|
67
|
+
expect(r).toBeNull();
|
|
68
|
+
expect(importImpl).not.toHaveBeenCalled();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('returns null when pkg.json could not be loaded', async () => {
|
|
72
|
+
const importImpl = jest.fn();
|
|
73
|
+
const r = await runUpdateCheck({
|
|
74
|
+
env: {},
|
|
75
|
+
pkg: null,
|
|
76
|
+
importImpl,
|
|
77
|
+
});
|
|
78
|
+
expect(r).toBeNull();
|
|
79
|
+
expect(importImpl).not.toHaveBeenCalled();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('runUpdateCheck — dependency tolerance', () => {
|
|
84
|
+
test('returns null when update-notifier is not installed', async () => {
|
|
85
|
+
const importImpl = jest.fn().mockRejectedValue(new Error('Cannot find module'));
|
|
86
|
+
const r = await runUpdateCheck({
|
|
87
|
+
env: {},
|
|
88
|
+
pkg: { name: 'x', version: '1.0.0' },
|
|
89
|
+
importImpl,
|
|
90
|
+
});
|
|
91
|
+
expect(r).toBeNull();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('returns null when the module exists but has the wrong shape', async () => {
|
|
95
|
+
const importImpl = jest.fn().mockResolvedValue({ /* no default, no callable */ });
|
|
96
|
+
const r = await runUpdateCheck({
|
|
97
|
+
env: {},
|
|
98
|
+
pkg: { name: 'x', version: '1.0.0' },
|
|
99
|
+
importImpl,
|
|
100
|
+
});
|
|
101
|
+
expect(r).toBeNull();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('runUpdateCheck — happy path', () => {
|
|
106
|
+
test('invokes update-notifier with the supplied pkg and calls notify()', async () => {
|
|
107
|
+
const notifyMock = jest.fn();
|
|
108
|
+
const updateNotifierFn = jest.fn().mockReturnValue({ notify: notifyMock });
|
|
109
|
+
const importImpl = jest.fn().mockResolvedValue({ default: updateNotifierFn });
|
|
110
|
+
|
|
111
|
+
const pkg = { name: '@loxia-labs/loxia-autopilot-one', version: '4.6.4' };
|
|
112
|
+
const result = await runUpdateCheck({ env: {}, pkg, importImpl });
|
|
113
|
+
|
|
114
|
+
expect(result).toEqual({ notify: notifyMock });
|
|
115
|
+
expect(updateNotifierFn).toHaveBeenCalledTimes(1);
|
|
116
|
+
const call = updateNotifierFn.mock.calls[0][0];
|
|
117
|
+
expect(call.pkg).toBe(pkg);
|
|
118
|
+
expect(typeof call.updateCheckInterval).toBe('number');
|
|
119
|
+
expect(notifyMock).toHaveBeenCalledTimes(1);
|
|
120
|
+
|
|
121
|
+
const notifyOpts = notifyMock.mock.calls[0][0];
|
|
122
|
+
expect(notifyOpts.isGlobal).toBe(true);
|
|
123
|
+
expect(notifyOpts.message).toContain('{packageName}');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('a throwing notifier does not surface — returns null', async () => {
|
|
127
|
+
const updateNotifierFn = jest.fn().mockImplementation(() => { throw new Error('boom'); });
|
|
128
|
+
const importImpl = jest.fn().mockResolvedValue({ default: updateNotifierFn });
|
|
129
|
+
const logger = { debug: jest.fn() };
|
|
130
|
+
const r = await runUpdateCheck({
|
|
131
|
+
env: {},
|
|
132
|
+
pkg: { name: 'x', version: '1.0.0' },
|
|
133
|
+
importImpl,
|
|
134
|
+
logger,
|
|
135
|
+
});
|
|
136
|
+
expect(r).toBeNull();
|
|
137
|
+
expect(logger.debug).toHaveBeenCalled();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared encryption primitives for at-rest credential storage.
|
|
3
|
+
*
|
|
4
|
+
* Used by:
|
|
5
|
+
* - services/apiKeyManager.js (api-keys.enc)
|
|
6
|
+
* - services/authCacheStore.js (auth-cache.enc)
|
|
7
|
+
*
|
|
8
|
+
* Both stores derive the same machine-specific AES-256-GCM key from a
|
|
9
|
+
* persistent salt at `<userDataDir>/.key-salt` plus os-derived data.
|
|
10
|
+
* Sharing the cipher primitives keeps the byte layout consistent and
|
|
11
|
+
* means a single review covers credential-at-rest for the whole app.
|
|
12
|
+
*
|
|
13
|
+
* On-disk format (per ciphertext, base64-encoded):
|
|
14
|
+
* [ IV (16B) | authTag (16B) | ciphertext (variable) ]
|
|
15
|
+
*
|
|
16
|
+
* KEY_DERIVATION_DOMAIN must stay constant — changing it invalidates
|
|
17
|
+
* every existing `api-keys.enc` on every user's machine.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import crypto from 'crypto';
|
|
21
|
+
import os from 'os';
|
|
22
|
+
import path from 'path';
|
|
23
|
+
import { promises as fs } from 'fs';
|
|
24
|
+
|
|
25
|
+
export const ALGORITHM = 'aes-256-gcm';
|
|
26
|
+
export const KEY_LENGTH = 32; // 256 bits
|
|
27
|
+
export const IV_LENGTH = 16;
|
|
28
|
+
export const AUTH_TAG_LENGTH = 16;
|
|
29
|
+
export const SALT_LENGTH = 32;
|
|
30
|
+
export const PBKDF2_ITERATIONS = 100000;
|
|
31
|
+
export const SALT_FILENAME = '.key-salt';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Domain-separation string mixed into the key derivation input. Must
|
|
35
|
+
* not change without a migration — existing on-disk files would
|
|
36
|
+
* become undecryptable.
|
|
37
|
+
*/
|
|
38
|
+
export const KEY_DERIVATION_DOMAIN = 'loxia-api-key-encryption-v1';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Read or create the per-machine salt and derive the AES key from it
|
|
42
|
+
* combined with stable machine identifiers.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} settingsDir - directory holding `.key-salt`
|
|
45
|
+
* @param {Object} [logger]
|
|
46
|
+
* @returns {Promise<Buffer>} 32-byte AES key
|
|
47
|
+
*/
|
|
48
|
+
export async function getOrCreateEncryptionKey(settingsDir, logger) {
|
|
49
|
+
const saltFile = path.join(settingsDir, SALT_FILENAME);
|
|
50
|
+
let salt;
|
|
51
|
+
try {
|
|
52
|
+
salt = await fs.readFile(saltFile);
|
|
53
|
+
} catch {
|
|
54
|
+
salt = crypto.randomBytes(SALT_LENGTH);
|
|
55
|
+
await fs.writeFile(saltFile, salt, { mode: 0o600 });
|
|
56
|
+
logger?.info?.('[secretsCipher] Generated new encryption salt');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const machineData = [
|
|
60
|
+
os.hostname(),
|
|
61
|
+
os.homedir(),
|
|
62
|
+
os.userInfo().username,
|
|
63
|
+
process.platform,
|
|
64
|
+
KEY_DERIVATION_DOMAIN,
|
|
65
|
+
].join(':');
|
|
66
|
+
|
|
67
|
+
return crypto.pbkdf2Sync(machineData, salt, PBKDF2_ITERATIONS, KEY_LENGTH, 'sha256');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Encrypt a UTF-8 plaintext to a base64 string carrying IV+authTag.
|
|
72
|
+
*
|
|
73
|
+
* @param {string} plaintext
|
|
74
|
+
* @param {Buffer} encryptionKey
|
|
75
|
+
* @returns {string} base64
|
|
76
|
+
*/
|
|
77
|
+
export function encrypt(plaintext, encryptionKey) {
|
|
78
|
+
if (!encryptionKey) throw new Error('Encryption key not initialized');
|
|
79
|
+
|
|
80
|
+
const iv = crypto.randomBytes(IV_LENGTH);
|
|
81
|
+
const cipher = crypto.createCipheriv(ALGORITHM, encryptionKey, iv);
|
|
82
|
+
|
|
83
|
+
let encrypted = cipher.update(plaintext, 'utf8', 'base64');
|
|
84
|
+
encrypted += cipher.final('base64');
|
|
85
|
+
|
|
86
|
+
const authTag = cipher.getAuthTag();
|
|
87
|
+
const combined = Buffer.concat([
|
|
88
|
+
iv,
|
|
89
|
+
authTag,
|
|
90
|
+
Buffer.from(encrypted, 'base64'),
|
|
91
|
+
]);
|
|
92
|
+
return combined.toString('base64');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Decrypt a base64 IV+authTag+ciphertext blob back to UTF-8.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} encryptedData base64
|
|
99
|
+
* @param {Buffer} encryptionKey
|
|
100
|
+
* @returns {string} plaintext
|
|
101
|
+
*/
|
|
102
|
+
export function decrypt(encryptedData, encryptionKey) {
|
|
103
|
+
if (!encryptionKey) throw new Error('Encryption key not initialized');
|
|
104
|
+
|
|
105
|
+
const combined = Buffer.from(encryptedData, 'base64');
|
|
106
|
+
const iv = combined.subarray(0, IV_LENGTH);
|
|
107
|
+
const authTag = combined.subarray(IV_LENGTH, IV_LENGTH + AUTH_TAG_LENGTH);
|
|
108
|
+
const encrypted = combined.subarray(IV_LENGTH + AUTH_TAG_LENGTH);
|
|
109
|
+
|
|
110
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, encryptionKey, iv);
|
|
111
|
+
decipher.setAuthTag(authTag);
|
|
112
|
+
|
|
113
|
+
let decrypted = decipher.update(encrypted.toString('base64'), 'base64', 'utf8');
|
|
114
|
+
decrypted += decipher.final('utf8');
|
|
115
|
+
return decrypted;
|
|
116
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* npm CLI update notifier — thin wrapper around `update-notifier`.
|
|
3
|
+
*
|
|
4
|
+
* Shows a non-blocking banner on CLI startup when a newer version of
|
|
5
|
+
* the published package is available on the npm registry. User stays
|
|
6
|
+
* in control: the CLI never auto-installs anything.
|
|
7
|
+
*
|
|
8
|
+
* Brand awareness:
|
|
9
|
+
* The CLI ships under two brand-specific package names
|
|
10
|
+
* (`@loxia-labs/loxia-autopilot-one`, `@loxia-labs/loxia-onbuzz`).
|
|
11
|
+
* `update-notifier` reads the package name from the runtime
|
|
12
|
+
* package.json so each brand's notifier checks the right registry
|
|
13
|
+
* entry automatically.
|
|
14
|
+
*
|
|
15
|
+
* Kill-switch:
|
|
16
|
+
* - LOXIA_DISABLE_UPDATE_CHECK=1 — our env var (preferred)
|
|
17
|
+
* - NO_UPDATE_NOTIFIER=1 — package's own opt-out
|
|
18
|
+
* - CI=true — most CIs set this; we honour it
|
|
19
|
+
*
|
|
20
|
+
* Dependency tolerance:
|
|
21
|
+
* `update-notifier` is dynamically imported. If the package isn't
|
|
22
|
+
* installed (e.g. dev tree without `npm install`), the function is
|
|
23
|
+
* a silent no-op — the CLI MUST still boot.
|
|
24
|
+
*
|
|
25
|
+
* Network tolerance:
|
|
26
|
+
* The check is a background fetch with cached result. We never await
|
|
27
|
+
* the network — `update-notifier` schedules a child-process fetch
|
|
28
|
+
* and writes the result to ~/.config/configstore for the NEXT run.
|
|
29
|
+
* That means: the FIRST time a user is offline, no banner. Subsequent
|
|
30
|
+
* runs use the cached version-comparison until the next check window.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { readFileSync } from 'fs';
|
|
34
|
+
import { dirname, join } from 'path';
|
|
35
|
+
import { fileURLToPath } from 'url';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Env vars that disable the check. All are case-sensitive string
|
|
39
|
+
* comparisons against `'1'` / `'true'` to match common conventions.
|
|
40
|
+
*/
|
|
41
|
+
const DISABLE_ENVS = Object.freeze([
|
|
42
|
+
'LOXIA_DISABLE_UPDATE_CHECK',
|
|
43
|
+
'NO_UPDATE_NOTIFIER',
|
|
44
|
+
'CI', // standard CI marker
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
/** How often update-notifier should re-check the npm registry. */
|
|
48
|
+
const UPDATE_CHECK_INTERVAL_MS = 1000 * 60 * 60 * 24; // 24h
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @returns {boolean} true if any kill-switch env is set truthy.
|
|
52
|
+
*/
|
|
53
|
+
export function isUpdateCheckDisabled(env = process.env) {
|
|
54
|
+
for (const key of DISABLE_ENVS) {
|
|
55
|
+
const v = env[key];
|
|
56
|
+
if (v && v !== '0' && v.toLowerCase() !== 'false') return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Load the package.json this CLI is running from (the installed one,
|
|
63
|
+
* not the one in src/utilities of a dev tree). Returned object always
|
|
64
|
+
* has at least `name` and `version`.
|
|
65
|
+
*
|
|
66
|
+
* @returns {{ name: string, version: string } | null}
|
|
67
|
+
*/
|
|
68
|
+
export function loadPackageJson({
|
|
69
|
+
startDir = dirname(fileURLToPath(import.meta.url)),
|
|
70
|
+
fs = { readFileSync },
|
|
71
|
+
} = {}) {
|
|
72
|
+
// Walk up from this file looking for package.json with a `bin`
|
|
73
|
+
// entry — that's the published CLI package, not a nested dep.
|
|
74
|
+
let dir = startDir;
|
|
75
|
+
const ROOT_LIMIT = 8;
|
|
76
|
+
for (let i = 0; i < ROOT_LIMIT; i++) {
|
|
77
|
+
try {
|
|
78
|
+
const raw = fs.readFileSync(join(dir, 'package.json'), 'utf8');
|
|
79
|
+
const pkg = JSON.parse(raw);
|
|
80
|
+
if (pkg.bin || pkg.name?.startsWith('@loxia-labs/')) {
|
|
81
|
+
return { name: pkg.name, version: pkg.version };
|
|
82
|
+
}
|
|
83
|
+
} catch { /* keep walking */ }
|
|
84
|
+
const parent = dirname(dir);
|
|
85
|
+
if (parent === dir) break;
|
|
86
|
+
dir = parent;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Run the update check and (if a newer version is on the registry)
|
|
93
|
+
* print a banner. Never throws. Never blocks. Safe to call exactly
|
|
94
|
+
* once at CLI entry.
|
|
95
|
+
*
|
|
96
|
+
* Returns the underlying notifier instance for tests, or null when
|
|
97
|
+
* disabled / package missing / pkg.json unreadable.
|
|
98
|
+
*/
|
|
99
|
+
export async function runUpdateCheck({
|
|
100
|
+
env = process.env,
|
|
101
|
+
pkg = loadPackageJson(),
|
|
102
|
+
importImpl = (specifier) => import(specifier),
|
|
103
|
+
logger = console,
|
|
104
|
+
} = {}) {
|
|
105
|
+
if (isUpdateCheckDisabled(env)) return null;
|
|
106
|
+
if (!pkg) return null;
|
|
107
|
+
|
|
108
|
+
let mod;
|
|
109
|
+
try {
|
|
110
|
+
mod = await importImpl('update-notifier');
|
|
111
|
+
} catch {
|
|
112
|
+
// Package not installed in this tree. Silent no-op.
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const updateNotifier = mod.default || mod;
|
|
117
|
+
if (typeof updateNotifier !== 'function') return null;
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const notifier = updateNotifier({
|
|
121
|
+
pkg,
|
|
122
|
+
updateCheckInterval: UPDATE_CHECK_INTERVAL_MS,
|
|
123
|
+
shouldNotifyInNpmScript: false,
|
|
124
|
+
});
|
|
125
|
+
// notify() is itself a no-op when there's no update; safe to call
|
|
126
|
+
// unconditionally.
|
|
127
|
+
notifier.notify?.({
|
|
128
|
+
defer: false, // print before the CLI does its work
|
|
129
|
+
isGlobal: true, // CLI ships as a global binary
|
|
130
|
+
message:
|
|
131
|
+
`Update available {currentVersion} → {latestVersion}\n` +
|
|
132
|
+
`Run \`npm i -g {packageName}\` to update.`,
|
|
133
|
+
});
|
|
134
|
+
return notifier;
|
|
135
|
+
} catch (err) {
|
|
136
|
+
// Any failure (network, configstore write, etc.) is non-fatal.
|
|
137
|
+
logger?.debug?.('[updateNotifier] check skipped:', err.message);
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|