business-role-library
v1.0.1
Published
Single source of truth for the catalog of organizational roles (Dutch public-sector context). Consumable as raw JSON or via a typed TypeScript API.
Downloads
281
Readme
business-role-library
Single source of truth for the catalog of organizational roles used across the for-the-money applications (Dutch public-sector context). Every consuming app reads its roles from here instead of keeping its own copy.
What's in it
roles.json— the canonical, ordered list of role records. This is the source of truth. Each record:{ "id": "burgemeester", "label": "Burgemeester", "category": "Politiek bestuur", "description": "Voorzitter van het college van B&W en de gemeenteraad. …" }categories.json— the category names, in display order.activities.json— shared, deduplicated catalog of activities (what roles do). Each has its own stable id and is reused across roles.role-activities.json— many-to-many join: role id → activity ids.responsibilities.json— per role; what the role is accountable for, each linking theactivityIdsit's derived from.painpoints.json— per role; where a responsibility breaks down, each linking theresponsibilityIdit threatens, with aseverityand an optionalconfidence. Painpoints are potential and the catalog is uncapped: a role may carry many, ranging from near-certain to speculative.*.schema.json— JSON Schema (draft 2020-12) for each file above.src/index.ts— typed TypeScript API over the JSON, includinggetRoleProfile(id)which assembles the full resolved chain.
The enrichment model
Roles are enriched along a deliberate, traceable chain:
role ──< performs >── activity ──> rolls up into ──> responsibility ──> threatened by ──> painpoint- An activity is concrete and verb-led ("aanvragen behandelen"). Activities
are shared: one activity (e.g.
adviseren-bestuur) is referenced by many roles, so it lives once inactivities.jsonand is joined in viarole-activities.json. - A responsibility is what a role is accountable for, inferred from a cluster
of that role's activities (
activityIdsmust be a subset of the role's join). - A painpoint is where that responsibility breaks down under real conditions.
Each threatens exactly one responsibility of the same role. Painpoints are
potential, not asserted certainties — there is no cap on how many a role can
have.
severitysays how badly it hurts if it occurs; the optionalconfidence(laag/middel/hoog) says how likely it is to occur at all, so consumers can rank near-certain painpoints above speculative ones.
Because every link is by id, you can trace any painpoint back through a
responsibility to the concrete activities that ground it — the enrichment is
auditable, not asserted. validate enforces all of these references.
Consuming it
Any tool / language — read the JSON
import roles from 'business-role-library/roles.json' with { type: 'json' }…or just read role-library/roles.json from disk. No build step, no types
required — this is why JSON is the canonical form.
TypeScript / bundled apps — use the typed API
import {
roles,
categories,
groupRoleTemplates,
isBuiltinRole,
CUSTOM_ROLE_CATEGORY,
// enrichment layers
activities,
roleActivities,
responsibilities,
painpoints,
getActivity,
getRoleActivities,
getRoleProfile,
type RoleTemplate,
type RoleGroup,
type Activity,
type Responsibility,
type Painpoint,
type RoleProfile,
} from 'business-role-library'
// The full resolved chain for one role:
const profile = getRoleProfile('vergunningverlener')
// profile.responsibilities[0].activities → activities it derives from
// profile.responsibilities[0].painpoints → painpoints that threaten itThe API ships as TypeScript source. Bundlers (Vite, etc.) consume it directly;
in Nuxt add the package to build.transpile.
Install as a local dependency from a sibling/child path:
// package.json
"dependencies": {
"business-role-library": "file:../role-library"
}Editing the catalog
Edit roles.json (and categories.json if adding a category), then validate:
npm run validatevalidate enforces: unique kebab-case ids, all four fields present and
non-empty, every category declared in categories.json, and every declared
category actually used.
For the enrichment files (all optional — absent files are skipped) it also
enforces referential integrity: unique activity / responsibility / painpoint
ids; every role key is a known role; every activity id resolves to the catalog;
each responsibility's activityIds are a subset of that role's join; each
painpoint's responsibilityId resolves and belongs to the same role; every
severity is laag, middel or hoog; and confidence, when present, is one
of those same three levels.
Invariants for consumers
idis stable — it's the join key. Don't rename ids; add new ones.- The role shape (
id,label,category,description) is the contract. Adding fields is backwards-compatible; renaming/removing is breaking.
