Feature breakdown · built with CraftHQ
Session timeout with inactivity warning
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 idle session warns the user with a countdown, then signs them out, so an unattended screen does not stay open.
How long a feature this size usually takes
Whole-team time — this build vs a typical team
8 FP · FP × 6.8 to 9.4 h (ISBSG 2023)
Estimate at this build's pace, not a measurement of this feature
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
Protect an unattended screen: warn the user before an idle session ends and then sign them out, with the timeout configurable.
Questions
One design decision was recorded before building.
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
An unattended, signed-in screen is a risk, but signing people out with no warning loses their work.
Who uses it
Every signed-in user, staff or customer.
User story
As a signed-in user, I want a warning before my session ends so that I am not signed out mid-task without notice.
Examples
Example 1
A user steps away. Near the timeout a countdown appears; they return, choose to stay signed in, and the session continues.
Example 2
A script quietly pings the server to keep the session alive without the user touching the screen. It does not count as activity, so the session still times out; and the server, not the browser, decides when a session has expired.
Dependencies & risks
Depends on
A 30-minute idle timeout, an absolute maximum session lifetime (12 hours for staff, 24 hours for customers), and a server that holds the authoritative remaining time and enforces it.
Risk & mitigation
A client-only timer could be stretched from the browser. Reduced by having the server own expiry and cap the absolute lifetime; the browser countdown only mirrors the server's expiry instant.
How it works
Simplified diagrams of the parts involved, the steps of one request, and where it runs.
Architecture
- 1activity or idle
- 2near timeout
- 3re-sync remaining time
- 4record the expiry
Sequence
- 1check remaining session time
- 2time remaining
- 3stay signed in (real activity)
- 4extend on activity, or expire when idle or past the lifetime
- 5continue or sign out
Infrastructure
- 1session check (authenticate + tenant check)
- 2read and write the session
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.
@sign-in @securityFeature: Session timeout with inactivity warningAs a signed-in userI want a warning before my session endsSo that I am not signed out mid-task without noticeAn idle session shows a countdown warning, then signs the user out. The server decides expiry; the browser timer only displays it.Background:Given a user is signed inAnd an idle timeout and an absolute maximum lifetime are configuredRule: A warning appears before an idle session endsScenario: The countdown warns before sign-outGiven a user has been idle and is near the timeoutWhen the warning threshold is reachedThen a live countdown warns the user the session will endScenario: Staying active keeps the sessionGiven the inactivity warning is showingWhen the user chooses to stay signed inThen the session continuesAnd the countdown clearsRule: An idle session is signed out and recordedScenario: Idle sign-outGiven a user has been idle with no activityWhen the countdown reaches zeroThen the user is signed outAnd a background job records the expiry in the audit trailRule: The server decides expiryScenario: The browser timer cannot extend the sessionGiven a user's browser still shows time remainingBut the server considers the session expiredWhen the user takes their next actionThen the server rejects it and signs the user outScenario: The absolute lifetime caps the sessionGiven a user has stayed active up to the absolute maximum lifetimeWhen the next request is made after the lifetime is reachedThen the session ends regardless of activity@edge-casesScenario Outline: Session states near the timeoutGiven a user has been idle for "<idle>"When the timer is checked against the serverThen the result is "<result>"Examples:| idle | result || under the threshold | session active || within the warning | countdown showing || past the timeout | signed out |
Questions
Questions raised in planning, each with the decision taken.
Should the timeout be a client-only timer, or owned by the server?
A client-only timer is simple but can be stretched from the browser and kept alive by a script without a real user. A server-owned timer decides expiry centrally and only resets on genuine activity.
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.
- Show the time left before sign-outLookup4
- Extend the session to stay signed inUser input4
- Total8
Not counted here
- Session plumbing: technical, not a user function
Components touched
Session-timeout module
A client-side module that tracks idle time from real user activity and shows the warning modal near the timeout.
Warning modal
A live countdown with a stay-signed-in action.
Idle and absolute limits
A 30-minute idle timeout and an absolute maximum session lifetime (12 hours for staff, 24 hours for customers), enforced by the server.
Server-owned expiry
The server holds the authoritative remaining time, decides expiry, and a background job records each expiry in the audit trail. The browser timer only displays the remaining time.
Data touched
Sessionread
The remaining time is read from the server, which owns it.
Sessionwrite
The session is extended on real activity, or torn down on idle expiry or when the absolute lifetime is reached.
Audit logappend
A session-timeout event, recorded by a background job when a session expires.
Security decisions
- The server decides expiry; the browser countdown only displays the remaining time, so a client timer cannot extend a session.
- The absolute lifetime caps the session regardless of activity.
- The idle timeout is 30 minutes and the absolute lifetime is 12 hours for staff and 24 hours for customers, enforced by the server.
- An idle expiry ends the session and a background job records it in the audit trail.
Subtasks
- A client-side session-timeout module tracking real activity, and a warning modal.
- A configurable idle timeout and an absolute maximum lifetime.
- Server-owned expiry that re-syncs the client; a background job records the expiry.
How each scenario is verified
- The countdown warns before sign-outA client countdown unit test checks the server-authoritative seconds, the static and live chip, and the warning open and dismiss.
- The server decides expiry, not the clientA server expiry-audit integration test confirms a background job audits each newly expired session.
- Staying active keeps the sessionA warning-modal unit test checks the live countdown, the stay-signed-in action and the in-flight disable.
- The absolute lifetime caps the session regardless of activityVerified by review.
Risk tier
Logic A person approves every merge. This is a Logic-tier change; it carries automated tests for its rules.
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.