Roles
Who may do or sign a step, where, and apart from whom. A role names a credential expression, the region its act needs, what the act pays, and the members it must differ from.
A role answers one question: who may do or sign this step, where, and apart from whom?
One role, and the step it signs. by names the role:
cat services/translation.ts roles: { translator: { credential: 'sworn translator' } },
deliver: {
translate: 'ai',
harden: { review: 'adversarial', lenses: ['meaning', 'terms'] },
sign: { by: 'translator', stamp: true },The rules table decides what the act needs, and the role says who holds it. check reads both back:
npx services.dev check who A translator signs every document before delivery. (rules 2026-10)
roles translator · sworn translator · your staff
steps translate · ai → harden · ai · adversarial · 2 lenses → sign · translator · * · stamped
bounds reserved sign to sworn translatorA role with no pool is your staff, working from the owner console. A role with a pool is filled from your marketplace. A role whose credential doesn't meet the row fails reserved_act_unstaffed, and the fix is the role's one line:
git add -A && git diff --stageddiff --git a/services/translation.ts b/services/translation.ts
index 0585d1f..d9dc9a6 100644
--- a/services/translation.ts
+++ b/services/translation.ts
@@ -6,7 +6,7 @@ export default Service({
input: { document: 'file', to: 'language: a BCP 47 tag, such as fr-CA' },
output: { document: 'file' },
rules,
- roles: { translator: { credential: 'translator' } },
+ roles: { translator: { credential: 'sworn translator' } },
deliver: {
translate: 'ai',
harden: { review: 'adversarial', lenses: ['meaning', 'terms'] },A translator holds either of two credentials. A reviewer holds all of one and any of two others, and reviews the translator, so the same member can never do both:
cat services/reviewed-translation.tsimport { Service } from 'services.dev'
import rules from '../rules.ts'
// Credential expressions and separation, read aloud: a translator holds either credential, the reviewer
// holds all of one and any of two, reviews the translator, and so is never the member who translated.
export default Service({
name: 'Reviewed Translation',
description: 'Translated by one person, signed by another.',
input: { document: 'file', to: 'language: such as fr', country: 'jurisdiction: such as FR' },
output: { document: 'file' },
rules,
roles: {
translator: { credential: ['sworn translator', 'certified translator'], where: 'country' },
reviewer: { credential: { all: ['sworn translator'], any: ['court interpreter', 'notary'] }, where: 'country', reviews: 'translator', pay: 40 },
},
deliver: {
draft: 'ai',
translate: { by: 'translator', checklist: ['every page is translated', 'the terms match the glossary'] },
harden: { review: 'adversarial', lenses: ['meaning', 'terms'] },
sign: { by: 'reviewer', stamp: true },
npx services.dev check who A sworn translator or certified translator in the job's country does the translate step. A reviewer in the job's country signs every document before delivery. (rules 2026-10)
roles translator · sworn translator or certified translator · country · your staff
reviewer · sworn translator, and court interpreter or notary · country · your staff · $40 an act · reviews translator, so never the member who did it
steps draft · ai → translate · translator · country · 2-item checklist → harden · ai · adversarial · 2 lenses → sign · reviewer · country · stamped
ledger +$149.00 · AI $1.26 (example) · reviewer $40.00 · you $107.74Each role gets its own Tasks and its own pay. Every Service that names the same Pool role draws on the same members.
Some work stays with the person who starts it, as a negotiation stays with the closer who wrote the proposal. span names the steps one Task holds. Once a step of the span is the role's, its Task holds every step after it in the span. The member who claims it keeps them all, and the last step's commit fulfills it. A step of the span that comes back after a revival is that member's alone for revive.first_call, then posts again.
talk says how the member reaches the party outside the thread: as the client whose matter it is, even when someone else ordered for them, with mail from the client's domain and calls bridged through the job. The party deals with the buyer alone, no address or number crosses, and every touch lands on the job's thread.
The Deal Service holds a closer for four steps, from the meeting to the close:
cat services/deal.ts closer: { pool: closers, span: ['meet', 'propose', 'negotiate', 'close'], revive: { first_call: '24h' },
pay: { share: '10%', of: 'closed_value', on: 'won', from: 'buyer' },
talk: { as: 'client', mail: 'client_domain', calls: 'bridged' } },Worked in: the Deal Service, three roles on one deal.
| Key | What it says | Default |
|---|---|---|
credential | What a member holds: one credential, any of a list, or { all, any } | the Pool role's |
where | The region the act needs: a jurisdiction input, '*' for any admission, or your function | the rules row's where |
pool | A Pool you write and import, '<door>/<pool>' for a Pool another operator exports, at the terms its door pins, or 'buyer' for the buyer's own professionals | your staff |
pay | What the act earns, fixed when its Task posts: dollars, { usd, on } at the act, a later step's guard ('meet.held') or an end, or { share, of, on }. Pay says when it is the member's | nothing |
pay.rail | Who sells the fee: 'brand', 'member' or 'entity' | the row's rail |
pay.from | Out of the price, or charged on top: 'price' or 'buyer' | 'price' |
pay.kill | What a share role accrues, in dollars, when the buyer withdraws after the claim | none on a share |
span | The steps one Task holds, in order: the member who claims it keeps each one, and the last one's commit fulfills it | the one step |
revive | { first_call: Within }: a step of the span that returns after a revival is the same member's alone for that long | none: it posts again |
talk | { as: 'client' | 'buyer' | 'brand'; mail?: 'client_domain' | 'buyer_domain' | 'brand_domain'; calls?: 'bridged' }: how the member reaches the party outside the thread, each touch on it | the thread alone; as alone, 'client' |
coverage | Insurance in force per act, in dollars | the Pool's |
reviews | This role signs what that role prepares, so never the same member | none |
with | { differ, same }: never the member who did one role, always the one who did another | none |
dispatch | How its Tasks reach members: 'feed', 'cascade', 'pick' or 'direct' | the Pool's |
Each credential's scope, one admission everywhere or per region, is declared once, in the Pool's scopes. Where an act happens has where.
Two more sources fill a role beside a Pool's members:
| Key | Who | How it reaches the record |
|---|---|---|
Pool.firms: true | a firm enrolls a bench of its own members | each member joins and is verified like any other; the firm's conflicts ledger joins each member's check, and the fill ladder's firms rung opens a Task to firms |
Pool.invite_by_buyer: true | a buyer invites their own professional | the invited professional joins the Pool through /join and the verifier, and is offered that buyer's Tasks by direct |
pool: 'buyer' | the buyer's own professionals, named on the order | the Task goes only to them, and eligibility still holds every one to the rules row |
A firm or an invited professional never skips verification, eligibility or the member charter.
| Surface | What a role adds |
|---|---|
| API | Its Task routes, GET /tasks to POST /tasks/:id/attest, for its members' own sessions |
| CLI | tasks list to tasks attest <task>, in a member's session |
| MCP | never: a person acts |
| SDK | never: a person acts |
| Site | The Service page names who signs |
| Docs | llms.txt names who signs |
| App | The delivery portal, at /<pool>, or the owner console for your staff |
→ GET /llms.txtA contract flagged, then advised on. $99 per matter, within 48 hours, charged on acceptance. An attorney signs at advise, stamped. The client consents first.| Code | When |
|---|---|
reserved_act_unstaffed | check: a step performs a reserved act, and no role on it holds the credential |
rail_conflict | check: pay.rail contradicts the row's rail |
ineligible | A member who fails a predicate, separation included, claims a Task. The answer names the cure |
reserved | A person without the credential attests a reserved act |
npx services.dev check roles attorney · bar admission · from attorneys · $50 an act
roles practitioner · patent attorney or agent · * · from attorneys · $150 an act- Legal. A practitioner from the attorneys Pool signs and files patents anywhere; an attorney signs where the client is admitted. The attorneys' Pool.
- Tax. A preparer signs the return, and the taxpayer authorizes it. The tax example.
- Sales. A closer closes, under a guard on the floor the client set. Its roles hold no credential.