Resource Registry — API Management (Instances & Admin)¶
Instance Management — base path /instances¶
💡 Architectural Note: Nested JSON vs Flat URIs
Throughout this chapter, you will see deep conceptual structures (like Facet instances or ConsistsOf instances attached to a Resource instance) represented as heavily nested JSON objects. This nesting is used for readability, payload efficiency, and representing the structural graph topology in a single response.
However, the REST URIs remain strictly flat. You do not update a Facet instance by constructing a nested path like/instances/{resource-type}/{resource-uuid}/{consists-of-type}/{consists-of-uuid}/{facet-type}/{facet-uuid}. Because every instance (Resource instance, Facet instance, IsRelatedTo instance, or ConsistsOf instance) is a topologically independent graph instance with a globally unique UUID, the API addresses every single instance individually via/instances/{type}/{instance-uuid}. For the design rationale behind this separation, see Flat Addressability vs Nested ROA Paths.
Authorization & Token Selection¶
| Action | HTTP | Path | Query Parameters | IS-M / Infra-M | IS-Admin | Ctx-M | IS-Editor | IS-Contrib | IS-Member |
|——–|——|——|——————|:————–:|:——–:|:—–:|:———:|:———-:|:———:|
| List | GET | /instances/{type} | limit, offset, polymorphic, hierarchical, metadataPolicy, contextsPolicy, membershipScope | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Execute JSON Query | QUERY | /instances (POST /instances/query fallback) | limit, offset, polymorphic, hierarchical, metadataPolicy, contextsPolicy, membershipScope | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Exists | HEAD | /instances/{type}/{instance-uuid} | hierarchical, metadataPolicy, contextsPolicy, membershipScope | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Read | GET | /instances/{type}/{instance-uuid} | hierarchical, metadataPolicy, contextsPolicy, membershipScope | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Create | POST | /instances/{type} | sync, bypassHierarchyCheck, metadataPolicy, contextsPolicy, membershipScope | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | ❌ |
| Create / Update | PUT | /instances/{type}/{instance-uuid} | sync, bypassHierarchyCheck, metadataPolicy, contextsPolicy, membershipScope | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | ❌ |
| Merge Update | PATCH | /instances/{type}/{instance-uuid} | metadataPolicy, contextsPolicy, membershipScope | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | ❌ |
| Remove from Current Context | DELETE | /instances/{type}/{instance-uuid} | propagationMode, dryRun, metadataPolicy, contextsPolicy, membershipScope | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | ❌ |
| Add to Context | PUT | /instances/{type}/{instance-uuid}/contexts/{new-context-uuid} | hierarchical, propagationMode, dryRun, metadataPolicy, contextsPolicy, membershipScope, bypassHierarchyCheck | ✅ | ✅ | ⚠️ | ⚠️ | ❌ | ❌ |
| Remove from Context | DELETE | /instances/{type}/{instance-uuid}/contexts/{context-uuid} | hierarchical, propagationMode, dryRun, metadataPolicy, contextsPolicy, membershipScope, bypassHierarchyCheck | ✅ | ✅ | ⚠️ | ⚠️ | ❌ | ❌ |
| List Instance Contexts | GET | /instances/{type}/{instance-uuid}/contexts | hierarchical, membershipScope | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Token Scope Rule:
| Operation Group | Token must be issued for |
|—————-|—————————|
| List, Execute JSON Query, Exists, Read | The operational Context from which visibility is evaluated |
| Create, Create / Update, Merge Update, Remove from Current Context | The operational Context where the instance is managed |
| Add to Context | The token Context is the deterministic source topology. Ctx-M and IS-Editor may target only its subtree. IS-M, Infra-M, and IS-Admin may also target a sibling Context, and any other live Context only by explicitly supplying bypassHierarchyCheck=true. |
| Remove from Context | The Context in the path, or @current for the token Context. As for Add to Context, Ctx-M and IS-Editor may target only the token Context subtree; IS-M, Infra-M, and IS-Admin may also target a sibling Context, and any other live Context, also under another Root, only by explicitly supplying bypassHierarchyCheck=true. |
| List Instance Contexts | The operational Context in which the instance is looked up, exactly as for Read; it also anchors membershipScope=subtree |
HTTP Contract¶
| Action | Additional Request Headers | Response Headers | Success HTTP Code | Error HTTP Code |
|——–|—————————-|——————|——————-|—————–|
| List | Accept | Content-Type, Link, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found |
| Execute JSON Query | Content-Type, Accept | Content-Type, Link, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden |
| Exists | Accept | Content-Length, Content-Type, Link, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found |
| Read | Accept | Content-Type, Link, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found |
| Create | Content-Type, Accept | Content-Type, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 201 Created | 400 Bad Request, 403 Forbidden, 404 Not Found, 409 Conflict |
| Create / Update | Content-Type, Accept | Content-Type, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 201 Created / 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found, 409 Conflict |
| Merge Update | Content-Type: application/merge-patch+json, Accept | Content-Type, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found, 409 Conflict |
| Remove from Current Context | Accept, Prefer (return) | Content-Type, X-Warning, Preference-Applied, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found, 409 Conflict |
| Add to Context | Accept, Prefer (return) | Content-Type, X-Warning, Preference-Applied, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found, 409 Conflict |
| Remove from Context | Accept, Prefer (return) | Content-Type, X-Warning, Preference-Applied, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found, 409 Conflict |
| List Instance Contexts | Accept | Content-Type, Link, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found |
Operational Notes¶
HEADIs the Bodyless Read:HEAD /instances/{type}/{instance-uuid}is the automatic bodyless view of the correspondingGET, not an independent operation with reduced semantics. It accepts the samehierarchical,metadataPolicy,contextsPolicy, andmembershipScopeparameters and returns the same status and representation headers (plus the computedContent-Length), while omitting only the response body.ListEndpoint403Absence: TheListendpoint never returns403 Forbiddenfor data visibility boundaries. Results are strictly filtered according to the token’s operational Context. If no instances exist within the token’s scope, it simply returns an empty list[], even if those instances exist in other Contexts. (Note: AListoperation returns403 Forbiddenonly for authorization reasons, never because nothing is visible: when the caller has no Resource Registry role, when it requests a privileged parameter value it is not entitled to (e.g.,membershipScope=global), or when the token Context itself is in a non-activestate, which acts as a global administrative block for standard roles, as detailed in the Context Management chapter).Path vs Body Consistency (Double-Check): When creating or updating an instance via
PUTorPATCHon/instances/{type}/{instance-uuid}, thetypeandidparameters in the URL path must exactly match thetypeandidfields provided inside the JSON payload. The same holds for thetypeof aPOST /instances/{type}: a bodytypedifferent from the path, a subtype included, returns400 Bad Request. Even thoughPATCHacts as a partial merge, thetypeandidfields are strictly mandatory in the JSON body. If they are missing or do not match, the server strictly rejects the request with a400 Bad Requestto prevent accidental data corruption or schema-mismatch errors.Type-in-Path Semantics (Exact Type Enforcement): For all endpoints targeting a specific instance using the path variable
{type}(e.g.,/{type}/{instance-uuid}), the client MUST specify the exact concrete Type of the instance. Specifying an abstract supertype (e.g., calling/instances/Resource/{uuid}when the instance is actually anEService) is strictly invalid. OnHEAD,GET,PATCH, andDELETEit is rejected with a404 Not Found(as the requested composite key(type, instance-uuid)effectively does not exist, which safely prevents any existence leakage of the UUID). The same404 Not Foundholds, on every endpoint that addresses the(type, instance-uuid)key (HEAD,GET,PATCH,DELETE,List Instance Contexts,Add to Context, andRemove from Context), for a{type}that is not a Resource, Facet, IsRelatedTo, or ConsistsOf Type, such as aPropertyType; onPOST, onPUT, and on the collectionGET /instances/{type}such a Type returns400 Bad Request.PUTandPOSTfollow the creation and update rules below: an abstract Type cannot be instantiated (409 Conflict), and a UUID already identifying an instance of another Type is occupied (409 Conflict). The system enforces strict 1:1 parity between the concrete instance schema and the{type}path parameter. (Note: This exact-match restriction applies strictly to single-instance targeting endpoints. The collection endpointGET /instances/{type}fully supports querying by abstract supertypes when combined with thepolymorphic=trueparameter).Instance Creation Scope: While flat URIs address every graph instance individually for reads and updates, standalone creation via
POST /instances/{type}orPUT /instances/{type}/{instance-uuid}is structurally valid only for Resource, IsRelatedTo, and ConsistsOf instances, of a concrete Type: a creation request for an abstract Type returns409 Conflict. As dictated by the core IS-Model topology, a Facet instance cannot exist independently (a standalone creation request for a Facet Type returns400 Bad Request) and must be created exclusively as a nested element (either within a parent Resource mutation payload, or within a standalone ConsistsOf mutation payload acting as itstarget). When a Relation instance is created on its own, its endpoints follow the direction of the Relation:sourceis always an endpoint reference to a Resource instance that already exists; it is never created by the Relation. Asourcethat is missingtypeorid, or that carries anything beyond an endpoint reference, returns400 Bad Request. A source that does not exist returns404 Not Found, and so does atypethat is not the concrete Type of the instance, because the source is looked up by its exact(type, id)key; a source that exists but is not present in the token Context returns403 Forbidden.ConsistsOf
target: always the complete new Facet instance, created together with the ConsistsOf instance. A reference to an existing Facet instance is rejected with409 Conflict, because every Facet instance already has its own ConsistsOf instance and can have only one.IsRelatedTo
target: either an endpoint reference to an existing Resource instance, or the complete new Resource instance (with its ConsistsOf/Facet composition), created together with the IsRelatedTo instance. An endpoint reference (typeandidonly) to a UUID that does not exist returns404 Not Found: a reference never creates. A referenced target that exists but is not present in the token Context returns403 Forbidden.
When a Relation instance is updated,
sourceis an endpoint reference to the persisted source, andtargetis either an endpoint reference to the persisted target or its complete representation, which updates it (see below). The same payload that created a Relation instance together with its target can therefore be repeated with the same outcome.Create(POST) — Optional Client-Supplied UUIDs: UnlikePUT,POST /instances/{type}does not require anidon the root instance or on any instance nested in it. Any suppliedidis honored only when it is globally unused. Anidthat is already in use, by an instance of any Type or by any other registry element, is a creation conflict (409 Conflict): the request is well formed and fails only because of the current state of the registry. Because the whole payload tree is created inside a single database transaction, a conflict anywhere in the tree rolls back the entire request atomically.Create(POST) Is Intentionally Not Idempotent: Two identicalPOSTrequests that omit everyidalways produce two distinct instances (Resource, Facet, IsRelatedTo, or ConsistsOf alike, depending on what is being created) — this is deliberatePOSTsemantics per RFC 9110 §9.3.3, not a limitation. Clients that need retry-safety for a specific element should supply that element’s ownid; see the point above for what happens on a resubmit in that case.Writes on instances outside the token Context: A
PUTorPATCHwhose root instance, or an existing ConsistsOf or Facet instance named in its body, exists but is not present in the token Context returns403 Forbidden, by the same rule as lookups. A write never brings an existing instance into the token Context: it enters it only throughAdd to Context. The only write that extends membership is aPUTwithhierarchical=true, which reaches the descendants of the token Context (see Hierarchical Distribution below).Lookup (
403vs404): For instance lookup endpoints (HEAD/GETon/instances/{type}/{instance-uuid}), the API intentionally distinguishes404 Not Found(no instance exists for the requested lookup key) from403 Forbidden(an instance matching the lookup key exists, but is outside the caller’s authorization scope). This distinction is preserved by design for operational diagnosability. Given the D4Science exposure model (write surfaces internal;/accessfacade internet-facing but read-scoped), this is an explicit and accepted security/operational trade-off. Mutation collision checks can also disclose UUID occupancy throughPOSTconflicts or cross-Type validation, so returning403 ForbiddenonGETdoes not materially change the threat model.Point Read Scope Contract (
hierarchical): Point lookups (HEAD/GET /instances/{type}/{instance-uuid}) intentionally supporthierarchicalfor scope alignment with collection discovery. Withouthierarchical=true, lookup is restricted to the token Context; withhierarchical=true, lookup is evaluated against the authorized descendant subtree.Discovery -> Fetch Symmetry Rule: If a client discovers an instance through a hierarchical collection operation (
GET /instances/{type}?hierarchical=trueorQUERY /instances?hierarchical=true), it should keep the samehierarchical=truescope on the subsequent point read. Dropping the flag narrows the scope and can legitimately turn a previous discovery into403 Forbiddenon point fetch.Lookup vs UUID Uniqueness: Point lookup uses the exact composite key
(type, instance-uuid)so that a wrong concrete Type returns404 Not Foundwithout disclosing which Type owns the UUID. Mutation validation nevertheless enforces one graph-wide UUID namespace across all instance categories and Types.PUTCreate-or-Update and UUID Reuse: The root UUID addressed byPUT /instances/{type}/{instance-uuid}creates the instance when globally unused and updates it in place when it already identifies the same concrete Type. A nested UUID identifying the same concrete Type is likewise updated only when its immutable topology (ownership or Relation endpoints) is consistent with the payload; an inconsistent placement or endpoint assertion returns409 Conflict. Any root or nested UUID already identifying an instance of a different concrete Type returns409 Conflict, as every occupied UUID does. A UUID composed entirely of one repeating hexadecimal character (e.g.,1111…11,aaaa…aa) is reserved by the system: supplying one as an instance ID or as a target Context ID returns400 Bad Request(see “System” Environments). These rules are deterministic.List Instance Contextsreturns: Returns a map of Context UUID → Context path. With the defaultmembershipScope=subtree, every role receives memberships within the token Context subtree; a Root Context token therefore yields a topologically global subtree.IS-M,Infra-M, andIS-Adminmay instead requestmembershipScope=globalto receive every membership independently of the token Context. The instance is looked up exactly as byReadandExists, for every role and everymembershipScopevalue: it must be present in the token Context, or in one of its descendants whenhierarchical=true; otherwise the request returns403 Forbidden(or404 Not Foundwhen the exact(type, instance-uuid)key does not exist).membershipScopeonly selects which memberships of the instance found this way are returned. The response emitsLink: rel="up"pointing back to the owning instance URI. Omitting memberships outside an explicitly requestedsubtreeemits noX-Result-Scopetoken;state-filteredis emitted when the applicable state policy removes a membership inside the requested boundary.
Contextual Mutations & Update Intent (PUT vs PATCH)¶
(Note on Response Shape: All PUT and PATCH operations on the base instance path /instances/{type}/{instance-uuid} always return a representation with the same structural shape as a standard Read operation for the targeted instance. Even if sync is used to distribute the state across multiple Contexts, the API response remains strictly bounded to the requested target instance. These operations do not trigger broad topological traversal (unlike membership operations) and therefore do not return an Operation Envelope).
Because Resource instances act as structural hubs for their nested Facet instances (via ConsistsOf instances), and because all these graph nodes are shared across Contexts by reference rather than being duplicated, updating a Resource instance’s topology in one Context can have broader repercussions. To effectively manage these shared topologies, the API explicitly distinguishes between PATCH (Merge) and PUT (Full Replace) operations, providing an escalating mechanism of topological impact.
Important (Global Property Mutations): Because property fields are intrinsically bound to the single underlying instance, modifying a property field via PATCH or PUT applies globally across all Contexts where that instance is shared. Therefore, the concept of a hierarchical Context sync applies exclusively to topological structural changes (i.e., modifying the graph structure, such as attaching or detaching Facet instances), never to property field mutations.
PATCH (Merge Semantic)¶
PATCH applies a Merge semantic (application/merge-patch+json), modifying only the provided fields and leaving the rest of the instance intact. In accordance with RFC 7396, arrays containing standard data fields (e.g., a list of strings) are treated as atomic values; providing such an array in a PATCH payload will completely replace the existing array.
Mandatory Identity Fields: Even though a Merge Patch normally allows clients to send only the fields they wish to change, the Resource Registry strictly requires the top-level
typeandidfields to be present in the JSON body. These fields must exactly match thetypeandidprovided in the URL path. If they are omitted or mismatched, the request is instantly rejected with a400 Bad Request.Relation endpoints in a
PATCH: On a IsRelatedTo or ConsistsOf instance,sourceandtargetmay be omitted. When present they follow the same rules as in aPUT: system fields inside them are dropped, a malformedsourceortargetreturns400 Bad Request, and one that identifies a different endpoint returns409 Conflict. Atargetthat carries content is merged into the persisted target, exactly as aPATCHaddressed to the target itself does; atargetthat is an endpoint reference leaves it untouched.Null and Omission Semantics: An omitted property is left unchanged, whereas an explicitly submitted
nullis an update instruction that removes the property in accordance with RFC 7396. Optional properties may therefore be removed throughPATCH; mandatory properties cannot be removed, and attempting to do so results in409 Conflictduring schema validation. The model does not exposenotnullas an independent constraint.Pragmatic Deviation on Graph Arrays: The Resource Registry API intentionally diverges from the RFC rule for structural graph arrays like
consistsOfwhen thePATCHis performed on a Resource instance. If aPATCHpayload on a Resource instance includes aconsistsOfarray, the backend performs a surgical merge: it patches only the explicitly referenced ConsistsOf and Facet instances (requiring both theidof the ConsistsOf instance and theidof its target Facet instance to safely match the instances) without dropping the omitted ones. If a client attempts to execute aPATCHomitting these nested IDs (e.g., intending to create a new nested structure on the fly), the request is strictly rejected with a400 Bad Request. To create new topological structures like adding a new Facet instance, clients must use aPUToperation: aPATCHnever creates, so a nestedidthat does not exist returns400 Bad Request, and a ConsistsOf instance whose submitted targetiddiffers from its persisted Facet instance returns409 Conflict, because a Relation never changes endpoint. A nested ConsistsOf instance that belongs to another Resource instance returns409 Conflict, as in aPUT.PATCHdoes not support hierarchical parameters: they are ignored withX-Warningfor roles allowed to use them, and return403 Forbiddenfor any other role.
PUT on Resource Instances (Topological Impact)¶
When the target of a PUT operation is a Resource instance, the API enforces a Full Replace semantic for the target Context. Any ConsistsOf instance or nested Facet instance omitted from the payload will be systematically removed from the Context: it leaves the token Context only, stays unchanged in every other Context it belongs to, and is deleted when the token Context was its last one. This enables atomic, transaction-level replacements of mandatory Facet instances without breaking schema validation (e.g., solving the “Cardinality Chicken-and-Egg” problem). The topological impact of a PUT operation on a Resource instance is governed by its query parameters:
1. Single Context Update (Local Copy-on-Write)¶
Without hierarchy parameters, the topological effect (adding, removing, or replacing Facet instances) is confined strictly to the current token Context. This operation handles any combination of structural changes: adding new Facet instances (by including new ConsistsOf JSON objects with a freshly client-generated id that does not yet exist in the system), removing existing ones (by omitting them from the payload), or both simultaneously.
This simultaneous action is what enables the Local Copy-on-Write (Forking) pattern: to create a local variation of a shared Facet instance without affecting other Contexts, the client can perform a PUT on the parent Resource instance, assigning a freshly client-generated id to both the new ConsistsOf instance and its nested Facet instance, instead of the id of the shared instances.
The system will create a new isolated clone for the current Context and seamlessly drop the old association locally. (Note: It is crucial to generate fresh ids for both. If the client reused the existing ConsistsOf instance’s id while only generating a new id for the Facet instance, it would attempt to retarget an existing shared ConsistsOf instance to a different Facet across different Contexts, which strictly violates the topological rule that a ConsistsOf instance points to exactly one immutable Facet target).
While a fork could theoretically be achieved using two distinct operations (a Remove from Current Context on the existing ConsistsOf instance, followed by a standalone creation of a new ConsistsOf instance along with its new target Facet instance), performing it in two steps is restricted by min/max constraints on the Resource:
If
max: 1but nomin, you could remove then create.If
min: 1but nomax, you could create then remove.If both
min: 1andmax: 1are set, any sequential order violates the schema.
More importantly, even without schema constraints, using a single PUT on the parent Resource is the only way to guarantee that both the addition and the removal are executed atomically within a single transaction.
For example, consider a Resource instance R currently composed of Facet instances [F1, F2, F3, F4] in the current Context, where F1 satisfies a strict min: 1, max: 1 schema constraint.
If a PUT request provides a new configuration [F1b, F2, F3, F5]: the old F1 and F4 are removed, while the new F1b and F5 are added, all simultaneously.
Because it executes as a single atomic transaction, the min: 1, max: 1 constraint (transitioning from F1 to F1b) is never violated.
(Note: Schema validation is strictly evaluated at the very end of the transaction. If the resulting topological state of the Resource instance violates its schema, the entire operation is safely rolled back and returns a 409 Conflict).
2. Subtree Synchronization (?sync=existing)¶
Safely pushes topological changes (like attaching or detaching Facet instances) only to descendant Contexts where the Resource instance is already explicitly shared. This atomically synchronizes the submitted Resource payload across the applicable descendant Contexts.
It is a synchronization of the payload, not a membership operation: every applicable descendant Context is aligned to exactly what the payload describes, and the propagation constraints of the ConsistsOf instances are not consulted (they govern Add to Context and Remove from Current Context, whose outcome depends on the graph rather than on a payload).
Similar to the Single Context Update scenario, attempting to manually replicate these topological shifts across the hierarchy via sequential Remove from Current Context and Add to Context operations on the nested instances in each child Context is heavily restricted by min/max constraints on the parent Resource:
If
max: 1but nomin, you could remove then add.If
min: 1but nomax, you could add then remove.If both
min: 1andmax: 1are set (e.g., swappingF1forF1b), any manual sequential propagation in the descendant Contexts strictly violates the schema.
By executing the [F1, F2, F3, F4] -> [F1b, F2, F3, F5] mutation described above with ?sync=existing, the identical simultaneous atomic replacement occurs not just in the current Context, but simultaneously across all applicable descendant Contexts, safely bypassing the schema deadlock.
Important (Strict Uniformization): Because the PUT operation enforces a Full Replace, any local topological deviations (e.g., an extra Facet instance previously added only in a child Context) are systematically wiped out to perfectly align the target Context with the submitted payload.
Because the resulting topology becomes completely uniform across all synced Contexts, the schema validation result is globally deterministic: it is mathematically impossible to adhere to the schema in one Context while violating it in another.
Crucially, a client can also achieve this in two separate phases: they might first update the local Context without the flag, and later issue the identical PUT [F1b, F2, F3, F5] ?sync=existing payload.
In this second phase, the operation behaves as a “pure sync”: it makes no local topological changes (since the state already matches) but atomically forces the alignment down the hierarchy. This “pure sync” pattern is extremely valuable for reconciling descendant Contexts that have become topologically misaligned (e.g., due to operational drift or mistakes).
Reconciling them in a single shot via PUT ?sync=existing is infinitely safer than the manual alternative (i.e., removing the entire Resource instance from the descendant Context and re-adding it with the corrected facets).
Removing a Resource instance from a Context normally triggers the avalanche destruction of its associated IsRelatedTo instances. Even if a client attempted to bypass the standard avalanche using a surgical removal of the Resource instance, the problem persists: a relation cannot logically exist in a Context if its source and target Resource instances are missing.
Therefore, removing the Resource instance inherently drops all its incoming and outgoing IsRelatedTo instances from that Context.
The client would then be forced to meticulously track down and perform surgical Add to Context operations to restore all those N relations (and potentially recreate from scratch any relations that existed only in that local Context). The atomic “pure sync” completely avoids this operational nightmare and collateral damage, perfectly restoring the intended schema and structure. (The orphaned F1 and F4 continue to exist in any external Contexts; if no longer referenced anywhere, they are destroyed by the Garbage Collector).
(Note: On a creation, sync=existing is logically ignored as the instance does not yet exist anywhere, and the system safely emits an X-Warning header. A role that is not allowed to use sync receives 403 Forbidden instead, because authorization is evaluated before applicability; see Parameter Value Handling).
3. Hierarchical Distribution (?sync=tree)¶
Operates identically to the Subtree Synchronization mode, but with one fundamental expansion in blast radius: instead of pushing changes only to descendant Contexts where the Resource instance is already explicitly shared, it forcefully propagates the Resource instance itself and all its topological changes to every descendant Context within the authorized subtree, systematically overriding local absences.
In other words, sync=tree synchronizes the payload over the whole subtree rooted at the token Context, whether or not the Resource instance is already present in each descendant: the result in every descendant Context is the same as in the token Context. Like sync=existing, it is a synchronization, not an Add to Context:
The payload decides, not the propagation constraints. Every ConsistsOf/Facet instance the payload describes reaches every descendant Context, including those whose ConsistsOf instance carries
add=unpropagate; every one it omits is removed there (strict uniformization, below). Propagation constraints govern membership operations only.Nothing outside the payload moves. IsRelatedTo instances attached to the Resource instance, which the payload does not describe, are neither added to nor removed from any descendant Context, and no related Resource instance follows. There is no
Add to Contextavalanche.It is the non-administrative way to push a Resource down a subtree. Hierarchical and
surgicalAdd to Context remain restricted toIS-Adminor higher because they propagate the live relation graph rather than a caller-bounded payload (see Privileged Add to Context Uses the Canonical Membership Endpoint).
This mode enforces the exact same strict uniformization, shares the exact same atomic transaction guarantees, and completely bypasses the manual schema violation limitations described above.
(Note: Unlike sync=existing, which is logically ignored on creation (emitting an X-Warning header), sync=tree is fully supported and actively used during the initial creation of a Resource instance to establish a baseline configuration across the entire subtree from day one).
4. Synchronization of One Context (?sync={context-uuid})¶
Operates as the Hierarchical Distribution, restricted to one named Context: the write is on the token Context, and the named Context ends up with the same Resource instance and the same ConsistsOf/Facet instances. A ConsistsOf instance the payload creates is created in both; one the payload names must be present in the token Context or be new. The cardinality constraints are checked on the token Context, and the named Context, aligned to it, satisfies them too; everything is one transaction. It is available on POST and PUT.
The named Context follows the rules of the destination of Add to Context: it must be live, reachable by the caller’s role (for IS-Editor and Ctx-M the token subtree; for IS-M, Infra-M, and IS-Admin also a sibling, and any live Context with bypassHierarchyCheck=true) and, for IS-Editor, effectively active (see sync).
Its typical use is a change that a Context must take from a parent rather than create on its own, such as the state of a service per Context: a VRE goes back to active with a PUT from its parent, where the service is active, carrying the EService instance as the parent sees it, with sync={vre-uuid}. The parent receives what it already holds and is unchanged; the VRE takes the shared StateFacet again and its own one leaves it.
PUT on Other Instances (Full Replace Semantic)¶
When the target of a PUT operation is not a Resource instance, the submitted payload is the complete replacement representation, not a merge patch. Every custom property that must remain must be repeated; an omitted optional property is removed, while omission of a mandatory property is resolved with its declared defaultValue, or, when none is declared, makes the resulting representation invalid and returns 409 Conflict after schema validation.
Facet instances: The payload includes matching
typeandidplus every custom property that must remain.IsRelatedTo instances: The payload includes matching
typeandid, the complete custom-property set,source,target, andpropagationConstraint.ConsistsOf instances: The payload includes matching
typeandid, the complete custom-property set,source,target, andpropagationConstraint.
For both Relation categories, source and target are required and identify the Relation’s persisted endpoints, which never change. In its basic form each is an endpoint reference (see Relation endpoint references): type and id are required, while the system fields supertypes, metadata, and contexts are accepted and dropped without warning, so that a Relation read from the API can be submitted back unchanged. An endpoint reference leaves the endpoint untouched.
A target whose only other members are an empty consistsOf or isRelatedTo array is an endpoint reference too. The target may instead carry content beyond the system fields: the properties of the Facet instance for a ConsistsOf instance, or the consistsOf composition of the Resource instance for an IsRelatedTo instance. It is then the complete representation of the target and replaces it, exactly as a PUT addressed to the target itself does, with the same validation and the same outcomes. This is what makes the PUT that created a Relation instance together with its target repeatable. To change only the Relation instance, submit the target as an endpoint reference: a complete representation replaces the target with what is submitted, including any change made to it in the meantime. Since a target without content is a reference, the properties of a Facet instance cannot all be removed through its ConsistsOf instance; that is done with a PUT on the Facet instance. The source is always an endpoint reference.
A missing, null, or malformed source or target, including a source that carries custom fields or nested instances, returns 400 Bad Request; a well-formed source or target whose id or type differs from the persisted endpoint returns 409 Conflict. propagationConstraint is mutable and validated against the concrete Relation contract; it is always required in a PUT, on creation and on update alike (omission returns 400 Bad Request), and optional only in a POST, where omission applies the model defaults (see IS-Model core topology). A Relation can be retargeted only by deleting it and creating a new one.
These requirements apply even when a submitted value is unchanged: PUT always carries the full client-controlled state. System-managed fields continue to follow the common drop-without-warning rule.
Note on
sync: Becausesyncexclusively governs the topological distribution of a Resource instance, it has no structural meaning when targeting a Facet, IsRelatedTo, or ConsistsOf instance directly. If a client mistakenly passes it when mutating these specific types, the system safely ignores it and emits anX-Warningheader, for roles allowed to use it (any other role receives403 Forbidden, since authorization is evaluated first) (e.g.,199 resource-registry "ignored-query-parameters=sync; ignored-count=1; reason=Not applicable for this instance type").
For detailed operational patterns (including Facet instance Forking, Copy-on-Write, and resolving cardinality constraints), refer to the API Operational Cookbook & Advanced Use Cases.
Membership Operations (Add to Context / Remove from Context)¶
Conceptual Note (Sharing & Unsharing): Because Contexts act as logical environments over a global graph, the act of “Adding to Context” can be conceptually viewed as “sharing” an instance into another Context, making it visible and usable there. Conversely, “Remove from Current Context” acts as “unsharing”. This documentation and the broader ecosystem may occasionally use the terms share and unshare informally to describe these membership operations.
The API manages an instance’s Context membership on one sub-resource, /instances/{type}/{instance-uuid}/contexts/{context-uuid}:
Add (
PUT): TheAdd to Contextoperation (PUT /instances/{type}/{instance-uuid}/contexts/{new-context-uuid}) adds an instance from a source Context (determined by the authorization token) to a destination Context (specified in the URL).Remove (
DELETE): TheRemove from Contextoperation (DELETE /instances/{type}/{instance-uuid}/contexts/{context-uuid}), its inverse, removes it from the Context specified in the URL, or from the token Context when the URL names@current.Remove from the current Context (
DELETE): TheRemove from Current Contextoperation (DELETE /instances/{type}/{instance-uuid}) is the shortcut ofRemove from Contexton@currentwithouthierarchical, and is available to every writer role.
The source topology is always the exact token Context, even for universal roles and even when
bypassHierarchyCheck=true is used. The bypass waives only destination containment; it never turns
the source lookup into a global or hierarchical search. Combining it with hierarchical=true
atomically applies that one source blueprint to the destination Context and all its descendants.
hierarchical=true applies to an Add to Context of any instance category: a Facet,
IsRelatedTo, or ConsistsOf instance is added to the destination Context and all its
descendants as a Resource instance is.
Implicit Pull on Relations (downstream only): If the direct target of the
Add to Contextoperation is a Relation instance (IsRelatedTo or ConsistsOf), strict topological integrity applies: a Relation instance cannot exist in a Context without both its source and its target. The two ends are treated differently, because propagation travels strictly downstream, from source to target, and never upstream (see Strict Downstream Propagation):
Source: the source Resource instance must already be in the destination Context. The system never pulls it; when it is missing, the operation fails with
409 Conflict.Target: the system ALWAYS pulls the target Entity instance into the destination Context (if it isn’t already there), whatever the
addconstraint of the explicitly added Relation instance,unpropagateincluded.The same holds when the direct target is a Facet instance: the ConsistsOf instance pointing to it is added with it, as a structural requirement and not as upstream propagation, and its source Resource instance must already be in the destination Context, otherwise
409 Conflict.This guarantees that the graph is always structurally sound within any given Context boundary.
Authorization Rules:
Ctx-MandIS-Editorcan add instances only to the token Context or one of its descendants.IS-M,Infra-M, andIS-Admincan add to the token Context subtree or to a sibling Context without an override. A sibling is a Context with the same parent as the token Context; the descendants of a sibling are not siblings, and the Root has none.IS-M,Infra-M, andIS-Admincan add to any live Context by explicitly settingbypassHierarchyCheck=true.propagationMode=surgicalandhierarchical=trueon Add to Context requireIS-M,Infra-M, orIS-Admin.Remove from Contextfollows the same rules on the Context it names:Ctx-MandIS-Editorreach only the token Context subtree;IS-M,Infra-M, andIS-Adminalso reach a sibling Context without an override, and any live Context, also under another Root, withbypassHierarchyCheck=true;hierarchical=true, which removes the instance from the Context and all its descendants, requiresIS-M,Infra-M, orIS-Admin.propagationModekeeps the meaning it has on every removal (surgicalis available to every role allowed to remove).Remove from Current Contextretains its endpoint-specific role and scope rules: it acts on the token Context only, and ignoreshierarchicalwithX-Warning.
Add to Context error outcomes:
| Situation | Status |
|———–|——–|
| Destination outside the Contexts the role may reach without bypassHierarchyCheck=true, or privileged parameter without the required role | 403 Forbidden |
| Destination Context does not exist | 404 Not Found |
| Destination Context exists but is deleted (cemetery) | 409 Conflict |
| Source (type, instance-uuid) key does not exist | 404 Not Found |
| Source exists but is not present in the token Context | 403 Forbidden |
| Token Context, or destination Context, not active, for a role without the administrative state override | 403 Forbidden |
| Final validation of the resulting state fails (e.g., missing source of an explicitly added Relation, mandatory Facet left behind) | 409 Conflict |
The destination is examined before its reachability: a destination that does not exist or is in the cemetery returns 404 Not Found or 409 Conflict also to a caller that could not reach it.
Remove from Context error outcomes:
| Situation | Status |
|———–|——–|
| Context outside the Contexts the role may reach without bypassHierarchyCheck=true, or privileged parameter without the required role | 403 Forbidden |
| Context does not exist | 404 Not Found |
| Context exists but is deleted (cemetery) | 409 Conflict |
| (type, instance-uuid) key does not exist | 404 Not Found |
| Instance exists but is present neither in the Context nor, with hierarchical=true, in any of its descendants | 200 OK, empty Operation Envelope (the requested state already holds) |
| Token Context, or the Context, not active, for a role without the administrative state override | 403 Forbidden |
| Final validation of the resulting state fails (e.g., a mandatory Facet removed) | 409 Conflict |
As for Add to Context, the Context is examined before its reachability.
Adding or removing from a Context triggers an avalanche effect. Before successfully returning, the system always strictly validates the resulting state in the target Contexts to prevent logical inconsistencies (e.g., ensuring mandatory Facet instances are present, or ensuring that a Relation instance is not added to a Context where its source Resource instance is missing). If this final validation fails, the operation is aborted and returns a 409 Conflict (topological/schema violation). If successful, every membership operation (Add to Context, Remove from Context, Remove from Current Context) returns the full list of instances affected by the avalanche effect. For a removal, the list includes the Relation instances that leave the Context only because one of their endpoints does, incoming ones included.
Even though the Add to Context operation triggers a complex avalanche process, it is exposed via PUT because it is strictly idempotent. Calling the endpoint 1 time or 100 times results in the same final graph state. The URI explicitly identifies the membership association. The same endpoint carries the privileged surgical, hierarchical, and cross-boundary variants; parameter-level authorization prevents less privileged roles from invoking them. A non-administrative caller that needs to bring a Resource instance into descendant Contexts without the relation avalanche uses the hierarchical instance PUT instead (Hierarchical Distribution above), which carries only the structure described by its payload.
Operation Envelope and Parameter Matrix¶
Because these operations can trigger avalanche effects, their canonical response is an Operation Envelope. The HTTP status code is always 200 OK (if successful), but the density of the response body and the effect of query parameters (metadataPolicy, contextsPolicy, membershipScope) depend strictly on the Prefer: return header. The default behavior is to return the full representation.
Successful operation-envelope responses always emit Preference-Applied with the applied payload shape (return=representation or return=minimal). When the request omits Prefer, the response still emits Preference-Applied: return=representation to make the default explicit.
| dryRun | Prefer: return header | Success HTTP Code | Action | Body Density | metadataPolicy, contextsPolicy, membershipScope |
|:—:|—|—|—|—|—|
| false | Missing or representation | 200 OK | Real Execution | Full Operation Envelope | Applied (enrich the returned envelope elements) |
| false | minimal | 200 OK | Real Execution | Minimal Operation Envelope | Ignored (no structural payload to enrich; a privilege-expanding value without the role still returns 403) |
| true | Missing or representation | 200 OK | Simulation Only | Simulated Full Operation Envelope | Applied (enrich the simulated envelope elements) |
| true | minimal | 200 OK | Simulation Only | Simulated Minimal Operation Envelope | Ignored (no structural payload to enrich; a privilege-expanding value without the role still returns 403) |
Content Negotiation (Prefer header) and Payload Shape:
Returning the full array of complex objects can be bandwidth-intensive for large avalanche operations. Clients can use the standard HTTP Prefer header to explicitly request different shapes of the response payload.
Prefer: return=minimal: Returns a highly optimized flat array payload containing only the core topological fields (type,id, and for Relation instances:source,target). Custom fields,supertypes,metadata,contexts, andpropagationConstraintare strictly omitted. If a client explicitly passes inclusion query parameters (e.g.,metadataPolicy=root), the system ignores them to honor the minimal structural contract, and emits aX-Warningheader (e.g.,199 resource-registry "ignored-query-parameters=metadataPolicy; ignored-count=1; reason=Overridden by Prefer: return=minimal").Prefer: return=representation(Default): Returns the same flat array, with every element in its own complete representation. The system fieldsmetadataandcontextsare included only if explicitly requested via their respective query parameters (metadataPolicy,contextsPolicy), whereaspropagationConstraintis inherently included as a standard structural field for all Relation instances.
Both forms list every affected instance as a separate element of the array (Resource, Facet, IsRelatedTo, and ConsistsOf alike); no element is nested inside another. Every Relation element carries source and target: in the minimal form as "type" and "id", in the full form as endpoint references (type, supertypes, id, plus metadata with metadataPolicy=all and contexts with contextsPolicy=all). With metadataPolicy and contextsPolicy, root enriches every element of the array and all also the endpoint references. See Operation Envelope Representation.
Try-Check-Confirm Pattern¶
Because these operations can trigger powerful and unpredictable avalanches, it is highly recommended to adopt a “Try-Check-Confirm” pattern using dryRun=true, and using Prefer: return=representation to simulate the operation without persisting changes.
Removal Paradigm (Reference Counting)¶
The Delete operation on the base instance endpoint (DELETE /instances/{type}/{instance-uuid}) functions as a removal from the current Context (triggering local remove propagation constraints). The instance is physically destroyed (Garbage Collected) only when removed from its very last Context. When the exact (type, instance-uuid) key exists but the instance is not present in the token Context, the requested state already holds: the operation is a no-op that returns 200 OK with an empty Operation Envelope, exactly as an Add to Context of an instance that is already present does, so a Remove from Current Context can be repeated safely. It returns 404 Not Found only when the key does not exist at all. (A read of the same instance returns 403 Forbidden instead, because a read asks for an instance that is not available in this Context, while a removal asks for a state that is already in place.)
The Remove from Context operation (DELETE /instances/{type}/{instance-uuid}/contexts/{context-uuid}) removes the instance from the Context named in the URL, and with hierarchical=true from that Context and all its descendants, atomically. Executed with hierarchical=true on a Root Context, it removes the instance from every Context of that tree, so it is deleted unless it is also in a Context under another Root. Executed with hierarchical=true on a specific Virtual Organization (VO), it removes the instance from that subtree while allowing it to survive in parallel Contexts. The same reference counting applies: the instance is deleted when it leaves its last Context. hierarchical=true and bypassHierarchyCheck=true are reserved to IS-M, Infra-M, and IS-Admin, as on Add to Context.
Because both operations trigger avalanche effects (via propagation constraints), they support the dryRun=true query parameter and the Prefer: return=representation header. Following the same “Try-Check-Confirm” pattern, clients can simulate deletion to receive a 200 OK with the Operation Envelope of all affected instances before committing.
Additional Constraints¶
hierarchicalis available to every role on read/query operations. On instance writes it is available toIS-M,Infra-M,IS-Admin,Ctx-M, andIS-Editoraccording to the endpoint-specific rules; hierarchicalAdd to Contextand hierarchicalRemove from Contextare restricted toIS-M,Infra-M, andIS-Admin.List Instance Contexts: the instance is looked up as byRead;membershipScope=subtreeis the default for every role;IS-M,Infra-M, andIS-Adminmay explicitly requestmembershipScope=global. The requested subtree boundary emits noX-Result-Scopetoken.Non-
activeContext behavior: See the detailed behavior documented in Context Management.
Admin API — base path /admin¶
This section groups the whole-system maintenance, diagnostics, and destructive operations. These APIs are intentionally segregated under the /admin path to allow strict API Gateway and WAF filtering. They are designed for administrative interventions and are restricted to global administrators (IS-Manager / Infrastructure-Manager).
Authorization & Token Selection¶
| Action | HTTP | Path | Query Parameters | IS-M / Infra-M | IS-Admin | Ctx-M | IS-Editor | IS-Contrib | IS-Member |
|——–|——|——|——————|:————–:|:——–:|:—–:|:———:|:———-:|:———:|
| Execute Raw Query | QUERY | /admin/raw-query (POST /admin/raw-query/query fallback) | hierarchical, metadataPolicy, contextsPolicy, membershipScope, rawResult | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| System Dump | GET | /admin/system/dump | — | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| System Restore | POST | /admin/system/restore | — | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
Token Scope Rule:
| Operation Group | Token must be issued for |
|—————-|—————————|
| All /admin/* operations | Administrative role (IS-M / Infra-M) is required. System Dump and System Restore are whole-system operations: the token’s Context is irrelevant. |
HTTP Contract¶
| Action | Additional Request Headers | Response Headers | Success HTTP Code | Error HTTP Code |
|——–|—————————-|——————|——————-|—————–|
| Execute Raw Query | Content-Type, Accept | Content-Type, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden |
| System Dump | Accept (application/zip) | Content-Type (application/zip), Content-Disposition (attachment) | 200 OK | 403 Forbidden |
| System Restore | Content-Type (application/zip) | — | 204 No Content | 400 Bad Request, 403 Forbidden, 409 Conflict |
Operational Notes¶
Execute Raw Query: Body: JSON payload
{"query": "..."}. ⚠️ NOT for production (OrientDB SQL, backend may change). Should not be used programmatically or implemented in a client library — intended for manual administrative diagnostics only. Only read-only statements are accepted. Any valid read-only OrientDB SQL statement is supported (e.g.,SELECT,TRAVERSE,MATCH,EXPLAIN). Because the endpoint executes under a read-only database user, metadata/system-class reads and vendor-specific read functions are permitted, whereas destructive operations are inherently rejected at the engine level. The database session is scoped to the token Context;hierarchical=trueextends its visibility to descendants. WithrawResult=false(default), element rows are formatted through the Information System model and honourmetadataPolicy,contextsPolicy, andmembershipScope, while scalar and projection rows have no Information System representation and are therefore preserved in backend-native JSON without being dropped; explicitly requested enrichment parameters are ignored for those rows withX-Warning. WithrawResult=true, every row retains the backend-native JSON shape and field names unmodified. Serialization is all-or-nothing: a row-formatting failure never produces a partial successful result.System Dump: Produces a complete logical dump of the entire Resource Registry state as a closed seven-entry ZIP archive (
Content-Disposition: attachment; filename="resource-registry-dump.zip"), independently of the caller’s token Context:manifest.json,RegistryMetadata, every registered Type schema, every Context (live and cemetery alike), every Query Template, and every Resource and IsRelatedTo instance, each with full metadata and embedded Context membership. Facet and ConsistsOf instances are not dumped separately — they are embedded within the representation of their owning Resource instance, exactly as when reading a Resource instance “as-a-whole”. Serialization is all-or-nothing: any collection or row serialization failure aborts the download instead of producing a successful incomplete archive. Every entry can be read withinformation-system-modelalone:manifest.json(aDumpManifest) describes the archive —formatVersionandcreatedAt— whileregistry-metadata.json(aRegistryMetadata) describes the registry the information comes from —models, every model by name (information-system-model, the domain model, and the runtime model holding the types created through REST, markedruntime: true), each with itsversionfrom the classpath, itstypes({ typeName: version }) and itsrevisionCount, next to the globalrevisionCount.System Restore: Ingests the exact seven-entry ZIP archive produced by
System Dumpand recreates the entire Resource Registry state in strict topological order: Types, Contexts, Query Templates, Resource instances, then IsRelatedTo instances, and finallyRegistryMetadata, kept as dumped except its globalrevisionCount, which stays the target’s. Missing, duplicate, unexpected, malformed, incompatible, or referentially invalid archive content is rejected with400 Bad Requestbefore any write — incompatible meaning an unsupportedformatVersion, or aninformation-system-modelversion inregistry-metadata.jsonnewer than the target’s; every Resource and IsRelatedTo instance must declare at least one valid Context membership. Referentially invalid means that a reference does not resolve inside the archive (a Contextparent, without cycles, or an IsRelatedTo endpoint); preflight does not verify that an IsRelatedTo instance is only in Contexts where both its Resource instances are; such an inconsistency fails during the restore, and neither Resource is added to a Context to make it hold. A restore reproduces the dumped state exactly: nothing is derived again, and no item is modified by being restored. The content of the archive is not validated again against the constraints a write is checked for (mandatory properties,minandmaxbounds, name rules): what the dumped registry held comes back as it was. Every original UUID and every originalmetadataobject (creator, creation/last-update timestamps) is preserved verbatim. Every instance comes back in exactly the Contexts the archive records for it. This holds for the ConsistsOf and Facet instances embedded in a Resource too: each carries its owncontexts, which is restored as it is and never recomputed from the Resource through the propagation constraints, so a Facet that was in fewer Contexts than its Resource comes back in those Contexts only. An archive in which an embedded ConsistsOf or Facet instance carries nocontexts, or in which a ConsistsOf is in a Context where its Resource or its Facet is not, is rejected with400 Bad Requestbefore any write. Every Context comes back as dumped, with itsstate,effectiveState,path,previousPaths, History andmetadata; restoring a Context adds no History event. A Context whosestateisdeletedis re-created in the cemetery: it has noparent, itspathrecords where it was, and it is not a Root. An archive is rejected with400 Bad Requestwhen a Context lacksstate,effectiveStateorpath, when a cemetery Context declares aparentor is declared as one, when more than one live Context has noparent, or when an instance declares a membership in a cemetery Context. Requires the target system to be empty (no Context, Query Template, Resource instance, or IsRelatedTo instance may already exist, and no Type may extend Resource, Facet, IsRelatedTo, ConsistsOf, orProperty) — the state immediately after a service startup against an empty database. This is a hard precondition with no override: restoring into an already-populated system is rejected outright (409 Conflict), never attempted as a merge. The archive is validated before the target is inspected: an invalid archive returns400 Bad Requestalso when the target is not empty. Archive preflight completes before the first write, but the subsequent restore is not one global transaction: an unexpected persistence failure can leave a partially populated target, which must be recreated before retrying.
High-Impact Topological Operations Summary¶
To consolidate the reader’s mental model before proceeding to Query Templates, the API provides several powerful mechanisms that can drastically alter the graph structure across multiple boundaries. Because of their significant high-impact nature and potential for massive avalanche consequences, it is vital to fully understand their blast radius. To ensure operational comprehension and safety, the following table summarizes these high-impact structural operations and their typical safe use cases:
| Operation Name | Method, Path & Parameters | Blast Radius | Dry-run? | Typical Safe Use |
|—|—|—|:—:|—|
| Single Context Update | PUT /instances/{type}/{instance-uuid} | Current Context. Replaces local topology and overwrites properties globally. | ❌ | Forking a shared element (Local Copy-on-Write) or updating a field globally. |
| Subtree Synchronization | PUT /instances/{type}/{instance-uuid}?sync=existing | Shared Subtree. Descendant Contexts where the instance is already explicitly shared. | ❌ | Safe topological alignment across the hierarchy without forcing inclusion in new Contexts. |
| Hierarchical Distribution | PUT /instances/{type}/{instance-uuid}?sync=tree | Current Context + Entire descendant subtree. | ❌ | Forced blanket replication of a mandatory baseline configuration for all child tenants. |
| Synchronization of One Context | PUT /instances/{type}/{instance-uuid}?sync={context-uuid} | Current Context + the named Context. | ❌ | Aligning one Context to its parent, e.g. bringing the state of a service back to active there. |
| Surgical Add to Context | PUT /instances/{type}/{instance-uuid}/contexts/{new-context-uuid}?propagationMode=surgical | Target Context (Targeted instance only). What the targeted instance brings with it depends on its type: see surgical, case by case. | ✅ | Manual topology repair or targeted injection of a single node. (Restricted to IS-M / Infra-M / IS-Admin). |
| Shallow Add to Context | PUT /instances/{type}/{instance-uuid}/contexts/{new-context-uuid}?propagationMode=shallow | Target Context + Avalanche (stops at existing instances). | ✅ | Safe, standard sharing of an instance and its strictly missing dependencies. |
| Deep Add to Context | PUT /instances/{type}/{instance-uuid}/contexts/{new-context-uuid}?propagationMode=deep | Target Context + Full Transitive Closure Avalanche. | ✅ | Forced re-evaluation and importation of a deeply interconnected graph. |
| Cross-Boundary Add | PUT /instances/{type}/{instance-uuid}/contexts/{new-context-uuid}?bypassHierarchyCheck=true | Cross-subtree (breaks logical tree boundaries). | ✅ | Injecting harvested infrastructure data or migrating cross-tenant instances. (Restricted to IS-M / Infra-M / IS-Admin). |
| Hierarchical Add | PUT /instances/{type}/{instance-uuid}/contexts/{new-context-uuid}?hierarchical=true | Target Context + Entire descendant subtree. | ✅ | Forced blanket propagation of an external instance into a specific target subtree. (Restricted to IS-M / Infra-M / IS-Admin). |
| Surgical Removal | DELETE /instances/{type}/{instance-uuid}?propagationMode=surgical | Current Context (Targeted instance only). Stops Remove-Propagation. | ✅ | Emergency “undo” facility to eliminate a relation without collateral resource damage. |
| Standard Removal | DELETE /instances/{type}/{instance-uuid}?propagationMode=shallow | Current Context + Garbage Collector Avalanche (for orphans). | ✅ | Standard removal. The instance dies physically only if removed from its final Context. |
| Hierarchical Removal | DELETE /instances/{type}/{instance-uuid}/contexts/{context-uuid}?hierarchical=true | Named Context + Entire descendant subtree (every Context of the tree if the Context is a Root). | ✅ | Decommissioning of a corrupted or obsolete instance from a whole subtree. (Restricted to IS-M / Infra-M / IS-Admin). |
| Cross-Boundary Removal | DELETE /instances/{type}/{instance-uuid}/contexts/{context-uuid}?bypassHierarchyCheck=true | Cross-subtree (a Context outside the token subtree, also under another Root). | ✅ | Undoing a Cross-Boundary Add, or removing an instance from another tree. (Restricted to IS-M / Infra-M / IS-Admin). |
(Note: Whole-system maintenance remains under /admin; the privileged variants of Add to Context and Remove from Context share the canonical membership endpoint and are gated by role-specific query parameters.)
Statistics API — base path /statistics¶
Aggregate figures on the whole registry, public, for the landing page of the service and the one of the IS GUI shown before the login. Only numbers appear: never a Context path or name, nor an instance UUID or content. Type names do appear, as the model documentation already publishes them. Every figure is computed on the IS model alone; the registry does not know the domain model.
Authorization & Token Selection¶
| Action | HTTP | Path | Query Parameters | Caller |
|——–|——|——|——————|——–|
| Read Statistics | GET | /statistics | — | Anyone: no token is needed, and a token sent is not read |
HTTP Contract¶
| Action | Additional Request Headers | Response Headers | Success HTTP Code | Error HTTP Code |
|——–|—————————-|——————|——————-|—————–|
| Read Statistics | Accept | Content-Type, Cache-Control (public, max-age=300), X-Warning | 200 OK | — |
A query parameter is ignored, with X-Warning.
Operational Notes¶
Groups and refresh. The document holds five groups:
contexts,typesandqueryTemplates, refreshed every 30 minutes;instancesandconnectivity, which scan every instance, refreshed every 6 hours in one pass. Each group carriescomputedAt, the time it was computed.Never waiting. Each instance of the service computes the groups in the background and returns the last result: a request never touches the database nor waits for a computation, and the statistics never delay the startup of the service. Until its first computation ends a group is present with
computedAtnull and no other field; a computation that fails is retried a minute later, and the group keeps its previous result meanwhile. Two instances of the service compute their figures independently: they can differ by what changed between their computations.Depth. Contexts are counted by depth in the tree,
1being a Root. In D4Science depth 2 is a VO and depth 3 a VRE; the pages showing the figures use those names.
| Group | Field | Meaning |
|—|—|—|
| contexts | total | Contexts, the deleted ones included |
| | byState | Contexts per state: created, active, suspended, deleted (the cemetery) |
| | byDepth | Live Contexts per depth |
| | maxDepth | The depth of the deepest live Context |
| | childrenPerContext | For each depth, average and max number of live children of a Context at that depth |
| | createdLast12Months | Contexts created in the last 12 months, the deleted ones included |
| types | total | Types of the five base types |
| | byBaseType | For each of Resource, Facet, IsRelatedTo, ConsistsOf, Property: total, abstract, concrete |
| | byModel | The types each model declares, keyed by the model name RegistryMetadata records; a model also declares types outside the five base types |
| | evolved | Types with more than one version in their changelog |
| queryTemplates | total | Query Templates |
| | parametric, parameterless | With at least one templateVariables entry, and without |
| | projection, instances | Whose template contains _emit, and the others, which return whole instances |
| instances | byBaseType | Instances of Resource, Facet, IsRelatedTo, ConsistsOf |
| | topResourceTypes | The ten Resource types with the most instances: type, count |
| | facetsPerResource | average number of Facet instances of a Resource instance |
| | resourcesPerContext | For each depth, median and max number of Resource instances in a live Context at that depth |
| | contextsWithoutInstances | Live Contexts holding no instance |
| | lastUpdateTime | The most recent lastUpdateTime of an instance (ISO 8601) |
| | updatedLast24Hours, updatedLast7Days | Instances whose lastUpdateTime falls in that window |
| | notUpdatedForAYear | Instances whose lastUpdateTime is more than a year old |
| connectivity | isRelatedToPerResource | average, median and max number of IsRelatedTo instances of a Resource instance, in either direction |
| | resourcesWithoutIsRelatedTo | Percentage of Resource instances with no IsRelatedTo instance |
| | contextsPerResource | average number of Contexts a Resource instance belongs to |