🌐 The Internet Computer! Free, Open-Source, and Self-Hostable.
This report summarizes scanner evidence for HeyPuter/puter, a TypeScript project with 43,669 GitHub stars. SynthScan examined 707,003 lines of code across 2087 source files, recording 1165 pattern matches distributed across 12 syntactic categories. The legacy adjusted pattern signal is 5.1 (Moderate 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.
Can maintainers explain intent, assumptions, and trade-offs? 270 finding(s).
Are imports declared and package/API names verified? 115 finding(s).
Are wrappers, guards, and repeated structures necessary? 839 finding(s).
Which changes need focused human review? 1165 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 1165 distinct pattern matches across 12 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 |
|---|---|---|---|---|
| MEDIUM | install.sh | 56 | # ── Step 1: dependency check ──────────────────────────────────────── | COMMENT |
| MEDIUM | install.sh | 64 | # ── Step 2: install dir ───────────────────────────────────────────── | COMMENT |
| MEDIUM | install.sh | 82 | # ── Step 3: docker-compose.yml + Caddy config ────────────────────── | COMMENT |
| MEDIUM | install.sh | 100 | # ── Step 4: secrets, .env, config.json ────────────────────────────── | COMMENT |
| MEDIUM | install.sh | 220 | # ── Step 5: bring it up ───────────────────────────────────────────── | COMMENT |
| MEDIUM | docker-compose.yml | 190 | # ── Optional: local LLM ─────────────────────────────────────────── | COMMENT |
| MEDIUM | src/dev-center/js/apps.js | 3050 | // ── App Users modal ────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/puter-js/tests/api/suites/ai.suite.ts | 456 | // ── Unified driver routing ────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/extensions.test.ts | 99 | // ── Registry writers ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/extensions.test.ts | 181 | // ── Event subscription ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/extensions.test.ts | 209 | // ── Route registration ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/extensions.test.ts | 342 | // ── Import proxy ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/clients/database/MySQLDatabaseClient.test.ts | 183 | // ── Replica read failover ─────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/driverPolicies.test.ts | 63 | // ── Non-AI drivers (migrated from hardcoded-permissions) ──────────── | COMMENT |
| MEDIUM | src/backend/drivers/driverPolicies.test.ts | 275 | // ── Iface coordination cross-check ────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/driverPolicies.test.ts | 291 | // ── Cross-driver invariants ──────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/meta.test.ts | 38 | // ── validateDriverRateLimit ───────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/meta.test.ts | 149 | // ── resolveDriverMethodRateLimit ──────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/meta.test.ts | 188 | // ── @Driver decorator: rateLimit propagation ──────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/meta.test.ts | 277 | // ── validateDriverConcurrent ──────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/meta.test.ts | 346 | // ── resolveDriverMethodConcurrent ─────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/meta.test.ts | 377 | // ── @Driver — concurrent option ───────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/meta.test.ts | 446 | // ── requireSubscription ───────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/meta.test.ts | 550 | // ── requireReputation ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/ai-ocr/OCRDriver.test.ts | 59 | // ── SDK mocks ─────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/ai-ocr/OCRDriver.test.ts | 101 | // ── Test harness ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/ai-ocr/OCRDriver.test.ts | 179 | // ── getReportedCosts ──────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/ai-ocr/OCRDriver.test.ts | 197 | // ── Argument validation ───────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/ai-ocr/OCRDriver.test.ts | 241 | // ── AWS Textract ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/ai-ocr/OCRDriver.test.ts | 415 | // ── Mistral OCR ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/ai-ocr/OCRDriver.test.ts | 780 | // ── Credit pre-flight ─────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/ai-ocr/OCRDriver.test.ts | 980 | // ── Default provider selection ────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/kv/KVStoreDriver.test.ts | 1686 | // ── Budget enforcement ─────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/util/fileInput.test.ts | 37 | // ── Test harness ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/util/fileInput.test.ts | 121 | // ── inferFilenameFromUrlOrPath ───────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/util/fileInput.test.ts | 153 | // ── loadFileInput — argument validation ───────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/util/fileInput.test.ts | 200 | // ── loadFileInput — data URL path ─────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/util/fileInput.test.ts | 298 | // ── loadFileInput — FS path ───────────────────────────────────────── | COMMENT |
| MEDIUM | src/backend/drivers/util/fileInput.test.ts | 421 | // ── loadFileInput web URL ────────────────────────────────────────── | COMMENT |
| MEDIUM | …ackend/drivers/notification/NotificationDriver.test.ts | 28 | // ── Test harness ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …ackend/drivers/notification/NotificationDriver.test.ts | 111 | // ── create ────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …ackend/drivers/notification/NotificationDriver.test.ts | 236 | // ── read ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …ackend/drivers/notification/NotificationDriver.test.ts | 288 | // ── select / predicates ───────────────────────────────────────────── | COMMENT |
| MEDIUM | …ackend/drivers/notification/NotificationDriver.test.ts | 373 | // ── mark_shown / mark_acknowledged ───────────────────────────────── | COMMENT |
| MEDIUM | …ackend/drivers/notification/NotificationDriver.test.ts | 463 | // ── Audience scoping ──────────────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 64 | // ── Test harness ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 110 | // ── Helpers ───────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 134 | // ── Model catalog ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 187 | // ── Auth + model resolution ───────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 421 | // ── Happy path: events + cost emission ────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 624 | // ── Validation event routing ──────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 681 | // ── Credit gate + max_tokens cap ──────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 1110 | // ── Claude thinking_tokens ────────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 1257 | // ── Normalisation ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 1345 | // ── OpenAI-shape normalization ────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 1632 | // ── Fallback / error envelope ─────────────────────────────────────── | COMMENT |
| MEDIUM | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 1806 | // ── Streaming ─────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …/drivers/ai-chat/providers/providerConsistency.test.ts | 78 | // ── Upstream SDK mocks ────────────────────────────────────────────── | COMMENT |
| MEDIUM | …/drivers/ai-chat/providers/providerConsistency.test.ts | 141 | // ── Harness ───────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …/drivers/ai-chat/providers/providerConsistency.test.ts | 339 | // ── Per-dialect upstream fixtures ─────────────────────────────────── | COMMENT |
| 715 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | src/dev-center/js/libs/jquery-3.6.0.min.js | 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):f | CODE |
| CRITICAL | src/puter-js/src/lib/utils.verificationGate.test.js | 90 | const asked = puter.ui.requestVerificationGate.mock.calls.map( | CODE |
| CRITICAL | …backend/controllers/fs/sharedFolderWrites.http.test.ts | 156 | const emit = env.server.clients.event.emit.bind( | CODE |
| CRITICAL⚡ | src/backend/services/permission/GroupGrants.test.ts | 32 | const user = await fx.env.server.stores.user.getById(userId); | CODE |
| CRITICAL⚡ | src/backend/services/permission/GroupGrants.test.ts | 40 | const owner = await fx.env.server.stores.user.getById(ownerId); | CODE |
| CRITICAL⚡ | src/backend/services/permission/GroupGrants.test.ts | 42 | await fx.env.server.clients.db.write( | CODE |
| CRITICAL⚡ | src/backend/services/permission/GroupGrants.test.ts | 51 | fx.env.server.clients.db.booleanValue(false), | CODE |
| CRITICAL | src/backend/services/permission/GroupGrants.test.ts | 288 | const owner = await fx.env.server.stores.user.getById( | CODE |
| CRITICAL | src/backend/services/permission/GroupGrants.test.ts | 333 | const rows = (await fx.env.server.clients.db.read( | CODE |
| CRITICAL | src/backend/services/permission/GroupGrants.test.ts | 356 | await fx.env.server.stores.team.softDelete(fx.b.uid); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareAccess.test.ts | 40 | const user = await fx.env.server.stores.user.getById(userId); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareAccess.test.ts | 48 | fx.env.server.services.acl.check( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareAccess.test.ts | 53 | fx.env.server.services.fs.getAncestorChain(path), | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareAccess.test.ts | 61 | const owner = await fx.env.server.stores.user.getById(ownerId); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareAccess.test.ts | 63 | await fx.env.server.clients.db.write( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareAccess.test.ts | 71 | fx.env.server.clients.db.booleanValue(false), | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 46 | const user = await fx.env.server.stores.user.getById(userId); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 53 | const owner = await fx.env.server.stores.user.getById(ownerId); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 55 | await fx.env.server.clients.db.write( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 63 | fx.env.server.clients.db.booleanValue(false), | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 77 | const share = await fx.env.server.services.share.share(actor, { | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 82 | await fx.env.server.services.shareNotification.notifyShared(actor, [ | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 89 | const rows = await fx.env.server.stores.notification.listByUserId( | CODE |
| CRITICAL | src/backend/services/share/TeamShareNotify.test.ts | 177 | const team = await fx.env.server.stores.team.getByUid(fx.a.uid); | CODE |
| CRITICAL | src/backend/services/share/TeamShareNotify.test.ts | 178 | await fx.env.server.stores.team.addMember( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 219 | const fresh = await fx.env.server.stores.user.create({ | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 225 | await fx.env.server.stores.team.addMember(fx.a.uid, fresh.id, { | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 230 | await fx.env.server.stores.userBlock.create( | CODE |
| CRITICAL | src/backend/services/share/TeamShareNotify.test.ts | 253 | await fx.env.server.stores.userBlock.deleteByPair( | CODE |
| CRITICAL | src/backend/services/share/TeamShareNotify.test.ts | 273 | await fx.env.server.services.share.share(actor, { | CODE |
| CRITICAL | src/backend/services/share/TeamShareNotify.test.ts | 282 | await fx.env.server.services.shareNotification.notifyShared( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 296 | await fx.env.server.services.share.share(actor, { | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 305 | await fx.env.server.services.shareNotification.notifyShared( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 312 | const team = await fx.env.server.stores.team.getByUid(fx.a.uid); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShareNotify.test.ts | 313 | const members = await fx.env.server.stores.team.listMemberIdsByGroupId( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 43 | const owner = await fx.env.server.stores.user.getById(ownerId); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 45 | await fx.env.server.clients.db.write( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 53 | fx.env.server.clients.db.booleanValue(false), | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 62 | const owner = await fx.env.server.stores.user.getById(ownerId); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 73 | fx.env.server.clients.db.write( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 81 | fx.env.server.clients.db.booleanValue(isDir), | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 88 | await fx.env.server.stores.fsEntry.getEntryByUuid(dirUid); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 442 | const team = await fx.env.server.stores.team.getByUid(fx.a.uid); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 443 | const entry = await fx.env.server.stores.fsEntry.getEntryByUuid( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 446 | await fx.env.server.stores.share.upsertActiveGroup({ | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 458 | const rows = await fx.env.server.stores.permission.readUserGroupPerms( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 468 | const entry = await fx.env.server.stores.fsEntry.getEntryByUuid( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 475 | await fx.env.server.stores.share.listGroupReachingMembers([ | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 566 | const team = await fx.env.server.stores.team.getByUid(fx.a.uid); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 567 | const entry = await fx.env.server.stores.fsEntry.getEntryByUuid(file.uid); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 568 | await fx.env.server.stores.share.upsertActiveGroup({ | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 575 | const rows = await fx.env.server.stores.share.listGroupOnFsentry(entry.id); | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 582 | const left = await fx.env.server.stores.permission.readUserGroupPerms( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 773 | const fileEntry = await fx.env.server.stores.fsEntry.getEntryByUuid( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 776 | await fx.env.server.stores.share.upsertActive({ | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 783 | const dirEntry = await fx.env.server.stores.fsEntry.getEntryByUuid( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 786 | const issuers = await fx.env.server.stores.share.listIssuerIdsBySubtree( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 793 | const members = await fx.env.server.stores.team.memberIdsAmong( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 831 | await fx.env.server.stores.permission.readUserGroupPerms( | CODE |
| CRITICAL⚡ | src/backend/services/share/TeamShare.test.ts | 836 | const entry = await fx.env.server.stores.fsEntry.getEntryByUuid( | CODE |
| 24 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | install.sh | 1 | #!/usr/bin/env sh | COMMENT |
| LOW | install.sh | 21 | # PUTER_URL base URL to fetch docker-compose.yml (default: GitHub raw, main branch) | COMMENT |
| LOW | install.sh | 61 | docker compose version >/dev/null 2>&1 \ | COMMENT |
| LOW | docker-compose.yml | 1 | --- | COMMENT |
| LOW | docker-compose.yml | 21 | # grabs this file, generates secrets, writes .env + config.json, and runs | COMMENT |
| LOW | docker-compose.yml | 321 | condition: service_started | COMMENT |
| LOW | extensions/whoami.ts | 41 | // Keys that must never leave the server, whoever put them on the response. | COMMENT |
| LOW | extensions/whoami.ts | 161 | unconfirmed_email: user.email, | COMMENT |
| LOW | extensions/useremailrx/index.ts | 61 | subdomain: 'api', | COMMENT |
| LOW | .github/workflows/puterjs-tests.yaml | 101 | # SDK coverage on both refs, reported as a PR comment — same shape as | COMMENT |
| LOW | src/dev-center/js/apps.js | 1921 | `/${auth_username}/AppData/${dev_center_uid}/${app.uid ?? app.uuid}`, | COMMENT |
| LOW | src/puter-js/test/aiProviders.test.js | 1 | /* eslint-disable */ | COMMENT |
| LOW | src/puter-js/test/signin.test.js | 1 | /* eslint-disable */ | COMMENT |
| LOW | src/puter-js/tests/e2e/specs/requestPermission.spec.js | 761 | expect(await page.evaluate(() => !!puter.authToken)).toBe(false); | COMMENT |
| LOW | src/puter-js/tests/e2e/specs/requestPermission.spec.js | 841 | // as soon as it has answered, which can happen before a listener | COMMENT |
| LOW | src/puter-js/src/lib/networkUtils.js | 481 | COMMENT | |
| LOW | src/puter-js/src/modules/UI.js | 501 | // we start from 1 because 0 is falsy and we want to avoid that for the message id | COMMENT |
| LOW | src/puter-js/src/modules/UI.js | 521 | // onWindowClose() is executed right before the window is closed. Users can override this function | COMMENT |
| LOW | src/puter-js/src/modules/UI.js | 541 | COMMENT | |
| LOW | src/puter-js/src/modules/UI.js | 561 | // Also shared with the SDK, whose token handler pins on the same set. | COMMENT |
| LOW | src/puter-js/src/modules/UI.js | 1961 | // reports a permission the user granted as denied. Parse once and | COMMENT |
| LOW | src/puter-js/src/modules/UI.js | 2061 | // the window the user is looking at — it reads `true` for a | COMMENT |
| LOW | src/puter-js/src/modules/UI.js | 2081 | // relationship is intact, so having seen it proves a close is a | COMMENT |
| LOW | src/puter-js/src/modules/UI.js | 2181 | // won't construct, no `document.body` yet because this was called | COMMENT |
| LOW | src/puter-js/src/modules/UI.js | 2341 | checkClosed = null; | COMMENT |
| LOW | src/puter-js/src/modules/UI.js | 2581 | COMMENT | |
| LOW | …r-js/src/modules/FileSystem/operations/upload/index.js | 141 | // we want to avoid uploading files in case there is not enough storage space. | COMMENT |
| LOW | src/backend/config.ts | 21 | import path from 'node:path'; | COMMENT |
| LOW | src/backend/config.ts | 121 | // API lives on the `api.` subdomain on the same host+port as the main | COMMENT |
| LOW | src/backend/server.ts | 261 | servicesContainers[serviceName] = this.services[serviceName]; | COMMENT |
| LOW | src/backend/server.ts | 581 | cookieName: this.#config.cookie_name, | COMMENT |
| LOW | src/backend/server.ts | 821 | this.#app.use( | COMMENT |
| LOW | src/backend/server.ts | 841 | // | COMMENT |
| LOW | src/backend/server.ts | 1001 | // that subdomain(s). Routes WITHOUT a `subdomain` option (and that | COMMENT |
| LOW | src/backend/server.ts | 1081 | mwChain.push(requireVerifiedAccount()); | COMMENT |
| LOW | src/backend/server.ts | 1261 | // from req.body — body is already parsed by the global JSON | COMMENT |
| LOW | src/backend/clients/event/types.ts | 341 | // accounts) before any Stripe SetupIntent is created. | COMMENT |
| LOW | src/backend/clients/event/types.ts | 761 | }; | COMMENT |
| LOW | src/backend/drivers/callableMethods.test.ts | 21 | import { puterDrivers } from './index.js'; | COMMENT |
| LOW | src/backend/drivers/util/aiLimits.ts | 21 | DEFAULT_FREE_SUBSCRIPTION, | COMMENT |
| LOW | …c/backend/drivers/ai-chat/ChatCompletionDriver.test.ts | 1701 | const line = warn.mock.calls | COMMENT |
| LOW | src/backend/drivers/ai-chat/ChatCompletionDriver.ts | 1441 | // What the request would get with money no object. | COMMENT |
| LOW | src/backend/drivers/ai-chat/providers/azure/models.ts | 21 | COMMENT | |
| LOW | …drivers/ai-chat/providers/mistral/MistralAiProvider.ts | 261 | } | COMMENT |
| LOW | src/backend/drivers/subdomain/SubdomainDriver.ts | 181 | if (!rootDirId) { | COMMENT |
| LOW | src/backend/drivers/subdomain/SubdomainDriver.ts | 661 | // { | COMMENT |
| LOW | src/backend/drivers/workers/WorkerDriver.ts | 221 | // Without this the driver falls back to the generic 600/minute default, | COMMENT |
| LOW | src/backend/drivers/workers/WorkerDriver.ts | 1041 | 400, | COMMENT |
| LOW | src/backend/drivers/apps/AppDriver.js | 701 | // 2. Raw base64 (no prefix) of a real image — normalized to a | COMMENT |
| LOW | src/backend/drivers/apps/AppDriver.js | 1081 | // Icon sizing hook (for future AppIconService integration) | COMMENT |
| LOW | src/backend/core/reputation.ts | 21 | import { isSystemActor, type Actor } from './actor'; | COMMENT |
| LOW | src/backend/core/http/types.ts | 321 | /** Internal: the property name used to stash decorator metadata on prototypes. */ | COMMENT |
| LOW | src/backend/core/http/middleware/rateLimit.js | 261 | else memoryConcurrentCounts.set(key, c - 1); | COMMENT |
| LOW | src/backend/core/http/middleware/puterSite.ts | 421 | // mirror of the private redirect above. Covers two cases: | COMMENT |
| LOW | src/backend/core/http/middleware/privateAppGate.test.ts | 961 | // app_uid=attacker; using it as a bootstrap on the target host | COMMENT |
| LOW | src/backend/util/nodeFetchDispatcherGuard.ts | 21 | // dispatcher slot — `Symbol.for('undici.globalDispatcher.1')`, shared with | COMMENT |
| LOW | src/backend/util/nodeFetchDispatcherGuard.ts | 41 | // data: fetch cannot fail meaningfully; if it ever does, the slot is | COMMENT |
| LOW | src/backend/util/nativeImport.ts | 21 | // analysis, but the resulting function inherits a vm context with no | COMMENT |
| LOW | src/backend/stores/index.ts | 81 | COMMENT | |
| LOW | src/backend/stores/app/AppStore.js | 101 | // - ownership: `owner_user_id`, `app_owner` — set via `create`'s second | COMMENT |
| 110 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | extensions/thumbnails.ts | 148 | async function decodeAndValidateThumbnail( | CODE |
| LOW | src/dev-center/js/apps.js | 2709 | function getDefaultPreviewImagesState () { | CODE |
| LOW | src/dev-center/js/apps.js | 2717 | function createPreviewThumbElement (item) { | CODE |
| LOW | src/puter-js/test/index.html | 1220 | function updateMasterCheckboxState() { | CODE |
| LOW | src/puter-js/src/modules/EmailConfirmationDialog.js | 259 | export function showEmailConfirmationDialog (message) { | CODE |
| LOW | src/puter-js/src/modules/Email/ComposerLib.js | 62 | export function determineTopLevelMimeType({ attachments = [], text, html }) { | CODE |
| LOW | src/backend/drivers/meta.ts | 180 | export function resolveDriverMethodRateLimit( | CODE |
| LOW | src/backend/drivers/meta.ts | 270 | export function resolveDriverMethodConcurrent( | CODE |
| LOW | src/backend/drivers/meta.ts | 296 | export function validateDriverRequireSubscription( | CODE |
| LOW | src/backend/drivers/meta.ts | 336 | export function resolveDriverMethodRequireSubscription( | CODE |
| LOW | src/backend/drivers/meta.ts | 363 | export function validateDriverRequireReputation( | CODE |
| LOW | src/backend/drivers/meta.ts | 403 | export function resolveDriverMethodRequireReputation( | CODE |
| LOW | src/backend/drivers/util/fileInput.ts | 343 | export function inferFilenameFromUrlOrPath( | CODE |
| LOW | src/backend/drivers/ai-video/creditCap.ts | 57 | export async function capSecondsToRemainingCredits({ | CODE |
| LOW | src/backend/drivers/ai-speech2txt/providerAliases.ts | 55 | export function normalizeSpeechToTextProvider( | CODE |
| LOW | src/backend/drivers/subdomain/SubdomainDriver.ts | 916 | function mapEntryToSubdomainRootDir(entry: FSEntry): Record<string, unknown> { | CODE |
| LOW | src/backend/core/http/middleware/rateLimit.js | 477 | export function listConfiguredRateLimitBackends() { | CODE |
| LOW | src/backend/core/http/middleware/rateLimit.js | 568 | export function computeNetworkFingerprint(req) { | CODE |
| LOW | src/backend/core/http/middleware/privateAppGate.ts | 191 | export async function resolveOwnedAppForHostedSite(opts: { | CODE |
| LOW | src/backend/core/http/middleware/privateAppGate.ts | 478 | export async function resolvePublicHostedIdentity(opts: { | CODE |
| LOW⚡ | src/backend/util/hostedAppBacking.ts | 61 | function normalizeHostedDomainValue(domainValue: unknown): string | null { | CODE |
| LOW⚡ | src/backend/util/hostedAppBacking.ts | 70 | function normalizeConfiguredHostedDomain(domainValue: unknown): string | null { | CODE |
| LOW⚡ | src/backend/util/hostedAppBacking.ts | 76 | function configuredHostedDomainValues( | CODE |
| LOW | src/backend/util/hostedAppBacking.ts | 107 | export function buildHostedSubdomainIndexUrlCandidates( | CODE |
| LOW | src/backend/util/hostedAppBacking.ts | 151 | export function extractPuterHostedSubdomain( | CODE |
| LOW | src/backend/util/hostedAppBacking.ts | 207 | export async function hostedIndexUrlBackingIsUnavailable({ | CODE |
| LOW | src/backend/util/hostedAppBacking.ts | 238 | export async function hostedIndexUrlBackingsAreUnavailable({ | CODE |
| LOW | src/backend/util/cardFallback.ts | 79 | export function cardFallbackAfterAttempts( | CODE |
| LOW | src/backend/util/cardFallback.ts | 139 | export function resetCardVerificationStatusCache(): void { | CODE |
| LOW | src/backend/util/cardFallback.ts | 147 | export async function isCardVerificationEnabled( | CODE |
| LOW | src/backend/util/inlineContentSecurity.ts | 38 | export function applyInlineContentSecurity( | CODE |
| LOW | src/backend/util/fileSigning.ts | 76 | function computeOwnerBoundSignature( | CODE |
| LOW | src/backend/util/fileSigning.ts | 224 | function noteLegacySignatureAccepted(): void { | CODE |
| LOW | src/backend/util/privateLaunchAccess.ts | 106 | export async function resolvePrivateLaunchAccess({ | CODE |
| LOW | src/backend/stores/metering/retention.ts | 28 | export function resolveMeteringRetentionMonths(config: { | CODE |
| LOW | src/backend/stores/fs/S3ObjectStore.ts | 56 | export function clampSignedUploadExpirySeconds(requested: unknown): number { | CODE |
| LOW | src/backend/stores/fs/pendingUploadSessionHelpers.ts | 30 | export function toPendingUploadSessionKey(sessionId: string): string { | CODE |
| LOW | src/backend/stores/fs/pendingUploadSessionHelpers.ts | 34 | export function toPendingUploadSessionExpiresAtSeconds( | CODE |
| LOW | src/backend/stores/fs/pendingUploadSessionHelpers.ts | 97 | export function normalizePendingUploadSession( | CODE |
| LOW | src/backend/stores/fs/pendingUploadSessionHelpers.ts | 145 | export function withPendingUploadSessionStatus( | CODE |
| LOW | src/backend/controllers/fs/legacyFsHelpers.ts | 356 | function mapAppForLegacyAssociatedApp( | CODE |
| LOW | src/backend/controllers/fs/legacyFsHelpers.ts | 585 | export function signingConfigFromAppConfig(config: IConfig): SigningConfig { | CODE |
| LOW | src/docs/build.js | 115 | function createDirectoryRecursively (directoryPath) { | CODE |
| LOW | src/docs/build.js | 122 | function removeDirectoryRecursively (directoryPath) { | CODE |
| LOW | src/docs/build.js | 166 | function generateSearchTriggerHTML () { | CODE |
| LOW | src/docs/build.js | 195 | function generateTableOfContentsHTML (htmlContent, title) { | CODE |
| LOW | src/docs/build.js | 236 | function generatePlatformCompatibilityHTML (frontMatter) { | CODE |
| LOW | src/docs/build.js | 693 | function getDescriptionFromMarkdown (sourcePath) { | CODE |
| LOW | src/mcp-connector/src/oauth.js | 140 | function protectedResourceMetadata(event) { | CODE |
| LOW | src/gui/src/UI/UIWindowPasswordChangeRequired.js | 25 | function UIWindowPasswordChangeRequired (options) { | CODE |
| LOW | src/gui/src/UI/UIWindowEmailConfirmationRequired.js | 23 | function UIWindowEmailConfirmationRequired (options) { | CODE |
| LOW | src/gui/src/UI/UIWindowPhoneVerificationRequired.js | 81 | function UIWindowPhoneVerificationRequired(options) { | CODE |
| LOW | src/gui/src/UI/UIWindowCardVerificationRequired.js | 66 | function UIWindowCardVerificationRequired(options) { | CODE |
| LOW | src/gui/src/UI/UIWindowDesktopBGSettings.js | 22 | async function UIWindowDesktopBGSettings (options) { | CODE |
| LOW | src/gui/src/UI/Settings/UIWindowConfirmUserDeletion.js | 23 | async function UIWindowConfirmUserDeletion (options) { | CODE |
| LOW | src/gui/src/UI/Settings/UIWindowFinalizeUserDeletion.js | 24 | async function UIWindowFinalizeUserDeletion (options) { | CODE |
| LOW | src/gui/src/UI/Dashboard/UIProfilePictureCropModal.js | 61 | export default function UIProfilePictureCropModal ({ picture, onSave, $container, returnFocusTo }) { | CODE |
| LOW | src/gui/src/helpers/verification_gates.js | 48 | export async function openVerificationGateWindow (code, { factors } = {}) { | CODE |
| LOW | src/gui/src/helpers/notificationApi.js | 39 | export async function markNotificationAcknowledged (uid) { | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | src/dev-center/js/websites.js | 57 | // Step 1: Show directory picker | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 67 | // Step 2: Ask for website name | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 71 | // Step 3: Create website with selected directory | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 447 | // Step 1: Show directory picker | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 454 | // Step 2: Confirm the change since it will replace the current website | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 474 | // Step 3: Show loading spinner | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 478 | // Step 4: Delete the existing website | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 481 | // Step 5: Create a new website with the same name but new directory | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 484 | // Step 6: Refresh the websites list to show the updated directory | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 487 | // Step 7: Show success message | COMMENT |
| LOW | src/dev-center/js/workers.js | 75 | // Step 1: Show file picker limited to .js files | COMMENT |
| LOW⚡ | src/dev-center/js/workers.js | 87 | // Step 2: Ask for worker name | COMMENT |
| LOW⚡ | src/dev-center/js/workers.js | 91 | // Step 3: Create worker with selected file | COMMENT |
| LOW | src/puter-js/test/ai.test.js | 113 | // For streaming, we need to check if it's an async iterator or has a different structure | COMMENT |
| LOW | src/docs/src/playground/examples/ai-image-edit.html | 8 | // Step 1: Generate initial image | COMMENT |
| LOW | src/docs/src/playground/examples/ai-image-edit.html | 23 | // Step 2: Edit the image in a follow-up turn | COMMENT |
| LOW | src/gui/src/index.js | 58 | // window.disable_temp_users might be set somewhere else, so we need to check if it is already set and if not, use t | COMMENT |
| LOW | src/gui/src/lib/jquery-ui-1.13.2/jquery-ui.js | 17258 | // IE sets focus asynchronously, so we need to check if focus | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | src/dev-center/js/websites.js | 57 | // Step 1: Show directory picker | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 67 | // Step 2: Ask for website name | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 71 | // Step 3: Create website with selected directory | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 447 | // Step 1: Show directory picker | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 454 | // Step 2: Confirm the change since it will replace the current website | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 474 | // Step 3: Show loading spinner | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 478 | // Step 4: Delete the existing website | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 481 | // Step 5: Create a new website with the same name but new directory | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 484 | // Step 6: Refresh the websites list to show the updated directory | COMMENT |
| LOW⚡ | src/dev-center/js/websites.js | 487 | // Step 7: Show success message | COMMENT |
| LOW | src/dev-center/js/workers.js | 75 | // Step 1: Show file picker limited to .js files | COMMENT |
| LOW⚡ | src/dev-center/js/workers.js | 87 | // Step 2: Ask for worker name | COMMENT |
| LOW⚡ | src/dev-center/js/workers.js | 91 | // Step 3: Create worker with selected file | COMMENT |
| LOW | src/docs/src/playground/examples/ai-image-edit.html | 8 | // Step 1: Generate initial image | COMMENT |
| LOW | src/docs/src/playground/examples/ai-image-edit.html | 23 | // Step 2: Edit the image in a follow-up turn | COMMENT |
| LOW | src/docs/src/AI/chat.md | 786 | // Step 1: Generate initial image | COMMENT |
| LOW | src/docs/src/AI/chat.md | 801 | // Step 2: Edit the image in a follow-up turn | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | extensions/whoami.test.ts | 100 | const { seat, team } = await seatOf('Acme Corp'); | CODE |
| LOW | extensions/whoami.test.ts | 110 | name: 'Acme Corp', | CODE |
| LOW | extensions/whoami.test.ts | 129 | const { seat } = await seatOf('Acme Corp'); | CODE |
| LOW | src/puter-js/tests/api/suites/components.suite.ts | 431 | prompt.setAttribute('placeholder', 'e.g. Ada'); | CODE |
| LOW | src/puter-js/tests/e2e/specs/requestAppData.spec.js | 62 | phone: { value: '555-0101' }, | CODE |
| LOW | src/puter-js/tests/e2e/specs/requestAppData.spec.js | 167 | seed: { phone: { value: '555-0101' } }, | CODE |
| LOW | src/puter-js/src/ui/components/PuterPrompt.js | 153 | const placeholder = this.getAttribute('placeholder') || ''; | CODE |
| LOW | src/puter-js/src/modules/UI.js | 1270 | if ( placeholder ) el.setAttribute('placeholder', placeholder); | CODE |
| LOW⚡ | src/puter-js/src/modules/teams/teams.test.js | 77 | 'PUT /teams/t-1': { ...TEAM_ROW, name: 'Acme Inc' }, | CODE |
| LOW⚡ | src/puter-js/src/modules/teams/teams.test.js | 81 | await expect(teams.update('t-1', { name: 'Acme Inc' })).resolves.toEqual({ ...TEAM, name: 'Acme Inc' }); | CODE |
| LOW⚡ | src/puter-js/src/modules/teams/teams.test.js | 83 | expect(call(1).body).toEqual({ name: 'Acme Inc' }); | CODE |
| LOW | src/backend/drivers/kv/KVStoreDriver.readCache.test.ts | 42 | email: 'test@test.com', | CODE |
| LOW | src/backend/drivers/kv/KVStoreDriver.test.ts | 48 | email: 'test@test.com', | CODE |
| LOW | src/backend/drivers/workers/WorkerDriver.test.ts | 40 | email: 'test@test.com', | CODE |
| LOW | src/docs/src/UI/prompt.md | 34 | puter.ui.prompt('Please enter your name:', 'John Doe').then((resp) => { | CODE |
| LOW | src/docs/src/playground/examples/ui-prompt.html | 5 | puter.ui.prompt('Please enter your name:', 'John Doe').then((resp) => { | CODE |
| LOW | src/docs/src/playground/examples/workers-exec.html | 187 | profile: { name: 'John Doe', email: 'john@example.com' }, | CODE |
| LOW | src/gui/src/UI/UIWindowPhoneVerificationRequired.js | 668 | if (inp) inp.setAttribute('placeholder', phone_example_for(c.iso) || ''); | CODE |
| LOW | src/gui/src/UI/UIQRCode.js | 78 | if ( options.appendTo && options.appendTo.$ === 'placeholder' ) { | CODE |
| LOW | src/gui/src/UI/UIQRCode.js | 93 | if ( destination && destination.$ === 'placeholder' ) { | CODE |
| LOW | src/gui/src/UI/UIWindowShare.js | 449 | if ( teams.length ) $recipient.attr('placeholder', i18n('share_add_people_teams', [], false)); | CODE |
| LOW | src/gui/src/UI/Dashboard/UIShareModal.js | 661 | $recipient.attr('placeholder', label).attr('aria-label', label); | CODE |
| LOW | src/gui/src/UI/Dashboard/teamBadge.test.js | 14 | const h = teamBadgeHtml({ team: { uid: 't-1', name: 'Acme Corp' } }); | CODE |
| LOW | src/gui/src/UI/Dashboard/teamBadge.test.js | 16 | expect(h).toContain('Acme Corp'); | CODE |
| LOW | src/gui/src/util/Placeholder.js | 42 | $: 'placeholder', | CODE |
| LOW | src/gui/src/util/Component.js | 160 | if ( destination.$ === 'placeholder' ) { | CODE |
| LOW | src/gui/src/lib/jquery-ui-1.13.2/jquery-ui.min.js | 6 | !function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(V){"use strict" | CODE |
| LOW | src/gui/src/lib/jquery-ui-1.13.2/jquery-ui.js | 2591 | element.data( dataSpace + "placeholder", placeholder ); | CODE |
| LOW | src/gui/src/lib/jquery-ui-1.13.2/jquery-ui.js | 2604 | var dataKey = dataSpace + "placeholder", | CODE |
| LOW | src/gui/src/helpers/shareSuggest.test.js | 97 | teams: [{ ...ACME, name: 'Acme Corp' }], | CODE |
| LOW | src/gui/src/helpers/shareSuggest.test.js | 100 | expect(names(out)).toEqual(['Acme Corp']); | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | src/puter-js/src/modules/Workers.js | 192 | // envelope from the backend, exactly as requested. | COMMENT |
| HIGH | src/backend/controllers/puterai/PuterAIController.ts | 256 | // Reverse-proxies AI-generated video URLs that can't be given | COMMENT |
| HIGH | src/gui/src/lib/jquery-ui-1.13.2/jquery-ui.js | 8706 | // Format a name, short or long as requested | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | src/docs/src/FS.md | 92 | puter.print('Error creating directory:', error); | CODE |
| MEDIUM | …/docs/src/playground/examples/fs-write-from-input.html | 11 | puter.print('Error writing file:', error); | CODE |
| MEDIUM | src/docs/src/playground/examples/fs-mkdir.html | 10 | puter.print('Error creating directory:', error); | CODE |
| MEDIUM | src/docs/src/FS/mkdir.md | 51 | puter.print('Error creating directory:', error); | CODE |
| MEDIUM | src/docs/src/FS/write.md | 76 | puter.print('Error writing file:', error); | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | src/gui/src/i18n/translations/nn.js | 187 | confirm_2fa_setup: 'Eg har lagt til koden i autentikatorappen min', // In English: "I have added the code to my | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | …puter-js/src/modules/FileSystem/operations/scaffold.js | 1 | // Shared scaffold for the filesystem operations in this directory. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | install.sh | 4 | # Usage: | COMMENT |