feat: rename matrix-accounts page to credentials, add github PAT tab

Part 2 of hyperhive#1970 (backend/CLI landed in PR #2378). Renames
/matrix-accounts.html -> /credentials.html and restructures it with a
sub-tab strip (MATRIX / GITHUB), reusing the shared @hive/shared/tabs.js
tab strip already used by /logs.html.

MATRIX tab carries over the existing account list + login form
unchanged. GITHUB tab adds a single-PAT provisioning form: status line
(present/absent, read from GET /api/github-account), a security-warning
banner (dedicated bot account + minimally-scoped token), a link to
generate a PAT at github.com/settings/tokens, and a paste-token form
posting to POST /api/github-account. Both tabs share one agent picker.

Updated docs/web-ui.md + docs/web-ui/dashboard.md to describe the new
page shape, and the H0M3 hub tile (index.html) to point at the renamed
page.
This commit is contained in:
iris 2026-07-11 12:38:47 +02:00
commit 5c2cae41a2
8 changed files with 376 additions and 148 deletions

View file

@ -10,6 +10,8 @@
// state / container load)
// dist/builds.html served at GET /builds.html (BU1LDS:
// rebuild queue / meta inputs / build logs)
// dist/credentials.html served at GET /credentials.html
// (CR3D3NTIALS: matrix + github accounts)
// dist/static/home.js index.html (H0M3) entry — menu tiles +
// matrix-tile gating + identity line
// dist/static/tabs.js dashboard.html entry — tab renderers +
@ -20,7 +22,10 @@
// log viewer sub-tabs
// dist/static/builds.js /builds.html entry — rebuild queue,
// meta inputs, build log history
// dist/static/{home,tabs,flow,logs,builds}.js.map source map siblings
// dist/static/credentials.js /credentials.html entry — matrix +
// github account sub-tabs
// dist/static/{home,tabs,flow,logs,builds,credentials}.js.map source map
// siblings
// dist/static/common.css loaded by every page (@hive/shared
// imports + shared typography/badges/
// buttons/inbox/side-panel)
@ -29,6 +34,8 @@
// dist/static/logs.css /logs.html only (log viewer sub-tabs)
// dist/static/builds.css /builds.html only (build lifecycle hub)
// dist/static/home.css index.html (H0M3) only (tile grid)
// dist/static/credentials.css /credentials.html only (matrix + github
// account forms)
//
// Each JS entry bundles `./common.js` (DOM helpers, Panel singleton,
// NOTIF, path linkification) independently — esbuild inlines the shared
@ -59,7 +66,7 @@ mkdirSync(staticDir(''), { recursive: true });
// follow-up once asset sizes warrant it). esbuild writes each entry
// to `static/<name>.js` based on the entryPoint basename.
await build({
entryPoints: [src('tabs.js'), src('flow.js'), src('logs.js'), src('home.js'), src('settings.js'), src('stats.js'), src('core.js'), src('builds.js'), src('matrix-accounts.js')],
entryPoints: [src('tabs.js'), src('flow.js'), src('logs.js'), src('home.js'), src('settings.js'), src('stats.js'), src('core.js'), src('builds.js'), src('credentials.js')],
outdir: staticDir(''),
bundle: true,
format: 'esm',
@ -98,7 +105,7 @@ await build({
// so a swap replaces only it) + theme.css (the semantic derivation
// layer) + common.css (shared typography, badges, buttons, inbox, side
// panel) plus its own page-specific bundle.
for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', 'flow.css', 'logs.css', 'home.css', 'settings.css', 'stats.css', 'core.css', 'builds.css', 'matrix-accounts.css']) {
for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', 'flow.css', 'logs.css', 'home.css', 'settings.css', 'stats.css', 'core.css', 'builds.css', 'credentials.css']) {
await build({
entryPoints: [src(entry)],
outfile: staticDir(entry),
@ -108,7 +115,7 @@ for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', '
});
}
for (const html of ['index.html', 'dashboard.html', 'flow.html', 'logs.html', 'settings.html', 'stats.html', 'core.html', 'builds.html', 'matrix-accounts.html']) {
for (const html of ['index.html', 'dashboard.html', 'flow.html', 'logs.html', 'settings.html', 'stats.html', 'core.html', 'builds.html', 'credentials.html']) {
copyFileSync(src(html), dist(html));
}