Releases: scub-france/docling-Studio
v0.6.2
0.6.2 — audit-driven release. Closes the 4 CRIT + 4 MAJ flagged by
the 0.6.1 audit and the 0.6.2 release-gate audit.
Highlights
- Image size cut by ~half —
latest-localdrops from 6.04 GB to 3.11 GB
(-48%), and a new slimlatest-remoteships at 547 MB. Details below. docling-servecontainer added under theremotecompose profile —
the backend now ships a slim image that delegates conversion to
quay.io/docling-project/docling-serve-cpu:v1.21.0over HTTP. Zero
HuggingFace Hub dependency in build or runtime.- Backend + embedding-service migrated from pip to
uv. Single source
of truth is nowpyproject.toml+uv.lock. BREAKING for anyone
bootstrapping fromrequirements*.txt. BAKE_MODELSdefault flipped fromtruetofalsein both
Dockerfiles. The only sanctioned HF touch in the project is now the
latest-localGHCR build inrelease.yml. BREAKING for operators
building from source — pass--build-arg BAKE_MODELS=trueexplicitly
to restore the old behaviour. See
docs/architecture/huggingface-dependency-map.md.- Reasoning stack made opt-in via
--build-arg WITH_REASONING=true
(#254). BREAKING — without the flag,/api/reasoningresponds503.
Pre-built images — major size reduction
The latest-local image dropped by ~48% (-2.93 GB) versus 0.5.1, and
the new remote variant ships at 547 MB — about an order of magnitude
smaller than 0.5.1's only published variant. Pulls are faster, hosts use
less disk, and cold starts are quicker.
| Image | 0.5.1 | 0.6.2 | Δ |
|---|---|---|---|
latest-local (Docling + models baked in) |
6.04 GB | 3.11 GB | -2.93 GB (-48%) |
latest-remote (talks to docling-serve over HTTP) |
— | 547 MB | new — -91% vs 0.5.1 local |
Where the bytes went:
uvmigration (#254) — smaller resolved venv vs pip, deterministic
lockfile, no transitive bloat that nobody noticed under pip's resolver.- Explicit CPU-only torch via
[tool.uv.sources]— drops ~3 GB of useless
CUDA wheels that used to come along for the ride onlatest-local. - Reasoning made opt-in —
docling-agent+mellea+ their LLM SDK
transitive weight move out of the default image. Rebuild with
--build-arg WITH_REASONING=trueto keep them. BAKE_MODELSopt-in for non-release builds — onlyrelease.yml
builds thelocaltarget with the ~1.3 GB Docling checkpoint bake; the
remotevariant carries none.- Hardened
.dockerignore— leaner build context, no spurious layer
churn on every rebuild.
Tags published
Both targets are tagged three ways for pinning flexibility:
ghcr.io/scub-france/docling-studio:0.6.2-remote/0.6-remote/latest-remoteghcr.io/scub-france/docling-studio:0.6.2-local/0.6-local/latest-local
Added
- Docling Serve container wired into compose (
#audit-10,dd1962e,bc9b4f8): newdocling-serveservice under theremotecompose profile, pinned toquay.io/docling-project/docling-serve-cpu:v1.21.0. Pairs withCONVERSION_MODE=remoteso the backend image stays slim and talks to a Docling Serve container over HTTP — no HF Hub dep on the build or runtime path. CI/release-gate E2E jobs now use this combo. - HuggingFace dependency map (
docs/architecture/huggingface-dependency-map.md): exhaustive list of every HF call site in the project, the single sanctioned touch point (release.yml→latest-local), and the maintenance rule that every new HF dep must be opt-in.
Changed
- Backend + embedding-service migrated from pip to uv (#254,
4d9bcf6):document-parser/requirements*.txtandembedding-service/requirements.txtremoved;uv.lockpluspyproject.toml's[project]/[dependency-groups]blocks are now the single source of truth. Dev workflow becomesuv sync --group dev(backend) /uv sync --group local(local Docling). PyTorch is redirected to the explicit CPU index via[tool.uv.sources]to avoid pulling the ~3 GB CUDA wheels intolatest-local. latest-localships with Docling model checkpoints baked at build time (#254,9d62337): suppresses the cold-start HF Hub download on the first/api/convert. End users get an instant first-convert from the pulled GHCR image..dockerignorehardened (#254,fe1dc16): tests, audit reports,.claude/,docker-compose*.ymland other build-irrelevant paths excluded — leaner build context, smaller intermediate layers.- Reasoning stack made opt-in via
WITH_REASONINGbuild-arg (#254,d1ed61e,bb2fe2b):docling-agentandmelleamoved out of[project.dependencies]into[dependency-groups.reasoning]. The defaultlatest-localimage no longer carries them —/api/reasoningresponds503(graceful degrade). Building with--build-arg WITH_REASONING=truerestores the 0.6.1 behaviour. BAKE_MODELSandBAKE_MODELdefault tofalse(#audit-10): bothdocument-parser/Dockerfileandembedding-service/Dockerfilenow opt out of HuggingFace Hub by default at build time. The only sanctioned bake isrelease.yml→latest-localGHCR image, which setsBAKE_MODELS=trueexplicitly on thelocalmatrix entry. See the new HF dependency map for details.
Fixed
- Remote-mode bbox overlay — second pass (
3936166, follow-up to the 0.6.1 fix): a code path the 0.6.1 patch missed still droppedself_refinServeConverter. The Linked-view canvas overlay now lights up consistently in remote mode. - Architecture test excludes generated files (
d29360d):tests/test_architecture.pyno longer scansuploads/,data/or other runtime artifacts — keeps the layering rules clean without false positives.
CI
STUDIO_MODE_ENABLEDopted in on the main CI too (8a61c22): the@criticalUI suite needs the legacy/studiosurface; previously onlyrelease-gate.ymlset the flag, leavingci.ymlE2E UI silently exercising the wrong surface.- Docling model bake skipped during CI builds (
051ac4a,#audit-10): bothci.ymlE2E jobs and bothrelease-gate.ymlE2E jobs (e2e-api,e2e-ui) now build the image withBAKE_MODELS=falseto avoid HuggingFace Hub 429 rate limits on shared GHA runners.release.ymlkeepsBAKE_MODELS=trueso the published image still carries the baked checkpoints. - Unit test no longer pulls HF tokenizer (
#audit-10):test_rechunk_with_serve_document_jsonwas instantiating a realLocalChunker, forcingHybridChunkerto downloadsentence-transformers/all-MiniLM-L6-v2. Now mocks theDocumentChunkerport — same intent, no public network in a unit test.
BREAKING CHANGES
- Backend dev workflow migrated to uv:
pip install -r document-parser/requirements*.txt/pip install -r embedding-service/requirements.txtno longer work — these files are gone. Useuv sync(--group devfor tests,--group localfor local Docling mode). Any third-party CI / IDE bootstrap script that relies on the oldrequirements*.txtlayout must migrate. - Reasoning runtime made opt-in: building
latest-localwithout--build-arg WITH_REASONING=trueproduces an image where/api/reasoningresponds503. Operators who depended on the 0.6.1 default-on reasoning stack must add the build-arg to their pipeline. BAKE_MODELSdefault flipped fromtruetofalsein bothdocument-parser/Dockerfileandembedding-service/Dockerfile. Operators who build their ownlocalimage from source and rely on the "instant first/api/convert" behaviour must now pass--build-arg BAKE_MODELS=trueexplicitly. The publishedghcr.io/.../docling-studio:latest-localimage is unaffected —release.ymlopts in. Pulling that image (the documented path) continues to work as before. Seedocs/architecture/huggingface-dependency-map.mdfor the rationale and the full HF call-site map.
v0.6.1 — Audit-remediated release
Release date : 2026-05-25
Audit verdict : GO — score 90.27/100, 0 CRIT, 3 MAJ planifiés pour 0.7.0
Full audit report : docs/audit/reports/release-0.6.1-reaudit/summary.md
Highlights
Per-document workspace (#263–#268)
The legacy single-page /studio editor gives way to a DocWorkspacePage shell with four dedicated tabs: Parse (preview + LAYERS filters + focus mode + tree color-coding), Chunk (Strategy popover for inline rechunk, decoupled "Generate chunks" CTA), Inspect (Markdown / Elements / Images), Compare. Every doc keeps its own state; navigation no longer leaks bbox or analysis context between documents.
Version history with paired snapshots (#267)
Every analysis run and rechunk now writes a frozen (analysis, chunks) snapshot. The History drawer lists them and lets you switch the active analysis on the fly — no more lost intermediates.
Backend goes DDD-granular (#256, #269)
New ChunkService exposes 9 doc-scoped routes under /api/documents/{id}/chunks/*. The no-UX-shaped-routes rule is now codified — every existing /api/* route is classified in docs/design/269-backend-ddd-audit.md.
Stores get real connection credentials (#279)
Stores are no longer pinned to env-var-only connections. Each store row carries its own connection_uri / connection_username / connection_password, with passwords sealed at rest via Fernet (STORE_SECRET_KEY). Per-(uri, user) connection pools for both Neo4j and OpenSearch. New "Test connection" button in the store form.
Ingest tab + push history (#225, #283, #285)
Workspace gets a proper Ingest view: history-driven shell, pending-push badge on the CTA, hierarchical doc tree with per-tab CTAs and ingest-targets popover. Backend exposes GET /api/documents/{id}/chunks/pushes for the history feed.
Master surface flags (#257)
Two new env-vars gate two opt-in surfaces:
STUDIO_MODE_ENABLED— re-enables the legacy/studiopage (kept around until 0.7.0 ships its rewrite)RAG_PIPELINE_ENABLED— gates the reasoning pipeline
Both default to false in production (see BREAKING below).
Karate UI e2e suite
First batch of UI regression coverage lands under e2e/ui/ — driven by Karate UI, not Playwright. CI runs @critical tagged scenarios on main.
⚠️ BREAKING CHANGES — read before upgrading
1. POST /api/documents/{id}/chunks/push response field
- { "jobId": "...", "summary": { ... } }
+ { "pushId": "...", "summary": { ... } }Frontend consumers and any external script that calls this endpoint must update.
2. Surface flags default off in production
STUDIO_MODE_ENABLED and RAG_PIPELINE_ENABLED were implicitly on before 0.6.1. If you rely on the legacy /studio page or the RAG pipeline, set them explicitly:
# docker-compose.yml or .env
STUDIO_MODE_ENABLED: "true"
RAG_PIPELINE_ENABLED: "true"3. STORE_SECRET_KEY required for sealed stores
Any 0.6.0 deployment that already created store rows with sealed passwords will fail to boot on 0.6.1 until STORE_SECRET_KEY is provided.
Generate a Fernet key and pin it in the environment:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"Rotating the key invalidates every existing sealed value — keep it stable.
4. i18n keys renamed
Any external translation override file must update:
| Old key | New key |
|---|---|
chunks.pushedJob |
chunks.pushDispatched |
chunks.stale.jobDispatched |
chunks.stale.pushDispatched |
docs.jobDispatched |
docs.pushDispatched |
Placeholder {jobId} → {pushId} in all three.
5. No auto-migration from 0.5.x (carried over from 0.6.0)
The SQLite schema is bootstrapped fresh from _SCHEMA. Upgrading from a 0.5.x database requires either (a) re-importing your documents into a fresh DB, or (b) hand-rolling the catch-up DDL.
Installation
Docker (recommended)
# Pull the new image (pick remote OR local)
docker pull ghcr.io/scub-france/docling-studio:0.6.1-local
# or
docker pull ghcr.io/scub-france/docling-studio:0.6.1-remote
# Multi-arch: linux/amd64 + linux/arm64Docker Compose
Update your docker-compose.yml (or .env) per the BREAKING CHANGES section above, then:
docker compose pull
docker compose up -d --wait
curl -s http://localhost:3000/api/health | jq .
# Expected: {"status":"ok","version":"0.6.1","engine":"...","deploymentMode":"self-hosted"}See docs/release/deployment-checklist.md for the full deploy + smoke-test procedure.
Quality gate
This release is the first to ship after a full 12-point audit + remediation cycle. Initial verdict was NO-GO (4 CRIT, 11 MAJ, score 79.12/100). After remediation, re-audit verdict is GO (0 CRIT, 3 MAJ planifiés pour 0.7.0, score 90.27/100).
| Audit dimension | Score |
|---|---|
| 01 Clean Architecture (Hexagonal) | 97/100 — GO |
| 02 DDD | 97/100 — GO |
| 03 Clean Code | 72/100 — GO CONDITIONNEL |
| 04 KISS | 87.5/100 — GO |
| 05 DRY | 75/100 — GO CONDITIONNEL |
| 06 SOLID | 100/100 — GO |
| 07 Decoupling | 73/100 — GO CONDITIONNEL |
| 08 Security | 100/100 — GO |
| 09 Tests | 96/100 — GO |
| 10 CI / Build | 100/100 — GO |
| 11 Documentation | 100/100 — GO |
| 12 Performance | 85.7/100 — GO |
Validation pipeline shipped green : backend 733 pytest, frontend 400 vitest, Karate API 39 e2e (12 features), Ruff + ESLint + Prettier + vue-tsc clean, Docker compose stack Healthy, multi-arch images built.
Full per-audit reports under docs/audit/reports/release-0.6.1-reaudit/.
Full changelog
See CHANGELOG.md § 0.6.1 for the unabridged Added / Changed / Fixed / Security / BREAKING CHANGES sections.
Diff : v0.5.1...v0.6.1
Docling Studio 0.5.0 — Live reasoning, Neo4j graph storage & audit-driven hardening
What's new
Live reasoning (feature-flag gated, opt-in package)
The reasoning subsystem ships behind a feature flag (REASONING_ENABLED) and an opt-in published package (docling-agent + mellea from PyPI). Both must be present at boot for the endpoint and the sidebar entry to surface — this lets us land the runner without forcing the heavy LLM dependency stack on every deployment.
- Reasoning-trace viewer — SQLite-backed graph built from
document_json, iteration-by-iteration overlay on the document outline (StructureViewer+GraphView), bidirectional PDF ↔ graph focus - Live reasoning loop —
POST /api/documents/:id/reasoningreturns answer + full iteration trace + convergence flag. Powered by docling-agent over Ollama (gpt-oss:20breference model). Tracks docling-agent#26 for the public-API replacement of the_rag_loopworkaround LLMProviderport withOllamaProvideradapter — opens the door to alternate LLM backends oncedocling-agentupstream supports them. New env varLLM_PROVIDER_TYPE(defaultollama) materializes the abstractionReasoningRunnerport withReasoningResult/ReasoningIteration/ReasoningParseErrordomain types; concreteDoclingAgentReasoningRunneradapter encapsulates all upstream coupling
Neo4j graph storage
- Graph-native document tree —
TreeWriter+ChunkWriteradapters, schema bootstrap at backend boot - Graph fetch endpoint —
GET /api/documents/:id/graph, 200-page cap (cf. ADR-001) Maintainstep in Studio with cytoscape-based interactive visualization- Architecture decision record —
docs/architecture/adr/ADR-001-graph-viz-library.mddocuments the cytoscape choice and the page cap rationale - Boot warning if the backend starts with
NEO4J_URIset and the dev-defaultchangemepassword
Audit framework & quality gate
- Audit master (
docs/audit/master.md) — 12 unitary audits (Hexagonal Architecture, DDD, Clean Code, KISS, DRY, SOLID, Decoupling, Security, Tests, CI/Build, Documentation, Performance), 4-tier criticality (CRIT/MAJ/MIN/INFO), weighted 100-point scoring,GO/GO CONDITIONNEL/NO-GOverdict - Audit reports for 0.5.0 under
docs/audit/reports/release-0.5.0/— per-audit detail, initial summary, post-remediation re-audit (1 CRIT + 12 MAJ remediated) - Hexagonal-architecture tests powered by
pytestarch(CI-enforced) — build fails ifapi/ordomain/importinfra/
Hexagonal hardening (audit-driven)
DocumentConverter.supports_page_batching: bool— replaces theisinstance(converter, ServeConverter)check (LSP fix)VectorStore.ping()— health probe goes through the port;IngestionService.ping()no longer reaches into_vector_store._client- API path params
{job_id}→{analysis_id}acrossapi/analyses.pyandapi/ingestion.pyto align the OpenAPI surface with the user-facing terminology (URL paths unchanged) - PDF preview —
Path.read_bytes()+ rasterisation wrapped inasyncio.to_thread, unblocks the FastAPI event loop on/preview - Cross-feature integration test moved to
frontend/src/__tests__/integration/so feature folders stay self-contained apiUrldead code removed from the settings store; orphansettings.apiUrli18n entries dropped- Document-status string
"uploaded"extracted toDOCUMENT_STATUS_UPLOADED localStoragekeys centralised infrontend/src/shared/storage/keys.ts(STORAGE_KEYS)
Infrastructure & deployment
docker-compose.ymlflagged as dev-only — header explicitly states defaults are not production-ready (Neo4jchangeme, OpenSearchDISABLE_SECURITY_PLUGIN=true); operators must harden their own production deployments- Trivy gate wired with
.trivyignore.yamlfor CVE-2026-40393 (Mesa, expiry 2026-06-30 — no Debian backport; follow-up viaopencv-python-headlesstracked in #189) - Trivy CLI pinned to
latest(was hardcoded tov0.69.3, yanked from upstream) - Remote chunking enabled in Docling Serve mode (previously local-only)
- Centralised magic numbers for page dimensions, limits, and timeouts
- Paste image size/type limits — env vars
MAX_PASTE_IMAGE_SIZE_MB,PASTE_ALLOWED_IMAGE_TYPES; surfaced in/api/health - Test counts: 446 backend, 202 frontend, full E2E Karate suite
Breaking changes
RAG_*env vars renamed toREASONING_*—RAG_ENABLED→REASONING_ENABLED,RAG_MODEL_ID→REASONING_MODEL_ID- Health response field renamed —
ragAvailable→reasoningAvailable - Reasoning endpoint renamed —
POST /api/documents/:id/rag→POST /api/documents/:id/reasoning - New env var
LLM_PROVIDER_TYPE(defaultollama)
Fixed
- Graph: collapse Docling
InlineGroupandPicturechildren to avoid empty leaf nodes (#197) - Neo4j: rewrite
fetch_graphusingCALLsubqueries for proper relationship traversal - CI: install
pytestarchin backend tests job (#177) - CI: ignore CVE-2026-40393 (Mesa) with expiry — Debian has no backport (#190)
- CI: docs build now tolerates audit-report cross-tree links in strict mode
- Reasoning: re-scroll PDF when re-clicking the active iteration
infra/docling_tree.py:101migratedisinstance(bbox, (list, tuple))to PEP 604 union (Ruff UP038)- Tightened terminal
assert X is not Nonechecks in domain/repo/service tests (compare the value, not just presence)
Docker images
# Remote (lightweight, delegates to Docling Serve)
docker pull ghcr.io/scub-france/docling-studio:0.5.0-remote
# Local (full Docling in-process — pair with REASONING_ENABLED + docling-agent for the live reasoning runner)
docker pull ghcr.io/scub-france/docling-studio:0.5.0-localDocling Studio 0.4.0 — Ingestion pipeline, OpenSearch & Ingest mode
What's new
Ingestion pipeline (Docling → embedding → OpenSearch)
- Orchestrated ingestion pipeline — end-to-end document indexing: Docling → chunking → embedding → OpenSearch with idempotent re-ingestion
- Vector index metadata schema —
IndexedChunkdomain model, OpenSearch mapping builder with FAISS/HNSW kNN, configurable embedding dimension VectorStoreport (Protocol) —ensure_index,index_chunks,search_similar,get_chunks,delete_document- OpenSearch adapter (
OpenSearchStore) — kNN vector search, full-text search, bulk indexing, document CRUD - Embedding microservice (
embedding-service/) — sentence-transformers REST API with batch processing and Dockerfile EmbeddingServiceport andEmbeddingClientHTTP adapter for remote embedding generation- Ingestion REST API —
POST /api/ingestion/{jobId},DELETE /api/ingestion/{docId},GET /api/ingestion/status,GET /api/ingestion/search
Ingest mode — 4th Studio mode
- Ingest promoted as 4th Studio mode (Configure → Verify → Prepare → Ingest) with dedicated
IngestPanel, summary, stepper and action button - Multi-step ingestion progress stepper — visual stepper: Embedding → Indexing → Done, with animated dot and auto-reset
- One-click ingestion button in Studio from completed analysis with progress feedback
Search
- Full-text search in indexed chunks —
GET /api/ingestion/search?q=…&doc_id=…endpoint, search bar with relevance score display - Dedicated search sidebar tab — search extracted into its own bounded context with store, API layer, page and route
Documents & monitoring
- My Documents screen — search, filter (all/indexed/not indexed), sort (name/date), ingestion status badges
- OpenSearch connection status indicator — green/red dot in sidebar footer with tooltip, polls every 30 s
Feature flags & deployment
- Feature-flag gating — ingestion pipeline opt-in via
OPENSEARCH_URL+EMBEDDING_URL; frontend hides all ingestion UI when disabled - Simplified Quick Start — one-liner
docker compose upin README docker-compose.ingestion.ymloverride for full-stack ingestion via Docker profiles- New env vars documented —
BATCH_PAGE_SIZE,MAX_FILE_SIZE_MB,MAX_PAGE_COUNT,RATE_LIMIT_RPM
Chunking enhancements
- Inline chunk text editing — double-click or edit button to modify chunk text, with save/cancel and "modified" badge
- Soft-delete chunks — delete button with confirmation dialog, chunks hidden from UI but preserved in data
Infrastructure
- Docker Compose dev stack (
docker-compose.dev.yml) — OpenSearch, Dashboards, hot-reload backend and Vite frontend - E2E Karate tests and unit tests for full ingestion workflow (PDF → chunks in OpenSearch)
- Test counts: 380 backend, 161 frontend
Fixed
- Rechunk timeout — update chunks synchronously in store instead of async re-fetch via emit (Vue does not await async emit handlers)
- Relevance score — display raw BM25 score instead of misleading percentage
- E2E selectors — replaced fragile index-based toggle selection with dedicated
data-e2eselectors - CI healthcheck — embedding service timing and missing
curlin slim image
Changed
BATCH_PAGE_SIZEdefault moved from Dockerfile tosettings.py, default set to 10- Batch chunking notice now shows "Coming soon" label
Docker images
# Remote (lightweight, delegates to Docling Serve)
docker pull ghcr.io/scub-france/docling-studio:0.4.0-remote
# Local (full Docling in-process)
docker pull ghcr.io/scub-france/docling-studio:0.4.0-localDocling Studio 0.3.1 — Batch progress & stability fixes
What's new
Added
- Batch conversion progress — segmented progress bar with ring indicator and per-batch visual feedback
- Inline mini progress bar in the top banner during analysis
- Informational notice in Prepare mode when chunking is unavailable (batch mode)
BATCH_PAGE_SIZEenvironment variable forwarded in Docker Compose
Fixed
- Batch progress reset to null on completion (progress_current/progress_total overwritten by stale in-memory job object)
- Regression test for batch progress preservation in
_run_analysis_innerflow - E2E assertion on final progress values in batch-progress feature
Docker images
# Remote (lightweight, delegates to Docling Serve)
docker pull ghcr.io/scub-france/docling-studio:0.3.1-remote
# Local (full Docling in-process)
docker pull ghcr.io/scub-france/docling-studio:0.3.1-localDocling Studio 0.3.0 — Chunking, Serve support & Refacto
What's new
Added
- Chunking support — domain objects, persistence, API endpoints, and frontend Prepare mode
- Chunk-to-bbox hover highlighting in Prepare mode
- Page filtering and collapsible config in Prepare mode
- Feature flipping mechanism
- Reusable pagination composable and PaginationBar component
- Version display in sidebar, settings page, and health endpoint
Fixed
- Feature flag health check blocked by CORS
- Zombie jobs and unprotected JSON parse
- Upload error not displayed in DocumentUpload component
- Serve API contract: send
to_formatsas repeated form fields - Audit findings: security, robustness, dead code, domain-infra violation
Changed
- Refactored backend to hexagonal architecture for converter extensibility
- Added ServeConverter adapter for remote Docling Serve integration
- Moved
@vitest/mockerfrom dependencies to devDependencies
Docker images
# Remote (lightweight, delegates to Docling Serve)
docker pull ghcr.io/scub-france/docling-studio:0.3.0-remote
# Local (full Docling in-process)
docker pull ghcr.io/scub-france/docling-studio:0.3.0-local