Keep the default quarantine policy for ordinary uploads and captures without a provider-resolved device identity. Audit the selected policy without fabricating a release or review event. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
QBit Record Files
Paused, unreleased work in progress — 2026-11-04. Implementation has stopped. This is a source checkpoint, not a production-ready release or a complete installable package set.
Start with current status and build prerequisites and known issues. These documents supersede older release-readiness statements below.
The root Maven module contains the QBit and its integration-test fixture classifier. Byte storage and attachment intake use the existing Collaboration attachment contracts. Generation and printing integrations live in their owning bridge modules, not here.
Retained, ordered, reviewed and audited files for QQQ records, built on the standard collaboration attachment path. Release candidate, not a production 1.0. See docs/TODO.md for exactly what is and is not done and docs/V1-REMAINING.md for the current v1 assessment.
What it does
- Bytes are stored once, through
AttachmentsService.upload; Record Files adds a retained-file row that references the attachment (checksum, size, media type, storage reference, provenance, lifecycle) and never writes collaboration tables or copies bytes. - A lifecycle adapter (
RecordFilesAttachmentLifecycle) plugs into collaboration's attachment SPI so every standard upload to a configured parent table is registered and retained, ordinary deletion and parent cleanup cannot remove it, and link issuance is gated and audited. Collaboration never imports this module. - File collections hold files of one source record in an explicit order; user-defined categories and review statuses classify files. Service changes commit with their outcome events. User-created categories and statuses use standard QQQ create/edit processes with atomic before/after audit; generic direct writes are denied.
- Events are append-only and carry actor, server time and correlation id. A signed-link event means "link authorized", not "downloaded".
Tables and permissions
| Table | Written by |
|---|---|
record_files_category, record_files_review_status |
audited create/edit processes requiring record-files.configure |
record_files_file, _collection, _collection_item, _event |
services only (direct writes denied) |
Permissions: record-files.view, .manage (intake, collections), .review, .release
(leave quarantine), .configure, .audit (read events). Every read and every service
action is also limited by whether the caller can see the source record.
Services
RetainedFileService (idempotent intake, get, listForRecord), CollectionService,
FileReviewService, PrintObservationService (observations only). Each has a no-arg
constructor that resolves the installed configuration and an injectable constructor.
Install
Produce collaboration first with the adapter as its attachment lifecycle, then this QBit. The producer refuses to install otherwise. Pick an
independent durable audit port suitable for your backend (RecordFilesQBitConfig.withAuditPort);
the default TableAuditPort opens and commits its own real JDBC transaction. It currently
qualifies file-backed H2 with WRITE_DELAY=0 and refuses memory/no-op transactions.
Apply RecordFilesSchema.h2Script(config) using host migration tooling after the owner
attachment schema. The prospective PostgreSQL script is not a supported runtime promise.
Not a 1.0
Resumable staging/session/finalization services and exact-version audited content reads
exist; HTTP/client integration is active work. Production storage lock, malware scanning,
completed-transfer observation and verified restore remain release gates.
New files are quarantined until released because nothing here scans content.
quarantineGeneratedFiles is an optional host setting: null (the default) inherits
quarantineNewFiles; explicit true/false selects initial quarantine only for
trusted Java intake with origin GENERATED. A host may choose false for renderer
outputs so native Preview returns its retained original immediately. This policy
applies to all trusted generated outputs, not only previews. Hosts must trust every
in-process producer allowed to supply that origin; origin is provenance, not a
cryptographic attestation of safe content.
quarantineCapturedFiles is a second optional host setting with the same shape
(getQuarantineCapturedFiles() / withQuarantineCapturedFiles(Boolean); null, the
default, inherits quarantineNewFiles). It applies only to intake with origin
CAPTURE and a nonblank device identity, and GENERATED keeps its own policy.
In the upload path that identity is the server-persisted capture identity that the
host's CaptureIdentityProvider resolved and revalidated; the manifest cannot carry
a device, actor, policy or CAPTURE label (strict JSON rejects them; CAMERA and
GALLERY items map to CAPTURE, so a device that passes the provider can label an
item either way). A desktop request with no provider identity, or any UPLOAD,
SCANNER_IMPORT, IMPORT or attachment-panel file, keeps quarantineNewFiles.
Direct Java RetainedFileService.intake callers are trusted host code, like
GENERATED: they could pass CAPTURE plus a device id, so hosts must not expose
that call to untrusted input.
Host prerequisites before setting it to false: a CaptureIdentityProvider that
actually approves each device and actor (a device id alone proves nothing, and Record
Files does not decide approval); an UploadConfiguration that bounds media types,
sizes and quotas to what the host accepts (for example JPEG/PNG only); and
parent-table visibility and permissions as before. Nothing scans content, so this
is a host trust decision, not a malware or human-review result. Existing quarantined
files are not released by configuration; release them through the normal release
process. Compatibility: the setting is additive and defaults to null, so existing
hosts and persisted data behave exactly as before.
Upload manifests cannot select GENERATED or change host policy. Uploaded,
imported and standard attachment-panel originals, and captures without a device
identity, retain quarantineNewFiles. Initial admission records FILE_REGISTERED with the chosen
policy and lifecycle, without a release, scan or human-review claim. Hash failures
still produce FAILED; permissions, current parent authorization and mandatory
audit remain enforced. Changing configuration never releases existing quarantined
versions, including replayed intakes. Production hosts must explicitly decide
whether their generated-output producers justify this policy; the product default
does not opt in.
Build
Requires JDK 21 and a qbit-collaboration release that contains the attachment lifecycle SPI
(qbit-collaboration.version in pom.xml). Built against released QQQ 4.1.0-RC.21
(qqq.version, imported through qqq-bom-pom) and parent qbit-build-parent 2.1.1.
./mvnw verify
Maven publication
Published POMs are self-contained: the estate's flatten-maven-plugin (ossrh mode) resolves ${revision} and the version
properties at build time, so a consumer needs no -Drevision override. The version comes from <revision> in pom.xml.
The inherited qbit-build-parent POM still warns until its owner publishes a literal version. Release candidate, not GA.