Skip to content
Scopwis
Development

Architecture

Scopwis is an autonomous analytics execution system with a Rust trust boundary and cross-platform Flutter clients.

Major components

LayerTechnologyResponsibility
ServerRust, Tokio, AxumAPI, auth, sessions, tasks, ownership
Data accessOpenDAL + provider adaptersAuthorized objects and tables
QueryDataFusion + ArrowTyped analytical plans and columnar results
AnalysisRegistered Rust methodsMining, diagnostics, forecasting, prediction
AgentModelProvider + ReAct runtimePlanning and tool selection
ReportsReportSpecDeclarative validated deliverables
UIFlutter + Forui + Scopwis tokensWeb/Desktop/Mobile workspaces
CLI/TUIRust, clap, ratatuiTerminal client

Execution flow

user question
  ↓
authorized source discovery
  ↓
metadata + semantics
  ↓
validated AgentPlan
  ↓
typed query / registered method execution
  ↓
Query / Mining artifacts
  ↓
evidence-backed Analysis Artifact
  ↓
answer
  └─ ReportSpec only when requested

The model proposes a path, but it does not own authorization, query compilation, artifact provenance, or report validation.

Product surfaces

The primary work destinations are Analyze, Data mining, and Reports. Settings is a separate application-level configuration surface. Data browsing and task history remain contextual tools rather than additional top-level destinations.

Storage and artifacts

Server-owned persistent state lives under the configured data root. Immutable artifact metadata and lineage are separated from large payload storage so evidence history can survive bounded payload expiry.

Conversation retention respects account ownership. At the 50-conversation process limit, a new conversation can replace only the current account's oldest history. If that account has no history to replace, creation returns a capacity error; deleting an owned conversation frees a slot. Follow-ups to an existing owned conversation remain available. Restart recovery enforces the same ownership rule. Recovering overflow in an ownerless legacy directory requires the explicit legacy ownership migration opt-in before deleting history.

Completed Agent task history stays on disk. Startup validates each durable record and retains a compact terminal summary, then loads the full answer and events only when that task is requested. Active records retain the state needed to report an interrupted run after restart.

Private conversation and task records are structurally preflighted before materialization, including ignored compatibility metadata. Task previews enforce the published kind/ID/revision/producer and 64-input boundaries on both startup and cold reads. Oversized decoded structure or malformed records fail recovery without deleting history or temporary evidence.

Known task metadata, errors, progress events, and response primitives obey the declared Unicode character bounds and enums before writing or restoring, including legacy migration. Omit optional task fields rather than supplying null; absent artifacts and retryability retain their declared defaults. Bounded private extensions and legacy metric defaults remain compatible. An invalid live terminal candidate is discarded as a whole and becomes a sanitized INTERNAL failure from the preceding valid snapshot. A valid candidate whose storage write fails instead becomes AGENT_TASK_PERSIST_FAILED while preserving validated events. Automatic plan pruning and duplicate-synthesis merging emit ordinary completed progress events; normalization is described by the summary, not a new wire status. These field checks do not re-authorize historical plans against current run permissions.

Durable task mutations heap-own their work unit before waiting for bounded IO capacity, so captured snapshots do not inflate nested async wait states. An unpolled transaction can be dropped without executing it; after its worker starts, cancelling the HTTP waiter does not release serialization before durable commit and registry/worker handoff settle.

Cross-platform boundary

Flutter owns presentation and interaction. Rust owns identity, authorization, data access, computation, Agent orchestration, and report validation. Native bridges move data in bounded batches instead of row-by-row calls; Web normally uses the typed HTTP/SSE/Arrow APIs.

Report responses are bounded while reading the HTTP stream, before JSON decoding: successful report payloads use a 64 MiB limit and error envelopes use 64 KiB. Replacing or closing a report request cancels its body subscription and prevents an obsolete result from replacing the current view.

Native model transports validate the entire tool-call envelope before submitting any call to the Agent. Malformed required tool fields reject the response instead of silently dropping a call and executing the remaining siblings.

Native Responses, Anthropic and Gemini JSON additionally passes a shared 64 MiB structural admission charge before tree decoding, separately from the 16 MiB wire limit. This includes unknown metadata and Responses encoded arguments; the charge is a deterministic resource gate, not an RSS guarantee.

For normative implementation contracts, see the repository docs/specs/ directory.

Type to search the English documentation.