Commit graph

3019 commits

Author SHA1 Message Date
Anish Sarkar
0ef02c43cc test(native-connector): cover reddit parser mappings 2026-07-04 17:28:17 +05:30
Anish Sarkar
1b1e612e20 test(native-connector): cover reddit fetch resilience 2026-07-04 17:28:13 +05:30
Anish Sarkar
4d950ddcb5 test(native-connector): add reddit post fixture 2026-07-04 17:28:08 +05:30
Anish Sarkar
672f79d620 test(native-connector): add reddit listing fixture 2026-07-04 17:28:02 +05:30
Anish Sarkar
83f52b17b1 test(native-connector): add reddit comment fixture 2026-07-04 17:27:56 +05:30
Anish Sarkar
f14bf1f06d test(native-connector): add reddit scraper test package 2026-07-04 17:27:53 +05:30
Anish Sarkar
975fdad0ef test(native-connector): add live reddit scraper e2e check 2026-07-04 17:27:47 +05:30
Anish Sarkar
3956045221 feat(native-connector): classify reddit scrape urls 2026-07-04 17:27:44 +05:30
Anish Sarkar
eaa8239e36 feat(native-connector): add reddit scraper orchestrator 2026-07-04 17:27:38 +05:30
Anish Sarkar
dd43ab8505 feat(native-connector): add reddit scraper schemas 2026-07-04 17:27:33 +05:30
Anish Sarkar
0745f433ab feat(native-connector): add reddit json parsers 2026-07-04 17:27:22 +05:30
Anish Sarkar
7151465e12 feat(native-connector): add anonymous reddit fetch layer 2026-07-04 17:27:13 +05:30
Anish Sarkar
1115d647cb feat(native-connector): expose reddit scraper public API 2026-07-04 17:26:58 +05:30
Anish Sarkar
54eab56b25 docs(native-connector): document anonymous reddit scraper design 2026-07-04 17:26:12 +05:30
DESKTOP-RTLN3BA\$punk
7185079bd6 feat(native-connector): added google maps places & reviews scrapers 2026-07-02 21:58:24 -07:00
DESKTOP-RTLN3BA\$punk
cc99bc4cae Update licensing information for SurfSense software
- Added Business Source License 1.1 details to the proprietary LICENSE file.
- Clarified terms of use, including production use restrictions and transition to Apache License after four years.
- Updated README.md to reflect the new licensing structure and its implications for users.

This change ensures clear communication of licensing terms for proprietary components within the SurfSense project.
2026-07-02 03:28:42 -07:00
DESKTOP-RTLN3BA\$punk
0445c646c6 refactor(native-connector): relocate youtube scraper under app/proprietary + parallelize playlists
Move app/scrapers -> app/proprietary/scrapers/youtube to sit alongside the existing proprietary web_crawler/platforms namespace, updating all external imports (routes, tests, e2e script, README). Internal imports were relative so are unchanged.

Also parallelize playlist per-video resolution: page video ids sequentially, then resolve the heavy watch-page fetches concurrently via fan_out (~150 videos ~70s, down from a few minutes). Items stream in completion order; sort by the order field for playlist order.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-02 02:34:04 -07:00
DESKTOP-RTLN3BA\$punk
99378d7b63 feat(native-connector): added youtube scrapers 2026-07-02 01:10:31 -07:00
DESKTOP-RTLN3BA\$punk
15fd0b08d6 feat: completed init mvp of phase 3 2026-06-30 03:02:40 -07:00
DESKTOP-RTLN3BA\$punk
bdacea8b6e feat(crawler): captcha solving + per-attempt billing (Phase 3d)
Wire captchatools as the StealthyFetcher-tier page_action to detect, harvest
(egressing from the crawl's own proxy IP), inject, and submit reCAPTCHA v2/v3
and hCaptcha tokens. Opt-in and off by default (zero attempts, zero cost).

Licensing split:
- Apache-2 app/utils/captcha/ holds the generic, vendor-agnostic config
  (CaptchaConfig + captcha_enabled() = flag AND key present).
- Proprietary app/proprietary/web_crawler/captcha.py holds the bypass logic
  (detect/harvest/inject) plus a process-wide solver latch that halts solving
  on unrecoverable errors (no balance / bad key).

Crawler: CrawlOutcome gains captcha_attempts/captcha_solved, surfaced via a
per-call captcha_state dict threaded crawl_url -> _crawl_with_stealthy(_sync)
and stamped onto every stealth terminal outcome. The stealth tier captures the
proxy once and reuses it for both the fetch and the solver (IP-coherence).

Billing: WebCrawlCreditService gains captcha_billing_enabled,
captcha_solves_to_micros, charge_captcha, and a generic check_balance, sharing
a single _apply_debit path. The indexer accumulates attempts (even on failed
crawls), runs a combined crawl+captcha pre-flight, and posts a per-attempt
owner charge as usage_type="web_crawl_captcha". The captcha worst-case is only
reserved when solving is actually enabled, so a solving-off deployment is never
blocked for captcha that can never run. Both chat scrape tools fold attempts
into the current turn before the success/fail branch.

Fully config-driven prices; no migration. New unit tests cover the config,
factory (detection/latch/timeout/cap), credit service, indexer wiring, and the
chat fold.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 22:58:21 -07:00
DESKTOP-RTLN3BA\$punk
17bdb06825 feat(03c): bill credits per successful web crawl
Add a config-driven crawl meter (1 USD / 1000 successes by default, retunable
via WEB_CRAWL_MICROS_PER_SUCCESS) mirroring EtlCreditService:

- WebCrawlCreditService (gate -> pre-check -> post-charge) on the unified wallet
- webcrawler indexer: pre-flight credit block + post-charge of the workspace
  owner per success, with a web_crawl TokenUsage audit row
- chat scrape_webpage (main + research): fold each successful scrape into the
  active turn's token accumulator so it settles with the chat turn
- WEB_CRAWL_CREDIT_BILLING_ENABLED / WEB_CRAWL_MICROS_PER_SUCCESS config + env
- unit tests (service) + integration tests (indexer wiring)
- scripts/e2e_phase3_crawl_billing.py: manual functional e2e (3a/3b/3c)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 21:40:53 -07:00
DESKTOP-RTLN3BA\$punk
62260125f7 feat(03b): add BYO custom proxy provider + bounded crawler rotation-retry
Add CustomProxyProvider (single endpoint or rotating pool via Scrapling ProxyRotator), registered as 'custom' alongside anonymous_proxies and selectable via PROXY_PROVIDER. Adds is_pool_backed to the ProxyProvider ABC + a zero-arg package helper. The web crawler does a bounded one-per-tier is_proxy_error rotation-retry gated on is_pool_backed() (single-endpoint providers no-op). Config/.env.example gain CUSTOM_PROXY_URL(S). Zero-arg getter contract unchanged for all consumers. Documents the proprietary boundary test (generic proxy infra stays Apache-2). Tests: provider, registry, crawler rotation (16).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 21:03:34 -07:00
DESKTOP-RTLN3BA\$punk
5c36cd3071 feat(03a): implement Scrapling-only web crawler and remove Firecrawl integration
- Standardized the web crawler to use Scrapling exclusively, removing Firecrawl entirely.
- Updated the crawler's location to `app/proprietary/web_crawler/connector.py` under a non-Apache-2 license boundary.
- Refactored the `WebCrawlerConnector` to eliminate the Firecrawl API key dependency, simplifying the interface for crawling URLs.
- Adjusted related components to accommodate the new structure and ensure successful crawl outcomes are properly handled.
- Updated documentation to reflect these changes and the new implementation status.
2026-06-29 20:37:56 -07:00
DESKTOP-RTLN3BA\$punk
2836654701 Merge commit '683a7d3bc2' into feat/rename-searchspace-to-workspace 2026-06-29 17:55:15 -07:00
Rohan Verma
32951ac141
Merge pull request #1543 from DhruvTilva/fix/codeblock-interior-line-indentation
fix: prevent spurious leading spaces in nested codeBlock interior lines
2026-06-29 17:45:21 -07:00
Rohan Verma
d22131185f
Merge pull request #1542 from DhruvTilva/fix/multilingual-embedding-truncation
fix: use token-safe truncation for document embeddings
2026-06-29 17:44:55 -07:00
DESKTOP-RTLN3BA\$punk
47e4dd9403 Merge commit '2148053569' into dev 2026-06-26 11:30:37 -07:00
DESKTOP-RTLN3BA\$punk
ab7d138b32 feat(hotpatch): fix migration 168 2026-06-26 11:30:06 -07:00
Rohan Verma
2148053569
Merge pull request #1544 from AnishSarkar22/fix/login-button
feat: update authentication defaults to LOCAL
2026-06-26 11:06:22 -07:00
CREDO23
902b3374ea docs(env): update spawn-paused runbook to workspace_id (Phase 2 carve-outs)
Align the .env.example operational runbook with the renamed Redis key
surfsense:spawn_paused:<workspace_id> (carve-out 3). All other carve-out
decisions are applied inline: KEEP enum values 'SEARCH_SPACE', Celery task names,
OTel/metric key "search_space.id", and historical alembic migrations; RENAME the
Redis/event/LangGraph keys and the default seed name "My Workspace".
2026-06-26 18:38:11 +02:00
CREDO23
ca9bd28934 test: rename SearchSpace -> Workspace across tests + fixtures (Phase 2 Wave F)
Apply the same rename to surfsense_backend/tests: workspace_id fields/vars,
Workspace* classes/schemas, table name searchspaces -> workspaces in raw SQL,
and the API URL spellings -> /workspaces. Preserves the carve-out wire literals
tests assert (Celery task names, OTel key "search_space.id").
2026-06-26 18:36:46 +02:00
CREDO23
56826a63bc refactor(routes): rename to workspace + consolidate URL spellings (Phase 2 Wave E)
Hard cutover of the HTTP surface: collapse the three legacy spellings
(/searchspaces, /search-spaces, /search-space/{id}) onto canonical
/workspaces/{workspace_id}/..., rename the gateway field-setter sub-actions to
singular /workspace, rename search_spaces_routes.py -> workspaces_routes.py and the
search_spaces_router -> workspaces_router include, and flip search_space_id ->
workspace_id in bodies/params. No alias routers: the old URLs now 404 by design.
Full app constructs with zero legacy path spellings.
2026-06-26 18:35:08 +02:00
CREDO23
7fb0707933 refactor(backend): rename search_space -> workspace across app bulk (Phase 2 Wave D)
Scoped codemod over surfsense_backend/app (excluding routes/, Wave E): renames
search_space_id -> workspace_id, search_space -> workspace, SearchSpace -> Workspace
across services, utils, tasks, agents, gateway, event_bus, notifications, podcasts,
automations, observability params, and prompt .md files. Also flips the camelCase
payload key searchSpaceId -> workspaceId (no backend reader; hard cutover).

Preserved carve-outs (verbatim): Celery task names "delete_search_space_background"
and "ai_sort_search_space" (wire names), and the OTel/metric key "search_space.id"
(dashboards depend on it). Enum values 'SEARCH_SPACE' and SearchSourceConnector
untouched.
2026-06-26 18:30:47 +02:00
CREDO23
0c53d884eb refactor(schemas): rename SearchSpace -> Workspace in Pydantic schemas (Phase 2 Wave C)
Rename schemas/search_space.py -> schemas/workspace.py, the SearchSpace* classes
-> Workspace* (incl. UserSearchSpaceAccess -> UserWorkspaceAccess), and the
search_space_id / search_space_name fields -> workspace_id / workspace_name across
all schema modules. Under hard cutover the serialized JSON keys change outright
(no alias). Re-exports in schemas/__init__.py updated.
2026-06-26 18:23:43 +02:00
CREDO23
d948b769ba refactor(db): rename search_space to workspace in satellite ORM models (Phase 2 Wave B)
Flip search_space_id -> workspace_id and the workspace relationship/back_populates
in the automations, file_storage, notifications, and podcasts persistence models,
and drop the Phase 1 Column("workspace_id", ...) shim. Full SQLAlchemy mapper
configuration now passes (db.py + satellites consistent).
2026-06-26 18:20:28 +02:00
CREDO23
df03565940 refactor(db): rename SearchSpace ORM core to Workspace (Phase 2 Wave A)
Flip the symbolic name in db.py: classes SearchSpace/Role/Membership/Invite ->
Workspace*, attributes search_space_id -> workspace_id (and owner_*), relationship
attrs + back_populates pairs, and drop the Phase 1 Column("workspace_id", ...) shim
now that attribute name == column name. Enum values 'SEARCH_SPACE' and the
SearchSourceConnector class are intentionally untouched (carve-outs).

Part of the atomic SearchSpace -> Workspace rename; the suite goes green only once
Waves B-F land (no half-renamed steady state).
2026-06-26 18:18:50 +02:00
CREDO23
49d3001fbf docs(db): tighten migration 170 docstring, move publication invariant to call site
Trim the header to a one-line summary and relocate the "never raw DROP/CREATE
PUBLICATION" invariant (bug #1355, migration 116) to the apply_publication call
site where a refactor would actually occur. Comment/docstring only; no behavior
change.
2026-06-26 17:59:05 +02:00
Anish Sarkar
ef9b5b42a8 feat: update JWT token lifetime and enhance header management in chat page
- Increased ACCESS_TOKEN_LIFETIME_SECONDS from 30 minutes to 60 minutes for improved session duration.
- Introduced getRequestHeadersWithCurrentDesktopAuth function to streamline authorization header management across fetch requests in the chat page.
2026-06-26 21:25:27 +05:30
CREDO23
5090ed734d feat(db): rename searchspace schema to workspace (migration 170)
Phase 1 (rename DB) commit 3: single Alembic migration (down_revision=169)
that physically renames the SearchSpace schema to WorkSpace to match the
already-shimmed ORM. Renames 4 tables, 24 columns
(search_space_id->workspace_id, owner_search_space_id->owner_workspace_id),
37 named/auto FK/PK/unique constraints, 25 indexes, and 4 sequences. Guarded
forms (ALTER ... IF EXISTS / DO-block RENAME CONSTRAINT) tolerate
runtime-created and absent objects.

Zero publication is reconciled via the blessed path: neutralize the four
column-list tables (documents/automations/new_chat_threads/podcasts) from the
publication, rename, then apply_publication() re-emits SET TABLE with the new
workspace_id lists (no raw DROP/CREATE PUBLICATION, per migration 116).
Downgrade fully reverses the renames and restores the old search_space_id
publication shape via a hardcoded SET TABLE, never importing the live module.

Targets the existing-deployment upgrade path (169 -> 170). The from-scratch
alembic path is a separate, pre-existing concern (0_initial uses create_all).

Verified on a realistic legacy@169 DB (with publication): upgrade clean,
zero_publication --verify passes, autogenerate EMPTY on a create_all DB,
and upgrade->downgrade->upgrade round-trips (old shape + old publication
restored on downgrade). Single alembic head = 170.
2026-06-26 17:27:31 +02:00
CREDO23
464e28ea25 refactor(db): publish workspace_id column in zero_publication
Phase 1 (rename DB) commit 2: flip the search_space_id entries in the
canonical Zero publication column lists (documents, automations,
new_chat_threads, podcasts) to the renamed physical column workspace_id,
so ALTER PUBLICATION ... SET TABLE matches the post-rename schema.

No test references the publication shape; functional verification via
`python -m app.zero_publication --verify` runs after migration 170
builds/renames the publication against a live DB.
2026-06-26 16:56:39 +02:00
Anish Sarkar
a80cb8c060 feat: update authentication defaults to LOCAL
- Changed default AUTH_TYPE in backend configuration to "LOCAL".
- Updated frontend environment configuration to reflect the new default for packaged clients.
- Adjusted runtime authentication resolution to use "LOCAL" as the fallback value.
2026-06-26 18:52:42 +05:30
CREDO23
c6d4e5df7c refactor(db): rename searchspaces table to workspaces
Phase 1 (rename DB) commit 1i: rename the SearchSpace table to workspaces
and flip all 24 inbound FK target strings (20 in db.py + the 4 satellite
models), plus the raw-SQL searchspaces references in the obsidian and
google-unification integration fixtures.

This completes the ORM half of Phase 1. The SearchSpace class name,
relationship/back_populates attribute names, and the /searchspaces API
route URLs are intentionally left for Phase 2.

Verified: unit 2375 passed/1 skip, integration 346 passed (baseline
parity); create_all builds every table with the workspaces name and all
FKs resolving to workspaces.id.
2026-06-26 13:27:16 +02:00
CREDO23
35f80268df refactor(db): rename search_space_roles table to workspace_roles
Phase 1 (rename DB) commit 1h: rename the roles table and flip both
inbound FKs (memberships.role_id, invites.role_id), plus the matching
raw-SQL cleanup in the obsidian plugin test.
2026-06-26 12:31:49 +02:00
CREDO23
0ed043379d refactor(db): rename search_space_memberships table to workspace_memberships
Phase 1 (rename DB) commit 1g: rename the memberships table (no inbound
FKs reference it) and update the matching raw-SQL cleanup in the obsidian
plugin test. Relationship attribute names stay until Phase 2.
2026-06-26 12:30:38 +02:00
CREDO23
3b545540e9 refactor(db): rename search_space_invites table to workspace_invites
Phase 1 (rename DB) commit 1f: rename the invites table and flip the one
inbound FK (memberships.invited_by_invite_id). The invites row's own
role_id -> search_space_roles FK is left for the roles rename commit.
2026-06-26 12:29:29 +02:00
CREDO23
581ae693fc refactor(db): shim podcasts.search_space_id to physical workspace_id
Phase 1 (rename DB) commit 1e: attribute->physical column shim on the
podcasts satellite model. ORM attribute and relationship unchanged.
2026-06-26 12:12:13 +02:00
CREDO23
bb953e6857 refactor(db): shim notifications.search_space_id to physical workspace_id
Phase 1 (rename DB) commit 1d: attribute->physical column shim on the
notifications satellite model, plus the inbox-list index column-ref and
its name aligned to workspace (ix_notifications_user_workspace_created).
2026-06-26 12:12:13 +02:00
CREDO23
9271678c73 refactor(db): shim automations.search_space_id to physical workspace_id
Phase 1 (rename DB) commit 1c: attribute->physical column shim on the
automations satellite model. ORM attribute and relationship unchanged.
2026-06-26 12:12:13 +02:00
CREDO23
e2578e09bc refactor(db): shim document_files.search_space_id to physical workspace_id
Phase 1 (rename DB) commit 1b: same attribute->physical column shim as
1a, applied to the document_files satellite model. ORM attribute name
unchanged; FK target string left for the searchspaces rename commit.
2026-06-26 12:08:26 +02:00
CREDO23
533cdfcc81 refactor(db): map search_space_id ORM attrs to physical workspace_id column
Phase 1 (rename DB) commit 1a: shim every search_space_id /
owner_search_space_id column to the renamed physical column
(workspace_id / owner_workspace_id) via Column("workspace_id", ...),
keeping the ORM attribute name unchanged so existing callers are
untouched. Flip all Table-level references that resolve by column key
(inner __table_args__ strings, the ck_connections_scope_owner CHECK
text, and the _INDEX_DEFINITIONS runtime DDL) plus the searchspace-named
constraint/index names to workspace_id. Update the three raw-SQL test
fixtures that referenced the physical column.

Note: SQLAlchemy defaults a column's key to its name, so passing an
explicit "workspace_id" name moves the Table.c key to workspace_id;
Table-level string refs must therefore change in this phase (the
opposite of the original plan's finding 1). The ORM attribute, the
SearchSpace class, relationships, table names, and FK target strings are
intentionally left for later commits/Phase 2.

Verified: unit 2375 passed/1 skip, integration 346 passed (baseline
parity); create_all builds every table with workspace_id.
2026-06-26 12:05:52 +02:00