Skip to content

Justification templates, history and an org-enforced format #185

Description

@FrodeHus

Area: Panel and notifications

The problem

Retyping the justification is a large part of the daily PIM tax. Organisations that require
justification (or a ticket number) for activation get one of two bad outcomes: people type work a
hundred times, which makes the audit trail worthless, or they type something real every time, which
makes activation tedious enough that they look for ways around it.

Elevate already does part of this well:

  • A profile carries an optional reason that prefills the run sheet's justification, and managed
    profiles pushed via ManagedProfiles / ManagedProfilesUrl can carry one too
    (docs/enterprise/profiles.md).
  • Per-role reason and duration are remembered and offered as the default next time
    (elevate activate falls back to what was used last for that role, then to the policy).
  • RolePolicy knows requiresJustification and requiresTicket, so the run sheet can ask.

What is missing is everything between "one remembered string per role" and "type it fresh":

  • No history or picker. Only the single last reason per role is offered. A user who alternates
    between three recurring reasons retypes two of them every time.
  • No templates. There is no way to define "Incident {ticket}", "Change {ticket}", "Access review"
    once and pick from them across roles.
  • No enforced format. An organisation that requires justifications to reference a ticket
    (INC\d+, CHG\d+) has no way to say so. The managed key set is ClientId,
    DisableUpdateCheck, AllowedSignInMethods, AllowedTenants, PinnedTenants,
    ManagedProfiles, ManagedProfilesUrl and the four Organization* keys — nothing about
    justification content. Elevate will happily submit asdf.

What you would like Elevate to do

Reason history and templates. Keep the last several justifications per account (not just per
role) and offer them in the run sheet as a picker, most recent first, still freely editable. Let a
user save one as a named template.

Org-defined templates. A managed key — say JustificationTemplates, a list of strings — that
publishes the reasons an organisation wants people to use, shown at the top of the picker.

Org-enforced format. A managed key — say JustificationPattern (a regular expression) plus
JustificationPatternMessage (what to tell the user when it does not match) — validated in the run
sheet before the request is sent, and in elevate activate --reason before the call. On failure,
show the message, not a regex. Locked with the usual "Managed by your organization" caption.

A minimum-length variant (JustificationMinimumLength) may be worth having alongside, since it
catches work without anyone having to write a regex.

All of it configured inline, through the existing enterprise packaging

These belong in the enterprise kit next to the keys that are already there, and — unlike
ManagedProfiles — none of them needs a URL companion.

ManagedProfilesUrl exists because a profile set is a JSON document that can grow past what is
comfortable to paste into a policy, and because an organisation wants to change it without
re-deploying a profile. Justification templates and a pattern are a short list of short strings and
two scalars. They fit inline in every transport Elevate already reads:

Transport Shape
macOS managed preferences (no.reothor.elevate) An array of strings and two strings, forced values only
Windows policy registry A REG_MULTI_SZ and two REG_SZ under HKLM\SOFTWARE\Policies\Reothor\Elevate / HKCU
ADMX template A list box and two text boxes
Jamf schema / Intune mobileconfig An array and two string properties
CLI managed.json An array and two strings

So the work is: three (or four) keys in docs/enterprise/keys.md with the rest, the matching entries
in the ADMX, mobileconfig, Jamf schema and managed.json templates under enterprise/, and the
usual precedence and locking behaviour — a managed value wins over the user's and renders disabled
with the "Managed by your organization" caption. No new delivery mechanism, no fetch, nothing to
host.

If an organisation later wants a large or centrally-maintained template library, a
JustificationTemplatesUrl could follow the ManagedProfilesUrl pattern — but it should not be in
the first cut. Adding a daily fetch for a handful of short strings is not worth the moving parts.

Same rules in the CLI. elevate activate --reason and elevate run must apply the pattern, so a
script cannot bypass what the panel enforces.

Alternatives considered

  • Rely on PIM's own requiresJustification. It only enforces that something was typed. It has
    no notion of content, which is exactly the gap.
  • Rely on the ticket field. requiresTicket covers the ticket-number case but not the general
    "say something meaningful" case, and not every org routes through a ticket system.
  • Push everything through managed profiles. A profile's reason works well for the recurring,
    pre-planned activation. It does not help the ad-hoc one, which is when justification quality
    matters most.

Anything else

  • This is enforcement at the client, not at the service. Someone using the portal directly is
    unaffected. Worth saying plainly in the docs so nobody mistakes it for a security control — it is
    a data-quality and convenience feature.
  • Ticket-system integration (pull the active ticket from ServiceNow / Jira / Azure DevOps and use it
    as the justification) is the natural next step and a separate issue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    clielevate command-line toolenhancementNew feature or requestenterpriseManaged configuration and fleet deploymentmacosmacOS menu bar appwindowsWindows 11 app

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions