Back to Password Reset & Access Requests

Developer Handover Pack

Everything needed to build the automation from scratch: current state, full agent specs, data flow, and the build stack.

4 pagesPDF · Technical
FS-DOC-04Technical

Developer Handover Pack

Password Reset & Access Requests

[YourCompany.com] · IT Department · Prepared by FullSpec · [Today's Date]

This document gives the FullSpec build team every specification needed to construct, wire, and test the three-agent Password Reset and Access Request automation. It covers the current-state process with bottlenecks identified, full agent specifications including triggers, tooling, IO contracts, and implementation constraints, the end-to-end data flow traced field by field, and the recommended build stack with estimated hours. The process owner's role is to confirm API access and service account details before build starts; everything else is handled by FullSpec.

01Process snapshot

Step
Name
Description
1
Request Received via Email or Slack
A staff member messages IT via Slack or email. IT reads and classifies the request as a reset or new access. (5 min)
2
Ticket Created Manually in Helpdesk
IT opens Jira and manually creates a ticket, copying request details. Frequently skipped under pressure, leaving no record. (6 min)
3
Identity Verified by IT
IT sends a follow-up message to confirm the requester's identity, sometimes checking an employee directory. Back-and-forth adds significant delay. BOTTLENECK (10 min)
4
Manager Approval Chased for New Access
IT messages or emails the requester's manager to confirm appropriateness. Waiting for a reply is the single biggest delay in the process. BOTTLENECK (20 min)
5
Access or Reset Actioned in Identity Provider
Once approval is confirmed, IT logs into Okta or Azure AD and performs the reset or provisions the new access role. (8 min)
6
Google Workspace or App Access Updated
If the request involves a Google Workspace group, IT navigates to that admin console separately and makes the change. (6 min)
7
Requester Notified Manually
IT sends a Slack message or email to confirm access has been restored or granted. No standard format is used. (4 min)
8
Ticket Closed and Audit Note Added
IT returns to Jira, adds a note about what was done, and closes the ticket. Frequently skipped when IT is busy. (5 min)
Time cost summary: Total manual time per cycle is 64 minutes. At approximately 60 requests per month that equates to roughly 64 hours of manual IT effort per month, or 6 hours per week. Steps 1 through 8 are all manual today. The automation replaces steps 1 to 8 in full, leaving one human-only exception path: IT escalation review when identity verification fails or a manager denies a request. Steps 3 and 4 are flagged as bottlenecks and account for 30 of the 64 minutes per cycle, making them the highest-priority targets for automation.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Request Intake Agent

Receives inbound requests from either the Slack slash command (/it-request) or the web intake form, classifies the request as a password reset or a new access request, extracts the relevant structured details (requester identity, system name, urgency), and creates a populated Jira ticket. Eliminates all manual reading, copying, and triage so that no human intervention is required at the top of the funnel. Complexity: Moderate.

Trigger
A staff member submits a Slack slash command or web form submission. The automation platform receives a structured webhook payload from Slack or the form endpoint.
Tools
Slack (slash command and incoming webhook), Jira (REST API ticket creation)
Replaces steps
Steps 1 and 2: Request received via Slack or email; ticket created manually in Jira
Estimated build
8 hours, Moderate complexity
// Input
slack_payload: {
  user_id: string,          // Slack user ID of requester
  user_name: string,        // Display name
  command: '/it-request',
  text: string,             // Raw request text from slash command
  response_url: string,     // Ephemeral reply endpoint
  trigger_id: string        // Used to open modal if needed
}
// OR form_submission: {
  requester_email: string,
  request_type: 'password_reset' | 'new_access',
  system_name: string,
  urgency: 'normal' | 'urgent',
  additional_notes: string
}

// Output
jira_ticket: {
  ticket_id: string,         // e.g. 'IT-4821'
  summary: string,           // Auto-generated from classification
  request_type: 'password_reset' | 'new_access',
  requester_slack_id: string,
  requester_email: string,
  system_name: string,
  status: 'Open',
  created_at: ISO8601,
  source_channel: 'slack_command' | 'web_form'
}
  • Slack app must be installed at the workspace level with the slash command /it-request registered. The OAuth scopes required are commands, chat:write, users:read, and users:read.email. Confirm with the process owner before build.
  • Jira integration requires a service account with project-level Create Issue and Edit Issue permissions on the IT helpdesk project. Use API token authentication (not OAuth) for server-to-server calls.
  • Classification logic must handle ambiguous text. If the request cannot be classified with confidence, default to request_type: 'new_access' and flag the ticket with a 'REVIEW_NEEDED' label rather than dropping or misrouting it.
  • Web form fallback must be built alongside the Slack command. Teams that do not use Slack daily need this path. The form should post to the same webhook endpoint as the Slack trigger to avoid duplicating downstream logic.
  • Dedupe check: if a Jira ticket already exists for the same requester_email with status 'Open' and the same system_name, link to the existing ticket rather than creating a duplicate. Surface a Slack message to the requester confirming their existing ticket ID.
  • Confirm the Jira project key and board ID with the process owner during discovery before wiring the ticket creation call.
Verification and Approval Agent

Handles two parallel verification paths based on the ticket's request_type. For password resets, it triggers an Okta identity verification challenge to the requester's registered MFA device or secondary email without any IT involvement. For new access requests, it sends the requester's direct manager a structured Slack message containing the ticket summary and one-click Approve or Deny buttons. Monitors for responses, sends a single automated reminder after 2 hours of no response, and escalates to the IT escalation queue after 24 hours. Records the outcome on the Jira ticket before handing off. Complexity: Complex.

Trigger
A new Jira ticket is created and classified by the Request Intake Agent. The automation platform reads the ticket_id and request_type field to determine which verification branch to execute.
Tools
Okta (API: /api/v1/authn and /api/v1/factors), Slack (interactive messages with Block Kit action buttons), Microsoft Azure AD (Graph API: GET /users/{id}/manager to resolve manager identity)
Replaces steps
Steps 3 and 4: Identity verified by IT; manager approval chased for new access
Estimated build
10 hours, Complex complexity
// Input
jira_ticket: {
  ticket_id: string,
  request_type: 'password_reset' | 'new_access',
  requester_email: string,
  requester_slack_id: string,
  system_name: string
}

// On password_reset branch:
okta_authn_response: {
  status: 'SUCCESS' | 'MFA_CHALLENGE' | 'LOCKED_OUT',
  session_token: string | null,
  factor_type: 'email' | 'sms' | 'totp'
}

// On new_access branch:
azure_ad_manager: {
  manager_email: string,
  manager_slack_id: string,   // Looked up via Slack users.lookupByEmail
  manager_display_name: string
}
slack_approval_response: {
  action_id: 'approve' | 'deny',
  responder_slack_id: string,
  responded_at: ISO8601,
  ticket_id: string
}

// Output
verification_result: {
  ticket_id: string,
  outcome: 'verified' | 'approved' | 'denied' | 'failed' | 'timeout',
  method: 'okta_mfa' | 'manager_slack_approval',
  decided_by: string,        // email of approver or 'okta_system'
  decided_at: ISO8601
}
  • Okta service account must have the SUPER_ADMIN or APP_ADMIN role scoped to the relevant application. Confirm the minimum required scope with the Okta admin before build. The /api/v1/authn endpoint is used to initiate the identity challenge; do not use the /api/v1/sessions endpoint for this flow.
  • Manager resolution uses the Azure AD Graph API (GET /v1.0/users/{requester_email}/manager). Requires the application registration to hold the User.Read.All delegated permission. If the manager field is null or the manager is not a Slack user, route the ticket immediately to the IT escalation queue rather than waiting for a timeout.
  • Slack interactive message buttons must use Block Kit with action_id values 'it_approve' and 'it_deny'. The Slack app's Request URL for interactive components must point to the automation platform's webhook endpoint. Confirm this URL is reachable from Slack's servers (public HTTPS, valid TLS).
  • Reminder timing: send one Slack reminder to the manager after 2 hours of no response. Do not send more than one reminder. After 24 hours with no response, update the Jira ticket status to 'Escalated' and post to the IT escalation channel with the ticket ID.
  • Denial and failure handling: if the manager clicks Deny, or if the Okta MFA challenge returns a LOCKED_OUT or failed status, set verification_result.outcome to 'denied' or 'failed', update the Jira ticket with the reason, and route to the IT escalation Slack channel. Do not proceed to provisioning.
  • The Okta MFA challenge link sent to the requester must expire after 15 minutes. If expired, the agent must generate a new challenge link and notify the requester via Slack before retrying.
Provisioning and Audit Agent

Executes the approved access change across Okta and Google Workspace, notifies the requester with a formatted Slack message, and closes the Jira ticket with a complete audit log entry. This agent only runs when verification_result.outcome is 'verified' or 'approved'. If the outcome is anything else, this agent does not execute and the escalation path handles the ticket. Complexity: Moderate.

Trigger
The Verification and Approval Agent emits a verification_result record with outcome set to 'verified' or 'approved'. The automation platform listens for this event and starts the provisioning branch.
Tools
Okta (API: /api/v1/users/{id}/lifecycle/resetPassword and /api/v1/users/{id}/roles), Google Workspace Admin SDK (directory.members.insert, drives.permissions.create), Slack (chat.postMessage), Jira (REST API: update issue, add comment, transition to Done)
Replaces steps
Steps 5, 6, 7, and 8: Access or reset actioned in identity provider; Google Workspace updated; requester notified; ticket closed with audit note
Estimated build
8 hours, Moderate complexity
// Input
verification_result: {
  ticket_id: string,
  outcome: 'verified' | 'approved',
  method: 'okta_mfa' | 'manager_slack_approval',
  decided_by: string,
  decided_at: ISO8601
}
jira_ticket: {
  request_type: 'password_reset' | 'new_access',
  requester_email: string,
  requester_slack_id: string,
  system_name: string,
  ticket_id: string
}

// On password_reset branch:
okta_reset_response: {
  reset_password_url: string,  // Temporary link sent to requester
  expires_at: ISO8601
}

// On new_access branch:
okta_role_response: {
  role_id: string,
  assigned_at: ISO8601
}
google_workspace_response: {
  group_email: string,         // Group the user was added to
  membership_status: 'ACTIVE'
}

// Output
audit_record: {
  ticket_id: string,
  action_taken: string,        // Human-readable summary
  okta_change: string,         // Role or reset reference
  google_workspace_change: string | null,
  approved_by: string,         // decided_by from verification_result
  approval_method: string,
  executed_at: ISO8601,
  jira_status: 'Done',
  slack_confirmation_sent: boolean
}
  • Okta provisioning calls require a service account with the USER_ADMIN role at minimum. The resetPassword lifecycle endpoint returns a temporary password reset URL that must be included in the Slack confirmation to the requester, not stored in the audit log.
  • Google Workspace Admin SDK requires a service account with domain-wide delegation enabled and the scope https://www.googleapis.com/auth/admin.directory.group.member for group membership changes. The group_email value to use for each system_name must be maintained in a lookup table in the automation platform's credential store.
  • Jira ticket close must use the correct transition ID for the 'Done' status in the configured workflow. Fetch available transitions via GET /rest/api/3/issue/{ticket_id}/transitions before wiring the close call; do not hardcode the transition ID as it varies by project.
  • Slack confirmation message must use a Block Kit template that includes: the action taken, the system name, the approval method, and any next steps (e.g. 'Set your new password using the link below. It expires in 60 minutes.'). Use a consistent message template across all runs.
  • If the Okta provisioning call fails (non-2xx response), do not close the Jira ticket. Instead, transition it to 'Failed', post an alert to the IT escalation Slack channel with the error detail, and stop. Do not retry more than once automatically.
  • Audit note written to Jira must record: action taken, system name, approval method, approved_by email, executed_at timestamp, and the Okta or Google Workspace reference ID. This is the compliance-facing record and must be complete on every run.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow with field names at each agent handoff
// ============================================================
// TRIGGER: Staff member submits Slack slash command or web form
// ============================================================
INPUT {
  source: 'slack_command' | 'web_form'
  user_id: string                   // Slack user ID
  user_name: string
  requester_email: string           // Resolved via Slack users.info if source=slack_command
  text: string                      // Raw request text
  trigger_id: string                // Slack modal opener (if needed)
}

// ============================================================
// AGENT 1: Request Intake Agent
// ============================================================
// Classification step
classify(text) -> request_type: 'password_reset' | 'new_access'
classify(text) -> system_name: string
classify(text) -> urgency: 'normal' | 'urgent'

// Dedupe check
GET /rest/api/3/issue/search?jql=project=IT AND status=Open
  AND reporter.email={requester_email} AND summary~{system_name}
-> existing_ticket_id: string | null
IF existing_ticket_id != null -> notify requester, STOP

// Jira ticket creation
POST /rest/api/3/issue
BODY {
  fields.project.key: 'IT'
  fields.summary: '[{request_type}] {system_name} - {user_name}'
  fields.issuetype.name: 'IT Request'
  fields.description: {text}
  fields.customfield_requester_email: {requester_email}
  fields.customfield_requester_slack_id: {user_id}
  fields.customfield_request_type: {request_type}
  fields.customfield_system_name: {system_name}
  fields.customfield_source_channel: {source}
}
-> ticket_id: string              // e.g. 'IT-4821'
-> jira_ticket_url: string

// HANDOFF 1->2: ticket_id, request_type, requester_email,
//               requester_slack_id, system_name

// ============================================================
// AGENT 2: Verification and Approval Agent
// ============================================================
IF request_type == 'password_reset' {
  // Okta MFA challenge
  POST /api/v1/authn
  BODY { username: {requester_email}, password: null }
  -> stateToken: string
  POST /api/v1/authn/factors/{factorId}/verify
  BODY { stateToken: {stateToken} }
  -> status: 'SUCCESS' | 'MFA_CHALLENGE' | 'LOCKED_OUT'
  -> sessionToken: string | null
  // Challenge link expires: 15 minutes
}

IF request_type == 'new_access' {
  // Resolve manager from Azure AD
  GET /v1.0/users/{requester_email}/manager
  -> manager_email: string
  -> manager_display_name: string
  // Resolve manager Slack ID
  GET /api/v1/users.lookupByEmail?email={manager_email}
  -> manager_slack_id: string

  // Send approval message
  POST /api/v1/chat.postMessage
  BODY {
    channel: {manager_slack_id}
    blocks: [Block Kit approval card with ticket_id, requester, system_name]
    actions: [{ action_id: 'it_approve' }, { action_id: 'it_deny' }]
  }
  // Wait for interactive callback (2hr reminder, 24hr escalation)
  <- slack_callback: { action_id, responder_slack_id, responded_at }
}

// Outcome written back to Jira
POST /rest/api/3/issue/{ticket_id}/comment
BODY { body: 'Verification outcome: {outcome} via {method} at {decided_at}' }

IF outcome IN ['denied','failed','timeout'] {
  // Transition ticket to 'Escalated', alert IT escalation channel
  POST /api/v1/chat.postMessage -> channel: '#it-escalations'
  STOP
}

// HANDOFF 2->3: ticket_id, request_type, requester_email,
//               requester_slack_id, system_name, outcome,
//               method, decided_by, decided_at

// ============================================================
// AGENT 3: Provisioning and Audit Agent
// ============================================================
IF request_type == 'password_reset' {
  POST /api/v1/users/{okta_user_id}/lifecycle/resetPassword?sendEmail=false
  -> reset_password_url: string
  -> expires_at: ISO8601
}

IF request_type == 'new_access' {
  // Okta role assignment
  POST /api/v1/users/{okta_user_id}/roles
  BODY { type: {mapped_role_for_system_name} }
  -> role_id: string
  -> assigned_at: ISO8601

  // Google Workspace group membership
  POST /admin/directory/v1/groups/{group_email}/members
  BODY { email: {requester_email}, role: 'MEMBER' }
  -> membership_status: 'ACTIVE'
}

// Slack confirmation to requester
POST /api/v1/chat.postMessage
BODY {
  channel: {requester_slack_id}
  blocks: [Block Kit confirmation card with action_taken,
           system_name, reset_password_url (if reset), next_steps]
}
-> slack_confirmation_sent: true

// Jira audit note + close
POST /rest/api/3/issue/{ticket_id}/comment
BODY { body: audit_note_string }  // action, system, approved_by, okta_ref, gws_ref, executed_at
POST /rest/api/3/issue/{ticket_id}/transitions
BODY { transition: { id: {done_transition_id} } }
-> jira_status: 'Done'

// ============================================================
// FINAL OUTPUT: audit_record persisted in Jira; requester unblocked
// ============================================================
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation tool with one workflow per agent (three workflows total): Request Intake Workflow, Verification and Approval Workflow, and Provisioning and Audit Workflow. All three workflows share a single credential store for API tokens and service account keys. No credentials are stored in workflow nodes directly.
Webhook configuration
Two inbound webhook endpoints are required. Endpoint 1 receives the Slack slash command POST payload and the Slack interactive component callback (Approve/Deny button clicks) from Slack's servers. Endpoint 2 receives web form submissions. Both endpoints must be public HTTPS URLs with valid TLS certificates. Slack requires a 200 OK response within 3 seconds; all heavy processing runs asynchronously after the immediate acknowledgement.
Templating approach
All Slack messages use Block Kit JSON templates stored as reusable snippets in the credential/config store. Jira ticket summaries and audit note bodies use string templates with named placeholders (e.g. {{requester_name}}, {{system_name}}, {{decided_at}}). Template versions are incremented when message copy changes to keep a history.
Error logging
All agent errors (non-2xx API responses, classification failures, null manager lookups, timeout events) are written to a dedicated error log table (e.g. a Supabase table: automation_errors with columns: run_id, agent_name, error_code, error_message, payload_snapshot, created_at). An alert is posted to the #it-automation-alerts Slack channel for any error that results in a ticket being moved to Escalated or Failed status. Non-critical warnings (e.g. dedupe match found) are logged to the table but do not trigger a Slack alert.
Testing approach
All agents are built and tested in a dedicated sandbox environment first using Okta sandbox, a Jira sandbox project (project key: ITSB), and a Slack test workspace. No production API calls are made during the build phase. Okta's preview sandbox supports full lifecycle and factor APIs. Google Workspace testing uses a test Google Workspace domain. Once all three agents pass sandbox testing, a controlled production pilot is run with two real requests observed by the FullSpec team before full go-live.
Estimated total build time
Request Intake Agent: 8 hours. Verification and Approval Agent: 10 hours. Provisioning and Audit Agent: 8 hours. End-to-end integration testing, error path validation, and QA: 2 hours. Total: 28 hours (aligns with confirmed build effort).
Before build starts, the following must be confirmed: Okta service account credentials and admin role scope; Jira project key, board ID, and Done transition ID; Slack app installation with slash command and interactive components enabled; Azure AD application registration with User.Read.All permission; Google Workspace service account with domain-wide delegation and directory.group.member scope; and the system-name-to-Okta-role and system-name-to-Google-group mapping table. Contact support@gofullspec.com to initiate the credentials handover checklist.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Password Reset & Access Requests.

Launch Plan
Operations · Owner
View
ROI and Business Case
Finance · Owner
View
Process Runbook / SOP
Operations · Owner
View
Integration and API Spec
Technical · Developer
View
Test and QA Plan
Quality · Developer
View