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,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account & API-key management routes on the local CLI server.
|
|
3
|
+
*
|
|
4
|
+
* These are thin proxies over the autopilot-backend's `/auth/*` and
|
|
5
|
+
* `/account/*` endpoints. The local server holds the user's JWT in
|
|
6
|
+
* `lastAuthResult.jwt` (encrypted on disk via authCacheStore) and
|
|
7
|
+
* forwards it as a `Authorization: Bearer` to the backend. The web-ui
|
|
8
|
+
* never sees the JWT after the initial OAuth landing — keeping it on
|
|
9
|
+
* the local-server side means:
|
|
10
|
+
*
|
|
11
|
+
* 1. No CORS dance between the browser and Azure backend.
|
|
12
|
+
* 2. The web-ui can talk to one origin (its own).
|
|
13
|
+
* 3. A compromised renderer cannot exfiltrate the bearer in plaintext
|
|
14
|
+
* (it lives in localStorage, but everything that NEEDS it goes
|
|
15
|
+
* through the local server).
|
|
16
|
+
* 4. Symmetric with the existing marketplaceApi pattern.
|
|
17
|
+
*
|
|
18
|
+
* Endpoints (mounted by webServer.js at boot):
|
|
19
|
+
* GET /api/account/profile — proxies /auth/me
|
|
20
|
+
* GET /api/account/balance — proxies /account/balance (ledger)
|
|
21
|
+
* GET /api/account/keys — proxies /auth/apikeys
|
|
22
|
+
* POST /api/account/keys — proxies /auth/apikey (one-time-reveal body)
|
|
23
|
+
* DELETE /api/account/keys/:id — proxies /auth/apikey/:id
|
|
24
|
+
* POST /api/account/handoff — mints + returns a portal handoff URL
|
|
25
|
+
*
|
|
26
|
+
* Auth: each route requires `lastAuthResult.jwt` to be present. When
|
|
27
|
+
* the user hasn't OAuth'd yet, we return 401 with a clear `code` the
|
|
28
|
+
* FE can branch on ('not_signed_in') so it can prompt for sign-in
|
|
29
|
+
* rather than show a generic error.
|
|
30
|
+
*
|
|
31
|
+
* Security guarantees:
|
|
32
|
+
* - The local server never returns the JWT to the renderer.
|
|
33
|
+
* - The API-key create endpoint returns the `lx_*` value exactly
|
|
34
|
+
* once (mirroring the backend); subsequent list calls show only
|
|
35
|
+
* metadata + a masked key.
|
|
36
|
+
* - The handoff URL embeds a single-use short-lived token, NOT the
|
|
37
|
+
* long-lived JWT.
|
|
38
|
+
* - All errors are normalised to `{ success: false, error, code? }`
|
|
39
|
+
* so the FE never has to special-case axios vs fetch envelopes.
|
|
40
|
+
*
|
|
41
|
+
* Testable design:
|
|
42
|
+
* `createAccountRouter()` accepts every dependency it needs (fetch
|
|
43
|
+
* impl, backend URL, JWT getter, logger). Production builds inject
|
|
44
|
+
* the real ones; tests inject stubs. See accountRoutes.test.js.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
import express from 'express';
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Default backend URL — overridable via the same `config.backend.baseUrl`
|
|
51
|
+
* the existing /auth routes use, so a single env-config change moves
|
|
52
|
+
* every backend call to staging or local-dev.
|
|
53
|
+
*/
|
|
54
|
+
const DEFAULT_BACKEND_URL = 'https://autopilot-api.azurewebsites.net';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Portal URL per brand. The handoff endpoint uses this to construct
|
|
58
|
+
* the deep-link the FE opens in the system browser. Two reasons we
|
|
59
|
+
* pick the brand at construction time, not request time:
|
|
60
|
+
* - The local server already knows its brand (loaded at boot).
|
|
61
|
+
* - The renderer should never get to influence which portal we send
|
|
62
|
+
* the user to (mitigation against open-redirect via a tampered
|
|
63
|
+
* request body).
|
|
64
|
+
*/
|
|
65
|
+
const PORTAL_URLS_BY_BRAND = Object.freeze({
|
|
66
|
+
autopilot: 'https://autopilot.loxia.ai',
|
|
67
|
+
onbuzz: 'https://onbuzz.loxia.ai',
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Codes the FE branches on. Keep this list in lockstep with web-ui's
|
|
72
|
+
* account API client. New codes must be added to the FE's switch.
|
|
73
|
+
*/
|
|
74
|
+
export const ERROR_CODES = Object.freeze({
|
|
75
|
+
NOT_SIGNED_IN: 'not_signed_in',
|
|
76
|
+
BACKEND_ERROR: 'backend_error',
|
|
77
|
+
NETWORK_ERROR: 'network_error',
|
|
78
|
+
BAD_REQUEST: 'bad_request',
|
|
79
|
+
NOT_FOUND: 'not_found',
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Build the account router. Pure DI — every external concern is a
|
|
84
|
+
* function the caller passes in.
|
|
85
|
+
*
|
|
86
|
+
* @param {Object} deps
|
|
87
|
+
* @param {() => string|null} deps.getJwt
|
|
88
|
+
* Returns the user's current JWT or null when unauthenticated.
|
|
89
|
+
* Caller hooks this to `() => webServer.lastAuthResult?.jwt`.
|
|
90
|
+
* @param {() => string} deps.getBrand
|
|
91
|
+
* Returns 'autopilot' | 'onbuzz'. Used to pick portal URL.
|
|
92
|
+
* @param {string} [deps.backendBaseUrl]
|
|
93
|
+
* @param {typeof fetch} [deps.fetchImpl]
|
|
94
|
+
* @param {Object} [deps.logger]
|
|
95
|
+
*/
|
|
96
|
+
export function createAccountRouter({
|
|
97
|
+
getJwt,
|
|
98
|
+
getBrand,
|
|
99
|
+
backendBaseUrl = DEFAULT_BACKEND_URL,
|
|
100
|
+
fetchImpl = fetch,
|
|
101
|
+
logger = console,
|
|
102
|
+
} = {}) {
|
|
103
|
+
if (typeof getJwt !== 'function') throw new Error('createAccountRouter: getJwt is required');
|
|
104
|
+
if (typeof getBrand !== 'function') throw new Error('createAccountRouter: getBrand is required');
|
|
105
|
+
|
|
106
|
+
const router = express.Router();
|
|
107
|
+
const baseUrl = backendBaseUrl.replace(/\/$/, '');
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Forward a request to the backend with the user's JWT. Returns a
|
|
111
|
+
* { status, body } tuple the route handlers can hand straight back
|
|
112
|
+
* to Express, normalising every transport failure into the same
|
|
113
|
+
* envelope.
|
|
114
|
+
*/
|
|
115
|
+
async function proxyToBackend(method, path, body) {
|
|
116
|
+
const jwt = getJwt();
|
|
117
|
+
if (!jwt) {
|
|
118
|
+
return {
|
|
119
|
+
status: 401,
|
|
120
|
+
body: { success: false, error: 'Sign in to manage your account', code: ERROR_CODES.NOT_SIGNED_IN },
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const url = `${baseUrl}${path}`;
|
|
124
|
+
try {
|
|
125
|
+
const res = await fetchImpl(url, {
|
|
126
|
+
method,
|
|
127
|
+
headers: {
|
|
128
|
+
'Authorization': `Bearer ${jwt}`,
|
|
129
|
+
'Content-Type': 'application/json',
|
|
130
|
+
},
|
|
131
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const text = await res.text();
|
|
135
|
+
let parsed;
|
|
136
|
+
try { parsed = text ? JSON.parse(text) : {}; } catch { parsed = { raw: text }; }
|
|
137
|
+
|
|
138
|
+
if (!res.ok) {
|
|
139
|
+
return {
|
|
140
|
+
status: res.status,
|
|
141
|
+
body: {
|
|
142
|
+
success: false,
|
|
143
|
+
error: parsed.error || parsed.message || `Backend returned ${res.status}`,
|
|
144
|
+
code: res.status === 404 ? ERROR_CODES.NOT_FOUND : ERROR_CODES.BACKEND_ERROR,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return { status: res.status, body: parsed };
|
|
149
|
+
} catch (err) {
|
|
150
|
+
logger?.warn?.('[accountRoutes] backend fetch failed', { method, path, error: err.message });
|
|
151
|
+
return {
|
|
152
|
+
status: 503,
|
|
153
|
+
body: {
|
|
154
|
+
success: false,
|
|
155
|
+
error: 'Could not reach the account service. Try again in a moment.',
|
|
156
|
+
code: ERROR_CODES.NETWORK_ERROR,
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ── Profile ────────────────────────────────────────────────────────
|
|
163
|
+
router.get('/profile', async (_req, res) => {
|
|
164
|
+
const r = await proxyToBackend('GET', '/auth/me');
|
|
165
|
+
// /auth/me returns either `{ user: {...} }` or `{...userFields}`.
|
|
166
|
+
// Normalise so the FE always sees `{ user: {...} }`.
|
|
167
|
+
if (r.status === 200) {
|
|
168
|
+
const u = r.body?.user || r.body;
|
|
169
|
+
return res.json({ success: true, user: u });
|
|
170
|
+
}
|
|
171
|
+
res.status(r.status).json(r.body);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// ── Balance ────────────────────────────────────────────────────────
|
|
175
|
+
router.get('/balance', async (_req, res) => {
|
|
176
|
+
// The backend exposes a balance read at /account/profile (which
|
|
177
|
+
// bundles plan + balance) — see autopilot-backend/routes/account.js.
|
|
178
|
+
// Calling this single endpoint instead of /ledger/balance keeps the
|
|
179
|
+
// local server free of ledger credentials.
|
|
180
|
+
const r = await proxyToBackend('GET', '/account/profile');
|
|
181
|
+
res.status(r.status).json(r.body);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// ── API keys list ──────────────────────────────────────────────────
|
|
185
|
+
router.get('/keys', async (_req, res) => {
|
|
186
|
+
const r = await proxyToBackend('GET', '/auth/apikeys');
|
|
187
|
+
res.status(r.status).json(r.body);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// ── API key create ────────────────────────────────────────────────
|
|
191
|
+
router.post('/keys', express.json(), async (req, res) => {
|
|
192
|
+
const { name, expiresIn } = req.body || {};
|
|
193
|
+
if (!name || typeof name !== 'string' || !name.trim()) {
|
|
194
|
+
return res.status(400).json({
|
|
195
|
+
success: false,
|
|
196
|
+
error: 'Provide a name to identify the key',
|
|
197
|
+
code: ERROR_CODES.BAD_REQUEST,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
const payload = { name: name.trim() };
|
|
201
|
+
if (expiresIn != null) payload.expiresIn = expiresIn;
|
|
202
|
+
const r = await proxyToBackend('POST', '/auth/apikey', payload);
|
|
203
|
+
res.status(r.status).json(r.body);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// ── API key revoke ────────────────────────────────────────────────
|
|
207
|
+
router.delete('/keys/:id', async (req, res) => {
|
|
208
|
+
const id = req.params.id;
|
|
209
|
+
if (!id || !/^[a-zA-Z0-9_-]+$/.test(id)) {
|
|
210
|
+
return res.status(400).json({
|
|
211
|
+
success: false,
|
|
212
|
+
error: 'Invalid key id',
|
|
213
|
+
code: ERROR_CODES.BAD_REQUEST,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
const r = await proxyToBackend('DELETE', `/auth/apikey/${encodeURIComponent(id)}`);
|
|
217
|
+
res.status(r.status).json(r.body);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// ── Portal handoff (Buy Credits) ──────────────────────────────────
|
|
221
|
+
router.post('/handoff', async (req, res) => {
|
|
222
|
+
const { destination } = req.body || {};
|
|
223
|
+
// Closed allowlist — never let the renderer drive arbitrary portal
|
|
224
|
+
// paths. New destinations must be added here intentionally.
|
|
225
|
+
const ALLOWED_DESTINATIONS = ['payment', 'subscription', 'api-keys', 'account'];
|
|
226
|
+
const path = destination && ALLOWED_DESTINATIONS.includes(destination) ? destination : 'payment';
|
|
227
|
+
|
|
228
|
+
const r = await proxyToBackend('POST', '/auth/handoff-token', { purpose: `portal-${path}` });
|
|
229
|
+
if (r.status !== 200 && r.status !== 201) {
|
|
230
|
+
return res.status(r.status).json(r.body);
|
|
231
|
+
}
|
|
232
|
+
const handoff = r.body?.handoff || r.body?.token;
|
|
233
|
+
if (!handoff) {
|
|
234
|
+
return res.status(502).json({
|
|
235
|
+
success: false,
|
|
236
|
+
error: 'Backend did not return a handoff token',
|
|
237
|
+
code: ERROR_CODES.BACKEND_ERROR,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
const brand = getBrand();
|
|
241
|
+
const portalBase = PORTAL_URLS_BY_BRAND[brand] || PORTAL_URLS_BY_BRAND.autopilot;
|
|
242
|
+
const url = `${portalBase}/${path}?handoff=${encodeURIComponent(handoff)}`;
|
|
243
|
+
res.json({ success: true, url });
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
return router;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Exported so tests + future routes can re-use it.
|
|
250
|
+
export const __test__ = { PORTAL_URLS_BY_BRAND, DEFAULT_BACKEND_URL };
|
|
@@ -33,6 +33,9 @@ import { getGalleryService } from '../services/galleryService.js';
|
|
|
33
33
|
import { getUserDataPaths } from '../utilities/userDataDir.js';
|
|
34
34
|
import { projectActiveRuns } from '../utilities/flowRunFilters.js';
|
|
35
35
|
import { recordOAuthResult, recordResolvedUser, projectAuthStatus } from '../utilities/authCache.js';
|
|
36
|
+
import AuthCacheStore from '../services/authCacheStore.js';
|
|
37
|
+
import { createAccountRouter } from './accountRoutes.js';
|
|
38
|
+
import { getBrand } from '../utilities/brand.js';
|
|
36
39
|
|
|
37
40
|
// Connect visual editor server to bridge (enables element selection forwarding)
|
|
38
41
|
setBridgeGetter(getVisualEditorBridge);
|
|
@@ -419,8 +422,15 @@ class WebServer {
|
|
|
419
422
|
// API Key Manager reference (will be set by LoxiaSystem)
|
|
420
423
|
this.apiKeyManager = null;
|
|
421
424
|
|
|
422
|
-
// Cached auth result for polling support (set by /auth/callback, cleared by /auth/signout)
|
|
423
|
-
|
|
425
|
+
// Cached auth result for polling support (set by /auth/callback, cleared by /auth/signout).
|
|
426
|
+
// Shape: { user, hasApiKey, jwt, timestamp }. The JWT is the critical
|
|
427
|
+
// field for marketplace publish/install/rate calls — see authCache.js.
|
|
428
|
+
// Persisted encrypted to <userDataDir>/settings/auth-cache.enc via
|
|
429
|
+
// `authCacheStore` so a server restart no longer wipes the JWT.
|
|
430
|
+
// Use `_setLastAuthResult(value)` rather than assigning directly so
|
|
431
|
+
// every mutation hits disk too.
|
|
432
|
+
this.lastAuthResult = null;
|
|
433
|
+
this.authCacheStore = new AuthCacheStore(this.logger);
|
|
424
434
|
|
|
425
435
|
// Credential Vault for secure credential management
|
|
426
436
|
this.credentialVault = null;
|
|
@@ -447,6 +457,20 @@ class WebServer {
|
|
|
447
457
|
*/
|
|
448
458
|
async initialize() {
|
|
449
459
|
try {
|
|
460
|
+
// Restore the persisted auth cache (JWT + user) so a server restart
|
|
461
|
+
// doesn't strand the FE without a token. Best-effort: a missing or
|
|
462
|
+
// corrupted file just leaves `lastAuthResult` at null.
|
|
463
|
+
await this.authCacheStore.initialize();
|
|
464
|
+
const restored = await this.authCacheStore.load();
|
|
465
|
+
if (restored) {
|
|
466
|
+
this.lastAuthResult = restored;
|
|
467
|
+
this.logger?.info?.('[WebServer] Restored auth cache from disk', {
|
|
468
|
+
hasUser: !!restored.user,
|
|
469
|
+
hasJwt: !!restored.jwt,
|
|
470
|
+
savedAt: restored.timestamp,
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
|
|
450
474
|
this.setupMiddleware();
|
|
451
475
|
await this.setupRoutes();
|
|
452
476
|
this.setupWebSocket();
|
|
@@ -462,7 +486,7 @@ class WebServer {
|
|
|
462
486
|
// In remote session mode, auto-configure API key from environment
|
|
463
487
|
if (process.env.LOXIA_REMOTE_SESSION === 'true' && process.env.LOXIA_API_KEY && this.apiKeyManager) {
|
|
464
488
|
try {
|
|
465
|
-
await this.apiKeyManager.
|
|
489
|
+
await this.apiKeyManager.setSessionKeys(null, { loxiaApiKey: process.env.LOXIA_API_KEY });
|
|
466
490
|
this.logger.info('Remote session: API key auto-configured from environment');
|
|
467
491
|
} catch (err) {
|
|
468
492
|
this.logger.warn('Remote session: Failed to set API key from environment', { error: err.message });
|
|
@@ -485,6 +509,22 @@ class WebServer {
|
|
|
485
509
|
}
|
|
486
510
|
}
|
|
487
511
|
|
|
512
|
+
/**
|
|
513
|
+
* Single mutator for `lastAuthResult`. Always writes to disk so a
|
|
514
|
+
* server restart can restore the JWT. Passing null clears both
|
|
515
|
+
* memory and disk. Every call site that previously assigned to
|
|
516
|
+
* `this.lastAuthResult` directly should go through this helper.
|
|
517
|
+
* @param {Object|null} value
|
|
518
|
+
* @returns {Promise<void>}
|
|
519
|
+
*/
|
|
520
|
+
async _setLastAuthResult(value) {
|
|
521
|
+
this.lastAuthResult = value || null;
|
|
522
|
+
// Fire-and-forget would be tempting but it lets a fast-following
|
|
523
|
+
// /api/auth/status read race the write. Awaiting is cheap: one
|
|
524
|
+
// ~200B AES-GCM write to a local file.
|
|
525
|
+
await this.authCacheStore.save(this.lastAuthResult);
|
|
526
|
+
}
|
|
527
|
+
|
|
488
528
|
/**
|
|
489
529
|
* Start the Visual Editor Server (always-on mode)
|
|
490
530
|
* Server runs on port 4000 (or configured port) and waits for agent connections
|
|
@@ -859,7 +899,7 @@ class WebServer {
|
|
|
859
899
|
|
|
860
900
|
// Store the API key if generated
|
|
861
901
|
if (apiKey && this.apiKeyManager) {
|
|
862
|
-
await this.apiKeyManager.
|
|
902
|
+
await this.apiKeyManager.setSessionKeys(null, { loxiaApiKey: apiKey });
|
|
863
903
|
this.logger?.info('API key auto-configured from OAuth login', { userId: userInfo.id });
|
|
864
904
|
}
|
|
865
905
|
|
|
@@ -870,11 +910,11 @@ class WebServer {
|
|
|
870
910
|
// marketplace publish/install/rate calls would 401 because the
|
|
871
911
|
// FE never got the token into localStorage. Logic lives in
|
|
872
912
|
// `utilities/authCache.js` so unit tests can lock the contract.
|
|
873
|
-
this.
|
|
913
|
+
await this._setLastAuthResult(recordOAuthResult({
|
|
874
914
|
user: userInfo,
|
|
875
915
|
jwt: token,
|
|
876
916
|
hasApiKey: !!apiKey,
|
|
877
|
-
});
|
|
917
|
+
}));
|
|
878
918
|
|
|
879
919
|
// Broadcast auth success to connected web UI clients
|
|
880
920
|
// Include the raw JWT so the frontend can use it for marketplace API calls
|
|
@@ -945,10 +985,10 @@ h2{color:#16a34a;margin-bottom:.5rem;} p{color:#666;}</style></head>
|
|
|
945
985
|
// Preserves any JWT from a prior OAuth login (this path mints
|
|
946
986
|
// no JWT of its own — it just links a user from an existing
|
|
947
987
|
// API key). See utilities/authCache.js for the invariant.
|
|
948
|
-
this.
|
|
988
|
+
await this._setLastAuthResult(recordResolvedUser({
|
|
949
989
|
user,
|
|
950
990
|
prevCache: this.lastAuthResult,
|
|
951
|
-
});
|
|
991
|
+
}));
|
|
952
992
|
|
|
953
993
|
res.json({ success: true, user });
|
|
954
994
|
} catch (error) {
|
|
@@ -961,9 +1001,9 @@ h2{color:#16a34a;margin-bottom:.5rem;} p{color:#666;}</style></head>
|
|
|
961
1001
|
this.app.post('/api/auth/signout', async (req, res) => {
|
|
962
1002
|
try {
|
|
963
1003
|
if (this.apiKeyManager) {
|
|
964
|
-
await this.apiKeyManager.
|
|
1004
|
+
await this.apiKeyManager.removeSessionKeys(null);
|
|
965
1005
|
}
|
|
966
|
-
this.
|
|
1006
|
+
await this._setLastAuthResult(null);
|
|
967
1007
|
this.broadcastToSession(null, {
|
|
968
1008
|
type: 'auth_signout',
|
|
969
1009
|
data: { timestamp: new Date().toISOString() }
|
|
@@ -974,6 +1014,19 @@ h2{color:#16a34a;margin-bottom:.5rem;} p{color:#666;}</style></head>
|
|
|
974
1014
|
}
|
|
975
1015
|
});
|
|
976
1016
|
|
|
1017
|
+
// =====================================================
|
|
1018
|
+
// Account & API-key management (proxied to autopilot-backend).
|
|
1019
|
+
// Defined in `interfaces/accountRoutes.js`; mounted here so the FE
|
|
1020
|
+
// can hit /api/account/{profile,balance,keys,handoff} without ever
|
|
1021
|
+
// touching the user's JWT directly.
|
|
1022
|
+
// =====================================================
|
|
1023
|
+
this.app.use('/api/account', createAccountRouter({
|
|
1024
|
+
getJwt: () => this.lastAuthResult?.jwt || null,
|
|
1025
|
+
getBrand: () => getBrand().isOnBuzz ? 'onbuzz' : 'autopilot',
|
|
1026
|
+
backendBaseUrl: this.config?.backend?.baseUrl,
|
|
1027
|
+
logger: this.logger,
|
|
1028
|
+
}));
|
|
1029
|
+
|
|
977
1030
|
// =====================================================
|
|
978
1031
|
// System Update API
|
|
979
1032
|
// =====================================================
|
|
@@ -85,12 +85,10 @@ describe('ApiKeyManager', () => {
|
|
|
85
85
|
expect(logger.warn).toHaveBeenCalled();
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
expect(id).toContain('loxia-api-key-encryption-v1');
|
|
93
|
-
});
|
|
88
|
+
// _getMachineIdentifier moved to `utilities/secretsCipher.js` as part
|
|
89
|
+
// of the DRY refactor sharing the cipher with `services/authCacheStore.js`.
|
|
90
|
+
// The equivalent coverage now lives in
|
|
91
|
+
// `src/utilities/__tests__/secretsCipher.test.js`.
|
|
94
92
|
|
|
95
93
|
test('_encrypt throws when no encryption key', () => {
|
|
96
94
|
expect(() => manager._encrypt('test')).toThrow('Encryption key not initialized');
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Round-trip + failure-mode tests for `services/authCacheStore.js`.
|
|
3
|
+
*
|
|
4
|
+
* The store is the disk half of the marketplace-publish fix: without
|
|
5
|
+
* it, a server restart wipes the JWT cache and the FE's polling
|
|
6
|
+
* fallback gets `{ user: null, jwt: null }` so any browser without the
|
|
7
|
+
* token already in localStorage 401s on publish.
|
|
8
|
+
*
|
|
9
|
+
* These tests exercise the real cipher against a tmp directory by
|
|
10
|
+
* pointing `getUserDataPaths` at it via the harness below.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, test, expect, beforeEach, afterEach, jest } 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
|
+
// Mock userDataDir BEFORE importing the store so the dynamic import
|
|
20
|
+
// below picks up the mock. Each test resets the tmpdir.
|
|
21
|
+
const tmpRoot = path.join(os.tmpdir(), 'authCacheStore-test-' + crypto.randomBytes(6).toString('hex'));
|
|
22
|
+
|
|
23
|
+
jest.unstable_mockModule('../../utilities/userDataDir.js', () => ({
|
|
24
|
+
getUserDataPaths: () => ({ settings: tmpRoot }),
|
|
25
|
+
ensureUserDataDirs: async () => { await fs.mkdir(tmpRoot, { recursive: true }); },
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
const { default: AuthCacheStore } = await import('../authCacheStore.js');
|
|
29
|
+
|
|
30
|
+
const SAMPLE_CACHE = Object.freeze({
|
|
31
|
+
user: { id: 'u-1', email: 'a@b.com' },
|
|
32
|
+
hasApiKey: true,
|
|
33
|
+
jwt: 'eyJ.test.jwt',
|
|
34
|
+
timestamp: '2026-05-11T12:00:00.000Z',
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
async function cleanTmp() {
|
|
38
|
+
try { await fs.rm(tmpRoot, { recursive: true, force: true }); } catch { /* ok */ }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('AuthCacheStore', () => {
|
|
42
|
+
beforeEach(async () => { await cleanTmp(); });
|
|
43
|
+
afterEach(async () => { await cleanTmp(); });
|
|
44
|
+
|
|
45
|
+
test('load returns null when uninitialized (no init() call yet)', async () => {
|
|
46
|
+
const store = new AuthCacheStore(null);
|
|
47
|
+
expect(await store.load()).toBeNull();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('load returns null when file does not exist', async () => {
|
|
51
|
+
const store = new AuthCacheStore(null);
|
|
52
|
+
await store.initialize();
|
|
53
|
+
expect(await store.load()).toBeNull();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('save then load returns the same row', async () => {
|
|
57
|
+
const store = new AuthCacheStore(null);
|
|
58
|
+
await store.initialize();
|
|
59
|
+
await store.save(SAMPLE_CACHE);
|
|
60
|
+
const loaded = await store.load();
|
|
61
|
+
expect(loaded).toEqual(SAMPLE_CACHE);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('save(null) deletes the file', async () => {
|
|
65
|
+
const store = new AuthCacheStore(null);
|
|
66
|
+
await store.initialize();
|
|
67
|
+
await store.save(SAMPLE_CACHE);
|
|
68
|
+
const filePath = path.join(tmpRoot, 'auth-cache.enc');
|
|
69
|
+
await fs.access(filePath); // exists
|
|
70
|
+
await store.save(null);
|
|
71
|
+
await expect(fs.access(filePath)).rejects.toThrow();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('clear() is a no-op when file does not exist', async () => {
|
|
75
|
+
const store = new AuthCacheStore(null);
|
|
76
|
+
await store.initialize();
|
|
77
|
+
await expect(store.clear()).resolves.toBeUndefined();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('two store instances on the same machine share the key — second can read what first wrote', async () => {
|
|
81
|
+
// This is the actual production scenario: restart spawns a fresh
|
|
82
|
+
// AuthCacheStore that must decrypt what the previous instance saved.
|
|
83
|
+
const writer = new AuthCacheStore(null);
|
|
84
|
+
await writer.initialize();
|
|
85
|
+
await writer.save(SAMPLE_CACHE);
|
|
86
|
+
|
|
87
|
+
const reader = new AuthCacheStore(null);
|
|
88
|
+
await reader.initialize();
|
|
89
|
+
expect(await reader.load()).toEqual(SAMPLE_CACHE);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('load returns null on corrupted ciphertext', async () => {
|
|
93
|
+
const store = new AuthCacheStore(null);
|
|
94
|
+
await store.initialize();
|
|
95
|
+
await fs.writeFile(path.join(tmpRoot, 'auth-cache.enc'), 'this-is-not-valid-base64-ciphertext!!');
|
|
96
|
+
expect(await store.load()).toBeNull();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('load returns null on schema-version mismatch', async () => {
|
|
100
|
+
const store = new AuthCacheStore(null);
|
|
101
|
+
await store.initialize();
|
|
102
|
+
// Hand-craft a valid ciphertext with the wrong version.
|
|
103
|
+
const { encrypt } = await import('../../utilities/secretsCipher.js');
|
|
104
|
+
const payload = JSON.stringify({ version: 999, cache: SAMPLE_CACHE });
|
|
105
|
+
const ct = encrypt(payload, store.encryptionKey);
|
|
106
|
+
await fs.writeFile(path.join(tmpRoot, 'auth-cache.enc'), ct);
|
|
107
|
+
expect(await store.load()).toBeNull();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('save survives ENOENT on directory creation between init and save (best-effort)', async () => {
|
|
111
|
+
// Edge case: someone deletes the settings dir mid-flight. save()
|
|
112
|
+
// should warn but not throw, so the request handler can finish.
|
|
113
|
+
const store = new AuthCacheStore(null);
|
|
114
|
+
await store.initialize();
|
|
115
|
+
await fs.rm(tmpRoot, { recursive: true, force: true });
|
|
116
|
+
await expect(store.save(SAMPLE_CACHE)).resolves.toBeUndefined();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -14,18 +14,13 @@
|
|
|
14
14
|
|
|
15
15
|
import { promises as fs } from 'fs';
|
|
16
16
|
import path from 'path';
|
|
17
|
-
import crypto from 'crypto';
|
|
18
|
-
import os from 'os';
|
|
19
17
|
import { getUserDataPaths, ensureUserDataDirs } from '../utilities/userDataDir.js';
|
|
20
18
|
import { isPlaceholderApiKey } from '../utilities/apiKeyPlaceholders.js';
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const AUTH_TAG_LENGTH = 16;
|
|
27
|
-
const SALT_LENGTH = 32;
|
|
28
|
-
const PBKDF2_ITERATIONS = 100000;
|
|
19
|
+
import {
|
|
20
|
+
getOrCreateEncryptionKey as _getOrCreateEncryptionKey,
|
|
21
|
+
encrypt as _cipherEncrypt,
|
|
22
|
+
decrypt as _cipherDecrypt,
|
|
23
|
+
} from '../utilities/secretsCipher.js';
|
|
29
24
|
|
|
30
25
|
class ApiKeyManager {
|
|
31
26
|
constructor(logger) {
|
|
@@ -73,103 +68,21 @@ class ApiKeyManager {
|
|
|
73
68
|
}
|
|
74
69
|
|
|
75
70
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
71
|
+
* Cipher primitives delegate to `utilities/secretsCipher.js` so the
|
|
72
|
+
* api-keys.enc and auth-cache.enc stores share one implementation
|
|
73
|
+
* and one byte layout. See that module for the on-disk format and
|
|
74
|
+
* the KEY_DERIVATION_DOMAIN constant.
|
|
79
75
|
*/
|
|
80
76
|
async _getOrCreateEncryptionKey(settingsDir) {
|
|
81
|
-
|
|
82
|
-
let salt;
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
salt = await fs.readFile(saltFile);
|
|
86
|
-
} catch (error) {
|
|
87
|
-
// Generate new salt
|
|
88
|
-
salt = crypto.randomBytes(SALT_LENGTH);
|
|
89
|
-
await fs.writeFile(saltFile, salt, { mode: 0o600 });
|
|
90
|
-
this.logger?.info('[ApiKeyManager] Generated new encryption salt');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Derive key from salt + machine-specific data
|
|
94
|
-
const machineData = this._getMachineIdentifier();
|
|
95
|
-
const key = crypto.pbkdf2Sync(
|
|
96
|
-
machineData,
|
|
97
|
-
salt,
|
|
98
|
-
PBKDF2_ITERATIONS,
|
|
99
|
-
KEY_LENGTH,
|
|
100
|
-
'sha256'
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
return key;
|
|
77
|
+
return _getOrCreateEncryptionKey(settingsDir, this.logger);
|
|
104
78
|
}
|
|
105
79
|
|
|
106
|
-
/**
|
|
107
|
-
* Get a machine-specific identifier for key derivation
|
|
108
|
-
* @returns {string}
|
|
109
|
-
*/
|
|
110
|
-
_getMachineIdentifier() {
|
|
111
|
-
const parts = [
|
|
112
|
-
os.hostname(),
|
|
113
|
-
os.homedir(),
|
|
114
|
-
os.userInfo().username,
|
|
115
|
-
process.platform,
|
|
116
|
-
'loxia-api-key-encryption-v1'
|
|
117
|
-
];
|
|
118
|
-
return parts.join(':');
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Encrypt data using AES-256-GCM
|
|
123
|
-
* @param {string} plaintext - Data to encrypt
|
|
124
|
-
* @returns {string} Encrypted data as base64
|
|
125
|
-
*/
|
|
126
80
|
_encrypt(plaintext) {
|
|
127
|
-
|
|
128
|
-
throw new Error('Encryption key not initialized');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const iv = crypto.randomBytes(IV_LENGTH);
|
|
132
|
-
const cipher = crypto.createCipheriv(ALGORITHM, this.encryptionKey, iv);
|
|
133
|
-
|
|
134
|
-
let encrypted = cipher.update(plaintext, 'utf8', 'base64');
|
|
135
|
-
encrypted += cipher.final('base64');
|
|
136
|
-
|
|
137
|
-
const authTag = cipher.getAuthTag();
|
|
138
|
-
|
|
139
|
-
// Combine IV + authTag + encrypted data
|
|
140
|
-
const combined = Buffer.concat([
|
|
141
|
-
iv,
|
|
142
|
-
authTag,
|
|
143
|
-
Buffer.from(encrypted, 'base64')
|
|
144
|
-
]);
|
|
145
|
-
|
|
146
|
-
return combined.toString('base64');
|
|
81
|
+
return _cipherEncrypt(plaintext, this.encryptionKey);
|
|
147
82
|
}
|
|
148
83
|
|
|
149
|
-
/**
|
|
150
|
-
* Decrypt data using AES-256-GCM
|
|
151
|
-
* @param {string} encryptedData - Encrypted data as base64
|
|
152
|
-
* @returns {string} Decrypted plaintext
|
|
153
|
-
*/
|
|
154
84
|
_decrypt(encryptedData) {
|
|
155
|
-
|
|
156
|
-
throw new Error('Encryption key not initialized');
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const combined = Buffer.from(encryptedData, 'base64');
|
|
160
|
-
|
|
161
|
-
// Extract IV, authTag, and encrypted data
|
|
162
|
-
const iv = combined.subarray(0, IV_LENGTH);
|
|
163
|
-
const authTag = combined.subarray(IV_LENGTH, IV_LENGTH + AUTH_TAG_LENGTH);
|
|
164
|
-
const encrypted = combined.subarray(IV_LENGTH + AUTH_TAG_LENGTH);
|
|
165
|
-
|
|
166
|
-
const decipher = crypto.createDecipheriv(ALGORITHM, this.encryptionKey, iv);
|
|
167
|
-
decipher.setAuthTag(authTag);
|
|
168
|
-
|
|
169
|
-
let decrypted = decipher.update(encrypted.toString('base64'), 'base64', 'utf8');
|
|
170
|
-
decrypted += decipher.final('utf8');
|
|
171
|
-
|
|
172
|
-
return decrypted;
|
|
85
|
+
return _cipherDecrypt(encryptedData, this.encryptionKey);
|
|
173
86
|
}
|
|
174
87
|
|
|
175
88
|
/**
|