What is in here
Everything before a workspace exists. It is a separate
prototype because it is a separate shell — no drawer, no Organisation, nothing to
navigate — and it ends by handing off to the app.
- Signing up — create an account, verify, then create a workspace or
join one. STORY-001, STORY-004.
- Signing in and getting back in — sign in, forgot password, set a new
one, and the three ways a reset link can fail. STORY-002, STORY-003. Added
2026-08-14.
- The waiting room — where a User with no Memberships lands on every
sign-in, and the workspace switcher for one with several. STORY-008, STORY-009.
These notes used to describe the app —
the drawer, event filters, “add sample events” — none of which is in this prototype. Left
behind when the four prototypes were merged into one and nobody re-read the page the
copy no longer matched. Replaced 2026-08-14.
What building sign-in settled
- Two refusals here are deliberately unhelpful, and both look like bugs.
A wrong password and an address with no account produce the same sentence, and
a reset request says the same thing whether or not the account exists. Anything more
useful turns the form into a way of asking us which of our customers' email addresses
are registered. Both screens now say so on the screen itself, because a reviewer who
does not know the rule will read them as sloppy and ask for them to be "fixed".
- The lockout has to offer a way out. "Too many attempts, wait 15
minutes" to somebody who has genuinely forgotten their password is a dead end — they
will keep trying, which is exactly what the limit is there to stop. It points at the
reset, and completing a reset clears the lock.
- A rejected new password does not burn the link. Both refusals say so.
Otherwise a mistyped password looks like it cost you the email, and you go and request
another one.
- "You have been signed out everywhere" is said out loud, not done quietly.
The likeliest reason to reset a password is that somebody else may have had it, and
being told the other sessions are gone is the reassurance that was wanted.
- Length is the only rule stated — no capitals, no symbols. Composition
rules push everyone to
Passw0rd! and nothing else; STORY-001 checks a
breached list instead — or rather, was going to; see below. The requirement is shown before
submission rather than after.
Two things it found
- “Already have an account? Sign in” pointed back at sign-up. It had
nowhere else to go — the screen did not exist — so the flow's one link out of it was a
loop, and the prototype had no door for a returning user at all.
- Focus never moved between screens, though the stylesheet said it did.
A comment at the top of
flow.html has claimed since the first version that
focus moves to the new screen's heading; nothing did it. A keyboard user was left at the
top of a document that had silently changed underneath them. The comment described the
intention and the code never caught up — which is the argument for checking the claim,
not the comment.
Try this
- From sign-up, follow “Already have an account?” Sign in with the
wrong password, then with an address that does not exist. Read both messages — they are
the same sentence, and that is the feature.
- Trip the rate limit in the toolbar, then follow the reset all the way
through. The lock is gone when you come back.
- On the reset screen try a short password and then
password123456. Both are
refused, and both say the link still works.
- Open an expired link from the “check your email” screen. Expired,
already used and never valid all produce one message.
- Sign in correctly and you land on the workspace chooser, not in a
workspace — this account is in two.
Still unanswered
- Settled 2026-08-14: eight characters, and no breached-password check.
The length was never specified anywhere and the prototype had been showing 12 as a
placeholder. The breach check was specified, and has been removed — a
deliberate acceptance of risk rather than an oversight, recorded on STORY-001 with what
it accepts:
password and 12345678 are valid passwords here.
What still stands between an account and an attacker is Argon2id, rate limiting, and
uniform failure responses — none of which helps if the hash itself leaks. Cheap to
revisit: a bundled word list and one function, no migration, and existing passwords
stay valid because the check would only run on the way in.
- Signing out cannot be checked here, and looks as though it can. The
app's drawer now has it — an account block at the foot, added the same day — and it
lands on this prototype's sign-in screen through
?screen=. What neither
prototype can show is the rest of the criterion: the session dying server-side, and the
back button reaching no authenticated page. Static files have no session, and the back
button will happily return you to the app. Do not tick that one off by clicking it.
- Request to join ends in a waiting state that grants nothing. Clear,
or a dead end?