# Project scopes and principal references

Configure a project and its spaces in the
[Relationship application](https://relationship.service.m7.org/), then retain
the resulting project, space and optional subspace IDs in your integration.
Use these reads to verify that mapping before graph or enrollment commands.

## Routes

All routes use POST under `https://api.relationship.service.m7.org/v1/`, with
the [Bearer and workspace contract](https://m7.org/docs/api/api.relationship.service.m7.org/authorization.md).

| Route | Required fields | Optional fields | Capability and result inside `data` |
| --- | --- | --- | --- |
| `/projects/context` | `project_id` | — | `project.view`; `project`, `membership`, `management_group_id`, `capabilities`. |
| `/projects/spaces/list` | `project_id` | `method`, `count`, `offset` | `space.list`; `project_id`, `items`, `next_offset`, `can_manage`, `capabilities`. |
| `/projects/subspaces/list` | `project_id`, `space_id` | `count`, `offset` | `space.list`; `project_id`, `items`, `next_offset`, `space`. |

IDs are non-nil dashed UUID strings. `method` is exactly `pairwise` or
`resource_membership`; omitting it lists both. Paging follows the
[common count/offset rules](https://m7.org/docs/api/api.relationship.service.m7.org/README.md#pagination-and-versions).

```bash
curl --fail-with-body --silent --show-error \
  --request POST 'https://api.relationship.service.m7.org/v1/projects/spaces/list' \
  --header 'Authorization: Bearer ACCESS_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{"project_id":"PROJECT_UUID","method":"resource_membership","count":100,"offset":0}'
```

Space records include `id`, `project_id`, `code`, `name`, `method`, `direction`,
`metadata` and integer `version`. Subspaces include `id`, `project_id`,
`space_id`, `code`, `name`, `metadata` and integer `version`; they inherit their
space's method and direction. Use IDs for commands; names and metadata are
display or application data.

## Scope semantics

Graph and enrollment commands require `project_id` and `space_id`.
`subspace_id` is an optional UUID string; omission or null selects the space
root. It does not include all subspaces. Root and subspace records are
independent, with one level of subspaces and no membership inheritance.

| Space method | Relationship meaning |
| --- | --- |
| `pairwise`, `mutual` | Two distinct principals; A↔B and B↔A identify the same bond. |
| `pairwise`, `directed` | A→B and B→A identify separate bonds. |
| `resource_membership`, `directed` | One principal belongs to the exact selected space root or subspace. |

Keep each consumer resource's mapping explicit. Metadata does not prove
ownership, authenticate an external resource or assign access in your service.
The same principals can have independent bonds in different scopes.

## Principal reference

```json
{
  "namespace": "example.app",
  "principal_id": "PERSON_UUID"
}
```

| Field | Required | Type and limit |
| --- | --- | --- |
| `namespace` | Yes | Nonempty UTF-8 string, at most 128 bytes; comparison is case-sensitive. |
| `principal_id` | Yes | Non-nil dashed UUID string, normalized to uppercase. |

The object accepts only those two fields. Choose a stable namespace and UUID
mapping for your own principals and derive them from authenticated application
context. Relationship does not resolve usernames, verify the principal exists
in your application or infer consent from its UUID.

Pairwise commands require both `source` and `target` references and reject
self-connections. Membership commands require `source`; omit `target` because
the selected scope is the resource. Stored records return `source_ref` and
`target_ref` (null for resource membership). Mutual pairwise records may return
their endpoints in canonical order, independent of the submitted order.

## Metadata and missing scopes

Metadata is a JSON object, up to 65,536 encoded bytes and 64 JSON levels. Keys
have application-defined meaning; metadata does not grant permissions. An
omitted metadata field on save preserves the existing object; `{}` clears it.
Invalid methods or references return body code 400. A missing space or a
subspace belonging to another space returns body code 404. A project may deny
access with body code 403 before revealing its records.

Deleting a scope in the management application removes its current
relationships and finalizes pending requests. Retain history as events, and
do not reuse an old mapping as though the deleted scope still exists.
