Documentation Index
Fetch the complete documentation index at: https://docs.provisionr.io/llms.txt
Use this file to discover all available pages before exploring further.
Sarah got promoted from Sales Engineer to Engineering Manager. Congratulations, Sarah.
Her HRIS record updates: job_title: "Engineering Manager", department: "Engineering".
The policy engine recalculates her access:
Should add: Engineering Manager group. People management tools. Budget dashboards.
Should remove: Salesforce (no longer in Sales). Sales Team Slack channels. Customer-facing tools.
The orchestration layer provisions the new access and revokes the old access.
Within 30 seconds, Sarah loses access to: All her customer accounts in Salesforce. Sales team communications. Customer success collaboration tools.
She’s in the middle of handing off three enterprise deals to her replacement. She needs Salesforce access for another month. She needs Sales Slack access to coordinate handoffs. She needs customer context to brief her replacement.
The automation just broke her transition.
This is why organizations need graceful deprecation—the practice of removing access gradually, with defined overlap periods, rather than revoking everything immediately when someone’s role changes.
Policy-based access is correct in principle: When someone’s role changes, their access should match their new role.
Policy-based access is wrong in practice: Role changes aren’t instantaneous. There’s a transition period where people need:
- Access from their old role (to hand off responsibilities)
- Access from their new role (to start new responsibilities)
- Time to adjust (customer context can’t be transferred instantly)
If old access is immediately revoked:
Handoffs break
Knowledge transfer requires access to the systems where knowledge lives.
Productivity drops
People spend time searching for who can help instead of working.
Frustration rises
“I can’t do my job because IT revoked everything.”
Shadow IT emerges
Manual workarounds, shared credentials.
Graceful deprecation with defined transition periods demonstrates controlled change management for access rights. The documented grace periods, with clear expiration dates and automatic revocation, satisfy SOC 2 CC6.2 (access modification) and ISO 27001 A.9.2.5 (review of user access rights) while acknowledging business continuity needs.
Graceful Deprecation Patterns
Different types of access need different deprecation strategies:
Pattern 1: Grace Period (Keep Access Temporarily)
Use case: Access that should be removed eventually, but the user needs overlap during transition.
role_transition:
user: "sarah.chen@company.com"
old_role: "Sales Engineer"
new_role: "Engineering Manager"
effective_date: "2024-11-24"
access_changes:
# Remove Salesforce, but with 30-day grace period
- resource: "salesforce:profile:sales-engineer"
action: "remove"
grace_period: "30 days"
expires_at: "2024-12-24"
justification: "30 days to hand off customer accounts"
# Remove Sales Team Slack, 14-day grace period
- resource: "slack:channel:#sales-team"
action: "remove"
grace_period: "14 days"
expires_at: "2024-12-08"
justification: "2 weeks to coordinate handoffs"
Implementation:
Instead of immediately revoking, the system:
- Marks access as “deprecated” (still active but scheduled for removal)
- Sets expiration date based on grace period
- Notifies user: “Your Salesforce access will be removed in 30 days”
- Auto-revokes on expiration date
State model:
Active → Deprecated → Expired (revoked)
↑ ↑
Grace period
Pattern 2: Downgrade (Reduce Permissions, Don’t Remove)
Use case: User still needs some access, but at a lower privilege level.
role_transition:
user: "sarah.chen@company.com"
old_role: "Sales Engineer"
new_role: "Engineering Manager"
access_changes:
# Keep GitLab access, but downgrade from Developer to Reporter
- resource: "gitlab:group:customer-solutions"
action: "downgrade"
old_permission: "developer"
new_permission: "reporter"
justification: "Still needs visibility into customer solutions, but no longer contributing code"
# Keep production access, but downgrade from Read/Write to Read-Only
- resource: "aws:prod-environment"
action: "downgrade"
old_permission: "read-write"
new_permission: "read-only"
justification: "Manager needs visibility but shouldn't be making changes"
Implementation:
The system modifies permission level instead of revoking entirely.
Pattern 3: Conditional Keep (Retain if Criteria Met)
Use case: Access should be removed unless specific conditions are met.
role_transition:
user: "sarah.chen@company.com"
old_role: "Sales Engineer"
new_role: "Engineering Manager"
access_changes:
# Keep Salesforce IF managing customer-facing team
- resource: "salesforce:profile:sales-engineer"
action: "conditional_keep"
condition:
type: "team_property"
check: "team.customer_facing == true"
if_true: "keep"
if_false: "remove_with_grace_period"
grace_period: "30 days"
Implementation:
The system evaluates the condition. If Sarah’s new team is customer-facing (Solutions Architecture, Customer Success, etc.), she keeps Salesforce. If not, it’s removed with grace period.
Pattern 4: Convert to Exception (Make Temporary Access Explicit)
Use case: Old role access becomes an exception with explicit expiration.
role_transition:
user: "sarah.chen@company.com"
old_role: "Sales Engineer"
new_role: "Engineering Manager"
access_changes:
# Convert Salesforce access to explicit exception
- resource: "salesforce:profile:sales-engineer"
action: "convert_to_exception"
exception:
justification: "Role transition - need to hand off enterprise accounts"
duration: "60 days"
requires_approval: false # Auto-approved for role transitions
notification: true # Notify user of expiration
Implementation:
Old access is removed from policy-based provisioning and added as an exception. This makes the temporary nature explicit and tracks it separately.
Pattern 5: Manager Approval for Retention
Use case: IT doesn’t know if old access should persist. Let the manager decide.
role_transition:
user: "sarah.chen@company.com"
old_role: "Sales Engineer"
new_role: "Engineering Manager"
access_changes:
- resource: "salesforce:profile:sales-engineer"
action: "request_manager_approval"
manager: "vp-engineering@company.com"
approval_request:
question: "Should Sarah retain Salesforce access in her new role?"
context: "She's transitioning from Sales Engineer to Engineering Manager. Salesforce access is not in the Engineering Manager policy."
options:
- value: "remove_immediately"
label: "Remove immediately"
- value: "remove_with_grace"
label: "Remove after 30-day handoff period"
- value: "keep_permanent"
label: "Keep permanently (if managing customer-facing team)"
Implementation:
The system sends an approval request to the manager. Based on response:
- Remove immediately
- Remove with grace period
- Keep permanently (and optionally update policy if this is a common pattern)
Implementation: Graceful Deprecation Engine
Data Model
from enum import Enum
class DeprecationAction(Enum):
REMOVE = "remove"
DOWNGRADE = "downgrade"
CONDITIONAL_KEEP = "conditional_keep"
CONVERT_TO_EXCEPTION = "convert_to_exception"
REQUEST_APPROVAL = "request_approval"
class AccessDeprecation:
def __init__(self, user, resource, action, **kwargs):
self.id = generate_id()
self.user = user
self.resource = resource # "system:resource_type:resource_id"
self.action = action
self.created_at = datetime.now()
self.status = "pending"
# Grace period settings
self.grace_period = kwargs.get("grace_period") # timedelta
self.expires_at = None
if self.grace_period:
self.expires_at = datetime.now() + self.grace_period
# Downgrade settings
self.old_permission = kwargs.get("old_permission")
self.new_permission = kwargs.get("new_permission")
# Conditional settings
self.condition = kwargs.get("condition")
# Exception conversion settings
self.exception_config = kwargs.get("exception_config")
# Approval settings
self.requires_approval = kwargs.get("requires_approval", False)
self.approver = kwargs.get("approver")
# Metadata
self.justification = kwargs.get("justification")
self.role_transition = kwargs.get("role_transition")
Deprecation Policy Configuration
# Define deprecation policies per access type
deprecation_policies:
# Salesforce access
- resource_pattern: "salesforce:*"
on_role_change:
from_departments: ["Sales", "Customer Success"]
to_departments: ["Engineering", "Product", "Finance"]
action: "remove"
grace_period: "30 days"
justification: "Standard handoff period for customer-facing roles"
# GitLab access
- resource_pattern: "gitlab:*"
on_role_change:
from_permissions: ["developer", "maintainer"]
to_permissions: ["reporter"]
action: "downgrade"
new_permission: "reporter"
justification: "Maintain visibility but remove write access"
# Production access
- resource_pattern: "aws:prod-*"
on_role_change:
from_roles: ["Engineer", "Senior Engineer"]
to_roles: ["Engineering Manager", "Director"]
action: "downgrade"
old_permission: "read-write"
new_permission: "read-only"
justification: "Managers need visibility but shouldn't make direct changes"
# Team-specific Slack channels
- resource_pattern: "slack:channel:#team-*"
on_role_change:
action: "conditional_keep"
condition:
type: "team_membership"
check: "user.new_team == channel.team"
if_true: "keep"
if_false: "remove_with_grace_period"
grace_period: "14 days"
Role Transition Handler
def handle_role_transition(user, old_attributes, new_attributes):
"""Handle access changes when user's role changes"""
# Calculate policy-based access for old and new roles
old_access = policy_engine.calculate_access(old_attributes)
new_access = policy_engine.calculate_access(new_attributes)
# Calculate delta
to_add = new_access - old_access
to_remove = old_access - new_access
to_keep = old_access & new_access
# Handle additions (straightforward)
for resource in to_add:
provision_access(user, resource)
# Handle removals (apply graceful deprecation)
deprecations = []
for resource in to_remove:
# Find applicable deprecation policy
policy = find_deprecation_policy(resource, old_attributes, new_attributes)
if policy:
# Create deprecation action
deprecation = AccessDeprecation(
user=user,
resource=resource,
action=policy.action,
grace_period=policy.grace_period,
old_permission=policy.old_permission,
new_permission=policy.new_permission,
condition=policy.condition,
justification=policy.justification,
role_transition={
"old_role": old_attributes.job_title,
"new_role": new_attributes.job_title,
"effective_date": new_attributes.effective_date
}
)
# Execute deprecation
result = deprecation.execute()
deprecations.append(deprecation)
else:
# No policy - default to immediate removal (with warning)
log_warning(f"No deprecation policy for {resource}. Removing immediately.")
revoke_access(user, resource)
# Handle resources that stay but might need permission updates
for resource in to_keep:
check_permission_changes(user, resource, old_attributes, new_attributes)
return {
"added": to_add,
"removed": to_remove,
"deprecations": deprecations
}
Real-World Scenarios
Scenario 1: Sales Engineer to Engineering Manager
Attributes change:
old:
job_title: "Sales Engineer"
department: "Sales"
team: "Enterprise Sales"
new:
job_title: "Engineering Manager"
department: "Engineering"
team: "Solutions Engineering"
Access changes:
| Resource | Old Access | New Access | Deprecation Action |
|---|
| Salesforce | Sales Engineer profile | (none) | Remove after 30 days (customer handoff) |
| Slack #sales-team | Member | (none) | Remove after 14 days (coordination) |
| Slack #customer-success | Member | (none) | Remove after 14 days |
| GitLab customer-solutions | Developer | Reporter | Downgrade immediately (context, not code) |
| Slack #engineering | (none) | Member | Add immediately |
| PeopleOps tools | (none) | Manager access | Add immediately |
Timeline:
- Day 0: Promotion effective. Engineering access added immediately.
- Day 1-14: Sarah has both Sales and Engineering access (overlap period)
- Day 14: Sales Slack channels removed
- Day 30: Salesforce removed
- Day 30+: Only Engineering access remains
Attributes change:
old:
job_title: "Engineer"
level: "L3"
new:
job_title: "Senior Engineer"
level: "L4"
Access changes:
| Resource | Old Access | New Access | Deprecation Action |
|---|
| Production | (none) | Read-only | Add immediately |
| On-call tools | (none) | Full access | Add immediately |
| GitLab | Developer | Maintainer | Upgrade immediately |
No deprecation needed—this is a promotion within the same department. Only additions and upgrades.
Attributes change:
old:
job_title: "Engineering Manager"
level: "M3"
new:
job_title: "Director of Engineering"
level: "M4"
Access changes:
| Resource | Old Access | New Access | Deprecation Action |
|---|
| Production | Read-write | Read-only | Downgrade immediately (managers don’t deploy) |
| Budget tools | Team-level | Org-level | Upgrade immediately |
| Strategic planning tools | (none) | Full access | Add immediately |
Rationale: Directors need less hands-on access and more strategic access.
User Communication
Users must know when their access will change.
On Role Transition
Subject: Your access is updating following your promotion
Hi Sarah,
Congratulations on your promotion to Engineering Manager!
Your access is being updated to match your new role:
Added immediately:
- Engineering Manager group
- People management tools (BambooHR, Lattice)
- Budget dashboards
Temporary access (will expire):
- Salesforce (expires Dec 24) - 30 days to hand off accounts
- Slack #sales-team (expires Dec 8) - 14 days for coordination
Downgraded:
- GitLab customer-solutions: Developer to Reporter (visibility maintained)
Questions about access? Reply to this email or ping #it-help.
— IT Team
Before Expiration
Subject: Reminder: Your Salesforce access expires in 7 days
Hi Sarah,
Your temporary Salesforce access expires in 7 days (Dec 24).
This access was granted during your transition from Sales Engineer to Engineering Manager for account handoffs.
If you still need Salesforce access:
[ Request Extension ] (requires VP approval)
If handoffs are complete:
No action needed - access will be automatically removed on Dec 24.
Questions? Reply to this email.
— IT Team
Monitoring Graceful Deprecation
Track these metrics:
Active deprecations. How many access grants are in grace period?
Average grace period duration. Are grace periods too long or too short?
Extension rate. What percentage of deprecations are extended?
Manual revocations. How often is access manually revoked before expiration?
Dashboard:
Graceful Deprecation Dashboard
Active Deprecations: 18
├─ Expiring this week: 5
├─ Expiring this month: 13
└─ Extended (this month): 2
Average grace period: 24 days
Extension rate: 8% (healthy - most expire as planned)
Most common deprecations:
1. salesforce:* (8 active)
2. slack:#sales-* (4 active)
3. gitlab:customer-solutions (3 active)
The Bottom Line
Immediate revocation breaks role transitions. Graceful deprecation makes them smooth.
Key patterns:
Grace period
Keep access temporarily—30 days for handoffs.
Downgrade
Reduce permission, don’t remove—Developer to Reporter.
Conditional keep
Retain if criteria met—customer-facing team keeps CRM.
Convert to exception
Make temporary access explicit.
Manager approval
Let the manager decide edge cases.
Implementation requirements:
- Deprecation policies (define how each access type should be removed)
- State tracking (active → deprecated → expired)
- Scheduled removal (auto-revoke on expiration)
- User notifications (communicate changes and timelines)
Timeline: 2-3 weeks to implement graceful deprecation on top of policy-based access.
Access shouldn’t be yanked immediately when roles change. Give people time to transition. That’s the difference between automation that helps and automation that breaks things.
Next up: Building audit-ready compliance—how to make auditors appreciate the access management system.
Want to see graceful deprecation in action? Explore Provisionr’s transition policies