fix(persona): never write a value the editor never held, and let a decision reach the copy - #197
Merged
Merged
Conversation
…cision reach the copy Two bugs a holder hit within minutes of #195, both from the same gap: the pool's value and the pool's decisions do not travel with the copy. **The editor was blanking values.** Since #194 the pane lists without `includeSensitive` — the plaintext of a sensitive attribute is deliberately not in the page — so an existing one reaches the editor with `value: undefined`. `rawValue(undefined)` is `""`, the field opens blank, and `attribute/put` REPLACES the record. Opening a withheld attribute to change its label, or the visibility controls #195 had just put in that same form, wrote an empty string over a value the console had never seen. There is no `attribute/get`, no version history and nothing to restore from, so it was silent and final. The editor now asks for the value on open — the same one-attribute request *Show* makes — and, separately, refuses to save while the value is neither loaded nor typed. Two mechanisms deliberately: the fetch is the convenience, the refusal is the property, and the refusal sends no put at all rather than writing something wrong. Typing a value yourself is the deliberate overwrite it allows, which is also why every control that edits the field goes through one writer: one that set `raw` directly would leave the guard reading a typed value as one nobody typed. **A decision did not reach the copy.** "What someone would receive" renders claims read from a face or a binding, and a claim is a copy that carries no `sensitivity` — the decision lives on the pool attribute it was materialised from. So a value the holder had just marked *show it* was masked one panel away from the card showing it in the clear: same person, same value, two answers. `decidedSensitivity` matches a resolved claim's `attributeId` back to the pool. An inline claim has no `attributeId` and no pool ancestor, so the registry answers for it — the right answer for that case rather than a gap in this one. Rebased onto #196 rather than merged with it: that PR moved the claim-type table to the agent's served one and threads a `registry` through these same components. Both props are additive and both are now passed at every call site. 7 new tests (359 extension, 562 core), `tsc -b` clean, `npm run build` clean. Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
🛡️ AI Agentic Security Code Review🔎 A manual security review is recommended before merging. Please contact the Security team for specifics and remediation guidance.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two bugs reported minutes after #195, both from one gap: neither the pool's value nor the pool's decisions travel with the copy.
1. The editor was blanking values — data loss
Since #194 the pane lists without
includeSensitive, so the plaintext of a sensitive attribute is deliberately not in the page. That means an existing one reaches the editor asvalue: undefined→rawValuereturns""→ the field opens blank → andpersona/attribute/putis a replace.So opening a withheld attribute to change its label — or the visibility controls #195 had just put in that same form — wrote an empty string over a value the console had never seen. Silently, and with no way back: there is no
attribute/get, no version history, nothing to restore from.Two mechanisms now, deliberately separate:
Every control that edits the field now goes through one writer. One that set
rawdirectly would leave the guard reading a typed value as one nobody typed — which the test caught while this was being written.2. A decision did not reach the copy
What someone would receive renders claims read from a face or a binding. A claim is a copy and carries no
sensitivity: the decision lives on the pool attribute it was materialised from, above the boundary those panels sit below. So a value the holder had just marked show it was masked in one panel and shown in the clear on the card one scroll away — same person, same value, two answers.decidedSensitivitymatches a resolved claim'sattributeIdback to the pool. An inline claim has noattributeIdand no pool ancestor to have decided anything, so the registry answers for it — the right answer for that case rather than a gap in this one.Rebased onto #196, not merged with it
#196 moved the claim-type table to the agent's served one and threads a
registrythrough these same components. It fixes neither of these — nothing in it touches the put path, and the claims panel still passed nosensitivity— but it rewrote the files. This branch was rebased onto it and the conflicts resolved by keeping both props at every call site, rather than letting a textual merge pick one.Checks
tsc -bclean;npm run buildclean,manager.jsa single chunk.Note for whoever hit this
Values already blanked this way are gone — they have to be re-entered. Worth knowing while reviewing: the window was #194 → this, and it applied to any attribute the registry resolves as
sensitivity: high, which includes every unregistered type.