# Organization invitations and applications

Native Management membership remains the authority for organization access.
Relationship manages invitations, applications, bonds and delivery receipts.
Acceptance grants ordinary `member` access and preserves existing membership,
role and membership data.

On `/members/settings/org`, **Invites & Applications** beside **New
Organization** opens received invitations, request updates, the caller's
applications and an Apply form. Owners send invitations and review
applications under **Access** in an organization. The tabs are **Members |
Invites & Apps | Policy**. A single **Add a principal** form sits beneath the
tabs, outside their panels, and appears on Members and Invites & Apps. Policy
hides it. The form offers **Send invitation** by default or **Direct
add** using the existing native access API. Direct add grants the chosen
access level immediately; invitations grant Member access only after consent.
Members shows current access; Invites & Apps shows pending requests for review.
Switching tabs preserves the shared form's draft and expanded state.
The owner modal uses its top alert for action results and errors, scrolling to
the top when it updates. Member refreshes after a change preserve that result.
Opening an invitation never accepts it.

## Routes

All routes below are authenticated JSON `POST` requests under `/api/v2`.
The normal [authorization](https://m7.org/docs/api/api.user.m7.org/authorization.md) and response envelope apply.
Nonexempt clients need `org.relationships.<action>` or a covering parent scope.
Scopes do not replace native access checks.

| Route suffix after `/org/relationships/` | Input | Authority / effect |
| --- | --- | --- |
| `invite` | `org`, `recipient`, `idempotency_key`; optional `type` (default `user`) and `message` | Current owner creates an invitation. Type `user` uses a native User UUID; type `app` uses a machine application's public Client ID. |
| `apply` | `org`, `idempotency_key`, optional `message` | Authenticated consumer user or machine application requests Member access for itself. |
| `requests` | `org`, optional `count`, `offset` | Current owner lists pending requests and incomplete accepted grants for this organization. |
| `status` | `command_id` | Recipient or current owner reads request status. |
| `accept` | `command_id`, integer `version` | Invitation recipient accepts; current owner approves an application. Applies a verified native grant. |
| `decline` | `command_id`, integer `version` | Invitation recipient declines; current owner declines an application. |
| `cancel` | `command_id`, integer `version` | Owner cancels an invitation; applicant withdraws its own application. |
| `notifications` | optional `count`, `offset` | Reads the authenticated caller's mailbox for this integration. |
| `applications` | optional `count`, `offset` | Reads only the authenticated caller's applications and current statuses. |
| `delivered` | `notification_id` | Acknowledges delivery for the authenticated caller; never grants consent. |

Every route accepts an optional `workspace_principal_id` sentinel. Use the
central principal UUID returned by an earlier response to reject actions after
the authenticated actor changes. It cannot select another actor. Pagination
uses integer `count` (1–50, default 25), nonnegative integer `offset` and
`next_offset` (`null` at the end).

Creation requires a nonnil UUID `idempotency_key`. Retry identical input with
the same key to recover the original command. Changing input needs a new key.
Messages are UTF-8 text, limited to 2,000 bytes. Requests expire after seven days.

For example, a current owner can invite a consumer user:

```bash
curl --fail-with-body --silent --show-error \
  --request POST 'https://api.user.m7.org/api/v2/org/relationships/invite' \
  --header 'Authorization: Bearer ACCESS_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{"org":"ORGANIZATION_UUID","recipient":"USER_UUID","type":"user","idempotency_key":"FRESH_REQUEST_UUID"}'
```

Bound tokens require the [matching sender proof](https://m7.org/docs/api/api.user.m7.org/authorization.md). Successful
operations use `status: 1`, `comment: "OK"`, and `data` containing the result.
Check the ordinary failure envelope for invalid fields, unavailable identities,
missing current owner/recipient authority, actor-sentinel mismatch, expired
requests, and stale decision versions. Read `status` again before retrying a
decision with its current `version`; do not automatically accept a different
request or widen the original consent.

## Identities and authority

Native account/client IDs, central principal UUIDs and Management principal
UUIDs are separate identifiers. The server resolves verified consumer users
and machine applications by source kind and tenant, then maps accepted grants
to native Management records. Invitation entry follows the native source
conventions above; response `principal_id` uses the central registry. Tenant
accounts and organization ownership references are not actors in this
workflow. Machine owner proxies cannot inherit the owner's requests or consent.

Only current owners create invitations or review applications. An invitation's
issuer must still be an eligible owner when it is accepted. Caller-supplied
actors, remote project/space/subspace IDs, role overrides and arbitrary metadata
are rejected.

Responses expose a `request` or an `items` list. Request fields include
`command_id`, `request_id`, `resource_id` (native organization UUID),
`organization_name`, `principal_id`, `principal_name`, `issuer_name`, `kind`,
`message`, `state`, `version`, `expires_at`, `grant_applied` and `access_active`.
Status responses also include `can_respond`. Remote protocol payloads and
credentials remain server-side.

Incomplete accepted applications appear in the owner's queue for retry;
recipients can retry incomplete invitation acceptance. A completed receipt
records the exact native membership UUID. Replaying it cannot recreate removed
access. Existing removal and leave operations synchronize remote bonds while
preserving native last-owner, metadata and tag cleanup checks.
