@cmmd-center/forge 0.9.3 → 0.9.5
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/dist/{BunHttpServer-Dc5XijQF.mjs → BunHttpServer-BgNCpQzV.mjs} +2 -2
- package/dist/{BunHttpServer-Cuya1Zon.cjs → BunHttpServer-DOAuw4Iq.cjs} +2 -2
- package/dist/{BunPTY-z9OKvyBo.cjs → BunPTY-2icf7sRj.cjs} +2 -2
- package/dist/{BunPTY-CfS5zDoQ.mjs → BunPTY-D-Klry5N.mjs} +2 -2
- package/dist/{BunServices-eq_c-3x1.mjs → BunServices-ChM4mYH9.mjs} +1 -1
- package/dist/{BunServices-khEuvPaA.cjs → BunServices-CiNXNzHD.cjs} +1 -1
- package/dist/Mime-BITO-E1U.mjs +1395 -0
- package/dist/Mime-CyHbecis.cjs +1400 -0
- package/dist/{Mime-B75_d9aw.mjs → NodeHttpServer-C_wePPV0.mjs} +614 -1456
- package/dist/{Mime-aSilaQX9.cjs → NodeHttpServer-D_ismXpd.cjs} +617 -1466
- package/dist/{NodePTY-ChjVFpUH.mjs → NodePTY-BMUFdM93.mjs} +2 -2
- package/dist/{NodePTY-BOaJi0JA.cjs → NodePTY-cb7HIasY.cjs} +2 -2
- package/dist/{NodeSqliteClient-GlgGqc8V.mjs → NodeSqliteClient-OdI1TawL.mjs} +1 -1
- package/dist/{NodeSqliteClient-Vunn3aFN.cjs → NodeSqliteClient-SsUCk9mA.cjs} +1 -1
- package/dist/{PTY-rn2kGjhB.mjs → PTY-CBkE5akF.mjs} +1 -1
- package/dist/{PTY-D5OpMK9s.cjs → PTY-U3JQnLXS.cjs} +1 -1
- package/dist/{SqliteClient-Bpkno4Ob.cjs → SqliteClient-CdAhI4lb.cjs} +1 -1
- package/dist/{SqliteClient-DYQAvreq.mjs → SqliteClient-aoOb51gB.mjs} +1 -1
- package/dist/bin.cjs +14484 -10871
- package/dist/bin.mjs +14667 -11052
- package/dist/client/apple-touch-icon.png +0 -0
- package/dist/client/apple-touch-icon.png.publish-bak +0 -0
- package/dist/client/assets/CanvasPanel-BIN3OTEQ.js +441 -0
- package/dist/client/assets/CompositeItem-UKxcvvWv.js +2 -0
- package/dist/client/assets/DiffPanel-CeuRaSj1.js +64 -0
- package/dist/client/assets/DiffPanel.logic-D5i9QswQ.js +21 -0
- package/dist/client/assets/DiffPanelShell-W5nEVL52.js +2531 -0
- package/dist/client/assets/DiffWorkerPoolProvider-D87CO5TY.js +73 -0
- package/dist/client/assets/PullRequestCodePanel-DAmHwtY9.js +5 -0
- package/dist/client/assets/Stream-CToP6xzI.js +15 -0
- package/dist/client/assets/Virtualizer-CnwVHiy3.js +2 -0
- package/dist/client/assets/__vite-browser-external-DkEyUtaV.js +2 -0
- package/dist/client/assets/abap-kWSt4ETq.js +2 -0
- package/dist/client/assets/actionscript-3-DUMfZd56.js +2 -0
- package/dist/client/assets/ada-B5ZVVI6u.js +2 -0
- package/dist/client/assets/andromeeda-DXFdNco6.js +2 -0
- package/dist/client/assets/andromeeda-DwmQuk--.js +2 -0
- package/dist/client/assets/angular-html-BHUTdQ2k.js +2 -0
- package/dist/client/assets/angular-ts-BSGCbJ0j.js +2 -0
- package/dist/client/assets/apache-Cu40O3Ol.js +2 -0
- package/dist/client/assets/apex-DMPEjfSG.js +2 -0
- package/dist/client/assets/apl-BoCi4WkG.js +2 -0
- package/dist/client/assets/applescript-mUd3mpyF.js +2 -0
- package/dist/client/assets/ara-LhQXZmm_.js +2 -0
- package/dist/client/assets/asciidoc-BhTPoeH5.js +2 -0
- package/dist/client/assets/asm-BGGwX2ZL.js +2 -0
- package/dist/client/assets/astro-BMi5lGMm.js +2 -0
- package/dist/client/assets/atomRegistry-Bq5Y4LP1.js +3 -0
- package/dist/client/assets/aurora-x-CLgz8jpO.js +2 -0
- package/dist/client/assets/aurora-x-DY4EgSB_.js +2 -0
- package/dist/client/assets/awk-emAjNmqG.js +2 -0
- package/dist/client/assets/ayu-dark-BOsBaLmt.js +2 -0
- package/dist/client/assets/ayu-dark-Dm87GVDE.js +2 -0
- package/dist/client/assets/ayu-light-CVzS2PQZ.js +2 -0
- package/dist/client/assets/ayu-light-nGNJ-WDB.js +2 -0
- package/dist/client/assets/ayu-mirage-CionIqJ2.js +2 -0
- package/dist/client/assets/ayu-mirage-wUDx3klU.js +2 -0
- package/dist/client/assets/ballerina-Zz4P1PCo.js +2 -0
- package/dist/client/assets/bat-CojohPr3.js +2 -0
- package/dist/client/assets/beancount-DIrDFIbZ.js +2 -0
- package/dist/client/assets/berry-BktKISqk.js +2 -0
- package/dist/client/assets/bibtex-QuZiL8vO.js +2 -0
- package/dist/client/assets/bicep-BBqBjbA3.js +2 -0
- package/dist/client/assets/bird2-FrGIamnO.js +2 -0
- package/dist/client/assets/blade-CUGHtpnt.js +2 -0
- package/dist/client/assets/bsl-Dwz0otKA.js +2 -0
- package/dist/client/assets/c-3r97XxSq.js +2 -0
- package/dist/client/assets/c3-D-fgrOzJ.js +2 -0
- package/dist/client/assets/cadence-53eYIqKQ.js +2 -0
- package/dist/client/assets/cairo-Cai_OBhL.js +2 -0
- package/dist/client/assets/canvasStateStore-D3R1Ldk1.js +2 -0
- package/dist/client/assets/catppuccin-frappe-B9ztfCCY.js +2 -0
- package/dist/client/assets/catppuccin-frappe-Dtq86Zt-.js +2 -0
- package/dist/client/assets/catppuccin-latte-D1lF_ULk.js +2 -0
- package/dist/client/assets/catppuccin-latte-jgmNlGoB.js +2 -0
- package/dist/client/assets/catppuccin-macchiato-CcX-f1yB.js +2 -0
- package/dist/client/assets/catppuccin-macchiato-DfuKQKcK.js +2 -0
- package/dist/client/assets/catppuccin-mocha-B3_lpdvM.js +2 -0
- package/dist/client/assets/catppuccin-mocha-DfNnOvvn.js +2 -0
- package/dist/client/assets/clarity-DCS2DMlE.js +2 -0
- package/dist/client/assets/clojure-XwHeeE37.js +2 -0
- package/dist/client/assets/cmake-VIYk9tbe.js +2 -0
- package/dist/client/assets/cmmdAuthRedirect-DLvl7JNi.js +2 -0
- package/dist/client/assets/cobol-IPhylbE9.js +2 -0
- package/dist/client/assets/codeowners-DiTXAskR.js +2 -0
- package/dist/client/assets/codeql-0208dEuz.js +2 -0
- package/dist/client/assets/coffee-BwGUpF4f.js +2 -0
- package/dist/client/assets/common-lisp-Bbk7xLRF.js +2 -0
- package/dist/client/assets/coq-CDDZdGGh.js +2 -0
- package/dist/client/assets/cpp-jFyTvZsm.js +2 -0
- package/dist/client/assets/crystal-DYkQl9zO.js +2 -0
- package/dist/client/assets/csharp-Dausz59m.js +2 -0
- package/dist/client/assets/css-jXIxCbs3.js +2 -0
- package/dist/client/assets/csv-e2HVQau9.js +2 -0
- package/dist/client/assets/cue-BMgE_xju.js +2 -0
- package/dist/client/assets/cypher-CA95tXqi.js +2 -0
- package/dist/client/assets/d-DeO2qMKQ.js +2 -0
- package/dist/client/assets/dark-plus-DaoBxEuI.js +2 -0
- package/dist/client/assets/dark-plus-hlEOAUn6.js +2 -0
- package/dist/client/assets/dart-_9gbW0uG.js +2 -0
- package/dist/client/assets/dax-BMSB_urL.js +2 -0
- package/dist/client/assets/desktop-CFWOIXtS.js +2 -0
- package/dist/client/assets/diff-K3NAzB5h.js +2 -0
- package/dist/client/assets/docker-BHQx5Ff2.js +2 -0
- package/dist/client/assets/dotenv-CkiqXLC8.js +2 -0
- package/dist/client/assets/dracula-C9rp4fWn.js +2 -0
- package/dist/client/assets/dracula-CIJxKfwh.js +2 -0
- package/dist/client/assets/dracula-soft-BN-taJLQ.js +2 -0
- package/dist/client/assets/dracula-soft-De1wWQ_v.js +2 -0
- package/dist/client/assets/dream-maker-BM-H3AID.js +2 -0
- package/dist/client/assets/edge-CVf1J8H7.js +2 -0
- package/dist/client/assets/elixir-DtWV_YYF.js +2 -0
- package/dist/client/assets/elm-BJC2NMzB.js +2 -0
- package/dist/client/assets/emacs-lisp-BBM_ORbk.js +2 -0
- package/dist/client/assets/erb-cwYn0k3w.js +2 -0
- package/dist/client/assets/erlang-QNS0KA0S.js +2 -0
- package/dist/client/assets/everforest-dark-BSYmfNnp.js +2 -0
- package/dist/client/assets/everforest-dark-DUW3cHBn.js +2 -0
- package/dist/client/assets/everforest-light-CXyS_8Pc.js +2 -0
- package/dist/client/assets/everforest-light-DR-OhbXr.js +2 -0
- package/dist/client/assets/fennel-CAUJGoSU.js +2 -0
- package/dist/client/assets/fish-Cgln2BIC.js +2 -0
- package/dist/client/assets/fluent-BFL910sE.js +2 -0
- package/dist/client/assets/fortran-fixed-form-GNS6k7js.js +2 -0
- package/dist/client/assets/fortran-free-form-DB-siuqX.js +2 -0
- package/dist/client/assets/fsharp-BEjSdIee.js +2 -0
- package/dist/client/assets/gdresource-D24f9BeL.js +2 -0
- package/dist/client/assets/gdscript-Bq5ZYHDh.js +2 -0
- package/dist/client/assets/gdshader-BWxXiThj.js +2 -0
- package/dist/client/assets/genie-BOcsPMcn.js +2 -0
- package/dist/client/assets/gherkin-pSvoetjt.js +2 -0
- package/dist/client/assets/git-commit-Ddcy2Rzd.js +2 -0
- package/dist/client/assets/git-rebase-95AHstHI.js +2 -0
- package/dist/client/assets/github-dark-BbHkogeI.js +2 -0
- package/dist/client/assets/github-dark-D1nTcH4E.js +2 -0
- package/dist/client/assets/github-dark-default-Cgu-j31c.js +2 -0
- package/dist/client/assets/github-dark-default-CwMUtNVn.js +2 -0
- package/dist/client/assets/github-dark-dimmed-BmSK4vhs.js +2 -0
- package/dist/client/assets/github-dark-dimmed-CQVfITf-.js +2 -0
- package/dist/client/assets/github-dark-high-contrast-8_9Rbsic.js +2 -0
- package/dist/client/assets/github-dark-high-contrast-BO-0858k.js +2 -0
- package/dist/client/assets/github-light-DWIA8Fx_.js +2 -0
- package/dist/client/assets/github-light-default-CR0FtjVb.js +2 -0
- package/dist/client/assets/github-light-default-LLPbqR-K.js +2 -0
- package/dist/client/assets/github-light-high-contrast-5o8qRjCb.js +2 -0
- package/dist/client/assets/github-light-high-contrast-C8BCDz6a.js +2 -0
- package/dist/client/assets/github-light-lCcn0xRl.js +2 -0
- package/dist/client/assets/gleam-DPm9Zc9U.js +2 -0
- package/dist/client/assets/glimmer-js-Cjwf-Ijv.js +2 -0
- package/dist/client/assets/glimmer-ts-DXnOWlZf.js +2 -0
- package/dist/client/assets/glsl-iXGbnqIU.js +2 -0
- package/dist/client/assets/gn-DEuV1her.js +2 -0
- package/dist/client/assets/gnuplot-CqGlKjK6.js +2 -0
- package/dist/client/assets/go-mptU-yl2.js +2 -0
- package/dist/client/assets/graphql-DJMVZQv3.js +2 -0
- package/dist/client/assets/groovy-CKg5KWq9.js +2 -0
- package/dist/client/assets/gruvbox-dark-hard-Df4rfbxN.js +2 -0
- package/dist/client/assets/gruvbox-dark-hard-DsK6pQOr.js +2 -0
- package/dist/client/assets/gruvbox-dark-medium-nlSbDtaA.js +2 -0
- package/dist/client/assets/gruvbox-dark-medium-zSmEeDKP.js +2 -0
- package/dist/client/assets/gruvbox-dark-soft-BSW4a3D0.js +2 -0
- package/dist/client/assets/gruvbox-dark-soft-DgI1MxVf.js +2 -0
- package/dist/client/assets/gruvbox-light-hard-D144A6HZ.js +2 -0
- package/dist/client/assets/gruvbox-light-hard-DMNoHzNU.js +2 -0
- package/dist/client/assets/gruvbox-light-medium-C0B0NCuj.js +2 -0
- package/dist/client/assets/gruvbox-light-medium-CY2MDbN0.js +2 -0
- package/dist/client/assets/gruvbox-light-soft-CWJ8aP9f.js +2 -0
- package/dist/client/assets/gruvbox-light-soft-CyPlqRD8.js +2 -0
- package/dist/client/assets/hack-CkGKtoya.js +2 -0
- package/dist/client/assets/haml-mV-E4efJ.js +2 -0
- package/dist/client/assets/handlebars-Da6i86YE.js +2 -0
- package/dist/client/assets/haskell-DFWkJmsd.js +2 -0
- package/dist/client/assets/haxe-DoXg9N2w.js +2 -0
- package/dist/client/assets/hcl-VbcvLW6X.js +2 -0
- package/dist/client/assets/hjson-dQ--SYg9.js +2 -0
- package/dist/client/assets/hlsl-DNh8NDKB.js +2 -0
- package/dist/client/assets/horizon-BeufL1QP.js +2 -0
- package/dist/client/assets/horizon-CnOil3H1.js +2 -0
- package/dist/client/assets/horizon-bright-BoFfNO4u.js +2 -0
- package/dist/client/assets/horizon-bright-CJCE-DcQ.js +2 -0
- package/dist/client/assets/houston-C5_OTP91.js +2 -0
- package/dist/client/assets/houston-jaZUvSzs.js +2 -0
- package/dist/client/assets/html-derivative-BOw7yS3Z.js +2 -0
- package/dist/client/assets/html-e1ppUAVa.js +2 -0
- package/dist/client/assets/html2canvas-C_LL7spC.js +6 -0
- package/dist/client/assets/http-DFrMFVWs.js +2 -0
- package/dist/client/assets/hurl-3N2UscjA.js +2 -0
- package/dist/client/assets/hxml-Ip0yb8dg.js +2 -0
- package/dist/client/assets/hy-Bg-RIaMc.js +2 -0
- package/dist/client/assets/imba-BjZ9NRcj.js +2 -0
- package/dist/client/assets/index-Dr7HwjTE.css +1 -0
- package/dist/client/assets/index-DyEYqQdf.js +151 -0
- package/dist/client/assets/index.es-piUKIQw4.js +6 -0
- package/dist/client/assets/ini-CXagdQO9.js +2 -0
- package/dist/client/assets/java-DY6ZSujp.js +2 -0
- package/dist/client/assets/javascript-BfTuFzbs.js +2 -0
- package/dist/client/assets/jinja-C4NVx4X-.js +2 -0
- package/dist/client/assets/jison-BaE4DrvM.js +2 -0
- package/dist/client/assets/json-LL0kLbs_.js +2 -0
- package/dist/client/assets/json5-B1LcXsA8.js +2 -0
- package/dist/client/assets/jsonc-CYSDka7c.js +2 -0
- package/dist/client/assets/jsonl-CwfwQmvE.js +2 -0
- package/dist/client/assets/jsonnet-DG_zYewp.js +2 -0
- package/dist/client/assets/jspdf.es.min-_OjqfV_L.js +80 -0
- package/dist/client/assets/jssm-IkACsEzj.js +2 -0
- package/dist/client/assets/jsx-BOBg7x46.js +2 -0
- package/dist/client/assets/julia-D5dobu9Y.js +2 -0
- package/dist/client/assets/just-D99ddsWv.js +2 -0
- package/dist/client/assets/kanagawa-dragon-BBUl63AF.js +2 -0
- package/dist/client/assets/kanagawa-dragon-CBGy-6ik.js +2 -0
- package/dist/client/assets/kanagawa-lotus-BKY9TlU3.js +2 -0
- package/dist/client/assets/kanagawa-lotus-D93oLQjR.js +2 -0
- package/dist/client/assets/kanagawa-wave-CWf0rFWt.js +2 -0
- package/dist/client/assets/kanagawa-wave-CZBJ3hQh.js +2 -0
- package/dist/client/assets/kdl-DuytcvNV.js +2 -0
- package/dist/client/assets/kotlin-DmtnKz6Z.js +2 -0
- package/dist/client/assets/kusto-DmrVjfae.js +2 -0
- package/dist/client/assets/laserwave-DTzUwFmi.js +2 -0
- package/dist/client/assets/laserwave-NRABVcaO.js +2 -0
- package/dist/client/assets/latex-0e5rhe9m.js +2 -0
- package/dist/client/assets/lean-Bhkhoed1.js +2 -0
- package/dist/client/assets/less-BgyohKqc.js +2 -0
- package/dist/client/assets/light-plus-Cbc9ZUH4.js +2 -0
- package/dist/client/assets/light-plus-SK-KfMAV.js +2 -0
- package/dist/client/assets/liquid-BR35Xk1k.js +2 -0
- package/dist/client/assets/llvm-BtFJuFOJ.js +2 -0
- package/dist/client/assets/log-Df3M8ERB.js +2 -0
- package/dist/client/assets/logo-VfSEjTs6.js +2 -0
- package/dist/client/assets/lua-BMt4EqAw.js +2 -0
- package/dist/client/assets/luau-DIHOVG2A.js +2 -0
- package/dist/client/assets/make-gTMDFaMm.js +2 -0
- package/dist/client/assets/markdown-B_5il8S2.js +2 -0
- package/dist/client/assets/marko-DN4rLggA.js +2 -0
- package/dist/client/assets/material-theme-Pm6m-Kzc.js +2 -0
- package/dist/client/assets/material-theme-darker-BxFgxa9U.js +2 -0
- package/dist/client/assets/material-theme-darker-pKUQPx9-.js +2 -0
- package/dist/client/assets/material-theme-lighter-BLqni5my.js +2 -0
- package/dist/client/assets/material-theme-lighter-D6-26WhM.js +2 -0
- package/dist/client/assets/material-theme-ocean-C2N-nFlu.js +2 -0
- package/dist/client/assets/material-theme-ocean-DCxzET3l.js +2 -0
- package/dist/client/assets/material-theme-palenight-DyQqRTLL.js +2 -0
- package/dist/client/assets/material-theme-palenight-Y14J3SJp.js +2 -0
- package/dist/client/assets/material-theme-zfTX2d95.js +2 -0
- package/dist/client/assets/matlab-B2zVSjQq.js +2 -0
- package/dist/client/assets/mdc-kokCuEO8.js +2 -0
- package/dist/client/assets/mdx-CL7pLDiG.js +2 -0
- package/dist/client/assets/mermaid-Cou83ohU.js +2 -0
- package/dist/client/assets/min-dark-Bg1kQHvJ.js +2 -0
- package/dist/client/assets/min-dark-BhN4iMRs.js +2 -0
- package/dist/client/assets/min-light-BjU80CRL.js +2 -0
- package/dist/client/assets/min-light-Bw9u-P_u.js +2 -0
- package/dist/client/assets/mipsasm-CNFOlV7Y.js +2 -0
- package/dist/client/assets/module-fAFg92om.js +4 -0
- package/dist/client/assets/mojo-DmJMpmxj.js +2 -0
- package/dist/client/assets/monokai-C4NNjw1j.js +2 -0
- package/dist/client/assets/monokai-DIfgn9Q6.js +2 -0
- package/dist/client/assets/moonbit-f-DlcHvh.js +2 -0
- package/dist/client/assets/move-3UEJ-86q.js +2 -0
- package/dist/client/assets/narrat-BSySVkso.js +2 -0
- package/dist/client/assets/nextflow-B6YiVxNF.js +2 -0
- package/dist/client/assets/nextflow-groovy-CJM1tnxB.js +2 -0
- package/dist/client/assets/nginx-yFGqgywB.js +2 -0
- package/dist/client/assets/night-owl-CVqrHJ7c.js +2 -0
- package/dist/client/assets/night-owl-M-9PEzO3.js +2 -0
- package/dist/client/assets/night-owl-light-BFLAfCgh.js +2 -0
- package/dist/client/assets/night-owl-light-CbICj08I.js +2 -0
- package/dist/client/assets/nim-H0r8m4Bj.js +2 -0
- package/dist/client/assets/nix-D01-yy0s.js +2 -0
- package/dist/client/assets/nord-DdQ2eXb7.js +2 -0
- package/dist/client/assets/nord-b31BpoFd.js +2 -0
- package/dist/client/assets/nushell-CHtjMTHK.js +2 -0
- package/dist/client/assets/objective-c-CpnACn2A.js +2 -0
- package/dist/client/assets/objective-cpp-CC37zF8s.js +2 -0
- package/dist/client/assets/ocaml-zEzf7VRa.js +2 -0
- package/dist/client/assets/odin-7LfNaizd.js +2 -0
- package/dist/client/assets/one-dark-pro-D7GXMkD_.js +2 -0
- package/dist/client/assets/one-dark-pro-DZNXQIff.js +2 -0
- package/dist/client/assets/one-light-D0m2woYU.js +2 -0
- package/dist/client/assets/one-light-vpvEwBNE.js +2 -0
- package/dist/client/assets/openscad-alCnkqb3.js +2 -0
- package/dist/client/assets/pascal-BzxE7FG0.js +2 -0
- package/dist/client/assets/perl-DMfQlGhS.js +2 -0
- package/dist/client/assets/php-eC0_nfgu.js +2 -0
- package/dist/client/assets/pierre-dark-C8scyjTE.js +2 -0
- package/dist/client/assets/pierre-dark-protanopia-deuteranopia-DjjI5tLG.js +2 -0
- package/dist/client/assets/pierre-dark-soft-U4k3hSAg.js +2 -0
- package/dist/client/assets/pierre-dark-tritanopia-CwldMLve.js +2 -0
- package/dist/client/assets/pierre-dark-vibrant-CbqW77RL.js +2 -0
- package/dist/client/assets/pierre-light-CRazXHrY.js +2 -0
- package/dist/client/assets/pierre-light-protanopia-deuteranopia-C-0-s32M.js +2 -0
- package/dist/client/assets/pierre-light-soft-CeMgeGD-.js +2 -0
- package/dist/client/assets/pierre-light-tritanopia-CwP7kaEp.js +2 -0
- package/dist/client/assets/pierre-light-vibrant-BRw7kdwa.js +2 -0
- package/dist/client/assets/pkl-B_4Y3aQj.js +2 -0
- package/dist/client/assets/plastic-7ebP7j7m.js +2 -0
- package/dist/client/assets/plastic-BxJ4wlPp.js +2 -0
- package/dist/client/assets/plsql-Vnj6O-p2.js +2 -0
- package/dist/client/assets/po-BDEiW-In.js +2 -0
- package/dist/client/assets/poimandres-CjxvpNV1.js +2 -0
- package/dist/client/assets/poimandres-DaajSABO.js +2 -0
- package/dist/client/assets/polar-DkeS43LD.js +2 -0
- package/dist/client/assets/postcss-BdW9ckpW.js +2 -0
- package/dist/client/assets/powerquery-Ck_tTsxM.js +2 -0
- package/dist/client/assets/powershell-CSE_7mny.js +2 -0
- package/dist/client/assets/preload-helper-2nxZ5jlD.js +1 -0
- package/dist/client/assets/prisma-Bo0mLS5-.js +2 -0
- package/dist/client/assets/prolog-BKKH5B6F.js +2 -0
- package/dist/client/assets/proto-CQGfqf21.js +2 -0
- package/dist/client/assets/pug-CdkPd3m5.js +2 -0
- package/dist/client/assets/puppet-CMQRMMTw.js +2 -0
- package/dist/client/assets/purescript-CCcyGQO2.js +2 -0
- package/dist/client/assets/purify.es-BOhOJYGt.js +3 -0
- package/dist/client/assets/python-DMPOlDIf.js +2 -0
- package/dist/client/assets/qml-CjgSvi7A.js +2 -0
- package/dist/client/assets/qmldir-WCdsq__X.js +2 -0
- package/dist/client/assets/qss-AtgwhOez.js +2 -0
- package/dist/client/assets/r-CyfaTtPo.js +2 -0
- package/dist/client/assets/racket-BChN0yKc.js +2 -0
- package/dist/client/assets/raku-y2whvo3i.js +2 -0
- package/dist/client/assets/razor-xg0jlt5d.js +2 -0
- package/dist/client/assets/red-4ASUbyQz.js +2 -0
- package/dist/client/assets/red-FUTSeuNn.js +2 -0
- package/dist/client/assets/reg-Vw5mc10D.js +2 -0
- package/dist/client/assets/regexp-DNjghFOM.js +2 -0
- package/dist/client/assets/rel-B7yBab0H.js +2 -0
- package/dist/client/assets/riscv-CoVA6mXv.js +2 -0
- package/dist/client/assets/rolldown-runtime-BeQ30c1w.js +1 -0
- package/dist/client/assets/ron-Dncoj8f2.js +2 -0
- package/dist/client/assets/rose-pine-BYqQazSr.js +2 -0
- package/dist/client/assets/rose-pine-DKVJldI6.js +2 -0
- package/dist/client/assets/rose-pine-dawn-BzAj1SA_.js +2 -0
- package/dist/client/assets/rose-pine-dawn-DpMWSJny.js +2 -0
- package/dist/client/assets/rose-pine-moon-BF7RtPma.js +2 -0
- package/dist/client/assets/rose-pine-moon-Buv_ZumG.js +2 -0
- package/dist/client/assets/rosmsg-DMM9gQ6F.js +2 -0
- package/dist/client/assets/rst-DUzGXO8S.js +2 -0
- package/dist/client/assets/ruby-rVw1KmtO.js +2 -0
- package/dist/client/assets/rust-Do9fnzCe.js +2 -0
- package/dist/client/assets/sas-DqCEPep6.js +2 -0
- package/dist/client/assets/sass-C-AYCcFv.js +2 -0
- package/dist/client/assets/scala-g1Tl2-Vx.js +2 -0
- package/dist/client/assets/scheme-DMNTmmtl.js +2 -0
- package/dist/client/assets/scss-DUVpCPFS.js +2 -0
- package/dist/client/assets/sdbl-DN-YwBSp.js +2 -0
- package/dist/client/assets/shaderlab-CU1ngQGv.js +2 -0
- package/dist/client/assets/shellscript-DhExEfAl.js +2 -0
- package/dist/client/assets/shellsession-BRLd459R.js +2 -0
- package/dist/client/assets/slack-dark-CHVebfsv.js +2 -0
- package/dist/client/assets/slack-dark-DsHK2SW9.js +2 -0
- package/dist/client/assets/slack-ochin-DLRnnjq1.js +2 -0
- package/dist/client/assets/slack-ochin-auUeui07.js +2 -0
- package/dist/client/assets/smalltalk-DfTqE6NI.js +2 -0
- package/dist/client/assets/snazzy-light-DYCniS15.js +2 -0
- package/dist/client/assets/snazzy-light-DcJ4c2TI.js +2 -0
- package/dist/client/assets/solarized-dark-C2M3A6iX.js +2 -0
- package/dist/client/assets/solarized-dark-f_BlEcC2.js +2 -0
- package/dist/client/assets/solarized-light-DGdaihLk.js +2 -0
- package/dist/client/assets/solarized-light-p0lk9NUw.js +2 -0
- package/dist/client/assets/solidity-UrsYApv4.js +2 -0
- package/dist/client/assets/soy-B2el7XDq.js +2 -0
- package/dist/client/assets/sparql-Ckg9aAAq.js +2 -0
- package/dist/client/assets/splunk-BbdNC7mF.js +2 -0
- package/dist/client/assets/sql-DiDaRjp9.js +2 -0
- package/dist/client/assets/src-pwcrD9wg.js +3 -0
- package/dist/client/assets/ssh-config-NaDpXiNE.js +2 -0
- package/dist/client/assets/stata-C71yNzqX.js +2 -0
- package/dist/client/assets/stylus-BmDWwNjA.js +2 -0
- package/dist/client/assets/surrealql-Cmypmwl2.js +2 -0
- package/dist/client/assets/svelte-VS6niI_T.js +2 -0
- package/dist/client/assets/swift-C69NyPuQ.js +2 -0
- package/dist/client/assets/synthwave-84-2NxBVDLO.js +2 -0
- package/dist/client/assets/synthwave-84-CVwMZOby.js +2 -0
- package/dist/client/assets/system-verilog-DJk0s1jv.js +2 -0
- package/dist/client/assets/systemd-CcQAXEZ9.js +2 -0
- package/dist/client/assets/talonscript-CUGr7vYM.js +2 -0
- package/dist/client/assets/tasl-BB-YNBB8.js +2 -0
- package/dist/client/assets/tcl-DR8-AcmN.js +2 -0
- package/dist/client/assets/templ-Cr4Do0uA.js +2 -0
- package/dist/client/assets/terraform-DS-GC2Bj.js +2 -0
- package/dist/client/assets/tex-CcZtvqzZ.js +2 -0
- package/dist/client/assets/toggle-BBEoD8mr.js +2 -0
- package/dist/client/assets/tokyo-night-9wJEO1G-.js +2 -0
- package/dist/client/assets/tokyo-night-ZUp4Hulo.js +2 -0
- package/dist/client/assets/toml-ByrHRc5Z.js +2 -0
- package/dist/client/assets/transport-B-82Ada5.js +2 -0
- package/dist/client/assets/ts-tags-Dhe4Ce_p.js +2 -0
- package/dist/client/assets/tsv-2A2hWH8i.js +2 -0
- package/dist/client/assets/tsx-rRP2I03K.js +2 -0
- package/dist/client/assets/turtle-BYbwzkhD.js +2 -0
- package/dist/client/assets/twig-DtN4j4nR.js +2 -0
- package/dist/client/assets/typeof-DOAxNSYQ.js +2 -0
- package/dist/client/assets/typescript-tv4fsI1Q.js +2 -0
- package/dist/client/assets/typespec-DoZVUoUi.js +2 -0
- package/dist/client/assets/typst-BmNF0lss.js +2 -0
- package/dist/client/assets/useTriggerFocusGuards-B2i3DSgR.js +2 -0
- package/dist/client/assets/v-CtCN4vLO.js +2 -0
- package/dist/client/assets/vala-DOsY6Y3z.js +2 -0
- package/dist/client/assets/vb-C1Ff9hOT.js +2 -0
- package/dist/client/assets/verilog-Dt4OfjHN.js +2 -0
- package/dist/client/assets/vesper-5ZmhmIun.js +2 -0
- package/dist/client/assets/vesper-J3W-7eep.js +2 -0
- package/dist/client/assets/vhdl-DkoQ3qnl.js +2 -0
- package/dist/client/assets/viml-C3b4aEDf.js +2 -0
- package/dist/client/assets/vitesse-black-CYOC7ssU.js +2 -0
- package/dist/client/assets/vitesse-black-DWaDDoI3.js +2 -0
- package/dist/client/assets/vitesse-dark-Bxewb9U5.js +2 -0
- package/dist/client/assets/vitesse-dark-CZotVzc8.js +2 -0
- package/dist/client/assets/vitesse-light-Bf_msd9a.js +2 -0
- package/dist/client/assets/vitesse-light-BfrRSjRx.js +2 -0
- package/dist/client/assets/vue-C0rWZC13.js +2 -0
- package/dist/client/assets/vue-html-bxw887C2.js +2 -0
- package/dist/client/assets/vue-vine-DUWGjTI5.js +2 -0
- package/dist/client/assets/vyper-BamdcTqV.js +2 -0
- package/dist/client/assets/wasm-C2MLrNQ1.js +2 -0
- package/dist/client/assets/wasm-CGd31VpO.js +2 -0
- package/dist/client/assets/wenyan-BPZ76iog.js +2 -0
- package/dist/client/assets/wgsl-sH_fVDG_.js +2 -0
- package/dist/client/assets/wikitext-BsPo9Czf.js +2 -0
- package/dist/client/assets/wit-BfBhtJwS.js +2 -0
- package/dist/client/assets/wolfram-GL7CPBRD.js +2 -0
- package/dist/client/assets/worker-Cvq2iJN1.js +162 -0
- package/dist/client/assets/workspaceReadinessAtom-DUP5NKsc.js +2 -0
- package/dist/client/assets/xml-C0zxRzgj.js +2 -0
- package/dist/client/assets/xsl-CC403A_G.js +2 -0
- package/dist/client/assets/yaml-BCnsJrvx.js +2 -0
- package/dist/client/assets/zenscript-CmwVE7RW.js +2 -0
- package/dist/client/assets/zig-GtQXM-vf.js +2 -0
- package/dist/client/favicon-16x16.png +0 -0
- package/dist/client/favicon-16x16.png.publish-bak +0 -0
- package/dist/client/favicon-32x32.png +0 -0
- package/dist/client/favicon-32x32.png.publish-bak +0 -0
- package/dist/client/favicon.ico +0 -0
- package/dist/client/favicon.ico.publish-bak +0 -0
- package/dist/client/forge-mark.svg +5 -0
- package/dist/client/index.html +131 -0
- package/dist/client/mockServiceWorker.js +336 -0
- package/dist/client/sidebar/forge-ember-field.webp +0 -0
- package/dist/{esm-wLIF-u3N.mjs → esm-Ce1GqbVk.mjs} +1 -1
- package/dist/{esm-BZhXwX5p.cjs → esm-Do7HVhLA.cjs} +1 -1
- package/dist/{execAsync-DWZyWH-_.mjs → execAsync-BNNdR88o.mjs} +1 -1
- package/dist/{execAsync-jnYVB5RZ.cjs → execAsync-BUcaFQ1D.cjs} +1 -1
- package/dist/forge-provision-display.sh +316 -0
- package/dist/{getMachineId-bsd-BLtyMA4j.cjs → getMachineId-bsd-C_qi9crE.cjs} +3 -3
- package/dist/{getMachineId-bsd-CTjiY7jG.mjs → getMachineId-bsd-FI863wjR.mjs} +3 -3
- package/dist/{getMachineId-darwin-DaGS2zUd.cjs → getMachineId-darwin-BOoNuqXn.cjs} +3 -3
- package/dist/{getMachineId-darwin-BrPuyPOo.mjs → getMachineId-darwin-D9VhTaPM.mjs} +3 -3
- package/dist/{getMachineId-linux-BsP3wJaE.cjs → getMachineId-linux-C9L-vW7m.cjs} +2 -2
- package/dist/{getMachineId-linux-D9QEWWF-.mjs → getMachineId-linux-DE2x36Kt.mjs} +2 -2
- package/dist/{getMachineId-unsupported-Cm-2s4Sg.mjs → getMachineId-unsupported-9S6pcxXb.mjs} +2 -2
- package/dist/{getMachineId-unsupported-B_M-gck7.cjs → getMachineId-unsupported-CmbM8LYa.cjs} +2 -2
- package/dist/{getMachineId-win-qtEKaUYj.mjs → getMachineId-win-0EVRuBxU.mjs} +3 -3
- package/dist/{getMachineId-win-3zJ3HQLG.cjs → getMachineId-win-BPaemVew.cjs} +3 -3
- package/dist/{open-CGXZLos4.cjs → open-BAsPVCWX.cjs} +1 -1
- package/dist/{open-Cf0bgbyx.mjs → open-FIgTDosf.mjs} +1 -1
- package/dist/runtimeBootstrap.cjs +8 -0
- package/dist/runtimeBootstrap.mjs +4 -0
- package/dist/runtimeControlAuthority-L85w5RTn.mjs +535 -0
- package/dist/runtimeControlAuthority-SNBF5Mjy.cjs +601 -0
- package/package.json +28 -30
- package/dist/NodeHttpServer-C7YMYP5R.cjs +0 -616
- package/dist/NodeHttpServer-D5-EtRwc.mjs +0 -605
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { createPublicKey, timingSafeEqual, verify } from "node:crypto";
|
|
4
|
+
import { readFileSync, unlinkSync } from "node:fs";
|
|
5
|
+
//#region src/auth/readOnceFileToken.ts
|
|
6
|
+
function createReadOnceFileTokenAccessor(config) {
|
|
7
|
+
let cachedFileToken = null;
|
|
8
|
+
let fileTokenResolved = false;
|
|
9
|
+
function readAndConsumeTokenFile(path) {
|
|
10
|
+
let contents;
|
|
11
|
+
try {
|
|
12
|
+
contents = readFileSync(path, "utf8");
|
|
13
|
+
} catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
unlinkSync(path);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.debug(`${config.debugLabel}: failed to unlink token file`, error);
|
|
20
|
+
}
|
|
21
|
+
const trimmed = contents.trim();
|
|
22
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
read(env = process.env) {
|
|
26
|
+
const fromEnv = env[config.envVar]?.trim();
|
|
27
|
+
if (fromEnv) return fromEnv;
|
|
28
|
+
if (!fileTokenResolved) {
|
|
29
|
+
const path = env[config.fileEnvVar]?.trim();
|
|
30
|
+
cachedFileToken = path ? readAndConsumeTokenFile(path) : null;
|
|
31
|
+
fileTokenResolved = true;
|
|
32
|
+
}
|
|
33
|
+
return cachedFileToken;
|
|
34
|
+
},
|
|
35
|
+
set(token) {
|
|
36
|
+
cachedFileToken = token;
|
|
37
|
+
fileTokenResolved = true;
|
|
38
|
+
},
|
|
39
|
+
reset() {
|
|
40
|
+
cachedFileToken = null;
|
|
41
|
+
fileTokenResolved = false;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/auth/runtimeGrantToken.ts
|
|
47
|
+
const accessor = createReadOnceFileTokenAccessor({
|
|
48
|
+
envVar: "FORGE_CMMD_RUNTIME_GRANT_TOKEN",
|
|
49
|
+
fileEnvVar: "FORGE_CMMD_RUNTIME_GRANT_TOKEN_FILE",
|
|
50
|
+
debugLabel: "runtimeGrantToken"
|
|
51
|
+
});
|
|
52
|
+
/**
|
|
53
|
+
* Resolves the CMMD runtime grant token, preferring the (legacy) environment
|
|
54
|
+
* variable and falling back to a one-time file read. The file, once read, is
|
|
55
|
+
* unlinked and its contents cached in memory for the remainder of the
|
|
56
|
+
* process — the secret is never read from disk twice.
|
|
57
|
+
*/
|
|
58
|
+
function runtimeGrantToken(env = process.env) {
|
|
59
|
+
return accessor.read(env);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Replaces the in-memory grant token cache with a freshly-issued one (see
|
|
63
|
+
* runtimeAuth/runtimeGrantRefresh.ts). This is the ONLY way a long-lived
|
|
64
|
+
* process picks up a rotated grant: the source file was already unlinked
|
|
65
|
+
* after its one read, and FORGE_CMMD_RUNTIME_GRANT_TOKEN (when present)
|
|
66
|
+
* always takes priority over this cache, matching `runtimeGrantToken()`'s own
|
|
67
|
+
* precedence. Does not touch disk — the refreshed secret lives only in this
|
|
68
|
+
* process's memory, same as the original.
|
|
69
|
+
*/
|
|
70
|
+
function setRuntimeGrantToken(token) {
|
|
71
|
+
accessor.set(token);
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/runtimeAuth/cmmdRuntimeTicket.ts
|
|
75
|
+
const CMMD_CLAUDE_READINESS_TICKET_AUDIENCE = "forge-claude-readiness";
|
|
76
|
+
const CMMD_CLAUDE_READINESS_TICKET_SCOPE = "claude-readiness-probe";
|
|
77
|
+
function decodeBase64UrlJson(value) {
|
|
78
|
+
try {
|
|
79
|
+
return JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
80
|
+
} catch {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function normalizePem(value) {
|
|
85
|
+
return value.includes("\\n") ? value.replace(/\\n/g, "\n") : value;
|
|
86
|
+
}
|
|
87
|
+
function stringClaim(payload, key) {
|
|
88
|
+
const value = payload[key];
|
|
89
|
+
if (typeof value === "string" && value.trim().length > 0) return value;
|
|
90
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
function constantTimeEqualString(left, right) {
|
|
94
|
+
const leftBuffer = Buffer.from(left, "utf8");
|
|
95
|
+
const rightBuffer = Buffer.from(right, "utf8");
|
|
96
|
+
if (leftBuffer.length !== rightBuffer.length) return false;
|
|
97
|
+
return timingSafeEqual(leftBuffer, rightBuffer);
|
|
98
|
+
}
|
|
99
|
+
function matchesExpected(actual, expected) {
|
|
100
|
+
return expected === void 0 || expected.trim().length === 0 || constantTimeEqualString(actual, expected);
|
|
101
|
+
}
|
|
102
|
+
function validTicketHeader(value) {
|
|
103
|
+
return typeof value === "object" && value !== null && value.alg === "EdDSA";
|
|
104
|
+
}
|
|
105
|
+
function validTicketSignature(input) {
|
|
106
|
+
try {
|
|
107
|
+
return verify(null, Buffer.from(input.signingInput), createPublicKey(normalizePem(input.publicKeyPem)), Buffer.from(input.signatureRaw, "base64url"));
|
|
108
|
+
} catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function nonNegativeIntegerClaim(value) {
|
|
113
|
+
return Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
114
|
+
}
|
|
115
|
+
function stringArrayClaim(value) {
|
|
116
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : null;
|
|
117
|
+
}
|
|
118
|
+
function verifiedRuntimeTicketPayload(token, publicKeyPem, audience = "forge-runtime") {
|
|
119
|
+
const parts = token.split(".");
|
|
120
|
+
if (parts.length !== 3) return null;
|
|
121
|
+
const [headerRaw, payloadRaw, signatureRaw] = parts;
|
|
122
|
+
if (!validTicketHeader(decodeBase64UrlJson(headerRaw))) return null;
|
|
123
|
+
const payload = decodeBase64UrlJson(payloadRaw);
|
|
124
|
+
if (typeof payload !== "object" || payload === null) return null;
|
|
125
|
+
const payloadRecord = payload;
|
|
126
|
+
if (payloadRecord["iss"] !== "cmmd" || payloadRecord["aud"] !== audience) return null;
|
|
127
|
+
return validTicketSignature({
|
|
128
|
+
signingInput: `${headerRaw}.${payloadRaw}`,
|
|
129
|
+
signatureRaw,
|
|
130
|
+
publicKeyPem
|
|
131
|
+
}) ? payloadRecord : null;
|
|
132
|
+
}
|
|
133
|
+
function verifyCmmdClaudeReadinessTicket(token, expectations) {
|
|
134
|
+
const payload = verifiedRuntimeTicketPayload(token, expectations.publicKeyPem, CMMD_CLAUDE_READINESS_TICKET_AUDIENCE);
|
|
135
|
+
if (!payload) return null;
|
|
136
|
+
const claims = runtimeTicketClaims(payload, false);
|
|
137
|
+
if (!claims || !runtimeTicketExpectationsMatch(claims, expectations)) return null;
|
|
138
|
+
const jti = stringClaim(payload, "jti");
|
|
139
|
+
const issuedAtSeconds = nonNegativeIntegerClaim(payload["iat"]);
|
|
140
|
+
const notBeforeSeconds = nonNegativeIntegerClaim(payload["nbf"]);
|
|
141
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
142
|
+
if (issuedAtSeconds === null || notBeforeSeconds === null || notBeforeSeconds > nowSeconds || issuedAtSeconds > nowSeconds + 5 || claims.expiresAtSeconds - issuedAtSeconds > 90) return null;
|
|
143
|
+
return jti && claims.scope.length === 1 && claims.scope[0] === CMMD_CLAUDE_READINESS_TICKET_SCOPE ? {
|
|
144
|
+
...claims,
|
|
145
|
+
jti
|
|
146
|
+
} : null;
|
|
147
|
+
}
|
|
148
|
+
function runtimeTicketExpiration(payload, allowExpired) {
|
|
149
|
+
const expiresAtSeconds = payload["exp"];
|
|
150
|
+
if (typeof expiresAtSeconds !== "number" || !Number.isFinite(expiresAtSeconds)) return null;
|
|
151
|
+
if (!allowExpired && Math.floor(Date.now() / 1e3) >= expiresAtSeconds) return null;
|
|
152
|
+
return expiresAtSeconds;
|
|
153
|
+
}
|
|
154
|
+
function requiredRuntimeIdentity(payload) {
|
|
155
|
+
const userId = stringClaim(payload, "user_id");
|
|
156
|
+
const orgId = stringClaim(payload, "org_id");
|
|
157
|
+
const projectId = stringClaim(payload, "project_id");
|
|
158
|
+
const runtimeId = stringClaim(payload, "runtime_id");
|
|
159
|
+
if (!userId || !orgId || !projectId || !runtimeId) return null;
|
|
160
|
+
return {
|
|
161
|
+
userId,
|
|
162
|
+
orgId,
|
|
163
|
+
projectId,
|
|
164
|
+
runtimeId
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function runtimeTicketClaims(payload, allowExpired) {
|
|
168
|
+
const expiresAtSeconds = runtimeTicketExpiration(payload, allowExpired);
|
|
169
|
+
if (expiresAtSeconds === null) return null;
|
|
170
|
+
const identity = requiredRuntimeIdentity(payload);
|
|
171
|
+
if (!identity) return null;
|
|
172
|
+
const scope = stringArrayClaim(payload["scope"]);
|
|
173
|
+
if (!scope) return null;
|
|
174
|
+
return {
|
|
175
|
+
...identity,
|
|
176
|
+
machineId: stringClaim(payload, "machine_id"),
|
|
177
|
+
credentialEpoch: nonNegativeIntegerClaim(payload["credential_epoch"]),
|
|
178
|
+
scope,
|
|
179
|
+
expiresAtSeconds
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function exactMachineExpectationMatches(claims, expectations) {
|
|
183
|
+
if (expectations.machineId !== void 0 && expectations.machineId.trim().length > 0) {
|
|
184
|
+
if (!claims.machineId) return false;
|
|
185
|
+
if (!constantTimeEqualString(claims.machineId, expectations.machineId)) return false;
|
|
186
|
+
}
|
|
187
|
+
return expectations.credentialEpoch === void 0 || claims.credentialEpoch === expectations.credentialEpoch;
|
|
188
|
+
}
|
|
189
|
+
function runtimeTicketExpectationsMatch(claims, expectations) {
|
|
190
|
+
return matchesExpected(claims.runtimeId, expectations.runtimeId) && matchesExpected(claims.orgId, expectations.orgId) && matchesExpected(claims.userId, expectations.userId) && matchesExpected(claims.projectId, expectations.projectId) && exactMachineExpectationMatches(claims, expectations);
|
|
191
|
+
}
|
|
192
|
+
function verifyCmmdRuntimeTicketWithExpirationPolicy(token, expectations, allowExpired) {
|
|
193
|
+
const payload = verifiedRuntimeTicketPayload(token, expectations.publicKeyPem);
|
|
194
|
+
if (!payload) return null;
|
|
195
|
+
const claims = runtimeTicketClaims(payload, allowExpired);
|
|
196
|
+
return claims && runtimeTicketExpectationsMatch(claims, expectations) ? claims : null;
|
|
197
|
+
}
|
|
198
|
+
function verifyCmmdRuntimeTicket(token, expectations) {
|
|
199
|
+
return verifyCmmdRuntimeTicketWithExpirationPolicy(token, expectations, false);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Verify a provisioning grant used only as refresh proof, retaining its signed
|
|
203
|
+
* identity and scope after `exp`. Expiration is intentionally the one relaxed
|
|
204
|
+
* check: signature, issuer, audience, claim shape, and caller expectations are
|
|
205
|
+
* identical to normal runtime-ticket verification. Callers must compare the
|
|
206
|
+
* returned ownership and authority to the freshly issued grant before storing
|
|
207
|
+
* it; this must never be used to authorize an ordinary runtime operation.
|
|
208
|
+
*/
|
|
209
|
+
function verifyCmmdRuntimeTicketRefreshProof(token, expectations) {
|
|
210
|
+
return verifyCmmdRuntimeTicketWithExpirationPolicy(token, expectations, true);
|
|
211
|
+
}
|
|
212
|
+
function authRuntimeTicketClaims(payload) {
|
|
213
|
+
const expiresAtSeconds = runtimeTicketExpiration(payload, false);
|
|
214
|
+
if (expiresAtSeconds === null) return null;
|
|
215
|
+
const userId = stringClaim(payload, "user_id");
|
|
216
|
+
const orgId = stringClaim(payload, "org_id");
|
|
217
|
+
const runtimeId = stringClaim(payload, "runtime_id");
|
|
218
|
+
const scope = stringArrayClaim(payload["scope"]);
|
|
219
|
+
return userId && orgId && runtimeId && scope ? {
|
|
220
|
+
orgId,
|
|
221
|
+
userId,
|
|
222
|
+
runtimeId,
|
|
223
|
+
scope,
|
|
224
|
+
expiresAtSeconds
|
|
225
|
+
} : null;
|
|
226
|
+
}
|
|
227
|
+
function authRuntimeTicketExpectationsMatch(claims, expectations) {
|
|
228
|
+
return matchesExpected(claims.runtimeId, expectations.runtimeId) && matchesExpected(claims.orgId, expectations.orgId) && matchesExpected(claims.userId, expectations.userId);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Card 1359 — verify the projectless personal-provider auth VM's transport
|
|
232
|
+
* ticket. It is the sibling of {@link verifyCmmdRuntimeTicket} for the distinct
|
|
233
|
+
* "forge-auth-runtime" audience: projectless, with no machine id or credential
|
|
234
|
+
* epoch (the auth VM serves no project and holds no broker scope), so it only
|
|
235
|
+
* asserts org/user/runtime identity + scope. The audience check keeps the two
|
|
236
|
+
* ticket families from cross-authenticating in either direction.
|
|
237
|
+
*/
|
|
238
|
+
function verifyCmmdAuthRuntimeTicket(token, expectations) {
|
|
239
|
+
const payload = verifiedRuntimeTicketPayload(token, expectations.publicKeyPem, "forge-auth-runtime");
|
|
240
|
+
if (!payload) return null;
|
|
241
|
+
const claims = authRuntimeTicketClaims(payload);
|
|
242
|
+
return claims && authRuntimeTicketExpectationsMatch(claims, expectations) ? claims : null;
|
|
243
|
+
}
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region src/runtimeAuth/runtimeControlAuthority.ts
|
|
246
|
+
const CONTROL_AUTHORITY_REFRESH_SKEW_SECONDS = 60;
|
|
247
|
+
const CONTROL_AUTHORITY_TIMEOUT_MS = 1e4;
|
|
248
|
+
const CONTROL_AUTHORITY_SCOPES = new Set(["heartbeat", "replication"]);
|
|
249
|
+
var RuntimeControlAuthorityError = class extends Error {
|
|
250
|
+
status;
|
|
251
|
+
code;
|
|
252
|
+
/**
|
|
253
|
+
* Whether trying again could plausibly succeed.
|
|
254
|
+
*
|
|
255
|
+
* A restarting control plane and a wrong credential both fail here and need
|
|
256
|
+
* opposite responses: the first must be retried until the deploy finishes,
|
|
257
|
+
* the second must not be retried at all. Without this the caller cannot tell
|
|
258
|
+
* them apart and picks wrong in one direction or the other.
|
|
259
|
+
*/
|
|
260
|
+
retryable;
|
|
261
|
+
constructor(input) {
|
|
262
|
+
super(input.message);
|
|
263
|
+
this.name = "RuntimeControlAuthorityError";
|
|
264
|
+
this.status = input.status ?? null;
|
|
265
|
+
this.code = input.code;
|
|
266
|
+
this.retryable = input.retryable ?? false;
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
/** Longest body prefix quoted into an error message. */
|
|
270
|
+
const CONTROL_AUTHORITY_BODY_PREVIEW = 180;
|
|
271
|
+
/**
|
|
272
|
+
* A short, credential-free description of a body that would not parse.
|
|
273
|
+
*
|
|
274
|
+
* The point is to identify the RESPONDER. A proxy error page says who it is in
|
|
275
|
+
* its first line, and that one line is the whole difference between "CMMD is
|
|
276
|
+
* redeploying" and a multi-hour dig through a guest.
|
|
277
|
+
*
|
|
278
|
+
* Redacted because this lands in logs and the responder is not always the one
|
|
279
|
+
* we think it is: anything resembling a JWT or a long opaque token is stripped
|
|
280
|
+
* rather than trusted to be harmless.
|
|
281
|
+
*/
|
|
282
|
+
function describeUnparsableBody(body) {
|
|
283
|
+
const collapsed = body.replace(/[A-Za-z0-9_-]{12,}\.[A-Za-z0-9_-]{12,}\.[A-Za-z0-9_-]{6,}/g, "<redacted-jwt>").replace(/[A-Za-z0-9_-]{40,}/g, "<redacted>").replace(/\s+/g, " ").trim();
|
|
284
|
+
return collapsed.length > CONTROL_AUTHORITY_BODY_PREVIEW ? `${collapsed.slice(0, CONTROL_AUTHORITY_BODY_PREVIEW)}…` : collapsed;
|
|
285
|
+
}
|
|
286
|
+
let authority = null;
|
|
287
|
+
let bootstrapInFlight = null;
|
|
288
|
+
function normalizedControlPlaneUrl(value) {
|
|
289
|
+
return value.trim().replace(/\/+$/u, "");
|
|
290
|
+
}
|
|
291
|
+
function asObject(value) {
|
|
292
|
+
return value !== null && typeof value === "object" ? value : null;
|
|
293
|
+
}
|
|
294
|
+
function readNullableString(value) {
|
|
295
|
+
if (value === null) return null;
|
|
296
|
+
return typeof value === "string" ? value : void 0;
|
|
297
|
+
}
|
|
298
|
+
function hasValidOptionalHeartbeatFields(payload) {
|
|
299
|
+
const countsAreValid = [payload.activeTurnCount, payload.activeSessionCount].every((value) => value === void 0 || Number.isSafeInteger(value) && value >= 0);
|
|
300
|
+
const stringsAreValid = [
|
|
301
|
+
payload.drainStartedAt,
|
|
302
|
+
payload.drainReason,
|
|
303
|
+
payload.drainTargetImageRef,
|
|
304
|
+
payload.drainTargetImageVersion
|
|
305
|
+
].every((value) => value === void 0 || value === null || typeof value === "string");
|
|
306
|
+
return countsAreValid && stringsAreValid && (payload.draining === void 0 || typeof payload.draining === "boolean") && (payload.drainForceRequired === void 0 || typeof payload.drainForceRequired === "boolean");
|
|
307
|
+
}
|
|
308
|
+
function requiredControlFields(payload) {
|
|
309
|
+
const runtimeId = payload.runtimeId;
|
|
310
|
+
const controlTicket = payload.controlTicket;
|
|
311
|
+
const expiresAt = payload.expiresAt;
|
|
312
|
+
if (typeof runtimeId !== "string" || runtimeId.trim().length === 0 || typeof controlTicket !== "string" || controlTicket.trim().length === 0 || typeof expiresAt !== "string" || !Number.isFinite(Date.parse(expiresAt))) return null;
|
|
313
|
+
return {
|
|
314
|
+
runtimeId,
|
|
315
|
+
controlTicket,
|
|
316
|
+
expiresAt
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
function optionalHeartbeatFields(payload) {
|
|
320
|
+
const activeTurnCount = payload.activeTurnCount;
|
|
321
|
+
const activeSessionCount = payload.activeSessionCount;
|
|
322
|
+
const drainStartedAt = readNullableString(payload.drainStartedAt);
|
|
323
|
+
const drainReason = readNullableString(payload.drainReason);
|
|
324
|
+
const drainTargetImageRef = readNullableString(payload.drainTargetImageRef);
|
|
325
|
+
const drainTargetImageVersion = readNullableString(payload.drainTargetImageVersion);
|
|
326
|
+
return {
|
|
327
|
+
...typeof activeTurnCount === "number" ? { activeTurnCount } : {},
|
|
328
|
+
...typeof activeSessionCount === "number" ? { activeSessionCount } : {},
|
|
329
|
+
...typeof payload.draining === "boolean" ? { draining: payload.draining } : {},
|
|
330
|
+
...drainStartedAt !== void 0 ? { drainStartedAt } : {},
|
|
331
|
+
...drainReason !== void 0 ? { drainReason } : {},
|
|
332
|
+
...drainTargetImageRef !== void 0 ? { drainTargetImageRef } : {},
|
|
333
|
+
...drainTargetImageVersion !== void 0 ? { drainTargetImageVersion } : {},
|
|
334
|
+
...typeof payload.drainForceRequired === "boolean" ? { drainForceRequired: payload.drainForceRequired } : {}
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function parseRuntimeControlAuthorityEnvelope(value) {
|
|
338
|
+
const payload = asObject(asObject(value)?.data);
|
|
339
|
+
if (!payload) return null;
|
|
340
|
+
const required = requiredControlFields(payload);
|
|
341
|
+
if (!required || !hasValidOptionalHeartbeatFields(payload)) return null;
|
|
342
|
+
return {
|
|
343
|
+
...required,
|
|
344
|
+
...optionalHeartbeatFields(payload)
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
function sameIdentity(stored, identity) {
|
|
348
|
+
return stored.controlPlaneUrl === normalizedControlPlaneUrl(identity.controlPlaneUrl) && stored.orgId === identity.orgId && stored.userId === identity.userId && stored.projectId === identity.projectId && stored.runtimeId === identity.runtimeId && stored.machineId === identity.machineId && stored.credentialEpoch === identity.credentialEpoch;
|
|
349
|
+
}
|
|
350
|
+
function isExactControlTicket(claims, identity) {
|
|
351
|
+
const scopes = new Set(claims.scope);
|
|
352
|
+
return claims.userId === identity.userId && claims.machineId === identity.machineId && claims.credentialEpoch === identity.credentialEpoch && scopes.size === CONTROL_AUTHORITY_SCOPES.size && [...CONTROL_AUTHORITY_SCOPES].every((scope) => scopes.has(scope));
|
|
353
|
+
}
|
|
354
|
+
function storeRuntimeControlAuthority(input) {
|
|
355
|
+
if (input.envelope.runtimeId !== input.identity.runtimeId) return false;
|
|
356
|
+
const claims = verifyCmmdRuntimeTicket(input.envelope.controlTicket, {
|
|
357
|
+
publicKeyPem: input.identity.publicKeyPem,
|
|
358
|
+
orgId: input.identity.orgId,
|
|
359
|
+
projectId: input.identity.projectId,
|
|
360
|
+
runtimeId: input.identity.runtimeId,
|
|
361
|
+
machineId: input.identity.machineId,
|
|
362
|
+
credentialEpoch: input.identity.credentialEpoch
|
|
363
|
+
});
|
|
364
|
+
if (!claims || !isExactControlTicket(claims, input.identity)) return false;
|
|
365
|
+
const responseExpirySeconds = Math.floor(Date.parse(input.envelope.expiresAt) / 1e3);
|
|
366
|
+
if (Math.abs(responseExpirySeconds - claims.expiresAtSeconds) > 1) return false;
|
|
367
|
+
if (authority && sameIdentity(authority, input.identity)) {
|
|
368
|
+
if (authority.expiresAtSeconds >= claims.expiresAtSeconds) return true;
|
|
369
|
+
}
|
|
370
|
+
authority = {
|
|
371
|
+
...input.identity,
|
|
372
|
+
controlPlaneUrl: normalizedControlPlaneUrl(input.identity.controlPlaneUrl),
|
|
373
|
+
token: input.envelope.controlTicket,
|
|
374
|
+
expiresAtSeconds: claims.expiresAtSeconds
|
|
375
|
+
};
|
|
376
|
+
return true;
|
|
377
|
+
}
|
|
378
|
+
async function readControlAuthorityResponse(response) {
|
|
379
|
+
if (!response.ok) throw new RuntimeControlAuthorityError({
|
|
380
|
+
status: response.status,
|
|
381
|
+
code: "CMMD_RUNTIME_CONTROL_AUTHORITY_REJECTED",
|
|
382
|
+
retryable: response.status >= 500,
|
|
383
|
+
message: `CMMD runtime control authority request failed (${response.status}).`
|
|
384
|
+
});
|
|
385
|
+
const raw = await response.text().catch(() => "");
|
|
386
|
+
try {
|
|
387
|
+
return JSON.parse(raw);
|
|
388
|
+
} catch {
|
|
389
|
+
throw new RuntimeControlAuthorityError({
|
|
390
|
+
status: response.status,
|
|
391
|
+
code: "CMMD_RUNTIME_CONTROL_AUTHORITY_INVALID_RESPONSE",
|
|
392
|
+
retryable: true,
|
|
393
|
+
message: `CMMD runtime control authority returned ${response.status} with a non-JSON body (content-type: ${response.headers.get("content-type") ?? "none"}): ${describeUnparsableBody(raw) || "<empty>"}`
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
async function requestWithTimeout(url, init, fetchImpl) {
|
|
398
|
+
const abortController = new AbortController();
|
|
399
|
+
const timeout = setTimeout(() => abortController.abort(), CONTROL_AUTHORITY_TIMEOUT_MS);
|
|
400
|
+
try {
|
|
401
|
+
return await readControlAuthorityResponse(await fetchImpl(url, {
|
|
402
|
+
...init,
|
|
403
|
+
signal: abortController.signal
|
|
404
|
+
}));
|
|
405
|
+
} finally {
|
|
406
|
+
clearTimeout(timeout);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
async function requestRuntimeControlHeartbeat(input) {
|
|
410
|
+
return requestWithTimeout(new URL(`/api/forge/context/runtime-authority/runtimes/${encodeURIComponent(input.grant.runtimeId)}/heartbeat`, `${input.grant.controlPlaneUrl}/`), {
|
|
411
|
+
method: "POST",
|
|
412
|
+
headers: {
|
|
413
|
+
authorization: `Bearer ${input.grant.grantToken}`,
|
|
414
|
+
"content-type": "application/json"
|
|
415
|
+
},
|
|
416
|
+
body: JSON.stringify({
|
|
417
|
+
activeTurnCount: input.activeTurnCount,
|
|
418
|
+
activeSessionCount: input.activeSessionCount,
|
|
419
|
+
...input.forgeGitCommit !== void 0 ? { forgeGitCommit: input.forgeGitCommit } : {}
|
|
420
|
+
})
|
|
421
|
+
}, input.fetchImpl);
|
|
422
|
+
}
|
|
423
|
+
function clearRejectedAuthority(error, grantToken) {
|
|
424
|
+
if (!(error instanceof RuntimeControlAuthorityError)) return;
|
|
425
|
+
if (error.status !== 401 && error.status !== 410) return;
|
|
426
|
+
if (authority?.token === grantToken) authority = null;
|
|
427
|
+
}
|
|
428
|
+
function readRuntimeControlAuthority(input) {
|
|
429
|
+
const current = authority;
|
|
430
|
+
if (!current) return null;
|
|
431
|
+
const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
432
|
+
if (current.expiresAtSeconds <= nowSeconds) {
|
|
433
|
+
authority = null;
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
if (current.runtimeId !== input.runtimeId || current.machineId !== input.machineId || current.credentialEpoch !== input.credentialEpoch) return null;
|
|
437
|
+
return {
|
|
438
|
+
controlPlaneUrl: current.controlPlaneUrl,
|
|
439
|
+
runtimeId: current.runtimeId,
|
|
440
|
+
machineId: current.machineId,
|
|
441
|
+
credentialEpoch: current.credentialEpoch,
|
|
442
|
+
grantToken: current.token,
|
|
443
|
+
expiresAtSeconds: current.expiresAtSeconds
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Seed the in-memory control authority from the sealed Service bootstrap grant.
|
|
448
|
+
* The grant must be exact-machine and carry exactly heartbeat + replication;
|
|
449
|
+
* it cannot authorize owner transport or any credential broker operation.
|
|
450
|
+
*/
|
|
451
|
+
function bootstrapRuntimeControlAuthorityFromNarrowGrant(input) {
|
|
452
|
+
const claims = verifyCmmdRuntimeTicket(input.grantToken, {
|
|
453
|
+
publicKeyPem: input.identity.publicKeyPem,
|
|
454
|
+
orgId: input.identity.orgId,
|
|
455
|
+
projectId: input.identity.projectId,
|
|
456
|
+
runtimeId: input.identity.runtimeId,
|
|
457
|
+
machineId: input.identity.machineId,
|
|
458
|
+
credentialEpoch: input.identity.credentialEpoch
|
|
459
|
+
});
|
|
460
|
+
if (!claims || !isExactControlTicket(claims, input.identity)) return false;
|
|
461
|
+
return storeRuntimeControlAuthority({
|
|
462
|
+
identity: input.identity,
|
|
463
|
+
envelope: {
|
|
464
|
+
runtimeId: input.identity.runtimeId,
|
|
465
|
+
controlTicket: input.grantToken,
|
|
466
|
+
expiresAt: (/* @__PURE__ */ new Date(claims.expiresAtSeconds * 1e3)).toISOString()
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
async function bootstrapRuntimeControlAuthority(input) {
|
|
471
|
+
const current = authority;
|
|
472
|
+
const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
473
|
+
if (current && sameIdentity(current, input.identity) && current.expiresAtSeconds > nowSeconds + CONTROL_AUTHORITY_REFRESH_SKEW_SECONDS) return true;
|
|
474
|
+
if (bootstrapInFlight) return bootstrapInFlight;
|
|
475
|
+
bootstrapInFlight = (async () => {
|
|
476
|
+
const envelope = parseRuntimeControlAuthorityEnvelope(await requestWithTimeout(new URL(`/api/forge/context/runtime-authority/runtimes/${encodeURIComponent(input.identity.runtimeId)}/control-ticket/bootstrap`, `${normalizedControlPlaneUrl(input.identity.controlPlaneUrl)}/`), {
|
|
477
|
+
method: "POST",
|
|
478
|
+
headers: {
|
|
479
|
+
authorization: `Bearer ${input.connectToken}`,
|
|
480
|
+
"x-forge-runtime-provisioning-grant": input.provisioningGrant
|
|
481
|
+
}
|
|
482
|
+
}, input.fetchImpl ?? fetch));
|
|
483
|
+
if (!envelope || !storeRuntimeControlAuthority({
|
|
484
|
+
identity: input.identity,
|
|
485
|
+
envelope
|
|
486
|
+
})) throw new RuntimeControlAuthorityError({
|
|
487
|
+
code: "CMMD_RUNTIME_CONTROL_AUTHORITY_INVALID_RESPONSE",
|
|
488
|
+
message: "CMMD runtime control authority response did not match this runtime."
|
|
489
|
+
});
|
|
490
|
+
return true;
|
|
491
|
+
})().finally(() => {
|
|
492
|
+
bootstrapInFlight = null;
|
|
493
|
+
});
|
|
494
|
+
return bootstrapInFlight;
|
|
495
|
+
}
|
|
496
|
+
async function sendRuntimeControlHeartbeat(input) {
|
|
497
|
+
const current = authority;
|
|
498
|
+
const grant = readRuntimeControlAuthority(input);
|
|
499
|
+
if (!current || !grant) return null;
|
|
500
|
+
let body;
|
|
501
|
+
try {
|
|
502
|
+
body = await requestRuntimeControlHeartbeat({
|
|
503
|
+
grant,
|
|
504
|
+
activeTurnCount: input.activeTurnCount,
|
|
505
|
+
activeSessionCount: input.activeSessionCount,
|
|
506
|
+
forgeGitCommit: input.forgeGitCommit,
|
|
507
|
+
fetchImpl: input.fetchImpl ?? fetch
|
|
508
|
+
});
|
|
509
|
+
} catch (error) {
|
|
510
|
+
clearRejectedAuthority(error, grant.grantToken);
|
|
511
|
+
throw error;
|
|
512
|
+
}
|
|
513
|
+
const envelope = parseRuntimeControlAuthorityEnvelope(body);
|
|
514
|
+
if (!envelope || !storeRuntimeControlAuthority({
|
|
515
|
+
identity: current,
|
|
516
|
+
envelope
|
|
517
|
+
})) throw new RuntimeControlAuthorityError({
|
|
518
|
+
code: "CMMD_RUNTIME_CONTROL_AUTHORITY_INVALID_RESPONSE",
|
|
519
|
+
message: "CMMD runtime heartbeat returned authority for a different runtime."
|
|
520
|
+
});
|
|
521
|
+
return {
|
|
522
|
+
activeTurnCount: envelope.activeTurnCount ?? input.activeTurnCount,
|
|
523
|
+
activeSessionCount: envelope.activeSessionCount ?? input.activeSessionCount,
|
|
524
|
+
draining: envelope.draining ?? false,
|
|
525
|
+
drainStartedAt: envelope.drainStartedAt ?? null,
|
|
526
|
+
drainReason: envelope.drainReason ?? null,
|
|
527
|
+
drainTargetImageRef: envelope.drainTargetImageRef ?? null,
|
|
528
|
+
drainTargetImageVersion: envelope.drainTargetImageVersion ?? null,
|
|
529
|
+
drainForceRequired: envelope.drainForceRequired ?? false
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
//#endregion
|
|
533
|
+
export { verifyCmmdAuthRuntimeTicket as a, verifyCmmdRuntimeTicketRefreshProof as c, createReadOnceFileTokenAccessor as d, sendRuntimeControlHeartbeat as i, runtimeGrantToken as l, bootstrapRuntimeControlAuthorityFromNarrowGrant as n, verifyCmmdClaudeReadinessTicket as o, readRuntimeControlAuthority as r, verifyCmmdRuntimeTicket as s, bootstrapRuntimeControlAuthority as t, setRuntimeGrantToken as u };
|
|
534
|
+
|
|
535
|
+
//# sourceMappingURL=runtimeControlAuthority-L85w5RTn.mjs.map
|