Organization and User Management

Overview

The Agent Passport Registry supports multi-tenant architecture with organizations and users. This system allows for proper ownership, access control, and assurance verification across different entities.

Core Concepts

Organizations

  • Multi-tenant entities that can own multiple agent passports
  • Member management with role-based access control
  • Assurance levels that apply to all owned passports
  • Domain verification for enhanced trust

Users

  • Individual entities that can own agent passports
  • Assurance verification through various methods
  • Organization membership for collaborative management

Ownership Model

  • Passports belong to owners (organizations or users)
  • Inherited assurance levels from owner to passport
  • Role-based permissions for organization members
  • Verifiable Attestation for all ownership changes

API Endpoints

Organizations

Create Organization

POST /api/orgs
Content-Type: application/json

{
  "name": "Acme Corporation",
  "domain": "acme.com",
  "contact_email": "[email protected]"
}

Response:

{
  "org_id": "ap_org_12345678",
  "name": "Acme Corporation",
  "domain": "acme.com",
  "contact_email": "[email protected]",
  "members": [],
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z",
  "assurance_level": "L0"
}

Get Organization Members

GET /api/orgs/{org_id}/members

Response:

{
  "org_id": "ap_org_12345678",
  "name": "Acme Corporation",
  "members": [
    {
      "user_id": "ap_user_87654321",
      "role": "admin",
      "added_at": "2024-01-15T10:30:00Z"
    },
    {
      "user_id": "ap_user_11111111",
      "role": "member",
      "added_at": "2024-01-16T09:15:00Z"
    }
  ]
}

Add Organization Member

POST /api/orgs/{org_id}/members
Content-Type: application/json

{
  "user_id": "ap_user_87654321",
  "role": "admin"
}

Users

Create User

POST /api/users
Content-Type: application/json

{
  "email": "[email protected]",
  "display_name": "John Doe"
}

Response:

{
  "user_id": "ap_user_87654321",
  "email": "[email protected]",
  "display_name": "John Doe",
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z",
  "assurance_level": "L0"
}

Owner Passports

Get Owner's Passports

GET /api/owners/{owner_id}/passports

Response:

{
  "owner_id": "ap_org_12345678",
  "owner_type": "org",
  "owner_display": "Acme Corporation",
  "passports": [
    {
      "agent_id": "ap_a2d10232c6534523812423eec8a1425c45678",
      "name": "Customer Support AI",
      "status": "active",
      "created_at": "2024-01-15T10:30:00Z"
    }
  ]
}

Assurance Levels

Level Definitions

Level Name Description Verification Method
L0 Self Self-declared None
L1 Email Email verification Email confirmation
L2 GitHub GitHub account verification OAuth
L3 Domain Domain ownership verification DNS/SSL
L4KYC KYC Know Your Customer Identity verification
L4FIN Financial Financial institution verification Banking data

Assurance Inheritance

Passports inherit assurance levels from their owners:

// Organization with L2 assurance
const org = {
  org_id: "ap_org_12345678",
  assurance_level: "L2",
  assurance_method: "github"
};

// All passports owned by this org inherit L2 assurance
const passport = {
  agent_id: "ap_a2d10232c6534523812423eec8a1425c45678",
  owner_id: "ap_org_12345678",
  assurance_level: "L2", // Inherited from org
  assurance_method: "github"
};

Implementation Examples

Creating an Organization with Members

import { AgentPassportClient } from '@agent-passport/sdk';

const client = new AgentPassportClient({
  baseUrl: 'https://api.aport.io',
  adminToken: process.env.ADMIN_TOKEN
});

// 1. Create organization
const org = await client.createOrganization({
  name: 'Acme Corporation',
  domain: 'acme.com',
  contact_email: '[email protected]'
});

// 2. Create users
const admin = await client.createUser({
  email: '[email protected]',
  display_name: 'Admin User'
});

const member = await client.createUser({
  email: '[email protected]',
  display_name: 'Member User'
});

// 3. Add members to organization
await client.addOrgMember(org.org_id, {
  user_id: admin.user_id,
  role: 'admin'
});

await client.addOrgMember(org.org_id, {
  user_id: member.user_id,
  role: 'member'
});

// 4. Create passport owned by organization
const passport = await client.createPassport({
  name: 'Customer Support AI',
  owner_id: org.org_id,
  controller_type: 'org',
  role: 'Customer Support Agent',
  description: 'AI agent for customer support',
  capabilities: [
    { id: 'messaging.send' },
    { id: 'crm.update' }
  ],
  limits: {
    max_actions_per_min: 100,
    allow_pii: false
  },
  regions: ['US-CA', 'US-NY'],
  status: 'active',
  contact: '[email protected]'
});

Checking Ownership and Permissions

// Verify agent and check ownership
const passport = await client.verifyAgent('ap_a2d10232c6534523812423eec8a1425c45678');

if (passport.owner_type === 'org') {
  console.log(`Agent owned by organization: ${passport.owner_display}`);
  
  // Check if user is member of owning organization
  const orgMembers = await client.getOrgMembers(passport.owner_id);
  const isMember = orgMembers.members.some(
    member => member.user_id === currentUserId
  );
  
  if (!isMember) {
    throw new Error('User is not a member of the owning organization');
  }
}

Assurance Level Validation

// Check if agent meets required assurance level
function validateAssuranceLevel(passport: PassportData, requiredLevel: string) {
  const levelHierarchy = ['L0', 'L1', 'L2', 'L3', 'L4KYC', 'L4FIN'];
  const currentLevelIndex = levelHierarchy.indexOf(passport.assurance_level);
  const requiredLevelIndex = levelHierarchy.indexOf(requiredLevel);
  
  if (currentLevelIndex < requiredLevelIndex) {
    throw new Error(
      `Agent assurance level ${passport.assurance_level} is insufficient. Required: ${requiredLevel}`
    );
  }
}

// Usage
const passport = await client.verifyAgent('ap_a2d10232c6534523812423eec8a1425c45678');
validateAssuranceLevel(passport, 'L2'); // Requires L2 or higher

Role-Based Access Control

Organization Roles

Role Permissions
admin Create/update/delete passports, manage members, view all data
member View passports, limited update permissions

Permission Checking

// Check if user can perform action on passport
async function checkPermission(
  userId: string, 
  passportId: string, 
  action: string
): Promise<boolean> {
  const passport = await client.verifyAgent(passportId);
  
  // Check if user owns the passport directly
  if (passport.owner_type === 'user' && passport.owner_id === userId) {
    return true;
  }
  
  // Check if user is admin of owning organization
  if (passport.owner_type === 'org') {
    const orgMembers = await client.getOrgMembers(passport.owner_id);
    const userMember = orgMembers.members.find(
      member => member.user_id === userId
    );
    
    if (userMember?.role === 'admin') {
      return true;
    }
  }
  
  return false;
}

// Usage
const canUpdate = await checkPermission(userId, passportId, 'update');
if (!canUpdate) {
  throw new Error('Insufficient permissions to update passport');
}

Domain Verification

Setting Up Domain Verification

// 1. Create organization with domain
const org = await client.createOrganization({
  name: 'Acme Corporation',
  domain: 'acme.com',
  contact_email: '[email protected]'
});

// 2. Organization admin adds DNS record
// TXT record: agent-passport-verification=ap_org_12345678

// 3. Verify domain ownership
const verification = await client.verifyDomain(org.org_id);
if (verification.verified) {
  // Update organization assurance level
  await client.updateOrganization(org.org_id, {
    assurance_level: 'L3',
    assurance_method: 'domain',
    assurance_verified_at: new Date().toISOString()
  });
}

Audit and Compliance

Ownership Changes

All ownership changes are logged:

{
  "event": "passport_ownership_changed",
  "timestamp": "2024-01-15T10:30:00Z",
  "passport_id": "ap_a2d10232c6534523812423eec8a1425c45678",
  "previous_owner": "ap_user_11111111",
  "new_owner": "ap_org_12345678",
  "changed_by": "ap_user_87654321",
  "reason": "Organization acquisition"
}

Member Management

Organization membership changes are tracked:

{
  "event": "org_member_added",
  "timestamp": "2024-01-15T10:30:00Z",
  "org_id": "ap_org_12345678",
  "user_id": "ap_user_87654321",
  "role": "admin",
  "added_by": "ap_user_11111111"
}

Best Practices

1. Organization Structure

  • Use organizations for business entities
  • Use users for individual developers
  • Assign appropriate roles based on responsibilities
  • Regularly audit membership and remove inactive users

2. Assurance Levels

  • Start with L0 for development
  • Upgrade to L1/L2 for production
  • Use L3+ for high-value operations
  • Document verification methods used

3. Security

  • Rotate admin tokens regularly
  • Monitor ownership changes closely
  • Use domain verification when possible
  • Implement proper access controls

4. Monitoring

// Monitor organization activity
const orgActivity = await client.getOrgActivity(orgId, {
  startDate: '2024-01-01',
  endDate: '2024-01-31'
});

console.log(`Organization created ${orgActivity.passportsCreated} passports`);
console.log(`Members performed ${orgActivity.actionsPerformed} actions`);

Troubleshooting

Common Issues

  1. User Not Found
    • Ensure user exists before adding to organization
    • Check user ID format (ap_user_*)

Debug Commands

# Check organization details
curl -H "Authorization: Bearer $ADMIN_TOKEN" \
  "https://api.aport.io/api/orgs/ap_org_12345678"

# List organization members
curl -H "Authorization: Bearer $ADMIN_TOKEN" \
  "https://api.aport.io/api/orgs/ap_org_12345678/members"

# Get owner's passports
curl -H "Authorization: Bearer $ADMIN_TOKEN" \
  "https://api.aport.io/api/owners/ap_org_12345678/passports"

Future Enhancements

  • Team Management: Sub-teams within organizations
  • Custom Roles: Organization-specific role definitions
  • Bulk Operations: Manage multiple passports at once
  • Integration APIs: Connect with external identity providers
  • Advanced Permissions: Granular permission system