# Identity lifecycle: join, move and leave

Move from account tickets to verified access outcomes. Track ownership and lifecycle separately for employees, suppliers and application identities.

Original AI-assisted SecNet educational content. Fictional local examples; not a standards provider publication, endorsement or compliance evidence. Page exercises do not create account progress.

Sources checked: 2026-10-21

## Identity source and account distinction

Ada joins fictional Harbor. An HR record identifies the person and effective date; an application account represents access in one system. One person may hold multiple accounts, while an application identity may represent no person at all. Map stable identity, authoritative source, manager/sponsor and access owner. Treating email as immutable person identity risks mismatches after renaming or reuse. Every name here is synthetic. NIST SP 800-63-4 became final in July 2025; identity assurance and the organization’s business authorization still require separate assessments.

## Provision access for an actual need

Instead of copying a colleague’s entire access, specify the job task, resource, action and duration. Even default role-catalog entitlements need resource-owner review. Record the sponsor’s request, approver authority and actual target-application outcome. Closing a ticket does not establish correct provisioning scope. Review appropriate enrollment and recovery arrangements before first use. Harbor creates no real accounts; learners locate gaps between requests, authoritative records, approval and target verification. A neat request form is useful evidence but is not proof that the application enforced the intended permissions.

## Access accumulation after a move

When Ada moves from procurement to audit, adding the new role while leaving the old one creates access accumulation. Review prior entitlements, group memberships, temporary privileges and separation-of-duties conflicts together. If a brief overlap is needed, document its rationale, expiry and risk owner. A manager change does not automatically supply application-owner approval. Distinguish future effective dates from actual execution times. Verify target outcomes and failed-operation queues; a successful synchronization indicator cannot establish that every downstream application applied the intended change.

## Leaving involves more than blocking a directory account

Departure review covers directory access, application sessions, local accounts, vendor access and person-dependent automations. Transfer record and data ownership through authorized processes; keeping access because colleagues share its password is not a solution. Document provider-specific token and session behavior. Exit evidence distinguishes requested time, operation applied at the target and authorized verification results. This exercise blocks no real person, makes no HR decision and ends no application session. It teaches why lifecycle closure must demonstrate an outcome rather than merely a completed central-directory ticket.

## Working sequence

1. Record the identity source and effective date.
2. Map business need to resource and action.
3. Review prior access and conflicts.
4. Identify evidence needed to verify target outcomes.
5. Assign owners and deadlines to open closure work.

## 1. Ticket exists: is the source authoritative?

A ticket alone verifies neither identity, effective date nor access ownership. Without an authoritative record and named owner, provisioning is not tied to a traceable business decision.

This code is a local policy model; it does not replace actual authentication, token validation or live permission tests.

### Weak implementation
```js
s => s.requestExists === true
```

### Corrected implementation
```js
s => s.requestExists === true &&
  s.authoritativeSource === true &&
  s.ownerNamed === true &&
  s.effectiveDate === true
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "documented-case",
      "input": {
        "requestExists": true,
        "authoritativeSource": true,
        "ownerNamed": true,
        "effectiveDate": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-authoritativeSource",
      "input": {
        "requestExists": true,
        "authoritativeSource": false,
        "ownerNamed": true,
        "effectiveDate": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "missing-ownerNamed",
      "input": {
        "requestExists": true,
        "authoritativeSource": true,
        "ownerNamed": false,
        "effectiveDate": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "documented-case",
      "input": {
        "requestExists": true,
        "authoritativeSource": true,
        "ownerNamed": true,
        "effectiveDate": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-authoritativeSource",
      "input": {
        "requestExists": true,
        "authoritativeSource": false,
        "ownerNamed": true,
        "effectiveDate": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "missing-ownerNamed",
      "input": {
        "requestExists": true,
        "authoritativeSource": true,
        "ownerNamed": false,
        "effectiveDate": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## 2. Is adding the new role sufficient?

Adding a role does not remove old permissions. Without reviewing previous access, conflicts and target outcomes, treating the move as complete hides accumulated privileges.

This code is a local policy model; it does not replace actual authentication, token validation or live permission tests.

### Weak implementation
```js
s => s.newRoleAdded === true
```

### Corrected implementation
```js
s => s.newRoleAdded === true &&
  s.oldRoleReviewed === true &&
  s.conflictChecked === true &&
  s.targetVerified === true
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "documented-case",
      "input": {
        "newRoleAdded": true,
        "oldRoleReviewed": true,
        "conflictChecked": true,
        "targetVerified": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-oldRoleReviewed",
      "input": {
        "newRoleAdded": true,
        "oldRoleReviewed": false,
        "conflictChecked": true,
        "targetVerified": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "missing-targetVerified",
      "input": {
        "newRoleAdded": true,
        "oldRoleReviewed": true,
        "conflictChecked": true,
        "targetVerified": false
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "documented-case",
      "input": {
        "newRoleAdded": true,
        "oldRoleReviewed": true,
        "conflictChecked": true,
        "targetVerified": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-oldRoleReviewed",
      "input": {
        "newRoleAdded": true,
        "oldRoleReviewed": false,
        "conflictChecked": true,
        "targetVerified": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "missing-targetVerified",
      "input": {
        "newRoleAdded": true,
        "oldRoleReviewed": true,
        "conflictChecked": true,
        "targetVerified": false
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## 3. The directory account is disabled

A central block does not prove every application session ended. Verify downstream access, sessions and ownership transfer separately; this model revokes no actual access.

This code is a local policy model; it does not replace actual authentication, token validation or live permission tests.

### Weak implementation
```js
s => s.directoryDisabled === true
```

### Corrected implementation
```js
s => s.directoryDisabled === true &&
  s.sessionsReviewed === true &&
  s.downstreamVerified === true &&
  s.assetsTransferred === true
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "documented-case",
      "input": {
        "directoryDisabled": true,
        "sessionsReviewed": true,
        "downstreamVerified": true,
        "assetsTransferred": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-sessionsReviewed",
      "input": {
        "directoryDisabled": true,
        "sessionsReviewed": false,
        "downstreamVerified": true,
        "assetsTransferred": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "missing-downstreamVerified",
      "input": {
        "directoryDisabled": true,
        "sessionsReviewed": true,
        "downstreamVerified": false,
        "assetsTransferred": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "documented-case",
      "input": {
        "directoryDisabled": true,
        "sessionsReviewed": true,
        "downstreamVerified": true,
        "assetsTransferred": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-sessionsReviewed",
      "input": {
        "directoryDisabled": true,
        "sessionsReviewed": false,
        "downstreamVerified": true,
        "assetsTransferred": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "missing-downstreamVerified",
      "input": {
        "directoryDisabled": true,
        "sessionsReviewed": true,
        "downstreamVerified": false,
        "assetsTransferred": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## Exit evidence

- Lifecycle record naming source, sponsor, resource owner and effective date.
- Outcome matrix for directory, applications, sessions and transferred ownership.

## References

- [NIST SP 800-63-4 · Digital identity guidelines · Final July 2025](https://pages.nist.gov/800-63-4/)
- [Microsoft Entra · Revoke user access and session limits](https://learn.microsoft.com/en-us/entra/identity/users/users-revoke-access)
