From 8a680a46ae4a037e40fc7b9e018f38aa77791a53 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 23 Aug 2026 04:33:46 +0000 Subject: [PATCH] refactor(plugin-sharing): put the shared logger contract on the precise signature Spell OptionalSharingLogger's members as a string message plus an optional Record of string keys to any values, and absorb sharing-rule-provenance.ts onto the shared type instead of a seventh local MinimalLogger. The shared shape shipped with the loose (msg: any, ...rest: any[]) spelling inherited from the two byte-identical declarations it replaced. That spelling documents nothing and catches nothing -- the same complaint this card levels at bare Function -- so the third module was unified onto the strict spelling it already declared, rather than the reverse. Caller cost is zero: every caller passes ctx.logger as any, or undefined. All 12 in-module call sites already pass exactly (string, object?). check:optional-error-sink membership is unchanged: 37 / 12 / 23 / 2, still 2 baselined. record-orphan-cleanup.ts's bare-Function members stay untouched -- tightening them moves that gate's population and remains open on #10692. Part of #10692 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01APWX2AwT3a4xDcjPCe8bk4 --- .../sharing-logger-precise-signature.md | 38 +++++++++++++++++++ .../plugin-sharing/src/logger-shapes.ts | 30 ++++++++++----- .../src/sharing-rule-provenance.ts | 9 ++--- 3 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 .changeset/sharing-logger-precise-signature.md diff --git a/.changeset/sharing-logger-precise-signature.md b/.changeset/sharing-logger-precise-signature.md new file mode 100644 index 0000000000..7298bbaa3c --- /dev/null +++ b/.changeset/sharing-logger-precise-signature.md @@ -0,0 +1,38 @@ +--- +"@objectstack/plugin-sharing": patch +--- + +Put `plugin-sharing`'s shared `{ info?, warn? }` logger contract on the precise +member signature and absorb the third module onto it (#10692). Internal types +only — no local `MinimalLogger` was ever exported, so there is no published +surface change and no runtime behaviour change. + +`OptionalSharingLogger` in `logger-shapes.ts` shipped with the loose spelling +`(msg: any, ...rest: any[]) => void`, inherited from the two byte-identical +declarations it replaced. Its members are now spelled +`(msg: string, meta?: Record) => void`, and +`sharing-rule-provenance.ts` — which already declared exactly that stricter +signature under its own local `MinimalLogger` — now imports the shared type +instead of declaring a seventh copy. + +That direction was chosen deliberately over unifying on the loose spelling. +`(msg: any, ...rest: any[])` documents nothing and catches nothing, which is the +same complaint this card levels at bare `Function`; folding the stricter module +onto it would have deleted real checking to buy uniformity. Taking the precise +spelling instead tightens the two modules that were already on the shared type, +and buys arity and type checking at all 12 in-module call sites — every one of +which already passes exactly a string message plus an optional metadata object. + +Caller cost is zero: every caller of the three affected binders passes +`ctx.logger as any` or `undefined`, so no caller constrains the signature. + +`check:optional-error-sink` (#9754) membership is unchanged and was verified +before and after: 37 sinks declare `error`, 12 required, 23 optional beside a +required `warn`, 2 permit silence, 2 baselined. The shared shape still declares +no `error` and must not grow one — that would enrol every module using it into +that gate's population, which is a contract decision for the #10556 family +rather than a side effect of de-duplication. + +`record-orphan-cleanup.ts`'s bare-`Function` members are deliberately untouched: +tightening them requires tightening two publicly exported option types first, +which moves that gate's population and remains open on #10692. diff --git a/packages/plugins/plugin-sharing/src/logger-shapes.ts b/packages/plugins/plugin-sharing/src/logger-shapes.ts index 2533d6dad5..beb0ac1333 100644 --- a/packages/plugins/plugin-sharing/src/logger-shapes.ts +++ b/packages/plugins/plugin-sharing/src/logger-shapes.ts @@ -19,6 +19,24 @@ * between this shape and a module that still declares its own, the diagnostic * names two different types instead of the same one twice. * + * ## Why the members are spelled precisely, and must stay that way + * + * The members take a `string` message and an optional `Record` of string keys + * to `any` values as structured metadata — NOT `(msg: any, ...rest: any[])`. + * + * This shape first shipped with that loose spelling, carried over from the two + * byte-identical declarations it replaced. `sharing-rule-provenance.ts` was + * left out of it precisely BECAUSE its own declaration was stricter, and + * folding it onto the loose spelling would have deleted real checking. That + * open question was ruled the other way (#10692): the shared contract takes the + * PRECISE spelling and the third module joins it. + * + * ⛔ Do not loosen these members back to `any` to make some new caller fit. + * `(msg: any, ...rest: any[])` documents nothing and catches nothing — the same + * complaint this package's card levels at bare `Function`. All call sites on + * this shape already pass exactly a message plus an optional metadata object; + * a caller that does not fit is the thing to look at, not this declaration. + * * ## ⛔ Why this shape declares no `error`, and must not grow one * * `check:optional-error-sink` (#9754) draws its population STRUCTURALLY: a sink @@ -47,15 +65,9 @@ * `SharingServiceOptions['logger']` and `ShareLinkServiceOptions['logger']` — * are themselves spelled with bare `Function`. Tightening it requires * tightening those producers first, which is a gate-population change, not a - * refactor. Recorded on #10692 rather than done quietly here. - * - `sharing-rule-provenance.ts` — `{ info?, warn? }` by OPTIONALITY but with a - * stricter member signature, `(msg: string, meta?: Record)`. - * Folding it onto the `(msg: any, ...rest: any[])` spelling below would DELETE - * real checking at its call sites; folding the others onto ITS spelling would - * tighten two modules. Either direction changes meaning, so neither is a - * de-duplication — see #10692 for the open contract question. + * refactor. It stays open on #10692 rather than being done quietly here. */ export interface OptionalSharingLogger { - info?: (msg: any, ...rest: any[]) => void; - warn?: (msg: any, ...rest: any[]) => void; + info?: (msg: string, meta?: Record) => void; + warn?: (msg: string, meta?: Record) => void; } diff --git a/packages/plugins/plugin-sharing/src/sharing-rule-provenance.ts b/packages/plugins/plugin-sharing/src/sharing-rule-provenance.ts index 2d72bfff7c..7e11a6d57b 100644 --- a/packages/plugins/plugin-sharing/src/sharing-rule-provenance.ts +++ b/packages/plugins/plugin-sharing/src/sharing-rule-provenance.ts @@ -26,22 +26,19 @@ * `input.id`) are not stamped — every rule-editing UI path updates by id. */ +import type { OptionalSharingLogger } from './logger-shapes.js'; + interface MinimalEngine { find(object: string, opts?: any): Promise; registerHook(event: string, handler: (ctx: any) => any, options?: Record): void; unregisterHooksByPackage(packageId: string): number; } -interface MinimalLogger { - info?: (msg: string, meta?: Record) => void; - warn?: (msg: string, meta?: Record) => void; -} - export const SHARING_RULE_PROVENANCE_PACKAGE = 'plugin-sharing:rule-provenance'; const SYSTEM_CTX = { isSystem: true, positions: [], permissions: [] } as const; -export function bindRuleProvenanceStamp(engine: MinimalEngine, logger?: MinimalLogger): void { +export function bindRuleProvenanceStamp(engine: MinimalEngine, logger?: OptionalSharingLogger): void { engine.registerHook( 'beforeUpdate', async (ctx: any) => {