Feature breakdown · built with CraftHQ
Add a user from the company directory
Hands-on build time
~1.8 to 2.8 h
Measured — hands-on build time, from the visible commits
Whole-team time at this build's pace
2 people incl. the product owner, requirements to merge
Estimate at this build's pace, not a measurement of this feature
An admin adds a user by their directory id; the id is verified against the company directory and the name is filled in, and the user is added once the admin confirms. Nothing is emailed.
How long a feature this size usually takes
Whole-team time — this build vs a typical team
6 FP · FP × 6.8 to 9.4 h (ISBSG 2023)
Estimate at this build's pace, not a measurement of this feature
Hands-on build time: ~1.8 to 2.8 h, measuredhands-on build time, from the visible commits
Both figures are whole-team time over the whole lifecycle, so they compare like for like. Ours is this build's pace — about 0.8 hours per function point across the whole build (two people, including the product owner, with requirements and review time). The industry range is an ISBSG project-level figure applied to one feature, so it is indicative.
Workflow
How it moved through the workflow
Select a stage. The build shipped, so every stage is complete; a person approved the merge.
Request
Add a user by their directory ID, verified live against the directory, with the name filled in, so identities are not mistyped.
Questions
One decision went to the business before building: show the directory lookup to the admin, or do it silently.
Approved
The product owner signs off the breakdown by moving the story into the approved state, and the build runs against that reference.
Definition of ready
Building
CraftHQ's build agents write the code and the tests together, run as a loop; a failing check halts the work until it passes.
Checks
Three checks run on every pull request: one on the product owner's machine as CraftHQ builds, one on the engineer's machine before review, and a code-quality scan in CI. Merging is gated by the CI check passing and a person's approval, enforced by branch protection.
Review
An engineer reviews the pull request and merges it.
Merged
The pull request is merged to main after a person approves it. Nothing merges without that approval.
Definition of done
Breakdown
The feature breakdown
Business first, then the engineering view. Tab through it.
Overview
The gap it closes
Typing a new user's name and identity by hand invites mistakes and a mismatch with the real directory.
Who uses it
Administrators adding a user to their organisation.
User story
As an admin, I want to add a user by their directory ID so that their identity is directory-verified and their name is filled in for me.
Examples
Example 1
An admin enters a valid directory ID. The directory is checked, the name is filled in, and the admin adds the user.
Example 2
An admin enters a directory ID that does not resolve. The admin sees a clear rejection, and no user is added.
Dependencies & risks
Depends on
A configuration-driven staff-domain allowlist, and a reachable company directory to verify the id and return the name.
Risk & mitigation
A wrong-domain or an identity that cannot be verified could be added. Reduced by a domain allowlist checked before any directory call and again on create (the same primitives as the sign-in path), and by confirming the id against the directory and failing closed on an unknown or unreachable result.
How it works
Simplified diagrams of the parts involved, the steps of one request, and where it runs.
Architecture
- 1enter a directory ID
- 2check the ID
- 3verify, read the name
- 4add the verified user
Sequence
- 1add a user by directory ID
- 2verify the ID
- 3resolved name or not found
- 4show the check result
- 5admin confirms
- 6add the verified user
Infrastructure
- 1add by directory ID
- 2verify the ID
- 3write the verified user
Acceptance criteria
Each scenario is written as a Gherkin spec. The Engineering tab shows the test that covers each one, or notes where it was verified by review.
@users-access @adminFeature: Add a user from the company directoryAs an adminI want to add a user by their directory idSo that their identity is directory-verified and their name is filled in for meAdding a user takes a directory id, verifies it against the company directory, fills in the name and, once the admin confirms, adds the user. Nothing is emailed; the user is added directly.Background:Given an admin is signed inRule: Only an admin may add a user from the directoryScenario: A non-admin cannot add a userGiven a signed-in user without the admin roleWhen they call the add-from-directory actionThen the action is refused on the serverRule: A new user is verified against the directory before the admin confirmsScenario: Adding a user by a valid directory idGiven an admin enters a valid directory id for an active directory account on an approved domainWhen the directory is checkedThen the directory result and the filled-in name are shown to the adminAnd the user is added only after the admin confirmsAnd the user is stored with the directory's name and immutable object idScenario: A directory id that does not resolve is rejectedGiven an admin enters a directory id that does not resolveWhen the directory is checkedThen the admin sees a clear rejectionAnd no user is addedRule: Unsafe or duplicate directory accounts are refusedScenario Outline: Directory ids that are refusedGiven an admin enters a directory id that is "<condition>"When the directory is checkedThen the add is refused with a clear messageAnd no user is addedExamples:| condition || already a user in this organisation || a disabled account in the directory || on a domain not in the approved list |Rule: A directory outage fails closedScenario: The directory is unreachableGiven the company directory is unreachableWhen an admin tries to add a user by directory idThen the add cannot proceed and the admin is told to try again laterAnd no user is added
Questions
Questions raised in planning, each with the decision taken.
Should the directory lookup be shown to the admin, or done silently?
Showing the check tells the admin the identity is verified; a silent lookup hides whether it succeeded.
How we sized it
A function point measures what the software does — its inputs, outputs, lookups and the data it stores — regardless of language or how many lines it took. Each counted item is weighted by complexity: a user input counts 3–6 points, an output or report 4–7, a lookup 3–6, data the feature owns 7–10, and data read from elsewhere 5–7.
- Add a user by their directory ID, verified against the company directoryUser input6
- Total6
Not counted here
- The user records: counted once, under User management
Components touched
Domain allowlist
The email domain must be on a configuration-driven staff-domain allowlist, checked in the service before any directory call and again on create, using the same primitives as the sign-in path. A wrong-domain email is hard-rejected.
Live directory lookup
Confirms the entered directory id against the company directory before a user is added and shows the result to the admin; an unknown or unreachable result is refused (fail-closed). The preview endpoint is admin-only and uses the same resolution, so it cannot drift from the add.
Name auto-fill
Fills the name from the directory, shown back to the admin as a verified result; the user is stored and matched on the immutable directory object id, not on an email that can change.
Rejection messages
A clear admin-facing message when an id does not resolve, is already a user, is a disabled account, or is on a non-approved domain.
Data touched
User rowswrite
A new user is tied to the verified directory identity by its immutable object id; email uniqueness is case-insensitive and enforced in the database, and a cross-tenant mapping is blocked.
Company directoryexternal
It is read to verify the id and return the name. The immutable directory object id is recorded on first add and matched on afterwards.
Security decisions
- Only an admin role reaches the add-from-directory action and the preview, enforced on the server.
- The email domain must be on a configured allowlist, checked before any directory call and again on create.
- The identity is verified against the company directory and matched on the immutable object id, failing closed on an unknown or unreachable result.
- A directory id that is already a user, a disabled account, or on a non-approved domain is refused, and no user is created.
- Email uniqueness is case-insensitive and enforced in the database, and a cross-tenant mapping is blocked.
Subtasks
- A configuration-driven staff-domain allowlist checked before any directory call and on create.
- A live directory lookup on add, matched on the immutable object id.
- Name auto-fill from the directory, and an admin-only preview using the same resolution.
- Clear admin rejection messages.
How each scenario is verified
- A wrong-domain email is refused before any directory workA domain-enforcement test rejects a disallowed public domain with the contracted message before any database work and passes a configured domain, reusing the sign-in allowlist primitives.
- Adding by a directory id and the sign-in pathCovered by the directory and sign-in path tests, including alias de-duplication.
- An unresolved directory id is refusedVerified by review of the fail-closed path.
Risk tier
Logic A person approves every merge. This is a Logic-tier change; it carries automated tests for its rules.
Activity
The visible commits (not squashed) cluster into about 1.8 to 2.8 hours of focused work.
- First of three visible commits
- Corrected and completed
- Merged to main after a person approved
Start here
Want this on your backlog?
Get a free baseline report on one repository, or scope a 3-month pilot measured against what your team’s work costs today.