Project members and invitations
The default Go API serves these reads through the Project owner. The development fixture mode remains available through explicit configuration. Generated clients and disposable fixture checks do not establish support in a deployed backend.
Both reads require a current Party identity and a canonical Project UUID.
Browsers use the Party session; the enrolled MCP gateway can use its
operation-bound assertion under the same current
owner permission checks.
Responses use Cache-Control: private, no-store. Neither operation accepts query
parameters. These reads add no mutation, realtime subscription or automatic polling.
Members
GET /api/v1/projects/{projectId}/members, operation getProjectMembers, requires
current project.view authority. The backend checks Project/source authority
before and after the read.
All properties are required. asserted_name and asserted_name_revision are
nullable. The name is the existing trusted AAI identity projection's name;
editable profile names and email addresses are never used as fallbacks.
A current projection with no name has a null name and its non-null revision.
A pending, superseded or currently ineligible identity projection has both fields
null. A missing name preserves the membership row and roles. Infrastructure or
corrupt-authority failures fail the whole query.
revision versions Project membership. asserted_name_revision independently
versions the Party identity projection and must not be compared between Parties.
An unchanged Project revision does not imply unchanged names.
items is ordered by party_id. The complete source observation contains at
most 256 member bindings; several qualified bindings can contribute to one Party
row. Every observed binding is resolved into a row or counted in
pending_member_count. membership_complete equals pending_member_count === 0.
This flag concerns membership resolution; it says nothing about missing names.
The count is diagnostic information and must never be labelled as invitations.
Show available rows and a simple incomplete-membership state when the flag is
false. Use a neutral missing-name label or shortened canonical Party ID.
The retained Project page uses asserted_name for every member, including the
viewer. Public profile visibility does not affect this authorised list. Its
own-profile read identifies the You marker only. The browser regression runs
with private/absent public profiles, independent name revisions, unavailable
reads and a delayed response from a previously selected Project:
Invitations
GET /api/v1/projects/{projectId}/invitations, operation listProjectInvitations,
requires current project.access.manage authority, currently granted to Project
administrators. Show this separate section only to those administrators.
All properties are required and non-null. invitation_id is an opaque reference,
not a canonical Party ID or acceptance credential. The backend derives this scoped reference without exposing the provider invitation locator. recipient_email is available
only through this administrator-authorised read and is not an asserted name.
Roles use the same canonical values as members.
This slice returns only provider-pending invitations whose expiry is after
read_at. It excludes accepted, cancelled, rejected and expired invitations.
There is no historical invitation list or acceptance/revocation operation.
expires_at is the provider's actual expiry, not a locally invented lifetime.
The backend resolves the exact canonical Project/provider binding, traverses all
provider pages and checks Project scope and customer itself. It rechecks current
administrator authority after acquisition. items contains the complete result,
bounded to 256 invitations and sorted by expires_at, then invitation_id.
There is no cursor. Overflow, missing pages, unsupported roles and malformed
provider data fail the whole request; partial results are never returned.
project_revision versions the Project authority used for this read, not the
invitation collection. read_at is successful acquisition completion time.
The provider supplies no atomic collection revision; this timestamp does not
establish a transactional snapshot across provider pages.
Clients, errors and rollout
The source schemas are members.paths.json,
invitations.paths.json and schemas.json.
Regenerate with pnpm generate:contracts. Both generated clients export:
The import is relative to the active frontend's src alias. Sources are
services/web/src/adaptors/generated/http/project/project.ts and
compat/themelio/services/web/src/adaptors/generated/http/project/project.ts.
The canonical web client also exports useGetProjectMembers and
useListProjectInvitations. Query-cache values must be cleared when the Party
session or Project access changes; HTTP no-store is not a React Query cache policy.
The generated fetch adaptor rejects non-success responses with the existing
HTTPError; inspect its status. Error bodies contain code: invalid_input
for 400, unauthorised for 401, not_found for 404 and
temporarily_unavailable for 503. Keep the two sections' loading/error states
independent. An invitation read failure does not invalidate a successful member
read.
Reconcile the API-auth credentials and deploy the Waldur actor capability before
the new Project owner, then deploy the new API and enable frontend use of the
new fields. The invitation adaptor guide
describes the scoped credential, URL and trust requirements. The established owner member query retains its original wire shape
for existing API instances. The new API calls GetProjectMemberDetails; an
older owner cannot satisfy that query and the read fails unavailable. Its reply
preserves presence of membership_complete, and the API rejects absent presence.
For real data, leave API_PROJECT_READ_FIXTURES unset or false and remove both
fixture scenario settings. An unavailable owner or provider produces an error;
the API never substitutes fixture data. Clear any cached fixture responses when
switching the development frontend to real reads.
Deploy backend support before relying on the new required fields. During a
mixed-version rollout, absent fields are unsupported-contract evidence, not
equivalent to null, false or zero. An old backend's invitation-route 404 must
not be converted into an empty invitation list. Frontend fixture work can proceed
against fixtures/members.json,
fixtures/invitations.json and
fixtures/invitations-empty.json; these are
contract examples, not live deployment evidence.
Page source
Source snapshot ยท Revision f928834c8.