Skip to content

fix(dbal): resolve object-source Source refs as system lookup — tenant filter emptied cross-org registers (fixes #2089)#2090

Open
rubenvdlinde wants to merge 1 commit into
developmentfrom
fix/dbal-source-system-resolution
Open

fix(dbal): resolve object-source Source refs as system lookup — tenant filter emptied cross-org registers (fixes #2089)#2090
rubenvdlinde wants to merge 1 commit into
developmentfrom
fix/dbal-source-system-resolution

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Summary

Fixes #2089 (follow-up to #2084 / PR #2088). DbalObjectSourceProvider::resolveSource() loaded the backing Source via organisation-filtered SourceMapper::find()/findAll(). A Source is shared infrastructure config (an external DB connection), not tenant-owned data — the schema's own read RBAC is already enforced by ObjectService::paginateObjectSource() (checkPermission()) before the provider ever runs. Filtering the Source row by the caller's active organisation added no additional isolation while breaking every dbal-backed schema whose Source lives in a different organisation, most visibly under saasMode: true where admin override is unconditionally disabled — resolveSource() returned null, and every downstream find/findAll/count/aggregate silently returned empty (logged only as a warning).

Design

  • Added SourceMapper::findForSystem(string $sourceId): ?Source — an id/uuid lookup with no RBAC verification and no organisation filter, mirroring the mapper's existing findBySyncEnabled() system-actor pattern (same file, same rationale: system-initiated lookup, no tenant scoping). Docblock states the security rationale explicitly and the constraint that it must never be exposed to a caller that hasn't already authorized at the schema/object level.
  • DbalObjectSourceProvider::resolveSource() now calls findForSystem() instead of find()/findAll().
  • Ordinary SourceMapper callers (Sources admin CRUD/listing) are untouched — default organisation filtering is not weakened for any other caller.
  • Added OpenSpec change dbal-source-resolution-system-context (proposal + tasks + spec delta) with @spec tags on both changed methods.

Tests

  • New regression test testResolveSourceUsesSystemLookupAcrossOrganisations in DbalObjectSourceProviderTest: a Source in a different organisation still resolves and serves objects, and asserts find()/findAll() are never called (only findForSystem()) — proving the fix path.
  • PaginateObjectSourceTest::testDeniedReadRejectsBeforeProviderIsConsulted (untouched) continues to cover REQ-DSRSC-002 — schema-level RBAC still gates before the provider runs.
  • php -l, composer phpcs (clean), phpstan (clean — also fixed a pre-existing phpstan-only warning on an unrelated method encountered while scoping the file) on both changed lib files.
  • Full DbalObjectSourceProviderTest (20/20) and PaginateObjectSourceTest (8/8) green in the nextcloud:34.0.0-apache container.

Test plan

…t filter emptied cross-org registers (fixes #2089)

DbalObjectSourceProvider::resolveSource() loaded the backing Source via
SourceMapper::find()/findAll(), both organisation-filtered. A Source is
shared infrastructure config, not tenant-owned data — the schema's own
read RBAC is already enforced by ObjectService::paginateObjectSource()
before the provider ever runs, so filtering the Source row by the
caller's active organisation added no isolation while breaking any
dbal-backed schema whose Source lives in a different organisation,
most visibly under saasMode:true where admin override is unconditionally
disabled.

Adds SourceMapper::findForSystem() — an id/uuid lookup with no RBAC
verification and no organisation filter, mirroring the existing
findBySyncEnabled() system-actor pattern — and wires resolveSource() to
use it. Ordinary SourceMapper callers (admin CRUD/listing) are untouched.

Adds openspec change dbal-source-resolution-system-context with the
requirement + rationale, and a regression test asserting resolution
goes through the unfiltered system lookup (never find()/findAll()) and
still returns objects for a cross-organisation Source.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openregister @ 54ff8d9

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 174/174
npm ✅ 555/555
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-07-24 21:19 UTC

Download the full PDF report from the workflow artifacts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant