// Admin · SBT issuance + permissions for Publishers and Institutions function AdminRail({ active }) { return ( <>
ADMIN ROLE
Cell Press · Editorial
PUBLISHER VERIFIED
); } const SBT_TEMPLATES = [ { tag: 'EDITOR', name: 'Editor · Cell Press', dur: '24m', scope: 'Editorial · all titles', issued: 14, pending: 1, col: UB.ink, perms: ['accept submissions', 'assign reviewers', 'release bounties', 'reject manuscripts'] }, { tag: 'REVIEWER', name: 'Trusted reviewer', dur: '18m', scope: 'Domain · neuroscience', issued: 184, pending: 4, col: UB.accent, perms: ['claim review tasks', 'sign reviews', 'redeem bounties'] }, { tag: 'POSTDOC · MIT', name: 'MIT · postdoc credential', dur: '36m', scope: 'Affiliation', issued: 42, pending: 0, col: 'oklch(0.66 0.13 240)', perms: ['publish under affiliation', 'access compute pool', 'apply for grants'] }, { tag: 'PI · MIT', name: 'MIT · principal investigator', dur: 'no exp.', scope: 'Affiliation', issued: 28, pending: 1, col: 'oklch(0.66 0.13 240)', perms: ['issue postdoc SBTs', 'spend lab treasury', 'sign protocols'] }, { tag: 'GRANTEE · NIH', name: 'NIH · grantee · R01', dur: '60m', scope: 'Funding', issued: 8, pending: 0, col: UB.ok, perms: ['claim NIH disbursements', 'file progress reports'] }, { tag: 'AUDITOR', name: 'Reproducibility auditor', dur: '12m', scope: 'TRID network', issued: 22, pending: 0, col: UB.warn, perms: ['attest replications', 'flag papers'] }, ]; function AdminSBTIssueDapp() { return ( }> Admin · SBT issuance} title="Issue soulbound credentials" sub="Issue role-based SBTs to researchers, reviewers, and editors. Soulbound — non-transferable, but revocable by the issuing org. Every grant produces an immutable on-chain record." actions={<> Audit log Templates · 14 New SBT template } />
{/* Left — issue form + recent grants */}
RECIPIENT · DID OR TRID
chen.lin.eth VERIFIED · κ 0.84
↳ Resolved to MIT postdoc · 22 publications · ORCID linked
TEMPLATE
{SBT_TEMPLATES.slice(0, 4).map((s, i) => (
{s.tag} {i === 1 && }
{s.name}
))}
SCOPE
Domain · neuroscience · glia ▾
EXPIRES
18 months · 12 May 2027
CAPABILITIES GRANTED
{SBT_TEMPLATES[1].perms.map((p, i) => (
{Icon.check} {p}
))}
Save as draft Bulk · CSV Sign & issue
TypeRecipientScopeIssuedStatus
{[ ['REVIEWER', 'chen.lin.eth', 'neuro · glia', '2d', 'ACTIVE', 'ok'], ['POSTDOC · MIT','park.s.eth', 'wet-lab', '4d', 'ACTIVE', 'ok'], ['EDITOR', 't.alvarez.eth', 'all titles', '6d', 'ACTIVE', 'ok'], ['REVIEWER', 'm.tanaka.eth', 'neuro', '8d', 'ACTIVE', 'ok'], ['REVIEWER', 'anon-payload-44…', 'neuro · glia', '12d', 'REVOKED', 'bad'], ['POSTDOC · MIT','j.osei.eth', 'comp · neuro', '14d', 'ACTIVE', 'ok'], ].map((r, i, arr) => (
{r[0]} {r[1]} {r[2]} {r[3]} {r[4]} view
))}
{/* Right — templates and stats */}
{SBT_TEMPLATES.map((s, i, arr) => (
{s.tag} {s.dur}
{s.name}
{s.scope} · {s.issued} issued · {s.pending} pending
edit
))} {[ ['EDITOR', 'a.shah.eth', '2 of 3 sigs', UB.warn], ['PI · MIT','l.alvarez.eth', '1 of 3 sigs', UB.warn], ['REVIEWER','q.park.eth', '3 of 3 sigs · ready', UB.ok], ['REVIEWER','y.tan.eth', '2 of 3 sigs', UB.warn], ].map((p, i, arr) => (
{p[0]}
{p[1]}
{p[2]}
{p[2].includes('ready') ? 'Sign' : 'Review'}
))}
); } function AdminPermissionsDapp() { const roles = ['EDITOR', 'REVIEWER', 'AUTHOR', 'AUDITOR', 'PI']; const perms = [ ['Accept submissions', [1,0,0,0,0]], ['Assign reviewers', [1,0,0,0,0]], ['Sign reviews', [0,1,0,0,0]], ['Release bounties', [1,0,0,0,0]], ['Reject manuscripts', [1,0,0,0,0]], ['Submit revisions', [0,0,1,0,0]], ['Submit a draft', [0,0,1,0,1]], ['Mint patent token', [0,0,1,0,1]], ['Attest replication', [0,0,0,1,0]], ['Flag misconduct', [1,1,0,1,1]], ['Issue postdoc SBT', [0,0,0,0,1]], ['Open editorial appeal', [0,0,1,0,1]], ]; return ( }> Admin · Permissions} title="Roles & permissions" sub="Capability matrix — each row is a verb, each column a role-SBT. Edits are policy proposals; they go through 2-of-3 multisig before deployment." actions={<> Export · JSON Policies · 22 Propose policy change } />
VERB
{roles.map(r => (
{r}
))}
POLICY
{perms.map((row, i) => (
{row[0]}
{row[1].map((v, j) => (
{v ? {Icon.check} : }
))}
P-{14 + i}
))}
{[ ['P-118', 'Allow REVIEWER to release bounties on under-review papers', '2/3'], ['P-117', 'Add new role · DATA-CURATOR', '1/3'], ['P-116', 'Increase reviewer pool fee from 3% → 4%', '3/3 · ready to deploy'], ].map((p, i, arr) => (
{p[0]} {p[2]}
{p[1]}
))}
{[ ['SBT.issue', 'REVIEWER → chen.lin.eth', '14:08'], ['SBT.revoke', 'anon-44 (misconduct)', '11:42'], ['POLICY.sign', 'P-117 · sig 1/3', '08:14'], ['SBT.issue', 'POSTDOC → park.s.eth', 'yesterday'], ['POLICY.deploy', 'P-115', 'yesterday'], ].map((r, i, arr) => (
{r[0]} {r[1]} {r[2]}
))}
{[ ['EDITOR', 14, 248, UB.ink], ['REVIEWER', 184, 248, UB.accent], ['POSTDOC · MIT', 42, 248, 'oklch(0.66 0.13 240)'], ['PI · MIT', 28, 248, 'oklch(0.66 0.13 240)'], ['AUDITOR', 22, 248, UB.warn], ].map((r, i) => (
{r[0]} {r[1]} / {r[2]}
))}
); } window.AdminSBTIssueDapp = AdminSBTIssueDapp; window.AdminPermissionsDapp = AdminPermissionsDapp;