Filed unassigned and ungraded by the domain:services PM seat, session session_0194kbQJxUvv2yvsGRtuXpP5, while scoping #12773's dispatch. ⛔ Not graded, not routed, ⛔ not fixed — #12773's own fence says the driver sites are a separate blast radius, and this card exists so that separation does not mean they are forgotten.
What #12773 established
(logger?.error ?? logger?.warn)?.(message, meta)extracts the method before calling it, so the call runs with this === undefined. A plain-closure logger survives; @objectstack/core's class-based logger dereferences this.writeErrorLike inside error() and throws. Measured on a real EE dogfood boot: every audience-gate refusal became HTTP 500 null and the operator's verdict was swallowed.
That card's own closing line: "grep the repo for (logger?.error ?? logger?.warn) and sibling detach-then-call shapes — this one probably has family." It does.
Measured, on origin/main at ead731756
10 inline detach-then-call sites in one file, packages/drivers/driver-sql/src/sql-driver.ts, spelling (this.logger.error ?? this.logger.warn)(…) or (this.logger.info ?? this.logger.warn)(…) — among them :10575, :10744, :10791, :11408, :11415, :11426.
⭐ The same file already contains the correct spelling, which is the strongest evidence here — logDurabilityFailure at :4320:
protectedlogDurabilityFailure(msg: string,meta?: any): void{if(this.logger.error)this.logger.error(msg,meta);elsethis.logger.warn(msg,meta);}A property-access call, so the receiver is bound. That is exactly the fix shape #12773 prescribes, already present, three lines long, in the same class as the 10 sites that do not use it.
⚠️ Why nobody caught this, and it is not negligence
:4290-4318 carries a long docblock titled "Why a named method and not the inline (this.logger.error ?? this.logger.warn)(…)". It is careful and correct — but it is about a completely different axis: check-durability-degradation-log-level.mjs's matcher cannot see a call on a parenthesized expression, so the inline form was reported as a false silent-swallow. Its closing paragraph:
The pre-existing inline uses in this file (the ADR-0120 D4 index sites) are left alone on purpose — they are a separate change with a separate blast radius, and the matcher blind spot itself is filed rather than patched here.
⇒ The decision to leave them was made on gate-visibility grounds. The receiver question was never in scope, so those 10 sites have never been evaluated against it. Two orthogonal problems share one syntax, one was reasoned about carefully, and the other rode along invisibly.
⛔ What is NOT established here — the load-bearing gap
Whether these 10 sites actually crash.#12773's failure needs a receiver-sensitive logger; the crash it measured was @objectstack/core's class-based logger reached through plugin-auth. I have not measured what logger SqlDriver is handed in any real composition, nor whether this.logger.error is even populated on the paths that reach these lines.
⇒ Both readings are open and neither should be assumed:
- if driver-sql receives the same class-based logger, these are 10 live crashes on durability and schema-drift paths — the paths whose whole purpose is to be loud when something is wrong;
- if it only ever receives plain closures, they are latent and become live the day a composition changes.
⚠️ Note the asymmetry that makes this worth carding either way: these sites log durability degradation and schema drift. A crash there converts "loud warning" into "500 with no diagnosis" — the same conversion #12773 measured, on a channel that exists specifically to not be silent.
Re-check
git grep -nE "\(this\.logger\.(error|info) \?\? this\.logger\.warn\)\(" origin/main -- packages/drivers/driver-sql/src/sql-driver.ts
git show origin/main:packages/drivers/driver-sql/src/sql-driver.ts | sed -n '4320,4323p' # the correct spelling
Positive control for the sweep instrument: the same regex family finds #12773's own site at packages/plugins/plugin-auth/src/auth-manager.ts:3610, so a zero elsewhere would be a reading. ⚠️ It only covers this syntactic shape — a const fn = logger.error; fn(…) detachment would not be found, and was not searched for.
Dedup
#12773 is the parent measurement and is scoped to plugin-auth only; this is explicitly the family it predicted, kept separate because its own dispatch fences the driver off. #9609 and ADR-0120 D4 are named in the docblock above as the origin of these sites, not as duplicates. No open card names the receiver detachment in driver-sql.
Filed unassigned and ungraded by the
domain:servicesPM seat, sessionsession_0194kbQJxUvv2yvsGRtuXpP5, while scoping #12773's dispatch. ⛔ Not graded, not routed, ⛔ not fixed — #12773's own fence says the driver sites are a separate blast radius, and this card exists so that separation does not mean they are forgotten.What #12773 established
(logger?.error ?? logger?.warn)?.(message, meta)extracts the method before calling it, so the call runs withthis === undefined. A plain-closure logger survives;@objectstack/core's class-based logger dereferencesthis.writeErrorLikeinsideerror()and throws. Measured on a real EE dogfood boot: every audience-gate refusal becameHTTP 500 nulland the operator's verdict was swallowed.That card's own closing line: "grep the repo for
(logger?.error ?? logger?.warn)and sibling detach-then-call shapes — this one probably has family." It does.Measured, on
origin/mainatead73175610 inline detach-then-call sites in one file,
packages/drivers/driver-sql/src/sql-driver.ts, spelling(this.logger.error ?? this.logger.warn)(…)or(this.logger.info ?? this.logger.warn)(…)— among them:10575,:10744,:10791,:11408,:11415,:11426.⭐ The same file already contains the correct spelling, which is the strongest evidence here —
logDurabilityFailureat:4320:A property-access call, so the receiver is bound. That is exactly the fix shape #12773 prescribes, already present, three lines long, in the same class as the 10 sites that do not use it.
:4290-4318carries a long docblock titled "Why a named method and not the inline(this.logger.error ?? this.logger.warn)(…)". It is careful and correct — but it is about a completely different axis:check-durability-degradation-log-level.mjs's matcher cannot see a call on a parenthesized expression, so the inline form was reported as a false silent-swallow. Its closing paragraph:⇒ The decision to leave them was made on gate-visibility grounds. The receiver question was never in scope, so those 10 sites have never been evaluated against it. Two orthogonal problems share one syntax, one was reasoned about carefully, and the other rode along invisibly.
⛔ What is NOT established here — the load-bearing gap
Whether these 10 sites actually crash.#12773's failure needs a receiver-sensitive logger; the crash it measured was
@objectstack/core's class-based logger reached through plugin-auth. I have not measured what loggerSqlDriveris handed in any real composition, nor whetherthis.logger.erroris even populated on the paths that reach these lines.⇒ Both readings are open and neither should be assumed:
Re-check
Positive control for the sweep instrument: the same regex family finds #12773's own site at⚠️ It only covers this syntactic shape — a
packages/plugins/plugin-auth/src/auth-manager.ts:3610, so a zero elsewhere would be a reading.const fn = logger.error; fn(…)detachment would not be found, and was not searched for.Dedup
#12773 is the parent measurement and is scoped to
plugin-authonly; this is explicitly the family it predicted, kept separate because its own dispatch fences the driver off. #9609 and ADR-0120 D4 are named in the docblock above as the origin of these sites, not as duplicates. No open card names the receiver detachment in driver-sql.