Charter · guide

A list of your own

Charter does not know what a screen is. The same charter and the same function decide which tools an assistant is handed.

Install it
pnpm add @niscorp/charter
Step 1 of 4

A list Charter has never seen

These are the tools an assistant at the box office could call. Nothing in Charter mentions tools.

To govern something with a charter, two things have to be true of it. It is set up as data, as a list of names. And a name that is missing means no.

A list Charter has never seen
import { resolvePrincipal, verifyCharter } from '@niscorp/charter';

const tools = ['bookings.find', 'bookings.cancel', 'shows.find', 'refunds.issue'];
Step 2 of 4

Roles over it

The roles are written exactly as they are for screens. The desk finds things and cancels bookings. Finance extends the desk and may issue refunds.

Roles over it
const charter = {
  desk: ['bookings.*', 'shows.find'],
  finance: { extends: ['desk'], allow: ['refunds.*'] },
};
Step 3 of 4

Resolve, and hand over

The answer is a set of names. What happens next is up to the thing being governed: here, the assistant is given only the tools in its set.

In Nisc an assistant runs as the user it works for, so it resolves with that user’s roles.

Resolve, and hand over
for (const role of ['desk', 'finance']) {
  console.log(role + ':', [...resolvePrincipal(charter, tools, [role])]);
}
Step 4 of 4

The verifier works on it too

The verifier is as blind to what the names mean. Add a tool that no role selects and it is reported, the same as a screen nobody can reach.

The verifier works on it too
const report = verifyCharter(charter, { actions: [...tools, 'members.export'], data: [] });
for (const issue of report.warnings) console.log(issue.rule + ':', issue.detail);
Then

Run it.

The three tools the desk gets, the four finance gets, and the new tool the verifier says nobody can reach.

Run it
npx tsx tools.mts
It prints
desk: [ 'bookings.find', 'bookings.cancel', 'shows.find' ]
finance: [ 'bookings.find', 'bookings.cancel', 'shows.find', 'refunds.issue' ]
orphan: action "members.export" is granted by no role — deployed but unreachable