Chapter 9 — Stale account lab
Lesson map
Lesson 09 published. Map, example, EX033.
flowchart TD
N0["Learning outcomes"]
N1["9.1 The report"]
N2["Lab — Stale accounts"]
N3["9.2 Interpreting results"]
N4["9.3 Deciding actions"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Worked example"]
EX --> Q["Exercise EX033"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["9.1 The report"]
N2["Lab — Stale accounts"]
N3["9.2 Interpreting results"]
N4["9.3 Deciding actions"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX033"]
[Learning outcomes]
|
v
[9.1 The report]
|
v
[Lab — Stale accounts]
|
v
[9.2 Interpreting results]
|
v
[9.3 Deciding actions]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX033]
Learning outcomes
You will (1) run a stale account report on synthetic data; (2) interpret stale and ownerless accounts; (3) decide actions with owners.
9.1 The report
Tomas writes a standard-library script that reads a synthetic export of Millbrook's directory and reports enabled accounts with no sign-in for more than 90 days, and enabled accounts with no owner on the staff list. The script only reads the synthetic data and prints a list for review. It ignores disabled accounts, which are already handled by the leaver process, so attention goes to accounts that could still be used today. He first tests it with a small file whose answers he already knows, and he saves each report with its run date for comparison.
Lab — Stale accounts
"""Stale account report on synthetic directory data (read-only)."""
from datetime import date
TODAY = date(2026, 3, 31)
LIMIT_DAYS = 90
# username, enabled, last sign-in, owner listed in HR?
ACCOUNTS = [
("a.shaw", True, date(2026, 3, 30), True),
("b.khan", True, date(2026, 3, 28), True),
("c.dunn", True, date(2025, 11, 2), True),
("d.reyes", True, date(2025, 9, 14), False),
("e.ford", False, date(2025, 6, 1), False),
("f.lin", True, date(2026, 2, 20), True),
("scanner", True, date(2026, 3, 31), True),
("temp-01", True, date(2025, 12, 1), False),
("g.moss", True, date(2026, 1, 15), True),
("h.patel", True, date(2026, 3, 29), True),
]
def main():
enabled = [a for a in ACCOUNTS if a[1]]
stale = [a for a in enabled if (TODAY - a[2]).days > LIMIT_DAYS]
orphan = [a for a in enabled if not a[3]]
print(f"accounts {len(ACCOUNTS)}, enabled {len(enabled)}")
for u, _, last, _ in stale:
print(f"stale: {u} ({(TODAY - last).days} days)")
print("enabled with no HR owner:", ", ".join(a[0] for a in orphan))
if __name__ == "__main__":
main()
Run with python3 lab_stale.py. Verified output:
accounts 10, enabled 9
stale: c.dunn (149 days)
stale: d.reyes (198 days)
stale: temp-01 (120 days)
enabled with no HR owner: d.reyes, temp-01
9.2 Interpreting results
The run reads 10 accounts, 9 enabled. Three are stale: c.dunn at 149 days, d.reyes at 198 days and temp-01 at 120 days. Two enabled accounts have no staff-list owner: d.reyes and temp-01. Tomas notes that d.reyes is both stale and ownerless, the strongest sign of a forgotten account. c.dunn has an owner, so the question is why she has not signed in, perhaps long-term leave, rather than whether the account should exist at all. He checks each finding by hand against the synthetic file before sharing it.
9.3 Deciding actions
Tomas brings the list to the practice manager. d.reyes was a locum who left last year, so the account is disabled. temp-01 was created for a temporary receptionist and never removed; it is disabled. c.dunn is a dentist on parental leave, so her account stays enabled but is recorded with an expected return date. The scanner account signed in today and has an owner, so it is fine. Decisions are made by the owner, using the report as evidence. Each decision is recorded.
Worked example
The report shows 3 stale and 2 ownerless accounts among 9 enabled; two are disabled and one parental-leave account is recorded.
Synthetic case. Accounts and the script are synthetic.
Errors and limits
Disabling every stale account automatically would lock out staff on leave.
Exercises
- EX033 — Stale list. Which accounts were stale? Rubric: 3 = c.dunn, d.reyes, temp-01;; 2 = three;; 1 = scanner;; 0 = none.
- EX034 — Ownerless. Which enabled accounts had no owner? Rubric: 3 = d.reyes and temp-01;; 2 = two;; 1 = c.dunn;; 0 = none.
- EX035 — Strongest sign. Why is d.reyes the strongest concern? Rubric: 3 = both stale and ownerless;; 2 = both;; 1 = name;; 0 = none.
- EX036 — Leave case. What happened to c.dunn's account? Rubric: 3 = stays enabled with return date recorded;; 2 = kept;; 1 = disabled;; 0 = none.
Synthesis
A read-only stale report, reviewed with owners, removes forgotten accounts without harming absent staff.
Continue studying — chapter 09 of 18
← Chapter 08 (draft) · Course chapter index · Chapter 10 (draft) →