Skip to content

Release: develop -> main - #1205

Merged
TaprootFreak merged 3 commits into
mainfrom
develop
Jul 29, 2026
Merged

Release: develop -> main#1205
TaprootFreak merged 3 commits into
mainfrom
develop

Conversation

@github-actions

Copy link
Copy Markdown

Automatic Release PR

This PR was automatically created after changes were pushed to develop.

Commits: 1 new commit(s)

Checklist

  • Review all changes
  • Verify CI passes
  • Approve and merge when ready for production

* docs(pages): record which cache rules the edge overrides

Two rules in this file do not reach the client as written. For responses the
edge caches, any max-age below four hours is raised to four hours: /widget/*
asks for one hour and /robots.txt for revalidation, and both arrive as
max-age=14400. Values above four hours are untouched, which is why the day
of cache on favicon.ico and logo.png does apply, and uncached responses pass
through, which is why no-cache works for index.html and manifest.json.

The value comes from CDN configuration and cannot be changed here. Writing
max-age=0 instead of no-cache would not help either -- it is below four hours
and would be raised the same way.

So the note records the limit rather than pretending the rules hold. A rule
that reads as applied and is not is worse than one that says where it stops.

* docs(pages): show the widget pair that makes the override visible

The note explained the override and proved it on robots.txt, but the clearest
evidence sits under the widget rule: /widget/v1.0.css is cached and reaches
the client as max-age=14400, while /widget/v1.0 is not cached and keeps the
max-age=3600 the rule asks for.

Same rule, two outcomes, decided only by whether that particular response is
cached -- which is the point the note is making.
* feat(buy): issue the personal IBAN directly from the selector

The pre-confirmation prompt is removed. A customer who sets
`personal-iban=frick` has already expressed that intent; asking again
interrupted the purchase without adding a decision.

This removes the prompt component, the per-customer confirmed/declined
state and the widget occurrence mechanism that forced a fresh
confirmation. The selector now takes effect directly.

Kept deliberately: the acknowledgement shown when the selector cannot be
honoured (ineligible currency or payment method, or a response that
failed verification), the response verification itself, and the handling
of an unrecognized selector. Without them a customer who asked for a
personal IBAN could silently receive shared-account details instead.

The hook no longer confirms anything, so usePersonalIbanConfirmation
becomes usePersonalIbanSelection.

Issuance is now gated solely by an initialised wallet and an
authenticated customer. Both halves of that gate are pinned
independently by new tests, so neither check can be dropped unnoticed.

* test(buy): cover the selector path without the removed prompt

The end-to-end spec still drove the confirmation dialog: it located the
prompt by its copy and clicked a button that no longer exists, so it
could not pass. It now covers the flow as it is — the selector applies
directly and the Bank Frick details render once the quote resolves.
Every other assertion it made is kept. No baseline for the prompt was
ever committed, so none had to be removed.

Removing the prompt also removed the only tests that exercised the real
selector hook; everything left replaces it with a mock. Since that
derivation feeds the sole gate before an irreversible account, it now
has its own test against the real hook: the selector from the URL, the
widget property taking precedence over a conflicting URL value, an
unrecognized value never becoming a request, and the authenticated
customer derived from a genuine session.

Also corrects three comments that still described a confirmation and a
decline that no longer exist.

* test(buy): pin the authenticated-customer check against a real break

The previous fixtures — a valid session against no session at all —
could not tell the two apart: replacing the account-field check with a
bare "is there a session" check left all of them green. That check is
one of only two conditions standing between the selector and an
irreversible account, so a test that cannot see it fail is not worth
having.

Two cases close it: a session without an account field, and one whose
account is a string rather than a number. Both must report no
authenticated customer. Verified by applying that exact break and
confirming these two, and only these two, turn red.

The file also moves to the naming this repo uses for hook tests, after
the hook file rather than the exported function.

Corrects one more comment from the previous round that was itself
wrong: the effective selector is filtered by recognition and
suppression only, never by eligibility, which is computed separately
and re-applied at each call site.

* fix(buy): treat an expired session as not authenticated

The authenticated-customer check read the account field out of the
decoded session. That field survives token expiry — the SDK keeps the
decoded payload and tracks freshness in a separate flag — so an expired
session still reported an authenticated customer. Since the
confirmation step was removed, this check is one of only two conditions
before an irreversible account is created, and it claimed more than it
established.

It now consults the freshness flag as well. Both values are written
together in the SDK and can only diverge at actual expiry, so a
legitimate session cannot be blocked by this. A test pins the expired
case.

Not exploitable today: the endpoint that issues the IBAN rejects an
expired token before anything is created. This closes the gap between
what the client claims locally and what it can actually establish.

Also updates the README section that still described the removed
confirmation step, including the note about the authentication
boundary, which now explains what really prevents a selector from
carrying across a logout.

* docs(buy): describe the test boundary as it actually is

Three statements claimed more than they deliver. The hook tests were
described as exercising authentication and router transitions; they are
static renders under different fixed initial conditions, with no state
change observed. The Jest setup was described as mocking the SDK
globally; each test file mocks it locally, and the paragraph's actual
point — that a fake SDK cannot exercise the production token parser,
guards or redirects — holds either way.

A test named after an expired token also did not exercise expiry: it
passes the flag directly. Renamed to say that, rather than made to
drive real expiry, since the hook consumes the flag as an opaque value
and driving it would test the SDK rather than this repository.

The comment beside the check also described the mechanism wrongly: the
flag is not set alongside the session, it is recomputed on every render
from the live token reference.
…abels (#1207)

* feat(safe): date the activity rows, and drop the bracketed order labels

Three things the Safe screen got wrong for a reader of the activity list:

- No entry carried a timestamp, so nothing could be placed in time. The
  rows now show the valuta timestamp, falling back to the creation date
  for orders that never completed, and no date at all when the API
  predates the fields.
- sZCHF fell through to the grey placeholder because AssetIconVariant has
  no such member. Saving positions mirror an underlying asset, so they now
  borrow its icon - both in the asset list and in the activity rows.
- The order labels named the form of the deposit (Fiat, Crypto, Saving).
  That distinction means nothing to the reader and is now gone from the
  labels and from the translations.

* fix(safe): type the activity timestamps as optional

The rendering path already handles their absence - an API predating the
fields serves neither, and the row then shows no date. Typing created as
required contradicted the code that guards against it.

* test(safe): regenerate the Safe baselines for the dated activity rows

The committed baselines still showed the bracketed labels and no dates,
i.e. exactly the state this branch changes. Regenerated on macOS against
a local API, both specs verified to reproduce without --update-snapshots.

The local data set had to be rebuilt: the original one was never recorded
anywhere, so the figures differ slightly. It carries an sZCHF position on
purpose - without a saving position the icon alias has nothing to show.

* fix(safe): tie the valuta timestamp to the completed state

completedAt is written once and never cleared, so reading it regardless of
status would keep showing a valuta for an order that has since moved back
out of Completed. Read it only while the order says it is completed.
@TaprootFreak
TaprootFreak merged commit 78dfdb9 into main Jul 29, 2026
7 checks passed
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