← All posts
Release Notes — KeyDog 2.4: Approvals, Custom Roles, and the New Permissions Engine

Release Notes — KeyDog 2.4: Approvals, Custom Roles, and the New Permissions Engine

KeyDog 2.4 introduces a complete rewrite of the permissions system: custom roles, fine-grained approvals, request workflows, and a much-improved reports section. The full notes from engineering.

KeyDog 2.4 has finished rolling out to all instances as of last Friday. This was a long cycle — nearly three months — and the headline reason is that we tore out and replaced the permissions engine. That work touched almost every page in the application and made everything else in this release possible.

I want to walk through what changed, why we did it now, and what is coming next.

The old permissions engine, and why we replaced it

KeyDog has had five built-in roles since launch: Owner, Admin, Manager, Staff, and Viewer. Each role was a hard-coded bundle of permissions. The bundles were tuned through pilot feedback and worked well for the median customer.

They did not work for the long tail. We had Campus customers who wanted a "security supervisor" role that could read everything but only write to security-related records. We had higher-ed customers who wanted a "department manager" role that could issue keys in their own department but not in others. We had K-12 customers who wanted to give the principal read-only access to everything in their building but no access to other buildings.

The old engine could not express any of these. The hard-coded bundles were not extensible without an engineering change. We had been writing "custom role" tickets to engineering for a year, and the backlog had grown to the point where it was clear we needed a different approach.

The new engine

The 2.4 engine is policy-based. Every action in the application — issuing a key, editing a door record, viewing a fob profile, exporting the audit log — is gated by a permission check against a policy. Policies are expressed as conditions over the acting user, the target resource, and the operation.

Concretely, a policy looks like this in the admin UI:

Allow user.role = "security_supervisor" to "read" resources where resource.type in ("door", "fob_profile") and resource.building in user.buildings

The five built-in roles are now expressed as policies in the same engine. The Owner role, for instance, is "allow any operation on any resource." The Viewer role is "allow read on any resource, deny everything else." Customers can extend the policy set with their own custom policies, scoped to custom roles.

Under the hood, the engine compiles policies to a decision tree at instance startup, caches the tree per role, and evaluates a permission check in about 80 microseconds on average. This was important — we did not want the permissions check to become a hot spot in normal request handling. The new engine is actually faster than the old one for most checks because the compiled tree is more cache-friendly than the chain of if-statements it replaced.

Custom roles

The headline feature for end users is custom roles. Any Owner or Admin can now create a role from the Settings → Roles & Permissions page. The flow:

  1. Click "New role."
  2. Give the role a name and a short description.
  3. Pick which built-in role to use as a starting point. (This populates the policy set with sensible defaults — you almost never want to start from nothing.)
  4. Add or remove policies in the policy editor. The editor shows you exactly which actions on which resources the role will allow.
  5. Save. The role is now assignable to users.

Roles are scoped to your instance. They do not affect other customers and they do not need to be reviewed by us. Most of our early users have created two or three custom roles in the first week and then stopped — the long tail of edge cases turns out to be shorter than we expected.

Approval workflows

The second headline feature is approval workflows. Certain actions can now be configured to require approval from a designated approver before they take effect.

The default approval-eligible actions:

  • Issuing a master or sub-master key
  • Granting a fob profile that includes high-security zones
  • Revealing a safe combination
  • Deleting (archiving) a staff record
  • Modifying an audit log retention setting

For each action, an Owner can set an approval policy: who can approve, whether one approver is enough or whether multiple are required, and how long an unanswered request stays open before it expires.

When an admin attempts an approval-gated action, the system creates an approval request and notifies the configured approvers by email. The approver can approve or deny the request from the email or from the in-app inbox. The action does not proceed until approved.

This was a heavily requested feature for institutions with formal segregation-of-duties requirements — most of our healthcare customers, all of our government customers, and a growing number of our higher-ed customers as their compliance posture matures.

Request workflow

Related to approvals, but distinct: the new request workflow lets non-admin users formally request access to a key, a door, or a fob profile. This is for institutions where staff should not have direct issuance access but should have a documented way to ask.

A staff user opens the staff self-service portal, browses the catalog of keys and access types available to their role, and submits a request. The request goes to an admin or supervisor, who either issues the access or denies the request with a documented reason. Either way, the request and its resolution are captured in the audit log.

This replaces a lot of email-based key request workflows that we have seen at customer sites. The documented audit trail is the obvious win; the less obvious win is that staff can self-serve to see what they are eligible for without having to ask, which reduces the support load on the admin team.

Reports, revamped

The reports section was the longest-overdue area of the application. The 1.0 reports were essentially canned CSV exports with no UI to speak of. The 2.4 reports are interactive — filter by date range, by building, by user, by key type, by holder — and render as both an in-browser view and an export.

The default report set:

  • Inventory snapshot. Every key in the system with current status, holder, location, and last action date.
  • Activity report. All issuances and returns in a date range, with optional grouping by holder, by key type, or by building.
  • Overdue summary. All keys past their return date, grouped by holder with contact information for follow-up.
  • Offboarding report. All keys held by staff marked as inactive, terminated, or on extended leave.
  • Audit excerpt. A filtered slice of the audit log suitable for compliance review.
  • Capacity utilization. Your plan limits vs. actual usage, with a 90-day trend.

Custom reports are not yet available in the UI but the underlying API supports them. We will be adding a custom report builder in 2.5.

Smaller improvements

  • Mobile-optimised admin views. The most-used admin pages (keys, staff, audit log, dashboard) now have a proper mobile layout. The 1.x mobile experience was usable but cramped. The new layout adapts cleanly down to a 360px viewport.
  • Search across resources. A global search bar at the top of the admin UI can search across keys, staff, doors, fob profiles, and audit events. Results are grouped by resource type and ranked by recency.
  • Two-factor authentication for admin accounts. Owner-enforced 2FA is now configurable per instance. Owners can require 2FA for all admin accounts; admin accounts get an in-app prompt to enroll the next time they sign in.
  • Audit log retention policies. Per-instance retention configuration with optional per-resource overrides. Most instances do not need this, but institutions with mixed retention requirements (longer for security-related events, shorter for routine operational events) now have a way to express it.

Fixes

The notable fixes in 2.4:

  • Fixed an issue where the floor plan editor would lose pin positions if the underlying PDF was replaced. Pin positions now migrate to the new PDF.
  • Fixed an issue with the kiosk pairing flow where a pairing code could be used twice in rapid succession. The token is now single-use.
  • Fixed a CSV import bug where staff records with non-ASCII characters in their names were being silently truncated. Full UTF-8 support across all import paths.
  • Fixed an issue with the offboarding view where keys held by the offboarded staff member would briefly appear as unassigned during the offboarding process. The view now uses transactional snapshots.
  • Fixed a Brevo webhook bug that was affecting a small number of customers whose support chat threads were not appearing in the admin dashboard.

What is in 2.5

The 2.5 cycle is starting now and is expected to land in early August. The headline items:

  • Custom report builder. UI for defining your own reports on top of the data model. SQL-free.
  • Workflow automations. Trigger an action (notify, escalate, create a follow-up task) when a defined event happens. Replaces a lot of manual monitoring.
  • Public API v2. The current API is functional but not idiomatic. We are redesigning it with cleaner resource naming, consistent pagination, and better error semantics.
  • SAML SSO for Campus. SAML has been an Enterprise-only feature; we are bringing it down to Campus based on customer demand.

If you want to follow along with what we are working on in real time, the public roadmap is at app.keydog.io/roadmap (accessible from any admin instance). Comments and votes on the roadmap items are read by the product team — they have driven several of the items above.

#release notes#permissions#approvals#v2.4

See KeyDog for yourself

Replace the key spreadsheet. Spin up a live demo or talk to our team about your campus.