React Forum
Blog & Guide Responses
Feb 12, 2023 · 04:00 PM

[Guide] Build a Password Manager (Route Vault + Scope) - implementation notes

Started by Rowan Pierce
guidepassword managervaultmirrorsscopetoken storederived health scoresecurity postureevidence

The Password Manager guide uses a clear architecture: vault-backed storage plus a mirror surface for UI, scope-based configuration for posture (environment, features, maybe policy), and stored-derived outputs like a "health score" so the UI stays consistent and explainable. I'm curious how people made this feel safe and debuggable without turning everything into security theater.

Read the guide

How did you design the vault + mirror boundary so UI is fast but secrets still feel protected? What did scope control in practice (policy, environment, risk posture), and how did you keep it explicit for users/support? Did you store a derived health score, and what inputs did you consider part of that contract? What evidence/log lines were most helpful when debugging "why is this entry flagged" or "why can't I access this item"?

Comments (22)

Back to latest
Marisol Vega
Feb 15, 2023 · 03:15 PM

Vault + mirror is the only way I’ve seen a secrets UI feel responsive without doing something reckless.

The mirror needs to be a strictly limited projection, otherwise you just copied secrets into another store.

Dmitri Kline
Feb 18, 2023 · 06:06 AM

We treated every vault read/write as an intent with an explicit lane and we log the contract transitions:

txt
[tips] intent=vault:unlock lane=pending reason=user:submit scope=policy:strict
[tips] intent=vault:unlock lane=ok reason=key:verified mirrorRev=12
[tips] derive=healthScore reason=mirror:update mirrorRev=12 score=0.72

Then we render data-vault-lane, data-mirror-rev, and data-scope-policy. Without that, the system feels like magic.

Keira Santos
Mar 01, 2023 · 03:03 AM

Counterpoint: scope config can become a hidden global if you aren’t careful.

We render scope as user-visible copy (not just debug evidence) when it changes behavior. If policy is strict, users should know what strict means.

Rowan Pierce
Mar 05, 2023 · 05:05 AM

Yes. In a password manager, policy isn’t just implementation. It’s part of the product contract.

If policy affects access or warnings, hiding it is a UX bug.

Grace McCoy
Mar 18, 2023 · 06:18 PM

The mirror boundary was easiest when we decided the mirror *never* contains secrets, only derived metadata.

Title, username hash, lastUpdated, risk flags, and a small preview summary that can’t reconstruct the secret.

Jasper Nguyen
Apr 06, 2023 · 06:06 AM

Long-form: security UX is mostly about predictability.

If the app randomly denies access or randomly flags entries, users will either ignore it or fear it. Neither is good.

The guide’s evidence posture—lanes, reasons, and explicit scope—turns security behavior into explainable behavior.

Nina Kapoor
Apr 18, 2023 · 06:18 PM

Derived health score is useful if it has a stable story. We logged the inputs so it wasn’t a mystery:

txt
[tips] healthScore score=0.72 reason=derive inputs="reuse:1 weak:0 old:1"

The string of inputs isn’t perfect, but it makes the score auditable.

Camille Duarte
May 10, 2023 · 10:10 AM

Counterpoint: scoring can turn into security theater if it’s not actionable.

We tied the score to actions (rotate password, enable 2FA) and logged the action reasons so UX was coherent.

Owen Price
Jun 01, 2023 · 06:06 AM

We also made vault unlock idempotent and safe to replay after refresh. The app replays the lane and logs a replay line so it doesn’t feel like it "remembered" secrets magically:

txt
[tips] replay intent=vault:unlock lane=ok reason=refresh mirrorRev=12
Benji Rios
Jul 14, 2023 · 02:14 PM

Long-form counterpoint: a vault UI can accidentally leak secrets through derived outputs (e.g. password length, pattern).

We audited derived fields and made a policy: derived outputs must be non-reconstructive and should be explainable in one sentence.

Lina Ortega
Aug 19, 2023 · 07:19 PM

Docs tie-in: security posture + state/vault concepts are the backbone here.

Related: Security and Safety and State Management (Best Practices).

Amina Farouk
Sep 18, 2023 · 12:12 PM

We used scope to model locale and policy simultaneously (scope as composite).

The key was making precedence explicit and logged, otherwise users couldn’t tell why warnings changed between environments.

Evan Brooks
Oct 15, 2023 · 03:15 PM

Counterpoint: too much evidence can be risky if it ends up in screenshots users share.

We kept evidence behind a debug toggle and made sure the debug view never shows secret-bearing values.

Theo Bennett
Nov 12, 2023 · 04:04 AM

Long-form: vault/mirror is also a performance posture.

If the UI reads encrypted storage directly, you’ll end up doing crypto work in render or effects and the whole app feels sluggish. Mirror avoids that by making a stable render-ready contract.

Tomas Rivera
Dec 02, 2023 · 02:02 AM

We added a "why blocked" evidence string for policy decisions (e.g. export disabled, copy disabled).

If the app blocks an action without a reason, users assume it’s broken.

Salma Qureshi
Dec 20, 2023 · 06:18 PM

Long-form: the guide reads like it’s trying to make security behavior narratable.

That’s the right goal. If behavior can be narrated with one log line and one evidence line, it’s much harder for the system to surprise users.

Harper Iqbal
Dec 23, 2023 · 11:23 PM

We also stored derived "duplicate password" flags as a separate lane, because duplicates can be transient (import flows).

Treating it as a lane prevented the UI from flickering warnings without explanation.

Mina Calder
Dec 26, 2023 · 10:22 PM

Counterpoint: vault unlock flows can be hostile if they’re too strict (timeouts, forced reauth).

We encoded timeouts as posture (strict vs relaxed) and made it visible. That made the tradeoff explicit rather than "the app hates me".

Jules Kwon
Dec 29, 2023 · 09:09 AM

We used the [tips] log format for audits too: last unlock, last export attempt, last policy denial.

It turned security incidents into timelines instead of detective work.

Ari Novak
Dec 30, 2023 · 10:10 AM

Long-form counterpoint: a password manager is a worst-case product for "implicit state" because users are already anxious.

Explicit lanes, explicit scope, and visible reasons are not optional. They are UX fundamentals.

Priya Liao
Dec 31, 2023 · 03:03 AM

If you implement this, start by deciding which derived fields are allowed into the mirror.

That one decision determines whether the system feels safe and whether the rest of the architecture stays disciplined.

Lena Fischer
Dec 12, 2023 · 12:12 PM

We also stored derived "vault health" separate from password health (unlock failures, mirror drift, token store version).

It kept the UI from conflating user behavior with system behavior.

Noah Vance
Dec 18, 2023 · 06:18 PM

Counterpoint: some teams will cargo-cult vault/mirror and then put secrets in the mirror anyway "for convenience".

We enforced it in code review: mirror never contains secrets, and any derived field must be justified as non-sensitive and non-reconstructive.