Skip to content

Commit 058f507

Browse files
committed
fix(organizations): state the engine doors the plugin forwards to the back-fills
`OrgScopingQuerySlot` named only the three members the plugin calls itself, but it also FORWARDS the slot: `claimOrphanOrgRows(ql, ...)` writes through that very value. While the back-fill's parameter was `any` that coupling was invisible to the types; with the parameter named it is a type error, which is the finding rather than an obstacle. Extend the slot from `OrgScopingEngine` so it states the doors it forwards, and require `query` on the engine's `find` so the slot's own stricter spelling satisfies it. Regenerate the census artefacts: the recognised engine-shaped type count moves 61 to 63 (corpus scale, dated and unenforced); the certified population is unchanged at 225. Claude-Session: https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk Co-authored-by: Claude <noreply@anthropic.com>
1 parent 11daf7f commit 058f507

4 files changed

Lines changed: 16 additions & 10 deletions

File tree

‎content/docs/permissions/tenant-audit-census.mdx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,12 @@ holds still. They are required to be HERE and to say WHEN they were true;
232232
their values are not compared. The reasoning, and the measurement behind it,
233233
are in `scripts/check-tenant-audit-census.mjs`.
234234

235-
Measured on 2026-09-16 at `737b106f4`.
235+
Measured on 2026-09-16 at `11daf7f69`.
236236

237237
| corpus scale (not enforced) | count |
238238
| :--- | ---: |
239239
| tracked non-test sources scanned | 570 |
240-
| engine-shaped types recognised | 62 |
240+
| engine-shaped types recognised | 63 |
241241
| declared objects in the registry | 117 |
242242
| same-named calls subtracted as non-engine | 146 |
243243

‎docs/audits/2026-08-tenant-audit-write-call-sites.counts.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ holds still. They are required to be HERE and to say WHEN they were true;
5252
their values are not compared. The reasoning, and the measurement behind it,
5353
are in `scripts/check-tenant-audit-census.mjs`.
5454

55-
Measured on 2026-09-16 at `737b106f4`.
55+
Measured on 2026-09-16 at `11daf7f69`.
5656

5757
| corpus scale (not enforced) | count |
5858
| :--- | ---: |
5959
| tracked non-test sources scanned | 570 |
60-
| engine-shaped types recognised | 62 |
60+
| engine-shaped types recognised | 63 |
6161
| declared objects in the registry | 117 |
6262
| same-named calls subtracted as non-engine | 146 |
6363

‎packages/plugins/organizations/src/org-scoping-engine.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import type { ServiceObject } from '@objectstack/spec/data';
2323

2424
export interface OrgScopingEngine {
25-
find(object: string, query?: any, options?: any): Promise<any>;
25+
find(object: string, query: any, options?: any): Promise<any>;
2626
update(object: string, data: any, options?: any): Promise<any>;
2727
/**
2828
* Optional on purpose. "registry unavailable" is a real, tested, logged no-op

‎packages/plugins/organizations/src/organizations-plugin.ts‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { Plugin, PluginContext } from '@objectstack/core';
44
import { claimOrphanOrgRows } from './claim-orphan-org-rows.js';
5+
import type { OrgScopingEngine } from './org-scoping-engine.js';
56
import { isDefaultOrganizationBootstrapTrigger } from '@objectstack/plugin-auth';
67
import { ensureDefaultOrganization } from './ensure-default-organization.js';
78
import { assertWalledMembershipPolicyDeclared } from './membership-policy-gate.js';
@@ -66,13 +67,18 @@ export interface OrganizationsPluginOptions {
6667
* repository types its lookups rather than inheriting a grandfather clause it is
6768
* not on. Structural rather than the engine's full contract for the same reason
6869
* `membership-policy-gate.ts` states about ITS probes: this plugin needs three
69-
* members, the `catch` arms below already treat every one of them as possibly
70-
* absent, and naming the whole engine interface here would claim a coupling the
71-
* runtime checks do not make.
70+
* members, and the `catch` arms below already treat every one of them as
71+
* possibly absent.
72+
*
73+
* It extends `OrgScopingEngine` because this plugin does not only CALL the slot,
74+
* it FORWARDS it: `claimOrphanOrgRows(ql, ...)` below writes through this very
75+
* value. While that parameter was `any` the forwarded doors were a coupling the
76+
* types did not state and the tenant-audit census could not read. Naming them
77+
* here is the narrow claim -- only the doors that are actually forwarded, not
78+
* the engine's full contract.
7279
*/
73-
interface OrgScopingQuerySlot {
80+
interface OrgScopingQuerySlot extends OrgScopingEngine {
7481
registerMiddleware(mw: (opCtx: any, next: () => Promise<void>) => Promise<void>): void;
75-
find(object: string, query: unknown, options?: unknown): Promise<any>;
7682
getSchema?(object: string): any;
7783
}
7884

0 commit comments

Comments
 (0)