@quickchatai/quickreview 1.1.0 → 1.3.1
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/README.md +137 -57
- package/bin/qcr.js +1 -1
- package/config.example.toml +60 -14
- package/deploy/ansible/README.md +20 -12
- package/deploy/ansible/inventory.example.ini +1 -1
- package/deploy/collect-secrets.sh +1 -1
- package/deploy/qcr-update.sh +1 -1
- package/dist/extensions/cli/home.js +14 -0
- package/dist/extensions/cli/home.js.map +1 -0
- package/dist/extensions/cli/login-route.js +5 -0
- package/dist/extensions/cli/login-route.js.map +1 -0
- package/dist/extensions/cli/selfimprove.js +18 -0
- package/dist/extensions/cli/selfimprove.js.map +1 -0
- package/dist/extensions/home.js +350 -0
- package/dist/extensions/home.js.map +1 -0
- package/dist/extensions/login-route.js +180 -0
- package/dist/extensions/login-route.js.map +1 -0
- package/dist/extensions/onboarding.js +35 -11
- package/dist/extensions/onboarding.js.map +1 -1
- package/dist/extensions/selfimprove.js +49 -0
- package/dist/extensions/selfimprove.js.map +1 -0
- package/dist/extensions/setup-scan.js +23 -592
- package/dist/extensions/setup-scan.js.map +1 -1
- package/dist/extensions/setup.js +2 -47
- package/dist/extensions/setup.js.map +1 -1
- package/dist/src/archive/restore.js +18 -15
- package/dist/src/archive/restore.js.map +1 -1
- package/dist/src/botworker.js +13 -2
- package/dist/src/botworker.js.map +1 -1
- package/dist/src/channelfs.js +3 -26
- package/dist/src/channelfs.js.map +1 -1
- package/dist/src/ciretry.js +2 -1
- package/dist/src/ciretry.js.map +1 -1
- package/dist/src/cli.js +54 -61
- package/dist/src/cli.js.map +1 -1
- package/dist/src/cliops.js +3 -2
- package/dist/src/cliops.js.map +1 -1
- package/dist/src/commands.js +25 -2
- package/dist/src/commands.js.map +1 -1
- package/dist/src/config.js +32 -2
- package/dist/src/config.js.map +1 -1
- package/dist/src/daemon.js +50 -8
- package/dist/src/daemon.js.map +1 -1
- package/dist/src/debuground.js +1 -0
- package/dist/src/debuground.js.map +1 -1
- package/dist/src/debugroundpi.js +6 -1
- package/dist/src/debugroundpi.js.map +1 -1
- package/dist/src/dispatch.js +5 -4
- package/dist/src/dispatch.js.map +1 -1
- package/dist/src/engine/caserunner-sdk.js +15 -251
- package/dist/src/engine/caserunner-sdk.js.map +1 -1
- package/dist/src/engine/debugpi.js +17 -5
- package/dist/src/engine/debugpi.js.map +1 -1
- package/dist/src/execboundary.js +10 -3
- package/dist/src/execboundary.js.map +1 -1
- package/dist/src/github.js +51 -16
- package/dist/src/github.js.map +1 -1
- package/dist/src/githubtoken.js +346 -0
- package/dist/src/githubtoken.js.map +1 -0
- package/dist/src/home/adapters.js +349 -0
- package/dist/src/home/adapters.js.map +1 -0
- package/dist/src/home/advanced.js +318 -0
- package/dist/src/home/advanced.js.map +1 -0
- package/dist/src/home/advancedtools.js +57 -0
- package/dist/src/home/advancedtools.js.map +1 -0
- package/dist/src/home/autoreview.js +325 -0
- package/dist/src/home/autoreview.js.map +1 -0
- package/dist/src/home/daemonstatus.js +32 -0
- package/dist/src/home/daemonstatus.js.map +1 -0
- package/dist/src/home/devicelogin.js +61 -0
- package/dist/src/home/devicelogin.js.map +1 -0
- package/dist/src/home/launch.js +202 -0
- package/dist/src/home/launch.js.map +1 -0
- package/dist/src/home/loginowner.js +205 -0
- package/dist/src/home/loginowner.js.map +1 -0
- package/dist/src/home/memory.js +122 -0
- package/dist/src/home/memory.js.map +1 -0
- package/dist/src/home/model.js +811 -0
- package/dist/src/home/model.js.map +1 -0
- package/dist/src/home/panel.js +520 -0
- package/dist/src/home/panel.js.map +1 -0
- package/dist/src/home/ports.js +19 -0
- package/dist/src/home/ports.js.map +1 -0
- package/dist/src/home/review.js +163 -0
- package/dist/src/home/review.js.map +1 -0
- package/dist/src/home/reviews.js +478 -0
- package/dist/src/home/reviews.js.map +1 -0
- package/dist/src/home/setup.js +507 -0
- package/dist/src/home/setup.js.map +1 -0
- package/dist/src/home/setupadapters.js +214 -0
- package/dist/src/home/setupadapters.js.map +1 -0
- package/dist/src/home/setupcard.js +199 -0
- package/dist/src/home/setupcard.js.map +1 -0
- package/dist/src/home/setuptools.js +45 -0
- package/dist/src/home/setuptools.js.map +1 -0
- package/dist/src/home/spend.js +160 -0
- package/dist/src/home/spend.js.map +1 -0
- package/dist/src/home/switches.js +209 -0
- package/dist/src/home/switches.js.map +1 -0
- package/dist/src/home/switchon.js +439 -0
- package/dist/src/home/switchon.js.map +1 -0
- package/dist/src/home/toolnames.js +41 -0
- package/dist/src/home/toolnames.js.map +1 -0
- package/dist/src/home/tune.js +341 -0
- package/dist/src/home/tune.js.map +1 -0
- package/dist/src/home/words.js +7 -0
- package/dist/src/home/words.js.map +1 -0
- package/dist/src/homes.js +14 -0
- package/dist/src/homes.js.map +1 -1
- package/dist/src/install.js +1 -1
- package/dist/src/install.js.map +1 -1
- package/dist/src/ipc/workerspec.js +8 -0
- package/dist/src/ipc/workerspec.js.map +1 -1
- package/dist/src/live/publish.js +1 -1
- package/dist/src/live/publish.js.map +1 -1
- package/dist/src/livecli.js +1 -1
- package/dist/src/livecli.js.map +1 -1
- package/dist/src/loginhint.js +8 -3
- package/dist/src/loginhint.js.map +1 -1
- package/dist/src/loginrefresh/handover.js +121 -0
- package/dist/src/loginrefresh/handover.js.map +1 -0
- package/dist/src/loginrefresh/lock.js +54 -3
- package/dist/src/loginrefresh/lock.js.map +1 -1
- package/dist/src/loginrefresh/pirefresh.js +3 -0
- package/dist/src/loginrefresh/pirefresh.js.map +1 -1
- package/dist/src/loginrefresh/refresher.js +33 -5
- package/dist/src/loginrefresh/refresher.js.map +1 -1
- package/dist/src/loginrefresh/supervisor.js +18 -1
- package/dist/src/loginrefresh/supervisor.js.map +1 -1
- package/dist/src/npmverbs.js +46 -14
- package/dist/src/npmverbs.js.map +1 -1
- package/dist/src/onboard/choices.js +35 -4
- package/dist/src/onboard/choices.js.map +1 -1
- package/dist/src/onboard/engine.js +32 -306
- package/dist/src/onboard/engine.js.map +1 -1
- package/dist/src/onboard/pipin.js +22 -0
- package/dist/src/onboard/pipin.js.map +1 -0
- package/dist/src/onboard/stepforward.js +41 -0
- package/dist/src/onboard/stepforward.js.map +1 -0
- package/dist/src/onboard/steps/appslug.js +4 -1
- package/dist/src/onboard/steps/appslug.js.map +1 -1
- package/dist/src/onboard/steps/bringup.js +3 -2
- package/dist/src/onboard/steps/bringup.js.map +1 -1
- package/dist/src/onboard/steps/compose.js +29 -0
- package/dist/src/onboard/steps/compose.js.map +1 -1
- package/dist/src/onboard/steps/configfill.js +120 -39
- package/dist/src/onboard/steps/configfill.js.map +1 -1
- package/dist/src/onboard/steps/githubaccount.js +595 -0
- package/dist/src/onboard/steps/githubaccount.js.map +1 -0
- package/dist/src/onboard/steps/githubapp.js +65 -7
- package/dist/src/onboard/steps/githubapp.js.map +1 -1
- package/dist/src/onboard/steps/golive.js +2 -0
- package/dist/src/onboard/steps/golive.js.map +1 -1
- package/dist/src/onboard/steps/index.js +11 -0
- package/dist/src/onboard/steps/index.js.map +1 -1
- package/dist/src/onboard/steps/ingress.js +80 -25
- package/dist/src/onboard/steps/ingress.js.map +1 -1
- package/dist/src/onboard/steps/llmauth.js +103 -30
- package/dist/src/onboard/steps/llmauth.js.map +1 -1
- package/dist/src/onboard/steps/loginshare.js +213 -0
- package/dist/src/onboard/steps/loginshare.js.map +1 -0
- package/dist/src/onboard/steps/memory.js +67 -3
- package/dist/src/onboard/steps/memory.js.map +1 -1
- package/dist/src/onboard/steps/proof.js +366 -56
- package/dist/src/onboard/steps/proof.js.map +1 -1
- package/dist/src/onboard/steps/repoconfig.js +72 -0
- package/dist/src/onboard/steps/repoconfig.js.map +1 -0
- package/dist/src/onboard/steps/topology.js +6 -6
- package/dist/src/onboard/steps/topology.js.map +1 -1
- package/dist/src/onboard/steps/transport.js +9 -1
- package/dist/src/onboard/steps/transport.js.map +1 -1
- package/dist/src/onboard/steps/tuiroute.js +102 -0
- package/dist/src/onboard/steps/tuiroute.js.map +1 -0
- package/dist/src/onboard/steps/verifyup.js +17 -1
- package/dist/src/onboard/steps/verifyup.js.map +1 -1
- package/dist/src/onboard/toolnames.js +30 -0
- package/dist/src/onboard/toolnames.js.map +1 -0
- package/dist/src/operatorwrite.js +23 -0
- package/dist/src/operatorwrite.js.map +1 -0
- package/dist/src/outcomes.js +4 -1
- package/dist/src/outcomes.js.map +1 -1
- package/dist/src/piagentdir.js +13 -0
- package/dist/src/piagentdir.js.map +1 -0
- package/dist/src/pilogin.js +31 -16
- package/dist/src/pilogin.js.map +1 -1
- package/dist/src/posting-journal.js +2 -1
- package/dist/src/posting-journal.js.map +1 -1
- package/dist/src/posting-outbox.js +6 -2
- package/dist/src/posting-outbox.js.map +1 -1
- package/dist/src/posting-receipt.js +14 -1
- package/dist/src/posting-receipt.js.map +1 -1
- package/dist/src/qcrbin.js +16 -11
- package/dist/src/qcrbin.js.map +1 -1
- package/dist/src/recheck.js +2 -1
- package/dist/src/recheck.js.map +1 -1
- package/dist/src/reconcile.js +22 -2
- package/dist/src/reconcile.js.map +1 -1
- package/dist/src/reviewargs.js +122 -0
- package/dist/src/reviewargs.js.map +1 -0
- package/dist/src/reviewcli.js +7 -161
- package/dist/src/reviewcli.js.map +1 -1
- package/dist/src/reviewdetach.js +76 -11
- package/dist/src/reviewdetach.js.map +1 -1
- package/dist/src/reviewhistory.js +32 -6
- package/dist/src/reviewhistory.js.map +1 -1
- package/dist/src/reviewnow.js +45 -0
- package/dist/src/reviewnow.js.map +1 -0
- package/dist/src/scancli.js +39 -691
- package/dist/src/scancli.js.map +1 -1
- package/dist/src/selfimprove.js +66 -0
- package/dist/src/selfimprove.js.map +1 -0
- package/dist/src/setup/adapters.js +5 -223
- package/dist/src/setup/adapters.js.map +1 -1
- package/dist/src/setup/caserunner.js +15 -249
- package/dist/src/setup/caserunner.js.map +1 -1
- package/dist/src/setup/engine.js +32 -341
- package/dist/src/setup/engine.js.map +1 -1
- package/dist/src/setup/facts.js +3 -592
- package/dist/src/setup/facts.js.map +1 -1
- package/dist/src/setup/findings.js +3 -947
- package/dist/src/setup/findings.js.map +1 -1
- package/dist/src/setup/presentation.js +3 -8
- package/dist/src/setup/presentation.js.map +1 -1
- package/dist/src/setup/scan.js +3 -724
- package/dist/src/setup/scan.js.map +1 -1
- package/dist/src/setup/scanbuild.js +9 -92
- package/dist/src/setup/scanbuild.js.map +1 -1
- package/dist/src/setup/scanlease.js +3 -250
- package/dist/src/setup/scanlease.js.map +1 -1
- package/dist/src/setup/scanreport.js +3 -288
- package/dist/src/setup/scanreport.js.map +1 -1
- package/dist/src/setup/scanrun.js +3 -1732
- package/dist/src/setup/scanrun.js.map +1 -1
- package/dist/src/setup/scantree.js +3 -256
- package/dist/src/setup/scantree.js.map +1 -1
- package/dist/src/setup/stage2request.js +3 -258
- package/dist/src/setup/stage2request.js.map +1 -1
- package/dist/src/setup/unitcut.js +3 -436
- package/dist/src/setup/unitcut.js.map +1 -1
- package/dist/src/state.js +2 -0
- package/dist/src/state.js.map +1 -1
- package/dist/src/statemachine.js +4 -1
- package/dist/src/statemachine.js.map +1 -1
- package/dist/src/takeover.js +1 -0
- package/dist/src/takeover.js.map +1 -1
- package/dist/src/takeoverpi.js +15 -1
- package/dist/src/takeoverpi.js.map +1 -1
- package/dist/src/tui/app.js +49 -0
- package/dist/src/tui/app.js.map +1 -1
- package/dist/src/tui/board.js +88 -12
- package/dist/src/tui/board.js.map +1 -1
- package/dist/src/tui/cmdbar.js +4 -1
- package/dist/src/tui/cmdbar.js.map +1 -1
- package/dist/src/tui/companion.js +76 -11
- package/dist/src/tui/companion.js.map +1 -1
- package/dist/src/tui/connect.js +7 -1
- package/dist/src/tui/connect.js.map +1 -1
- package/dist/src/tui/deploytab.js +2 -2
- package/dist/src/tui/deploytab.js.map +1 -1
- package/dist/src/tui/filters.js +5 -2
- package/dist/src/tui/filters.js.map +1 -1
- package/dist/src/tui/ghread.js +61 -5
- package/dist/src/tui/ghread.js.map +1 -1
- package/dist/src/tui/index.js +109 -20
- package/dist/src/tui/index.js.map +1 -1
- package/dist/src/tui/memforward.js +39 -2
- package/dist/src/tui/memforward.js.map +1 -1
- package/dist/src/tui/memory.js +3 -16
- package/dist/src/tui/memory.js.map +1 -1
- package/dist/src/tui/memoryurl.js +22 -0
- package/dist/src/tui/memoryurl.js.map +1 -0
- package/dist/src/tui/model.js +25 -0
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/prpause.js +7 -0
- package/dist/src/tui/prpause.js.map +1 -1
- package/dist/src/tui/remote.js +7 -1
- package/dist/src/tui/remote.js.map +1 -1
- package/dist/src/tui/route.js +143 -0
- package/dist/src/tui/route.js.map +1 -0
- package/dist/src/tui/setupstate.js +32 -0
- package/dist/src/tui/setupstate.js.map +1 -0
- package/dist/src/tui/sshtriage.js +102 -5
- package/dist/src/tui/sshtriage.js.map +1 -1
- package/dist/src/tui/theme.js +2 -1
- package/dist/src/tui/theme.js.map +1 -1
- package/dist/src/tui/unwedge.js +2 -12
- package/dist/src/tui/unwedge.js.map +1 -1
- package/dist/src/verdicts.js +17 -5
- package/dist/src/verdicts.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/src/webhook.js +12 -1
- package/dist/src/webhook.js.map +1 -1
- package/dist/src/wire.js +34 -8
- package/dist/src/wire.js.map +1 -1
- package/dist/src/workerworld.js +11 -1
- package/dist/src/workerworld.js.map +1 -1
- package/docker/README.md +1 -1
- package/docker/companion/entrypoint.sh +20 -1
- package/docker/entrypoint.sh +57 -6
- package/docker-compose.yml +16 -1
- package/extensions/cli/home.ts +14 -0
- package/extensions/cli/login-route.ts +10 -0
- package/extensions/cli/selfimprove.ts +18 -0
- package/extensions/home.ts +484 -0
- package/extensions/login-route.ts +220 -0
- package/extensions/onboarding.ts +41 -11
- package/extensions/selfimprove.ts +65 -0
- package/extensions/setup-scan.ts +79 -766
- package/extensions/setup.ts +14 -70
- package/package.json +6 -4
- package/prompts/onboarding.md +58 -18
- package/schemas/review-result.v1.json +60 -0
- package/scripts/deploy.sh +8 -6
- package/scripts/mint-token.sh +25 -4
- package/scripts/qcr-host.sh +28 -5
- package/scripts/vm-ghcr-login.sh +7 -4
- package/src/archive/restore.ts +18 -21
- package/src/botworker.ts +13 -2
- package/src/channelfs.ts +3 -26
- package/src/ciretry.ts +2 -1
- package/src/cli.ts +59 -67
- package/src/cliops.ts +3 -2
- package/src/commands.ts +28 -2
- package/src/config.ts +62 -4
- package/src/daemon.ts +58 -7
- package/src/debuground.ts +3 -0
- package/src/debugroundpi.ts +12 -1
- package/src/dispatch.ts +5 -4
- package/src/engine/caserunner-sdk.ts +29 -314
- package/src/engine/debugpi.ts +17 -5
- package/src/execboundary.ts +16 -4
- package/src/github.ts +57 -15
- package/src/githubtoken.ts +435 -0
- package/src/home/adapters.ts +418 -0
- package/src/home/advanced.ts +421 -0
- package/src/home/advancedtools.ts +96 -0
- package/src/home/autoreview.ts +385 -0
- package/src/home/daemonstatus.ts +55 -0
- package/src/home/devicelogin.ts +107 -0
- package/src/home/launch.ts +257 -0
- package/src/home/loginowner.ts +248 -0
- package/src/home/memory.ts +176 -0
- package/src/home/model.ts +965 -0
- package/src/home/panel.ts +666 -0
- package/src/home/ports.ts +338 -0
- package/src/home/review.ts +206 -0
- package/src/home/reviews.ts +565 -0
- package/src/home/setup.ts +689 -0
- package/src/home/setupadapters.ts +217 -0
- package/src/home/setupcard.ts +288 -0
- package/src/home/setuptools.ts +57 -0
- package/src/home/spend.ts +194 -0
- package/src/home/switches.ts +293 -0
- package/src/home/switchon.ts +554 -0
- package/src/home/toolnames.ts +46 -0
- package/src/home/tune.ts +405 -0
- package/src/home/words.ts +8 -0
- package/src/homes.ts +17 -0
- package/src/install.ts +1 -1
- package/src/ipc/workerspec.ts +15 -0
- package/src/live/publish.ts +4 -1
- package/src/livecli.ts +6 -1
- package/src/loginhint.ts +8 -3
- package/src/loginrefresh/handover.ts +138 -0
- package/src/loginrefresh/lock.ts +72 -3
- package/src/loginrefresh/pirefresh.ts +3 -0
- package/src/loginrefresh/refresher.ts +34 -5
- package/src/loginrefresh/supervisor.ts +25 -2
- package/src/npmverbs.ts +55 -13
- package/src/onboard/choices.ts +40 -4
- package/src/onboard/engine.ts +70 -421
- package/src/onboard/pipin.ts +31 -0
- package/src/onboard/stepforward.ts +61 -0
- package/src/onboard/steps/appslug.ts +4 -1
- package/src/onboard/steps/bringup.ts +3 -2
- package/src/onboard/steps/compose.ts +31 -0
- package/src/onboard/steps/configfill.ts +144 -40
- package/src/onboard/steps/githubaccount.ts +716 -0
- package/src/onboard/steps/githubapp.ts +92 -8
- package/src/onboard/steps/golive.ts +2 -0
- package/src/onboard/steps/index.ts +11 -0
- package/src/onboard/steps/ingress.ts +98 -31
- package/src/onboard/steps/llmauth.ts +114 -29
- package/src/onboard/steps/loginshare.ts +258 -0
- package/src/onboard/steps/memory.ts +76 -3
- package/src/onboard/steps/proof.ts +473 -55
- package/src/onboard/steps/repoconfig.ts +85 -0
- package/src/onboard/steps/topology.ts +7 -6
- package/src/onboard/steps/transport.ts +15 -0
- package/src/onboard/steps/tuiroute.ts +119 -0
- package/src/onboard/steps/verifyup.ts +20 -1
- package/src/onboard/toolnames.ts +34 -0
- package/src/operatorwrite.ts +25 -0
- package/src/outcomes.ts +8 -1
- package/src/piagentdir.ts +12 -0
- package/src/pilogin.ts +32 -16
- package/src/posting-journal.ts +6 -1
- package/src/posting-outbox.ts +10 -2
- package/src/posting-receipt.ts +17 -0
- package/src/qcrbin.ts +16 -11
- package/src/recheck.ts +2 -1
- package/src/reconcile.ts +29 -3
- package/src/reviewargs.ts +119 -0
- package/src/reviewcli.ts +6 -167
- package/src/reviewdetach.ts +107 -13
- package/src/reviewhistory.ts +20 -6
- package/src/reviewnow.ts +76 -0
- package/src/scancli.ts +75 -826
- package/src/selfimprove.ts +90 -0
- package/src/setup/adapters.ts +13 -221
- package/src/setup/caserunner.ts +34 -273
- package/src/setup/engine.ts +62 -496
- package/src/setup/facts.ts +3 -627
- package/src/setup/findings.ts +3 -1264
- package/src/setup/presentation.ts +3 -18
- package/src/setup/scan.ts +3 -1033
- package/src/setup/scanbuild.ts +20 -114
- package/src/setup/scanlease.ts +3 -297
- package/src/setup/scanreport.ts +3 -373
- package/src/setup/scanrun.ts +3 -2268
- package/src/setup/scantree.ts +3 -259
- package/src/setup/stage2request.ts +3 -347
- package/src/setup/unitcut.ts +3 -523
- package/src/state.ts +43 -0
- package/src/statemachine.ts +4 -1
- package/src/takeover.ts +5 -0
- package/src/takeoverpi.ts +16 -2
- package/src/tui/app.ts +47 -0
- package/src/tui/board.ts +111 -14
- package/src/tui/cmdbar.ts +4 -1
- package/src/tui/companion.ts +80 -11
- package/src/tui/connect.ts +7 -1
- package/src/tui/deploytab.ts +2 -2
- package/src/tui/filters.ts +7 -3
- package/src/tui/ghread.ts +74 -7
- package/src/tui/index.ts +117 -23
- package/src/tui/memforward.ts +52 -3
- package/src/tui/memory.ts +3 -15
- package/src/tui/memoryurl.ts +22 -0
- package/src/tui/model.ts +36 -2
- package/src/tui/prpause.ts +11 -2
- package/src/tui/remote.ts +9 -1
- package/src/tui/route.ts +173 -0
- package/src/tui/setupstate.ts +56 -0
- package/src/tui/sshtriage.ts +127 -6
- package/src/tui/theme.ts +2 -1
- package/src/tui/unwedge.ts +2 -14
- package/src/verdicts.ts +23 -5
- package/src/version.ts +1 -1
- package/src/webhook.ts +10 -1
- package/src/wire.ts +42 -9
- package/src/workerworld.ts +16 -2
- package/dist/src/live/projection.js +0 -450
- package/dist/src/live/projection.js.map +0 -1
- package/dist/src/live/read.js +0 -60
- package/dist/src/live/read.js.map +0 -1
- package/dist/src/onboard/launch.js +0 -83
- package/dist/src/onboard/launch.js.map +0 -1
- package/dist/src/setup/ledger.js +0 -207
- package/dist/src/setup/ledger.js.map +0 -1
- package/dist/src/setup/stage2.js +0 -617
- package/dist/src/setup/stage2.js.map +0 -1
- package/dist/src/setup/textsniff.js +0 -89
- package/dist/src/setup/textsniff.js.map +0 -1
- package/src/live/projection.ts +0 -491
- package/src/live/read.ts +0 -86
- package/src/onboard/launch.ts +0 -115
- package/src/setup/ledger.ts +0 -324
- package/src/setup/stage2.ts +0 -926
- package/src/setup/textsniff.ts +0 -95
|
@@ -80,13 +80,14 @@ import {
|
|
|
80
80
|
embedderInputsCheck,
|
|
81
81
|
localEmbedderEnvEntries,
|
|
82
82
|
} from "./embeddings.js";
|
|
83
|
+
import { CHOICE_KEYS } from "../choices.js";
|
|
83
84
|
import { readEnvKey, readTomlKey, setEnvKey } from "./ingress.js";
|
|
84
85
|
import { UID_CHOICE_KEY } from "./preflight.js";
|
|
85
86
|
import { topologyOf } from "./topology.js";
|
|
86
87
|
|
|
87
88
|
export const BRINGUP_STEP_ID = "bringup";
|
|
88
89
|
/** Recorded timestamp of this step's successful bring-up. */
|
|
89
|
-
export const BROUGHT_UP_CHOICE_KEY =
|
|
90
|
+
export const BROUGHT_UP_CHOICE_KEY = CHOICE_KEYS.broughtUpAt;
|
|
90
91
|
|
|
91
92
|
/**
|
|
92
93
|
* The note, in the operator's words, emitted before the pull begins.
|
|
@@ -442,7 +443,7 @@ export function bringUpStep(opts: BringUpStepOptions = {}): OnboardingStep {
|
|
|
442
443
|
}),
|
|
443
444
|
);
|
|
444
445
|
const ok = checks.every((c) => c.ok);
|
|
445
|
-
if (ok) ctx.recordChoice(
|
|
446
|
+
if (ok) ctx.recordChoice(CHOICE_KEYS.broughtUpAt, ctx.adapters.clock().toISOString());
|
|
446
447
|
return { ok, checks, data: { profile, up_at: ctx.adapters.clock().toISOString() } };
|
|
447
448
|
},
|
|
448
449
|
|
|
@@ -74,6 +74,9 @@ export const MEMORY_IMAGE_REPO = "ghcr.io/quickchatai/quickreview-memory";
|
|
|
74
74
|
|
|
75
75
|
export { CONTAINER_STATE_DIR };
|
|
76
76
|
export const CONTAINER_DRYRUN_DIR = `${CONTAINER_STATE_DIR}/dryrun`;
|
|
77
|
+
/** The daemon's command root in the release image (`<root>/commands`, with the
|
|
78
|
+
* root-sealed `operator/` under it and the result files in `results/`). */
|
|
79
|
+
export const CONTAINER_COMMANDS_DIR = "/opt/qcr/commands";
|
|
77
80
|
|
|
78
81
|
/** `<sandbox root>` — the engine's contract is stateDir = `<root>/state`. */
|
|
79
82
|
export function rootOf(adapters: OnboardAdapters): string {
|
|
@@ -157,6 +160,12 @@ export function daemonExecArgs(root: string, argv: readonly string[]): string[]
|
|
|
157
160
|
return composeArgs(root, ["exec", "-T", DAEMON_SERVICE, ...argv]);
|
|
158
161
|
}
|
|
159
162
|
|
|
163
|
+
/** The same exec as uid 0 — the operator seal on `commands/operator/`, which
|
|
164
|
+
* the daemon's own uid (every session's) can read but not write. */
|
|
165
|
+
export function daemonRootExecArgs(root: string, argv: readonly string[]): string[] {
|
|
166
|
+
return composeArgs(root, ["exec", "-T", "-u", "0", DAEMON_SERVICE, ...argv]);
|
|
167
|
+
}
|
|
168
|
+
|
|
160
169
|
export async function daemonExec(
|
|
161
170
|
runner: ProcessRunner,
|
|
162
171
|
root: string,
|
|
@@ -172,9 +181,31 @@ export interface PsReport {
|
|
|
172
181
|
detail: string;
|
|
173
182
|
}
|
|
174
183
|
|
|
184
|
+
/** docker-compose.yml's `name:` — the project label on its containers. */
|
|
185
|
+
export const COMPOSE_PROJECT = "quickreview";
|
|
186
|
+
|
|
187
|
+
/** `docker ps` over the compose project label, one compose-ps-shaped JSON row
|
|
188
|
+
* per running container: asks Docker without reading the compose file. */
|
|
189
|
+
export function projectPsArgs(): string[] {
|
|
190
|
+
return [
|
|
191
|
+
"ps",
|
|
192
|
+
"--filter",
|
|
193
|
+
`label=com.docker.compose.project=${COMPOSE_PROJECT}`,
|
|
194
|
+
"--format",
|
|
195
|
+
'{"Service":"{{.Label "com.docker.compose.service"}}","State":"{{.State}}"}',
|
|
196
|
+
];
|
|
197
|
+
}
|
|
198
|
+
|
|
175
199
|
export async function composePs(runner: ProcessRunner, root: string): Promise<PsReport> {
|
|
176
200
|
const ps = await runner.run("docker", composeArgs(root, ["ps", "--format", "json"]));
|
|
177
201
|
if (ps.code !== 0) {
|
|
202
|
+
// `docker compose ps` interpolates the compose file first, and before the
|
|
203
|
+
// bring-up has written the project .env (QCR_SECRETS_DIR and the rest) it
|
|
204
|
+
// refuses to run at all. That is a question about the file, not the
|
|
205
|
+
// stack: Docker itself still answers which of the project's containers
|
|
206
|
+
// run. Only when Docker cannot answer either is the state unknown.
|
|
207
|
+
const plain = await runner.run("docker", projectPsArgs());
|
|
208
|
+
if (plain.code === 0) return { ok: true, rows: parseComposePs(plain.stdout), detail: "" };
|
|
178
209
|
return {
|
|
179
210
|
ok: false,
|
|
180
211
|
rows: [],
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
type ChoiceName,
|
|
64
64
|
botLoginFor,
|
|
65
65
|
ingressChoiceOf,
|
|
66
|
+
userAuthRecorded,
|
|
66
67
|
type IngressChoice,
|
|
67
68
|
} from "../choices.js";
|
|
68
69
|
import {
|
|
@@ -76,8 +77,8 @@ import {
|
|
|
76
77
|
} from "../engine.js";
|
|
77
78
|
import { deliverConfigChange, configDeliveryChecks } from "./configdelivery.js";
|
|
78
79
|
import type { TransportOptions } from "./transport.js";
|
|
79
|
-
import { BARE_HOSTNAME_RE, readTomlKey, secretsDirFor } from "./ingress.js";
|
|
80
|
-
import { SSH_ALIAS_RE } from "./topology.js";
|
|
80
|
+
import { BARE_HOSTNAME_RE, CONTAINER_STATE_DIR, readTomlKey, secretsDirFor } from "./ingress.js";
|
|
81
|
+
import { SSH_ALIAS_RE, topologyOf, type Topology } from "./topology.js";
|
|
81
82
|
|
|
82
83
|
export const CONFIG_FILL_STEP_ID = "config_fill";
|
|
83
84
|
|
|
@@ -120,9 +121,12 @@ function escapeRe(s: string): string {
|
|
|
120
121
|
* marker in place — the EXPLANATION after it is the part worth keeping. */
|
|
121
122
|
export function rewriteFillMarker(comment: string): string {
|
|
122
123
|
if (!/←\s*FILL/.test(comment)) return comment;
|
|
123
|
-
return comment.replace(/←\s*FILL(\s*\(\d+\))?\s*:?\s*/, "filled by qcr
|
|
124
|
+
return comment.replace(/←\s*FILL(\s*\(\d+\))?\s*:?\s*/, "filled by qcr: ");
|
|
124
125
|
}
|
|
125
126
|
|
|
127
|
+
/** A line without the CR of its CRLF ending. */
|
|
128
|
+
const bare = (line: string): string => line.replace(/\r$/, "");
|
|
129
|
+
|
|
126
130
|
function sectionAt(lines: string[]): string[] {
|
|
127
131
|
const out: string[] = [];
|
|
128
132
|
let cur = "";
|
|
@@ -134,10 +138,12 @@ function sectionAt(lines: string[]): string[] {
|
|
|
134
138
|
if (splitTail(continuation) !== null) continuation = null;
|
|
135
139
|
continue;
|
|
136
140
|
}
|
|
137
|
-
const m = HEADER_RE.exec(line);
|
|
141
|
+
const m = HEADER_RE.exec(bare(line));
|
|
138
142
|
if (m) cur = m[1]!.trim();
|
|
139
143
|
out.push(cur);
|
|
140
|
-
const assignment = /^\s*(?:"(?:[^"\\]|\\.)*"|'[^']*'|[A-Za-z0-9_-]+)\s*=\s*(.*)$/.exec(
|
|
144
|
+
const assignment = /^\s*(?:"(?:[^"\\]|\\.)*"|'[^']*'|[A-Za-z0-9_-]+)\s*=\s*(.*)$/.exec(
|
|
145
|
+
bare(line),
|
|
146
|
+
);
|
|
141
147
|
if (assignment && splitTail(assignment[1]!) === null) continuation = assignment[1]!;
|
|
142
148
|
}
|
|
143
149
|
return out;
|
|
@@ -148,9 +154,18 @@ function sectionAt(lines: string[]): string[] {
|
|
|
148
154
|
* key order. An existing assignment has only its VALUE replaced (its trailing
|
|
149
155
|
* comment survives, with a spent `← FILL` marker rewritten); a commented-out
|
|
150
156
|
* assignment is uncommented in place; a key absent from its section is appended
|
|
151
|
-
* to the end of that section; a missing section is appended at EOF.
|
|
157
|
+
* to the end of that section; a missing section is appended at EOF. Line
|
|
158
|
+
* endings survive too: a CRLF file is patched as LF and given its CRs back, so
|
|
159
|
+
* an edited or added line ends the way every other line does, and in a file of
|
|
160
|
+
* mixed endings the edited line keeps its own.
|
|
152
161
|
*/
|
|
153
162
|
export function patchToml(text: string, edits: readonly TomlEdit[]): string {
|
|
163
|
+
if (text.includes("\r\n") && !/(^|[^\r])\n/.test(text))
|
|
164
|
+
return patchLines(text.replace(/\r\n/g, "\n"), edits).replace(/\n/g, "\r\n");
|
|
165
|
+
return patchLines(text, edits);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function patchLines(text: string, edits: readonly TomlEdit[]): string {
|
|
154
169
|
const lines = text.split("\n");
|
|
155
170
|
for (const edit of edits) {
|
|
156
171
|
const sections = sectionAt(lines);
|
|
@@ -161,7 +176,7 @@ export function patchToml(text: string, edits: readonly TomlEdit[]): string {
|
|
|
161
176
|
for (const re of [live, commented]) {
|
|
162
177
|
for (let i = 0; i < lines.length && !applied; i++) {
|
|
163
178
|
if (sections[i] !== edit.section) continue;
|
|
164
|
-
const m = re.exec(lines[i]!);
|
|
179
|
+
const m = re.exec(bare(lines[i]!));
|
|
165
180
|
if (!m) continue;
|
|
166
181
|
try {
|
|
167
182
|
if (!Object.hasOwn(parseToml(`${m[2]} = 0`), edit.key)) continue;
|
|
@@ -170,11 +185,13 @@ export function patchToml(text: string, edits: readonly TomlEdit[]): string {
|
|
|
170
185
|
}
|
|
171
186
|
let end = i;
|
|
172
187
|
let tail = m[4]!;
|
|
173
|
-
while (splitTail(tail) === null && end + 1 < lines.length)
|
|
188
|
+
while (splitTail(tail) === null && end + 1 < lines.length)
|
|
189
|
+
tail += "\n" + bare(lines[++end]!);
|
|
174
190
|
const parts = splitTail(tail);
|
|
175
191
|
if (!parts) throw new Error(`cannot patch unterminated TOML assignment ${edit.key}`);
|
|
176
192
|
const comment = parts.comment ? `${parts.gap}${rewriteFillMarker(parts.comment)}` : "";
|
|
177
|
-
lines
|
|
193
|
+
const cr = lines[end]!.endsWith("\r") ? "\r" : "";
|
|
194
|
+
lines.splice(i, end - i + 1, `${m[1]}${m[2]}${m[3]}${edit.value}${comment}${cr}`);
|
|
178
195
|
applied = true;
|
|
179
196
|
}
|
|
180
197
|
if (applied) break;
|
|
@@ -228,9 +245,17 @@ export interface FillFacts {
|
|
|
228
245
|
secrets_dir: string;
|
|
229
246
|
topology: string;
|
|
230
247
|
ingress: string;
|
|
248
|
+
/** The GitHub route the github_account step recorded ("user" | "app"), ""
|
|
249
|
+
* while unanswered — which is the App route's interview. */
|
|
250
|
+
github_auth?: string;
|
|
251
|
+
/** The person's own login on the "user" route (`GET /user`). */
|
|
252
|
+
account_login?: string;
|
|
231
253
|
}
|
|
232
254
|
|
|
233
|
-
export type AnswerKey = Exclude<
|
|
255
|
+
export type AnswerKey = Exclude<
|
|
256
|
+
keyof FillFacts,
|
|
257
|
+
"secrets_dir" | "topology" | "ingress" | "github_auth" | "account_login"
|
|
258
|
+
>;
|
|
234
259
|
|
|
235
260
|
export interface Question {
|
|
236
261
|
id: AnswerKey;
|
|
@@ -282,7 +307,9 @@ export const QUESTIONS: readonly Question[] = [
|
|
|
282
307
|
"clone directory, backfill identity — is derived from this one answer.",
|
|
283
308
|
prompt: 'Which repository should the reviewer watch? ("owner/name")',
|
|
284
309
|
optional: false,
|
|
285
|
-
|
|
310
|
+
// On the own-account route the github_account step already asked, from
|
|
311
|
+
// the repos the person's account reaches.
|
|
312
|
+
from: [CHOICE_KEYS.accountRepo, CHOICE_KEYS.repo],
|
|
286
313
|
read: (cfg) => cfg.github.repo,
|
|
287
314
|
validate: (v) =>
|
|
288
315
|
REPO_SLUG_RE.test(v)
|
|
@@ -298,8 +325,10 @@ export const QUESTIONS: readonly Question[] = [
|
|
|
298
325
|
"The companion — the local pi that sits beside the TUI — reads the code a review is about. Your checkout is " +
|
|
299
326
|
"mounted READ-ONLY into its container: it can read every file and change none of them. A missing checkout only " +
|
|
300
327
|
"makes the companion less informed; it never breaks the reviewer.",
|
|
301
|
-
prompt:
|
|
302
|
-
|
|
328
|
+
prompt:
|
|
329
|
+
"Where is your local checkout of that repository? (Enter if there is none here — the companion starts without it)",
|
|
330
|
+
// A fresh box has no checkout, and the daemon clones the repository itself.
|
|
331
|
+
optional: true,
|
|
303
332
|
from: [CHOICE_KEYS.repoDir],
|
|
304
333
|
read: (cfg) => cfg.companion.reviewed_repo_dir,
|
|
305
334
|
validate: (v) => {
|
|
@@ -325,6 +354,8 @@ export const QUESTIONS: readonly Question[] = [
|
|
|
325
354
|
prompt: "What is your GitHub App's slug?",
|
|
326
355
|
optional: false,
|
|
327
356
|
from: [CHOICE_KEYS.appSlug],
|
|
357
|
+
// No App exists on the own-account route: `[github] app_slug` stays "".
|
|
358
|
+
asked: (choices) => !userAuthRecorded(choices),
|
|
328
359
|
read: (cfg) => cfg.github.app_slug,
|
|
329
360
|
validate: (v) =>
|
|
330
361
|
SLUG_RE.test(v)
|
|
@@ -390,7 +421,7 @@ export const QUESTIONS: readonly Question[] = [
|
|
|
390
421
|
"It is never used to authenticate anything — the App credential is the only identity that acts.",
|
|
391
422
|
prompt: "What is your GitHub login? (Enter to skip)",
|
|
392
423
|
optional: true,
|
|
393
|
-
from: [CHOICE_KEYS.ownerLogin],
|
|
424
|
+
from: [CHOICE_KEYS.accountLogin, CHOICE_KEYS.ownerLogin],
|
|
394
425
|
read: (cfg) => cfg.owner.github_login,
|
|
395
426
|
validate: validateGithubLogin,
|
|
396
427
|
},
|
|
@@ -493,27 +524,51 @@ export interface Derivable {
|
|
|
493
524
|
holds(cfg: Config, facts: FillFacts): string | null;
|
|
494
525
|
}
|
|
495
526
|
|
|
496
|
-
/** The
|
|
497
|
-
|
|
498
|
-
|
|
527
|
+
/** The topology a fill is for: the recorded one, and "local" while none is
|
|
528
|
+
* recorded — `topologyOf`'s reading, the one every other step uses. */
|
|
529
|
+
function fillTopology(topology: string): Topology {
|
|
530
|
+
return topologyOf({ [CHOICE_KEYS.topology]: topology });
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/** The TUI transport a topology implies (an unrecorded one is local). */
|
|
534
|
+
function tuiTargetFor(topology: string): "local" | "ssh" {
|
|
535
|
+
return fillTopology(topology) === "vm" ? "ssh" : "local";
|
|
499
536
|
}
|
|
500
537
|
|
|
538
|
+
/** The release image's state dir inside the compose daemon container (the
|
|
539
|
+
* `qcr-state` volume), where the local TUI reads status.json. */
|
|
540
|
+
const LOCAL_TUI_STATE_DIR = CONTAINER_STATE_DIR;
|
|
541
|
+
|
|
501
542
|
export const DERIVABLES: readonly Derivable[] = [
|
|
502
543
|
{
|
|
503
544
|
id: "bot_login",
|
|
504
545
|
path: "[github] bot_login",
|
|
505
546
|
explain:
|
|
506
|
-
"the bot login is the App slug plus the [bot] suffix — asking for it twice is how the two drift apart"
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
547
|
+
"the bot login is the App slug plus the [bot] suffix — asking for it twice is how the two drift apart. On your own " +
|
|
548
|
+
"GitHub account it is your login: the reviews are posted as you",
|
|
549
|
+
write: (f) =>
|
|
550
|
+
f.github_auth === "user"
|
|
551
|
+
? f.account_login
|
|
552
|
+
? { section: "github", key: "bot_login", value: tomlString(f.account_login) }
|
|
553
|
+
: null
|
|
554
|
+
: {
|
|
555
|
+
section: "github",
|
|
556
|
+
key: "bot_login",
|
|
557
|
+
value: tomlString(botLoginFor(f.app_slug)),
|
|
558
|
+
},
|
|
512
559
|
stable: true,
|
|
513
|
-
holds: (cfg) =>
|
|
514
|
-
|
|
560
|
+
holds: (cfg, f) => {
|
|
561
|
+
if (f.github_auth === "user") {
|
|
562
|
+
if (!cfg.github.bot_login.trim())
|
|
563
|
+
return "[github] bot_login is empty — on your own account it is your GitHub login; run the github_account step";
|
|
564
|
+
return f.account_login && cfg.github.bot_login !== f.account_login
|
|
565
|
+
? `[github] bot_login is "${cfg.github.bot_login}" but your account is "${f.account_login}" — run the github_account step again`
|
|
566
|
+
: null;
|
|
567
|
+
}
|
|
568
|
+
return cfg.github.bot_login === botLoginFor(cfg.github.app_slug)
|
|
515
569
|
? null
|
|
516
|
-
: `[github] bot_login is "${cfg.github.bot_login}" but the App slug "${cfg.github.app_slug}" implies "${botLoginFor(cfg.github.app_slug)}"
|
|
570
|
+
: `[github] bot_login is "${cfg.github.bot_login}" but the App slug "${cfg.github.app_slug}" implies "${botLoginFor(cfg.github.app_slug)}"`;
|
|
571
|
+
},
|
|
517
572
|
},
|
|
518
573
|
{
|
|
519
574
|
id: "clone_dir",
|
|
@@ -547,7 +602,7 @@ export const DERIVABLES: readonly Derivable[] = [
|
|
|
547
602
|
holds: (cfg) =>
|
|
548
603
|
cfg.github.secrets_dir.trim()
|
|
549
604
|
? null
|
|
550
|
-
: "[github] secrets_dir is empty — the
|
|
605
|
+
: "[github] secrets_dir is empty — the GitHub credential has nowhere to live",
|
|
551
606
|
},
|
|
552
607
|
{
|
|
553
608
|
id: "review_team",
|
|
@@ -588,10 +643,12 @@ export const DERIVABLES: readonly Derivable[] = [
|
|
|
588
643
|
"the history importer's identity and labels cascade off [github] — never a second copy to keep in sync",
|
|
589
644
|
write: () => null,
|
|
590
645
|
stable: true,
|
|
591
|
-
holds: (cfg) => {
|
|
646
|
+
holds: (cfg, f) => {
|
|
592
647
|
if (cfg.backfill.bot_login !== cfg.github.bot_login)
|
|
593
648
|
return "[backfill] bot_login no longer follows [github] bot_login";
|
|
594
|
-
|
|
649
|
+
// The actor is the App slug; the own-account route has no App, and the
|
|
650
|
+
// loader decides what stands in for it there.
|
|
651
|
+
if (f.github_auth !== "user" && cfg.backfill.bot_actor !== cfg.github.app_slug)
|
|
595
652
|
return "[backfill] bot_actor no longer follows [github] app_slug";
|
|
596
653
|
if (cfg.backfill.trigger_label !== cfg.github.trigger_label)
|
|
597
654
|
return "[backfill] trigger_label no longer follows [github] trigger_label";
|
|
@@ -615,15 +672,12 @@ export const DERIVABLES: readonly Derivable[] = [
|
|
|
615
672
|
path: "[tui] target",
|
|
616
673
|
explain:
|
|
617
674
|
'follows the recorded topology: "local" when the daemon runs on this machine (the TUI talks to local Docker), "ssh" on the VM route',
|
|
618
|
-
write: (f) => {
|
|
619
|
-
const target = tuiTargetFor(f.topology);
|
|
620
|
-
return target ? { section: "tui", key: "target", value: tomlString(target) } : null;
|
|
621
|
-
},
|
|
675
|
+
write: (f) => ({ section: "tui", key: "target", value: tomlString(tuiTargetFor(f.topology)) }),
|
|
622
676
|
stable: true,
|
|
623
677
|
holds: (cfg, f) => {
|
|
624
678
|
const want = tuiTargetFor(f.topology);
|
|
625
|
-
return
|
|
626
|
-
? `[tui] target = "${cfg.tui.target}", but the
|
|
679
|
+
return cfg.tui.target !== want
|
|
680
|
+
? `[tui] target = "${cfg.tui.target}", but the topology is ${f.topology || "local (none recorded)"} — the TUI would ` +
|
|
627
681
|
`${want === "local" ? "look for the daemon over ssh" : "look for the daemon in local Docker"}. ` +
|
|
628
682
|
`Fix: run this step again (it writes target = "${want}")`
|
|
629
683
|
: null;
|
|
@@ -635,7 +689,8 @@ export const DERIVABLES: readonly Derivable[] = [
|
|
|
635
689
|
explain:
|
|
636
690
|
"the bundled local Compose project runs service daemon as quickreview-daemon-1; preserve an operator's custom container",
|
|
637
691
|
write: (f, fresh, existing) =>
|
|
638
|
-
f.topology === "local" &&
|
|
692
|
+
fillTopology(f.topology) === "local" &&
|
|
693
|
+
(fresh || existing?.tui.container === TUI_DEFAULTS.container)
|
|
639
694
|
? { section: "tui", key: "container", value: tomlString("quickreview-daemon-1") }
|
|
640
695
|
: null,
|
|
641
696
|
stable: false,
|
|
@@ -647,12 +702,41 @@ export const DERIVABLES: readonly Derivable[] = [
|
|
|
647
702
|
explain:
|
|
648
703
|
"the bundled local Compose project runs the memory sidecar as quickreview-memory-1, where the memory forward must relay; preserve an operator's custom container",
|
|
649
704
|
write: (f, fresh, existing) =>
|
|
650
|
-
f.topology === "local" &&
|
|
705
|
+
fillTopology(f.topology) === "local" &&
|
|
706
|
+
(fresh || (existing?.tui.memory_container ?? "") === "")
|
|
651
707
|
? { section: "tui", key: "memory_container", value: tomlString("quickreview-memory-1") }
|
|
652
708
|
: null,
|
|
653
709
|
stable: false,
|
|
654
710
|
holds: () => null,
|
|
655
711
|
},
|
|
712
|
+
{
|
|
713
|
+
id: "tui_remote_state_dir",
|
|
714
|
+
path: "[tui] remote_state_dir",
|
|
715
|
+
explain:
|
|
716
|
+
`on this machine the TUI reads status.json inside the daemon container, where the release image keeps its state (${LOCAL_TUI_STATE_DIR}, ` +
|
|
717
|
+
"the compose state volume) — the shipped default is the VM host's path; preserve an operator's custom path",
|
|
718
|
+
write: (f, fresh, existing) =>
|
|
719
|
+
fillTopology(f.topology) === "local" &&
|
|
720
|
+
(fresh || existing?.tui.remote_state_dir === TUI_DEFAULTS.remote_state_dir)
|
|
721
|
+
? { section: "tui", key: "remote_state_dir", value: tomlString(LOCAL_TUI_STATE_DIR) }
|
|
722
|
+
: null,
|
|
723
|
+
stable: false,
|
|
724
|
+
holds: () => null,
|
|
725
|
+
},
|
|
726
|
+
{
|
|
727
|
+
id: "tui_sudo_docker",
|
|
728
|
+
path: "[tui] sudo_docker",
|
|
729
|
+
explain:
|
|
730
|
+
"off on this machine: the wizard's own bring-up drives docker without sudo, so the TUI does too (a sudo password " +
|
|
731
|
+
"prompt behind the TUI's screen can only fail); on the VM route sudo stays the shipped default",
|
|
732
|
+
write: (f, fresh, existing) =>
|
|
733
|
+
fillTopology(f.topology) === "local" &&
|
|
734
|
+
(fresh || existing?.tui.sudo_docker === TUI_DEFAULTS.sudo_docker)
|
|
735
|
+
? { section: "tui", key: "sudo_docker", value: "false" }
|
|
736
|
+
: null,
|
|
737
|
+
stable: false,
|
|
738
|
+
holds: () => null,
|
|
739
|
+
},
|
|
656
740
|
{
|
|
657
741
|
id: "tui_ssh_host",
|
|
658
742
|
path: "[tui] ssh_host",
|
|
@@ -729,6 +813,9 @@ export const DEFAULT_SECRETS_DIR = "";
|
|
|
729
813
|
* Read from ITS artefacts (the `deploy_shape` marker it writes) so this step
|
|
730
814
|
* reports the same required set without duplicating the wizard's validators. */
|
|
731
815
|
export const REQUIRED_SECRETS: readonly string[] = ["app_id", "app.pem", "webhook_secret"];
|
|
816
|
+
/** The own-account route's one secret: the person's token, written by
|
|
817
|
+
* `qcr github-token sync` (the github_account step runs it). */
|
|
818
|
+
export const USER_ROUTE_SECRETS: readonly string[] = ["github_token"];
|
|
732
819
|
export const TUNNEL_SHAPE_SECRET = "tunnel_token";
|
|
733
820
|
|
|
734
821
|
/** Unlike `readTextOrNull`, only ABSENCE is null: a file that exists and
|
|
@@ -918,6 +1005,8 @@ export async function collectAnswers(
|
|
|
918
1005
|
DEFAULT_SECRETS_DIR,
|
|
919
1006
|
topology: str(choices, CHOICE_KEYS.topology),
|
|
920
1007
|
ingress: str(choices, CHOICE_KEYS.ingress),
|
|
1008
|
+
github_auth: str(choices, CHOICE_KEYS.githubAuth),
|
|
1009
|
+
account_login: str(choices, CHOICE_KEYS.accountLogin),
|
|
921
1010
|
};
|
|
922
1011
|
return { facts, missing, rejected, asked, ignored };
|
|
923
1012
|
}
|
|
@@ -992,7 +1081,17 @@ export function changedEdits(text: string, edits: readonly TomlEdit[]): TomlEdit
|
|
|
992
1081
|
}
|
|
993
1082
|
|
|
994
1083
|
/** What the secrets dir holds, at the one resolution every step uses. */
|
|
995
|
-
function secretsReport(dir: string): CheckResult {
|
|
1084
|
+
function secretsReport(dir: string, userRoute: boolean): CheckResult {
|
|
1085
|
+
if (userRoute) {
|
|
1086
|
+
const missing = USER_ROUTE_SECRETS.filter((f) => !existsSync(join(dir, f)));
|
|
1087
|
+
return {
|
|
1088
|
+
name: "secrets",
|
|
1089
|
+
ok: true,
|
|
1090
|
+
detail: missing.length
|
|
1091
|
+
? `${dir}: still missing ${missing.join(", ")} — the github_account step writes it from your GitHub sign-in (no App secrets on this route)`
|
|
1092
|
+
: `${dir}: your GitHub token is present — the own-account route needs no App secrets`,
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
996
1095
|
if (!existsSync(dir)) {
|
|
997
1096
|
return {
|
|
998
1097
|
name: "secrets",
|
|
@@ -1221,11 +1320,14 @@ export function configFillStep(opts: { transport?: TransportOptions } = {}): Onb
|
|
|
1221
1320
|
ok: true,
|
|
1222
1321
|
detail:
|
|
1223
1322
|
`topology ${facts.topology || "(unrecorded — filled for a daemon on this machine, so [tui] ssh_host stays empty)"}, ` +
|
|
1224
|
-
`ingress ${facts.ingress || "(unrecorded — filled for an ingress that assigns its own hostname, so [server] hostname stays empty)"}` +
|
|
1323
|
+
`ingress ${facts.ingress || "(unrecorded — filled for an ingress that assigns its own hostname, so [server] hostname stays empty)"}, ` +
|
|
1324
|
+
`github ${facts.github_auth === "user" ? "own account (no App questions, no App secrets)" : "App"}` +
|
|
1225
1325
|
`${str(ctx.choices, CHOICE_KEYS.authRoute) ? `, auth route ${str(ctx.choices, CHOICE_KEYS.authRoute)}` : ""}`,
|
|
1226
1326
|
});
|
|
1227
1327
|
// Read after the write, so the dir is the one the written config names.
|
|
1228
|
-
checks.push(
|
|
1328
|
+
checks.push(
|
|
1329
|
+
secretsReport(secretsDirFor(ctx.adapters, ctx.choices), userAuthRecorded(ctx.choices)),
|
|
1330
|
+
);
|
|
1229
1331
|
|
|
1230
1332
|
const ok = checks.every((c) => c.ok);
|
|
1231
1333
|
if (ok) recordChoices(ctx, facts, configPath, parsed);
|
|
@@ -1320,6 +1422,8 @@ export function configFillStep(opts: { transport?: TransportOptions } = {}): Onb
|
|
|
1320
1422
|
secrets_dir: cfg.github.secrets_dir,
|
|
1321
1423
|
topology: str(ctx.choices, CHOICE_KEYS.topology),
|
|
1322
1424
|
ingress: str(ctx.choices, CHOICE_KEYS.ingress),
|
|
1425
|
+
github_auth: str(ctx.choices, CHOICE_KEYS.githubAuth),
|
|
1426
|
+
account_login: str(ctx.choices, CHOICE_KEYS.accountLogin),
|
|
1323
1427
|
};
|
|
1324
1428
|
for (const d of DERIVABLES) {
|
|
1325
1429
|
if (!d.stable) continue;
|