Dockhand - Docker management you will like.
This report summarizes scanner evidence for Finsys/dockhand, a TypeScript project with 6,957 GitHub stars. SynthScan examined 531,178 lines of code across 1783 source files, recording 502 pattern matches distributed across 9 syntactic categories. The legacy adjusted pattern signal is 1.1 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 487 finding(s).
Are imports declared and package/API names verified? 10 finding(s).
Are wrappers, guards, and repeated structures necessary? 277 finding(s).
Which changes need focused human review? 502 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 502 distinct pattern matches across 9 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | vite.config.ts | 177 | function buildDockerStreamHttpRequest(path: string, target: DockerTarget, body = ''): string { | CODE |
| LOW | src/hooks.server.ts | 96 | async function cleanupOrphanedScannerContainers() { | CODE |
| LOW | src/lib/git-stack-branch.ts | 71 | export function normalizeStackBranchUpdate( | CODE |
| LOW | src/lib/config/grid-columns.ts | 262 | export function getDefaultColumnPreferences(gridId: GridId): { id: string; visible: boolean }[] { | CODE |
| LOW | src/lib/stores/sidebar-preferences.ts | 67 | function createSidebarPreferencesStore() { | CODE |
| LOW | src/lib/stores/containers.ts | 309 | async function loadPendingUpdatesInternal(envId: number | null) { | CODE |
| LOW | src/lib/stores/grid-preferences.ts | 42 | function createGridPreferencesStore() { | CODE |
| LOW | src/lib/server/stacks.ts | 708 | export function validateStacksDirAtStartup(): void { | CODE |
| LOW | src/lib/server/stacks.ts | 1117 | async function checkFlatLocalStackNameCollision(stackName: string, envId?: number | null): Promise<string | null> { | CODE |
| LOW | src/lib/server/stacks.ts | 2344 | async function cleanupOrphanStackContainers( | CODE |
| LOW | src/lib/server/stacks.ts | 2861 | export async function computeStackDeletionPaths( | CODE |
| LOW | src/lib/server/stacks.ts | 3211 | async function reconcileStackPendingUpdates(stackName: string, envId: number): Promise<void> { | CODE |
| LOW | src/lib/server/stacks.ts | 4083 | async function resolveProviderVarsBestEffort( | CODE |
| LOW | src/lib/server/stacks.ts | 4129 | async function applyProviderSecretsToComposeResult( | CODE |
| LOW | src/lib/server/container-event-notify.ts | 10 | export function shouldNotifyContainerEvent( | CODE |
| LOW | src/lib/server/vulnerabilities-cache.ts | 95 | export function getVulnerabilitiesCacheStats(): { envs: number; views: number; inflight: number } { | CODE |
| LOW | src/lib/server/vulnerabilities-cache.ts | 101 | export function invalidateVulnerabilitiesCache(envIdNum?: number | null): void { | CODE |
| LOW | src/lib/server/scheduled-actions-list.ts | 16 | export async function containerActionScheduleRows() { | CODE |
| LOW | src/lib/server/oidc-callback-core.ts | 25 | export function describeTokenExchangeFailure(status: number, body: string): string { | CODE |
| LOW | src/lib/server/content-disposition.ts | 10 | export function attachmentContentDisposition(filename: string): string { | CODE |
| LOW | src/lib/server/stack-path-utils.ts | 5 | export function getStackPathHintsFromContainers(containers: { labels?: Record<string, string> | null }[]): { | CODE |
| LOW | src/lib/server/stack-path-utils.ts | 59 | export function moveStackFilePathCrossDevice( | CODE |
| LOW | src/lib/server/vulnerabilities.ts | 279 | export function parseVulnerabilitiesQuery(url: URL): VulnerabilitiesQuery { | CODE |
| LOW | src/lib/server/vulnerabilities.ts | 312 | export async function getFilteredSortedFindings(envIdNum: number, query: VulnerabilitiesQuery): Promise<Finding[]> { | CODE |
| LOW | src/lib/server/nav-preferences.ts | 50 | export async function getEffectiveNavPreferences(userId: number | null): Promise<NavPreferences> { | CODE |
| LOW | src/lib/server/license.ts | 187 | export async function hasValidEnterpriseLicense(): Promise<boolean> { | CODE |
| LOW | src/lib/server/token-cache.ts | 79 | export function invalidateTokenCacheForUser(userId: number): void { | CODE |
| LOW | src/lib/server/dockhand-override-file.ts | 14 | export function buildDockhandOverrideFile(envVars: Record<string, string>): string { | CODE |
| LOW | src/lib/server/container-image-divergence.ts | 57 | export function detectImageLabelDivergence( | CODE |
| LOW | src/lib/server/scanner-output-core.ts | 24 | export function classifyUnparseableOutput(output: string): 'truncated' | 'cli-error' | 'unknown' { | CODE |
| LOW | src/lib/server/webhook-secret-policy.ts | 16 | export function decideWebhookSecretPolicy( | CODE |
| LOW | src/lib/server/webhook-secret-policy.ts | 37 | export function webhookConfigRequiresSecret( | CODE |
| LOW | src/lib/server/host-path.ts | 111 | function populateCachesFromInspect(info: OwnContainerInfo, ownDockerHostOverride?: string): void { | CODE |
| LOW | src/lib/server/host-path.ts | 154 | function resolveDataDirFromInspect(info: OwnContainerInfo, dataDir: string): string | null { | CODE |
| LOW | src/lib/server/host-path.ts | 182 | async function inspectOwnContainerViaDbEnv(containerId: string, dataDir: string): Promise<string | null> { | CODE |
| LOW | src/lib/server/host-path.ts | 356 | export function getAutoDetectedDockerHost(): string | null { | CODE |
| LOW | src/lib/server/host-path.ts | 418 | export function translateContainerPathViaMount(containerPath: string): string | null { | CODE |
| LOW | src/lib/server/host-path.ts | 485 | export function unpersistedComposePathWarning( | CODE |
| LOW | src/lib/server/host-path.ts | 577 | export function rewriteComposeVolumePaths(composeContent: string, workingDir: string): { content: string; modified: bool | CODE |
| LOW | src/lib/server/subprocess-manager.ts | 717 | export function refreshSubprocessEnvironments(): void { | CODE |
| LOW | src/lib/server/registry-auth.ts | 41 | export function canReattachAuthOnRedirect(from: string, to: string): boolean { | CODE |
| LOW⚡ | src/lib/server/docker.ts | 3861 | export async function getRegistryManifestDigest(imageName: string, _envId?: number | null, signal?: AbortSignal): Promis | CODE |
| LOW⚡ | src/lib/server/docker.ts | 3865 | export async function getRegistryManifestDigestDetailed(imageName: string, _envId?: number | null, signal?: AbortSignal) | CODE |
| LOW⚡ | src/lib/server/docker.ts | 3874 | async function getRegistryImageCreatedAt(imageName: string, digest: string, envId?: number | null, parentSignal?: AbortS | CODE |
| LOW | src/lib/server/docker.ts | 2046 | async function recreateSystemdManagedContainer( | CODE |
| LOW | src/lib/server/docker.ts | 2135 | async function findRunningContainerByName( | CODE |
| LOW | src/lib/server/docker.ts | 2211 | export async function recreateContainerFromInspect( | CODE |
| LOW | src/lib/server/docker.ts | 2699 | export async function createContainerFromMetadata( | CODE |
| LOW | src/lib/server/docker.ts | 3322 | export async function getImageReleaseAgeWarning(imageName: string, envId?: number | null): Promise<string | null> { | CODE |
| LOW | src/lib/server/docker.ts | 3756 | async function harborListProjectRepositories(baseUrl: string, project: string, headers: Record<string, string>): Promise | CODE |
| LOW | src/lib/server/docker.ts | 3985 | async function localImageMatchesRegistry( | CODE |
| LOW | src/lib/server/docker.ts | 4048 | export async function checkImageUpdateAvailable( | CODE |
| LOW | src/lib/server/docker.ts | 4695 | export async function connectContainerToNetwork( | CODE |
| LOW | src/lib/server/docker.ts | 4748 | export async function connectContainerToNetworkRaw( | CODE |
| LOW | src/lib/server/docker.ts | 4775 | export async function disconnectContainerFromNetwork( | CODE |
| LOW | src/lib/server/docker.ts | 5382 | export async function runContainerWithStreaming(options: { | CODE |
| LOW | src/lib/server/docker.ts | 6541 | export async function getOrCreateVolumeHelperContainer( | CODE |
| LOW | src/lib/server/docker.ts | 6541 | export async function getOrCreateVolumeHelperContainer( | CODE |
| LOW | src/lib/server/docker.ts | 6618 | export async function createVolumeHelperContainer( | CODE |
| LOW | src/lib/server/docker.ts | 6630 | export async function releaseVolumeHelperContainer( | CODE |
| 212 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | scripts/emergency/reset-db.sh | 5 | # WARNING: This will DELETE ALL DATA! | COMMENT |
| LOW | scripts/emergency/restore-db.sh | 5 | # WARNING: This will overwrite the current database! | COMMENT |
| LOW | scripts/emergency/sqlite/reset-db.sh | 4 | # WARNING: This will DELETE ALL DATA including users, settings, and activity logs! | COMMENT |
| LOW | scripts/emergency/sqlite/restore-db.sh | 4 | # WARNING: This will overwrite the current database! | COMMENT |
| LOW | scripts/emergency/postgres/reset-db.sh | 4 | # WARNING: This will DELETE ALL DATA including users, settings, and activity logs! | COMMENT |
| LOW | scripts/emergency/postgres/restore-db.sh | 4 | # WARNING: This will overwrite the current database! | COMMENT |
| LOW⚡ | src/lib/server/docker.ts | 3649 | // Step 1: check the WWW-Authenticate header from /v2/ | COMMENT |
| LOW⚡ | src/lib/server/docker.ts | 3656 | // Step 2: confirm via /api/v2.0/ping | COMMENT |
| LOW⚡ | src/lib/server/env-interpolation.ts | 16 | // Step 1: Find lines matching `- ENV_KEY=...${...}...` | COMMENT |
| LOW⚡ | src/lib/server/env-interpolation.ts | 23 | // Step 2: Extract all ${VAR} references from the value | COMMENT |
| LOW | src/lib/server/git.ts | 1833 | // Step 1: Connecting | COMMENT |
| LOW⚡ | src/lib/server/git.ts | 1845 | // Step 2: Cloning | COMMENT |
| LOW⚡ | src/lib/server/git.ts | 1855 | // Step 3: Fetching (blobless clone - fetches all commits but blobs on-demand) | COMMENT |
| LOW | src/lib/server/git.ts | 1896 | // Step 4: Reading compose file | COMMENT |
| LOW | src/lib/server/git.ts | 1981 | // Step 5: Deploying stack | COMMENT |
| LOW⚡ | src/lib/server/scheduler/tasks/env-update-check.ts | 451 | // Step 1: Pull new image | COMMENT |
| LOW⚡ | src/lib/server/scheduler/tasks/env-update-check.ts | 459 | // Step 2: Get new image ID | COMMENT |
| LOW⚡ | src/lib/server/scheduler/tasks/env-update-check.ts | 466 | // Step 3: SAFETY - Restore original tag to old image | COMMENT |
| LOW⚡ | src/lib/server/scheduler/tasks/env-update-check.ts | 471 | // Step 4: Tag new image with temp suffix | COMMENT |
| LOW⚡ | src/lib/server/scheduler/tasks/env-update-check.ts | 475 | // Step 5: Scan the immutable image ID | COMMENT |
| LOW | src/lib/server/registry/auth-header.ts | 44 | // Step 1: Challenge request to /v2/ (always at registry root, not under org path). | COMMENT |
| LOW | src/lib/server/registry/auth-header.ts | 66 | // Step 2: Parse WWW-Authenticate header | COMMENT |
| LOW | src/lib/server/registry/auth-header.ts | 101 | // Step 3: Request token from realm (with credentials if available). | COMMENT |
| LOW | src/lib/server/registry/manifest-digest.ts | 108 | // Step 1: Challenge request to /v2/ | COMMENT |
| LOW | src/lib/server/registry/manifest-digest.ts | 130 | // Step 2: Parse WWW-Authenticate header | COMMENT |
| LOW | src/lib/server/registry/manifest-digest.ts | 160 | // Step 3: Request token from realm (with credentials if available). | COMMENT |
| LOW⚡ | src/routes/dashboard/DraggableGrid.svelte | 166 | // Step 1: Push items that directly collide with the moved item | COMMENT |
| LOW⚡ | src/routes/dashboard/DraggableGrid.svelte | 176 | // Step 2: Resolve cascading collisions by sorting top-to-bottom and pushing down | COMMENT |
| LOW | src/routes/api/registries/test/+server.ts | 70 | // Step 1: connectivity — can we reach /v2/ at all? | COMMENT |
| LOW | src/routes/api/registries/test/+server.ts | 88 | // Step 2: if credentials provided, test authentication. | COMMENT |
| LOW | src/routes/api/registry/image/+server.ts | 74 | // Step 1: Resolve manifest digest. Try each type individually because | COMMENT |
| LOW | src/routes/api/registry/image/+server.ts | 100 | // Step 2: Delete the manifest by digest using the matched type | COMMENT |
| LOW⚡ | src/routes/api/self-update/+server.ts | 263 | // Step 1: Pull the new Dockhand image | COMMENT |
| LOW⚡ | src/routes/api/self-update/+server.ts | 270 | // Step 2: Build container config from self-inspect | COMMENT |
| LOW⚡ | src/routes/api/self-update/+server.ts | 290 | // Step 3: Pull the updater image | COMMENT |
| LOW⚡ | src/routes/api/self-update/+server.ts | 297 | // Step 4: Create new container with temp name | COMMENT |
| LOW | src/routes/api/self-update/+server.ts | 337 | // Step 5: Launch updater sidecar (point of no return) | COMMENT |
| LOW | …c/routes/api/containers/batch-update-stream/+server.ts | 314 | // Step 1: Pull latest image | COMMENT |
| LOW | …c/routes/api/containers/batch-update-stream/+server.ts | 387 | // Step 2: Scan temp image | COMMENT |
| LOW⚡ | src/routes/backups/CreateBackupModal.svelte | 37 | // Step 1: Select source | COMMENT |
| LOW⚡ | src/routes/backups/CreateBackupModal.svelte | 45 | // Step 2: Configure | COMMENT |
| LOW | src/routes/backups/CreateBackupModal.svelte | 90 | // Step 3: Schedule & Run | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docker-entrypoint-node.sh | 101 | adduser -u "$PUID" -G "$TARGET_GROUP" -h /home/dockhand -D dockhand | COMMENT |
| LOW | tests/preview-env-security.test.ts | 221 | }); | COMMENT |
| LOW | tests/deploy-endpoints.test.ts | 481 | }); | COMMENT |
| LOW | tests/deploy-log-store.test.ts | 201 | // not a permanent miss. | COMMENT |
| LOW | tests/fs-guard.test.ts | 1 | import { describe, test, expect, beforeAll, afterAll } from 'bun:test'; | COMMENT |
| LOW | tests/deploy-run-record.test.ts | 241 | await recorder.end(false, undefined, 'exit code 1'); | COMMENT |
| LOW | updater/update.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/export-stacks.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/reset-mfa.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/relocate-stack-paths.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/reset-password.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/reset-db.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/_relocate-common.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/create-admin.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/backup-db.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/restore-db.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/sqlite/reset-mfa.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/sqlite/reset-password.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/sqlite/create-admin.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/sqlite/backup-db.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/sqlite/restore-db.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/postgres/reset-mfa.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/postgres/reset-password.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/postgres/list-users.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/postgres/create-admin.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/postgres/backup-db.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/emergency/postgres/restore-db.sh | 1 | #!/bin/sh | COMMENT |
| LOW | scripts/openapi/lib.ts | 201 | // * pointer to a related endpoint) | COMMENT |
| LOW | scripts/openapi/lib.ts | 321 | return 0; | COMMENT |
| LOW | scripts/openapi/lib.ts | 561 | COMMENT | |
| LOW | src/lib/env-merge.ts | 1 | // Merge a git stack's repo .env vars with its DB override vars for display in the | COMMENT |
| LOW | src/lib/server/stacks.ts | 1341 | // Anchor for everything compose-adjacent: the directory the compose file | COMMENT |
| LOW | src/lib/server/stacks.ts | 2921 | return withStackLock(stackName, async () => { | COMMENT |
| LOW | src/lib/server/stacks.ts | 3841 | // what the provider supports: | COMMENT |
| LOW | src/lib/server/crash-guard.ts | 1 | // Process-level safety net: a rejected promise that nothing awaits (e.g. an aborted | COMMENT |
| LOW | src/lib/server/git-branch-lookup.ts | 61 | if (bracket) return bracket[1].toLowerCase(); | COMMENT |
| LOW | src/lib/server/dns-dispatcher.ts | 1 | import { setGlobalDispatcher, Agent, EnvHttpProxyAgent, type Dispatcher } from 'undici'; | COMMENT |
| LOW | src/lib/server/dns-dispatcher.ts | 141 | // the backup helper's restic progress). undici's default bodyTimeout (300s) aborts a | COMMENT |
| LOW | src/lib/server/host-path.ts | 581 | // We look for patterns like: | COMMENT |
| LOW | src/lib/server/docker.ts | 2381 | // A container's Config.Env/Labels are flattened at create time, so the old | COMMENT |
| LOW | src/lib/server/docker.ts | 3101 | const existingOptions = extractContainerOptions(oldContainerInfo); | COMMENT |
| LOW | src/lib/server/docker.ts | 4121 | return { hasUpdate: false, currentDigest: currentRepoDigests[0] ?? currentImageId, localDigests }; | COMMENT |
| LOW | src/lib/server/docker.ts | 5481 | // On some Docker hosts (e.g. Synology NAS with older kernels), follow=true | COMMENT |
| LOW | src/lib/server/docker.ts | 5501 | // leave exitCode undefined — the guard below fails closed on undefined. | COMMENT |
| LOW | src/lib/server/sse.ts | 141 | // end() is still counted as "attempted" and never retried. | COMMENT |
| LOW | src/lib/server/preview-env-handler.ts | 101 | */ | COMMENT |
| LOW | src/lib/server/scanner.ts | 861 | COMMENT | |
| LOW | src/lib/server/git.ts | 1501 | console.log(`${logPrefix} Calling deployStack...`); | COMMENT |
| LOW | src/lib/server/git.ts | 1781 | const repoPath = await getStackRepoPath(stackId, gitStack.stackName, gitStack.environmentId); | COMMENT |
| LOW | src/lib/server/git.ts | 2041 | } catch (error) { | COMMENT |
| LOW | src/lib/server/git.ts | 2321 | console.log(`${logPrefix} Temp directory: ${tempDir}`); | COMMENT |
| LOW | src/lib/server/db.ts | 4701 | .returning({ id: scheduleExecutions.id }); | COMMENT |
| LOW | src/lib/server/secretproviders/probe-cache.ts | 21 | } | COMMENT |
| LOW | src/lib/server/backups/restic.ts | 261 | destination.hostPath || translateLocalRepoPath(repo) | COMMENT |
| LOW | src/lib/server/backups/restore-service.ts | 601 | // swap writes to that exact path on `env`'s daemon. If `env` is NOT the snapshot's | COMMENT |
| LOW | src/lib/server/backups/retention.ts | 101 | // held lock before giving up. This runs inside Dockhand's per-repo serializer, so | COMMENT |
| LOW | src/lib/server/backups/backup-service.ts | 321 | // regression in the selectedVolumes filter is visible in the execution log. | COMMENT |
| LOW | src/lib/server/backups/backup-service.ts | 361 | ? `${v.source} → ${v.name}` | COMMENT |
| LOW | src/lib/server/backups/restore-script.ts | 121 | // (e.g. two different snapshots restored into /srv/shared, from different repos so | COMMENT |
| LOW | src/lib/server/backups/index.ts | 161 | // ALL relative binds (files AND dirs), not just dirs: a single-file bind (./config.yaml) | COMMENT |
| 18 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | src/lib/server/docker.ts | 3649 | // Step 1: check the WWW-Authenticate header from /v2/ | COMMENT |
| LOW⚡ | src/lib/server/docker.ts | 3656 | // Step 2: confirm via /api/v2.0/ping | COMMENT |
| LOW⚡ | src/lib/server/env-interpolation.ts | 16 | // Step 1: Find lines matching `- ENV_KEY=...${...}...` | COMMENT |
| LOW⚡ | src/lib/server/env-interpolation.ts | 23 | // Step 2: Extract all ${VAR} references from the value | COMMENT |
| LOW | src/lib/server/git.ts | 1833 | // Step 1: Connecting | COMMENT |
| LOW⚡ | src/lib/server/git.ts | 1845 | // Step 2: Cloning | COMMENT |
| LOW⚡ | src/lib/server/git.ts | 1855 | // Step 3: Fetching (blobless clone - fetches all commits but blobs on-demand) | COMMENT |
| LOW | src/lib/server/git.ts | 1896 | // Step 4: Reading compose file | COMMENT |
| LOW | src/lib/server/git.ts | 1981 | // Step 5: Deploying stack | COMMENT |
| LOW⚡ | src/lib/server/scheduler/tasks/env-update-check.ts | 451 | // Step 1: Pull new image | COMMENT |
| LOW⚡ | src/lib/server/scheduler/tasks/env-update-check.ts | 459 | // Step 2: Get new image ID | COMMENT |
| LOW⚡ | src/lib/server/scheduler/tasks/env-update-check.ts | 466 | // Step 3: SAFETY - Restore original tag to old image | COMMENT |
| LOW⚡ | src/lib/server/scheduler/tasks/env-update-check.ts | 471 | // Step 4: Tag new image with temp suffix | COMMENT |
| LOW⚡ | src/lib/server/scheduler/tasks/env-update-check.ts | 475 | // Step 5: Scan the immutable image ID | COMMENT |
| LOW | src/lib/server/registry/auth-header.ts | 44 | // Step 1: Challenge request to /v2/ (always at registry root, not under org path). | COMMENT |
| LOW | src/lib/server/registry/auth-header.ts | 66 | // Step 2: Parse WWW-Authenticate header | COMMENT |
| LOW | src/lib/server/registry/auth-header.ts | 101 | // Step 3: Request token from realm (with credentials if available). | COMMENT |
| LOW | src/lib/server/registry/manifest-digest.ts | 108 | // Step 1: Challenge request to /v2/ | COMMENT |
| LOW | src/lib/server/registry/manifest-digest.ts | 130 | // Step 2: Parse WWW-Authenticate header | COMMENT |
| LOW | src/lib/server/registry/manifest-digest.ts | 160 | // Step 3: Request token from realm (with credentials if available). | COMMENT |
| LOW⚡ | src/routes/dashboard/DraggableGrid.svelte | 166 | // Step 1: Push items that directly collide with the moved item | COMMENT |
| LOW⚡ | src/routes/dashboard/DraggableGrid.svelte | 176 | // Step 2: Resolve cascading collisions by sorting top-to-bottom and pushing down | COMMENT |
| LOW | src/routes/api/registries/test/+server.ts | 70 | // Step 1: connectivity — can we reach /v2/ at all? | COMMENT |
| LOW | src/routes/api/registries/test/+server.ts | 88 | // Step 2: if credentials provided, test authentication. | COMMENT |
| LOW | src/routes/api/registry/image/+server.ts | 74 | // Step 1: Resolve manifest digest. Try each type individually because | COMMENT |
| LOW | src/routes/api/registry/image/+server.ts | 100 | // Step 2: Delete the manifest by digest using the matched type | COMMENT |
| LOW⚡ | src/routes/api/self-update/+server.ts | 263 | // Step 1: Pull the new Dockhand image | COMMENT |
| LOW⚡ | src/routes/api/self-update/+server.ts | 270 | // Step 2: Build container config from self-inspect | COMMENT |
| LOW⚡ | src/routes/api/self-update/+server.ts | 290 | // Step 3: Pull the updater image | COMMENT |
| LOW⚡ | src/routes/api/self-update/+server.ts | 297 | // Step 4: Create new container with temp name | COMMENT |
| LOW | src/routes/api/self-update/+server.ts | 337 | // Step 5: Launch updater sidecar (point of no return) | COMMENT |
| LOW | …c/routes/api/containers/batch-update-stream/+server.ts | 314 | // Step 1: Pull latest image | COMMENT |
| LOW | …c/routes/api/containers/batch-update-stream/+server.ts | 387 | // Step 2: Scan temp image | COMMENT |
| LOW⚡ | src/routes/backups/CreateBackupModal.svelte | 37 | // Step 1: Select source | COMMENT |
| LOW⚡ | src/routes/backups/CreateBackupModal.svelte | 45 | // Step 2: Configure | COMMENT |
| LOW | src/routes/backups/CreateBackupModal.svelte | 90 | // Step 3: Schedule & Run | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | scripts/emergency/export-stacks.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/clear-sessions.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/reset-mfa.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/relocate-stack-paths.sh | 15 | # Usage: | COMMENT |
| LOW | scripts/emergency/disable-auth.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/reset-password.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/reset-db.sh | 7 | # Usage: | COMMENT |
| LOW | scripts/emergency/list-users.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/create-admin.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/backup-db.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/restore-db.sh | 7 | # Usage: | COMMENT |
| LOW | scripts/emergency/sqlite/clear-sessions.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/sqlite/reset-mfa.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/sqlite/disable-auth.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/sqlite/reset-password.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/sqlite/reset-db.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/sqlite/list-users.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/sqlite/create-admin.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/sqlite/backup-db.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/sqlite/restore-db.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/postgres/clear-sessions.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/postgres/reset-mfa.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/postgres/disable-auth.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/postgres/reset-password.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/postgres/reset-db.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/postgres/list-users.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/postgres/create-admin.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/postgres/backup-db.sh | 6 | # Usage: | COMMENT |
| LOW | scripts/emergency/postgres/restore-db.sh | 6 | # Usage: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | scripts/emergency/export-stacks.sh | 26 | # Check if running locally (not in Docker) | COMMENT |
| LOW | scripts/emergency/sqlite/clear-sessions.sh | 23 | # Check if running locally (not in Docker) | COMMENT |
| LOW | scripts/emergency/sqlite/reset-mfa.sh | 34 | # Check if running locally (not in Docker) | COMMENT |
| LOW | scripts/emergency/sqlite/reset-mfa.sh | 45 | # Check if user exists | COMMENT |
| LOW | scripts/emergency/sqlite/disable-auth.sh | 23 | # Check if running locally (not in Docker) | COMMENT |
| LOW | scripts/emergency/sqlite/reset-password.sh | 41 | # Check if running locally (not in Docker) | COMMENT |
| LOW | scripts/emergency/sqlite/reset-password.sh | 52 | # Check if user exists | COMMENT |
| LOW | scripts/emergency/sqlite/reset-password.sh | 86 | # Check if node and argon2 are available | COMMENT |
| LOW | scripts/emergency/sqlite/reset-db.sh | 32 | # Check if running locally (not in Docker) | COMMENT |
| LOW | scripts/emergency/sqlite/list-users.sh | 20 | # Check if running locally (not in Docker) | COMMENT |
| LOW | scripts/emergency/sqlite/list-users.sh | 48 | # Check if user has Admin role | COMMENT |
| LOW | scripts/emergency/sqlite/create-admin.sh | 30 | # Check if running locally (not in Docker) | COMMENT |
| LOW | scripts/emergency/sqlite/create-admin.sh | 64 | # Check if admin user already exists | COMMENT |
| LOW | scripts/emergency/sqlite/create-admin.sh | 87 | # Check if user already has Admin role | COMMENT |
| LOW | scripts/emergency/sqlite/backup-db.sh | 26 | # Check if running locally (not in Docker) | COMMENT |
| LOW | scripts/emergency/sqlite/restore-db.sh | 40 | # Check if running locally (not in Docker) | COMMENT |
| LOW | scripts/emergency/sqlite/restore-db.sh | 45 | # Check if backup file exists | COMMENT |
| LOW | scripts/emergency/postgres/reset-mfa.sh | 41 | # Check if user exists using psql | COMMENT |
| LOW | scripts/emergency/postgres/reset-password.sh | 65 | # Check if user exists | COMMENT |
| LOW | scripts/emergency/postgres/reset-password.sh | 102 | # Check if node and argon2 are available | COMMENT |
| LOW | scripts/emergency/postgres/list-users.sh | 61 | # Check if user has Admin role | COMMENT |
| LOW | scripts/emergency/postgres/create-admin.sh | 77 | # Check if admin user already exists | COMMENT |
| LOW | scripts/emergency/postgres/create-admin.sh | 100 | # Check if user already has Admin role | COMMENT |
| LOW | scripts/emergency/postgres/restore-db.sh | 64 | # Check if backup file exists | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/backups/restore-script.test.ts | 272 | // script's scaffold cleanup (`rm -rf <staging>/volumes`) depends on that. | COMMENT |
| MEDIUM | tests/backups/restore-script.test.ts | 285 | // scaffold. Reproduce restic's output layout exactly. | COMMENT |
| MEDIUM | scripts/generate-openapi.ts | 319 | // --scaffold <file> | COMMENT |
| MEDIUM | scripts/openapi/lib.ts | 457 | // --scaffold (starting point). Deliberately conservative: false negatives | COMMENT |
| MEDIUM | scripts/openapi/lib.ts | 466 | // shallowly (verified via spot-check across the annotated + scaffold sets). | COMMENT |
| MEDIUM | src/lib/server/backups/restore-script.ts | 132 | // straight into the mount and `rm -rf`-ing a `volumes` scaffold there - that | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/secret-masking.test.ts | 51 | // ─── parseEnvInterpolation ───────────────────────────────────────── | COMMENT |
| MEDIUM | tests/secret-masking.test.ts | 195 | // ─── buildMaskSet (simulates getSecretKeysToMask) ────────────────── | COMMENT |
| MEDIUM | tests/secret-masking.test.ts | 247 | // ─── Provider-injected keys (H1) ─────────────────────────────────── | COMMENT |
| MEDIUM | tests/secret-masking.test.ts | 289 | // ─── Full masking pipeline ───────────────────────────────────────── | COMMENT |
| MEDIUM | src/routes/stacks/StackModal.svelte | 343 | // ─── Path State (Simplified) ───────────────────────────────────────────────── | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/container-labels.test.ts | 212 | 'maintainer': 'admin@example.com', | CODE |
| LOW | src/routes/settings/auth/users/UserModal.svelte | 383 | placeholder={isEditing ? 'admin@example.com' : 'john@example.com'} | CODE |
| LOW | src/routes/settings/auth/users/UserModal.svelte | 393 | placeholder={isEditing ? 'Administrator' : 'John Doe'} | CODE |
| LOW | …routes/settings/notifications/NotificationModal.svelte | 412 | <Input id="notif-smtp-username" bind:value={formSmtpUsername} placeholder="user@example.com" /> | CODE |
| LOW | src/routes/api/auth/login/+server.ts | 25 | * resp-200-example: {"success":true,"user":{"id":1,"username":"admin","email":"admin@example.com","displayName":"Admin" | COMMENT |
| LOW | src/routes/api/auth/session/+server.ts | 11 | * resp-200-example: {"authenticated":true,"authEnabled":true,"user":{"id":1,"username":"admin","email":"admin@example.c | COMMENT |
| LOW | src/routes/api/profile/+server.ts | 60 | * body-example: {"displayName":"Jane Doe","currentPassword":"***","newPassword":"***"} | COMMENT |
| LOW | src/routes/api/users/+server.ts | 23 | * resp-200-example: [{"id":1,"username":"admin","email":"admin@example.com","displayName":"Admin","isAdmin":true,"isAct | COMMENT |
| LOW | src/routes/api/users/+server.ts | 84 | * body-example: {"username":"jdoe","email":"jdoe@example.com","password":"correct horse battery staple","displayName":" | COMMENT |
| LOW | src/routes/api/users/[id]/+server.ts | 89 | * body-example: {"displayName":"Jane Doe","email":"jane@example.com"} | COMMENT |