Chapter 8. Architecture

RT is built like a layer cake. Each layer has no innate knowledge of what sits on top of it.[11] This chapter takes a tour of RT’s structure and then a more detailed look at RT’s database and object models.

Before we get into the nitty gritty details of how RT is put together, let’s take a quick look at the RT layer cake and see what we get out of each layer. Figure 8-1 shows the layers and how they fit together.

SQL Database

Behind everything that RT does, there’s an SQL database. This database stores all of RT’s data and metadata. Some SQL databases provide their own procedural languages that allow developers to implement large applications entirely inside the database. This has the disadvantage of tying an application tightly to a specific database engine, such as MySQL or Oracle. RT takes a different tack, using the database as a datastore. Because of this, RT is able to run on top of a number of different database engines, each of which has different strengths. RT works to make sure that data stored in SQL is relatively easy to query using other tools, though we strongly recommend that you not alter the database by hand.

DBI

Perl’s DBI is the standard SQL Database Interface for Perl programs. It defines an interface that various and sundry database drivers (DBDs) implement in a largely consistent manner. In addition to MySQL, Postgres, and Oracle, you’ll find DBD modules that let you talk to LDAP, flat text files, and even Google as if

they were SQL databases. If you come from the Java world, you can think of DBI as Perl’s equivalent to JDBC.

DBIx::SearchBuilder

DBIx::SearchBuilder is the secret sauce that lets an object-oriented application like RT talk to a table-oriented relational database. SearchBuilder presents a simple object-oriented API to Perl programs and translates those API calls into SQL statements tuned for the specific database. A row from any given database table can be accessed via a subclass of DBIx::SearchBuilder::Record. To search for and work with sets of records all at once, RT provides a Collection class for each database table, which is a subclass of DBIx::SearchBuilder itself.

RT application platform libraries

Until now, we’ve only talked about RT as a ticketing system. Once you start looking at the architecture and APIs, you’ll quickly discover that there’s a whole application platform under the hood in addition to the ticketing system.

RT’s application platform libraries are the guts of RT. They provide database connectivity, logging infrastructure, users, groups, access control, links, and a few other bits. While the ticketing system uses the RT application platform, it’s not the only application that does so. RTFM[12] is a knowledge-base tool that uses the RT application platform to implement an entirely different application.

RT ticketing system libraries

RT’s ticketing system libraries use the RT application platform as a base to provide tickets, transactions, attachments, custom fields, and queues. The ticketing system defines groups and access control rights and a type of link that teaches the application platform how to deal with links between ticket objects.

Mason handler

The Mason handler is one of many possible applications that runs on top of the RT Core libraries. It provides a wrapper around the Mason templating system.[13] Mason is conceptually similar to ASP, PHP, or JSP, but for Perl.

RT comes with two main sets of Mason templates out of the box: user interface templates, which are designed for end users to interact with their browsers, and REST templates, which are designed to be easy for other software to interact with. As of version 3.4, the REST templates are designed to present information in RFC822 format, which anything can parse.

Right now, the Mason templates for the RT application platform and RT ticketing system are very tightly integrated, but moving forward, the templates are changing to improve how they are broken out.

HTTP Clients

RT has three HTTP clients: a web browser, the email gateway, and the command-line interface. Most users interact with RT using their browsers. RT’s email gateway is a tiny Perl script that your mail server runs every time an email message destined for RT comes in. The email gateway, in turn, dispatches the message to your RT server over HTTP or HTTPS. It waits around for the RT server to confirm receipt of the message and then exits.

RT’s command-line interface is a web browser. But not like you’re imagining. The CLI communicates with RT over the web, using the same authentication system as the rest of RT, so you can use it from anywhere that you can use RT’s web interface. Like any other web client, it uses GET and POST to download from and upload to your RT server.

In the next sections and chapters, we’ll dive into RT’s internals to get a better sense of how RT is put together. As you’re reading, it may be useful to refer to RT’s source code. All the paths we talk about will be relative to your RT installation path. By default, RT is installed into /opt/rt3, but you or your system administrator may have installed it elsewhere. Some flavors of Unix—such as Debian Linux and FreeBSD—package RT and install its code and configuration files into locations that fit system policy.

lib/

Standard Perl libraries live in lib/. RT.pm contains RT’s basic initialization routines. It reads RT’s configuration file, sets up connections to the database and logging system, and loads system-internal objects.

RT’s other Perl libraries live inside the RT/ subdirectory of lib. To add RT-specific behavior, both RT/Record.pm and RT/SearchBuilder.pm subclass DBIx::SearchBuilder and DBIx::SearchBuilder::Record::Cachable, respectively. RT/Interface/Web.pm handles many of the details of initialization of RT’s Mason handler and provides a number of helper functions for the Mason Interface. RT/Interface/REST.pm provides helper functions for RT’s REST-based web services framework. RT/Interface/Email.pm provides routines for handling incoming email messages and converting them into RT’s preferred formats and encodings.

Standard lexicon files live in lib/RT/I18N/. Lexicon files contain translations of RT into languages other than English. They’re in the extended GNU Gettext format that Locale::Maketext::Lexicon supports.

share/html/

Standard Mason components live in share/html/.

bin/

Executable RT programs live in bin/. rt is the RT command-line tool. It talks to your RT server via HTTP or HTTPS. You can copy it to other servers or your desktop to run. rt-crontool lets you script actions like escalations or reminder email using your system’s cron facility. You can use rt-mailgate to funnel incoming email into RT. Like rt, it can run on any server (such as your mail server) that has Perl installed. webmux.pl is the mod_perl handler for RT. mason_handler.fcgi is the FastCGI handler for RT. standalone_httpd is a full RT webserver in a single tiny Perl script. It’s useful for testing out RT or for your development environment. Because it’s a non-forking, non-threaded Perl script, it might not stand up to full-scale production use.

sbin/

RT system programs live in sbin/. These tools are used during initial installation of RT. They should almost never be needed during regular use of RT. rt-test-dependencies is a tool to help verify that you’ve installed all the Perl modules RT needs to run and to help you install any that you happen to be missing. rt-setup-database is the RT helper script that sets up a database schema, ACLs, and data for RT or any RT extensions that touch the database.

var/

Mason cache data lives in var/mason_data/. Under some database backends, session data and locks may be stored under var/session_data/. If you are using the SQLite backend, its database is under var/ by default, such as the file var/rt3.

etc/

Configuration files live in etc/. RT_Config.pm lists out all of RT’s default configuration parameters. Database configuration parameters are set automatically by RT’s configure script, but just about everything else is the factory default.

When RT starts up, it looks in RT_Config.pm and then overrides the defaults it finds there with local configuration from RT_SiteConfig.pm. This way, you can add any RT configuration you want to RT_SiteConfig.pm, rather than hand-editing the RT_Config.pm file and merging changes every time you upgrade.

The initial database schema also lives in etc/, in multiple different schema.* files customized for each database platform.

local/

Site-local Perl libraries live in local/lib/. Site-local Mason components live in local/html/. Site-local lexicon files live in local/po/.

Before RT 3.0, RT was language-agnostic. The user interface was in English,[14] and RT didn’t do anything special with the text entered by users. As long as you only used the web interface, it worked OK. Users in Japan could enter text in Japanese. Users in Spain could enter text in Spanish. When RT tried to send mail, the recipient wouldn’t be able to read it, since RT didn’t know enough about the content of the message to correctly label it.

RT 3.0 changed all that. The interface has been fully internationalized,[15] and we’ve standardized on Unicode and the 8-bit UTF-8 encoding. This means that you can use English, Spanish, Russian, Japanese, Korean, and Chinese in the same message, and RT will store and display them just fine.

When a user connects to RT’s web interface, RT tells his browser that it should speak to RT in UTF-8. Because the web came into being after the advent of Unicode, most every web browser knows how to speak UTF-8.

Sadly, the situation isn’t so rosy in the world of email. Every language has its own encoding, sometimes even two or three of them. For email, RT has to do all of the hard work. When it receives an email message, it has a look at the message headers to see if the sender told us what encoding they were using. If the sender didn’t tell RT, it uses the Perl module Encode::Guess to look at the message’s content and guess what the most likely encoding is. Once RT knows what encoding an incoming message is in, it converts the message to UTF-8. When sending messages back out, RT looks at a site’s list of preferred encodings, picks the most apropriate one, and re-encodes the message.

This section takes a tour of RT’s logical model , shown in Figure 8-2. RT maps its logical model closely to its object model , so we’ve condensed the details of the object and logical models throughout the section.

Every RT object has a field called ID. This field is an integer that’s automatically set to a unique value when an object is created and never changes. RT uses these values internally as keys to objects. Additionally, many of RT’s objects have fields called Creator, Created, LastUpdated, and LastUpdatedBy. These fields automatically track the users who created and most recently updated these objects and the times of those actions. For clarity, we’ve skipped over those fields in the schema listings below.

Each of the database tables we discuss here corresponds to two RT objects, a record class and a collection class. The methods for each of these classes are split up into several files; see Overlays in Chapter 10 for more details. Method-level documentation for each class is available in Perl’s perldoc format. Each collection class is named the same as RT’s database table for that sort of object. Each record class is named for the singular version of the collection. So if you’re interested in users, for example, you want to look at both RT::Users and RT::User. By default, the primary file for each of these classes lives in /opt/rt3/lib/RT/.

The documentation in both the record and the collection modules gives an overview of the database schema for the class and provides pointers to other files that contain class methods and documentation:

    perldoc /opt/rt3/lib/RT/User.pm

and

    perldoc /opt/rt3/lib/RT/Users.pm

Each of these files will give you an overview of the database schema for the class, as well as provide pointers to other files that contain class methods and documentation.

In RT, a user is any individual who can perform actions within the system. Any time you create, modify, look at, or delete an object, you need to do it as a user.

Out of the box, RT comes with three special users :

Users have the following fields:

Name

Every user in RT has a Name, which is guaranteed to be unique. While RT doesn’t reference users directly by Name, users authenticate to RT and search for other users by Name.

EmailAddress

A user’s EmailAddress is used by RT to attach incoming email messages to a user account upon receipt. It’s also used by RT to figure out where to send outgoing mail when tickets are updated. No two users may have the same email address, although it’s fine to have many users with no email address.

Password

While RT supports external access control mechanisms, many sites don’t have a universal authentication framework, so RT provides its own password-based system. Internally, RT stores an MD5 hash of a user’s password in the Password field but never exposes it directly to end-users. Unlike most other fields, Password is write-only. RT provides SetPassword and IsPassword methods but not a Password method. RT treats passwords such as *NO-PASSWORD and *LOCK* as locked passwords and never allows password-based access to accounts with such passwords.

Comments

RT is often used in a customer-service scenario, where it’s important to be able to keep notes about users. The Comments field is a scratch-pad about a user, but it isn’t visible to that user unless they’re part of the Privileged group.

Signature

When composing mail from within the web interface, RT automatically will append a user’s Signature to the message.

RealName

In a number of situations, RT will display a user’s RealName, rather than their Name or EmailAddress.

Lang

RT’s web interface provides browser-based language negotiation features, but it’s sometimes useful to override that with a user’s preferred language. The Lang field stores an RFC3066-style language tag.

Gecos

RT provides functionality to allow command-line tools written around the RT framework to map the current Unix username to an RT user’s Gecos field.

NickName, Organization, HomePhone, WorkPhone, MobilePhone, PagerPhone, Address1, Address2, City, State, Zip, Country, FreeformContactInfo

RT provides these fields to allow sites to use it as a contact management system. They’re not used internally.

EmailEncoding, WebEncoding, ExternalContactInfoId, ContactInfoSystem, ExternalAuthId, AuthSystem, Timezone, PGPKey

RT doesn’t currently use these fields.

A collection of users and other groups can be assigned rights, made watchers of tickets, and so on. Groups can contain users and groups. Groups can’t contain themselves.

Groups have the following fields:

Name

Every group in RT has a name, purely for human convenience. Internally, RT doesn’t care about group names.

Description

Likewise, the Description is provided so that users know what a particular group is for.

Domain

Many parts of RT use the groups system for a wide variety of different purposes. Domain is a high level way to mark what type each group is.

ACLEquivalence

Internally, RT’s access control system only grants rights to groups. When first created, every user has an ACL equivalence group created with only that user as a member. Whenever RT’s API is used to grant rights to an individual user, the right is really granted to that user’s ACL equivalence group.

SystemInternal

RT keeps track of certain user attributes with system-wide meta-groups. Upon installation, RT creates three of these SystemInternal metagroups: Everyone, Privileged, and Unprivileged. Every single user is added as a member of the Everyone group and either the Privileged or Unprivileged group. If a user is Unprivileged, they can’t be granted rights directly, and RT’s web frontend automatically shunts them to a restricted self-service frontend upon login.

UserDefined

UserDefined groups are system-wide groups created by local staff. Generally, they’re used as a system managment convenience. Rights are granted to groups, rather than individual users, and groups are made Ccs or AdminCcs of Tickets or Queues. This makes it easier for administrators to track who can perform actions or who will receive email on a specific topic.

Personal

Personal groups are defined by individual users for their own personal use. Currently, they’re used only by the Delegation system to allow users to delegate rights to other users or groups.

RT::System-Role, RT::Queue-Role and RT::Ticket-Role

Role groups are designed to allow administrators to grant rights to a role and configure mailing rules for a role at either the System or Queue level and have that configuration apply to every user who is operating in that role for a given ticket or queue. As of RT 3.0, the possible roles are Requestor, Cc, AdminCc, and Owner.

Type

For ACLEquivalence groups, the group’s type is 'UserEquiv‘.

For SystemInternal groups, the group’s type is one of 'Everyone', 'Privileged', or 'Unprivileged‘.

For each of the role groups, the type is one of Owner, Requestor, Cc, or AdminCc.

For Personal groups, the type is always “” (an empty string).

Instance

For ACLEquivalence and Personal groups, the group’s instance is the user’s ID.

For SystemInternal and UserDefined groups, the group’s instance is always 0.

For RT::Ticket-Role groups, the group’s instance is the Ticket’s ID.

For RT::Queue-Role groups, the group’s instance is the Queue’s ID.

For RT::System-Role groups, the group’s instance is always 1.

A single row in an access control list is an Access Control Entry or ACE. The Access Control List (ACL) table details which rights each Principal has for any ACLed object in RT. ACLed objects include: tickets, queues, and groups.

ACLs have the following fields:

PrincipalType

PrincipalType captures which sort of object a given ACE applies to. For each of the roles—Owner, Requestor, Cc, and AdminCc—the PrincipalType is the name of that role.

For regular groups, the PrincipalType is simply Group.

For an ACE granting rights to a user, the PrincipalType is Group. Behind the scenes, rights are never granted directly to users, but to their ACL equivalence groups.

PrincipalId

PrincipalId is a pointer to the principal to which this ACE applies. In the case of regular groups and role groups, it points to the group in question’s Principal. If the ACE grants rights to a specific user, the PrincipalId points to that user’s ACL equivalence group.

RightName

The RightName is a simple textual identifier for the right being granted. For any object that supports access control, you can get a complete list of what rights it supports with the AvailableRights() method.

ObjectType

Each ACE applies to a specific object. ObjectType is the class of that object. For example, if you granted a right on Queue 1, the class would be RT::Queue.

ObjectId

ObjectId is the ID of the object to which this ACE refers. For example, if you granted a right on Queue 1, the ObjectId would be 1.

DelegatedFrom

RT’s ACL delegation system allows individual users to delegate rights that had been granted to them and automatically removes the delegated rights when the grantor’s rights are revoked. DelegatedFrom is a pointer to the ID of the ACE on which this right is based.

DelegatedBy

DelegatedBy is the Principal ID of the user who delegated this right.

The Links table keeps track of relationships between entities. The object classes wrapping Links have built-in intelligence to do clever things with RT tickets, but you can think of the Links system as a simple store for RDF-style Subject-Predicate-Object triples (Base-Type-Target in RT’s lexicon).[17]

Links have the following fields:

Base

Base is the URI of the left-hand side of this link relation. It can contain any URI. By default, RT ships with classes that can handle http:, https:, file:, ftp: and fsck.com-rt: URIs.

LocalBase

If this Link’s base is a local ticket, LocalBase is a pointer to the ID of that ticket. This field is a convenience that makes it easier for RT to find links related to a particular ticket.

Type

Type describes what sort of relationship the Base has to the Target. Out of the box, RT supports three simple types of relationships:

RefersTo

The Base refers to the Target. This is a simple weak reference that lets you tie related objects together. For example, “The purchase of new servers refers to the estimates we got from these six vendors.”

DependsOn

The Base in some way depends on the Target. In the ticketing system side of RT, we use DependsOn to track cases when one Ticket must be completed before another one can be completed such as “The purchase of new servers depends on budget approval for the server migration project.”

MemberOf

The Target contains the Base. In the ticketing system side of RT, we use MemberOf to track parent-child relationships such as “The purchase of new servers is a member of the server migration project.”

Target

Target is the URI of the right-hand side of this link relation. It can contain any URI.

LocalTarget

If this Link’s target is a local ticket, LocalTarget is a pointer to the ID of that ticket. This field is a convenience that makes it easier for RT to find links related to a particular ticket.

Transactions record everything that happens to a ticket, from its creation through its eventual resolution. Each transaction can have one or more Attachments. Unlike most objects in RT, transactions are immutable once created.

Transactions have the following fields:

ObjectType

ObjectType describes the class of record to which this transaction refers. Most often, you’ll see RT::Ticket here. (In previous versions, RT only tracked transactions on tickets). As of RT 3.4, RT also records changes to RT::User and RT::Group objects.

ObjectId

ObjectId is a pointer to the ID of the record to which this transaction refers.

Type

A transaction’s Type describes what sort of update it is. For most simple updates to individual ticket fields, the type is Set. For adding a comment to a ticket, it’s Comment. For updates to Custom Fields, it’s CustomField.

TimeTaken

For some types of transactions, like Comment and Correspond, users can specify how long they spent on the update. TimeTaken tracks that value in minutes.

Field

For updates that alter a field or custom field, Field tracks what was changed.

OldValue

OldValue tracks what a field was changed from. In the case of deletion, OldValue is the value that was deleted.

NewValue

NewValue tracks what a field was changed to. In the case of a new value being added, NewValue tracks the new value.

Data

Some transactions have a bit more data than can be encapsulated easily in the previous fields. Data stores the subjects of incoming correspondence and occasionally other data.

ReferenceType

Some transactions store changes to custom fields for things like images, files, or large text blocks. When RT records one of those updates as a transaction, it sets ReferenceType to RT::ObjectCustomFieldValue and fills in OldReference and/or NewReference. Because storing two copies of these big objects can bloat the database, RT stores changes to large values like this by reference instead of just copying the values like it does for smaller fields.

NewReference

NewReference contains a pointer to an added value of the type stored in ReferenceType.

OldReference

OldReference contains a pointer to a deleted value of the type stored in ReferenceType.

The Attachment table stores any message body or attachment for a transaction in a structured manner, so MIME email messages can be rebuilt.

Attachments are arbitrarily complex MIME entities that can be tied to tickets using transactions. Every email message that RT associates with a ticket will be stored in the database as one or more attachments. If an attachment is made up of multiple MIME parts, RT will split those parts into a tree of related attachments and store each one in the database.

Attachments have the following fields:

TransactionId

Each Attachment is associated with a Transaction. TransactionId is a reference to the ID of the Transaction associated with this attachment.

Parent

If this attachment is part of a complex MIME structure, Parent points to another Attachment representing the parent MIME section.

MessageId

If an attachment is an email message, MessageId stores its Message-Id: header. In the future, this will make it easier to build message threads.

Subject

If an attachment is an email message, Subject stores its Subject: header.

Filename

If an attachment is a named file, Filename stores what it was called when it was submitted to RT.

ContentType

ContentType stores this attachment’s MIME type.

ContentEncoding

When possible, RT undoes all of the encoding that attachments are wrapped in for transport by email, so it can store them in their raw forms in the database. Some databases, like PostgreSQL and Oracle don’t support binary data in the same sorts of fields that they use to store character data, like the bodies of email messages. On these databases, RT transparently encodes stored attachments into Base64 or QuotedPrintable encoding when stuffing them into the database and transparently undoes it when pulling them back out.

Data about what sort of encoding is used is stored in the ContentEncoding header.

Content

Content is the actual body of the attachment, stored as UTF-8 text, binary data, or encoded data.

Headers

RT stores the attachment’s message headers and MIME headers in the Headers field. RT also stores additional data, including the attachment’s length and original text encoding, if it was converted into UTF-8 by RT.

RT allows sites to track custom metadata per ticket using a facility known as Custom Fields. These custom fields can be applied to tickets globally or per-queue. Custom fields can be of several types: Select from a list, free-form data entry in a text field, free-form data entry in a textarea field (with either plain or wiki text), file upload, and image upload. Additionally, each custom field can accept either a single value or multiple values. For all intents and purposes, users interacting with RT can treat custom fields the same as regular fields like Status and Subject. Users can see, edit, and search on custom field values through the same interfaces that they use to work with RT. At the API level, however, they’re treated somewhat differently.

CustomFields have the following fields:

Name

Each custom field has a name displayed to users editing or viewing it. Names aren’t guaranteed to be unique.

Description

Description is a human-readable summary of a custom field.

Type

A custom field’s Type describes what sort of values it accepts. As of RT 3.4, acceptable values are: Select, Freeform, Text, Image, and Binary. Select fields let the user pick values from a list. Freeform fields let the user enter individual lines of text. Text fields let the user enter large (up to a couple megabytes) blocks of text. Image fields let the user upload images as custom field values. Binary fields let the user attach files as values.

MaxValues

MaxValues tells RT how many values this custom field can have for a given object. Out of the box, RT 3.4 lets users pick 0, which allows unlimited possible values, or 1, which limits users to a single selection.

SortOrder

SortOrder is an integer field used by RT to automatically list custom fields in the order you want to present them. RT lists custom fields in ascending order sorted by SortOrder.

Disabled

Disabled is a boolean field that specifies whether RT should let users see and modify a custom field and its values. It’s important not to lose historical data about custom fields and their values, so disable custom fields instead of deleting them.

LookupType

RT uses LookupType to describe what sorts of objects to which a custom field applies. RT::Queue-RT::Ticket means that the custom field applies to tickets in a given queue. RT::Queue-RT::Ticket-RT::Transaction means that the custom field applies to transactions on tickets in a given queue. RT::Group tells RT that this custom field should apply to groups. Similarly, RT::User makes sure the custom field only shows up on user objects.

Pattern

RT 3.4 doesn’t do anything with a custom field’s Pattern attribute, but future releases or plugins will add the ability to validate users’ input against a regular expression stored there.

Repeated

The Repeated attribute is reserved for future use.

ObjectCustomFieldValues holds all current custom field values for all tickets within RT. Values are stored by value, rather than by reference. This enables users to switch custom field types from Select to Freeform and back again without loss of data.

RT is a ticketing sytem. It should come as no suprise that one of the core objects is the Ticket. Every ticket has a number of things associated with it, including role groups for Owner, Requestors, Cc, and AdminCc. Owner is quite special in that it can contain only one user, but the others can contain multiple users and groups. By default, RT is configured to treat each of the groups specially, but internally they are quite similar. Additionally, a ticket can have a number of attached Transactions, CustomFields, and Links.

Tickets have the following fields:

EffectiveId

By default, a ticket’s EffectiveId is the same as its ID. RT supports the ability to merge tickets together. When you merge a ticket into another one, RT sets the first ticket’s EffectiveId to the second ticket’s ID. RT uses this data to quickly look up which ticket you’re really talking about when you reference a merged ticket.

Queue

Tickets are grouped into queues. Each ticket can have one and only one queue. Queue is a pointer to the ID of the queue for this ticket.

Type

Type is a simple textual identifer that describes what sort of ticket this is. By default, all tickets are of Type ticket. Generally, there’s no reason to change that.

Owner

Owner is a pointer to the ID of the Principal who owns this ticket. This information is also stored in the ticket’s Owner role group, but it is cached in the Ticket record for performance reasons.

Subject

Subject is a simple human-readable description of what this ticket is about.

Priority, InitialPriority, and FinalPriority

When a ticket is first created, its Priority is copied into its InitialPriority. An external tool can move a ticket’s Priority up (or down) toward its FinalPriority.

TimeEstimated, TimeWorked, and TimeLeft

RT allows users to track how much time, in minutes, a given ticket is estimated to take. Over time, users can add to the TimeWorked and (hopefully) subtract from the TimeLeft.

Status

Each ticket has a single current Status, which can be one of new, open, stalled, resolved, rejected, or deleted. Deleted tickets are treated specially in that they can’t be displayed in ticket listings.

Told

Told tracks the last time a ticket update was sent to the requestor.

Starts

Starts is primarily intended for users’ project management needs. RT doesn’t handle it specially.

Started

Started tracks the last time the ticket’s status was flipped from new to another status.

Due

Due tracks the ticket’s due date.

Resolved

The name Resolved is a bit misleading. This field tracks the last time that this ticket’s status was set to resolved, rejected, or deleted.

IssueStatement and Resolution

These fields are not currently used by RT.

The Queue is RT’s basic administrative unit. Every ticket is categorized into a Queue. Access control, business logic, notifications, and custom fields can all be configured at the queue level.

Queues have the following fields:

Name

Each queue has a unique Name. This name is displayed to users and used by tools such as RT’s mail gateway to determine in which queue a new ticket should be created.

Description

Description is a human-readable explanation of a queue’s purpose that is displayed to administrative staff and sometimes included in outgoing email messages about tickets in this queue.

CorrespondAddress

When RT sends out public email correspondence about a ticket, it automatically sets the message’s From: and Reply-To: headers to the queue’s CorrespondAddress. It’s up to local staff to make sure that both this and the queue’s CommentAddress are set to values that will be properly routed back into RT.

CommentAddress

When RT sends out private email comments about a ticket, it automatically sets the message’s From: and Reply-To: headers to the queue’s CommentAddress.

InitialPriority

InitialPriority specifies a default priority for a newly created ticket in this queue.

FinalPriority

FinalPriority specifies a default ending priority for a newly created ticket in this queue. RT ships with a small tool that you can insert into cron to automatically move tickets toward their FinalPriority as they approach their due dates.

DefaultDueIn

DefaultDueIn, if set, will set the due dates of newly created tickets in this queue to DefaultDueIn days in the future.

Disabled

Sometimes, you don’t want a queue to appear in listings anymore. Deleting the queue outright would lose data about every ticket that had ever been in that queue. Instead, RT provides the Disabled flag, which simply masks the queues you don’t want to see anymore.

Scrips are one of RT’s key bits of extensibility. Scrips are bits of custom logic that users can install into RT without changing any system code. Scrips are composed of a Condition and an Action. If the Condition returns success, then RT will prepare the Action. If the action is prepared cleanly, it is Committed and all relevant email is sent out and data written to the database.

Scrips have the following fields:

Description

The Description is a simple human-readable explanation for this Scrip.

ScripCondition

ScripCondition is a pointer to the ID of a ScripCondition object.

ScripAction

ScripAction is a pointer to the ID of a ScripAction object.

CustomIsApplicableCode

CustomIsApplicableCode is a field used primarily by user-defined conditions. Its content is used as the source code for an anonymous subroutine, which can return true or false. If it returns true, the Scrip’s Action is prepared. Otherwise, processing of this scrip ceases.

CustomPrepareCode

CustomPrepareCode is a field used primarily by user-defined actions. Its content is used as the source code for an anonymous subroutine, which can return true or false. If it returns true, the CustomCommitCode is evaluated. Otherwise, processing of this scrip ceases.

CustomCommitCode

CustomCommitCode is a field used primarily by user-defined actions. Its content is used as the source code for an anonymous subroutine, which should perform whatever action the ScripAction needs to perform and return true on success or false on failure.



[11] There are a couple of places where this isn’t quite true yet, but it’s being improved with each new version.

[12] The RT FAQ Manager. It doesn’t mean anything else, really!

[13] Dave Rolsky and Ken Williams’s Embedding Perl in HTML with Mason (O’Reilly) is the canonical source for everything about Mason.

[14] End users painstakingly translated the entire application into three or four different languages.

[15] Well, almost fully, it doesn’t deal quite right with right-to-left languages like Hebrew and Arabic yet.

[16] To make the access control system work, it’s important that a group be listed as a member of itself.

[17] For more information about RDF, see Practical RDF (O’Reilly).