caffeinelabs/skills

extension-user-approval

Approval-based user management.

All-time #1007 Trending #728 Hot #3540 First seen Apr 4, 2026
8-week activity · all time api

Installation

$ npx skills add caffeinelabs/skills --skill extension-user-approval

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Security audits

Partner security reviews for this skill.

agent-trust-hub Reviewed

Analyzed Apr 21, 2026

snyk Reviewed

Analyzed Apr 21, 2026

socket Score 0.9000 · 0 alerts

Analyzed Apr 21, 2026

  • license 1
  • maintenance 1
  • quality 0.9
  • supply chain 1
  • vulnerability 1

0 alerts

Also in this package

Other skills from caffeinelabs/skills · top by installs.

npx skills add caffeinelabs/skills

Browse all from caffeinelabs/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 6
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.1

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,370 B
  • docs SUMMARY.md 59 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 18,700 installs

SKILL.md

User Approval

User approval extension for Caffeine AI.

Overview

This skill adds approval-based user management. Users request access; admins approve or reject. Approved users gain access to protected features.

Prerequisite: You must follow [extension-authorization](../extension-authorization/SKILL.md) first, as this integration depends on it.

Backend

Module API

The prefabricated module mo:caffeineai-user-approval/approval provides low-level approval state management. Do not modify it.

```mo:caffeineai-user-approval/approval import AccessControl "mo:caffeineai-authorization/access-control";

module { public type ApprovalStatus = { #approved; #rejected; #pending; };

public type UserApprovalState = { / internal state / };

public func initState(accessControlState: AccessControl.AccessControlState) : UserApprovalState;

public func isApproved(state : UserApprovalState, caller : Principal) : Bool; public func requestApproval(state : UserApprovalState, caller : Principal); public func setApproval(state : UserApprovalState, user : Principal, approval : ApprovalStatus);

public type UserApprovalInfo = { principal : Principal; status : ApprovalStatus; };

public func listApprovals(state : UserApprovalState) : [UserApprovalInfo]; }


## Setup in main.mo

`include MixinUserApproval(accessControlState, approvalState)` MUST be placed in `main.mo`, not in a custom mixin file. Declare `approvalState` at actor top level and pass it into the mixin. The mixin provides these public endpoints automatically:

- `isCallerApproved()`
- `requestApproval()`
- `setApproval(user, status)`
- `listApprovals()`

Keep `approvalState` in scope for custom approval guards in app-specific endpoints.

Do NOT redeclare any of the mixin-provided functions.

```motoko filepath=src/backend/main.mo
import AccessControl "mo:caffeineai-authorization/access-control";
import MixinAuthorization "mo:caffeineai-authorization/MixinAuthorization";
import MixinUserApproval "mo:caffeineai-user-approval/MixinUserApproval";
import UserApproval "mo:caffeineai-user-approval/approval";
import Runtime "mo:core/Runtime";

actor {
    let accessControlState : AccessControl.AccessControlState;
    include MixinAuthorization(accessControlState, null);
    let approvalState : UserApproval.UserApprovalState;
    include MixinUserApproval(accessControlState, approvalState);

    // Example custom endpoint with an approval guard:
    // public shared ({ caller }) func protectedFeature() : async () {
    //     if (not (UserApproval.isApproved(approvalState, caller) or AccessControl.hasPermission(accessControlState, caller, #admin))) {
    //         Runtime.trap("Unauthorized: Only approved users can perform this action");
    //     };
    // };
};

The migration chain head — UserApproval.initState depends on the access-control state, so compute it in order inside the migration body:

```motoko filepath=src/backend/migrations/00000000_000000.mo import AccessControl "mo:caffeineai-authorization/access-control"; import UserApproval "mo:caffeineai-user-approval/approval";

module { type NewActor = { accessControlState : AccessControl.AccessControlState; approvalState : UserApproval.UserApprovalState; };

public func migration(_old : {}) : NewActor { let accessControlState = AccessControl.initState(); { accessControlState; approvalState = UserApproval.initState(accessControlState); }; }; };


On `initState`, existing admins are automatically approved. All other users are pending.

IMPORTANT: Apply the right authorization and/or approval check to each custom public function.

# Frontend

Approval-based user management:

# User Approval Flow
- Check approval status (`isCallerApproved`)
- If not approved, show option to request approval (`requestApproval`)
- Block access to main features for non-approved users
- Admins have access to all features of the application
- Display approval status clearly in the UI

# Admin Dashboard
For admin users, provide a dashboard to:
- List all users with their approval status (`listApprovals`)
- Approve or reject users (`setApproval`)
- View and assign user roles (using `getCallerUserRole` and `assignCallerUserRole`)

# Backend Integration
The backend already implements the following functionality.
The full interface can be found in <backend-interface>

// Check if current user is approved, admins are always approved
isCallerApproved(): Promise<boolean>;

// Submit approval request
requestApproval(): Promise<void>;

// Get all users and their approval status (admin only)
listApprovals(): Promise<Array<UserApprovalInfo>>;

// Approve or reject a user (admin only)
setApproval(user: Principal, status: ApprovalStatus): Promise<void>;

// Assign a role to a user (admin only)
assignCallerUserRole(user: Principal, role: UserRole): Promise<void>;

// Get current role for a specific user
getCallerUserRole(): Promise<UserRole>;