Database Verification guide: the index list carries a TYPE, not a boolean
Pairs with freeitsm #991, which taught the index backfill about FULLTEXT so the
forthcoming search corpus table can reach grown installs and not just fresh ones.
The guide said the backfill "only covers KEY / UNIQUE KEY / INDEX", which is now
wrong, and it did not describe the row format at all -- so anyone reading the
generated list would reasonably have assumed the old boolean.
Documents the format change and, more importantly, the trap: the old idiom was
$isUnique ? 'UNIQUE KEY' : 'KEY' and the string 'key' is truthy, so code reading
the element directly would now build a UNIQUE index over duplicate-laden
columns. Callers use dbVerifyIndexTypeOf().
Also records why a wrong index kind is worse than a missing one -- a FULLTEXT
index downgraded to an ordinary KEY keeps the count correct while every
full-text search on an upgraded install silently returns nothing -- plus the two
full-text specifics worth knowing: InnoDB only indexes CHAR/VARCHAR/TEXT, and
the first full-text index on a table rebuilds it (harmless here, since db_verify
indexes a table it has just created empty).
Absorb the README's deep-dive content ahead of the README slim-down
The project README is being reduced to a landing page; every fact it
held that the wiki lacked is merged here first (615 lines across 33
pages): the full email-threading & reply-flow design onto Tickets,
directory layout + module-page pattern + file-locations reference onto
Architecture, per-endpoint tables onto API Reference, MFA login flow +
LDAP subsection + injection/audit notes onto Security, the icon library
and editor internals onto Network Mapper, Branding + landing-page and
help/search internals + debug-tool depth onto System, planned objects
onto CMDB, custody/locations/warranty onto Assets, and more.
Also corrects stale claims found during the audit: the Knowledge
audience table still said customer-visible articles had no reader
(the portal Knowledge section shipped), a pre-#903 Portal-Privacy
ambiguity row, the Workflows trigger-wiring section (catalogue spans
every module now), the superseded System module-access bullet, the
Multi-Tenancy users page marked "Planned" for a shipped feature,
and the locale count (21 languages incl. Ukrainian, not 20).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
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.
DB Verify guide: document the index-list drift guard
Add the "you can't forget to regenerate" section: dbVerifyIndexListSelfCheck()
re-parses freeitsm.sql on every verify run and fails loudly when the
generated list has drifted, with the same parser generating and auditing
the list. This is the real answer to "how do we avoid this drift again" —
enforcement, not discipline.
Add Database Verification developer guide
How the DB Verify page is built and maintained: the mutating Verify flow
vs the read-only Describe flow, how tables are filed under modules
(derived from name, how to handle multi-module tables), the index
backfill and the duplicate-blocks-a-unique behaviour, and why we don't
check against an exported "golden" database. Complements the existing
Database Integrity page (FKs, delete rules, orphans).