AX 3.0 owns its tables as the database user bmssa (bmssa.SQLDICTIONARY), so
looking only in dbo never recognised a real AX 3.0 database. Detection now
uses sys.tables by name in any schema; later AX versions in dbo still match.
Tested against mock AX 3.0 (bmssa, int RECID), AX 4+ (dbo, bigint RECID) and
a plain database.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Seen on a customer's SQL Server 2005 SP4 (legacy ODBC):
- agent-jobs declared @since with an initial value (2008+): "Incorrect syntax
near CONVERT" and SQLI-JOB-001/002 never ran. Now DECLARE; SET.
- plan-analysis used query_hash (2008+) and failed every 30 minutes for
SQLI-PLAN-001/002/003. On 2005 a statement is now identified by
sql_handle + offsets, as top SQL does. It needs sys.dm_exec_text_query_plan,
so the new capability TextQueryPlan (2005 SP2, 9.0.3042) is required.
- COM-DB-001 used OBJECT_SCHEMA_NAME (2005 SP2+); now joins sys.objects and
sys.schemas.
Audit of all collector SQL and community rules without minimumVersion 10.0:
the rest is 2005 syntax or behind a version/capability check.
Sql2005CompatibilityTests (2005 cannot run in CI): every collector that can
run on 2005 is scanned for 2008+ syntax in its SQL (inline DECLARE, +=,
MERGE, CONCAT/IIF/FORMAT/TRY_*, OFFSET/FETCH, date/time types, multi-row
VALUES), version-branched files listed explicitly; the same for community
rules; and the 2005 variants of plan analysis and top SQL must not use
query_hash. Verified to fail on the old agent-jobs SQL.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
COM-AX-001..007, Database scope, metadata and DMVs only (the agent has no
data access). An AX database is recognised by OBJECT_ID() of SQLDICTIONARY,
DATAAREA and SYSCONFIG, AX 3.0 by its 32-bit RECID, so the queries compile
and return nothing in every other database. SQL Server 2005 syntax.
- AX 3.0 out of support; AX 3.0 on SQL Server newer than 2005
- MAXDOP not 1 (server value before 2016, database scoped from 2016)
- tables without a unique RECID index (failed or partial synchronisation)
- large heaps (ClusterIndex not set in the AOT), statistics off
Tested against a mock AX 3.0 database and a plain database on SQL Server
2025, with QUOTED_IDENTIFIER both on and off (no XML methods).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Rules can now be data: a JSON file with one read-only SELECT where every
row is a finding, with {column} templates, server or per-database scope,
minimum version, sensitive columns and references. Community rules live
in rules/community (reviewed via pull request), ship with every build
and with the signed rule pack; local rules are read from the agent's
data folder every five minutes. Queries are checked for anything that
could write, run with the least-privilege login, and a missing
permission makes the rule not measurable rather than failing. The
rule engine picks up catalog changes without a restart. Authors get
'rules validate' and 'rules test --instance'. Four example community
rules (sa active, orphaned database owners, default trace off,
untrusted foreign keys).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK