Designing Append‑First Data Models for Docs‑Style Collaboration and Auditing
16th August, 2026
I was debugging a billing dispute when two things happened: a product manager edited the same paragraph I had just summarized, and an automated summarizer had already emitted a citation that no longer matched the new text. That tiny race—human edit, background job, and model output colliding—exposed a core tension: collaboration is not just about low-latency syncing; it changes what you record, how you index it, and who owns the truth.
In this post I explain a mental model for collaboration-aware data models, show a concrete architecture/data-flow example, and describe what I implemented in the ARIL tenancy and audit model. I end with failure modes, mitigations, and a practical checklist you can apply to similar systems.
Why collaboration changes the data model
Traditional data models assume a primary record that gets updated in place. Collaboration, especially Google Docs-style concurrent editing, undermines that assumption in four ways:
- Multiplicity of truth: multiple users (and automated agents) can change state concurrently. - Temporal reasoning: consumers need to know which version produced a downstream artifact (a summary, a vector embedding, an audit decision). - Tenant isolation: collaborative systems are often multi-tenant, so isolation and policy must travel with the data. - Auditability: you must be able to reconstruct who changed what, when, and which downstream outputs used which inputs.
Mental model: append-first, lineage-second
Treat the document store as an append-only stream of operations (or deltas), and treat the current document state as a projection. Record edits, citations, and derived artifacts (embeddings, summaries) as first-class, versioned objects with stable identifiers. Key concepts:
- Operation: an atomic user or system change (insert, delete, attribute change) with author, timestamp, and op-id. - Snapshot: a point-in-time projection of operations (can be a CRDT state, or a compacted diff). - Artifact: anything derived from a snapshot (embedding vectors, summaries, classification labels), annotated with source snapshot-id and a digest of the inputs. - Tenant context: the tenant id and policy tags travel with every operation and artifact.
This model makes lineage explicit: an artifact references the exact snapshot (or op-range) that produced it. You can invalidate or recompute artifacts if the referenced snapshot changes.
A concrete architecture/data-flow example
Below is a compact flow for “document edited -> embedding updated -> retrieval used for a model response”:
1. User edits document in the browser. The client emits a sequence of operations to the collaboration service (CRDT or OT). Each op includes tenant-id and user-id. 2. The collaboration service appends ops into the tenant-scoped operation log and emits a committed snapshot event with snapshot-id (compaction runs asynchronously). 3. A downstream worker subscribes to snapshot events and computes deterministic artifacts: chunking, text cleaning, embeddings. The worker writes artifacts to a tenant-scoped vector table with artifact metadata including snapshot-id and op-range used. 4. A retrieval query resolves candidate artifacts by vector similarity and then verifies artifact snapshot-ids against the latest document snapshot for staleness; if stale, it either re-ranks or queues recomputation. 5. The final model pipeline emits a response and records an audit event referencing: request id, tenant id, artifact ids used, model version, and snapshot-ids.
A minimal table to clarify responsibilities
| Component | Responsibility | |---|---| | Collaboration log | Append ops, low-latency sync (CRDT/OT), tenant scoping | | Snapshot service | Compact ops into snapshots, assign snapshot-ids | | Artifact worker | Deterministic chunking/embeddings; store artifact metadata referencing snapshots | | Retrieval service | Vector queries + snapshot staleness checks | | Audit store | Durable events linking request -> artifacts -> snapshots -> users |
What I built around this idea (ARIL tenancy and audit model)
In the ARIL local monorepo I implemented the core pieces of this approach:
- Tenant-scoped knowledge bases, documents, and chunks with protected routes and per-tenant isolation. (Implemented) - Embedding generation and pgvector-backed retrieval with artifact metadata that references document/chunk ids and snapshot markers. (Implemented) - Citation and evaluation metrics attached to artifacts and model outputs so each response can be traced back to sources. (Implemented) - An audit trail model that logs events (who, when, what artifacts were used). (Implemented)
What remains a gate or operational work:
- Real production Postgres migration and deployment are environment gates; the monorepo includes migrations and schemas, but the production migration pipeline is not yet executed in a live environment. (Gate)
Where this breaks (failure modes and mitigations)
1) Out-of-order artifacts: a worker computes embeddings for a snapshot, but subsequent edits make them stale. - Mitigation: embed snapshot-id and op-range in artifact metadata; on retrieval, validate freshness and prefer artifacts whose snapshot-id matches the latest compacted snapshot or trigger async recompute.
2) Audit log growth and query cost: logging every low-level op and artifact can balloon storage and slow queries. - Mitigation: tiered retention (raw ops short-term, compactions and snapshots long-term), partitioned audit indices by tenant, precomputed materialized audit views for common queries.
3) Cross-tenant leakage: misconfigured tenancy enforcement could expose artifacts across tenants. - Mitigation: fail-closed middleware that enforces tenant-scoped DB schemas or row-level security, encryption of tenant secrets, and protected routes (what ARIL uses).
4) Model/operator confusion: automated agents (summarizers, rankers) produce edits concurrently with humans, causing frequent invalidations. - Mitigation: explicit agent identities and approval gates for automated edits; use merge policies (human-precedence or causal merge) and surface conflicting ranges in the UI for quick resolution.
5) Vector drift and retrieval inconsistency: embeddings evolve (model updates) causing mismatches between stored vectors and new model behaviors. - Mitigation: record embedding model version in artifact metadata and include scheduled re-embedding jobs when models update.
A practical checklist (5–8 checks)
- Check tenant isolation: enforce tenant-id at every layer (API, DB, vector store). - Check lineage: every artifact must reference a snapshot-id or op-range. - Check audit linkage: record request -> artifact -> snapshot -> user for each model response. - Check artifact freshness: retrieval must detect and handle stale artifacts. - Check retention policy: define and implement audit and artifact retention/compaction. - Check model versioning: include model/version metadata for embeddings and generative models. - Check gates for automated agents: require approval for any auto-edits that affect persistent documents.
Conclusion
Google Docs-style collaboration forces you to stop thinking of a single canonical record and start thinking in terms of append-only operations, versioned snapshots, and explicit lineage. That shift makes retrieval, embedding, and audit correct-by-construction: artifacts are always tied to the inputs that generated them, tenants remain isolated, and operators can reason about recomputation and retention. In ARIL I implemented a tenant-scoped append-and-artifact model with pgvector retrieval and audit trails; production migration and operational hardening remain deliberate gates.
References
[1] Model Context Protocol — https://modelcontextprotocol.io/introduction
[2] Anthropic — Model Context Protocol news — https://www.anthropic.com/news/model-context-protocol
[3] Operational transforms and CRDTs (survey) — https://arxiv.org/abs/2005.11401
[4] On consistency and collaboration (relevant theories) — https://arxiv.org/abs/2307.03172
[5] My portfolio repo (ARIL & related projects) — https://github.com/deepanshuvermaa/my-portfolio
[6] Additional portfolio projects and examples — https://github.com/deepanshuvermaa/museum-of-failure