Skip to content

Deep clean of the codebase - #131

Merged
Isma-L154 merged 8 commits into
mainfrom
chore/deep-clean
Sep 24, 2026
Merged

Isma-L154 merged 8 commits into
mainfrom
chore/deep-clean

Conversation

@Isma-L154

Copy link
Copy Markdown
Owner

Closes #130.

Summary

A repository-wide cleanup: Go core, web app, deployment Worker, scripts, CI and docs. One commit per concern, no intended behaviour change except where a failure used to be silent.

Findings and fixes

Security

  • Share-link decompression was unbounded. A link is capped before decoding (~48 kB), but a crafted one could still expand ~1000× in the recipient's tab. Decompression now stops past twice the workspace limit and reports too-large. Regression test: a 40 MB payload in a sub-64 kB link.
  • Stored workspaces are only restored if every file is text.
  • Reviewed with no change needed: path traversal (normalisePath is used by imports, links and typed paths), the worker channel (timeouts, restart, model version check), the Worker (CSP, headers, fail-open rate limit), CI secrets (only on push and same-repo PRs, least-privilege permissions), and a secrets scan of the tree and history (none found).

Silent failures made visible

  • A shared link that cannot be opened no longer falls back to the stored workspace without a word.
  • Files left out when loading a shared or stored workspace (over a limit, or with an unusable path) are now counted in the footer, so part of a project is never presented as all of it.

CI

  • Seven E2E specs had never run in CI: the workflow listed specs by hand and the list had drifted from package.json (import, camera, examples, editor, files, image, split). There are now two Playwright projects (functional and timed budgets), and CI runs the same test:e2e:browser / test:e2e:performance scripts developers do.

Structure and readability

  • App.tsx 316 → ~250 lines: file operations are fileActions (pure, 5 tests), the header is AppHeader, and "open a workspace" is one function instead of two copies.
  • Four copies of the pluralisation rule are now one plural().
  • announce() takes named options instead of five positional arguments.
  • ImportDropZone is renamed ImportPanel (drops are handled by the page now); .app-import is renamed .header-panel.
  • paths.ts held raw control bytes in a regex, so git treated it as binary; it now uses escapes.
  • Diagram.tsx comment lines 63 → 24, keeping every why.

Dead code and types

  • knip: 9 unused exported types and 1 function made module-private.
  • The only as any (the folder picker's webkitdirectory) is replaced by a typed React augmentation.

Checked and left alone

  • npm audit: 0 vulnerabilities. go vet, staticcheck: clean. go mod tidy: clean. govulncheck: 0 reachable; it notes x/crypto/openpgp (GO-2026-5932, no fix available) in a module the code does not import.
  • The Go functions above cyclomatic complexity 15 (18–19) are switches over Terraform's reference kinds; clear, and in the fuzzed core, so not rewritten.
  • scripts/make-brand-assets.mjs (flagged by knip) is a documented manual script.
  • Generated files (web/src/model/generated/*) come from schemas/ and were not edited.
  • No unused CSS: the flagged classes are built dynamically (dg-edge-${kind}, diagnostic-${severity}).

Remaining debt

  • GitHub Actions are pinned to major tags, not SHAs.
  • A local, untracked spike/ directory (158 MB of old build output) remains on the development machine; it is not in the repository.

Validation

  • npm run verify (generate check, gofmt, go vet, go test, typecheck, lint, format, web tests 281/281, build within budget): pass
  • npm run test:e2e:browser 75/75, npm run test:e2e:performance 7/7: pass
  • knip: only the documented manual script remains

A share link is capped before decoding, but its decompressed size was not:
a link under 64 kB could expand to tens of megabytes in the recipient's
tab. Stop decompressing past twice the workspace limit. A link that could
not be opened used to fall back to the stored workspace silently; the
footer now says so. Stored records are only restored if every file is
text.
CI listed the specs to run by hand, and the list had drifted from
package.json: the import, camera, examples, editor, file, image and split
specs had never run in CI. Two Playwright projects, the functional suite
and the timed budgets, now decide what runs, and CI calls the same npm
scripts as a developer does.
knip found nine exported types and one function nothing imports; they are
module-private now. ImportDropZone no longer handles drops (the page does),
so it is ImportPanel, and the header panel it shares with the examples is
.header-panel. The path check's control-character class held raw control
bytes, which made git treat paths.ts as binary; it is written with escapes.
App had grown to hold the file bar's validation and writes, the header's
markup and the same replace-forget-close sequence twice. File operations
are now fileActions (pure, tested), the header is AppHeader, and opening
a workspace is one function. Four copies of the pluralisation rule are
one.
…130)

Diagram.tsx carried essays where a sentence says the same why; its
comment lines go from 63 to 24 with every reason kept. announce() took
five positional arguments, three of them optional numbers, so its call
sites read as announce(node, parent, connections, 3, 0); they are named.
Loading a workspace skipped files over the limits or with unusable paths
without a word, presenting part of a project as all of it: the one thing
the workspace's limits exist to prevent. The footer now says how many
files were left out.
@github-actions

Copy link
Copy Markdown

Preview: https://07490776-terravisual.ilsproj.workers.dev

Security headers were verified against this deployment.

@Isma-L154
Isma-L154 merged commit 85534d7 into main Sep 24, 2026
7 checks passed
@Isma-L154
Isma-L154 deleted the chore/deep-clean branch September 24, 2026 04:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deep clean of the codebase

1 participant