Toby Allen

Verified directors and public registries: identity proofing meets FGA

· Auth0, Customer Identity Products, Auth0 FGA, Identity Security

The previous post ran the same persona-separated model across six consumer and professional verticals without changing the schema once. Government services push on it differently. A company registry and a citizen-facing permit system both introduce a case the earlier verticals didn't need: proving that whoever holds a governance role is who they claim to be, not just that they hold the role.

Australia's Digital ID System defines exactly this as three ID-proofing levels - Basic (an email or mobile number), Standard (two ID documents plus a face match, used for things like opening a utility account), and Strong (two ID documents including a photo ID, plus a face match, used for welfare and government services). In this post I will detail how identity verification gets modelled as a first-class part of the FGA model from this series, using a company registry and a citizen permit system as the two worked examples, and where I had to add a genuinely new relation rather than reuse an existing one.

A director, and a verified director, are different facts

Acme Widgets has three people with governance-shaped authority. Mira founded the company and is its owner. Priyanka joined later as a co-director and has completed identity verification to Standard. Raj was appointed at the same board meeting as Priyanka and already has identical admin rights - he can manage the company's registry filing right now - but he hasn't completed ID proofing yet.

Acme Widgets: two verified directors, one appointed director awaiting verification, one ordinary employee, and a registered agent firm

That distinction between holding a governance role and holding a verified one needed a new relation, director, separate from the existing admin. It's a small but deliberate addition: admin already meant "day-to-day management authority" everywhere else in this model - Northwind's IT administrator managing a corporate news subscription, for instance - and that's a materially different concept from a statutory governance role that a regulator cares about. verified_director then checks two things together: is this persona a director (or the owner), and is the person behind that persona proofed to at least Standard - the same real-world requirement behind Australia's Director ID scheme.

Jamie, an ordinary employee, is neither a director nor verified, but he can still view the filing - the same public wildcard that makes a company's basic registry entry searchable by anyone covers him too, incidentally. Swiftfile Agents, a registered corporate-services firm, lodges routine filings on Acme's behalf under an engagement granted to its whole current staff roster, exactly the same primitive as the accounting and law firm engagements from the previous post.

Why a disqualified director can't just use a different login

The reason person exists at all in this model is to answer questions an access check never asks itself. Company registries are the clearest possible illustration of that. Victor was a director of Oldco, which failed; he's since been disqualified from acting as a director. If he tries to register a new company, Newventure, under a different login, that new persona has zero relationship in the entire model to his old one - no shared role, no shared business, nothing an authorisation check would ever traverse.

That's deliberate, and it's also exactly why there's no disqualified relation anywhere in this model. Screening a prospective director against a disqualification register isn't an access-control decision FGA is positioned to answer - it's a compliance query that needs to resolve a login back to a real person and check an external register. What the model guarantees is that the resolution is reliable: however many logins Victor controls, they all resolve to the same person, so a compliance system built on top of this graph always knows who to actually check, even though the day-to-day authorisation model never asks that question on its own.

Citizen services: statutory roles that needed nothing new

A building application system for a local council turned out not to need any new relation at all, which was the more surprising result of the two. Homer submits a building application. Nadia submits an unrelated one. Neither needs to individually grant council staff access to their specific application, because a case officer is just a member of the council's own service, and a senior approver who can sign off decisions is just its admin - both cascade to every application under that service the same way any service-level role cascades to every account beneath it, elsewhere in this model.

A council's case officers and senior approvers cascade to every application through service-level roles; an engaged architect stays scoped to one project

Homer separately engages an architecture firm to manage his application specifically. That engagement is scoped to his one application only - the firm's access says nothing about Nadia's unrelated garage application, even though the council's own staff have jurisdiction over both. No relation named "case officer" or "approver" exists anywhere in the schema; they're labels for roles the model already had.

Final Thoughts

The genuinely new piece here isn't a clever trick - it's a small, self-referencing relation on the login (verified_basic / verified_standard / verified_strong), gating one new permission (verified_director) that combines a governance role with a proofing level. Everything else - the public wildcard, the statutory case-officer/approver cascade, the disqualified-director resolution - falls out of primitives the model already had. The repository has the full model, both verticals' test files, and the diagrams this post is drawn from. A follow-up post moves away from time-bounded access entirely, into delegation bounded by a dollar figure instead.