refactor - #4
Merged
Merged
refactor#4
Conversation
…ring into server.ts and delete the pass-through module Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s 8 now-orphaned imports Superseded by orchestrator/reconcileHandler (boot reconciliation). Zero call sites; the 8 imports it owned (Repository, Github, RepositoryHandler, sendMail, IUser, IRepository, DockerContainer, DockerContainerService) are removed with it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t bodies into one private emit() helper Each emit* export kept its name + typed signature (call sites and type safety unchanged); only the repeated userId-guard + try/emit/catch body is deduplicated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…od function Extract hydrateUser, loadCompleteTenancy, ensurePersonalOrg, ensureOwnerMembership, linkDefaultOrganization. The 82-line orchestrator is now a linear read of 5 named single-responsibility steps; each was a self-contained block before. Behavior preserved (tenancy-* suite green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… function Extract backfillRepositories; table-drive the 12 org-stamping passes via ORG_STAMP_PASSES (order preserved: Docker before Metric). 87-line function with two big loops becomes a short orchestrator. Behavior preserved (tenancy suite green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…erNetwork memoization The two private fields were only ever set to null (never assigned the fetched value), so the getDockerImage/getDockerNetwork cache guards never fired and the fetch always ran fresh. Removed the fields, their constructor inits, and the two dead guard lines. Behavior identical (guards were no-ops); IDockerImage/IDockerNetwork imports stay (method return types). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ntainer reloadContainer is typed Promise<void> but returned newContainer; all 6 callers await it without using the value. Removed the misleading return to match the signature. (Full step-extraction of this 68-line fn deferred: no behavioral test exists — reload.test.ts mocks the method — so a daemon-mock test must precede it.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ision.ts Both buildHandler and deployHandler defined byte-identical populateRepository helpers. Moved one copy to provision.ts (their shared dependency) as a named export; both now import it. Dropped buildHandler's now-unused Repository import (tsc 24->23). Behavior identical. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…erviceFields normalizeService and parseLegacy.toService both normalized command/environment/ ports/volumes identically; factored into one helper. splitImageRef left untouched (intentionally different across compose/prebuilt). The '?? raw.env' fallback is a no-op for legacy entries, so behavior is preserved (templates.test.ts green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…>23 (modules 1-8) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…enant filter
The tenant-scope clause (admin->{} else project $in caller's projectIds) was
copy-pasted verbatim in backupDatabase/restoreDatabase/getConnectionString.
Extracted to a local reachableScope(req) helper. NOTE: scanner suggested routing
these through resolveProjectOr403, but that resolves a :projectId param — these
endpoints key off a database :id, so that helper is the wrong tool; a local filter
helper is the correct dedup. Behavior identical.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nual_review (modules 9-10) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rel re-export
Trimmed the 13-line copyright header + import/export indirection to a single
`export { default } from './ProtectedRoute'`, matching sibling organism barrels
(AppShell, StatusBar). Client build green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rom 4 near-identical hooks useUserDockerContainers/Images/Networks/PortBinding shared the same paged-fetch + cleanup-on-unmount shape; each is now a thin config wrapper over a shared useUserResource. Public hook names + return shapes unchanged (barrel intact). Behavior preserved verbatim, including the intentional dataKey/cleanupPath mismatch (e.g. 'dockerContainers' vs 'containers') and portBinding's undefined initial page. useUserRepositories left as-is (60s polling, different shape). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
StatusChip/StatTile/IconButton had zero imports across client/src (grep-confirmed); they were left over from a mid-migration that completed. Client build green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eUserResource, kit aliases) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
errText (err->string|err.message|fallback) was redefined identically in Alerting, SetupOrganization, OrganizationSettings, Team. Moved to @utilities/common/errText and imported. Client build green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n file
EnvironmentsModal was a module-scope sibling component (props-only interface
{project,onClose}, no shared state with Projects), so moving it to its own file
is a pure mechanical extraction. Projects.jsx 528->381 LOC; dropped now-unused
StatusBadge + Trash2 imports. Client build green. (Other god-component smells in
this file — 28 useState, modal-reset dup — deferred: no FE test net.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cate util InstallModal was a module-scope sibling (props-only), extracted to its own file (Templates.jsx 429->279 LOC). truncate was shared by both parent and modal, so relocated to @utilities/common/truncate and imported in both (avoids duplication and a backwards parent<-modal import). Dropped now-unused Input import. Build green. (CatalogBrowser + 14 useState consolidation deferred: no FE test net.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…emplates + 3 god-components -> manual_review); hook truncate fix Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ual_review + run summary Final: 13 completed, 9 manual_review, 15 atomic commits, gate green (server tsc 23/23, vitest 131/131, client build OK). pending=0, in_progress=0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…stopOrchestrator, default barrel
All three were unreferenced: enqueueBuild (only producer of standalone type:'build'
jobs — none are enqueued; runBuild is called directly by deployHandler), stopOrchestrator
(SIGINT handler uses process.exit(0), never calls it), and the export default {...} object
(all import sites use named imports; templateHandler's dynamic import uses the named
.enqueueDatabaseJob). Dispatch 'build' case + buildHandler left intact (runBuild still used).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r.error The updateContainerFile catch block swallowed errors via console.log(error) (a debug leftover). Converted to logger.error with the codebase's file-prefix convention so a writeFile failure is actually recorded instead of going to stdout. Not deleted: the catch has no other handling, so removing it would silently swallow the error. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d-code + dockerFS logger) 2 deletions applied, gate green (server tsc 23/23, vitest 131/131, client build OK). pending=0, in_progress=0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
if(import.meta.env) is always truthy (env is an object), so the timing console.log and error-tracking middleware ran in PRODUCTION on every API call. Changed to import.meta.env.DEV to restore the obvious dev-only intent and silence prod console noise. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
this.authToken = null was set in the constructor but never read or reassigned anywhere (grep across client/src). Speculative field, removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… + dead field) 2 changes, gate green (server tsc 23/23, vitest 131/131, client build OK). pending=0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ive-deployment status Two bugs surfaced when creating a Git app: 1. HTTP 403 'Pool overlaps with other one on this address space' — randomIPv4Subnet picked a /24 blindly with no awareness of existing networks, and could land in 172.16/12 which overlaps Docker's own /16 bridges. Now pickFreeSubnet() reads the live Docker network list and chooses a non-overlapping /24 inside 10.0.0.0/8 (real 32-bit overlap math, random-then-linear-scan, throws if exhausted). Subnet allocation moved from the model's pure pre-save hook to materializeNetwork (it needs Docker I/O); subnet index made sparse since it's now filled post-save. 2. Dashboard showed wrong/empty Status — getMyRepositories read deployments[0] (the OLDEST deployment) instead of the most recent; now reads the last (push-ordered) already-populated deployment's status directly, no extra query. Adds server/tests/network-subnet.test.ts (5 tests: in-range, no-overlap incl. /16 edge case, deterministic fallback, exhaustion). Verified end-to-end on the live daemon: 5 consecutive new networks created with zero Pool overlaps; broken repo redeployed to success. Gate: tsc 23, 136 tests pass, client build OK. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…500) GET /repository/me/ returned HTTP 500 for any user owning a repo without a linked GitHub account: getMyRepositories builds 'new Github(user, repo)' per repo, and the constructor did user.github.getDecryptedAccessToken() — throwing on undefined user.github, BEFORE getRepositoryInfo's graceful-degrade catch, so one GitHub-less repo crashed the entire dashboard list. - Github constructor: null-safe user.github; unauthenticated Octokit when no token (API calls then fail into the existing remoteUnavailable degrade path). cloneRepository private-clone token interpolation made null-safe too. - getMyGithubRepositories / detectFramework: explicit 400 Github::Account::NotLinked instead of a cryptic 500 when the endpoint genuinely requires GitHub. Adds server/tests/github-constructor.test.ts (3 tests). Verified live: GET /repository/me/ now 200 with the repo listed (status none, remote unavailable — correct for a GitHub-less repo). Gate: tsc 23, 139 tests, client build OK. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A validation failure (missing/invalid field) returned HTTP 401, which the frontend treats as an auth failure → logout / redirect to login. So a routine 'field required' error (e.g. POST /port-binding without externalPort) logged the user out instead of showing a field error. ValidationError now maps to 400 Bad Request. Adds server/tests/error-handler.test.ts (5 tests: ValidationError 400, CastError 400, dup-key 400, RuntimeError passthrough, JWT stays 401). Verified live: port-binding without externalPort now returns 400. Gate: tsc 23, 144 tests, client build OK. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s; add PANEL_HOST configuration
… improved styling and layout style: enhance ChartTooltip and Sparkline components with updated styles refactor: modify TopList and Chart axes for better visual consistency fix: adjust PageBody and PageHeader layouts for responsive design feat: add eyebrow prop to PageHeader for additional context style: refine ThemeToggle and NotFound components for better user experience fix: improve ServerUnreachable component layout and messaging test: clean up tests for Avatar and EntitySelect components feat: extend API contracts with new navigation and channel interfaces refactor: enhance query-cache and resource hooks for better state management test: update optimistic writes and resource stream tests for accuracy chore: clean up use-remembered-selection hook and related tests fix: update socket frame tests for correct payload structure chore: tidy up theme store and format-metrics utility functions build: streamline Vite configuration for better plugin management
…d terminal functionalities
Projects carried a per-project Environment layer (production/staging/preview) that nothing behaved differently on: every entity stored environmentId as nullable and always wrote null. Delete the model, service, controller, routes, error table and dialogs, drop environmentId from the database, deployment, metric, repository and template contracts, and add ContainerAddress to docker contracts for repository/database addresses. Rename the seeded default project from 'Default Environment' to 'Default Project'.
cad6dad deleted the environment contracts but kept the api controller, model and service and the web dialog that imported them, so the api crashed on boot and the web build failed on types. Finish the removal.
…tainer Every new Deployment row started with an empty environmentVariables map, so a push wiped what the user had saved, and the map only reached exec-strategy apps through the relaunch exec: Dockerfile and prebuilt image containers were created without it. Copy the previous deployment's variables forward and resolve the container Env from one place that merges the container row with the latest deployment.
…ow its address Each application had its own bridge network, so nothing could reach anything else. Attach every container to quantum-org-<env>-<orgId> with its slugified name as DNS alias, record the IP it gets there on start, restart and reconcile, and show it as an Address column in Applications next to a separate Ports column.
Lift the repository page's editor and row helpers into shared so template installs can reuse them; it autosaves like the rest of the app.
…ment A stack is a TemplateInstall that owns its spec, parsed from the compose file (image, command, environment, ports, named volumes, depends_on; build contexts and bind mounts are refused with the service named), so provisioning, logs, shell and lifecycle are reused as they are. The file and each service's variables are editable from the install page, saved automatically and applied on redeploy, which also tears down services dropped from the file.
One credential per registry and organization, encrypted at rest and managed from Settings → Organization; every image pull now goes through pullImage, which sends the matching credential and, for ghcr.io, falls back to the connected GitHub account (the OAuth login now asks for read:packages). A refused pull names the registry and where to fix it.
- Deleted CreateDomainDialog and CreateUpstreamDialog components. - Removed DomainStatusChip component and its associated styles. - Eliminated Domains page and its related logic for managing domains. - Removed domain error messages and status utilities. - Updated API tests to reflect changes in domain routes to repository routes. - Introduced autosave functionality in forms with a new useAutosave hook. - Added SaveStatus component to display save state in forms.
A code-server sidecar per application: Open in VS Code on a repository or a compose stack page starts a codercom/code-server container that mounts the same files the app sees (the repository checkout, or every named volume of the stack under its service name), joins the app's network and the organization network, and serves on a published port behind a generated password. The dormant codespace module gains its job types, its handler entries and repository/install targets; stop keeps the container down across reconciles, and the workspace goes away with its application. Deleting a codespace never removed its container because the row was gone before the job ran; the ids now travel in the job payload, and tearing down a network first disconnects whatever is still attached.
A repository can now list container paths to keep: each becomes a named Docker volume that the deploy recreates the container around, so data written outside /app survives deploys and restarts. Deploys stop removing volumes (they only ever held nothing before), the container row follows the repository's list on every provision, and the settings page gets a Persistent volumes section that saves and redeploys. Deleting a repository used to leave its container, ports, network and deployments behind; repository.deleted now queues a teardown job that removes them together with the volumes.
After the source is fetched, a .env at the repository's root directory is parsed with dotenv and every variable the user has not set in the Environment tab is added to the deployment, so a fresh repository starts with its own defaults and values set in the panel keep winning.
Rendered from the interface's own fonts and tokens over a real Applications screenshot, with the template catalogue under the title; light and dark variants served through a picture element.
Applications, templates, logs, shell, compose editor, environment, account and organization settings, captured in dark mode from the running stack; the six captures of the old interface are gone.
Deploying Quantum with Docker comes first, then the features, then where the data lives and how to develop. Sections that documented the old UI (NGINX walkthrough, Namecheap, storage screenshots, GitHub OAuth screenshots) are gone with their images; what remains describes the current stack: dashboard ports bound to localhost, HTTPS through Traefik with PANEL_HOST, the template seed command, compose stacks, internal addresses, registries and VS Code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.