You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Docbank now has a fixed-route Datalab Convert adapter for every format a profile declares and the media inspector authorizes. It uploads the exact verified source, polls the known request, and maps Marker Document/Page output into page, slide, sheet, or image evidence. Unverified structure falls back to bounded Markdown with degraded provenance.
Provider callback and result URLs are ignored. Hosted profiles require HTTPS and a named API-key binding; redirects, ambient cookies, proxies, oversized responses, partial results, and version drift fail closed. Once Datalab returns a request ID, Docbank stays on that job instead of risking a second paid submission.
Why
Datalab can cover more formats than a PDF-only adapter, but the same exact-byte, local-inspection, destination, and provenance rules still apply. Ambiguous or partial conversions must not become silent duplicate charges or incomplete durable evidence.
Usage
For library use, construct the client with datalab.New(profile, secrets, httpClient). The profile pins its HTTPS origin, named API-key binding, locally inspectable formats, and finite source, result, and artifact limits.
This PR adds the adapter contract only. Daemon, API, and CLI registration is intentionally deferred to S1–S3.
Bridge contract diverges from runtime validation — document/bridge/source-evidence-v1.schema.json:75, document/bridge/openapi.yaml:175
Unit omissions require a locator at runtime, but the schema neither defines it nor permits extra properties. OpenAPI also accepts any object—including {}—as a receipt, while runtime validation requires a closed, populated RenditionReceipt. Generated implementations may fail to interoperate. Fix: Add the omission locator and kind-specific requirements to the evidence schema, fully define receipt and usage schemas, and test representative responses against both schemas and runtime validation.
Artifact limits are enforced after payload retrieval — document/bridge/client.go:390
Payloads are downloaded before checking MaxArtifacts, AllowedArtifactRoles, or MaxTotalResultBytes. A bridge can therefore force the daemon to download and retain many or unauthorized payloads before rejection. Fix: Validate artifact count and roles before resolving payloads, then enforce an overflow-safe cumulative byte limit while reading inline and result-route artifacts.
Verdict: Changes requested—three medium-severity issues could cause runaway processing or incorrect authorization and version metadata behavior.
Medium
Terminal extraction failures loop indefinitely — internal/store/extraction.go:480
After lexical cutover, terminal failures remain queued and are immediately reprocessed. A batch of invalid or oversized blobs can create a tight loop that repeatedly rewrites extraction state and rebuilds lexical generations, starving later work. Fix: Remove queue entries for terminal results from the current extractor and rely on extractor-version changes to requeue them. Add a worker-level test covering persistent failures after lexical publication.
Authorization expiry is not enforced during bridge jobs — document/bridge/client.go:124 Render checks authorization.ExpiresAt only initially and then uses TotalTimeout. A job may continue polling and fetching artifacts after authorization expires; endpoint-controlled timestamps could also allow post-expiry results to appear valid. Fix: Bound execution by the earliest caller deadline, total timeout, or authorization expiry. Check the local clock before requests, artifact fetches, and successful return, and cancel the remote job immediately upon expiry.
Historical versions receive current attachment metadata — internal/store/source_metadata.go:194
Historical content metadata is combined with the node’s current filename, path, and latest provenance. After a rename, move, or content replacement, the versions API can attribute old bytes to newer attachment facts. Fix: Persist and query attachment/provenance snapshots per content version, or omit facts that cannot reliably be associated with the requested version.
The PR has one high-severity transport vulnerability and four medium-severity correctness and concurrency issues.
High
Cleartext provider origins expose documents and credentials — document/docling/client.go:678, document/bridge/client.go:546
Both clients permit non-loopback http:// origins under the operator_network trust boundary, transmitting source documents and API credentials in plaintext. Network observers or attackers could steal or alter documents, credentials, and returned renditions. Require HTTPS for all non-loopback origins. If local HTTP is needed, use a restricted transport that ensures every resolved address is loopback-only, while preserving transport injection for tests.
Medium
Uploaded content is not verified against its authorized digest — document/bridge/client.go:258
The bridge checks only upload length, so a mutable or custom AuthorizedUpload can transmit different same-length bytes while claiming the authorized SHA-256 digest. Hash the stream, compare it with metadata.SHA256, and ensure multipart writing completes successfully before accepting the response.
Cancellation and transport errors lose their classification — document/bridge/client.go:172
Raw context errors violate the rendition-provider error contract, causing document.RenderRendition to replace them with an “unclassified rendition provider error.” Wrap cancellation, deadline, and transport failures using the appropriate RenditionProviderError codes, with coverage through document.RenderRendition.
Historical versions can be reported with current provenance — internal/store/source_metadata.go:194
Historical metadata combines the requested version’s blob evidence with the node’s current path and latest provenance, potentially attributing a replacement’s source path and timestamps to an older version. Associate provenance with the content version or introducing operation; otherwise omit facts that cannot be tied to the requested version.
Backfill batches can block exclusive maintenance for hours — cmd/docbank/daemon.go:179
Checksum and source-metadata backfills hold the mutation gate for an entire batch, including reads of potentially large originals, while new mutations are rejected as maintenance-busy. Acquire and release the gate per target, or yield between targets so queued exclusive maintenance can take precedence.
Verdict: One high-severity security issue and four medium-severity correctness issues require fixes.
High
Windows upload spools may expose private document contents through inherited DACLs Location:document/upload/spool_windows.go:29 Mkdir(..., 0o700) and OpenFile(..., 0o600) do not guarantee owner-only permissions on Windows. The spool directory and file inherit the parent DACL, potentially allowing another local account to read or replace the staged document. Fix: Create and pin the directory with a protected, current-user-only DACL using the established winsecurity.MkdirPrivatePinnedAt pattern, then validate the restricted DACL. Alternatively, reject spool roots that are not owner-restricted.
Medium
Authorized upload integrity is not verified Location:document/bridge/client.go:258
The bridge checks only upload length, so different same-length content can be uploaded while the manifest, idempotency key, and result remain bound to the authorized SHA-256. Fix: Read into a bounded local spool, verify both length and SHA-256 before starting the HTTP request, and upload only the verified bytes.
Operations can continue after authorization expires Location:document/bridge/client.go:124
The operation deadline ignores authorization.ExpiresAt, allowing polling, artifact retrieval, and remote processing beyond the authorization interval. Fix: Bound the operation context by the earliest caller deadline, total timeout, or authorization expiry, and classify expiry as a policy rejection.
Auxiliary MD5 enrichment breaks exact-build retries Location:internal/store/processing_catalog.go:313
Retry validation compares the submitted build against a loaded record enriched with MD5 from blob_checksums, although MD5 is not stored in rendition_artifacts. This can incorrectly report different immutable metadata for a staged publication. Fix: Exclude auxiliary MD5 data from immutable build equality and enrich returned views only after reuse validation.
XMP parsing collapses sibling RDF values Location:internal/processing/source_metadata.go:337
XML character data is copied into every open ancestor without preserving child boundaries, causing RDF list values such as multiple creators to be concatenated and deeply nested input to amplify allocations. Fix: Parse RDF list items explicitly and use bounded buffers only for recognized fields, preserving individual rdf:li values.
Two medium-severity issues need attention; no security regressions were identified.
Medium
Permanent extraction failures are requeued indefinitely — internal/store/processing_migration.go:239
After lexical cutover, RecordExtraction preserves queue entries for live blobs, while migration treats failed results as ineligible and reinserts them. Terminal failures such as oversized or invalid UTF-8 files will therefore retry forever. Treat current-version ExtractionFailed results as completed terminal outcomes and clear their queue entries. Add a worker test with an active lexical head confirming the queue drains.
Artifact response media types conflict between the OpenAPI contract and client — document/bridge/openapi.yaml:74, client.go:479
OpenAPI declares application/octet-stream, but the client requires Content-Type to exactly match the artifact manifest’s media type. A server generated from the published contract may consequently be rejected. Specify a wildcard/dynamic response media type compatible with the manifest, or allow application/octet-stream in the client while retaining checksum and length validation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Docbank now has a fixed-route Datalab Convert adapter for every format a profile declares and the media inspector authorizes. It uploads the exact verified source, polls the known request, and maps Marker Document/Page output into page, slide, sheet, or image evidence. Unverified structure falls back to bounded Markdown with degraded provenance.
Provider callback and result URLs are ignored. Hosted profiles require HTTPS and a named API-key binding; redirects, ambient cookies, proxies, oversized responses, partial results, and version drift fail closed. Once Datalab returns a request ID, Docbank stays on that job instead of risking a second paid submission.
Why
Datalab can cover more formats than a PDF-only adapter, but the same exact-byte, local-inspection, destination, and provenance rules still apply. Ambiguous or partial conversions must not become silent duplicate charges or incomplete durable evidence.
Usage
For library use, construct the client with
datalab.New(profile, secrets, httpClient). The profile pins its HTTPS origin, named API-key binding, locally inspectable formats, and finite source, result, and artifact limits.This PR adds the adapter contract only. Daemon, API, and CLI registration is intentionally deferred to S1–S3.
Part of #176 (R8). Stacks on #198.