{
  "feature": "oauth-provider",
  "version": "1.0.0",
  "description": "OAuth 2.0 authorization server for issuing tokens to third-party applications",
  "category": "integration",
  "tags": [
    "oauth",
    "authorization",
    "tokens",
    "api",
    "security",
    "third-party",
    "integration"
  ],
  "fields": [
    {
      "name": "client_id",
      "type": "text",
      "required": true,
      "label": "Client ID",
      "sensitive": false,
      "validation": [
        {
          "type": "required",
          "message": "Client ID is required"
        },
        {
          "type": "pattern",
          "value": "^[a-zA-Z0-9_-]{16,64}$",
          "message": "Client ID must be 16-64 alphanumeric characters"
        }
      ]
    },
    {
      "name": "client_secret_hash",
      "type": "text",
      "required": false,
      "label": "Client Secret Hash",
      "sensitive": true,
      "validation": [
        {
          "type": "minLength",
          "value": 32,
          "message": "Client secret must be at least 32 characters"
        }
      ]
    },
    {
      "name": "redirect_uris",
      "type": "json",
      "required": true,
      "label": "Redirect URIs",
      "sensitive": false,
      "validation": [
        {
          "type": "required",
          "message": "At least one redirect URI is required"
        }
      ]
    },
    {
      "name": "allowed_scopes",
      "type": "multiselect",
      "required": true,
      "label": "Allowed Scopes",
      "sensitive": false,
      "options": [
        {
          "value": "read",
          "label": "Read"
        },
        {
          "value": "write",
          "label": "Write"
        },
        {
          "value": "profile",
          "label": "Profile"
        },
        {
          "value": "email",
          "label": "Email"
        },
        {
          "value": "openid",
          "label": "OpenID"
        },
        {
          "value": "admin",
          "label": "Admin"
        }
      ],
      "validation": [
        {
          "type": "required",
          "message": "At least one scope is required"
        }
      ]
    },
    {
      "name": "grant_types",
      "type": "multiselect",
      "required": true,
      "label": "Grant Types",
      "sensitive": false,
      "options": [
        {
          "value": "authorization_code",
          "label": "Authorization Code"
        },
        {
          "value": "client_credentials",
          "label": "Client Credentials"
        },
        {
          "value": "refresh_token",
          "label": "Refresh Token"
        }
      ],
      "validation": [
        {
          "type": "required",
          "message": "At least one grant type is required"
        }
      ]
    },
    {
      "name": "app_name",
      "type": "text",
      "required": true,
      "label": "Application Name",
      "sensitive": false,
      "validation": [
        {
          "type": "required",
          "message": "Application name is required"
        },
        {
          "type": "minLength",
          "value": 2,
          "message": "Application name must be at least 2 characters"
        },
        {
          "type": "maxLength",
          "value": 100,
          "message": "Application name must be less than 100 characters"
        }
      ]
    },
    {
      "name": "app_logo",
      "type": "url",
      "required": false,
      "label": "Application Logo URL",
      "sensitive": false,
      "validation": [
        {
          "type": "url",
          "message": "Please enter a valid URL for the application logo"
        }
      ]
    }
  ],
  "rules": {
    "authorization_code": {
      "code_expiry_seconds": 600,
      "code_length": 32,
      "single_use": true,
      "pkce": {
        "required_for_public_clients": true,
        "challenge_methods": [
          "S256"
        ]
      }
    },
    "tokens": {
      "access_token": {
        "format": "jwt",
        "expiry_seconds": 3600,
        "signing_algorithm": "RS256"
      },
      "refresh_token": {
        "expiry_days": 30,
        "rotate_on_use": true,
        "revoke_family_on_reuse": true
      },
      "token_length": 64
    },
    "client_registration": {
      "secret_hashing": "bcrypt",
      "secret_display": "once",
      "require_https_redirect": true,
      "localhost_exception": true
    },
    "consent": {
      "show_scopes": true,
      "remember_consent": true,
      "consent_expiry_days": 90
    },
    "rate_limit": {
      "token_endpoint": {
        "window_seconds": 60,
        "max_requests": 30,
        "scope": "per_client"
      },
      "authorize_endpoint": {
        "window_seconds": 60,
        "max_requests": 20,
        "scope": "per_user"
      }
    }
  },
  "outcomes": {
    "rate_limited": {
      "priority": 1,
      "error": "OAUTH_RATE_LIMITED",
      "given": [
        {
          "field": "request_count",
          "source": "computed",
          "operator": "gt",
          "value": 30,
          "description": "More than 30 token requests per minute from this client"
        }
      ],
      "result": "return 429 with \"Too many requests. Please slow down.\""
    },
    "invalid_client": {
      "priority": 2,
      "error": "OAUTH_INVALID_CLIENT",
      "given": [
        {
          "field": "client_id",
          "source": "input",
          "operator": "not_exists",
          "description": "Client ID not found in registered applications"
        }
      ],
      "result": "return 401 with \"Invalid client credentials\""
    },
    "invalid_redirect_uri": {
      "priority": 3,
      "error": "OAUTH_INVALID_REDIRECT",
      "given": [
        {
          "field": "redirect_uri",
          "source": "input",
          "operator": "not_in",
          "value": "registered_redirect_uris",
          "description": "Redirect URI does not match any registered URI for this client"
        }
      ],
      "result": "show error page (NEVER redirect to unregistered URI)"
    },
    "pkce_required": {
      "priority": 4,
      "error": "OAUTH_PKCE_REQUIRED",
      "given": [
        {
          "field": "client_type",
          "source": "db",
          "operator": "eq",
          "value": "public",
          "description": "Client is a public application (no secret)"
        },
        {
          "field": "code_challenge",
          "source": "input",
          "operator": "not_exists",
          "description": "PKCE code challenge not provided"
        }
      ],
      "result": "return 400 with \"PKCE is required for public clients\""
    },
    "authorization_code_expired": {
      "priority": 5,
      "error": "OAUTH_CODE_EXPIRED",
      "given": [
        {
          "field": "authorization_code",
          "source": "db",
          "operator": "exists",
          "description": "Code exists in database"
        },
        {
          "field": "code_created_at",
          "source": "db",
          "operator": "lt",
          "value": "now - 10m",
          "description": "Code was issued more than 10 minutes ago"
        }
      ],
      "then": [
        {
          "action": "delete_record",
          "type": "authorization_code",
          "target": "authorization_code",
          "description": "Remove expired code"
        }
      ],
      "result": "return 400 with \"Authorization code has expired\""
    },
    "refresh_token_reuse_detected": {
      "priority": 6,
      "error": "OAUTH_TOKEN_REUSE",
      "transaction": true,
      "given": [
        {
          "field": "refresh_token",
          "source": "input",
          "operator": "exists",
          "description": "Refresh token provided"
        },
        {
          "field": "refresh_token_used",
          "source": "db",
          "operator": "eq",
          "value": true,
          "description": "This refresh token has already been used (possible theft)"
        }
      ],
      "then": [
        {
          "action": "invalidate",
          "target": "token_family",
          "description": "Revoke all tokens in this family — potential compromise"
        },
        {
          "action": "emit_event",
          "event": "oauth.token_reuse_detected",
          "payload": [
            "client_id",
            "user_id",
            "token_family_id",
            "timestamp",
            "ip_address"
          ]
        }
      ],
      "result": "return 401 and revoke all tokens in the family"
    },
    "client_registered": {
      "priority": 7,
      "transaction": true,
      "given": [
        {
          "field": "app_name",
          "source": "input",
          "operator": "exists",
          "description": "Application name provided"
        },
        {
          "field": "redirect_uris",
          "source": "input",
          "operator": "exists",
          "description": "At least one redirect URI provided"
        },
        {
          "field": "grant_types",
          "source": "input",
          "operator": "exists",
          "description": "At least one grant type selected"
        }
      ],
      "then": [
        {
          "action": "create_record",
          "type": "oauth_client",
          "target": "client",
          "description": "Create client with generated client_id and hashed secret"
        },
        {
          "action": "emit_event",
          "event": "oauth.client_registered",
          "payload": [
            "client_id",
            "app_name",
            "allowed_scopes",
            "grant_types",
            "timestamp"
          ]
        }
      ],
      "result": "return client_id and client_secret (secret shown once only)"
    },
    "consent_granted": {
      "priority": 8,
      "transaction": true,
      "given": [
        {
          "field": "user_consent",
          "source": "input",
          "operator": "eq",
          "value": true,
          "description": "User approved the authorization request"
        },
        {
          "field": "client_id",
          "source": "db",
          "operator": "exists",
          "description": "Client is registered and active"
        }
      ],
      "then": [
        {
          "action": "create_record",
          "type": "authorization_code",
          "target": "authorization_code",
          "description": "Generate single-use authorization code (10-min expiry)"
        },
        {
          "action": "emit_event",
          "event": "oauth.authorized",
          "payload": [
            "client_id",
            "user_id",
            "scopes",
            "timestamp"
          ]
        }
      ],
      "result": "redirect to redirect_uri with authorization code"
    },
    "token_issued": {
      "priority": 9,
      "transaction": true,
      "given": [
        {
          "field": "authorization_code",
          "source": "input",
          "operator": "exists",
          "description": "Valid authorization code or client credentials provided"
        },
        {
          "field": "client_id",
          "source": "db",
          "operator": "exists",
          "description": "Client is registered and active"
        }
      ],
      "then": [
        {
          "action": "create_record",
          "type": "access_token",
          "target": "access_token",
          "description": "Generate JWT access token (1-hour expiry)"
        },
        {
          "action": "create_record",
          "type": "refresh_token",
          "target": "refresh_token",
          "description": "Generate refresh token (30-day expiry)"
        },
        {
          "action": "delete_record",
          "type": "authorization_code",
          "target": "authorization_code",
          "description": "Consume the authorization code (single use)"
        },
        {
          "action": "emit_event",
          "event": "oauth.token_issued",
          "payload": [
            "client_id",
            "user_id",
            "scopes",
            "token_type",
            "timestamp"
          ]
        }
      ],
      "result": "return access_token, refresh_token, token_type, and expires_in"
    },
    "token_revoked": {
      "priority": 10,
      "transaction": true,
      "given": [
        {
          "field": "token",
          "source": "input",
          "operator": "exists",
          "description": "Token provided for revocation"
        },
        {
          "field": "client_id",
          "source": "input",
          "operator": "exists",
          "description": "Client requesting revocation is authenticated"
        }
      ],
      "then": [
        {
          "action": "invalidate",
          "target": "token",
          "description": "Mark token as revoked"
        },
        {
          "action": "emit_event",
          "event": "oauth.token_revoked",
          "payload": [
            "client_id",
            "user_id",
            "token_type",
            "timestamp"
          ]
        }
      ],
      "result": "return 200 OK (always succeed — RFC 7009)"
    }
  },
  "errors": [
    {
      "code": "OAUTH_INVALID_CLIENT",
      "status": 401,
      "message": "Invalid client credentials",
      "retry": false
    },
    {
      "code": "OAUTH_INVALID_REDIRECT",
      "status": 400,
      "message": "Invalid redirect URI",
      "retry": false
    },
    {
      "code": "OAUTH_PKCE_REQUIRED",
      "status": 400,
      "message": "PKCE code challenge is required for public clients",
      "retry": true
    },
    {
      "code": "OAUTH_CODE_EXPIRED",
      "status": 400,
      "message": "Authorization code has expired. Please try again.",
      "retry": true
    },
    {
      "code": "OAUTH_TOKEN_REUSE",
      "status": 401,
      "message": "Token has been revoked for security reasons",
      "retry": false
    },
    {
      "code": "OAUTH_RATE_LIMITED",
      "status": 429,
      "message": "Too many requests. Please slow down.",
      "retry": true
    },
    {
      "code": "OAUTH_INVALID_SCOPE",
      "status": 400,
      "message": "One or more requested scopes are not allowed",
      "retry": true
    },
    {
      "code": "OAUTH_CONSENT_DENIED",
      "status": 403,
      "message": "User denied the authorization request",
      "retry": false
    }
  ],
  "events": [
    {
      "name": "oauth.client_registered",
      "description": "New OAuth client application registered",
      "payload": [
        "client_id",
        "app_name",
        "allowed_scopes",
        "grant_types",
        "timestamp"
      ]
    },
    {
      "name": "oauth.authorized",
      "description": "User granted authorization to a client application",
      "payload": [
        "client_id",
        "user_id",
        "scopes",
        "timestamp"
      ]
    },
    {
      "name": "oauth.token_issued",
      "description": "Access and refresh tokens issued to a client",
      "payload": [
        "client_id",
        "user_id",
        "scopes",
        "token_type",
        "timestamp"
      ]
    },
    {
      "name": "oauth.token_revoked",
      "description": "Token revoked by client or user",
      "payload": [
        "client_id",
        "user_id",
        "token_type",
        "timestamp"
      ]
    },
    {
      "name": "oauth.token_reuse_detected",
      "description": "Refresh token reuse detected — possible token theft",
      "payload": [
        "client_id",
        "user_id",
        "token_family_id",
        "timestamp",
        "ip_address"
      ]
    },
    {
      "name": "oauth.consent_revoked",
      "description": "User revoked consent for a client application",
      "payload": [
        "client_id",
        "user_id",
        "timestamp"
      ]
    }
  ],
  "related": [
    {
      "feature": "login",
      "type": "required",
      "reason": "Users must authenticate before authorizing third-party apps"
    },
    {
      "feature": "api-gateway",
      "type": "recommended",
      "reason": "Gateway validates access tokens on API requests"
    },
    {
      "feature": "webhook-ingestion",
      "type": "optional",
      "reason": "Third-party apps may register webhooks after authorization"
    }
  ],
  "agi": {
    "goals": [
      {
        "id": "reliable_oauth_provider",
        "description": "OAuth 2.0 authorization server for issuing tokens to third-party applications",
        "success_metrics": [
          {
            "metric": "success_rate",
            "target": ">= 99.5%",
            "measurement": "Successful operations divided by total attempts"
          },
          {
            "metric": "error_recovery_rate",
            "target": ">= 95%",
            "measurement": "Errors that auto-recover without manual intervention"
          }
        ],
        "constraints": [
          {
            "type": "availability",
            "description": "Must degrade gracefully when dependencies are unavailable",
            "negotiable": false
          },
          {
            "type": "security",
            "description": "Sensitive fields must be encrypted at rest and never logged in plaintext",
            "negotiable": false
          }
        ]
      }
    ],
    "autonomy": {
      "level": "supervised",
      "escalation_triggers": [
        "error_rate > 5"
      ]
    },
    "safety": {
      "action_permissions": [
        {
          "action": "rate_limited",
          "permission": "autonomous"
        },
        {
          "action": "invalid_client",
          "permission": "autonomous"
        },
        {
          "action": "invalid_redirect_uri",
          "permission": "autonomous"
        },
        {
          "action": "pkce_required",
          "permission": "autonomous"
        },
        {
          "action": "authorization_code_expired",
          "permission": "autonomous"
        },
        {
          "action": "refresh_token_reuse_detected",
          "permission": "autonomous"
        },
        {
          "action": "client_registered",
          "permission": "autonomous"
        },
        {
          "action": "consent_granted",
          "permission": "autonomous"
        },
        {
          "action": "token_issued",
          "permission": "autonomous"
        },
        {
          "action": "token_revoked",
          "permission": "human_required"
        }
      ]
    },
    "tradeoffs": [
      {
        "prefer": "reliability",
        "over": "throughput",
        "reason": "integration failures can cascade across systems"
      }
    ],
    "verification": {
      "invariants": [
        "sensitive fields are never logged in plaintext",
        "all data access is authenticated and authorized",
        "error messages never expose internal system details"
      ]
    },
    "coordination": {
      "protocol": "request_response",
      "consumes": [
        {
          "capability": "login",
          "from": "login",
          "fallback": "degrade"
        }
      ]
    }
  }
}