Commit Graph

2031 Commits

Author SHA1 Message Date
amhsirak e8807096c3 fix: add sdk api gen URL validation 2026-07-16 00:29:30 +05:30
Karishma Shukla ae73f1f676 Merge pull request #1132 from getmaxun/wait-logic
fix: add wait for ready logic scrape
2026-07-15 23:28:08 +05:30
Karishma Shukla 79b1e995c8 Merge pull request #1130 from getmaxun/strip-hidden
fix: strip hidden base64-encoded data blobs
2026-07-15 23:06:42 +05:30
Karishma Shukla a5ea29ca29 Merge pull request #1128 from getmaxun/llm-config
fix: cover llm config setup for all robot types
2026-07-15 22:53:29 +05:30
Rohit Rajan 5ae84cdb7e fix: check hex 64bit key 2026-07-15 21:35:51 +05:30
Karishma Shukla a078b9fea7 Merge pull request #1138 from hmhngx/feat/incremental-run-persistence
fix: persist crawl/search results incrementally instead of only at the end of the run
2026-07-15 13:58:36 +05:30
hmhngx 0c0033216f chore: drop jest test infra to keep PR scoped to persistence fix
Per maintainer review (RohitR311 on #1138): the repo has no existing
test infra or CI to run tests, so introducing jest here is out of
scope. Removes jest configs, test files, tsconfig.test.json, the
test:server script, and jest/ts-jest/@types/jest/jest-environment-jsdom
dependencies from both maxun-core and server.

output-validation.ts stays - it's a real production module (not test
code) extracted to fix the duplicated isPartial bug CodeRabbit flagged;
only its test file is dropped.
2026-07-13 21:16:32 +07:00
Karishma Shukla 4731cce37c Merge pull request #1134 from sebastiondev/fix/cwe20-inputhandlers-onchangeur-522c
fix(browser-management): restrict handleChangeUrl to http(s) schemes
2026-07-10 18:42:38 +05:30
hmhngx 5b19898341 test(server): cover mergeSearchDelta empty-state and no-mutation cases
mergeCrawlDelta already had tests for an undefined starting state and
for not mutating its inputs; mergeSearchDelta was missing the same
coverage.
2026-07-10 14:36:06 +07:00
hmhngx 84c96baa24 fix(server): roll back crawl/search persist cursor on dropped writes
computeCrawlSearchPersistDelta advances lastPersistedResultCount as
soon as a delta is computed, before the write is confirmed. If
flushPersistenceBuffer exhausts its retries and drops the batch, that
data was never actually written, but the cursor had already moved
past it - so it was silently lost forever instead of being resent
with the next page's delta.

Roll the cursor back by the dropped delta's size when a batch is
dropped, so the next page recovers the lost items instead of skipping
them. Covered by two new tests exercising the real retry-exhaustion
path via a rejecting sequelize.transaction mock.
2026-07-10 14:16:38 +07:00
hmhngx 3198a92041 fix(server): set partialDataExtracted before triggerIntegrationUpdates
If triggerIntegrationUpdates threw, the catch(_) swallowed it and left
partialDataExtracted false even though hasData was true, so isPartial
was persisted incorrectly on the failure path.
2026-07-10 14:16:29 +07:00
hmhngx 5b37919042 fix(server): correct isPartial detection for scrapeSchema/scrapeList
Addresses CodeRabbit review on #1138 (both findings confirmed valid
against the actual code, not just the review's claim):

- hasData's scrapeSchema/scrapeList checks used `.length > 0`, but both
  are always plain objects keyed by action name, never arrays -
  `.length` on a plain object is undefined, so the check could never
  be true. isPartial could never reflect a run whose only partial
  output was scrapeSchema/scrapeList. Pre-existing bug, not introduced
  by this PR, but copied into abortRun's check when extending it here.
- abortRun reloaded the run before checking for partial data but never
  forced the interpreter's persistence buffer to flush first -
  scrapeList isn't on the immediate-flush allowlist, so a buffered
  scrapeList page could be invisible to the reload.

Both fixes now live in one place (hasPartialOutput /
flushReloadAndCheckPartialOutput in output-validation.ts) instead of
duplicated inline in task-runner.ts's two call sites, which is how the
same bug ended up in two places to begin with.

Verified with mutation testing: reintroduced the .length > 0 bug,
confirmed 3 tests fail; reintroduced the reload-before-flush ordering
bug, confirmed the ordering test fails; restored the fix, all 14 pass.
2026-07-10 11:41:08 +07:00
hmhngx 54e88270c9 test(server): mock storage/mino in the delta-persistence tests
Rebasing onto the latest develop pulled in #1105's per-page screenshot
upload path, which added a BinaryOutputService import to Interpreter.ts
that attempts a real MinIO connection at module load. Mock it so these
tests stay hermetic instead of noisily (and potentially flakily)
failing to connect to a MinIO that isn't there in CI.
2026-07-10 10:56:02 +07:00
hmhngx af5198e172 fix(server): exclude tests from the production build
Same class of bug already fixed on the maxun-core side: `tsc -p
server/tsconfig.json` (the actual build:server script) was compiling
server/src/**/__tests__ into server/dist, since the base tsconfig's
include (src/**/*) picked them up with nothing excluding them. Found
by actually running the production build rather than trusting
--noEmit type-checks, which don't reveal what gets emitted.
2026-07-10 10:45:23 +07:00
hmhngx 52639c4c1e test(server): add delta/merge tests for crawl and search persistence
server had no test infra at all (no test script, no jest config). Add
jest/ts-jest scoped to server/, and directly unit test
computeCrawlSearchPersistDelta/mergeCrawlDelta/mergeSearchDelta - the
new delta-slicing and append-merge logic - without needing to mock
the database or drive a full interpreter run.

Verified these tests actually catch the regression they're meant to:
temporarily reverted the slicing to send full arrays again and
confirmed 4 of the 11 tests fail, including the end-to-end one showing
the exact page duplication the fix prevents.
2026-07-10 10:45:22 +07:00
hmhngx d5bfe00ef2 fix(server): persist crawl/search deltas instead of full snapshots
crawl/search deliver the full cumulative array on every page callback,
and persistDataToDatabase was writing that whole array to Postgres on
every single page - meaning page 1's data got re-sent on every write
for the rest of the run, an O(n^2) total-bytes cost that gets worse
the more pages a crawl visits (each carrying full page HTML).

Track how many items have already been persisted per action and slice
off just the new ones before they reach the persistence buffer, then
append (rather than overwrite) that delta into the existing DB state.
The in-memory cache and socket broadcast are untouched - only what
gets written to Postgres changes. Extracted as computeCrawlSearchPersistDelta/
mergeCrawlDelta/mergeSearchDelta so this can be tested directly.
2026-07-10 10:45:22 +07:00
hmhngx 60951196bc feat(server): add isPartial flag for interrupted crawl/search runs
status alone doesn't distinguish a failed/aborted run that still has
usable partial data from one with nothing recovered - that signal only
existed transiently in socket/webhook payloads and was lost on reload.
Persist it as a real column, set from both the crash-catch path and
abortRun, and expose it via formatRunResponse.

Also fix abortRun's partial-data check, which only looked at
scrapeSchema/scrapeList and missed crawl/search entirely, and reload
the run before checking since the interpreter's persistence buffer
writes through a separate Run instance.
2026-07-10 10:45:22 +07:00
hmhngx 9c39ff9fcf fix(server): flush crawl/search persistence immediately
persistDataToDatabase only force-flushed the batched write immediately
for scrapeSchema; everything else, including per-page crawl/search
writes, sat in the buffer for up to 3s or 5 items before hitting
Postgres. A hard process kill inside that window would still lose
data. Extend the immediate-flush condition to crawl and search too.
2026-07-10 10:45:22 +07:00
asherdrake 1f60733f86 fix: preserve base64 screenshot entries when end-of-run upload retry fails 2026-07-08 17:19:56 -07:00
asherdrake e24d13c274 memoize bucket config check, and construct BinaryOutputService at call site 2026-07-08 15:18:47 -07:00
emperor 087fe81159 feat: upload each screenshot to MinIO immediately after capture
Screenshots were captured per page (single scraping pass) but held in
memory as base64 for the whole run and bulk-uploaded to MinIO only at
the end. Since maxun-core awaits binaryCallback after each page scrape,
the run-mode callback is the natural upload point: page N's screenshot
now lands in MinIO and run.binaryOutput (as a public URL) before page
N+1 is scraped.

- BinaryOutputService.uploadBinaryOutputItem: single-item upload,
  extracted from the bulk loop so object-key and public-URL
  construction (#832) stay single-source. Returns null on failure
  instead of throwing.
- Run-mode binaryCallback uploads first; on failure the item keeps its
  base64 payload so the end-of-run bulk upload retries it.
- uploadAndStoreBinaryOutput passes already-uploaded URL entries
  through untouched, making the end-of-run call idempotent — required
  because it fully replaces run.binaryOutput.
- persistBinaryDataToDatabase stores URL entries as plain strings so
  the mid-run DB shape matches the final uploaded shape.

Applies to all run-mode screenshots (crawl/search page captures and
regular screenshot actions share the same callback payload).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 13:36:43 -07:00
asherdrake 0fc11a694e fix: address CodeRabbit review on single-pass screenshot capture
- validate formats in PUT /runs/:id before persisting, so a malformed
  value can't reach the interpreter and break formats.includes(...)
- re-throw on failed search-result navigation so it records an error
  entry instead of scraping/screenshotting the stale page (matches the
  crawl loop's behavior)
- correct stale getNavigationWaitStrategy JSDoc (networkidle is driven
  by visualRenderRequired, not screenshot formats)
- fix duplicated phrase in processRobotOutputFormats JSDoc
2026-07-05 16:03:03 -07:00
asherdrake 564a90f083 Merge branch 'getmaxun:develop' into fix/single-pass-screenshots 2026-07-05 15:04:20 -07:00
emperor a7283d0c31 fix: capture crawl/search screenshots in single scraping pass reducing time from 2N pages just down to N (#1105) 2026-07-04 16:05:51 -07:00
Sebastion 8cc3b38b7a docs(browser-management): clarify ALLOWED_NAVIGATION_PROTOCOLS scope
Address CodeRabbit review: the previous doc comment near
ALLOWED_NAVIGATION_PROTOCOLS overstated what the URL check protects
against. It implied that filtering by scheme alone would also block
navigation to internal HTTP(S) endpoints, which is not the case:
http://localhost, http://127.0.0.1, http://169.254.169.254, RFC1918
ranges etc. still pass because they use the http(s) scheme.

Reword the JSDoc to:
- describe this check as scheme validation only (WHATWG URL parser +
  http/https allowlist)
- keep the non-network URI examples (file:, chrome:, data:, javascript:)
  that this check does block
- add an explicit "Limitations" note stating that internal-host SSRF
  is not mitigated and would require separate host/IP-range filtering
  in the input:url handling path

No behavioural change.
2026-07-04 03:20:27 +01:00
Sebastion f80dec2a42 fix(browser-management): restrict handleChangeUrl to http(s) schemes
The recording browser worker exposes an `input:url` socket event which
forwarded the client-supplied URL directly to `page.goto(url)` in
`handleChangeUrl`. Because Playwright runs on the server, any recording
client could coerce the shared worker into loading `file:///etc/passwd`,
`chrome://`, `about:`, `data:`, `javascript:` URIs, or arbitrary internal
HTTP endpoints. The response then becomes accessible to subsequent scrape
steps and is exfiltrated as run output.

Parse the incoming URL with the WHATWG URL API and reject anything whose
protocol is not `http:` or `https:` before generating the workflow pair
and before invoking `page.goto`. Malformed URLs (parser throws), relative
paths, protocol-relative URLs and opaque schemes are all rejected. The
rejection reuses the existing `emitBrowserPageError` broadcast so the
client sees a friendly message instead of a silent no-op.

CWE-20 (Improper Input Validation).
2026-07-03 21:44:25 +01:00
amhsirak 03afbe9865 chore: remove unused import 2026-07-03 18:28:25 +05:30
amhsirak 1625523891 chore: remove unused import 2026-07-03 18:28:14 +05:30
amhsirak 412f7fa622 chore: remove unused import 2026-07-03 18:26:50 +05:30
Rohit Rajan 6aee602a54 fix: add wait for ready logic scrape 2026-06-30 15:34:41 +05:30
amhsirak f91b70995b fix: strip hidden blob data 2026-06-29 16:23:53 +05:30
Rohit Rajan 7c5b1310e7 fix: address coderabbit reviews 2026-06-26 14:29:16 +05:30
Rohit Rajan 58130b88da fix: cover llm config setup for all robot types 2026-06-26 13:56:22 +05:30
Rohit Rajan d18dee467e fix: code duplication 2026-06-24 22:42:54 +05:30
Karishma Shukla c739dcbf5c Merge pull request #1122 from getmaxun/optim-imgs
fix: reduce docker images size
2026-06-24 22:11:22 +05:30
Rohit 67c17673cb Merge branch 'develop' into scrape-fixes 2026-06-24 22:03:48 +05:30
Rohit 3c40f8a693 Merge branch 'develop' into multi-site 2026-06-24 21:58:36 +05:30
Karishma Shukla 665261c3be Merge pull request #1116 from getmaxun/squery-clean
fix: clean smart query data display
2026-06-24 21:53:08 +05:30
Karishma Shukla 40f400e786 Merge pull request #1115 from getmaxun/chrome-error
fix: chrome web data network error display
2026-06-24 21:52:05 +05:30
Karishma Shukla b28eb2245b Merge pull request #1113 from getmaxun/llm-rob-create
fix: display llm robot create on reload or tab switch
2026-06-24 21:46:41 +05:30
Rohit Rajan 9b7e11fabb fix: reduce docker images size 2026-06-24 20:58:33 +05:30
Rohit Rajan c9dcf14f51 chore: cleanup 2026-06-20 11:12:04 +05:30
Rohit Rajan daafed9088 fix: md conversion reliability, llm extraction accuracy 2026-06-20 11:03:49 +05:30
Rohit Rajan 5c824bc903 feat: add support for multi url llm extraction 2026-06-20 10:14:44 +05:30
Rohit Rajan 38d66dd357 fix: create llm extract robot stub 2026-06-20 09:53:02 +05:30
Rohit Rajan f5f20185d5 fix: clean smart query data display 2026-06-19 12:15:29 +05:30
Rohit Rajan 8e05672c55 fix: add error message display chrome web data error 2026-06-19 11:53:09 +05:30
Osamaali313 755e7687c5 fix(storage): honor MINIO_PUBLIC_URL for browser-facing object URLs
Screenshot/file URLs written to a run's binaryOutput were built from the
internal MinIO host/port (defaulting to localhost:9000). Any deployment
where MinIO sits behind a reverse proxy or on a non-localhost public
address produced unreachable URLs, so stored screenshots never loaded.

Prefer a complete public base URL via MINIO_PUBLIC_URL (e.g.
https://storage.example.com) and fall back to the existing
MINIO_PUBLIC_HOST:MINIO_PORT composition for local/dev setups, so existing
configurations are byte-for-byte unchanged. Documents the variable in ENVEXAMPLE.

Fixes #832
2026-06-14 00:09:51 +03:00
Rohit Rajan 86e4936938 fix: llm pagination and limit 2026-06-10 22:53:21 +05:30
Rohit Rajan 618db65da5 chore: specify all formats in web2api 2026-06-08 18:34:39 +05:30