Skip to content

fix: bind related-table allowRead to a proper resource instance - #1532

Merged
kriszyp merged 1 commit into
mainfrom
kris/related-allowread-binding
Jul 2, 2026
Merged

fix: bind related-table allowRead to a proper resource instance#1532
kriszyp merged 1 commit into
mainfrom
kris/related-allowread-binding

Conversation

@kriszyp

@kriszyp kriszyp commented Jun 30, 2026

Copy link
Copy Markdown
Member

Summary

The related-table read check inside the built-in allowRead invoked relatedTable.prototype.allowRead.call(null, user, property, context) — binding this to null. It's harmless today because the built-in allowRead is closure-based and never reads this, but null is an improper binding that would break if the base hook ever referenced instance state.

This constructs a related-type resource instance and invokes allowRead on it, so this is a valid resource of the related type.

Scope (deliberately narrow)

  • Behavior-preserving. The same base table-level RBAC check runs (relatedTable is the base table class, so the resolved method is identical), only with a correct this.
  • Does not consult a related-table allowRead override. Per the allowRead design, it is a grant hook over RBAC, default RBAC has no per-record granularity, and overrides are evaluated on their own read paths. Propagating overrides to related-table reads would be a behavior change and is intentionally out of scope here.

This is the safe "signature/binding correction" slice of the #1422 / #1487 allowRead review — the fail-closed hardening is in #1489.

Testing

  • tsc --noEmit clean.
  • integrationTests/server/operation-user-rbac.test.ts30/30 (table/attribute read-permission paths unaffected).

No new test: the change is behavior-preserving, so existing relationship + RBAC coverage applies. Happy to add a dedicated relationship-with-attribute-permission regression if preferred.

Refs #1487, #1422.

🤖 Generated with Claude Code

The related-table read check inside the built-in allowRead invoked
`relatedTable.prototype.allowRead.call(null, user, property, context)` — binding
`this` to null. It happens to be harmless today because the built-in allowRead is
closure-based and never reads `this`, but null is an improper binding and would
break if the base hook ever referenced instance state.

Construct a related-type resource instance and invoke allowRead on it instead, so
`this` is a valid resource of the related type. This is behavior-preserving: the
same base table-level RBAC check runs (relatedTable is the base table class), and
it deliberately does not consult a related-table allowRead *override* — default
RBAC has no per-record granularity and overrides are grant hooks evaluated on
their own read paths.

Verified: tsc clean; operations RBAC integration suite 30/30 (attribute/table read
permissions unaffected).

Refs #1487 (allowRead consolidation), #1422.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the permission checking logic in resources/Table.ts by instantiating a properly-bound instance of the related table (relatedResource) to invoke allowRead, rather than calling it with a null context via .call(null, ...). This ensures that this correctly references a valid resource of the related type. There are no review comments, and I have no additional feedback to provide.

@claude

claude Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found.

@kriszyp
kriszyp merged commit 2e4ea51 into main Jul 2, 2026
47 checks passed
@kriszyp
kriszyp deleted the kris/related-allowread-binding branch July 2, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants