DATA-WSF-001 — Reconcile metadata and object mutations
| Field | Value |
|---|---|
| Status | Open; source-verified |
| Severity | High |
| Components | sparqd/workspace-file-management-backend, PostgreSQL, S3/OSS |
| Associated issues | Not opened |
Concrete observed case
Create, update, clone, multipart completion, and revert mutate object storage before committing PostgreSQL. A commit or uniqueness failure can leave an unreferenced object or version. Permanent file and folder deletion removes objects before committing metadata deletion; an intervening failure can leave live metadata pointing at missing bytes or a partly deleted subtree.
Expected condition
Every operation reaches one observable terminal state: committed, compensated, or queued for reconciliation. Retrying must be idempotent.
Why it matters
The two stores cannot share a database transaction. Untracked bytes increase cost, while metadata pointing to missing content causes user-visible loss.
Existing controls and workarounds
Name uniqueness constraints prevent duplicate active metadata. They cannot remove bytes already written before the constraint fails. Operators currently need manual inspection.
Do not retry an ambiguous failed upload blindly; first refresh and check whether metadata committed.
Alternatives considered
- Recommended: persisted operation/outbox state plus idempotency keys, compensation, and a periodic reconciler.
- Immutable object first with a pending metadata row, promoted after commit.
- Best-effort inline rollback only — useful but insufficient when rollback itself fails.
Component involvement
- The workspace file backend owns idempotency, durable operation state, compensation, and reconciliation.
- PostgreSQL records operation intent and terminal outcome.
- S3/OSS supplies immutable identity and deletion/version results.
Reproduction and verification
Inject storage and commit failures at each boundary in a disposable bucket and database. Confirm retries and the reconciler converge without losing committed content.
Resolution conditions
Close when fault-injection tests cover every cross-store operation and orphan or missing-object metrics alert within an agreed objective.
Validation and blockers
Mutation ordering is source-confirmed. Fault injection and an orphan inventory were not run in the shared sandbox.