# Resource Registry — API Operational Cookbook & Advanced Use Cases

Because the Resource Registry employs a strictly typed graph database under the hood, standard REST operations (`PUT`, `PATCH`, `DELETE`) have specific graph-level side effects. This section details common operational patterns and corner cases.

## The Shared Instance Mutation (Global Effect for Facets and Relations)

**Scenario:** An instance (e.g., a **Facet** instance or an **IsRelatedTo** instance) is shared across multiple Contexts (e.g., Context `C1` and Context `C2`). You want to update a field (e.g., a specific property of the **Facet** instance, or the `propagationConstraint` of the **Relation** instance), and you *want* that update to be reflected for everyone.
**Action:** Send a `PUT` or `PATCH` containing the modified payload, **explicitly including its existing `id`**.
**Graph Mechanism:** The backend resolves the existing instance using the provided ID and updates its property fields. Because fields are intrinsically bound to the single underlying instance, the change is immediately visible globally across all Contexts where that instance is shared. (This applies equally to `Encrypted` fields and structural system fields like `propagationConstraint`).

## Context-Local Instance Forking (Copy-on-Write)

**Scenario:** A **Resource** instance is shared across Contexts `C1` and `C2`. You want to update a **Facet** instance *only for your Context* (`C1`), branching off from the shared configuration without affecting Context `C2`.
**Action:** Send a `PUT` payload where the modified **ConsistsOf** instance **and** its nested **Facet** instance each carry a **freshly client-generated `id`** (a UUID that does not yet exist in the system), instead of the `id` of the shared instances.
**Graph Mechanism:** The backend interprets each not-yet-existing `id` as a request to create a new instance. Specifically, within the operational Context `C1`, it explicitly drops the existing **ConsistsOf** instance (and consequently its target **Facet** instance) from the Context. It then creates a brand new **Facet** instance and attaches it to the **Resource** instance via a newly created **ConsistsOf** instance, using the client-supplied `id` values. Because Contexts are strictly isolated, the original **ConsistsOf** and **Facet** instances remain completely untouched and safely attached to the shared **Resource** instance in Context `C2`.
*(Both ids must be fresh — reusing the existing **ConsistsOf** instance's `id` while only generating a new one for the **Facet** instance would retarget a shared **ConsistsOf** instance to a different **Facet** across Contexts, which is topologically invalid; see [`09-api-instances-and-admin.md`, "Single Context Update (Local Copy-on-Write)"](../09-api-instances-and-admin.html#single-context-update-local-copy-on-write) for the full explanation).*

## The Cardinality Chicken-and-Egg (`min: 1, max: 1`)

**Scenario:** A **Resource** instance has a mandatory **Facet** instance (e.g., `StateFacet` with `min:1, max:1`). You need to completely replace this **Facet** instance with a new one for your Context. You cannot `POST` the new one first (violates `max: 1`) and you cannot `DELETE` the old one first (violates `min: 1`).
**Action:** Send a `PUT` request for the entire **Resource** instance, removing the old **Facet** instance from the payload array and including the new one with a freshly client-generated `id` (a UUID that does not yet exist in the system).
**Graph Mechanism:** The `PUT` operation acts as a "Full Replace" for the Context. The backend calculates the delta: it removes the omitted old **Facet** instance and attaches the new one. Validation constraints (like `min/max`) are strictly evaluated **at the end of the transaction**. Since the final state contains exactly 1 `StateFacet`, validation passes seamlessly.

## Hierarchical Downstream Mutations (`hierarchical` vs `syncExistingHierarchy`)

When executing a `PUT` operation on a **Resource** instance as an administrative role (`IS-Editor` or higher), you have two powerful mechanisms to push topological changes (e.g., changes to its attached **Facet** instances) down a Context tree. It is crucial to understand the difference to avoid unintended data proliferation.

*(Note on Parameter Conflict: The flags `hierarchical=true` and `syncExistingHierarchy=true` describe two mutually exclusive propagation strategies. If a client mistakenly passes BOTH flags on the same `PUT` request, the API strictly rejects the request with a `400 Bad Request` to prevent ambiguity).*

### The Surgical Sync (`?syncExistingHierarchy=true`)

**Scenario:** You want to push a configuration change down to all child VREs (Contexts `C_Child_1`, `C_Child_2`) *only* if they have already explicitly "opted-in" by having the **Resource** instance shared with them.
**Action:** Issue a `PUT /instances/{resource-type}/{instance-uuid}?syncExistingHierarchy=true` targeting the parent Context.
**Graph Mechanism:** This acts as a safe, cascading sync. The backend applies the `PUT` state replacement to the **Resource** instance in the parent Context AND in all descendant Contexts **where the **Resource** instance already exists**. It does *not* implicitly share the **Resource** instance to child Contexts that did not already have it.

### The Blanket Replication (`?hierarchical=true`)

**Scenario:** You want to enforce a global baseline, ensuring a specific **Resource** instance is present and updated across *all* descendant Contexts, overriding any local absences.
**Action:** Issue a `PUT /instances/{resource-type}/{instance-uuid}?hierarchical=true` targeting the parent Context.
**Graph Mechanism:** The backend applies the `PUT` state replacement to the parent Context AND forcefully propagates the **Resource** instance into **every single descendant Context** within the authorization scope. If a child Context did not previously possess the **Resource** instance, it is implicitly added to it (acting as a combined Create/Update + `Add to Context` avalanche).

## Surgical **Relation** instance / **Entity** instance Deletion (`?propagationMode=surgical`)

**Scenario:** You accidentally created an **IsRelatedTo** instance with `remove: cascade` to an important target **Resource** instance, and you need to delete the **Relation** instance without triggering the avalanche that would destroy the target **Resource** instance.
**Action:** Issue a `DELETE /instances/{type}/{instance-uuid}?propagationMode=surgical` (where `{instance-uuid}` is the UUID of the **Relation** instance or the source **Entity** instance).
**Graph Mechanism:** This triggers a surgical non-cascading delete. The backend physically destroys the targeted **Relation** instance (or the targeted **Entity** instance and its strictly required **Facet** instances), but explicitly **ignores** any `remove` propagation constraints towards external instances. This acts as a safe "undo" facility, but must be used carefully to avoid leaving detached or unlinked instances floating in the Context unintentionally.

## Descriptive-Topology Closure on Direct Relation Add

When managing graph topologies, a strict theoretical model would dictate that an edge cannot be added to a Context unless both its source and target nodes are already present. However, the IS-Model API implements a deliberate "Developer Experience (DX) bypass" to simplify interactions.

If a client attempts to execute an `Add to Context` directly on a **Relation** instance, and the target **Entity** instance is missing from the destination Context, the system does not fail with a dependency error. Instead, it **implicitly pulls** the target **Entity** into the Context, actively bypassing the `unpropagate` constraint if present on the **Relation**.

**Design Rationale:**
This behavior is an intentional system compromise. It allows clients to share a specific connection (and its necessary downstream requirement) in a single API call, rather than forcing them to first discover the target ID, make a separate `PUT` call to add the target, and finally make a `PUT` call for the relation. While it creates a minor asymmetry with the theoretical propagation model (where `unpropagate` means "stop"), the necessity of preserving structural integrity (no dangling edges) combined with developer ergonomics justifies this implicit closure.

*(Note: The implicit pull strictly applies to the target. If the **source Resource** is missing, the operation strictly fails with a `409 Conflict`. This enforces the model's unbreakable rule: **the avalanche is strictly downstream**. We only force the downstream pull to preserve topological closure when bypassing `unpropagate`. If a client wants to add the source, they must explicitly invoke `Add to Context` on the source instance itself. We never implicitly pull upstream. Furthermore, this implicit downstream pull triggers standard propagation rules for the target itself. If the pulled target **Resource** instance has mandatory **Facet** instances governed by `add: unpropagate` constraints, those **Facet** instances will correctly NOT be pulled. Consequently, the target **Resource** instance will fail its final schema validation, and the entire transaction will be predictably rejected with a `409 Conflict`. The system behaves as a strict deterministic engine: it does not magically override downstream constraints to rescue a poorly modeled resource instance).*

## Canonical Mutation Semantics: `PUT` (Replace Intent) vs `PATCH` (Merge Intent)

To reduce ambiguity for client implementers, this section uses the **same initial state** and shows the resulting state after each method. *(Note: This is a simplified structural example to demonstrate the delta mechanics; a real `EService` instance would require additional mandatory facets to pass strict schema validation).*

- **`PUT`** = replace intent on the addressed instance representation.
- **`PATCH`** = merge intent (partial modification).

**Shared initial state (conceptual):**

```json
{
  "type": "EService",
  "id": "1a50a46d-2210-4a17-bd2f-22450b109264",
  "consistsOf": [
    {
      "type": "ConsistsOf",
      "id": "8bb0a45e-1110-4b17-ad3f-11450b109277",
      "target": {
        "type": "StateFacet",
        "id": "7aa991ba-2043-4259-8d85-b6377ac778df",
        "value": "created"
      }
    },
    {
      "type": "ConsistsOf",
      "id": "9cc0b56f-2220-4c28-be4f-22560c200388",
      "target": {
        "type": "AccessPointFacet",
        "id": "39bd3a5b-9737-40bc-8934-6e491aee8fed",
        "endpoint": "https://old.example.org"
      }
    }
  ]
}
```

### `PUT` Replace Intent (example)

**Request headers:**
- `Content-Type: application/json`
- `Accept: application/json`

**Client request (`PUT /instances/EService/1a50a46d-2210-4a17-bd2f-22450b109264`):**
```json
{
  "type": "EService",
  "id": "1a50a46d-2210-4a17-bd2f-22450b109264",
  "consistsOf": [
    {
      "type": "ConsistsOf",
      "id": "c11d1e44-5555-4a17-bc4e-33660a209999",
      "target": {
        "type": "StateFacet",
        "id": "d22e2f55-6666-4b28-cd5f-44770b30aaaa",
        "value": "ready"
      }
    }
  ]
}
```
*(Both `id` values are freshly client-generated UUIDs that don't yet exist in the system — this is a new **ConsistsOf**/**StateFacet** pair, not an update of the omitted **AccessPointFacet** one.)*

**Final state after `PUT` (intent):**

```json
{
  "type": "EService",
  "id": "1a50a46d-2210-4a17-bd2f-22450b109264",
  "consistsOf": [
    {
      "type": "ConsistsOf",
      "id": "c11d1e44-5555-4a17-bc4e-33660a209999",
      "target": {
        "type": "StateFacet",
        "id": "d22e2f55-6666-4b28-cd5f-44770b30aaaa",
        "value": "ready"
      }
    }
  ]
}
```

- The addressed instance representation is replaced by what was sent.
- Omitted parts (e.g., the **AccessPointFacet** instance) are not preserved by intent.
- Validation (cardinality/schema constraints) is evaluated on the final post-mutation state.

### `PATCH` Merge Intent (example)

**Request headers:**
- `Content-Type: application/merge-patch+json`
- `Accept: application/json`

**Client request (`PATCH /instances/EService/1a50a46d-2210-4a17-bd2f-22450b109264`):**
```json
{
  "type": "EService",
  "id": "1a50a46d-2210-4a17-bd2f-22450b109264",
  "consistsOf": [
    {
      "type": "ConsistsOf",
      "id": "8bb0a45e-1110-4b17-ad3f-11450b109277",
      "target": {
        "type": "StateFacet",
        "id": "7aa991ba-2043-4259-8d85-b6377ac778df",
        "value": "ready"
      }
    }
  ]
}
```

**Final state after `PATCH` (intent):**

```json
{
  "type": "EService",
  "id": "1a50a46d-2210-4a17-bd2f-22450b109264",
  "consistsOf": [
    {
      "type": "ConsistsOf",
      "id": "8bb0a45e-1110-4b17-ad3f-11450b109277",
      "target": {
        "type": "StateFacet",
        "id": "7aa991ba-2043-4259-8d85-b6377ac778df",
        "value": "ready"
      }
    },
    {
      "type": "ConsistsOf",
      "id": "9cc0b56f-2220-4c28-be4f-22560c200388",
      "target": {
        "type": "AccessPointFacet",
        "id": "39bd3a5b-9737-40bc-8934-6e491aee8fed",
        "endpoint": "https://old.example.org"
      }
    }
  ]
}
```

- Only the provided property field value (for `StateFacet.value`) is merged/updated.
- Unspecified property fields remain unchanged.

> **Media type rule:** In this API, PATCH requests use `application/merge-patch+json`.

| Method | Client sends | Server intent on addressed instance representation |
|--------|--------------|----------------------------------------------------|
| `PUT`  | full instance representation | replace with submitted instance representation |
| `PATCH` | partial instance representation (delta) | merge only submitted property field values |
