Skip to content

History / Multi Tenancy Developer Guide

Revisions

  • External issue trackers + Jira connector developer guides (#945-947) Two pages, split on the line that matters: the engine page is the contract every tracker must satisfy, the Jira page is the worked example. That split is the point — whoever writes the GitHub or Azure DevOps connector needs to know which decisions were forced by the contract and which were just how Jira happens to work, and both pages say so explicitly. Also cross-referenced from Multi-Tenancy-Developer-Guide: tracker connections added to the connection column of the three-meanings-of-NULL table, and the outbound twin of the membrane rule recorded next to the inbound one. Both pages carry a "keeping this page honest" section listing what must be updated in the same commit as a code change.

    @edmozley edmozley committed Aug 1, 2026
  • Database Verification: document the column drift guard (#884) Rewrites the section that said columns were unguarded — accurate when written yesterday, made false by building the guard. Now covers why columns are the harder case (both files hand-maintained, so drift runs in two directions and each direction breaks a DIFFERENT install), the #879 bug that prompted it, how the check works, and where $schema now lives. Emphasises that the comparison is deliberately forgiving — base type, length and nullability only, ignoring DEFAULT/case/whitespace — because a guard that cries wolf gets ignored. The noise-resistance test is called out as load-bearing rather than incidental. Records what is STILL unguarded: foreign keys, built from explicit FK groups with nothing comparing them to freeitsm.sql. Flagged as the next self-check. Also notes you can run the whole of Database Verification headlessly against a scratch database ($_SESSION['setup_access'], DB_NAME override) and that php -l proves nothing here, since a fatal in this endpoint is served as HTTP 200. Multi-Tenancy dev guide + CMDB case study: file maps updated for $schema's move to includes/db_verify_schema.php, and the "columns have no guard yet" line in the case study corrected — written an hour before the guard existed.

    @edmozley edmozley committed Jul 18, 2026
  • Two new multi-tenancy dev pages, and make file involvement explicit Ed's feedback: the CMDB/Network Mapper work was substantial enough to deserve proper documentation, and dev guides should make it much clearer WHICH php/js files are involved. Fair - the guide named files in prose but had no scannable map, so it couldn't actually be worked from. NEW Multi-Tenancy-CMDB-Case-Study: the worked example for a module whose rows LINK to each other. Why a graph differs from a list (three link mechanisms, all separate holes); the no-shared-CIs decision and what it forced; the core lesson that a same-company invariant must bind ALL-ACCESS actors because a scope check cannot help someone who legitimately reaches both sides; a full colour-keyed file map; the Network Mapper boundary and why get_diagram.php is deliberately unfiltered; what stayed shared and why; the move-between-companies gap. NEW Multi-Tenancy-Test-Harness: the reusable verification kit, roughly 20 lines from module-agnostic. Leads with ALWAYS INCLUDE A POSITIVE CONTROL, because breaking that rule produced a green suite that proved nothing. Also the three tricks that make CLI testing work (DB_NAME defined first, session established before the endpoint's own session_start, php:// wrapper override for the empty php://input), the static tenant-count cache forcing separate processes, the fixture shape, and what to assert. Developer guide gains section 1a "The files you will touch" - a colour-keyed table of the ~10 places every module needs, each with what you do and whether it is skippable. Plus the point that a correctly-scoped module needs NO JavaScript changes at all (CMDB changed zero lines), and if you are editing JS to hide rows you are filtering in the wrong layer. The Reference section is now a "copy from these" table pointing at shipped examples per shape. Also fixed a pre-existing broken link (db-verify) and pointed two #882 references away from the user-facing Pitfalls page.

    @edmozley edmozley committed Jul 18, 2026
  • CMDB is now multi-company; record the invariant and two testing lessons Multi-Tenancy-Progress: CMDB marked done, with the two deferrals written down - moving a CI between companies (and the shape it would take), and the deliberate Network Mapper boundary where diagrams stay unfiltered. CMDB page: a Multi-company section - one CI, one company, no shared CIs, what that implies for parent/relationships/object_ref, what stays install-wide (classes, properties, relationship types, icons) and why, and the move-to- company gap. Developer guide: - new special case for a graph of inter-linking rows. The headline is that a same-company invariant must bind an ALL-ACCESS actor too - a scope check can't help when the actor legitimately reaches both sides - and that a link leaks even when the far row is unreadable. - ALWAYS INCLUDE A POSITIVE CONTROL. "Was it blocked?" assertions pass just as happily when the request was broken as when it was refused. php://input is empty under the CLI SAPI, so a whole write suite failed validation before reaching any tenancy check and every isolation assertion went green - nine checks proving nothing. The tell was the positive controls failing too. - drive the real endpoint rather than a copy of its SQL, and why: parameter ORDER (SELECT-subquery and JOIN...ON fragments bind before WHERE) is the bug class a reimplementation can never catch.

    @edmozley edmozley committed Jul 18, 2026
  • Document the connection shape, the NULL-semantics trap and fresh-install drift Multi-Tenancy-Developer-Guide: - section 1 now documents THREE table shapes, not two. Connections (mailboxes, messaging channels, web chat widgets) are a distinct shape where NULL means shared intake, not Default-owned, and the list is deliberately install-wide. Flags that using activeTenantFilter here would hide shared-intake channels and break per-sender routing. - notes the credentials exception to "caps guard writes not reads". - adds analystCanAccessChannel / analystCanAssignTenant to the toolbox. - verify section: N=1 and N=2 MUST run in separate processes because tenantCount() memoises in a static; plus the scratch-database fixture recipe, which doubles as a fresh-install test. - checklist: name what NULL means; assert the two schema files agree; validate a client-supplied company against the actor's access rather than existence. Database-Verification-Developer-Guide: new section on the gap the index drift guard doesn't cover — columns. Uses the asset_locations.tenant_id bug as the worked example and explains why it survived review (development only ever exercises the upgrade path, so fresh-install drift is invisible until someone downloads it). Suggests extending the self-check to columns. Multi-Tenancy-Progress: Knowledge and messaging/web chat marked done, with the open tenant_channel_senders UI gap and the webchat routing asymmetry recorded.

    @edmozley edmozley committed Jul 18, 2026
  • Multi-Tenancy: locations are purely per-company (correct Settings/Progress/Dev Guide)

    @edmozley edmozley committed Jul 15, 2026
  • Multi-Tenancy: add Developer Guide (make a module company-aware); assets in Progress + Settings

    @edmozley edmozley committed Jul 15, 2026