Skip to content

fix: deserialize should only expose @exposed fields#78

Merged
ryanrasti merged 1 commit into
mainfrom
ryan_fix_deser_visibility
May 11, 2026
Merged

fix: deserialize should only expose @exposed fields#78
ryanrasti merged 1 commit into
mainfrom
ryan_fix_deser_visibility

Conversation

@ryanrasti
Copy link
Copy Markdown
Owner

No description provided.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR tightens the @expose security contract by ensuring deserialization only materializes fields explicitly marked with @expose, preventing accidental leakage of unexposed columns (e.g. secrets) from bare .from().execute() results and from scalar subqueries that deserialize record composites.

Changes:

  • Adds @expose-aware deserializeRows filtering (drops unmarked columns when an exposed-field Set is present).
  • Extends Record.of(...) to accept an optional exposed-field Set so scalar subqueries (.scalar()) can filter composite record deserialization.
  • Adds RPC tests covering multiple selection shapes for @expose gating (but scalar cases currently lack assertions).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/util.ts Adds expose-aware deserializeRows implementation and duck-typed deserializable check.
src/types/overrides/record.ts Updates Record.of to optionally filter deserialized composite fields by exposed set.
src/rpc.test.ts Adds RPC tests for @expose gating across query shapes (scalar cases currently only log).
src/exoeval/tool.ts Adds exposedFieldsOf() helper to extract exposed-field Set from marker-bearing instances.
src/database.ts Routes query/mutation execution through new deserializeRows(..., exposedFieldsOf(output)).
src/builder/query.ts Removes old deserializeRows implementation; updates scalar subquery path to pass exposed fields into Record.of.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/builder/query.ts Outdated
Comment thread src/util.ts Outdated
Comment thread src/util.ts Outdated
Comment thread src/rpc.test.ts
Comment thread src/rpc.test.ts Outdated
Comment on lines +277 to +279
// What do the embedded Record array elements contain? Should NOT have password.
// eslint-disable-next-line no-console
console.log("[scalar many] rows:", JSON.stringify(rows));
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Comment thread src/util.ts Outdated
Comment thread src/util.ts Outdated
Comment thread src/builder/query.test.ts
@ryanrasti ryanrasti force-pushed the ryan_fix_deser_visibility branch from aedb53a to ade7903 Compare May 11, 2026 15:26
@ryanrasti ryanrasti merged commit 0f3ccf4 into main May 11, 2026
3 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Comment thread src/util.ts
Comment on lines +73 to +77
throw new Error(
`deserializeRows: output column '${k}' is not a typed pg expression (got ${JSON.stringify(type)}). ` +
`The select callback must return an object whose values are Any instances.`,
);
}
Comment thread src/util.ts
Comment on lines +60 to +64
if (exposed == null) {
throw new Error(
`deserializeRows: expected a plain object or an @expose-marked table instance as shape, got ${JSON.stringify(shape)}`,
);
}
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