This is a submission for the Permit.io Authorization Challenge: Permissions Redefined
What I Built 🛠️
Viskify is a full-stack hiring platform that lets candidates prove their skills and credentials with blockchain-signed Verifiable Credentials (VCs) and AI-graded SkillPasses. Recruiters can then filter talent by proof instead of promises, while issuers (universities / employers) sign off on credentials in a couple of clicks.
To keep security sane as the feature-set grows, I ripped out every hand-rolled if (role === …)
check and moved all authorization logic to Permit.io. The result is a cleaner codebase, live-editable policies, and a demo that shows how externalized RBAC can power a real production workflow (candidate → issuer → recruiter → admin) with zero redeploys.
Persona | Everyday pain | Viskify fix |
---|---|---|
Candidate | Re-uploading the same PDF certificates to each job portal | One DID-backed profile + SkillPass quizzes |
Recruiter | Manual credential verification, résumé keyword soup | Filter by on-chain VCs and quiz scores |
Issuer | Endless email chains for reference checks | Dashboard to review and sign requests |
Admin | Fragile in-code ACLs | Permit.io PDP enforcing policies centrally |
Demo 🌐
- Live app: https://viskify-permit-io.vercel.app Log in with the test users below or create your own account (auto-synced to Permit).
Password | Role | |
---|---|---|
[email protected] |
myPassword |
admin |
[email protected] |
myPassword |
candidate |
[email protected] |
myPassword |
recruiter |
[email protected] |
myPassword |
issuer |
Want to see Permit in action?
Log in as[email protected]
, open */dashboard*, then hit/api/admin/stats
in another tab – 200 OK.
Log out, switch to[email protected]
, hit the same endpoint – 401 Unauthorized.
Screenshots:
Project Repo 📦
https://github.com/syntaxsurge/viskify-permit-io
Key folders:
-
/permit
– declarative base RBAC policy (base.yml
). -
/scripts/sync-permit.ts
– idempotent seeding of roles, resources & demo users via the Permit SDK. -
/app
– Next.js 15 App Router code (Server Actions, Route Handlers, RSC).
The README explains the full architecture plus copy-paste setup commands.
My Journey 🛤️
- Prototype → pain: I started with classic role checks sprinkled across API routes. After adding a fourth role the code smelled.
- Enter Permit.io: Spun up the cloud PDP, wrote an RBAC policy in YAML, and deleted ~120 LOC of brittle guards. ✂️
-
CLI FTW: The Permit CLI let me seed roles/resources and demo users straight from
pnpm permit:cli
; no dashboard clicking. -
Live tweaks: During testing a recruiter needed read-only access to a new
talent_search
resource. I toggled a checkbox in Permit and instantaneously the UI lit up – no redeploy, no PR. - Takeaways:
- Externalized auth turns “oops, forgot a check” bugs into policy edits.
- Keeping policies next to code (
/permit/*.yml
) still feels GitOps-friendly. - The PDP latency is negligible (<2 ms in local tests).
Using Permit.io for Authorization 🔐
-
Policy definition –
permit/policies/base.yml
declares roles (admin
,candidate
,recruiter
,issuer
), resources (dashboard
,admin_stats
, …) and actions. -
Seeding –
pnpm permit:cli
runsscripts/sync-permit.ts
which:
- Creates the roles/resources via the SDK.
- Assigns granular permissions (only admins get
admin_stats:read
, everyone getsdashboard:view
). - Syncs four demo users and assigns their roles.
API routes use the same helper (assertPermission
) before hitting the DB.
-
Local vs Cloud PDP – by default we hit
https://cloudpdp.api.permit.io
, but running the PDP Docker image locally (docker run permitio/pdp-v2 ...
) and settingPERMIT_PDP_URL
works identically.