Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .changeset/sharing-logger-precise-signature.md
Original file line numberDiff line numberDiff line change
@@ -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<string, any>) => 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.
30 changes: 21 additions & 9 deletions packages/plugins/plugin-sharing/src/logger-shapes.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand DownExpand Up@@ -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<string, any>)`.
* 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<string, any>) => void;
warn?: (msg: string, meta?: Record<string, any>) => void;
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -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<any[]>;
registerHook(event: string, handler: (ctx: any) => any, options?: Record<string, any>): void;
unregisterHooksByPackage(packageId: string): number;
}

interface MinimalLogger {
info?: (msg: string, meta?: Record<string, any>) => void;
warn?: (msg: string, meta?: Record<string, any>) => 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) => {
Expand Down
Loading