[{"data":1,"prerenderedAt":32},["ShallowReactive",2],{"doc-github":3},{"html":4,"headings":5},"\u003Cp>A workspace connects its GitHub accounts and organisations once; each project\nthen picks the repos it uses. AI error notes and legal documents can read those\nrepos (the legal wizard's \u003Cem>Suggest from my repos\u003C\u002Fem> reads the file list and dependency manifests; see \u003Ca href=\"\u002Fdocs\u002Flegal\">LEGAL.md\u003C\u002Fa>). HelpBites only ever reads them: the app asks for read-only access.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>In the panel\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Col>\n\u003Cli>Settings → \u003Cstrong>GitHub\u003C\u002Fstrong> → \u003Cem>Connect GitHub\u003C\u002Fem>. Install the app on your account or\norganisation and choose which repos it may see (all, or only some).\u003C\u002Fli>\n\u003Cli>Project → Settings → \u003Cstrong>GitHub repos\u003C\u002Fstrong>: pick the repos this project uses (up\nto 10, from any connected account).\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>\u003Cstrong>What reads them.\u003C\u002Fstrong> AI error notes (\u003Ca href=\"\u002Fdocs\u002Ferrors\">ERRORS.md\u003C\u002Fa>): when an error\narrives, HelpBites lists each repo's files at its default branch, matches the\nstack-trace paths by path suffix (a path must match exactly one file), and reads\nup to 3 of them (100 KB max each; the prompt gets about 80 lines around the\nfailing line). The text goes to the AI as untrusted data. Nothing is stored,\nand failures (no repos, GitHub not set up, a repo that is gone) skip silently.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Changelog from commits.\u003C\u002Fstrong> \u003Cem>Changelog → From commits\u003C\u002Fem> reads the repos' commit messages (newest\n300 per repo, default branch) and has the AI draft changelog entries; see \u003Ca href=\"\u002Fdocs\u002Ffeedback\">FEEDBACK.md\u003C\u002Fa>.\nTo draft entries automatically on every push, turn the app's webhook on (below). Only the push's\ncommit messages are used, and they go to the AI as untrusted data.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>\u003Ccode>#12\u003C\u002Fcode> in commits and pull requests.\u003C\u002Fstrong> With the webhook on, what you write on GitHub links back to the\nboard. A commit pushed to the default branch, or a pull request merged into it, that mentions \u003Ccode>#12\u003C\u002Fcode> in its\ncommit message, pull request title or description, or branch name is shown on that item (the board item's\ndrawer and the feedback post's editor list \u003Cem>Commits and pull requests\u003C\u002Fem>). A closing keyword right before the\nnumber (\u003Ccode>close\u003C\u002Fcode>, \u003Ccode>closes\u003C\u002Fcode>, \u003Ccode>closed\u003C\u002Fcode>, \u003Ccode>fix\u003C\u002Fcode>, \u003Ccode>fixes\u003C\u002Fcode>, \u003Ccode>fixed\u003C\u002Fcode>, \u003Ccode>resolve\u003C\u002Fcode>, \u003Ccode>resolves\u003C\u002Fcode>, \u003Ccode>resolved\u003C\u002Fcode>) also moves\nthe board item to the board's first \u003Cem>done\u003C\u002Fem> status: through the same path as dragging the card, so linked\nposts follow if the board syncs them, their followers are emailed, and a changelog draft appears if the\nproject drafts entries for finished work. The move is made as &quot;GitHub&quot;. An item that is already done or\ncanceled is left alone, and nothing is ever moved back.\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Which item \u003Ccode>#12\u003C\u002Fcode> means.\u003C\u002Fstrong> The board item numbered 12 when the project's board is on and has one, else\nthe feedback post numbered 12, else nothing. Say which in your message by numbering carefully; the board\nand the feedback board count separately.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>What is not a reference.\u003C\u002Fstrong> Code spans and fenced blocks, links, \u003Ccode>owner\u002Frepo#12\u003C\u002Fcode> (an issue in another\nrepository), numbers of six digits or more (colours), and in a commit message the pull request number GitHub\nitself adds: a squash commit's trailing \u003Ccode>(#34)\u003C\u002Fcode> and \u003Ccode>Merge pull request #34 from …\u003C\u002Fcode>. The pull request's own\nnumber in its title or description is ignored too. A branch name counts as \u003Ccode>fix\u002F12-login\u003C\u002Fcode>,\n\u003Ccode>feature\u002F42-widget\u003C\u002Fcode>, \u003Ccode>issue-12\u003C\u002Fcode>, \u003Ccode>gh-12\u003C\u002Fcode> or \u003Ccode>#12\u003C\u002Fcode>, never as a closing keyword.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>What a keyword closes.\u003C\u002Fstrong> Only a keyword directly before the number: \u003Ccode>fixes #12, #13\u003C\u002Fcode> closes 12 and\nmerely mentions 13. A keyword before a feedback post's number is recorded (\u003Cem>closes\u003C\u002Fem>) but changes nothing:\nonly board items move.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Stored once.\u003C\u002Fstrong> Each commit or pull request is stored once per item (a redelivery changes nothing);\n\u003Ccode>GET \u002Fv1\u002Fadmin\u002Fgithub-refs?project=&lt;id&gt;&amp;kind=board|feedback&amp;id=&lt;item or post&gt;\u003C\u002Fcode> lists them. They are\nrebuilt from new pushes, not carried by an export or transfer.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Events.\u003C\u002Fstrong> \u003Ccode>github.commit.referenced\u003C\u002Fcode> for each new commit link and \u003Ccode>github.pull_request.merged\u003C\u002Fcode> for each\nmerged pull request (\u003Ca href=\"\u002Fdocs\u002Fevents\">EVENTS.md\u003C\u002Fa>).\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Changing which repos the app can see happens on GitHub (the app's installation\nsettings); the lists here are read live. \u003Cem>Disconnect\u003C\u002Fem> only forgets the link in\nHelpBites; uninstall the app on GitHub to revoke access there too. A connection\ncan't be disconnected while a project uses its repos.\u003C\u002Fp>\n\u003Ch2 id=\"registering-the-github-app-server-owner-once\">Registering the GitHub App (server owner, once)\u003Ca class=\"heading-anchor\" href=\"#registering-the-github-app-server-owner-once\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>Do this once per server, on the GitHub account that should own the app. Replace \u003Ccode>https:\u002F\u002Fhelpbites.app\u003C\u002Fcode> with\nyour \u003Ccode>APP_URL\u003C\u002Fcode> everywhere below. It takes about five minutes.\u003C\u002Fp>\n\u003Ch3 id=\"1-create-the-app\">1. Create the app\u003Ca class=\"heading-anchor\" href=\"#1-create-the-app\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh3>\n\u003Cp>GitHub → your avatar → \u003Cstrong>Settings\u003C\u002Fstrong> → \u003Cstrong>Developer settings\u003C\u002Fstrong> → \u003Cstrong>GitHub Apps\u003C\u002Fstrong> → \u003Cstrong>New GitHub App\u003C\u002Fstrong>. Give it a name\n(it becomes the slug in \u003Ccode>github.com\u002Fapps\u002F&lt;slug&gt;\u003C\u002Fcode>) and fill in:\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs-img\u002Fgithub\u002Fapp-urls.webp\" alt=\"The app's URL fields: homepage, callback URL and Request user authorization ticked\">\u003C\u002Fp>\n\u003Cdiv class=\"table-wrap\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Field\u003C\u002Fth>\n\u003Cth>Value\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>Homepage URL\u003C\u002Ftd>\n\u003Ctd>your \u003Ccode>APP_URL\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Callback URL\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>&lt;APP_URL&gt;\u002Fv1\u002Fgithub\u002Fcallback\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Request user authorization (OAuth) during installation\u003C\u002Ftd>\n\u003Ctd>\u003Cstrong>tick it\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Setup URL\u003C\u002Ftd>\n\u003Ctd>greyed out while the box above is ticked; GitHub uses the callback URL instead\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Enable Device Flow\u003C\u002Ftd>\n\u003Ctd>leave off\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Ch3 id=\"2-turn-the-webhook-on\">2. Turn the webhook on\u003Ca class=\"heading-anchor\" href=\"#2-turn-the-webhook-on\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh3>\n\u003Cp>The webhook is optional, but it is what drafts changelog entries from pushes and links \u003Ccode>#12\u003C\u002Fcode> in commits and pull\nrequests to the board. Without it the rest of the connection still works.\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs-img\u002Fgithub\u002Fwebhook.webp\" alt=\"The webhook section: Active ticked, the webhook URL and a secret\">\u003C\u002Fp>\n\u003Cp>Tick \u003Cstrong>Active\u003C\u002Fstrong>, set \u003Cem>Webhook URL\u003C\u002Fem> to \u003Ccode>&lt;APP_URL&gt;\u002Fv1\u002Fwebhooks\u002Fgithub\u003C\u002Fcode> and invent a \u003Cem>Secret\u003C\u002Fem> (for example\n\u003Ccode>openssl rand -hex 32\u003C\u002Fcode>). Keep it: it becomes \u003Ccode>GITHUB_APP_WEBHOOK_SECRET\u003C\u002Fcode>. Leave \u003Cem>Enable SSL verification\u003C\u002Fem> on.\u003C\u002Fp>\n\u003Ch3 id=\"3-give-it-read-only-access\">3. Give it read-only access\u003Ca class=\"heading-anchor\" href=\"#3-give-it-read-only-access\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh3>\n\u003Cp>Open \u003Cstrong>Permissions &amp; events\u003C\u002Fstrong> (on the new-app form it is the same section) → \u003Cstrong>Repository permissions\u003C\u002Fstrong> and set:\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs-img\u002Fgithub\u002Fpermission-contents.webp\" alt=\"Contents set to Read-only\">\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs-img\u002Fgithub\u002Fpermission-pull-requests.webp\" alt=\"Pull requests set to Read-only from the Access dropdown\">\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Contents\u003C\u002Fstrong>: Read-only (file lists, dependency manifests, commit messages).\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Pull requests\u003C\u002Fstrong>: Read-only. HelpBites never reads pull requests through the API; the permission only exists so\nGitHub will deliver the pull request event.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Metadata\u003C\u002Fstrong>: Read-only is added for you and cannot be changed.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Everything else stays \u003Cem>No access\u003C\u002Fem>. Setting a permission is what reveals the event checkboxes below it. Under\n\u003Cstrong>Subscribe to events\u003C\u002Fstrong> tick \u003Cstrong>Pull request\u003C\u002Fstrong> and \u003Cstrong>Push\u003C\u002Fstrong>:\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs-img\u002Fgithub\u002Fevents.webp\" alt=\"The Pull request and Push events ticked\">\u003C\u002Fp>\n\u003Ch3 id=\"4-who-can-install-it\">4. Who can install it\u003Ca class=\"heading-anchor\" href=\"#4-who-can-install-it\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh3>\n\u003Cp>At the bottom of the form, \u003Cem>Where can this app be installed?\u003C\u002Fem>: \u003Cstrong>Any account\u003C\u002Fstrong> if your users connect their own\nGitHub (a public service), \u003Cstrong>Only on this account\u003C\u002Fstrong> if only you do. Then \u003Cstrong>Create GitHub App\u003C\u002Fstrong> (or \u003Cstrong>Save changes\u003C\u002Fstrong>\non an existing app).\u003C\u002Fp>\n\u003Ch3 id=\"5-collect-the-credentials\">5. Collect the credentials\u003Ca class=\"heading-anchor\" href=\"#5-collect-the-credentials\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh3>\n\u003Cp>On the app's page, copy the \u003Cstrong>App ID\u003C\u002Fstrong> and \u003Cstrong>Client ID\u003C\u002Fstrong> from the top. Then open \u003Cstrong>Credentials\u003C\u002Fstrong>:\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs-img\u002Fgithub\u002Fcredentials.webp\" alt=\"The Credentials page with the Client secrets and Key pairs tabs\">\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Client secrets\u003C\u002Fstrong> → \u003Cem>New secret\u003C\u002Fem>. GitHub shows it once; copy it now.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Key pairs\u003C\u002Fstrong> → \u003Cem>Generate a private key\u003C\u002Fem>. GitHub downloads a \u003Ccode>.pem\u003C\u002Fcode>; keep it private.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 id=\"6-set-the-environment-variables\">6. Set the environment variables\u003Ca class=\"heading-anchor\" href=\"#6-set-the-environment-variables\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh3>\n\u003Cdiv class=\"code-block\">\u003Cbutton type=\"button\" class=\"copy-btn\" data-copy aria-label=\"Copy to clipboard\">Copy\u003C\u002Fbutton>\u003Cpre class=\"shj-lang-plain\">\u003Ccode>GITHUB_APP_ID=…            # the App ID\nGITHUB_APP_SLUG=…          # the name in github.com\u002Fapps\u002F&lt;slug&gt;\nGITHUB_APP_CLIENT_ID=…\nGITHUB_APP_CLIENT_SECRET=…\nGITHUB_APP_PRIVATE_KEY=…   # the .pem; literal \\n is accepted\nHELPBITES_SECRET=…         # already needed for contacts; signs the install link\nGITHUB_APP_WEBHOOK_SECRET=…  # optional: the webhook's Secret; without it pushes are refused (503)\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\n\u003Cp>Restart the server. Settings → \u003Cstrong>GitHub\u003C\u002Fstrong> now shows \u003Cem>Connect GitHub\u003C\u002Fem> instead of &quot;GitHub isn't set up on this\nserver&quot;. Click it, install the app on your account or organisation and pick the repos it may see.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Upgrading an existing app.\u003C\u002Fstrong> Merged pull requests need the \u003Cem>Pull requests: read-only\u003C\u002Fem> permission and the\n\u003Cem>Pull request\u003C\u002Fem> event, which an app registered before this existed does not have. On GitHub open the app's settings\n(Developer settings → GitHub Apps → your app), add the permission and tick the event; GitHub then asks every\naccount that installed the app to accept the new permission (each owner gets an email and a banner), and the event\nonly arrives for installations that have. Until then nothing breaks: those installations keep working, push\nevents still link commits, and merged pull requests are simply not linked. HelpBites never reads pull requests\nthrough the API, so the permission only exists for GitHub to deliver the event.\u003C\u002Fp>\n\u003Cp>A project is found from a push by the repo ids saved when its repos were picked. Projects whose\nrepos were picked before this existed need their repos saved once more (Project → Settings →\nGitHub repos).\u003C\u002Fp>\n\u003Cp>Until all of these are set, the GitHub tab says it isn't set up.\u003C\u002Fp>\n\u003Ch2 id=\"how-it-is-kept-safe\">How it is kept safe\u003Ca class=\"heading-anchor\" href=\"#how-it-is-kept-safe\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>No GitHub credential is stored. Only the installation id and account name are\nsaved in the workspace; short-lived installation tokens are minted from the\napp's key when needed.\u003C\u002Fli>\n\u003Cli>GitHub returns the browser with an installation id, which anyone could\nforge in a URL. The OAuth code that comes with it is exchanged and the\ninstallation must be on that person's own list, so a workspace can't attach\nan account it doesn't control. The link back is signed, single-purpose and\nexpires after 15 minutes.\u003C\u002Fli>\n\u003Cli>The webhook is accepted only with a valid \u003Ccode>x-hub-signature-256\u003C\u002Fcode> (HMAC-SHA256 of the raw body with\n\u003Ccode>GITHUB_APP_WEBHOOK_SECRET\u003C\u002Fcode>), and each delivery id is acted on once. Pushes and merged pull requests\ncount only on a repo's default branch, and only for projects that picked that repo.\u003C\u002Fli>\n\u003Cli>A repo is saved only if GitHub lists it for that installation, with GitHub's\nown name for it.\u003C\u002Fli>\n\u003C\u002Ful>\n",[6,10,14,17,20,23,26,29],{"id":7,"text":8,"level":9},"registering-the-github-app-server-owner-once","Registering the GitHub App (server owner, once)",2,{"id":11,"text":12,"level":13},"1-create-the-app","1. Create the app",3,{"id":15,"text":16,"level":13},"2-turn-the-webhook-on","2. Turn the webhook on",{"id":18,"text":19,"level":13},"3-give-it-read-only-access","3. Give it read-only access",{"id":21,"text":22,"level":13},"4-who-can-install-it","4. Who can install it",{"id":24,"text":25,"level":13},"5-collect-the-credentials","5. Collect the credentials",{"id":27,"text":28,"level":13},"6-set-the-environment-variables","6. Set the environment variables",{"id":30,"text":31,"level":9},"how-it-is-kept-safe","How it is kept safe",1792766843063]