HNHacker News
TopNewBestAskShowJobs

jussinevavuori

12 karma · joined March 30, 2025

submissionscomments
jussinevavuori··on You're protecting your data wrong – Introducing the Protected Query Pattern
CLARIFICATION TO ARTICLE

Hello, it's me, the author!

I'd like to take the time to clarify a few things about the article. I'm not claiming this to be revolutionary to all people, I'm just claiming it to be useful for some people.

The intent of the protected query pattern is the following:

- Co-locate query and authorization logic (easier to maintain) - Allow (but not require) inner functions to be pure (e.g. trivial to cache with upcoming Next.js "use cache" API). - Allow easy bypassing of authorization for some contexts. - Simplify logic elsewhere (e.g. getDocument.protect("id") is a pretty one liner).

In most cases, I use the protector pattern to either allow or disallow the entire query, based on the results. Filtering or redacting the data is done much more rarely. †

What I did NOT intend:

- I did not intend to select all rows and return only the useful. You are right, that would be horrible for performance. However, I understand how easy it is to come to that conclusion, seeing how I introduced the Kilpi.filter function.

Thank you all for your feedback, this allows me to improve on this pattern and Kilpi in general!

† Your worries about performance have given me ideas of a new "preprotector" function that would stop the query before it ever even starts. I'll have to think about adding it in the future!

jussinevavuori··on You're protecting your data wrong – Introducing the Protected Query Pattern
This is not what I'd intended to communicate with this article. The Kilpi.filter pattern is not the primary point of this article, it is only a minor utility provided by Kilpi for special cases. I do not suggest to fetch all rows and return only authorized rows. The inner query function should still be performant and return only the requested data.

My point was to show how you can co-locate your queries and authorization logic, just as you would with any sensible data access layer. However, this approach keeps the inner function pure and e.g. easily cacheable with the upcoming Next.js "use cache" directive, and also allows easy bypassing of the authorization logic when required by your application.

I hope this clarifies my intent.

jussinevavuori··on You're protecting your data wrong – Introducing the Protected Query Pattern
Thank you for the comment. This is not what I'd intended to communicate with this article. The Kilpi.filter pattern is not the primary point of this article, it is only a minor utility provided by Kilpi for special cases.

My point was to show how you can co-locate your queries and authorization logic, just as you would with any sensible data access layer. This method however keeps the inner function pure and easily cacheable, e.g. with the upcoming "use cache" Next.js directive, and allows easy explicit bypassing of the protection with e.g. `.unsafe()`, which is required in some scenarios in your application.

I hope this clarifies my intent.

jussinevavuori··on You're protecting your data wrong – Introducing the Protected Query Pattern
Thank you for the questions.

1. While yes, this would allow you to `SELECT * FROM table` and then filter on your server. However, I believe that most developers are aware that that is, as you said, horribly inefficient. For performance, you would definitely make your queries only return the authorized data.

(Although, now that you've mentioned it, I'm starting to think of a "pre-protect" API to stop the query before it ever even runs in the first place, which would solve the performance issue.)

I'm sure this won't suit everyone, however I've found it a very helpful pattern in my experience. In most cases in my apps, that the protector is only a safe-guard for exceptions, and the app would function securely even without protectors. However, they add an extra layer of security and confidence.

2. The function returned by Kilpi.query is not pure, however the inner function is pure. For example, considering the upcoming Next.js "use cache" directive, you can add it to the inner function wrapped by Kilpi.query and it just works.

jussinevavuori··on Kilpi: Open-source authorization framework for TypeScript applications
Hi, my name is Jussi.

I am the author of Kilpi, a new open source authorization library for Typescript applications.

It is an opinionated library, that solves real problems for applications. It considers all aspects of authorization: queries, mutations, redacting data, changing your UI, defining policies, ABAC, RBAC, ReBAC...

I've created over a dozen applications throughout my career, and struggled with building a scalable authorization solution every time.

This is until I built my own company, Inclusive Mobility and decided to finally create a robust, scalable authorization solution. It ended up being so good, I decided I had to open source and release it to the public.

I'd love to hear your opinions on application authorization, how you do it and whether you think Kilpi is the right tool for the job.