docs: function allowModel (args) {
      // validate args
      this.requireValidArgsModel(args)
      // start new audit
      this.newAudit(args, 'model')
      // get states array from args if any
      var states = args.states
      // set deleted flag if request is for deleted state
      var deleted = states && states.includes('deleted') ? true : false
      // audit deleted state
      this.audit.setRule({
          deleted: deleted,
          allow: !deleted,
      })
      // get access rules
      var rules = this.getRules('model')
      // if no rules exist for model then default to allow
      if (!rules) {
          // default to allow accept for deleted state
          return this.audit.setAllow(deleted ? false : true)
      }
      // get roles from session or use defaults
      var roles = this.getRoles(args.session)
      // default to allow
      var allow = true
      // check global rules
      if (rules.allow) {
          allow = this.isRoleAllowed(allow, roles, rules.allow, false, 'global')
      }
      // get model specific rules
      rules = rules.model && rules.model[args.model]
      // if there are no model specific rules then return current allow
      if (!rules) {
          // return current allow state or false if deleted
          return this.audit.setAllow(deleted ? false : allow)
      }
      // check model specific rule
      if (rules.allow) {
          allow = this.isRoleAllowed(allow, roles, rules.allow, false, 'model')
      }
      // get action specific rules
      rules = rules.action && rules.action[args.action]
      // if there are no action specific rules then return current allow
      if (!rules) {
          // return current allow state or false if deleted
          return this.audit.setAllow(deleted ? false : allow)
      }
      // check action specific rule
      if (rules.allow) {
          allow = this.isRoleAllowed(allow, roles, rules.allow, false, 'action')
      }
      // create action has no ownership scope so return current allow value
      if (args.action === 'create') {
          // return current allow state - there can be no deleted state for
          // create so ignore deleted
          return this.audit.setAllow(allow)
      }
      // the request scope is based on either a specific record instance and
      // whether or not the requesting session owns that instance or on an
      // abstract request for whether or not the session would be allowed to
      // access the given scope
      var scope
      // access is being requested to a specific record
      if (args.accessId) {
          // if session owns record then scope is own
          scope = args.accessId === args.session.accessId ? 'own' : 'any'
      }
      // scope access is being requested in the abstract as opposed to for a
      // specific record
      else if (args.scope) {
          scope = args.scope
      }
      // in strict mode an error would be throw if neither scope or accessId
      // provided for non-create action - in non-strict mode default to any
      else {
          scope = 'any'
      }
      // if access request is for a specific instance with one or more states
      // then current session must be allowed access for ALL of those states
      if (states) {
          // get number of states
          var statesLen  = states.length
          // check acess for each state
          for (var i=0; i < statesLen; i++) {
              var state = states[i]
              // set flag to indicate if the state is deleted
              var deleted = state === 'deleted'
              // deleted is special system state that defaults to deny
              if (deleted) {
                  allow = false
              }
              // get state rules
              var stateRules = rules.state && rules.state[state]
              // there are no rules for this state
              if (!stateRules) {
                  // if there are no rules to override default deny on deleted
                  // then return deny
                  if (deleted) {
                      return this.audit.setAllow(false)
                  }
                  // evaluate next state if any
                  else {
                      continue
                  }
              }
              // get any rules
              var anyRules = stateRules.any && stateRules.any.allow
              // any scope includes own scope so test first
              if (anyRules) {
                  // pass changed flag so that undefined will be returned unless
                  // allow state was changed by matching rule
                  var allowAny = this.isRoleAllowed(allow, roles, anyRules, true, 'state', {
                      allowScope: scope,
                      ruleScope: 'any',
                      state: state,
                  })
                  // rule specifically allows access
                  if (allowAny === true) {
                      // allow on any applies to both any and own no matter what
                      // scope was requested
                      allow = true
                      // evaluate next state if any
                      continue
                  }
                  // rule specifically denies access 
                  else if (allowAny === false) {
                      // if any scope was requested then access is denied
                      if (scope === 'any') {
                          return this.audit.setAllow(false)
                      }
                  }
              }
              // get own rules
              var ownRules = stateRules.own && stateRules.own.allow
              // if access not allowed by any scope then evaluate own scope
              if (ownRules) {
                  // pass changed flag so that undefined will be returned unless
                  // allow state was changed by matching rule
                  var allowOwn = this.isRoleAllowed(allow, roles, ownRules, true, 'state', {
                      allowScope: scope,
                      ruleScope: 'own',
                      state: state,
                  })
                  // rule specifically allows access
                  if (allowOwn === true) {
                      // if the request scope is own then allow
                      if (scope === 'own') {
                          allow = true
                          // evaluate next state
                          continue
                      }
                  }
                  // rule specifically denies access
                  else if (allowOwn === false) {
                      // a deny on own also applies to any
                      return this.audit.setAllow(false)
                  }
              }
              // if any is denied and own not allowed then deny
              if (allowAny === false) {
                  return this.audit.setAllow(false)
              }
              // if state is deleted and no rule specifically allowed then deny
              if (deleted) {
                  return this.audit.setAllow(false)
              }
          }
      }
      // if access determination is not made based on state then evaluate general
      // rules that apply to all states
      var anyRules = rules.any && rules.any.allow
      // evaluate any rules
      if (anyRules) {
          // check access for any role
          var allowAny = this.isRoleAllowed(allow, roles, anyRules, true, 'action', {
              allowScope: scope,
              ruleScope: 'any',
          })
          // if any allowed then access is allowed for both any and own
          if (allowAny === true) {
              return this.audit.setAllow(true)
          }
          else if (allowAny === false) {
              // if any not allowed and any was requested then deny
              if (scope === 'any') {
                  return this.audit.setAllow(false)
              }
              // if own scope requested and any denied then will be denied
              // for own unless specifically allowed
              else {
                  allow = allowAny
              }
          }
      }
      // get own rules
      var ownRules = rules.own && rules.own.allow
      // if there are own rules and scope is own then apply them
      if (ownRules && scope === 'own') {
          allow = this.isRoleAllowed(allow, roles, ownRules, false, 'action', {
              allowScope: scope,
              ruleScope: 'own',
          })
      }
      // return final decision
      return this.audit.setAllow(allow)
  }