Commit Graph
5 Commits
Author SHA1 Message Date
Marc-André Bombeck 0da9040f2c test: enforce sharing client step-up
Freezes the authority split the third level ships with. A token exercises a
MANAGE grant, and a Guardian's authority over a managed profile, exactly as a
browser does — proved at the resolver, where neither had a Bearer case before.
A token cannot offer MANAGE and cannot create a managed profile at all, because
both gates resolve through the session cookie; the second had no test until now,
and it runs against a real database with a wildcard token to make the width of
the permission irrelevant.

The claim set is held together by a map naming, per claim, the file and the test
title that proves it, so removing any one of them fails rather than quietly
narrowing what a native client may do.

The fence's client-facing half is frozen beside it: the account payload publishes
the record context on a cookie session and null on a token, and the published
contract says so under the same header names the server matches on.
2026-08-07 05:11:02 +02:00
Marc-André Bombeck 26fceca219 fix: answer the managed-profile Guardian routes in one shape
- publish the roster's entry from the invitation and `{ grantId, revokedAt }`
  from the removal, instead of the account-grant row Prisma returned
- drop the invitation's self refusal: it named a code no request can elicit,
  because a Guardian grant's grantor is the profile and never the caller
- name the duplicate grant error rather than catching every grant refusal into
  a sentence that would be wrong for any other one
- keep the rate limit and the unknown-identifier 404 free of an error code,
  as their siblings elsewhere are, and say why at the call site
2026-08-07 04:39:50 +02:00
Marc-André Bombeck 8793bbf229 fix: close four small gaps around the managed-profile surface
- bound profile creation at ten an hour per account, the ceiling its
  guardian sibling has carried since it shipped
- distinguish a failed roster read from a slow one, with the way back
- cover the three caller states the roster read has to refuse: an
  unaccepted invitation, an expired grant, and MANAGE held elsewhere
- cover what deletion does to a guardian standing inside the record
2026-08-07 03:56:39 +02:00
Marc-André Bombeck 6bfcccd755 feat: manage the guardians of a managed profile
- list who looks after a profile, invite another guardian and end an
  existing access from the profile's own row
- state the last-guardian floor from the real roster before the act, and
  say plainly that an invitation counts only once it is accepted
- give each of the invitation refusals its own sentence, branching on
  status for the two the route sends without an error code
- cover every call the card can make against the real routes
2026-08-07 02:22:30 +02:00
Marc-André Bombeck 365ba8c2eb feat: list the guardians of a managed profile
- add GET /api/managed-profiles/{id}/guardians, cookie-only, refusing
  anybody who is not an active guardian of that profile with the same 404
  an unknown id gets
- disclose the grant id, the party block already shared between grant
  parties, the derived state and the two timestamps, and nothing else
- publish the route in the OpenAPI contract
2026-08-07 02:01:21 +02:00