Skip to content

finding(objectql): registerObject's cross-package ownership refusal throws a bare Error, so no rejection test on that path can assert an ADR-0112 envelope #14367

Description

@hotlong

Found while implementing ADR-0130 D1+D3 (#14163 / PR #14354). Out of that card's scope, filed rather than fixed.

The site

SchemaRegistry.registerObject refuses a second code package claiming an object name another package already owns:

// packages/objectql/src/registry.ts — registerObject, ownership: 'own'
throw new Error(
  `Object "${fqn}" is already owned by package "${existingOwner.packageId}". ` +
  `Package "${packageId}" cannot claim ownership. Use 'extend' to add fields.`
);

It is a real refusal on a real path — the metadata load path reaches it through registerApp — but it carries no code and no status, so it is not an ADR-0112 envelope like the sibling refusals around it (resolveArtifactPackageOrder's DUPLICATE_ARTIFACT_PACKAGE / INVALID_ARTIFACT_PACKAGE_ENTRY, and the DUPLICATE_ARTIFACT_OBJECT_NAME refusal PR #14354 adds one layer up).

Why it matters, measured rather than argued

While reverse-verifying #14163 I ablated the new install-time object-name check and re-ran the pairing suite. The assertion expect(refused).toBeDefined() stayed green through that ablation — because this bare Error fires one step later and looks, to a throw-shaped assertion, exactly like the refusal that had just been deleted. Only the envelope assertion (code + status) went red.

So any rejection test written against this ownership rule today can only be a bare toThrow(), which is precisely the assertion ADR-0112 and ADR-0130 D3 rule out by name: it stays green against an unrelated Error from anywhere else in the path.

Suggested shape (not prescriptive)

Give the refusal an envelope — an error class with code (SCREAMING_SNAKE, registered in the dispatcher error-code vocabulary with a reachability verdict, the way DUPLICATE_ARTIFACT_OBJECT_NAME is) and status: 422 — keeping the message text as-is so existing message-substring assertions are unaffected. Worth checking at the same time whether any current test asserts only that this path throws.

Note the neighbouring late-install branch (ADR-0029 D9 §6.1, tenant-authored sitting owner) is not a refusal and is not part of this.

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions