Connect by JBRH Open Connect

One file service for two audiences

Files attach by button, drop or paste and go through one service both audiences share — file_workspace over media_assets, a table that was already workspace-scoped and under row-level security, so nothing new had to be governed. Both routers call the same body; each adds only its route. Reading and writing are separate, and a change is a new version with provenance and an audit entry.

Status
Available What this means
Audience
both, developer
Last verified
Product version
6.3.2

One body, two doors#

Connect is one codebase with two audiences: the operator's own workspace and a customer's. The tempting shape is a full implementation for one and a trimmed copy for the other. It drifts, and it drifts in the direction nobody is watching — the audience whose screen the writer does not have open.

The shape that holds is that new behaviour lives in a module both routers call, and router and owner_router add only the route. file_workspace is one instance of it; mailbox_console and the voice configuration endpoints are others. What that rules out is a reduced view for the other audience unless the omission is deliberate and written down.

No new table, on purpose#

Files are stored as media_assets, which already carried workspace_id, already appeared in SCOPED_TABLES, and already had a row-level security policy. That is a security decision more than a tidiness one.

A new scoped table has to have row-level security applied in the same release, because create_all makes the table at boot while the policy comes from tools/pg_harden.py, an operational script. Three prospect_* tables once shipped with row-level security off for exactly that reason, and were enabled and forced afterwards with the policy every other scoped table carries. A table holding workspace_id that is missing from SCOPED_TABLES is scoped by nothing at all.

Reusing a governed table means a file inherits the same three enforcement points as everything else — the customer_safe allowlist, the SQLAlchemy workspace kernel, and the database's own policy — without anyone having to remember to add them.

What the service does at the door#

ConcernBehaviour
ImagesPNG, JPEG and WebP, read with the standard library
PDFThe text layer where there is one; where there is not, the document is given to the model to read
Office formatsDOCX, XLSX and PPTX
Text and dataCSV and TSV, TXT, MD, JSON
Structural attacksDOCTYPE and ENTITY declarations and zip bombs are refused before anything is parsed
ChangesConnect creates and modifies files as new versions, with provenance and an audit entry — never an edit in place

Reading and writing being separate tools matters more than it sounds. A document is untrusted text: an instruction inside it reaches the model along with everything else, and the containment is that the model can summarise or propose, while a change lands as a new version somebody can see and undo.

What this shape does not give you#

  • No optical character recognition. A scanned PDF with no text layer is handed to the model rather than transcribed by a dedicated engine, and the result should be treated accordingly.
  • No passage index. A long document is read; it is not chunked into a searchable store, which is the same limit the grounding design has.
  • One service is a single point of change. A defect at the door affects both audiences at once. That is the deliberate trade against drift, and it is why the parity suite reads the running route table rather than trusting an assertion.
  • Size and throughput ceilings are not published here: UNKNOWN. What is documented is the refusal behaviour, which is the part that matters for safety.

Questions#

Where does an uploaded file actually live?

In media_assets, stamped with the workspace it belongs to and covered by the same row-level security policy as the rest of that workspace's records. No separate file table was introduced, so there is no second place for the isolation rules to be forgotten.

Does Connect overwrite a file when it changes one?

No. A modification is a new version with provenance and an audit entry, so the prior content is still there and the change is attributable. That is also what makes it safe for a model to act on a document it was asked about.

Do the operator and a customer get different file behaviour?

The same behaviour over the same implementation. The audiences differ commercially — a customer's use is bounded by their plan's allowances — not in which code runs.