Skip to content

chore(web): remove the admin SPA and its OAuth worker routes - #6413

Merged
waynesun09 merged 1 commit into
mainfrom
remove-web-admin
Aug 20, 2026
Merged

chore(web): remove the admin SPA and its OAuth worker routes#6413
waynesun09 merged 1 commit into
mainfrom
remove-web-admin

Conversation

@waynesun09

@waynesun09 waynesun09 commented Aug 20, 2026

Copy link
Copy Markdown
Member

Summary

Work on the web admin SPA is stopped, and we are removing the feature rather than leaving it paused.

Leaving it paused was not holding. The pause lived in exactly one place — the title of docs/web-admin-deployment.md, a Cloudflare deployment doc — while every operative signal in the repo pointed the other way: CI still ran the admin test suite, web/admin/README.md carried no notice, CODEOWNERS had no carve-out, and #2528 carried both good first issue and ready-to-code. Since ready-to-code routes to the code agent (internal/dispatch/router.go:125), both human contributors and our own automation were being aimed at paused code. #6369 is what that looks like in practice: a correct, well-tested PR against code that is on its way out.

What is removed

  • web/admin/ — the Svelte SPA — and web/docs/, an orphan test whose source module was already gone and which no vitest config collected.
  • The OAuth BFF in the site Worker/api/oauth/authorize, /api/oauth/token, /api/github/user, oauthCors.ts, and the admin API test suite. The Worker is now a passthrough to the ASSETS binding.
  • [[ratelimits]], run_worker_first, and patch-wrangler-rate-limit-namespace-ids.mjs. The patch script existed to keep rate-limit namespace ids unique per Worker name; its only other job was patching top-level name, which is redundant because both deploy paths already pass --name explicitly. Left in place it would have failed the deploy with missing [[ratelimits]].
  • GITHUB_APP_* / TURNSTILE_* wiring from site-deploy.yml (production deploy and PR preview upload) and sample.env.local. The site Worker now needs no vars and no secrets.
  • The root Vite build, svelte-check, eslint.config.js, and every runtime npm dependency — all admin-only. vite.config.ts survives as a vitest-only config so the VitePress theme tests keep running.

eslint.config.js is removed rather than retargeted: it explicitly ignored docs/, cloudflare_site/, and web/public/, so with the SPA gone it had nothing left in scope. Happy to reinstate it pointed somewhere useful if a reviewer prefers.

Explicitly not affected — verified

Constraint Check Result
VitePress docs site npm run docs:build passes; /docs/ still assembled into the deploy bundle; site-deployment.html, doc-site.html, architecture.html all render
Public mint, mint.fullsend.sh git status internal/dispatch/cf/ untouched — separate Worker with its own wrangler.toml under internal/dispatch/cf/workersrc/; DefaultPublicMintURL / DefaultPerRepoMintURL unchanged
Landing page + document graph bundle step web/public/index.html/, web/public/graph.html/graph.html, unchanged
CLI install e2e e2e/admin/ is TestAdminInstallUninstall / TestVendorFromSubdirectory against the CLI, not the SPA. Untouched.
Tests npm test 7 VitePress theme tests + 3 new Worker passthrough tests, all pass
Go go build ./... clean; no file under internal/ or cmd/ is touched
Hooks pre-commit run --all-files all pass, including both markdown link checkers

Not a breaking change

The admin SPA was never rolled out, so removing it and its Worker routes breaks nothing for users — there is no deployed UI for anyone to migrate off, and installation has always been CLI-driven (fullsend github setup, fullsend repos). No ! marker or BREAKING CHANGE: trailer, deliberately: a migration notice in the GoReleaser release notes for a surface nobody had would be actively misleading.

not_found_handling = "single-page-application" is left as-is, so any stale /admin/* path falls back to the landing page rather than returning a JSON 404. That is intentional and asserted by a test.

Docs

docs/web-admin-deployment.md was mostly documentation-site deployment guidance that happened to live under an admin-titled page, so it is not simply deleted — the still-relevant content (Cloudflare Worker setup, API token, account id and Worker name, custom domains, Pages migration, fork/upstream GitHub setup, local preview, troubleshooting) is preserved as docs/site-deployment.md, with the admin OAuth and Turnstile material dropped and a note that the mint is a separate Worker. docs/admin-oauth-worker.md is deleted outright. doc-site.md's cross-link, both VitePress sidebar entries, web/README.md, docs/architecture.md's repository-layout section, and a dated note on ADR 0019 are all updated to match.

Follow-ups, not in this PR

Ops — these cannot be done from the repo:

  • Delete the now-unused Cloudflare Worker secrets GITHUB_APP_CLIENT_SECRET and TURNSTILE_SECRET_KEY, and vars GITHUB_APP_CLIENT_ID / TURNSTILE_SITE_KEY, from the documentation-site Worker.
  • Delete repo/org secrets FULLSEND_GITHUB_APP_CLIENT_SECRET, FULLSEND_TURNSTILE_SECRET_KEY and variables FULLSEND_GITHUB_APP_CLIENT_ID, FULLSEND_TURNSTILE_SITE_KEY.
  • The GitHub App used for admin user-OAuth, and its callback URLs, can be retired.

Backlog: the issue sweep is now folded into this PR — see Issues closed by this PR below.

Governance: whether removing a component warrants its own ADR beyond the note on ADR 0019 is a maintainer call; happy to write one.

Issues closed by this PR

Every open issue scoped to the removed SPA or its OAuth Worker routes, including the sub-issue tree under epic #509. GitHub closes these on merge.

Epic and feature work

Closes #509 — Admin web UI / SPA: delivery index for Story #124
Closes #512 — Admin web: organization hub
Closes #513 — Admin web: install or repair Fullsend for an organization
Closes #514 — Admin web: onboard and offboard repos from the org dashboard
Closes #547 — Admin web: trustworthy org listing and GitHub App install guidance

SPA defects and chores

Closes #541 — Admin SPA: token-at-rest strategy (localStorage vs mitigations)
Closes #542 — Admin SPA: surface non-401 errors from refreshSession
Closes #618 — Admin SPA: overlapping org-list layer analysis
Closes #619 — Admin SPA: GitHub REST rate-limit handling and retry policy
Closes #620 — Admin SPA: batch org GraphQL drops per-org hints
Closes #621 — Admin SPA: empty OAuth authorization code handoff error
Closes #623 — Admin SPA: install-readiness probes report only first missing capability
Closes #626 — Admin SPA: extract shared components and CSS design tokens
Closes #674 — admin: parallelize inner-layer API calls in enrollment and secrets analysis
Closes #675 — admin: wire up /org/:login and /install/:login routes in App.svelte
Closes #550 — Browser-based test suite for admin SPA with parity vs Go CLI flows
Closes #622 — Dev experiment: OAuth localhost helper uses a fixed OAuth state value

Worker OAuth, Turnstile, and the GitHub proxy — all routes removed here

Closes #505 — Pass client IP to Turnstile siteverify on admin token exchange
Closes #506 — Align production and preview admin hostnames for OAuth redirect validation
Closes #543 — Site Worker: generic JSON errors for GitHub /user proxy
Closes #546 — Admin OAuth: explicit GitHub authorize scope
Closes #585 — Site / admin SPA: Content-Security-Policy headers for Worker and static responses

web-admin drift from the Go backend

Closes #2526 — fix(web-admin): agentsFromConfig() references removed agents block
Closes #2528 — fix(web-admin): VALID_ROLES has 4 roles vs Go's 8

Closed separately, not by this PR

fullsend admin install is the per-org installer deprecated by ADR 0044 (ADR 0033 makes per-repo the sole supported model), and the install path is slated for removal. The admin namespace itself is being repurposed for org-administrator commands — admin foreign for mint service management is the first. These two were closed as not planned on that basis; they are Go CLI issues and this PR does not touch them:

Deliberately not closed

These matched an "admin" search, or hang off epic #509, but survive the removal. Worth noting that #509 is closed by this PR while two of its children (#544, #545) are not — closing the epic does not mean the whole subtree goes.

Issue Why it stays open
#544 Go toolchain pin in mise.toml. Filed under epic #509 but unrelated to the SPA.
#545 Duplicate npm ci across site-build and site-deploy. Verified both workflows still install, so still valid.
#3440 Shared workflow-polling helper in internal/cli/admin.go / internal/layers/enrollment.go. Its callers are admin enable / admin disable — per-org commands — so it is covered by the per-org install-mode deprecation (ADR 0044), not by the SPA removal. Owned by that effort.
#637 Monitoring/status dashboard, explicitly decoupled from the installer UI. Future work, unaffected.
#5808 defaults.auto_merge never consumed. Mentions the SPA schema in passing; the Go half stands.
#1154 Review-agent blindspot on CSS-heavy PRs. Agent behavior, not this code.

Supersedes #6369.

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

Site preview

Preview: https://022343c9-site.fullsend-ai.workers.dev

Commit: 8e6cdd104786db2c6de1431cee5ea790fd6bc114

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 3:03 PM UTC · Completed 3:24 PM UTC

Commit: 70cbb88 · View workflow run →

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Remove web admin SPA and OAuth worker routes; make site Worker assets-only

✨ Enhancement ⚙️ Configuration changes 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Delete the deprecated web/admin/ SPA and its orphaned tests.
• Simplify the Cloudflare site Worker to a static ASSETS passthrough with no secrets.
• Remove admin-only CI/build tooling and update deployment/docs accordingly.
Diagram

graph TD
  GH["GitHub Actions"] --> SB["Build Site"] --> BND[("site artifact")]
  BND --> SD["Deploy Site"] --> CF["Cloudflare Worker"] --> AS["ASSETS static"]
  subgraph Legend
    direction LR
    _ci["CI job"] ~~~ _svc["Worker"] ~~~ _db[("Artifact")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Keep Worker `/api/*` stubs returning 410
  • ➕ Provides explicit signal to clients/bookmarks that admin endpoints are intentionally gone
  • ➕ May reduce confusion vs SPA fallback behavior from static assets routing
  • ➖ Adds ongoing maintenance surface in the Worker for a removed product
  • ➖ Conflicts with goal of minimizing secrets/vars and keeping Worker purely static
2. Separate admin removal into staged PRs (Worker → CI → docs)
  • ➕ Smaller review chunks and easier rollback if deploy issues appear
  • ➖ Intermediate states can break CI or deploy until all parts land
  • ➖ More coordination overhead than a single coherent removal

Recommendation: Current approach (full removal + simplifying the Worker to ASSETS-only) is the cleanest long-term outcome: it eliminates misleading contribution signals and removes secrets/ratelimit/patching complexity from deploy. Consider whether you want an explicit 410 response for legacy /api/* paths; otherwise the minimal Worker is preferable.

Files changed (102) +444 / -12762

Enhancement (1) +6 / -560
index.tsRemove admin OAuth BFF; serve static assets only +6/-560

Remove admin OAuth BFF; serve static assets only

• Deletes all OAuth/token/user proxy endpoints, CORS hardening, and rate limiting logic. The Worker now simply forwards requests to the 'ASSETS' binding when present.

cloudflare_site/worker/src/index.ts

Refactor (42) +0 / -4533
oauthCors.tsRemove OAuth/CORS helper module +0/-194

Remove OAuth/CORS helper module

• Deletes the OAuth/CORS policy and tab-binding utilities previously used by the admin OAuth BFF routes.

cloudflare_site/worker/src/oauthCors.ts

index.htmlRemove admin SPA entry HTML +0/-12

Remove admin SPA entry HTML

• Deletes the SPA HTML entrypoint that was built and served under '/admin/'.

web/admin/index.html

App.svelteRemove admin SPA main application component +0/-469

Remove admin SPA main application component

• Deletes the main Svelte application component implementing the admin UI.

web/admin/src/App.svelte

app.cssRemove admin SPA styling +0/-8

Remove admin SPA styling

• Deletes the global CSS used by the admin SPA.

web/admin/src/app.css

adminSessionCaches.tsRemove admin session cache helpers +0/-14

Remove admin session cache helpers

• Deletes auth/session cache utilities used by the admin SPA.

web/admin/src/lib/auth/adminSessionCaches.ts

githubUnauthorized.tsRemove GitHub unauthorized handling logic +0/-14

Remove GitHub unauthorized handling logic

• Deletes helper logic for classifying/handling GitHub auth failures in the SPA.

web/admin/src/lib/auth/githubUnauthorized.ts

oauth.tsRemove SPA OAuth/PKCE client implementation +0/-388

Remove SPA OAuth/PKCE client implementation

• Deletes the browser-side OAuth flow implementation that relied on Worker '/api/oauth/*' endpoints.

web/admin/src/lib/auth/oauth.ts

pkce.tsRemove PKCE helpers +0/-21

Remove PKCE helpers

• Deletes PKCE utility functions used by the admin OAuth flow.

web/admin/src/lib/auth/pkce.ts

previewHandoff.tsRemove preview/deploy handoff helpers +0/-20

Remove preview/deploy handoff helpers

• Deletes code used for preview environment handoff in the admin UI.

web/admin/src/lib/auth/previewHandoff.ts

session.tsRemove session management module +0/-48

Remove session management module

• Deletes SPA-side session handling for the removed admin feature.

web/admin/src/lib/auth/session.ts

tokenStore.tsRemove token storage implementation +0/-74

Remove token storage implementation

• Deletes token persistence logic used by the admin SPA.

web/admin/src/lib/auth/tokenStore.ts

turnstile.tsRemove Turnstile integration module +0/-180

Remove Turnstile integration module

• Deletes browser-side Turnstile support used during token exchange.

web/admin/src/lib/auth/turnstile.ts

client.tsRemove GitHub API client wrapper +0/-38

Remove GitHub API client wrapper

• Deletes SPA-side GitHub client code used for admin UI features.

web/admin/src/lib/github/client.ts

githubAppInstallLink.tsRemove GitHub App install link helper +0/-7

Remove GitHub App install link helper

• Deletes the helper that constructed GitHub App install URLs for the admin UI.

web/admin/src/lib/github/githubAppInstallLink.ts

user.tsRemove GitHub user/profile helper +0/-56

Remove GitHub user/profile helper

• Deletes code used to handle '/user' profile data in the admin UI.

web/admin/src/lib/github/user.ts

analyzeOrg.tsRemove analyze org layer +0/-35

Remove analyze org layer

• Deletes logic for analyzing organizations in the admin UI.

web/admin/src/lib/layers/analyzeOrg.ts

configRepo.tsRemove config repo layer +0/-55

Remove config repo layer

• Deletes admin UI code that interpreted/validated config repositories.

web/admin/src/lib/layers/configRepo.ts

constants.tsRemove admin layer constants +0/-19

Remove admin layer constants

• Deletes constants used by the removed admin UI layers.

web/admin/src/lib/layers/constants.ts

dispatch.tsRemove dispatch layer +0/-43

Remove dispatch layer

• Deletes admin UI code that interacted with dispatch-related operations.

web/admin/src/lib/layers/dispatch.ts

enrollment.tsRemove enrollment layer +0/-57

Remove enrollment layer

• Deletes admin UI code for enrollment-related operations.

web/admin/src/lib/layers/enrollment.ts

githubClient.tsRemove GitHub client layer abstraction +0/-120

Remove GitHub client layer abstraction

• Deletes the GitHub client wrapper used by admin UI layers.

web/admin/src/lib/layers/githubClient.ts

orgConfigParse.tsRemove org config parsing module +0/-179

Remove org config parsing module

• Deletes logic for parsing organization configuration in the admin UI.

web/admin/src/lib/layers/orgConfigParse.ts

preflight.tsRemove preflight module +0/-88

Remove preflight module

• Deletes admin UI preflight check implementation.

web/admin/src/lib/layers/preflight.ts

secrets.tsRemove secrets layer +0/-69

Remove secrets layer

• Deletes admin UI code that reasoned about repo/org secrets state.

web/admin/src/lib/layers/secrets.ts

workflows.tsRemove workflows layer +0/-50

Remove workflows layer

• Deletes admin UI workflow analysis/inspection code.

web/admin/src/lib/layers/workflows.ts

batchOrganizationsFullsendRepoGraphql.tsRemove org batching GraphQL helper +0/-84

Remove org batching GraphQL helper

• Deletes GraphQL batching helper used by the admin UI.

web/admin/src/lib/orgs/batchOrganizationsFullsendRepoGraphql.ts

deployOAuthScopes.tsRemove deploy OAuth scopes helper +0/-10

Remove deploy OAuth scopes helper

• Deletes code related to required OAuth scopes for deployment flows.

web/admin/src/lib/orgs/deployOAuthScopes.ts

emptyOrgListHint.tsRemove empty org list hint helper +0/-15

Remove empty org list hint helper

• Deletes helper used to render empty-state hints in org list UI.

web/admin/src/lib/orgs/emptyOrgListHint.ts

fetchOrgs.tsRemove org fetching logic +0/-206

Remove org fetching logic

• Deletes admin UI logic for fetching organizations/installations data.

web/admin/src/lib/orgs/fetchOrgs.ts

filter.tsRemove org filtering helper +0/-13

Remove org filtering helper

• Deletes filtering helpers used by the admin org list UI.

web/admin/src/lib/orgs/filter.ts

githubPermissionHints.tsRemove permission hints module +0/-137

Remove permission hints module

• Deletes code that generated GitHub permission guidance in the admin UI.

web/admin/src/lib/orgs/githubPermissionHints.ts

installReadinessProbes.tsRemove install readiness probes module +0/-137

Remove install readiness probes module

• Deletes admin UI logic that checked installation readiness conditions.

web/admin/src/lib/orgs/installReadinessProbes.ts

installationOrgRows.tsRemove installation org rows module +0/-57

Remove installation org rows module

• Deletes code that normalized/displayed installation org rows in the UI.

web/admin/src/lib/orgs/installationOrgRows.ts

orgListAnalysisCache.tsRemove org analysis cache module +0/-30

Remove org analysis cache module

• Deletes caching helper used by org list analysis.

web/admin/src/lib/orgs/orgListAnalysisCache.ts

orgListRow.tsRemove org list row model +0/-263

Remove org list row model

• Deletes org list row data model and related UI helpers.

web/admin/src/lib/orgs/orgListRow.ts

engine.tsRemove status engine module +0/-23

Remove status engine module

• Deletes status computation engine used by the admin UI.

web/admin/src/lib/status/engine.ts

types.tsRemove status type definitions +0/-26

Remove status type definitions

• Deletes status type definitions for admin UI.

web/admin/src/lib/status/types.ts

main.tsRemove admin SPA entrypoint +0/-5

Remove admin SPA entrypoint

• Deletes the SPA bootstrap file.

web/admin/src/main.ts

InstallEntryStub.svelteRemove admin route stub component +0/-35

Remove admin route stub component

• Deletes a Svelte route component used in the admin UI.

web/admin/src/routes/InstallEntryStub.svelte

OrgDashboardStub.svelteRemove org dashboard stub route +0/-37

Remove org dashboard stub route

• Deletes a Svelte route component for the admin org dashboard stub.

web/admin/src/routes/OrgDashboardStub.svelte

OrgList.svelteRemove main admin org list route +0/-1182

Remove main admin org list route

• Deletes the primary admin UI route implementing org listing and related flows.

web/admin/src/routes/OrgList.svelte

vite-env.d.tsRemove admin Vite environment types +0/-15

Remove admin Vite environment types

• Deletes the Vite env typings used by the admin project.

web/admin/src/vite-env.d.ts

Tests (35) +44 / -3399
index.worker.test.tsReplace admin API suite with ASSETS passthrough test +44/-592

Replace admin API suite with ASSETS passthrough test

• Removes the extensive admin OAuth and GitHub proxy tests and replaces them with a minimal test asserting requests are forwarded to 'env.ASSETS.fetch()'.

cloudflare_site/worker/src/index.worker.test.ts

oauthCors.test.tsRemove oauthCors tests +0/-128

Remove oauthCors tests

• Deletes tests for the now-removed OAuth/CORS support module.

cloudflare_site/worker/src/oauthCors.test.ts

githubUnauthorized.test.tsRemove admin auth unit tests (GitHub unauthorized) +0/-12

Remove admin auth unit tests (GitHub unauthorized)

• Deletes unit tests for the removed admin auth behavior.

web/admin/src/lib/auth/githubUnauthorized.test.ts

oauth.test.tsRemove OAuth client unit tests +0/-443

Remove OAuth client unit tests

• Deletes extensive unit tests for the SPA-side OAuth/PKCE logic.

web/admin/src/lib/auth/oauth.test.ts

pkce.test.tsRemove PKCE tests +0/-24

Remove PKCE tests

• Deletes tests for PKCE helpers used only by the admin SPA.

web/admin/src/lib/auth/pkce.test.ts

previewHandoff.test.tsRemove preview handoff tests +0/-18

Remove preview handoff tests

• Deletes tests for preview/deploy handoff behavior in the SPA.

web/admin/src/lib/auth/previewHandoff.test.ts

session.test.tsRemove session tests +0/-146

Remove session tests

• Deletes unit tests for admin session management logic.

web/admin/src/lib/auth/session.test.ts

tokenStore.test.tsRemove token store tests +0/-82

Remove token store tests

• Deletes tests for storing OAuth access tokens in the admin UI.

web/admin/src/lib/auth/tokenStore.test.ts

turnstile.test.tsRemove Turnstile tests +0/-42

Remove Turnstile tests

• Deletes tests for Turnstile integration used by the removed OAuth flow.

web/admin/src/lib/auth/turnstile.test.ts

client.test.tsRemove GitHub client tests +0/-29

Remove GitHub client tests

• Deletes tests for the SPA’s GitHub client wrappers.

web/admin/src/lib/github/client.test.ts

githubAppInstallLink.test.tsRemove GitHub App install link tests +0/-35

Remove GitHub App install link tests

• Deletes tests for generating GitHub App install links in the SPA.

web/admin/src/lib/github/githubAppInstallLink.test.ts

user.test.tsRemove GitHub user parsing tests +0/-108

Remove GitHub user parsing tests

• Deletes unit tests around user profile shaping for the admin UI.

web/admin/src/lib/github/user.test.ts

analyzeOrg.test.tsRemove layer tests (analyze org) +0/-60

Remove layer tests (analyze org)

• Deletes tests for admin UI data-layer functions.

web/admin/src/lib/layers/analyzeOrg.test.ts

configRepo.test.tsRemove config repo layer tests +0/-113

Remove config repo layer tests

• Deletes tests for configuration-repo related admin UI logic.

web/admin/src/lib/layers/configRepo.test.ts

dispatch.test.tsRemove dispatch layer tests +0/-34

Remove dispatch layer tests

• Deletes tests for admin UI dispatch-related logic.

web/admin/src/lib/layers/dispatch.test.ts

enrollment.test.tsRemove enrollment layer tests +0/-44

Remove enrollment layer tests

• Deletes tests for admin enrollment checks and flows.

web/admin/src/lib/layers/enrollment.test.ts

config-valid.yamlRemove admin layer fixture data +0/-8

Remove admin layer fixture data

• Deletes fixture YAML used by config-repo layer tests.

web/admin/src/lib/layers/fixtures/configrepo/config-valid.yaml

githubClient.test.tsRemove GitHub client layer tests +0/-21

Remove GitHub client layer tests

• Deletes tests for GitHub client abstraction used by admin layers.

web/admin/src/lib/layers/githubClient.test.ts

orgConfigParse.test.tsRemove org config parse tests +0/-146

Remove org config parse tests

• Deletes tests for parsing org config in the admin UI.

web/admin/src/lib/layers/orgConfigParse.test.ts

preflight.test.tsRemove preflight tests +0/-66

Remove preflight tests

• Deletes tests for admin UI preflight checks.

web/admin/src/lib/layers/preflight.test.ts

secrets.test.tsRemove secrets layer tests +0/-64

Remove secrets layer tests

• Deletes tests around admin UI secret verification logic.

web/admin/src/lib/layers/secrets.test.ts

workflows.test.tsRemove workflows layer tests +0/-49

Remove workflows layer tests

• Deletes tests for workflow-related admin UI logic.

web/admin/src/lib/layers/workflows.test.ts

batchOrganizationsFullsendRepoGraphql.test.tsRemove org batching tests +0/-63

Remove org batching tests

• Deletes tests for batching org queries in the admin UI.

web/admin/src/lib/orgs/batchOrganizationsFullsendRepoGraphql.test.ts

deployOAuthScopes.test.tsRemove deploy OAuth scopes tests +0/-8

Remove deploy OAuth scopes tests

• Deletes tests for OAuth scope display/logic used by the admin UI.

web/admin/src/lib/orgs/deployOAuthScopes.test.ts

emptyOrgListHint.test.tsRemove empty org list hint tests +0/-12

Remove empty org list hint tests

• Deletes tests for admin UI hinting when org list is empty.

web/admin/src/lib/orgs/emptyOrgListHint.test.ts

fetchOrgs.test.tsRemove fetch orgs tests +0/-270

Remove fetch orgs tests

• Deletes extensive tests for fetching org/installations in admin UI.

web/admin/src/lib/orgs/fetchOrgs.test.ts

filter.test.tsRemove org filtering tests +0/-23

Remove org filtering tests

• Deletes tests for filtering org lists in the UI.

web/admin/src/lib/orgs/filter.test.ts

githubPermissionHints.test.tsRemove permission hints tests +0/-166

Remove permission hints tests

• Deletes tests for permission hint logic used in admin UI.

web/admin/src/lib/orgs/githubPermissionHints.test.ts

installReadinessProbes.test.tsRemove install readiness probes tests +0/-111

Remove install readiness probes tests

• Deletes tests for installation readiness probing logic.

web/admin/src/lib/orgs/installReadinessProbes.test.ts

installationOrgRows.test.tsRemove installation org rows tests +0/-127

Remove installation org rows tests

• Deletes tests for installation org row modeling in the UI.

web/admin/src/lib/orgs/installationOrgRows.test.ts

orgListAnalysisCache.test.tsRemove org list analysis cache tests +0/-35

Remove org list analysis cache tests

• Deletes tests for caching org analysis results.

web/admin/src/lib/orgs/orgListAnalysisCache.test.ts

orgListRow.test.tsRemove org list row tests +0/-198

Remove org list row tests

• Deletes tests for org list row modeling.

web/admin/src/lib/orgs/orgListRow.test.ts

engine.test.tsRemove status engine tests +0/-36

Remove status engine tests

• Deletes tests for status computation engine used by admin UI.

web/admin/src/lib/status/engine.test.ts

types.test.tsRemove status types tests +0/-9

Remove status types tests

• Deletes tests for status type definitions used by admin UI.

web/admin/src/lib/status/types.test.ts

vitePluginDocs.test.tsRemove orphaned web docs plugin test +0/-77

Remove orphaned web docs plugin test

• Deletes an unused/orphaned test under 'web/docs/' whose source module was already gone and not collected by vitest.

web/docs/build/vitePluginDocs.test.ts

Documentation (10) +142 / -274
config.tsUpdate sidebar links for new site deployment doc +1/-6

Update sidebar links for new site deployment doc

• Replaces the removed web-admin deployment and admin OAuth worker links with a new Site Deployment link.

docs/.vitepress/config.ts

0019-web-source-and-cloudflare-site-layout.mdAdd removal note for the admin SPA and OAuth Worker +9/-0

Add removal note for the admin SPA and OAuth Worker

• Adds a dated note documenting that 'web/admin/' and the related site Worker OAuth BFF were removed, while preserving the ADR’s web/cloudflare_site split rationale.

docs/ADRs/0019-web-source-and-cloudflare-site-layout.md

admin-oauth-worker.mdRemove admin OAuth Worker hardening notes +0/-43

Remove admin OAuth Worker hardening notes

• Deletes documentation describing the OAuth BFF routes and their security model, since those routes no longer exist.

docs/admin-oauth-worker.md

architecture.mdUpdate repo layout section to reflect assets-only site Worker +9/-1

Update repo layout section to reflect assets-only site Worker

• Updates the repository layout description to emphasize VitePress docs and notes the removal of the admin SPA and OAuth BFF, clarifying the mint Worker is unaffected.

docs/architecture.md

doc-site.mdPoint doc-site guidance to new site deployment doc +1/-1

Point doc-site guidance to new site deployment doc

• Updates the reference from 'web-admin-deployment.md' to 'site-deployment.md' for Cloudflare Worker setup/troubleshooting.

docs/doc-site.md

site-deployment.mdAdd comprehensive Cloudflare site deployment guide +112/-0

Add comprehensive Cloudflare site deployment guide

• Introduces new documentation describing the site bundle contents, CI build/deploy flows, Cloudflare/GitHub setup, local preview steps, and troubleshooting for the assets-only Worker.

docs/site-deployment.md

web-admin-deployment.mdRemove web admin deployment documentation +0/-91

Remove web admin deployment documentation

• Deletes the on-hold admin deployment doc now that the admin SPA and its deployment path are removed.

docs/web-admin-deployment.md

sample.env.localRemove admin OAuth/Turnstile env sample +0/-52

Remove admin OAuth/Turnstile env sample

• Deletes the sample env file documenting GitHub App and Turnstile keys for the admin OAuth flow, which no longer exists.

sample.env.local

README.mdUpdate web docs to remove admin SPA references +10/-1

Update web docs to remove admin SPA references

• Rewrites the web README to describe only the landing page and document graph, and points readers to VitePress/docs and the assets-only Cloudflare site worker.

web/README.md

README.mdRemove admin SPA README +0/-79

Remove admin SPA README

• Deletes documentation for building/running the Svelte admin SPA and its local OAuth requirements.

web/admin/README.md

Other (14) +252 / -3996
lint.ymlStop running admin checks; keep tests for docs/Worker +1/-4

Stop running admin checks; keep tests for docs/Worker

• Renames the vitest step to reflect docs theme + site Worker tests and removes the svelte-check step that was only relevant to the deleted admin SPA.

.github/workflows/lint.yml

site-build.ymlRemove admin SPA build and bundling from site artifact +0/-9

Remove admin SPA build and bundling from site artifact

• Stops triggering on 'vite.config.ts', removes the 'npm run build' step, and stops copying 'web/dist' (admin/assets) into '_bundle/public/'. The artifact now contains landing/graph HTML, VitePress docs, and Cloudflare site assets/worker.

.github/workflows/site-build.yml

site-deploy.ymlDrop CI wrangler patching and secret/var injection +1/-38

Drop CI wrangler patching and secret/var injection

• Removes the CI patch step for wrangler.toml and deletes all GitHub/Turnstile secret and var wiring for production deploy and PR preview uploads. Notes that the site Worker now requires no vars or secrets.

.github/workflows/site-deploy.yml

.gitignoreStop ignoring admin build outputs +0/-2

Stop ignoring admin build outputs

• Removes ignores for 'web/dist' and 'web/admin/dist', which are no longer produced after removing the SPA build.

.gitignore

.pre-commit-config.yamlLimit lint-staged hook scope to docs theme files +1/-1

Limit lint-staged hook scope to docs theme files

• Updates the lint-staged pre-commit hook file matcher to only include 'docs/.vitepress/', removing 'web/admin/src/'.

.pre-commit-config.yaml

.stylelintrc.jsonRemove Svelte stylelint config +1/-1

Remove Svelte stylelint config

• Drops the 'stylelint-config-html/svelte' extension, leaving only Vue + standard configs now that Svelte sources are removed.

.stylelintrc.json

patch-wrangler-rate-limit-namespace-ids.mjsRemove wrangler ratelimit namespace patch script +0/-142

Remove wrangler ratelimit namespace patch script

• Deletes the CI helper that patched worker name and '[[ratelimits]].namespace_id' values; it is no longer needed after removing ratelimits and secret bulk behavior.

cloudflare_site/scripts/patch-wrangler-rate-limit-namespace-ids.mjs

wrangler.tomlRemove admin routing and Worker rate limits +1/-26

Remove admin routing and Worker rate limits

• Deletes 'run_worker_first' for '/api/*' and removes '[[ratelimits]]' blocks tied to the admin OAuth endpoints. Updates the dev comment to reflect assets-only Worker usage.

cloudflare_site/wrangler.toml

eslint.config.jsRemove admin-focused ESLint configuration +0/-92

Remove admin-focused ESLint configuration

• Deletes the ESLint config that primarily targeted 'web/admin/' sources and ignored most other repo paths.

eslint.config.js

package-lock.jsonDrop admin/runtime JS dependencies +231/-3499

Drop admin/runtime JS dependencies

• Removes Svelte/admin-related packages and other runtime dependencies that were only required by the admin SPA/OAuth tooling; keeps docs/worker test toolchain dependencies.

package-lock.json

package.jsonRemove admin build/dev scripts and dependencies; keep docs/worker tooling +5/-57

Remove admin build/dev scripts and dependencies; keep docs/worker tooling

• Eliminates Vite build/preview scripts, svelte-check, admin lint targets, and admin-related dependencies. Keeps 'dev:worker', docs scripts, and vitest runs (docs theme + worker).

package.json

vite.config.tsConvert root Vite config into vitest-only config +11/-108

Convert root Vite config into vitest-only config

• Removes Svelte/Vite build, dev server proxy, and SPA fallback logic. Keeps only a vitest configuration that runs docs theme tests under 'docs/.vitepress/'.

vite.config.ts

svelte.config.jsRemove admin Svelte configuration +0/-4

Remove admin Svelte configuration

• Deletes the Svelte config for the removed SPA.

web/admin/svelte.config.js

tsconfig.jsonRemove admin TypeScript config +0/-13

Remove admin TypeScript config

• Deletes the tsconfig used by the admin SPA and svelte-check.

web/admin/tsconfig.json

@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. ADR script reference stale 🐞 Bug ⚙ Maintainability
Description
docs/ADRs/0019-web-source-and-cloudflare-site-layout.md now states there is “no root `npm run
build”, but the ADR’s Decision point 1 still claims the repo has root scripts such as npm run dev`
/ npm run build. This contradiction makes contributor guidance incorrect after the script removals
in this PR.
Code

docs/ADRs/0019-web-source-and-cloudflare-site-layout.md[R16-19]

+> **Note (2026-08-20):** The admin installation SPA described in points 1 and 3 was
+> removed. `web/` now holds only the static landing page and document graph under
+> `web/public/`; there is no Vite build and no root `npm run build`. The site Worker
+> under `cloudflare_site/worker/` is a static-asset passthrough — its OAuth BFF was
Relevance

●●● Strong

Recent ADR precedents accept corrections to stale or contradictory documentation after
implementation changes.

PR-#242
PR-#6111

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The ADR’s new note explicitly states there is no root npm run build, but Decision #1 still
describes root scripts npm run dev / npm run build as part of the layout decision, creating an
internal contradiction in the same document.

docs/ADRs/0019-web-source-and-cloudflare-site-layout.md[16-23]
docs/ADRs/0019-web-source-and-cloudflare-site-layout.md[35-38]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
ADR 0019 includes a newly-added removal note stating there is no root `npm run build`, but the existing Decision #1 still says the repo has root scripts like `npm run dev` / `npm run build`.

## Issue Context
This PR removes the root Vite build and associated scripts, so ADR 0019 should no longer describe those scripts as present.

## Fix Focus Areas
- docs/ADRs/0019-web-source-and-cloudflare-site-layout.md[16-23]
- docs/ADRs/0019-web-source-and-cloudflare-site-layout.md[35-38]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 57 rules

Grey Divider

Tip of the day
💡 Did you know, you can copy the agent prompt from any finding and feed it to your IDE agent

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread docs/ADRs/0019-web-source-and-cloudflare-site-layout.md
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

Review

Findings

Medium

  • [protected-path] .github/workflows/lint.yml, .github/workflows/site-build.yml, .github/workflows/site-deploy.yml, .pre-commit-config.yaml — These files are under protected paths (.github/, .pre-commit-config.yaml). The PR links to epic Admin web UI / SPA: delivery index for Story #124 #509 and ~25 sub-issues, and the description explains the rationale for modifying CI workflows (removing admin SPA build steps, secret injection, and rate-limit patching) and the pre-commit config (narrowing lint-staged scope to docs/.vitepress/ only). Human approval is always required for protected-path changes, regardless of context.

Info

  • [provenance-warning] — Prior review context discarded: provenance validation failed (unverifiable-wrong-app). This review treats all findings as first-time assessments.
Previous run

Review

Findings

Medium

  • [protected-path] .github/workflows/lint.yml, .github/workflows/site-build.yml, .github/workflows/site-deploy.yml, .pre-commit-config.yaml — These governance and infrastructure files are modified by this PR. The PR links to issues and provides detailed rationale for the changes (removing admin SPA CI wiring, narrowing lint-staged scope). Human approval is always required for protected-path changes, regardless of context.

Low

  • [import-convention] cloudflare_site/worker/src/index.worker.test.ts:1 — The test imports env from cloudflare:test alongside createExecutionContext and waitOnExecutionContext on a single import line. The established codebase convention (e.g., internal/dispatch/cf/workersrc/src/index.test.ts) uses import { env } from "cloudflare:workers" as a separate statement. Both are functionally equivalent — cloudflare:test re-exports env — but the convention divergence is worth noting.
Previous run (2)

Review

Findings

Medium

  • [stale-reference] cloudflare_site/worker/vitest.config.mts:16 — The miniflare bindings still provide GITHUB_APP_CLIENT_ID, GITHUB_APP_CLIENT_SECRET, TURNSTILE_SITE_KEY, and TURNSTILE_SECRET_KEY, but the Worker's Env interface now only defines ASSETS?: Fetcher. These dead configuration values will mislead future contributors into thinking the Worker still uses OAuth/Turnstile secrets. This file was not included in the PR diff.
    Remediation: Remove the bindings object from vitest.config.mts since the Worker no longer uses these environment variables.

  • [protected-path] .github/workflows/lint.yml, .github/workflows/site-build.yml, .github/workflows/site-deploy.yml, .pre-commit-config.yaml — This PR modifies governance and infrastructure files under protected paths (.github/, .pre-commit-config.yaml). The PR links to issue fix(web-admin): VALID_ROLES has 4 roles vs Go's 8 #2528 and explains the rationale: removing the admin SPA requires updating CI workflows (removing svelte-check, admin build steps, and secrets wiring) and the lint-staged pattern. Human approval is always required for protected-path changes, regardless of context.

Low

  • [stale-secrets] .github/workflows/site-deploy.yml — After merge, previously-deployed Cloudflare Worker secrets (GITHUB_APP_CLIENT_SECRET, TURNSTILE_SECRET_KEY) and vars (GITHUB_APP_CLIENT_ID, TURNSTILE_SITE_KEY) will remain in the Cloudflare runtime as stale environment variables until manually removed. The simplified Worker has no code paths to leak them. The PR body already documents this as a follow-up ops task.
    Remediation: After merging, remove stale secrets and vars from the Cloudflare Worker dashboard and GitHub Actions secrets/variables.

  • [unused-import] cloudflare_site/worker/src/index.worker.test.ts:1 — The env import from cloudflare:test and the trailing void env; are dead code — all tests now construct their own testEnv objects and never reference the pool-provided env.
    Remediation: Remove env from the import and delete the void env; line.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 3:37 PM UTC · Ended 3:52 PM UTC

Commit: 083f769 · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 3:53 PM UTC · Completed 4:14 PM UTC

Commit: 9301a27 · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

Work on the web admin SPA is stopped and the feature is being removed
rather than left paused. Paused-but-present code kept advertising itself
as live work: the pause was recorded only in the title of
docs/web-admin-deployment.md, while CI still ran the admin test suite and
issue #2528 carried both good-first-issue and ready-to-code, so the code
agent and human contributors were both routed at it (PR #6369).

Removed:

- web/admin/ (Svelte SPA) and web/docs/ (orphan test whose source was
  already gone)
- The OAuth BFF in the site Worker: /api/oauth/authorize, /api/oauth/token
  and /api/github/user, plus oauthCors.ts and the admin API tests. The
  Worker is now a passthrough to the ASSETS binding.
- The two [[ratelimits]] blocks, run_worker_first, and the wrangler.toml
  patch script that existed only to keep their namespace ids unique. The
  deploy already passes --name explicitly, so the name patch was redundant.
- GITHUB_APP_* and TURNSTILE_* wiring from site-deploy.yml (both the
  production deploy and the PR preview upload), sample.env.local, and the
  matching miniflare test bindings.
- The root Vite build, svelte-check, eslint config, the Svelte half of the
  Prettier config, and every runtime npm dependency, all of which were
  admin-only. vite.config.ts survives as a vitest-only config so the
  VitePress theme tests keep running.

Note that removing run_worker_first makes the passthrough the Worker's
only code path. The ASSETS binding was never declared in wrangler.toml,
which was harmless while the Worker only ran for /api/* (those paths
returned JSON before reaching the ASSETS branch) but would now 503 every
request that reaches the Worker. wrangler.toml declares
binding = "ASSETS", and a test asserts it is present.

Unaffected, and verified so:

- The VitePress documentation site builds and ships unchanged; docs:build
  passes and /docs/ is still assembled into the deploy bundle.
- The public mint at mint.fullsend.sh is a separate Worker provisioned
  from internal/dispatch/cf/ with its own wrangler.toml. No file under
  internal/ is touched.
- e2e/admin/ is the CLI install e2e suite, not the SPA, and is untouched.

Cloudflare-side secrets (GITHUB_APP_CLIENT_SECRET, TURNSTILE_SECRET_KEY)
and the FULLSEND_GITHUB_APP_* / FULLSEND_TURNSTILE_* repo secrets and
variables are now unused and should be deleted out of band.

The admin SPA was never rolled out, so this is not a user-facing breaking
change and carries no `!` marker: there is no deployed UI for anyone to
migrate off. Installation has always been driven by the CLI
(`fullsend github setup`, `fullsend repos`). Stale /admin/* paths fall back
to the landing page rather than 404, since not_found_handling stays
"single-page-application".

Refs #2528

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 4:19 PM UTC · Completed 4:35 PM UTC

Commit: 8e6cdd1 · View workflow run →

@waynesun09
waynesun09 added this pull request to the merge queue Aug 20, 2026
Merged via the queue into main with commit 9ee3798 Aug 20, 2026
72 checks passed
@waynesun09
waynesun09 deleted the remove-web-admin branch August 20, 2026 17:07
@fullsend-ai-retro

fullsend-ai-retro Bot commented Aug 20, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 5:08 PM UTC · Completed 5:29 PM UTC

Commit: 8e6cdd1 · View workflow run →

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #6413 — Remove the admin SPA and its OAuth worker routes

Overall assessment: The workflow went well. This was a large deletion PR (104 files, −12,771 lines) by waynesun09 removing the admin SPA. It merged in ~2 hours with zero false-positive review findings and thorough author engagement. All improvement opportunities identified are already tracked by existing open issues.

Timeline

Time (UTC) Event
15:01 PR opened, review agent triggered
15:13 Qodo posts 1 medium finding (ADR 0019 script reference stale)
15:24 Review agent run 1 completes — 4 findings (stale-reference, protected-path, stale-secrets, unused-import)
15:35 Force-push, review agent run 2 starts
15:51 Force-push, run 2 cancelled, run 3 starts
16:14 Run 3 completes — 2 findings (protected-path, import-convention)
16:17 Force-push (fixes), run 4 starts
16:35 Run 4 completes — only protected-path policy flag, zero code findings
16:41 Approved by ralphbean
16:57 Approved by ifireball
17:04 Author responds to all inline comments with fixes
17:07 Merged

What went right

  1. All review findings were valid — zero false positives across 3 completed reviews.
  2. Strong beyond-the-diff analysis — The review agent proactively caught stale miniflare bindings in vitest.config.mts (not in the PR diff) that would mislead future contributors. The author fixed this in a subsequent force-push.
  3. Correct protected-path enforcement.github/workflows/ and .pre-commit-config.yaml changes were flagged for human review and the requires-manual-review label was applied.
  4. Exemplary author engagement — All 3 actionable findings were fixed. No findings were dismissed. The author's fixes included adding a new test (wrangler bindings assertion for env.ASSETS) rather than simply removing dead code.
  5. Efficient resolution — ~2 hours from open to merge for a 104-file PR closing 22 issues.

Gaps identified (all covered by existing issues)

ADR contradiction missed (evidence for agents#720 and agents#265): Qodo caught that the new removal note added to ADR 0019 (stating there is no root npm run build) contradicts the existing Decision text that references npm run dev / npm run build as example scripts. The review agent reviewed this file across 3 runs and never caught the internal contradiction. This is a clear instance of the framing-detail consistency gap described in agents#720 and the narrative synthesis gap in agents#265.

Provenance validation failures (evidence for fullsend#5388 and agents#203): All review runs on this PR failed provenance validation with "unverifiable-wrong-app", forcing prior review context to be discarded. Each re-review started from scratch. In this case the impact was minimal because the author fixed the flagged issues between pushes, but this is a recurring pattern caused by empty REVIEW_APP_CLIENT_ID in per-repo install mode.

Cancelled review run (evidence for fullsend#4960): Run 2 was cancelled after ~17 minutes because a force-push arrived while it was running. This is a known waste pattern tracked across multiple open issues.

No new proposals

All improvement opportunities are already covered by existing open issues. No new proposals are warranted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment