Skip to content

fix(persona): a decision does not wait for the claim-type table - #200

Merged
stormer78 merged 1 commit into
mainfrom
fix/holder-decision-outranks-missing-table
Sep 8, 2026
Merged

fix(persona): a decision does not wait for the claim-type table#200
stormer78 merged 1 commit into
mainfrom
fix/holder-decision-outranks-missing-table

Conversation

@stormer78

Copy link
Copy Markdown
Contributor

From a live wallet: every value masked — including name.legal, and including one explicitly marked show it — under a heading saying the agent's claim-type table "does not declare these", about an agent that had not answered at all.

The agent serves no persona/claim-types/list. That is a legitimate state (the task is new), and the console holds no table because of it. What was wrong is that the state was handled three different ways, each of them wrong in a different direction.

1. The holder's decision was discarded along with the table

treatmentFor returned the fail-closed floor for a missing registry before it looked at the override, on the reasoning that a decision "cannot be applied over an answer that has not arrived."

That reads well and is backwards. §4 rule 1 makes the holder's answer win over the registry's — so where they gave one there is nothing to combine and nothing to wait for. An agent that serves no table, or failed to answer once, was silently overruling every choice its owner had made about their own values, and the screen attributed that to the registry.

The override is now applied first. The mask axis still keeps a declared token's registry mask — the narrowness #195 argued for — and that is exactly what a missing table cannot know, so there the holder is the only evidence there is.

2. The screen said the table had declined the tokens

With no table, every attribute grouped as unregistered, whose words are "your agent's claim-type table does not declare these". That is a claim about the tokens that nobody had checked — the same error as reporting a context the agent would not answer for as a context that holds nothing.

unknown is now its own family and its own source, and says your agent has not said — it did not answer with a claim-type table, so everything here is treated as the most private kind until it does.

3. The failure was swallowed

persona.tsx loaded the table under a comment saying it "needs no failure branch of its own, because the same agent answers both: if this refuses there are no attributes to mask either."

They are different tasks, and the live wallet is the counter-example: it listed its pool perfectly and served no table. registry.error is now shown with what it means for the screen, and reloadAll reloads it — left out, one failure kept every value masked for the life of the tab.

Also: the wording asked about twice

A withheld value read "not on this page", and pressing Show then fetched and displayed it — so the card said the value was not here and then produced it. It now says with your agent, which the next press does not contradict. ("not requested" → "not on this page" → "with your agent" is three attempts at one sentence; the first described the request, the second described the page, and only the third describes where the value is.)

Checks

  • 7 new tests. Extension 366 pass, core 576 pass.
  • tsc -b clean; npm run build clean, manager.js a single chunk.
  • Pinned: a decision holds with registry: null, in both directions (show it and keep it back), and reports source: "holder" rather than a default wearing the holder's name; no table plus no decision still fails closed but reports unknown; a declared token keeps the registry's mask when there is a table; and the pane renders the "would not give its claim-type table" note when only that task fails — mounted against a fake agent that answers everything else, which is the shape the live wallet was in.

What this does not fix

If a value stays masked after this, the override is not stored on the attribute — select it and the strip will say "You decided: shown" when it is. That would be a different bug, in the write path rather than the read one.

Reported from a live wallet, and three defects behind one screen. The agent
does not answer `persona/claim-types/list`, so the console holds no table — and
that state was handled three different ways, each of them wrong.

**The holder's decision was discarded with it.** `treatmentFor` returned the
fail-closed floor for a missing registry *before* reading the override, on the
reasoning that a decision "cannot be applied over an answer that has not
arrived". That reads well and is backwards: §4 rule 1 makes the holder's answer
win over the registry's, so where they gave one there is nothing to combine and
nothing to wait for. An agent that serves no table — or failed to answer once —
was silently overruling every choice its owner had made about their own values,
and the screen attributed that to the registry. The override is now applied
first. The mask axis still keeps a *declared* token's registry mask, which is
exactly what a missing table cannot know, so there the holder is the only
evidence there is.

**The screen said the table had declined the tokens.** With no table every
attribute grouped as `unregistered`, whose words are "your agent's claim-type
table does not declare these" — a claim about the tokens that nobody had
checked, and the same error as reporting a context the agent would not answer
for as a context that holds nothing. `unknown` is now its own family and its own
`source`, and says *your agent has not said*.

**The failure was swallowed.** `persona.tsx` loaded the table with a note saying
it "needs no failure branch of its own, because the same agent answers both".
They are different tasks: the live wallet listed its pool perfectly and served
no table. `registry.error` is now shown, with what it means for the screen, and
`reloadAll` reloads it — left out, one failure kept every value masked for the
life of the tab.

Also the wording a person asked about twice: a withheld value read "not on this
page", and pressing *Show* then fetched and displayed it, so the card said the
value was not here and then produced it. It now says **with your agent**, which
the next press does not contradict.

7 new tests (366 extension, 576 core), `tsc -b` clean, `npm run build` clean.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
@stormer78
stormer78 merged commit 8625c82 into main Sep 8, 2026
3 checks passed
@stormer78
stormer78 deleted the fix/holder-decision-outranks-missing-table branch September 8, 2026 12:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant