Documents and Maintenance
Documents store metadata for physical files. Maintenance requests track operational issues and interventions.
documents
Purpose
Stores metadata for physical files saved on disk or object storage.
Suggested attributes
| Field | Description |
|---|---|
id | Primary identifier. |
entity_type | Linked business entity type. |
entity_id | Linked business entity identifier. |
document_type | Contract, invoice, bill, identity document, receipt, photo, report, or other document type. |
file_path | Disk or object storage path. |
file_name | Original or display file name. |
mime_type | File MIME type. |
uploaded_by_user_id | Platform user who uploaded the file. |
created_at | Creation timestamp. |
notes | Free-form notes. |
Linked entities
| Entity | Example use |
|---|---|
party | Identity document, company certificate, tax document. |
property | Cadastral document, floor plan, property photo. |
property_unit | Room photo, room inventory. |
contract | Contract PDF or registration receipt. |
bank_transaction | Bank receipt or supporting proof. |
expected_expense | Expected bill notice. |
utility_bill | Utility bill PDF. |
maintenance_request | Photos, estimates, completion proof. |
expense | Invoice or receipt. |
Relationships
| Relationship | Description |
|---|---|
documents.uploaded_by_user_id to users.id | Optional uploader reference. |
documents.entity_type and documents.entity_id | Polymorphic business link. |
Notes and design rationale
Contracts are business entities. The contract PDF is a document linked to a contract. File storage concerns should remain separate from business records.
vector_rebuild_runs
Purpose
Tracks administrator-triggered Vector DB rebuild executions. The table stores the durable state of a rebuild; WebSocket events are only a live delivery mechanism and are not the source of truth.
Suggested attributes
| Field | Description |
|---|---|
id | Primary identifier. |
status | PENDING, RUNNING, COMPLETED, COMPLETED_WITH_ERRORS, FAILED, or CANCELLED. |
started_by_user_id | Admin user who started the rebuild. |
cancelled_by_user_id | Admin user who requested cancellation. |
started_at | Rebuild start timestamp. |
finished_at | Rebuild completion/cancellation/failure timestamp. |
total_documents | Number of candidate documents for the run. |
processed_documents | Number of documents processed so far. |
failed_documents | Number of failed documents. |
skipped_documents | Number of skipped documents. |
options_json | Rebuild options used for the run. |
summary_json | Final counters and technical summary. |
error_message | Run-level error when the whole run fails. |
summary_json.metrics stores the operational summary:
| Metric | Meaning |
|---|---|
totalDurationMs | Total run duration in milliseconds. |
documentsPerMinute | Processed documents per minute. |
ocrFailures | Failed items classified as OCR/text-extraction failures. |
indexingFailures | Failed items classified as indexing/vector failures. |
indexed | Successfully indexed documents. |
failed | Failed documents. |
skipped | Skipped documents. |
vector_rebuild_run_items
Purpose
Tracks per-document rebuild state for one Vector DB rebuild run.
Suggested attributes
| Field | Description |
|---|---|
id | Primary identifier. |
run_id | Parent rebuild run. |
document_id | Document being processed. Nullable to preserve run audit if a document is later deleted. |
document_version_id | Document version processed by the run. Nullable to preserve run audit if a version is later deleted. |
status | PENDING, PROCESSING, INDEXED, SKIPPED, or FAILED. |
ocr_applied | Whether OCR was applied during processing. |
chunks_created | Number of vector chunks created. |
error_message | Item-level error. |
started_at | Item processing start timestamp. |
finished_at | Item processing end timestamp. |
Ownership
document-indexer-service owns rebuild orchestration and Vector DB writes. docs-service owns document download and storage access. datahub owns persistence. redisWsBridge delivers progress events to AdminInterface.
Security and audit
All admin rebuild endpoints are protected server-side through authService /auth/validate; the UI token is validated by the backend before any run or preview is created.
Security constraints:
- AdminInterface never receives storage tokens, storage object keys, document contents, extracted text, or vector chunk text.
- Preview returns only technical metadata and counters.
- Redis events contain only
runId, state, counters,documentId, OCR yes/no, chunk count, timestamps, and compact errors. - Logs must not include document content, chunk text, storage object keys, or provider tokens.
started_by_user_idandcancelled_by_user_idprovide auditability for destructive/expensive operations.
Rebuild preview options
The first admin endpoint for this capability is POST /document-indexer-service/admin/vector-rebuild/preview.
Supported options:
| Option | Values |
|---|---|
mode | missing_only, changed_only, full_rebuild |
scope | all, entity_type, entity_id, document_id |
deleteBeforeReindex | Boolean, used by later execution endpoints. |
forceOcr | Boolean. |
maxDocuments | Positive integer with service-side cap. |
dryRun | Always treated as true by the preview endpoint. |
The preview endpoint is read-only: it reads document metadata and extracted text presence from datahub, but does not download files, run OCR, create embeddings, or write to Qdrant.
Rebuild run APIs
| Endpoint | Purpose |
|---|---|
POST /document-indexer-service/admin/vector-rebuild/start | Creates a run, creates run items, starts async processing, and returns runId immediately. |
GET /document-indexer-service/admin/vector-rebuild/runs | Lists rebuild runs for history and recovery. |
GET /document-indexer-service/admin/vector-rebuild/runs/:id | Returns one rebuild run. |
GET /document-indexer-service/admin/vector-rebuild/runs/:id/items | Lists per-document items for a rebuild run. |
POST /document-indexer-service/admin/vector-rebuild/runs/:id/cancel | Marks the run as CANCELLED; the worker stops between documents. |
POST /document-indexer-service/admin/vector-rebuild/runs/:id/retry-failed | Creates a new run with only failed items from the source run. |
Rollout note:
- First release: schema, dry-run, and AdminInterface preview only.
- Second release: single-document rebuild is enabled with
VECTOR_REBUILD_SINGLE_DOCUMENT_ENABLED=true; start requests must usescope=document_id. - Third release: batch rebuild is enabled with
VECTOR_REBUILD_EXECUTION_ENABLED=true; all scopes can be executed andmaxDocumentscontrols batch size. - Fourth release: retry failed items, cancellation controls, complete paginated history, and operational refinements in AdminInterface.
Execution is idempotent at document level: before rebuilt chunks are inserted, existing Qdrant points for that document_id are deleted. Chunk metadata includes document_id, document_version_id, chunk_index, checksum, entity_type, and entity_id.
OCR remains owned by docs-service. The rebuild worker reuses stored document_texts when available and long enough; otherwise it sends the downloaded file to docs-service /docs/text/extract and indexes the returned extracted/OCR text.
Rebuild live events
document-indexer-service publishes Redis events after persisted run/item state changes. WebSocket delivery through redisWsBridge is best-effort; the persisted run tables remain the source of truth.
| Event | Meaning |
|---|---|
vector_rebuild.started | Run and items were created. |
vector_rebuild.progress | Counters changed. |
vector_rebuild.item_completed | One document was indexed. |
vector_rebuild.item_failed | One document failed and the run continued. |
vector_rebuild.completed | Run reached COMPLETED or COMPLETED_WITH_ERRORS. |
vector_rebuild.failed | Run-level failure. |
vector_rebuild.cancelled | Run was cancelled. |
Payloads include runId, status, counters, timestamp, and, when applicable, documentId and a short error message.
Operational limits and recovery
The first implementation processes one document at a time. This keeps storage, OCR, embedding generation, and Qdrant load predictable. Cancellation is cooperative: if a document is already being indexed, processing stops before the next item.
If WebSocket delivery is unavailable, AdminInterface must show a warning and use the persisted run APIs as recovery source:
GET /document-indexer-service/admin/vector-rebuild/runs/:idGET /document-indexer-service/admin/vector-rebuild/runs/:id/items
Recommended recovery procedure:
- Inspect the run status and failed items.
- Use compact item errors to identify the failing capability: storage download, OCR, embedding, or Vector DB.
- Fix the owner service/configuration.
- Retry with
document_id,entity_id, ormissing_onlyscope before usingfull_rebuild.
maintenance_requests
Purpose
Tracks maintenance issues and interventions.
Suggested attributes
| Field | Description |
|---|---|
id | Primary identifier. |
property_id | Linked property. |
property_unit_id | Optional unit attribution. |
reported_by_party_id | Party that reported the issue. |
assigned_to_party_id | Assigned provider, manager, or internal party. |
category | Maintenance category. |
priority | LOW, MEDIUM, HIGH, or URGENT. |
status | OPEN, IN_PROGRESS, WAITING_FOR_SUPPLIER, COMPLETED, or CANCELLED. |
description | Issue description. |
estimated_cost | Estimated cost. |
final_cost | Final cost. |
document_id | Optional primary document. |
created_at | Creation timestamp. |
closed_at | Closure timestamp. |
Relationships
| Relationship | Description |
|---|---|
maintenance_requests.property_id to properties.id | Each request belongs to a property. |
maintenance_requests.property_unit_id to property_units.id | Optional unit-level request. |
maintenance_requests.reported_by_party_id to parties.id | Reporter party. |
maintenance_requests.assigned_to_party_id to parties.id | Assigned party or provider. |
maintenance_requests.document_id to documents.id | Optional primary document. |
maintenance_requests to expenses | A maintenance request may generate one or more expenses. |
Notes and design rationale
Maintenance requests connect operational workflows to properties, tenants, providers, expenses, and documents. Future implementations may add a dedicated maintenance-expense join table if one request generates several invoices.