most "type-safe" permission checks are only as trustworthy as data typescript never actually verified

i'm the author of zap-studio/permit, a small authorization library. i'm posting this because of a specific problem that i feel i'm either totally right or totally wrong.

types don't exist at runtime. that's not news, but it's easy to forget it applies to permission checks specifically. a check like ctx.user.id === post.authorId "type-checks" fine. but post usually came from a db row, an api payload, or whatever. none of that passed through a place typescript could verify it. if a lazy join returns authorId: null, or a migration changes a column's nullability, the check still compiles. it just quietly does the wrong thing at runtime, which is the one place a permission check actually matters.

most type-safe permission libraries stop at the type. permit doesn't: resources are defined with a standard schema validator (zod, valibot, or arktype), and policy.can() re-validates the resource against that schema every time it evaluates a rule, not just once at setup. an invalid resource resolves to false. meaning, it fails closed, it never throws.

here's a code example

const policy = createPolicy<AppContext>({
  resources,
  actions,
  rules: {
    post: {
      read: allow(),
      write: when((ctx, _, post) => ctx.user?.id === post.authorId),
      delete: deny(),
    },
  },
});

await policy.can(context, "post:read", postResource);

conditions compose with and(), or(), not(), and whole policies compose with mergePoliciesAnd / mergePoliciesOr, so you can split authorization by feature or team and combine it later.

but, if you already know permix, which is the most established option here, it seems it doesn't solve this specific issue, mostly because it's deny by default (like permit). nothing stops write: (ctx, post) => ctx.user.id === post.authorId from running against bad data and returning true, undefined === undefined is true, so a missing authorId can accidentally grant access nobody meant to grant. permit isn't "better," it just refuses to run the rule at all if the resource fails its schema first. curious if others have hit this in practice or think it's rare enough not to matter.

and here are some links for curious people to check the code or docs:

reddit.com
u/atrtde — 5 days ago
▲ 82 r/commandline+1 crossposts

dotfiles-manager: a lean and easy dotfiles manager

i've been building and polishing this cli for about a year now. it was called mntn before, but i recently renamed it to dotfiles-manager since the developer experience feels good enough to me.

it fully embraces using git for versioning and works for three things:

  1. config files (.zshrc, .bashrc, etc.)
  2. packages (npm ls -g and more)
  3. encrypted files (.ssh/)

finally, if you change computers or environments, you can switch between profiles. the default is common, but you can also create profiles like personal or work.

u/atrtde — 14 days ago