You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a tenant-scoped user (any tenant other than tenant 1) connects via pgwire and runs INSERT or SELECT on a collection owned by their tenant, the query fails with unknown table — even though SHOW COLLECTIONS lists the collection and CREATE COLLECTION just succeeded on the same connection.
Client: postgres.js via Bun, prepare: false (still hits QueryParser::parse_sql via the extended Parse/Bind/Execute flow)
Reproduction
-- as superuser (tenant 1)
CREATE TENANT acme;
-- ok — assigns tenant_id = 2CREATEUSERsvc WITH PASSWORD 'x' ROLE readwrite TENANT 2;
-- ok
Reconnect as svc on pgwire :6432:
CREATE COLLECTION t2_mem TYPE DOCUMENT STRICT (
id STRING PRIMARY KEY,
content STRING NOT NULL
);
-- OK
SHOW COLLECTIONS;
-- lists t2_mem with owner=svcINSERT INTO t2_mem (id, content) VALUES ('a', 'alpha');
-- ERROR: unknown table: t2_memSELECT*FROM t2_mem;
-- ERROR: unknown table: t2_mem
Same behaviour with tenant_admin role (e.g. the auto-created acme_admin).
Expected
A tenant 2 user should be able to INSERT/SELECT on a collection that CREATE COLLECTION just persisted without error and that SHOW COLLECTIONS lists as theirs.
Actual
unknown table on every INSERT/SELECT against a non-tenant-1 collection. Works normally as the default superuser (tenant 1).
Storage-level data isolation itself holds — no actual row leak across tenants. But the parse-vs-execute tenant mismatch makes every tenant > 1 unable to see its own collections through the planner.
Source pointer
nodedb/src/control/server/pgwire/handler/prepared/parser.rs:37-42 — try_infer_types in NodeDbQueryParser.
For cross-reference, the DDL path at nodedb/src/control/server/pgwire/ddl/collection/create/handler.rs:56 reads identity.tenant_id correctly, which is why CREATE COLLECTION and SHOW COLLECTIONS work but subsequent planning does not.
Summary
When a tenant-scoped user (any tenant other than tenant 1) connects via pgwire and runs
INSERTorSELECTon a collection owned by their tenant, the query fails withunknown table— even thoughSHOW COLLECTIONSlists the collection andCREATE COLLECTIONjust succeeded on the same connection.Environment
nodedb-0.0.2-linux-arm64release binary127.0.0.1:6432b024c560(post-ci(release): add Discord notification job for new releases #28 merge)postgres.jsvia Bun,prepare: false(still hitsQueryParser::parse_sqlvia the extendedParse/Bind/Executeflow)Reproduction
Reconnect as
svcon pgwire:6432:CREATE COLLECTION t2_mem TYPE DOCUMENT STRICT ( id STRING PRIMARY KEY, content STRING NOT NULL ); -- OK SHOW COLLECTIONS; -- lists t2_mem with owner=svc INSERT INTO t2_mem (id, content) VALUES ('a', 'alpha'); -- ERROR: unknown table: t2_mem SELECT * FROM t2_mem; -- ERROR: unknown table: t2_memSame behaviour with
tenant_adminrole (e.g. the auto-createdacme_admin).Expected
A tenant 2 user should be able to
INSERT/SELECTon a collection thatCREATE COLLECTIONjust persisted without error and thatSHOW COLLECTIONSlists as theirs.Actual
unknown tableon everyINSERT/SELECTagainst a non-tenant-1 collection. Works normally as the default superuser (tenant 1).Asymmetric cross-tenant shape (same behaviour, opposite side)
SELECT * FROM <tenant-1-collection>[](empty) silentlySELECT * FROM <tenant-2-collection>unknown tableerrorSELECT * FROM <own tenant-2 collection>unknown tableerrorStorage-level data isolation itself holds — no actual row leak across tenants. But the parse-vs-execute tenant mismatch makes every tenant > 1 unable to see its own collections through the planner.
Source pointer
nodedb/src/control/server/pgwire/handler/prepared/parser.rs:37-42—try_infer_typesinNodeDbQueryParser.For cross-reference, the DDL path at
nodedb/src/control/server/pgwire/ddl/collection/create/handler.rs:56readsidentity.tenant_idcorrectly, which is whyCREATE COLLECTIONandSHOW COLLECTIONSwork but subsequent planning does not.