+
+
+=head1 Date and time handling
+
+=over 4
+
+=item C<$DateTimeFormat>
+
+You can choose date and time format. See the "Output formatters"
+section in perldoc F<lib/RT/Date.pm> for more options. This option
+can be overridden by users in their preferences.
+
+Some examples:
+
+C<Set($DateTimeFormat, "LocalizedDateTime");>
+C<Set($DateTimeFormat, { Format => "ISO", Seconds => 0 });>
+C<Set($DateTimeFormat, "RFC2822");>
+C<Set($DateTimeFormat, { Format => "RFC2822", Seconds => 0, DayOfWeek => 0 });>
+
+=cut
+
+Set($DateTimeFormat, "DefaultFormat");
+
+# Next two options are for Time::ParseDate
+
+=item C<$DateDayBeforeMonth>
+
+Set this to 1 if your local date convention looks like "dd/mm/yy"
+instead of "mm/dd/yy". Used only for parsing, not for displaying
+dates.
+
+=cut
+
+Set($DateDayBeforeMonth, 1);
+
+=item C<$AmbiguousDayInPast>, C<$AmbiguousDayInFuture>
+
+Should an unspecified day or year in a date refer to a future or a
+past value? For example, should a date of "Tuesday" default to mean
+the date for next Tuesday or last Tuesday? Should the date "March 1"
+default to the date for next March or last March?
+
+Set C<$AmbiguousDayInPast> for the last date, or
+C<$AmbiguousDayInFuture> for the next date; the default is usually
+correct. If both are set, C<$AmbiguousDayInPast> takes precedence.
+
+=cut
+
+Set($AmbiguousDayInPast, 0);
+Set($AmbiguousDayInFuture, 0);
+
+=item C<$DefaultTimeUnitsToHours>
+
+Use this to set the default units for time entry to hours instead of
+minutes. Note that this only effects entry, not display.
+
+=cut
+
+Set($DefaultTimeUnitsToHours, 0);
+
+=item C<$SimpleSearchIncludeResolved>
+
+By default, the simple ticket search in the top bar excludes "resolved" tickets
+unless a status argument is specified. Set this to a true value to include
+them.
+
+=cut
+
+Set($SimpleSearchIncludeResolved, 0);
+
+=item C<$TimeInICal>
+
+By default, events in the iCal feed on the ticket search page
+contain only dates, making them all day calendar events. Set
+C<$TimeInICal> if you have start or due dates on tickets that
+have significant time values and you want those times to be
+included in the events in the iCal feed.
+
+This option can also be set as an individual user preference.
+
+=cut
+
+Set($TimeInICal, 0);
+
+=back
+
+
+
+=head1 Cryptography
+
+A complete description of RT's cryptography capabilities can be found in
+L<RT::Crypt>. At this moment, GnuPG (PGP) and SMIME security protocols are
+supported.
+
+=over 4
+
+=item C<%Crypt>
+
+The following options apply to all cryptography protocols.
+
+By default, all enabled security protocols will analyze each incoming
+email. You may set C<Incoming> to a subset of this list, if some enabled
+protocols do not apply to incoming mail; however, this is usually
+unnecessary. Note that for any verification or decryption to occur for
+incoming mail, the C<Auth::Crypt> mail plugin must be added to
+L</@MailPlugins> as specified in L<RT::Crypt/Handling incoming messages>.
+
+For outgoing emails, the first security protocol from the above list is
+used. Use the C<Outgoing> option to set a security protocol that should
+be used in outgoing emails. At this moment, only one protocol can be
+used to protect outgoing emails.
+
+Set C<RejectOnUnencrypted> to 1 if all incoming email must be
+properly encrypted. All unencrypted emails will be rejected by RT.
+
+Set C<RejectOnMissingPrivateKey> to 0 if you don't want to reject
+emails encrypted for key RT doesn't have and can not decrypt.
+
+Set C<RejectOnBadData> to 0 if you don't want to reject letters
+with incorrect data.
+
+If you want to allow people to encrypt attachments inside the DB then
+set C<AllowEncryptDataInDB> to 1.
+
+Set C<Dashboards> to a hash with Encrypt and Sign keys to control
+whether dashboards should be encrypted and/or signed correspondingly.
+By default they are not encrypted or signed.
+
+=back
+
+=cut
+
+Set( %Crypt,
+ Incoming => undef, # ['GnuPG', 'SMIME']
+ Outgoing => undef, # 'SMIME'
+
+ RejectOnUnencrypted => 0,
+ RejectOnMissingPrivateKey => 1,
+ RejectOnBadData => 1,
+
+ AllowEncryptDataInDB => 0,
+
+ Dashboards => {
+ Encrypt => 0,
+ Sign => 0,
+ },
+);
+
+=head2 SMIME configuration
+
+A full description of the SMIME integration can be found in
+L<RT::Crypt::SMIME>.
+
+=over 4
+
+=item C<%SMIME>
+
+Set C<Enable> to 0 or 1 to disable or enable SMIME for
+encrypting and signing messages.
+
+Set C<OpenSSL> to path to F<openssl> executable.
+
+Set C<Keyring> to directory with key files. Key and certificates should
+be stored in a PEM file in this directory named named, e.g.,
+F<email.address@example.com.pem>.
+
+Set C<CAPath> to either a PEM-formatted certificate of a single signing
+certificate authority, or a directory of such (including hash symlinks
+as created by the openssl tool C<c_rehash>). Only SMIME certificates
+signed by these certificate authorities will be treated as valid
+signatures. If left unset (and C<AcceptUntrustedCAs> is unset, as it is
+by default), no signatures will be marked as valid!
+
+Set C<AcceptUntrustedCAs> to allow arbitrary SMIME certificates, no
+matter their signing entities. Such mails will be marked as untrusted,
+but signed; C<CAPath> will be used to mark which mails are signed by
+trusted certificate authorities. This configuration is generally
+insecure, as it allows the possibility of accepting forged mail signed
+by an untrusted certificate authority.
+
+Setting C<AcceptUntrustedCAs> also allows encryption to users with
+certificates created by untrusted CAs.
+
+Set C<Passphrase> to a scalar (to use for all keys), an anonymous
+function, or a hash (to look up by address). If the hash is used, the
+'' key is used as a default.
+
+See L<RT::Crypt::SMIME> for details.
+
+=back
+
+=cut
+
+Set( %SMIME,
+ Enable => @RT_SMIME@,
+ OpenSSL => 'openssl',
+ Keyring => q{@RT_VAR_PATH@/data/smime},
+ CAPath => undef,
+ AcceptUntrustedCAs => undef,
+ Passphrase => undef,
+);
+
+=head2 GnuPG configuration
+
+A full description of the (somewhat extensive) GnuPG integration can
+be found by running the command `perldoc L<RT::Crypt::GnuPG>` (or
+`perldoc lib/RT/Crypt/GnuPG.pm` from your RT install directory).
+
+=over 4
+
+=item C<%GnuPG>
+
+Set C<Enable> to 0 or 1 to disable or enable GnuPG interfaces
+for encrypting and signing outgoing messages.
+
+Set C<GnuPG> to the name or path of the gpg binary to use.
+
+Set C<Passphrase> to a scalar (to use for all keys), an anonymous
+function, or a hash (to look up by address). If the hash is used, the
+'' key is used as a default.
+
+Set C<OutgoingMessagesFormat> to 'inline' to use inline encryption and
+signatures instead of 'RFC' (GPG/MIME: RFC3156 and RFC1847) format.
+
+=cut
+
+Set(%GnuPG,
+ Enable => @RT_GPG@,
+ GnuPG => 'gpg',
+ Passphrase => undef,
+ OutgoingMessagesFormat => "RFC", # Inline
+);
+
+=item C<%GnuPGOptions>
+
+Options to pass to the GnuPG program.
+
+If you override this in your RT_SiteConfig, you should be sure to
+include a homedir setting.
+
+Note that options with '-' character MUST be quoted.
+
+=cut
+
+Set(%GnuPGOptions,
+ homedir => q{@RT_VAR_PATH@/data/gpg},
+
+# URL of a keyserver
+# keyserver => 'hkp://subkeys.pgp.net',
+
+# enables the automatic retrieving of keys when verifying signatures
+# 'keyserver-options' => 'auto-key-retrieve',
+);
+
+=back
+
+
+
+=head1 Lifecycles
+
+=head2 Lifecycle definitions
+
+Each lifecycle is a list of possible statuses split into three logic
+sets: B<initial>, B<active> and B<inactive>. Each status in a
+lifecycle must be unique. (Statuses may not be repeated across sets.)
+Each set may have any number of statuses.
+
+For example:
+
+ default => {
+ initial => ['new'],
+ active => ['open', 'stalled'],
+ inactive => ['resolved', 'rejected', 'deleted'],
+ ...
+ },
+
+Status names can be from 1 to 64 ASCII characters. Statuses are
+localized using RT's standard internationalization and localization
+system.
+
+=over 4
+
+=item initial
+
+You can define multiple B<initial> statuses for tickets in a given
+lifecycle.
+
+RT will automatically set its B<Started> date when you change a
+ticket's status from an B<initial> state to an B<active> or
+B<inactive> status.
+
+=item active
+
+B<Active> tickets are "currently in play" - they're things that are
+being worked on and not yet complete.
+
+=item inactive
+
+B<Inactive> tickets are typically in their "final resting state".
+
+While you're free to implement a workflow that ignores that
+description, typically once a ticket enters an inactive state, it will
+never again enter an active state.
+
+RT will automatically set the B<Resolved> date when a ticket's status
+is changed from an B<Initial> or B<Active> status to an B<Inactive>
+status.
+
+B<deleted> is still a special status and protected by the
+B<DeleteTicket> right, unless you re-defined rights (read below). If
+you don't want to allow ticket deletion at any time simply don't
+include it in your lifecycle.
+
+=back
+
+Statuses in each set are ordered and listed in the UI in the defined
+order.
+
+Changes between statuses are constrained by transition rules, as
+described below.
+
+=head2 Default values
+
+In some cases a default value is used to display in UI or in API when
+value is not provided. You can configure defaults using the following
+syntax:
+
+ default => {
+ ...
+ defaults => {
+ on_create => 'new',
+ on_resolve => 'resolved',
+ ...
+ },
+ },
+
+The following defaults are used.
+
+=over 4
+
+=item on_create
+
+If you (or your code) doesn't specify a status when creating a ticket,
+RT will use the this status. See also L</Statuses available during
+ticket creation>.
+
+=item on_merge
+
+When tickets are merged, the status of the ticket that was merged
+away is forced to this value. It should be one of inactive statuses;
+'resolved' or its equivalent is most probably the best candidate.
+
+=item approved
+
+When an approval is accepted, the status of depending tickets will
+be changed to this value.
+
+=item denied
+
+When an approval is denied, the status of depending tickets will
+be changed to this value.
+
+=item reminder_on_open
+
+When a reminder is opened, the status will be changed to this value.
+
+=item reminder_on_resolve
+
+When a reminder is resolved, the status will be changed to this value.
+
+=back
+
+=head2 Transitions between statuses and UI actions
+
+A B<Transition> is a change of status from A to B. You should define
+all possible transitions in each lifecycle using the following format:
+
+ default => {
+ ...
+ transitions => {
+ '' => [qw(new open resolved)],
+ new => [qw(open resolved rejected deleted)],
+ open => [qw(stalled resolved rejected deleted)],
+ stalled => [qw(open)],
+ resolved => [qw(open)],
+ rejected => [qw(open)],
+ deleted => [qw(open)],
+ },
+ ...
+ },
+
+The order of items in the listing for each transition line affects
+the order they appear in the drop-down. If you change the config
+for 'open' state listing to:
+
+ open => [qw(stalled rejected deleted resolved)],
+
+then the 'resolved' status will appear as the last item in the drop-down.
+
+=head3 Statuses available during ticket creation
+
+By default users can create tickets with a status of new,
+open, or resolved, but cannot create tickets with a status of
+rejected, stalled, or deleted. If you want to change the statuses
+available during creation, update the transition from '' (empty
+string), like in the example above.
+
+=head3 Protecting status changes with rights
+
+A transition or group of transitions can be protected by a specific
+right. Additionally, you can name new right names, which will be added
+to the system to control that transition. For example, if you wished to
+create a lesser right than ModifyTicket for rejecting tickets, you could
+write:
+
+ default => {
+ ...
+ rights => {
+ '* -> deleted' => 'DeleteTicket',
+ '* -> rejected' => 'RejectTicket',
+ '* -> *' => 'ModifyTicket',
+ },
+ ...
+ },
+
+This would create a new C<RejectTicket> right in the system which you
+could assign to whatever groups you choose.
+
+On the left hand side you can have the following variants:
+
+ '<from> -> <to>'
+ '* -> <to>'
+ '<from> -> *'
+ '* -> *'
+
+Valid transitions are listed in order of priority. If a user attempts
+to change a ticket's status from B<new> to B<open> then the lifecycle
+is checked for presence of an exact match, then for 'any to B<open>',
+'B<new> to any' and finally 'any to any'.
+
+If you don't define any rights, or there is no match for a transition,
+RT will use the B<DeleteTicket> or B<ModifyTicket> as appropriate.
+
+=head3 Labeling and defining actions
+
+For each transition you can define an action that will be shown in the
+UI; each action annotated with a label and an update type.
+
+Each action may provide a default update type, which can be
+B<Comment>, B<Respond>, or absent. For example, you may want your
+staff to write a reply to the end user when they change status from
+B<new> to B<open>, and thus set the update to B<Respond>. Neither
+B<Comment> nor B<Respond> are mandatory, and user may leave the
+message empty, regardless of the update type.
+
+This configuration can be used to accomplish what
+$ResolveDefaultUpdateType was used for in RT 3.8.
+
+Use the following format to define labels and actions of transitions:
+
+ default => {
+ ...
+ actions => [
+ 'new -> open' => { label => 'Open it', update => 'Respond' },
+ 'new -> resolved' => { label => 'Resolve', update => 'Comment' },
+ 'new -> rejected' => { label => 'Reject', update => 'Respond' },
+ 'new -> deleted' => { label => 'Delete' },
+
+ 'open -> stalled' => { label => 'Stall', update => 'Comment' },
+ 'open -> resolved' => { label => 'Resolve', update => 'Comment' },
+ 'open -> rejected' => { label => 'Reject', update => 'Respond' },
+
+ 'stalled -> open' => { label => 'Open it' },
+ 'resolved -> open' => { label => 'Re-open', update => 'Comment' },
+ 'rejected -> open' => { label => 'Re-open', update => 'Comment' },
+ 'deleted -> open' => { label => 'Undelete' },
+ ],
+ ...
+ },
+
+In addition, you may define multiple actions for the same transition.
+Alternately, you may use '* -> x' to match more than one transition.
+For example:
+
+ default => {
+ ...
+ actions => [
+ ...
+ 'new -> rejected' => { label => 'Reject', update => 'Respond' },
+ 'new -> rejected' => { label => 'Quick Reject' },
+ ...
+ '* -> deleted' => { label => 'Delete' },
+ ...
+ ],
+ ...
+ },
+
+=head2 Moving tickets between queues with different lifecycles
+
+Unless there is an explicit mapping between statuses in two different
+lifecycles, you can not move tickets between queues with these
+lifecycles -- even if both use the exact same set of statuses.
+Such a mapping is defined as follows:
+
+ __maps__ => {
+ 'from lifecycle -> to lifecycle' => {
+ 'status in left lifecycle' => 'status in right lifecycle',
+ ...
+ },
+ ...
+ },
+
+=cut
+
+Set(%Lifecycles,
+ default => {
+ initial => [qw(new)], # loc_qw
+ active => [qw(open stalled)], # loc_qw
+ inactive => [qw(resolved rejected deleted)], # loc_qw
+
+ defaults => {
+ on_create => 'new',
+ on_merge => 'resolved',
+ approved => 'open',
+ denied => 'rejected',
+ reminder_on_open => 'open',
+ reminder_on_resolve => 'resolved',
+ },
+
+ transitions => {
+ "" => [qw(new open resolved)],
+
+ # from => [ to list ],
+ new => [qw( open stalled resolved rejected deleted)],
+ open => [qw(new stalled resolved rejected deleted)],
+ stalled => [qw(new open rejected resolved deleted)],
+ resolved => [qw(new open stalled rejected deleted)],
+ rejected => [qw(new open stalled resolved deleted)],
+ deleted => [qw(new open stalled rejected resolved )],
+ },
+ rights => {
+ '* -> deleted' => 'DeleteTicket',
+ '* -> *' => 'ModifyTicket',
+ },
+ actions => [
+ 'new -> open' => { label => 'Open It', update => 'Respond' }, # loc{label}
+ 'new -> resolved' => { label => 'Resolve', update => 'Comment' }, # loc{label}
+ 'new -> rejected' => { label => 'Reject', update => 'Respond' }, # loc{label}
+ 'new -> deleted' => { label => 'Delete', }, # loc{label}
+ 'open -> stalled' => { label => 'Stall', update => 'Comment' }, # loc{label}
+ 'open -> resolved' => { label => 'Resolve', update => 'Comment' }, # loc{label}
+ 'open -> rejected' => { label => 'Reject', update => 'Respond' }, # loc{label}
+ 'stalled -> open' => { label => 'Open It', }, # loc{label}
+ 'resolved -> open' => { label => 'Re-open', update => 'Comment' }, # loc{label}
+ 'rejected -> open' => { label => 'Re-open', update => 'Comment' }, # loc{label}
+ 'deleted -> open' => { label => 'Undelete', }, # loc{label}
+ ],
+ },
+# don't change lifecyle of the approvals, they are not capable to deal with
+# custom statuses
+ approvals => {
+ initial => [ 'new' ],
+ active => [ 'open', 'stalled' ],
+ inactive => [ 'resolved', 'rejected', 'deleted' ],
+
+ defaults => {
+ on_create => 'new',
+ on_merge => 'resolved',
+ reminder_on_open => 'open',
+ reminder_on_resolve => 'resolved',
+ },
+
+ transitions => {
+ '' => [qw(new open resolved)],
+
+ # from => [ to list ],
+ new => [qw(open stalled resolved rejected deleted)],
+ open => [qw(new stalled resolved rejected deleted)],
+ stalled => [qw(new open rejected resolved deleted)],
+ resolved => [qw(new open stalled rejected deleted)],
+ rejected => [qw(new open stalled resolved deleted)],
+ deleted => [qw(new open stalled rejected resolved)],
+ },
+ rights => {
+ '* -> deleted' => 'DeleteTicket',
+ '* -> rejected' => 'ModifyTicket',
+ '* -> *' => 'ModifyTicket',
+ },
+ actions => [
+ 'new -> open' => { label => 'Open It', update => 'Respond' }, # loc{label}
+ 'new -> resolved' => { label => 'Resolve', update => 'Comment' }, # loc{label}
+ 'new -> rejected' => { label => 'Reject', update => 'Respond' }, # loc{label}
+ 'new -> deleted' => { label => 'Delete', }, # loc{label}
+ 'open -> stalled' => { label => 'Stall', update => 'Comment' }, # loc{label}
+ 'open -> resolved' => { label => 'Resolve', update => 'Comment' }, # loc{label}
+ 'open -> rejected' => { label => 'Reject', update => 'Respond' }, # loc{label}
+ 'stalled -> open' => { label => 'Open It', }, # loc{label}
+ 'resolved -> open' => { label => 'Re-open', update => 'Comment' }, # loc{label}
+ 'rejected -> open' => { label => 'Re-open', update => 'Comment' }, # loc{label}
+ 'deleted -> open' => { label => 'Undelete', }, # loc{label}
+ ],
+ },
+);
+
+
+
+
+
+=head1 Administrative interface
+
+=over 4
+
+=item C<$ShowRTPortal>
+
+RT can show administrators a feed of recent RT releases and other
+related announcements and information from Best Practical on the top
+level Admin page. This feature helps you stay up to date on
+RT security announcements and version updates.
+
+RT provides this feature using an "iframe" on C</Admin/index.html>
+which asks the administrator's browser to show an inline page from
+Best Practical's website.
+
+If you'd rather not make this feature available to your
+administrators, set C<$ShowRTPortal> to 0.
+
+=cut
+
+Set($ShowRTPortal, 1);
+
+=item C<%AdminSearchResultFormat>
+
+In the admin interface, format strings similar to tickets result
+formats are used. Use C<%AdminSearchResultFormat> to define the format
+strings used in the admin interface on a per-RT-class basis.
+
+=cut
+
+Set(%AdminSearchResultFormat,
+ Queues =>
+ q{'<a href="__WebPath__/Admin/Queues/Modify.html?id=__id__">__id__</a>/TITLE:#'}
+ .q{,'<a href="__WebPath__/Admin/Queues/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
+ .q{,__Description__,__Address__,__Priority__,__DefaultDueIn__,__Lifecycle__,__SubjectTag__,__Disabled__},
+
+ Groups =>
+ q{'<a href="__WebPath__/Admin/Groups/Modify.html?id=__id__">__id__</a>/TITLE:#'}
+ .q{,'<a href="__WebPath__/Admin/Groups/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
+ .q{,'__Description__',__Disabled__},
+
+ Users =>
+ q{'<a href="__WebPath__/Admin/Users/Modify.html?id=__id__">__id__</a>/TITLE:#'}
+ .q{,'<a href="__WebPath__/Admin/Users/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
+ .q{,__RealName__, __EmailAddress__,__Disabled__},
+
+ CustomFields =>
+ q{'<a href="__WebPath__/Admin/CustomFields/Modify.html?id=__id__">__id__</a>/TITLE:#'}
+ .q{,'<a href="__WebPath__/Admin/CustomFields/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
+ .q{,__AddedTo__, __FriendlyType__, __FriendlyPattern__,__Disabled__},
+
+ Scrips =>
+ q{'<a href="__WebPath__/Admin/Scrips/Modify.html?id=__id____From__">__id__</a>/TITLE:#'}
+ .q{,'<a href="__WebPath__/Admin/Scrips/Modify.html?id=__id____From__">__Description__</a>/TITLE:Description'}
+ .q{,__Condition__, __Action__, __Template__, __Disabled__},
+
+ Templates =>
+ q{'<a href="__WebPath__/__WebRequestPathDir__/Template.html?Queue=__QueueId__&Template=__id__">__id__</a>/TITLE:#'}
+ .q{,'<a href="__WebPath__/__WebRequestPathDir__/Template.html?Queue=__QueueId__&Template=__id__">__Name__</a>/TITLE:Name'}
+ .q{,'__Description__','__UsedBy__','__IsEmpty__'},
+ Classes =>
+ q{ '<a href="__WebPath__/Admin/Articles/Classes/Modify.html?id=__id__">__id__</a>/TITLE:#'}
+ .q{,'<a href="__WebPath__/Admin/Articles/Classes/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
+ .q{,__Description__,__Disabled__},
+);
+
+=item C<%AdminSearchResultRows>
+
+Use C<%AdminSearchResultRows> to define the search result rows in the admin
+interface on a per-RT-class basis.
+
+=cut
+
+Set(%AdminSearchResultRows,
+ Queues => 50,
+ Groups => 50,
+ Users => 50,
+ CustomFields => 50,
+ Scrips => 50,
+ Templates => 50,
+ Classes => 50,
+);
+