What happens
On a freshly seeded database with plugin-audit loaded, every load of Setup →
System Overview logs a burst of:
WARN [Analytics] dataset "sys_audit_log_metrics" backing object "sys_audit_log" is unavailable
(SELECT COUNT(*) AS "event_count" FROM "sys_audit_log" WHERE (action = 'login' AND …)
- no such table: sys_audit_log); returning an empty result instead of failing the widget
12 of these per dashboard load in my session (login / permission_change /
config_change counters, plus the GROUP BY action and GROUP BY user_id charts).
The tables are genuinely absent:
sys_audit_log MISSING
sys_activity MISSING
sys_comment EXISTS
(88 tables in the DB; Audit is in the loaded-plugin list.)
Why this is worse than log noise
The analytics layer degrades gracefully — empty result instead of a failed widget
— so the client sees nothing wrong. My browser sweep recorded
/_console/apps/com.objectstack.setup/dashboard/system_overview as completely
clean: no failed requests, no console errors, no error text.
So the dashboard renders 0 logins, 0 permission changes, 0 config changes and
looks authoritative doing it. That is the "Total Spend: 0 on a populated table"
failure mode rest-server.ts calls out by name in the analytics resolver comment
— except here it is structural rather than a wrong-database mistake, and it is
the security dashboard reading zero.
The guard that should prevent this exists and isn't taking effect
plugin-audit/src/audit-plugin.ts has provisionSystemTables() (~L168-198),
added for precisely this, with a docblock that describes today's symptom:
sys_audit_log / sys_activity / sys_comment are otherwise lazy-created on first
WRITE … A freshly provisioned env that READS one first … hits SQLite "no such
table" … The UI degrades to an empty feed, but the log is noisy and can mask
real errors.
It is wired at kernel:ready (~L80, L97) and loops [SysAuditLog, SysActivity, SysComment] calling engine.syncObjectSchema(obj.name).
Two of its three tables are missing anyway, and no AuditPlugin: could not provision … warning appears in the log — so the per-object catch never fired.
syncObjectSchema does exist on the ObjectQL engine (objectql/src/engine.ts:5628),
so the early if (typeof sync !== 'function') return; bail is the most likely
path, but I did not confirm which of the two silent exits is taken — that belongs
to the fix. sys_comment existing while the other two don't suggests it gets
created by some other path rather than by this loop succeeding.
Worth noting the early return is silent: if provisioning is skipped wholesale,
nothing says so.
Suggested direction
- Find why the
kernel:ready provisioning doesn't reach syncObjectSchema for
these objects, and make both bail-outs audible (a logger.warn on the
typeof sync !== 'function' return) so a future skip isn't silent again.
- Consider whether a shipped system dataset whose backing table may not exist
should surface as "not available" in the widget rather than a confident 0 —
an empty audit chart and a zero-events audit chart mean very different things
to whoever is reading a security dashboard.
Repro
os dev --ui --seed-admin -d file:/tmp/fresh.db in examples/app-showcase
- Sign in, open
/_console/apps/com.objectstack.setup/dashboard/system_overview
- Server log shows the
no such table: sys_audit_log warnings; the dashboard
shows zeros with no error
sqlite3 /tmp/fresh.db ".tables" | grep -E 'sys_audit_log|sys_activity' → nothing
Observed on main @ 0e96e46, SqlDriver(better-sqlite3), single-tenant.
Found while browser-sweeping showcase + Studio for #4879.
What happens
On a freshly seeded database with
plugin-auditloaded, every load of Setup →System Overview logs a burst of:
12 of these per dashboard load in my session (login / permission_change /
config_change counters, plus the
GROUP BY actionandGROUP BY user_idcharts).The tables are genuinely absent:
(88 tables in the DB;
Auditis in the loaded-plugin list.)Why this is worse than log noise
The analytics layer degrades gracefully — empty result instead of a failed widget
— so the client sees nothing wrong. My browser sweep recorded
/_console/apps/com.objectstack.setup/dashboard/system_overviewas completelyclean: no failed requests, no console errors, no error text.
So the dashboard renders 0 logins, 0 permission changes, 0 config changes and
looks authoritative doing it. That is the "Total Spend: 0 on a populated table"
failure mode
rest-server.tscalls out by name in the analytics resolver comment— except here it is structural rather than a wrong-database mistake, and it is
the security dashboard reading zero.
The guard that should prevent this exists and isn't taking effect
plugin-audit/src/audit-plugin.tshasprovisionSystemTables()(~L168-198),added for precisely this, with a docblock that describes today's symptom:
It is wired at
kernel:ready(~L80, L97) and loops[SysAuditLog, SysActivity, SysComment]callingengine.syncObjectSchema(obj.name).Two of its three tables are missing anyway, and no
AuditPlugin: could not provision …warning appears in the log — so the per-objectcatchnever fired.syncObjectSchemadoes exist on the ObjectQL engine (objectql/src/engine.ts:5628),so the early
if (typeof sync !== 'function') return;bail is the most likelypath, but I did not confirm which of the two silent exits is taken — that belongs
to the fix.
sys_commentexisting while the other two don't suggests it getscreated by some other path rather than by this loop succeeding.
Worth noting the early return is silent: if provisioning is skipped wholesale,
nothing says so.
Suggested direction
kernel:readyprovisioning doesn't reachsyncObjectSchemaforthese objects, and make both bail-outs audible (a
logger.warnon thetypeof sync !== 'function'return) so a future skip isn't silent again.should surface as "not available" in the widget rather than a confident
0—an empty audit chart and a zero-events audit chart mean very different things
to whoever is reading a security dashboard.
Repro
os dev --ui --seed-admin -d file:/tmp/fresh.dbinexamples/app-showcase/_console/apps/com.objectstack.setup/dashboard/system_overviewno such table: sys_audit_logwarnings; the dashboardshows zeros with no error
sqlite3 /tmp/fresh.db ".tables" | grep -E 'sys_audit_log|sys_activity'→ nothingObserved on
main@ 0e96e46,SqlDriver(better-sqlite3), single-tenant.Found while browser-sweeping showcase + Studio for #4879.