Repository navigation
Releases
v0.5.0
Third stable release of the channel, and the first since 0.3.2 on NuGet.org / npmjs. The 0.5.0 line moves field
storage onto the Dignite.Abp.FlexFields kernel (field architecture v3), rebuilds the document permission core
on ABP's resource-based authorization (per-type grants, uploader ownership, Documents.ReadAll), tidies the
multi-stage event contract (DocumentTextExtractedEto, FieldsExtractedEto retired), replaces re-classify with a
re-parse from the original file, adds operator notifications and a per-tenant on/off feature, moves the MCP
server onto the shared Dignite.Abp.AspNetCore.Mcp endpoint (vault_extract_* tool names), and lands on
ABP Framework 10.7 / Angular 22. The granular per-preview history, with the migration for every breaking entry, is
retained in the 0.5.0-preview.* sections of CHANGELOG.md; this section lists only what changed after 0.5.0-preview.17.
As a
0.y.zrelease the exit contracts may still change — see CONTRIBUTING → Versioning and releases.
Upgrading from 0.3.x is breaking on the REST, EventBus, MCP, permission and Angular contracts (each entry marked
BREAKING below carries its migration) and needs the EF migrations of this line applied (--migrate-database).
A 0.3.x deployment that holds field values must run the field architecture v2 → v3 data migration first: it
ships only in0.5.0-preview.1/0.5.0-preview.2, which were published to GitHub Packages, not to NuGet.org —
follow the runbook on one of those builds, verify it, and
only then move to 0.5.0. Skipping it loses every field value while the upgrade reports success (see0.5.0-preview.4in the CHANGELOG).
The Angular library is published as@dignite/ng.vault-extract;@dignite/vault-extractstops at0.3.2.
Changed
- abp-modules
10.7.0, the first stable release, on both sides (was10.0.0-rc.29).Dignite.Abp.FlexFields.*,
Dignite.Abp.AspNetCore.Mcp,Dignite.Abp.Notifications.*andDignite.NotificationCenter.*move to10.7.0,
along with@dignite/ng.flex-fields,@dignite/ng.flex-fields-ckeditorand@dignite/ng.notification-centerand
the published Angular library's dependency pins. This lifts the last gate on a stable NuGet release: a stable
Dignite.Vault.Extract.*no longer depends on a pre-release package (NU5104). No source change, no EF migration. - Restore no longer needs
GITHUB_PACKAGES_TOKEN. abp-modules10.7.0is published to nuget.org only (its
GitHub Packages feed carries pre-releases), soNuGet.Configdrops thegithubsource and its mapping, and the
duplicatehost/NuGet.Configis removed; every package resolves from nuget.org. - The stable npm publish step in
release.ymltreats "already published" as a soft skip, like the pre-release step, so
a first publish bootstrapped by hand (npm Trusted Publishing cannot create a package) does not fail the release run. - NuGet.org publishing moves to NuGet Trusted Publishing (OIDC), like the npm side; no long-lived API key (#711).
v0.5.0-preview.17
The operator UI takes the product's own name: its URL prefix and navigation menu change from documents / Documents to vault-extract / Vault Extract. Angular and localization only; no EF migration and no change to the REST, MCP or EventBus contracts.
Changed
- BREAKING (Angular): the operator UI mounts at
vault-extract, notdocuments, and its localization keys name their resource.
documentscollides too easily with other systems, in both the menu label and the URL, so the module takes the
product's own name. Hosts must mountDOCUMENTS_ROUTESatpath: 'vault-extract'(provideExtract()registers its
menu entries under that prefix). Routes:documents/overview→vault-extract/overview,documents/list→
vault-extract/documents,documents/types→vault-extract/document-types,documents/cabinets→
vault-extract/cabinets,documents/recycle→vault-extract/documents-recycle-bin; a document's detail and file
preview move tovault-extract/documents/:idandvault-extract/documents/:id/file, and a type's fields page to
vault-extract/document-types/:typeId/fields. Old/documents/...bookmarks stop resolving. - BREAKING (Angular + localization):
Menu:Documentsis nowMenu:VaultExtract, and reads "Vault Extract" in every
language (it was Documents / 文档库 / ドキュメント / 文件庫). A host that overrodeMenu:Documentsto rebrand the menu
must override the new key. The library's templates and services now writeVaultExtract::Keyinstead of::Key,
so they no longer depend on the host's default localization resource inheritingVaultExtract; a host that
re-labelled aVaultExtractkey through its own default resource must add the override to theVaultExtract
resource itself.
v0.5.0-preview.16
Both sides move to ABP Framework 10.7.0 and abp-modules 10.0.0-rc.29, with Angular 22 on the frontend. One EF migration, Abp107_BackgroundJobsCompletionTime: ABP 10.6's
background-jobs change adds a nullable CompletionTime column to AbpBackgroundJobs and replaces the index
IX_AbpBackgroundJobs_IsAbandoned_NextTryTime with IX_AbpBackgroundJobs_ApplicationName_CompletionTime_IsAbandoned_NextTryTime.
Additive, no data change; StoreSuccessfulJobs stays off, so the column is written only by jobs that fail.
Changed
- abp-modules
10.0.0-rc.29, on both sides.Dignite.Abp.FlexFields.*,Dignite.Abp.AspNetCore.Mcp,
Dignite.Abp.Notifications.*andDignite.NotificationCenter.*move from rc.28 to rc.29, along with
@dignite/ng.flex-fields,@dignite/ng.flex-fields-ckeditorand@dignite/ng.notification-centerand the
published Angular library's dependency pins. FlexFields and Notification Center module references use the new
AbpFlexFields*Module/AbpNotificationCenter*Moduleclass names; namespaces and package names stay the same.
Microsoft.Extensions.FileProviders.Embeddedmoves to10.0.12to meet the new packages' minimum.
The CKEditor dependency moves to v49 with its Angular adapter v12. No additional EF migration. - Breaking - ABP Framework 10.7.0 (was 10.5.0). Every
Volo.Abp.*pin inDirectory.Packages.propsmoves to
10.7.0, so the publishedDignite.Vault.Extract.*packages now depend onVolo.Abp.* >= 10.7.0: a consuming host
must be on ABP 10.7.0 or later. abp-modules10.0.0-rc.28requires it (its packages depend on
Volo.Abp.* >= 10.7.0).Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite5.5.0 -> 5.7.0 and
Volo.Abp.Studio.Client.AspNetCore2.2.7 -> 3.1.4 (host only, never published) move with it. No source change was
needed to compile against 10.7.0. - abp-modules
10.0.0-rc.28, .NET side.Dignite.Abp.FlexFields.*,Dignite.Abp.AspNetCore.Mcp,
Dignite.Abp.Notifications.*andDignite.NotificationCenter.*move from rc.25 to rc.28. rc.28 renames the
file-storing module toDignite.Abp.BlobStoring.Pipeline/.Imaging(contributors for ABP 10.7's BLOB content
pipeline); Vault Extract uses neither the old nor the new packages and keepsVolo.Abp.BlobStoringas is. - Breaking - Angular 22,
@abp/ng.*10.7.0, TypeScript 6 (was Angular 21, 10.5.0, TypeScript 5.9). The workspace
follows ABP 10.7.0's Angular template:@angular/*22.2,@angular/cli/@angular/build22.2,ng-packagr22.2,
typescript6.0.3,@abp/ng.*~10.7.0,@abp/ng.theme.lepton-x~5.7.0,angular-eslint22. The published
@dignite/ng.vault-extractnow peers on@angular/* ^22.0.0and depends on@abp/ng.* ~10.7.0: a consuming
Angular host must be on Angular 22 and ABP 10.7. Angular's v22 migrations were applied and then trimmed: the six components that declared no change-detection
strategy now declareOnPushlike the other fourteen (the migration insertsChangeDetectionStrategy.Eager,
which the workspace'sprefer-on-push-component-change-detectionlint rule rejects; their templates hold only
reactive-form bindings and plain inputs), and the$safeNavigationMigration()wrappers and the
extended-diagnostics suppression the migration adds were dropped, since the build needs neither. TypeScript 6
deprecatesbaseUrl, sotsconfig.base.jsondrops it and itspathsare relative to the file.legacy-peer-depsstays:@abp/ng.theme.shared10.7 still
depends onngx-datatable22 andng-bootstrap20, whose peer ranges stop before Angular 22. - abp-modules
10.0.0-rc.28, Angular side.@dignite/ng.flex-fields,@dignite/ng.flex-fields-ckeditorand
@dignite/ng.notification-centermove from rc.25 to rc.28, and the two flex-fields packages are now installed from
npmjs.org under their@dignite/*names: thenpm:@dignite-projects/...alias and the GitHub Packages registry
lines inangular/.npmrcare gone (the@dignite-projectsnames no longer resolve there). .github/dependabot.ymlnow holdsVolo.Abp.*at the 10.7 line,Volo.Abp.Studio.Client.AspNetCorebelow 3.1.5, and@angular/*at the 22 line.- GDPR erasure keeps its tenant sweep on ABP 10.7 (#698). ABP 10.7's
GdprUserDataDeletionRequestedEtocarries a
TenantId; the GDPR module's publisher sets it to the tenant the deletion was requested in, and the event bus runs
the handler inside that tenant when it is set. That names the layer the request came from, not every layer the
user's documents can sit in (one account can be a member of several tenants), soGdprUserDataDeletionEventHandler
still sweeps the Host and every tenant and does not read the event's tenant. No behaviour change: the "drop the
sweep on 10.7" note in the handler and in the docs is replaced by this decision, and a test pins that an event
naming a tenant still reaches every layer.
Fixed
- Pre-release Angular publishing keeps the
@dignite/ng.flex-fieldsand@dignite/ng.flex-fields-ckeditor
dependencies on npmjs instead of rewriting them to GitHub Packages aliases. Those aliases no longer resolve
for the new abp-modules releases. The published Vault Extract preview package itself still uses the
@dignite-projects/ng.vault-extractname on GitHub Packages.
v0.5.0-preview.15
The abp-modules libraries move to 10.0.0-rc.25 (File Explorer removed upstream; Vault Extract never used it). No EF migration.
Changed
- abp-modules
10.0.0-rc.25, on both sides.Dignite.Abp.FlexFields.*,Dignite.Abp.AspNetCore.Mcp,
Dignite.Abp.Notifications.*andDignite.NotificationCenter.*move to10.0.0-rc.25, and the Angular pins
@dignite/ng.flex-fields,@dignite/ng.flex-fields-ckeditorand@dignite/ng.notification-centermove with them.
rc.25 removesDignite.FileExplorer.*from abp-modules and leaves file-storing with its core only; Vault Extract
does not use File Explorer, so this is a lockstep upgrade with no behaviour change and no EF migration.
v0.5.0-preview.14
The abp-modules libraries move to 10.0.0-rc.24, and a host can now run operator notifications as a split deployment. No EF migration.
Changed
- abp-modules
10.0.0-rc.24, on both sides.Dignite.Abp.FlexFields.*,Dignite.Abp.AspNetCore.Mcp,
Dignite.Abp.Notifications.*andDignite.NotificationCenter.*move to10.0.0-rc.24, and the Angular pins
@dignite/ng.flex-fields,@dignite/ng.flex-fields-ckeditorand@dignite/ng.notification-centermove with them,
so the wire shape stays the same on both ends. rc.23 madeINotificationDefinitionManagerasynchronous, so the one
test that called it awaitsGetAsync/GetGroupsAsync. rc.24 renames the notifications packages after ABP's own
layout: the contracts are nowDignite.Abp.Notifications.Abstractions, and the plainDignite.Abp.Notificationsis
the in-process implementation (the local publisher, the distributor and the delivery handlers).
Dignite.Vault.Extract.Applicationnow referencesDignite.Abp.Notifications.Abstractionsand depends on
AbpNotificationsAbstractionsModule, where it referencedDignite.Abp.Notificationsand depended on
AbpNotificationsModule. Left as it was, it would have pulled the distributor into every process that embeds
Application, and a publisher usingDignite.Abp.Notifications.Clientwould then have distributed its notifications
itself instead of sending them to the notification service. Its production code is otherwise unchanged.
Host impact:- The Vault Extract host as shipped does not change:
Dignite.NotificationCenter.Applicationbrings the
implementation. - A host that embeds Application and installs neither the Notification Center nor
.Clientnow resolves
NullNotificationPublisher: each notification logs a warning and is dropped. Install one of the two to deliver. - The distribution background job is named
Dignite.Abp.Notifications.Distribute(since rc.23), so jobs still
queued under the old name (Dignite.Abp.Notifications.NotificationDistributionJobArgs) are not picked up after the
upgrade. Vault Extract sends each notification to one explicit recipient, which is distributed inline, so its own
queue is normally empty; check thatAbpBackgroundJobsholds no row under the old name before deploying. - No EF migration (
dotnet ef migrations has-pending-model-changesreports none).
- The Vault Extract host as shipped does not change:
- Operator notifications can run as a split deployment (optional). A host may install
Dignite.Abp.Notifications.ClientandDignite.Abp.Notifications.EntityFrameworkCore(or.MongoDB) instead of
Dignite.NotificationCenter.*, map theNotificationCenterconnection string to a notification service's
database, and let that service own the inbox and the SignalR hub. The Vault Extract host as shipped keeps the
monolith install and does not change. In a split deployment the transaction inDocumentNotificationDispatcher
holds only the outbox write of the publish request, not the inbox rows, which the service writes; the comment
there said otherwise and now says both. See
Operator notifications and the
deployment checklist.
v0.5.0-preview.5
Rebuilds the document permission core on ABP's resource-based authorization (#629 → #632 → #635 → #636 → #645 → #648). One rule now governs every documents-domain operation, and the operator UI follows the same pattern: entry (VaultExtract.Documents) AND either the module-wide permission for that operation, the matching grant on the document's own type, or having uploaded it.
Four contract breaks come with it — entry is required everywhere, VaultExtract.Documents stops meaning "read every document" (the new Documents.ReadAll does), Documents.Restore is removed in favour of Documents.Delete, and VaultExtractPermissions.DocumentTypes.Resources moves to VaultExtractResourcePermissions. Each BREAKING entry below carries its migration note, and two changes need a deployment step: the sub-document owner backfill under #635 and the duplicate Host-layer roles left behind by the seed defect in #640.
Added
-
Per-document-type Read / Edit / Delete grants (#632, completing the topic opened by #629). Three resource permissions join
…DocumentType.Uploadon theDocumentTyperesource —…DocumentType.Read,…DocumentType.Edit,…DocumentType.Delete— all managed by the existingVaultExtract.DocumentTypes.ManagePermissions, so ABP's dialog simply renders four checkboxes. One rule governs all of them: an operation on a document is authorized byVaultExtract.Documents(entry) AND either the module-wide permission for that operation OR the matching grant on the document's current type. Entry gates both halves of the OR — a caller who may not open the documents area may not mutate documents in it either, which matters because handing out a per-type grant is gated byDocumentTypes.ManagePermissionsalone, a permission unrelated toDocuments.*. Restore joins the table without a fifth name:RestoreAsyncis admitted by theDeletegrant on the document's type — whoever may delete may undo (#645 then did the same at the role level, mergingDocuments.RestoreintoDocuments.Delete; see its entry below). Reaching the recycle bin requires entry alone, and its rows are the caller's readable soft-deleted documents, own included (#635 — #632 had admitted by the Restore arm across the layer,Documents.Restoreor aDeletegrant on at least one type, while narrowing the rows by the read arm, so aDelete-grant-only caller was let into a bin the UI then reported as empty).PermanentDeleteAsyncremains module-wide only. It is implemented once, in an application-layerDocumentAccessCheckerthat every enforcement point calls (UploadAsync's inline OR from #629 moved onto it), because ABP'sResourcePermissionCheckerhas no module-wide fallback of its own. Reads are additionally narrowed at the query — the operator list, the data download, the MCPsearch_documentstool and the review-queue count all pass through the one sharedDocumentQueries.ApplyMetadataFilterchain, so a page's total count is narrowed by the same predicate as its rows. The MCP read paths (get_documentand thevault-extract://documents/{id}resources) fold the new authorization refusal into the "Document not found" answer they already give for a nonexistent or cross-tenant id, so a document outside the caller's read scope cannot be told apart from one that does not exist.DocumentTypeDto.resourcePermissionsnow carries all four keys. (#632 also gaveIDocumentTypeAppService.GetVisibleAsyncan optionalincludeResourcePermissionsflag for the MCP paths; #636 removed it again before release in favour ofGetVisibleSummariesAsync— see its entry below.) Grants still live inAbpResourcePermissionGrants, which has existed since theInitialmigration — no schema change and no EF migration is required. See the configuration page.Untyped documents belong to no type, so no per-type grant can ever cover one. Under #632 that meant only a
Documents.ReadAllholder reached them; #635 adds the second arm that can — the uploader — which is what finally makes a failed classification reachable by the person who can fix it. Sub-documents carry their own type and are covered by it.The four resource-permission strings are frozen contracts from the first grant row onwards, the same discipline the
Extract:*error codes follow — they are persisted verbatim in the grant table.In the operator UI, the document list and the document detail page gate every per-document action by the same rule (delete, confirm, reclassify, re-recognize, re-extract, field and Markdown editing, reject, allow duplicate, resolve warnings) — #635 moved that judgment onto the server and the client now binds to the
rightsobject on the row, see below. The Confirm / Reclassify type pickers list only the types the caller may assign, bulk-delete selection drops rows the caller may not delete, the Needs review toggle and quick link follow an Edit grant on any visible type, and the overview's statistics card renders only for aDocuments.ReadAllholder — without it the request behind it is never made. Routes are unchanged;Documentsstill gates entry. -
Per-document-type upload permissions (#629), built on ABP's resource-based authorization rather than a hand-written grant table. Two names are introduced: the standard permission
VaultExtract.DocumentTypes.ManagePermissions, which gates who may hand out access, and the resource permissionDignite.Vault.Extract.Documents.DocumentTypes.DocumentType.Upload, granted per document type to a user or a role. A caller's type scope for upload is "every type of the layer if they holdDocuments.Upload, otherwise the types they hold theUploadgrant on", and the grant is enough on its own (#645 — #629 first gave the all-types half toDocuments.ConfirmClassificationand still requiredDocuments.Uploadbeside the grant; see the upload entry under Changed). Grants live inAbpResourcePermissionGrants, which has existed since theInitialmigration — no schema change and no EF migration is required.DocumentTypeDtogains aresourcePermissionsdictionary reporting the caller's own grants onGetVisibleAsync, andIDocumentTypeAppService.GetVisibleAsyncadditionally admitsDocuments.Uploadholders so an upload-only caller can see the list to pick from. Managing the grants goes through ABP's own resource-permission endpoints and dialog; nothing is added toIDocumentTypeAppService. See the configuration page. The document types list gained a Permissions row action (gated byManagePermissions) that opens ABP's resource-permission dialog for the row's type, and the upload picker lists every type plus the untyped "Let AI classify" option for aDocuments.Uploadholder, and otherwise only the types the caller holds anUploadgrant on, from which it requires a selection (#645; #629 first keyed this onConfirmClassificationand showed an empty state to an uploader granted no type, which the overview now answers with its read-only card).Both new strings are frozen contracts from the first grant row onwards, the same discipline the
Extract:*error codes follow — they are persisted verbatim in the grant table. The resource name must in particular stay equal totypeof(DocumentType).FullName, which a unit test asserts.
Changed
- Whoever uploaded a document may now read, edit and delete it (#635). The document permission core is rebuilt around one rule, stated once: entry (
VaultExtract.Documents) AND ( the module-wide permission for the operation OR the caller owns the document, where the rule allows it OR the matching per-type grant on the document's current type ). The per-typeRead/Edit/Deletegrants keep their names and their rows and come to mean "over other people's documents of this type"; their display names say so. Two day-one failures fall out of the new arm: a principal holding entry plus anUploadgrant — the exact shape #629 exists to express — could upload a document and then never see it again, and a document whose classification failed was invisible to every caller without a module-wide permission, so the documents that most need a human were the ones their uploader could not reach. Ownership isDocument.CreatorId, ABP's audit property: no new permission, no new frozen string, no schema change and no EF migration. Derived sub-documents inherit their origin's owner from now on, so the sub-documents of a bundle reach the person who uploaded the bundle. Machine identities (a client-credentials token has nosub) never match the ownership arm.DocumentListItemDtoand `DocumentDto...
v0.3.2
Patch release for the 0.3.x stable line. This release closes a silent field-extraction truncation on large multi-value fields (a production bank-statement document lost the tail of a transcribed table with no error signal), and fixes a cluster of vision-LLM OCR and PDF ruling-line issues surfaced by the same document — LaTeX-table / layout-annotation cleanup, no-content-refusal normalization, and stacked per-row table-box detection.
Fixed
- Field extraction silently truncating large multi-value fields —
FieldExtractionWorkflownever setChatOptions.MaxOutputTokens, so SiliconFlow silently applied its own ~4096-token default completion cap; even once sized (CJK-aware, since field values preserve the document's original wording andDefaultLanguagedefaults to Japanese), the OpenAI SDK serializes it asmax_completion_tokens, which SiliconFlow's endpoint doesn't recognize and silently ignores instead of erroring. ADelegatingHandleron the host's SiliconFlowHttpClientnow rewrites the outgoing request body to the legacymax_tokensfield it does understand; a response cut off at the limit (FinishReason.Length) also now logs a distinct warning instead of degrading with no diagnosable signal. - Chat-client HTTP hangs from stale pooled connections — the host's OpenAI-compatible
HttpClientnow boundsPooledConnectionLifetimeto 5 minutes and raisesNetworkTimeoutto 300s (with the SDK's own 100sHttpClient.Timeoutdisabled, since it was silently overridingNetworkTimeoutback down to 100s), closing a failure mode where a NAT/proxy-dropped idle connection hung every request that reused it for the full timeout before ABP's retry loop re-queued the job. - VisionLlm OCR: LaTeX tables and leaked layout annotations — a vision LLM (observed on Qwen3-VL), trained heavily on academic document datasets, still rendered line-item tables as
\begin{tabular}and occasionally leaked an internal bounding-box HTML comment into the transcription, despite the prompt requiring GitHub-Flavored Markdown and forbidding both.VisionLlmOutputGuardnow deterministically rewrites\begin{tabular}blocks to GFM tables and strips HTML comments, the same fix pattern as the existing code-fence stripper (#448). - VisionLlm OCR: single-page running-header/footer judgment — the prompt now asks the model to judge boilerplate by position and style rather than by confirmed repetition (a single-page call can never confirm repetition across pages), closing a case where a page-bottom confidentiality line and page number survived transcription.
- VisionLlm OCR: no-content refusals inlined as transcribed text — despite the prompt asking for no output at all on an unreadable image, the model sometimes returned an English refusal sentence instead, which was then treated as real content and occasionally misjudged by sub-document segmentation as a standalone document (observed on two purely decorative images in a bank-statement PDF).
VisionLlmOutputGuard.LooksLikeNoContentRefusalnow normalizes a detected refusal to an empty result, length-gated so real (longer) transcriptions can never be misclassified; the segmentation prompt also now treats a confirmed-empty embedded-image OCR result as never a standalone document. - PDF ruling-line grid detection missed stacked per-row table boxes — some report engines (observed on a Japanese bank-statement PDF) draw a table's grid as many small per-row rectangles rather than continuous ruling lines, which
DetectGridssilently dropped, falling back to the less reliable whitespace-heuristic path and mis-clustering rows.ChainStackedRowBoxes/ChainCollinearVerticalSegmentschain these leftover shapes into valid rule candidates.
Changed
SlugSuggestionAppServicemoved off theStructuredkeyed chat client ontoTitleGenerator—Structuredis now reserved for classification and field extraction, the accuracy-sensitive callers where mis-output is user-visible, so it stays pinned to a strong model rather than trimming cost; slug suggestion's single-shot, prompt-unique-per-call shape matchesTitleGenerator's existing usage instead.
v0.3.1
Patch release for the 0.3.x stable line. This release tightens field-schema cleanup and prompt-budget guards, hardens MCP client-IP handling behind trusted proxies, fixes delete guards around recycle-bin documents, restores stable NuGet symbol validation by embedding PDBs, and adds operator bulk-delete selection to the document list and recycle bin.
Added
- Bulk document delete selection — the operator document list and recycle bin now support multi-row selection and bulk delete actions, with localized selection/status text (#534).
Changed
- Release packaging — NuGet packages now embed portable PDBs in the assemblies instead of shipping separate
.snupkgsymbol packages, avoiding NuGet.org symbol-validation failures while preserving Source Link step-in support.
Fixed
- Field-definition cleanup — deleting field definitions now removes orphaned field-validation warnings and duplicate-basis cleanup is schema-aware, so fields with matching codes in different document types are not crossed (#528).
- Field-schema prompt budgets — schema prompt-budget validation now applies per document type and accounts for the actual cascade restore fields (#468).
- Cabinet and document-type deletion — cabinet deletion unfiles recycle-bin documents and uses set-based cleanup; document-type delete guards now count recycle-bin documents instead of allowing a type with retained documents to be removed (#530, #531).
Security
- MCP forwarded client IP handling — the host now trusts forwarded client IPs only through explicitly configured proxies and normalizes trusted proxy address forms, keeping rate-limit identity stable behind supported reverse proxies (#469).
v0.3.0
Second stable release of the channel. The 0.3.0 line adds field validation warnings as a first-class extraction output, brings multi-tenancy to the host (tenant administration, tenant-correct background jobs, and a tenant-scoped MCP surface), broadens ingestion to born-digital formats, deepens OpenXML / PDF structure extraction, repositions the export flow onto the document list, and puts a size ceiling on every text that crosses an LLM boundary. The MCP egress returns to OAuth-only and becomes additively extensible by downstream modules. The granular per-preview history is retained in the 0.3.0-preview.* sections below.
As a
0.y.zrelease the exit contracts may still change — see CONTRIBUTING → Versioning and releases. Upgrading from 0.2.0 is backward-compatible at the package level, but deployments must apply the new EF Core migrations (tenant management,PendingReview, and the field-validation-warning table) before running the new binaries.
Added
- Field validation warnings — field extraction now returns, in one structured LLM response, the extracted value and strongly-typed validation warnings. Warnings persist as a
Documentchild collection, raise a new blocking review reason (FieldValidationWarning) that withholdsDocumentReadyEto, surface on the REST detail and in the operator UI, and are cleared by a clean re-extraction or an explicit operator "mark resolved" action. Generic and business-type-independent — the channel presets no domain rules; architecturally the fourth instance of theDuplicateSuspectedblocking-review pattern (#527). - Multi-tenancy in the host — the host application now includes ABP Tenant Management (EF mapping, migration, and Angular routes) so host operators can administer tenants from the deployed UI (#522). The MCP egress accepts an optional
tenantIdonsearch_documents/get_document/list_document_types/list_cabinetsand returns tenant-scoped resource URIs, preserving the selected layer as clients follow MCP links (#519 and follow-ups). - Digital upload formats — accept CSV / TSV, DOCX, plain-text, and XLSX uploads through the same pipeline as scans and PDFs (#471).
- The MCP surface is additively extensible by downstream modules — a downstream ABP module appends its own tools via
AddMcpServer().WithTools<T>()and its ownresources/listcategories viaVaultExtractMcpOptions.ResourceListContributors, without forking; the open-source surface stays strictly single-tenant (#475, #476). Cabinets are exposed as a discovery resource andsearch_documentscan scope to one (#473);search_documentsresults carry explicittotalCount/truncated(#445). - Document-type configuration packs — export a document type with its field definitions as a portable pack and import it into another layer or deployment, driven from the operator UI with local shape validation, a preview, and create-and-update / create-only reconciliation (#444, #513).
- "Data Download" export — the export flow is repositioned onto the document list, defaults to all of the type's fields, filters by extracted field values, and adds an "export current view" toolbar action (#414, #496); an extracted-field-value filter is available on the operator document list (#415).
- Field-definition prompts accept Markdown with an AI-polish action — a Markdown prompt editor and an AI "polish" endpoint; the former prompt-length cap is dropped (#447).
DocumentLifecycleStatus.PendingReview— a document whose pipelines have run as far as they can but that still carries a blocking review reason derives toPendingReviewinstead ofProcessing, giving the operator UI an honest, non-spinner status without changing the egress gate (#510).
Changed
- A size ceiling now bounds every text crossing an LLM boundary (#491). Field extraction and segmentation gate above the ceiling — reaching a terminal review state rather than extracting from a truncated prefix, and never rethrowing an oversized body into the job-retry loop; classification / title / cabinet suggestion and the MCP document body truncate surrogate-safely and announce the cut. Prompt ceilings are host configuration (
VaultExtractBehaviorOptions); the MCP egress ceiling is a compile-timeconst. - Document pipeline background jobs run in the document's tenant context — parse, classification, field extraction, segmentation, and cabinet-suggestion jobs no longer leak through ambient or missing tenant state, with regression coverage across the reprocessing dispatch paths (#521).
- One figure format across PDF and OpenXML — OpenXML figure transcriptions are wrapped in the same
ImageOcrMarkupmarkers the PDF path emits, so downstream sees a single figure representation (#480). - Deeper OpenXML structure extraction — DOCX custom-style heading levels (#316), footnotes / endnotes (#315), and per-instance figure walking (#322); PPTX group-transform / layout-inherited reading order and group scale composition (#313, #456);
mc:AlternateContentshapes no longer silently skipped (#319); heading resolution and figure traversal memoized per document (#458, #318). - Build / packaging — SourceLink, deterministic CI builds, and NuGet symbol packages; NuGet and npm license metadata aligned with the LGPL-3.0-only LICENSE.
Fixed
- Concurrent-upload deadlock — documents uploaded concurrently no longer deadlock in the pipeline (#533).
- Non-BOM legacy-encoded
.csv/.tsv/.txtno longer decode as UTF-8 and land inDocument.Markdownas U+FFFD garbage (#493). - Restore the embedded-document route that the segmentation rework left detected-but-unroutable, as a Markdown slice (#494); restore the sub-document delete guard on both delete paths (#508).
- Field extraction is scheduled transactionally at classification completion, closing a premature-
Readyrace, and a reused pipeline run clears its stale status message on retry (#527). - DOCX note-body hyperlinks resolved against the owning
FootnotesPart/EndnotesPart(#457); the #268 completeness signal trips when the PDF lattice path drops an out-of-grid fragment (#450 follow-up); multi-level chart category axes and blank leaf category labels (#321). - Angular: serialize document-list
fieldFiltersinto bindable query params (#415); dark-theme-aware document-detail cabinet text color.
Removed
- The static MCP
X-Api-Keyauthentication channel (added in 0.2.0, hardened in #431–#435) —/mcpis OAuth-only again. Guided OAuth and the OAuth client-credentials grant cover both interactive and headless clients, so a standing pre-shared secret is redundant; a leftoverMcp:ApiKeyconfiguration section is now inert and ignored (#514). - The export-template layer, superseded by the document-list-driven "Data Download" export (#499); unused lerna tooling from the build (#503).
Security
- The gitignored
appsettings.secrets.jsonno longer leaks intodotnet publishoutput (#502). - Within the line, the MCP API-key channel was first promoted to a real ASP.NET Core authentication scheme and hardened — per-IP rate limiting, SHA-256 hash-at-rest keys, and a least-privilege service-account seed (#431, #433, #434, #435) — and then retired in favour of OAuth-only
/mcp(#514, see Removed); the granular history is in the preview sections below.
v0.2.0
First stable release of the 0.2.0 line. Headlined by the rebrand to Dignite Vault Extract, the container / sub-document model, and a major expansion of structure-aware text extraction (PDF / DOCX / PPTX). The granular per-preview history is retained in the 0.2.0-preview.* sections below.
Upgrading from 0.1.0 is breaking: NuGet package IDs and namespaces moved to the
Dignite.Vault.Extract.*prefix, the Angular library is now@dignite/vault-extract, and the C# module / type prefix isVaultExtract. See the Changed entries below. As a0.y.zrelease the exit contracts may still change — see CONTRIBUTING → Versioning and releases.
Added
- Container & sub-document model — a document can be recognised as a container and segmented into derived sub-documents, with full provenance across the MCP and Angular egress and
OriginDocumentIdon the events (#346, #347, #351, #354, #360, #363, #371, #375). - Structure-aware text extraction — embedded raster/image extraction from digital PDF, DOCX, and PPTX via
IOcrProvider/ OpenXML; column-aware PDF reading order; digital-layer and lattice (ruled) table reconstruction into Markdown tables; PDF font size/weight → Markdown headings; running header/footer stripping; skip the full-page scan background of searchable / sandwich PDFs; and figure OCR markers kept as egress provenance annotations (#301, #311, #308, #323, #307, #314, #309, #324, #310, #326, #329, #340, #403, #383, #381, #450). - Static API-key fallback authentication for the
/mcpegress, alongside OpenIddict Bearer and the OAuth discovery flow, for clients that cannot run the dynamic OAuth flow (#430, closes #428). MCP discovery is now a one-callAddExtractMcpDiscovery(...)extension (#422). - Duplicate re-upload detection via field fingerprint, gating
DocumentReadyEto(#411). - Angular: live pipeline status on document detail via interim polling (#442); render LongText extracted-field values as Markdown (#418); document AI overview statistics with cabinet / document-type overview cards and an upload-first home page (#333, #341, #335, #342, #332, #339).
Changed
- BREAKING — package identifiers renamed to the
Dignite.Vault.Extract.*prefix, and the Angular library is published as@dignite/vault-extract(#370, #382). - BREAKING — C# type and module prefix unified from
ExtracttoVaultExtract(VaultExtractDomainModule,VaultExtractDbContext,VaultExtractErrorCodes, …), matching theDignite.Vault.Extractnamespace and ABP convention. Namespaces, theExtractextraction verb, and every serialized contract (error codesExtract:*, DB table prefix, config sections, blob container, localization resources) are unchanged (#438). - Rebranded the UI to the DIGNITE badge; reduced to four supported languages and aligned the localization files to a common layout.
- OCR recognition language is now provider-specific; removed the dead central
VaultExtractOcrOptionslayer (#441). - Enforce document-type layer-scoped uniqueness in the application layer (#304).
Fixed
- PDF reading-order and table reconstruction hardening: band-aware ordering, robustness to narrow gutters / sparse / empty columns, and key-value tables under titles / stamps (#407, #446 and related).
- Unwrap stray Markdown code fences from VisionLlm OCR so tables render (#448).
- Block deleting a source that still has live sub-documents, and harden the orphan read path (#391).
- Keep document titles / headings out of the OCR running-header exclusion (#409).
- Escape source-text Markdown metacharacters in generated output (#320, #337).
- Angular: dark-theme-aware document detail, home context panel, and upload drop-zone; reason-aware review banner with a complete-fields action; localize
ExportFormat/FieldDataTypelist labels; persist list filters / paging in the URL.
Removed
- Legacy Angular document-upload route and dead segmentation fields (#390).
- Dead central OCR options layer (#441) and the
pack-all.ps1packaging script.
Security
- Bumped Angular to 21.2 and patched dev-dependency CVEs (#425).