skip to content

A driver moves to another member firm and takes on new duties, so why does a grants model that only ever adds eventually let them do everything?

level: seniorimportance: should knowfreq 45%

answer

  1. joiner, mover, leaver — the middle one
  2. addition has no opposite
  3. compute the target, not the history
  4. diff both directions in one transaction
  5. zero removals is a bug signal

basics

~20 s

A move is two operations — grant the new authority and withdraw the old — and pipelines usually implement only the first. Unioned grants accumulate across moves until someone who has changed firm three times holds the union of all three.

solid answer

~50 s

Joiners and leavers get attention because they are visible events; the mover is the case teams skip, and it is where standing access quietly builds up. If a change of firm or role is applied by adding whatever the new position implies, nothing ever takes the old position's authority away. After three moves a driver holds the union of three roles at three firms, which is more than anyone ever approved. The fix is to treat authority derived from employment as a **computed target set**, not a log of additions: recompute what this person should hold given their current firm and duties, diff it against what they hold, and apply removals as well as additions in the same transaction. Grants that were made by hand rather than derived must carry that origin, because a recomputation is not entitled to remove them — it flags them for review instead. Make the removals observable: a move that removes nothing is usually a bug, not a person whose duties genuinely overlapped.

code

pseudocode · 20 lines
pseudocode
on employment_change(person):
    employment = source_of_truth.current(person)   # firm, role, depot today
    target     = derive_grants(employment)         # what they SHOULD hold now
    held       = account.grants(person)

    derived_held = held.where(origin == DERIVED)
    manual_held  = held.where(origin == MANUAL)

    to_add    = target - derived_held
    to_remove = derived_held - target              # the half that is usually missing

    transaction:
        account.grant(person, to_add, origin = DERIVED)
        account.revoke(person, to_remove)

    audit.record(person, employment, to_add, to_remove,
                 skipped = manual_held - target)   # manual grants: report, do not strip

    if to_add.isEmpty() and to_remove.isEmpty():
        metrics.count("move.no_op")                # expected sometimes; alert on a population of them

go deeper

for a junior

Recall that people change roles as well as arrive and leave, and that a change of role has to take authority away as well as give it.

for a middle

Explain why a log of additions cannot express a move, and describe recomputing a target set from current employment facts and applying the difference in both directions.

for a senior

Show the origin column that protects hand-made grants from recomputation, the diff record per move, and the alert on a population of moves that removes nothing.

for a principal

Decide how much standing authority the cooperative tolerates between the employment change and the effective removal, and whether manual grants are permitted at all without an owner and an expiry.

In a haulage cooperative's shared hours system, drivers do not only join and leave — they move. A driver transfers between member firms, is promoted from driving to scheduling, or covers a depot for a season. The joiner and the leaver are conspicuous events that somebody has built a pipeline for. The mover is the case that gets skipped, and it is the one that produces a person who can do everything. ## Why a move is two operations A move is **grant the new authority and withdraw the old, atomically**. A pipeline that responds to a change by adding what the new position implies performs half of it. Nothing in the flow ever asks what the previous position implied, so the old authority persists. The accumulation is not dramatic — it is one extra capability per move, which is exactly why nobody notices until an access review finds a scheduler at one firm who can still approve hours at two others. The subtle part is that this frequently does not look like a bug in the data. Every grant the person holds was legitimately granted at the moment it was made. The defect is the missing withdrawal, and a log of additions has no representation for it. ## Compute the target, then diff The repair is to stop storing authority as a history of additions and start deriving it: 1. **Compute the target set** for the person from their current employment facts — firm, role, depot — as the source of truth states them today. 2. **Diff** that target against what the account currently holds. 3. **Apply both halves** — additions and removals — in one transaction, so the account is never momentarily holding neither or both. The point that distinguishes a senior answer is step 3's removals being non-optional and being *derived*, not hand-picked. If the pipeline can only ever be told to add, a move cannot be expressed at all. ## Not every grant may be recomputed away A recomputation that removes everything it did not derive will strip authority someone deliberately granted by hand, so each grant carries its origin: | grant origin | on a move | why | |---|---|---| | derived from the firm's group membership or role | recomputed and removed automatically | the source of truth owns it end to end | | granted by hand by a cooperative administrator | kept, and flagged for review | the sweep cannot know the intent behind it | | temporary cover, granted with an expiry | expires on its own; the move does not extend it | its lifetime was bounded at grant time | | held by an account with no current employment record | quarantined and reported | the person may not be anywhere at all | The honest answer to an interviewer is that the second row is where real systems leak, and the mitigation is not to forbid manual grants but to force them to carry an owner and a review date. ## The event usually does not say "move" A move often arrives as a plain attribute change — a department value, a group membership — with no marker that a transition happened, and some sources emit it as a removal and an addition that can arrive out of order or in separate batches. Some employment systems really do emit a leaver and a joiner pair, which is worse: applied literally it deletes and recreates the person. Because the shape of the event cannot be relied upon, the target-and-diff model is what makes moves safe — it converges on the same state whichever way the change turns up, and it converges again when the next scheduled comparison runs. ## Make removal observable Removals are the half nobody sees, so instrument them: - log the diff — grants added, grants removed, grants skipped because they were manual — as one record per move, with the employment change that triggered it; - alert when a move applies additions and **zero** removals across a population, which almost always means the removal branch is not wired rather than that duties genuinely overlapped; - track authority per person over time, because monotonic growth across an estate is the signature of this defect; - state the window between the employment change and the effective removal, and treat it the way a leaver window is treated. And remember what the diff does not do by itself: withdrawing a grant changes what future decisions allow, but access already in flight continues until the sessions and tokens carrying the old authority are ended or expire. The removal half of a move has a lag for the same reason a departure does, and the design owns that number.

  • A recomputation would remove a grant a cooperative administrator added by hand last month. What should happen?
    It is kept and reported, not removed. The pipeline derives authority from employment facts and has no knowledge of why a human granted something, so stripping it would silently undo a deliberate decision. Manual grants should be required to carry an owner and a review date so the report has somewhere to go rather than accumulating as permanent exceptions.
  • How would you detect that the removal half has quietly stopped working?
    Alert on shape, not on individual moves. If a whole population of employment changes produces additions and zero removals, the removal branch is almost certainly unwired. Reinforce that with authority-per-person tracked over time: across an estate that figure should be roughly flat, and monotonic growth is the signature of an add-only pipeline.
  • The change arrives as a removal from one group and an addition to another, in separate batches, out of order. Does that break the model?
    No, and that is the argument for it. Each application recomputes the target from the employment facts as they currently stand rather than replaying deltas, so whichever batch lands first the account converges on a correct state, and the next scheduled comparison converges again if a batch was dropped entirely.

A depot keyring. Every time a driver changes depot they are handed the new depot's key, and nobody ever asks for the old one back. Each handover is individually reasonable, and after three moves one person can open every gate in the cooperative.

saying these in an interview costs you the question

  • Moves are just a joiner event with different data
  • Access reviews every quarter will catch accumulated grants
  • Authority should be the union of everything ever granted
  • A recomputation can safely remove every grant it did not derive
  • Removing a grant ends access that is already in flight