Resource Registry — API Management (Contexts & Types)¶
Context Management — base path /contexts¶
Authorization & Token Selection¶
| Action | HTTP | Path | Query Parameters | IS-M / Infra-M | IS-Admin / Ctx-M | IS-Editor | IS-Contrib | IS-Member |
|——–|——|——|——————|:————–:|:—————-:|:———:|:———-:|:———:|
| List | GET | /contexts | limit, offset, lifecycle, metadataPolicy | ✅ | ✅ | ✅ | ✅ | ✅ |
| Execute JSON Query | QUERY | /contexts | limit, offset, lifecycle, metadataPolicy | ✅ | ✅ | ✅ | ✅ | ✅ |
| Read | GET | /contexts/{context-uuid} | depth, metadataPolicy | ✅ | ✅ | ✅ | ✅ | ✅ |
| Read Current | GET | /contexts/@current | depth, metadataPolicy | ✅ | ✅ | ✅ | ✅ | ✅ |
| Create | PUT | /contexts/{context-uuid} | metadataPolicy | ✅ | ⚠️ | ❌ | ❌ | ❌ |
| Tracked Update | PATCH | /contexts/{context-uuid} | metadataPolicy | ✅ | ⚠️ | ❌ | ❌ | ❌ |
| Read History | GET | /contexts/{context-uuid}/history | None | ✅ | ✅ | ❌ | ❌ | ❌ |
| Delete | DELETE | /contexts/{context-uuid} | None | ✅ | ⚠️ | ❌ | ❌ | ❌ |
Token Scope Rule:
| Operation Group | Token must be issued for |
|—————–|————————–|
| List, Execute JSON Query | No specific target Context is required; authorization is evaluated from the token role |
| Read, Read History | The Context being read itself (self). Administrative roles (IS-M, Infra-M, IS-Admin, Ctx-M) may alternatively present a token for any ancestor of the target Context, at any depth up the chain — this deliberately mirrors what depth already discloses from that same ancestor, so it adds no new exposure. Non-administrative roles never get this extension; for them the token must match the Context being read exactly. (Contrast with Create/Tracked Update/Delete below, which stay strictly limited to the immediate parent — a deliberate one-hop governance boundary for write operations that this read-side extension does not relax.) For Read History, this rule combines with the stricter Level-1 role gate (IS-M/Infra-M/IS-Admin/Ctx-M only — non-administrative roles cannot call it at all). |
| Read Current | The current token Context (token-bound endpoint semantics) |
| Create, Tracked Update, Delete | Parent Context of the target Context. (Exception: operations on a Root Context require a token issued for the Root Context itself) |
HTTP Contract¶
| Action | Additional Request Headers | Response Headers | Success HTTP Code | Error HTTP Code |
|——–|—————————-|——————|——————-|—————–|
| List | Accept | Content-Type, Link, X-Warning | 200 OK | 403 Forbidden |
| Execute JSON Query | Content-Type, Accept | Content-Type, Link, X-Warning | 200 OK | 400 Bad Request, 403 Forbidden |
| 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 |
| Read Current | Accept | Content-Type, Link, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 403 Forbidden, 404 Not Found |
| Create | Content-Type, Accept | Content-Type, Link, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 201 Created / 200 OK | 400 Bad Request, 403 Forbidden, 409 Conflict |
| Tracked Update | Content-Type: application/merge-patch+json, Accept | Content-Type, Link, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found, 409 Conflict |
| Read History | Accept | Content-Type, Link, X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found |
| Delete | None | X-Warning, conditional X-Result-Scope / X-Resolved-Context-Path | 204 No Content | 400 Bad Request, 403 Forbidden, 404 Not Found, 409 Conflict |
Operational Notes¶
Token path resolution: Every operation that derives an operational Context from the caller’s token first matches the token path against current
pathvalues and then, only when no current path matches, againstpreviousPaths. A fallback match has the same authorization meaning as a direct match and emitsX-Result-Scope: previous-pathplusX-Resolved-Context-Pathcontaining the current path. A direct match emits neither header. This shared behavior applies to Context reads and parent-scope mutations as well as instance operations.Read:
GET /contexts/{context-uuid}resolves a Context explicitly by UUID. The distinction between403and404is intentional and operationally significant:404 Not Found: no Context with the specified UUID exists — neither among live contexts nor in the cemetery.403 Forbidden: a Context with the specified UUID exists but is inaccessible to the caller. This occurs when the Context is in the DELETED state (cemetery) and the caller does not hold a manager role (IS-M/Infra-M), or when the Context exists among live contexts but the caller’s token is neither for that exact Context nor — for administrative roles only — for one of its ancestors (see the Token Scope Rule above).
Read Current:
GET /contexts/@currentapplies the same403vs404distinction asRead, but with a key difference: the target Context is not specified explicitly by the caller — it is resolved implicitly from the authorization token itself.404 Not Found: the token’s path cannot be resolved to any known Context — neither among live contexts nor in the cemetery. The known root causes are:IAM / IS bootstrap race: the IAM has registered a Context path and issued a token for it, but the corresponding Context record has not yet been created in the IS (or the creation failed). This is inherently transient: in a correctly sequenced deployment the IS Context is provisioned before the IAM path is activated. If this 404 appears in production it signals an integration error.
Token carries an unknown path: the path embedded in the token matches neither a current
pathnor any retainedpreviousPathsentry.
403 Forbidden: the token’s path resolves to a Context in the DELETED state (cemetery) and the caller does not hold a manager role. This is inherently a transient edge case — it can only arise in the window between Context deletion and the expiration or IAM-side revocation of the caller’s outstanding token. In a correctly integrated deployment, token revocation is triggered on Context deletion, making this state short-lived.
IS-Admin / Ctx-M permissions: For
Create,Tracked Update, andDelete, the token must be of the parent Context; IS-Admin / Ctx-M receives filtered metadata.The Root Context Bootstrap Exception: The authorization rule dictates that creating a Context requires a token for its parent. This creates a logical paradox for a Root Context (which has
parent: null). To resolve this without introducing insecure anti-patterns or requiring a token without a resource, the API permits anIS-M / Infra-Mto create a Root Context using a token explicitly issued for that exact Root Context being created.Creation via
PUTvsPOST: The API usesPUTinstead ofPOSTfor Context creation because the target Context UUID must be explicitly provided in the URL path by the client (e.g.,/contexts/{context-uuid}). Accepting an internal UUID exclusively in the body of aPOSTrequest to the base collection endpoint would be an architectural anti-pattern. Note that the UUID must also be present in the JSON body representation; the server performs a strict double-check between the URL path and the body representation to ensure consistency.PUT /contexts/{context-uuid}semantics (idempotent creation):PUTis strictly for Context creation. It requires definingid,name, andparent. Thestatefield is system-managed upon creation (forced toCREATED); suppliedstateandpreviousPathsfields are ignored and reported throughX-Warning. Historical paths can be introduced only through authenticatedPATCH. To strictly adhere to HTTPPUTidempotency, sending the exact same creation payload multiple times will return201 Createdthe first time and200 OK(no-op) on subsequent identical requests. However, if a client attempts to execute aPUTon an existing Context with a payload that is incongruent with the existing representation, the system will reject it with409 Conflict. Creating a Context whose current path matches another Context’s retained previous path removes that retained value in the same transaction and records the collision in the affected Context’s History. All legitimate state modifications must be performed exclusively via theTracked Update(PATCH) endpoint.PATCH /contexts/{context-uuid}semantics (Tracked Update): Uses theapplication/merge-patch+jsonmedia type (RFC 7396) to partially update the Context. The body must be a JSON object. It processes changes only tostate,name,parent, andpreviousPaths; every other top-level field is ignored and reported through anX-Warningheader.state, when present, must be the stringactiveorsuspended(createdanddeletedare system-managed).name, when present, must be a valid non-null Context name.parent, when present, must be either JSON null (move to the Root level) or an object containing a textual UUIDid; the resulting hierarchy must remain acyclic.previousPaths, when present, must be null or an array of absolute path strings and replaces the complete retained ordered set; null and[]clear it, duplicate values are removed, and administrators may add historical paths for remediation. When one patch also renames or reparents the Context, the explicit replacement runs first and the outgoing current path is then appended. Every descendant whose path changes receives its own outgoing path atomically. The backend writes history and modification metadata only for effective tracked-field changes, so an empty patch, a same-value patch, or a patch containing only ignored fields is a successful200 OKno-op.Reparenting and Renaming Constraints: Changing the
parentContext or thenameof a Context shifts the structural addressing and IAM resolution of an entire hierarchical branch. To ensure security consistency and prevent accidental “live exposure”, reparenting or renaming is strictly allowed only when the Context’s localstateis non-ACTIVE(e.g.,SUSPENDEDorCREATED). Attempting to move or rename a Context while its localstateisACTIVEwill result in a409 Conflict.Architectural Rationale: Why check the local
stateinstead of theeffectiveState? Consider a child Context whose local state isACTIVE, but its parent isSUSPENDED. Due to inheritance, the child’seffectiveStateis naturallySUSPENDED. If the system permitted the move based solely on theeffectiveState, an administrator could move this child under a new,ACTIVEparent. Because its local state was alreadyACTIVE, the child Context would instantly “wake up” and become fully operational immediately upon transfer, potentially exposing the entire subtree to live network traffic without warning. Forcing the local state to be manually set toSUSPENDEDbefore the move guarantees that the Context remains safely offline during and after the migration, requiring a deliberate secondary action to reactivate it.
Read History:
GET /contexts/{context-uuid}/historyis a pure read-only endpoint that returns a flat JSON array ofEventobjects (sorted in reverse-chronological order, newest first). The path identifier must be a valid UUID; malformed values return400 Bad Request. Query parameters are unsupported and ignored with anX-Warningheader; in particular,lifecyclecannot select cemetery routing. Lifecycle visibility is derived exclusively from role:IS-M/Infra-Mcan read live or deleted Context history, whileIS-Admin/Ctx-Mcan read live Context history only. This provides a complete audit trail of the Context’s lifecycle. EachEventexplicitly captures the transition details:who: The principal who triggered the change.what: The transition value (e.g.,CREATED -> ACTIVE).where: The specific field modified (e.g.,stateorname).when: The timestamp of the occurrence.how: The triggering mechanism or API method (e.g.,PATCH).
Changes to
previousPathsare recorded independently: direct and cascaded path changes add the outgoing path, explicit replacements record each addition and removal, and creation-time path reuse records the reclaimed path and new Context UUID. These events usewhere: previousPathsand do not replace the separatename,parent, orpathevents.Crucial Auditing Feature: This history actively records changes to the
effectiveState. If an ancestor Context is suspended, the backend cascades the suspension down the tree, writing anEventinto the history of every descendant Context (e.g.,where: effectiveState,how: Cascade from parent /contexts/{parent-uuid}). This guarantees that administrators can instantly understand why a specific Context went offline without manually traversing the parent hierarchy.Context Deletion (The Cemetery):
DELETEpermanently removes the Context from active listings and transitions it to aDELETEDstate in the historical “cemetery” (from which it cannot be resurrected, though a new Context with the same path but a different UUID can be created). The path identifier must be a valid UUID; malformed values return400 Bad Request. The target must exist in the live topology, so deleting an unknown or already deleted UUID returns404 Not Found. The operation requires an administrative token for the target’s current immediate parent, or for the target itself when deleting a Root Context. Unsupported query parameters are ignored and reported throughX-Warning. Deletion fails with409 Conflictif the Context still contains any child Contexts or graph instances. Collection reads (GET /contexts,QUERY /contexts) support explicit cemetery visibility via thelifecycleparameter:live(default),deleted,all. Access to cemetery-inclusive modes (deleted,all) is restricted toIS-M / Infra-M; for all other roles, requesting these modes returns403 Forbidden.Execute JSON Query (QBE):
QUERY /contextsexposes the powerful JSON Query-By-Example engine specifically for the Contexts collection. Instead of polluting theGET /contextsendpoint with hardcoded query parameters, clients can submit a JSON payload matching the desired Context state. This allows advanced filtering across the entire Context representation (e.g., querying{"effectiveState": "suspended"}to find all offline Contexts, or searching bymetadata.createdBy). The endpoint shares the exact same semantics, operators, and_emitprojection capabilities as the instance query engine.Lifecycle visibility contract:
lifecycle=livereturns only active-topology contexts (default);lifecycle=deletedreturns only cemetery contexts;lifecycle=allreturns the union. The server applies role checks before query evaluation.
Non-
ACTIVEContext behavior: When a Context is non-ACTIVE(e.g.,CREATEDorSUSPENDED), performing instance operations within it is restricted based on the caller’s role.IS-M / Infra-Mcan operate freely regardless of the Context state. AnIS-Admin / Ctx-Mcan perform instance operations inside a non-ACTIVEContext provided their credentials explicitly address that specific Context. This intentional design allows an administrator to safely “prepare” a newlyCREATEDContext by pre-populating instances without external interference, before finally flipping the state toACTIVE. Roles with lesser administrative scope (IS-Editor,IS-Contrib, andIS-Member) are strictly blocked from performing any instance operations (both read and write) within non-ACTIVEContexts and will receive a403 Forbidden.
Context Lifecycle State Machine¶
A Context transitions through a strict lifecycle governed by the API operations. The state machine ensures that environments can be safely prepared (CREATED), paused (SUSPENDED), actively used (ACTIVE), and securely destroyed (DELETED).
Architectural Metaphor (Founder, CEO and Division Manager): To understand the authorization split between parent and child Contexts during lifecycle operations, consider a corporate metaphor.
The Root Context Bootstrap: An entrepreneur has a business idea. They found a company, and by the physical act of founding it, they become its CEO. This perfectly explains the Bootstrap Exception: an
IS-Mcreating the Root Context uses a token for that exact new boundary.The Child Contexts: The CEO (the admin of the Root Context) decides to create a new company division (
PUT /contexts/child). The CEO creates it (which starts inCREATED), eventually activates it (ACTIVE), temporarily suspends it (SUSPENDED), or permanently closes it (DELETED). However, the CEO assigns a specific manager (the admin of the child Context) to run the division. This local manager is the one who actually populates the division with employees and rules (creating/updating instances inside theCREATEDContext). Once the local manager has prepared everything, the CEO officially declares the division open (PATCH /contexts/childtoACTIVE). This perfectly illustrates why creating/activating a Context requires parent-level authority, while populating it requires local authority.
---
config:
theme: neutral
flowchart:
edgeLabelBackground: "#ffffff"
---
stateDiagram-v2
[*] --> CREATED : Create (PUT)
CREATED --> ACTIVE : Tracked Update (PATCH)
ACTIVE --> SUSPENDED : Tracked Update (PATCH)
SUSPENDED --> ACTIVE : Tracked Update (PATCH)
CREATED --> DELETED : Delete (DELETE)
ACTIVE --> DELETED : Delete (DELETE)
SUSPENDED --> DELETED : Delete (DELETE)
DELETED --> [*] : Terminal State (Cemetery)
note right of DELETED
Deletion is permanently irreversible.
Requires empty Context
(0 instances, 0 children).
end note
State Transition Matrix
All transitions require the caller to possess a valid token for the parent Context and hold an authorized managerial role (IS-M / Infra-M or IS-Admin / Ctx-M).
| Current State | API Operation | Next State | System Behavior & Validation |
|—————|—————|————|——————————|
| (Does not exist) | PUT | CREATED | The system provisions the Context. The state is forced to CREATED. |
| CREATED | PATCH | ACTIVE | Opens the Context to operational users (IS-Editor, IS-Contrib, IS-Member). |
| ACTIVE | PATCH | SUSPENDED | Temporarily blocks IS-Editor, IS-Contrib and IS-Member from performing operations. Useful for maintenance or administrative locks. |
| SUSPENDED | PATCH | ACTIVE | Restores normal operations for all roles. |
| Any non-DELETED | DELETE | DELETED | Moves the Context to the historical cemetery. Strict validation: the Context MUST NOT contain any child Contexts or instances, otherwise the request is rejected with 409 Conflict. |
Immutability of the Cemetery: Once a Context reaches the
DELETEDstate, it cannot be resurrected or updated viaPATCH. However, because it physically vacates the active topology, an administrator can create a brand new Context using the samenameandparent(resulting in the same hierarchical path), but it will possess a completely new, unique UUID.
Inherited Operational State (effectiveState)¶
To support maintenance operations at scale without altering the physical state of thousands of sub-environments, the system strictly separates local configuration (state) from operational evaluation (effectiveState). The effectiveState is a read-only field that is persistently stored in the database (and cached in Redis); it is never computed on the fly at read time. The system recomputes and atomically cascades it to all descendant Contexts whenever the Context’s own state or any ancestor’s state changes.
State Evaluation Matrix:
| Parent’s effectiveState | Context’s Local state | Resulting effectiveState |
|—————————|————————-|—————————-|
| (None / Root Context) | (Any state) | = Local state |
| (Any state) | CREATED | CREATED |
| (Any state) | DELETED | DELETED |
| CREATED | SUSPENDED or ACTIVE | SUSPENDED (inherited) |
| SUSPENDED | SUSPENDED or ACTIVE | SUSPENDED (inherited) |
| ACTIVE | SUSPENDED | SUSPENDED |
| ACTIVE | ACTIVE | ACTIVE |
Rationale for
CREATEDinheritance: If a child Context has been locally advanced toACTIVEorSUSPENDEDby a local administrator, it is no longer a blank slate. Therefore, its parent’sCREATEDstate acts purely as an operational lock, yielding an effectiveSUSPENDEDstate to freeze operations without reverting or obscuring the child’s explicitly configured local status.
Architectural Rationale (Offline Restructuring): There are no restrictions on Context Lifecycle operations (
PUT,PATCH,DELETEfor Contexts) based on the parent’s state. AnIS-Adminhas full authority to build and configure an entire nested topology while an ancestor Context is still in aCREATEDorSUSPENDEDstate. This grants administrators the power to perform massive Offline Restructuring: they can prepare an entire tree of environments in the background and, when everything is perfect, simply switch the ancestor Context toACTIVE. The system relies entirely on theeffectiveStatealgorithm to ensure that operational users cannot access these environments until the entire ascendance chain is properly activated.
This architectural design allows an administrator to securely lock down an entire branch (e.g., a VO and its 50 VREs) via a single state update on the parent node, without destroying the historical configuration state of the children. When an ancestor is placed in a SUSPENDED or CREATED state, the system cascades the change to all descendants in the same database transaction: every descendant’s persisted effectiveState is updated to SUSPENDED if its local state was ACTIVE, ensuring that a stale cached or stored value can never bypass the lock.
The Universal effectiveState Rule for Operations:
Throughout this documentation and the API authorization rules, any restriction mentioning that operations are blocked in non-ACTIVE Contexts always refers strictly to the effectiveState. The following matrix illustrates whether a role is disabled by the Context’s state lock when attempting an operation on a graph instance (such as creating or reading a Resource instance). The specific privileges (e.g., who can write vs read) remain strictly governed by the API reference tables; this matrix solely defines whether the Context’s effectiveState acts as an absolute barrier (Disabled, yielding a 403 Forbidden) or if it allows the role to proceed (Enabled). This evaluation does NOT apply to Context Lifecycle operations (like updating a Context via PATCH).
| effectiveState | IS-M / Infra-M | IS-Admin / Ctx-M | IS-Editor | IS-Contrib | IS-Member |
|——————|—————-|——————|———–|————|———–|
| CREATED | ✅ Enabled | ✅ Enabled | ❌ Disabled (403) | ❌ Disabled (403) | ❌ Disabled (403) |
| ACTIVE | ✅ Enabled | ✅ Enabled | ✅ Enabled | ✅ Enabled | ✅ Enabled |
| SUSPENDED | ✅ Enabled | ✅ Enabled | ❌ Disabled (403) | ❌ Disabled (403) | ❌ Disabled (403) |
| DELETED | ❌ Disabled (403) | ❌ Disabled (403) | ❌ Disabled (403) | ❌ Disabled (403) | ❌ Disabled (403) |
(Note: The effectiveState barrier applies equally to both read and write operations for roles IS-Editor, IS-Contrib, and IS-Member. IS-M and IS-Admin / Ctx-M are not restricted on reads or writes by Context state, except in DELETED Contexts).
Client Guidance: The
effectiveStateis exposed to allow API clients to determine in advance whether their instance operations (whether executing a read query or a mutation) will be accepted (e.g., to disable buttons in a GUI), or to understand the reason for a rejection a posteriori. Any attempt to operate when the matrix evaluates toDisabledwill be rejected by the system. (Note onDELETEDcontexts: While all operations on graph instances inside aDELETEDContext are universally blocked for everyone, global administrators can still inspect deleted Contexts through Context collection/read APIs using thelifecyclevisibility model and viaGET /contexts/{context-uuid}/history.)
Type Management — base path /types¶
Authorization & Token Selection¶
| Action | HTTP | Path | Query Parameters | IS-M / Infra-M | IS-Admin / Ctx-M | IS-Editor | IS-Contrib | IS-Member |
|——–|——|——|——————|:————–:|:—————-:|:———:|:———-:|:———:|
| Execute JSON Query | QUERY | /types | limit, offset, depth, metadataPolicy | ✅ | ✅ | ✅ | ✅ | ✅ |
| Create | PUT | /types/{type-name} | None | ✅ | ❌ | ❌ | ❌ | ❌ |
| Read | GET | /types/{type-name} | depth, metadataPolicy | ✅ | ✅ | ✅ | ✅ | ✅ |
| Delete | DELETE | /types/{type-name} | None | ✅ | ❌ | ❌ | ❌ | ❌ |
Token Scope Rule:
| Operation Group | Token must be issued for |
|—————-|—————————|
| Execute JSON Query| No specific target Context is required; authorization is evaluated from the token role |
| Create, Delete | No specific target Context is required; authorization is evaluated from the token role (requires IS-M / Infra-M) |
| Read | No specific target Context is required; authorization is evaluated from the token role |
HTTP Contract¶
| Action | Additional Request Headers | Response Headers | Success HTTP Code | Error HTTP Code |
|——–|—————————-|——————|——————-|—————–|
| Execute JSON Query | Content-Type, Accept | Content-Type, Link, X-Warning | 200 OK | 400 Bad Request, 403 Forbidden |
| Create | Content-Type, Accept | Content-Type, X-Warning | 201 Created / 200 OK | 400 Bad Request, 403 Forbidden, 409 Conflict |
| Read | Accept | Content-Type, Link, X-Warning | 200 OK | 403 Forbidden, 404 Not Found |
| Delete | None | X-Warning | 204 No Content | 403 Forbidden, 404 Not Found, 409 Conflict |
Operational Notes¶
Creation via
PUTvsPOST: The API usesPUTinstead ofPOSTfor Type creation because the Type identifier (type-name) must be explicitly provided in the URL path by the client (e.g.,/types/{type-name}). Accepting an identifier exclusively in the body of aPOSTrequest to the base collection endpoint would be an architectural anti-pattern. Note that thenamemust also be present in the JSON body representation; the server performs a strict double-check between the URL path and the body representation to ensure consistency.Internal
idownership during creation: Theidfield inside the Type JSON represents its internal global UUID. The REST endpoint URL strictly uses the readabletype-name, never the UUID. If a client includes anidfield in the creation payload, the backend attempts to honor it and store the Type with that specific UUID. Reuse by another Type definition in the same schema category produces409 Conflict; reuse by an element or Type definition in a different category produces400 Bad Request, following the registry-wide UUID ownership rule. If the client omits theid, the backend automatically generates a new random UUID for the Type.PUT /types/{type-name}semantics (idempotent creation):PUTconsumes onlyapplication/jsonand is accepted for the creation of a new Type with the provided identifier. The body must be a complete Type definition whosenameexactly matches the path. To strictly adhere to HTTPPUTidempotency, if a client submits a definition for an existing Type, the server compares the complete structural representation — including the discriminator, changelog, properties and all their constraints, Resource relationship declarations, Relation endpoints, and extension fields — while excluding only the identity/audit fieldsidandmetadata. An identical definition returns200 OK(no-op); any structural difference returns409 Conflict, because online Type updates are forbidden. A Type markedlockedis served read-only: any submission that would change it returns409 Conflict. A new definition also returns409 Conflictwhen it violates the current Type graph, including unresolved or final parents, unresolved referenced Types, inconsistent multiple inheritance, contradictory inherited cardinalities, or simultaneousabstract: trueandfinal: true. Malformed JSON, an invalid Type representation, or path/body name mismatch returns400 Bad Request. Both successful outcomes return the persisted Type representation and identify its canonical name-addressed URI throughContent-Location. A newly created Type advances the shared schema version before its Redis entry and C3 linearization are stored, so the derived entries are immediately readable at the published version and the schema projection worker is notified. (Contrast with Query Template definitions: while Query Templates fully support onlinePUTupdates, Types are structural graph contracts and strictly forbid them).Type Evolution & Versioning: Type update via REST is intentionally not exposed (Type changes are breaking). Type changes (e.g. making a field mandatory) can break running instances and dependent systems. Internally, the framework’s update logic inherently blocks Type modification if there are existing instances of that Type. To evolve a Type while keeping the same Type name, a framework administrator must perform an offline assessment to evaluate the impact and define a formal data migration plan before manually forcing the upgrade offline.
Absence of a standalone
Listendpoint: There is intentionally no standaloneListendpoint (e.g.,GET /types) for schema definitions. Clients are expected to discover available Types hierarchically by invoking theReadendpoint on any known Type and using thedepthparameter. For example, a client can retrieve the entire Resource schema tree by callingGET /types/Resource?depth=-1, or dynamically explore a specific sub-branch by callingGET /types/Service?depth=-1or any other known subtype.Type read semantics:
GET /types/{type-name}accepts only the exact case-sensitive Type name and always returns a JSON array with the requested Type first.depth=0returns only that Type, a positivedepth=Nincludes descendants through exactly N inheritance levels, anddepth=-1includes all descendants; invalid values fall back to0and produceX-Warning. Multiple-inheritance paths do not duplicate a descendant.metadataPolicy=none|root|allcontrols metadata across the flat result (rootandallare equivalent for this endpoint, as all returned types are peer definitions; onlynoneomits it), and non-global roles receive masked metadata identities. Successful reads expose the canonical name-addressed URI throughContent-Locationand each direct parent throughLink: rel=supertype. Versioned positive and negative cache entries are retired by schema changes, and an incomplete cached descendant traversal falls back atomically to persistence rather than returning a partial subtree.Execute JSON Query (QBE):
QUERY /typesrequires a JSON object targeting one ofResourceSchema,FacetSchema,IsRelatedToSchema,ConsistsOfSchema, orPropertySchema; every other category is rejected with400 Bad Requestbefore database execution, even when its filters would match no rows. Thedepthparameter controls descendant expansion for plain-stringname,source, andtargetmatches:0is exact, a positive value includes descendants through that many levels, and-1(default) is unbounded. Full Type results honormetadataPolicyand redactmetadata.createdByandmetadata.lastUpdateByfor non-privileged roles; Relation Type definitions exposesourceandtargetas canonical Type-name strings. An_emitquery instead returns only its flat aliases while preserving each selected value’s native JSON type, ignores an explicitly suppliedmetadataPolicywithX-Warning, and still redacts aliases sourced from sensitive metadata fields. Pagination applies to both full and projected rows; invalid query parameters fall back according to the shared parameter rules and emitX-Warning.Type Deletion Constraints:
DELETE /types/{type-name}is a protected schema operation. Query parameters are unsupported, ignored, and reported throughX-Warning. The server MUST reject the request with409 Conflictwhen deleting the Type would leave the Type dictionary structurally inconsistent. A Type is deletable through the public REST API only when all the following conditions are true:it has no concrete instances;
it has no subtypes;
it is not referenced by any other Type definition;
it is not part of the Information System model itself (
locked).
Reverse-reference checks are evaluated by Type category:
Deleting a Resource Type is rejected if that Type is used as the source Resource Type of any ConsistsOf Type definition.
Deleting a Resource Type is rejected if that Type is used as the source Resource Type or target Resource Type of any IsRelatedTo Type definition.
Deleting a Resource Type is rejected if that Type is used as the target Resource Type in any Resource – IsRelatedTo –> Resource schema constraint declared by another Resource Type.
Deleting a Facet Type is rejected if that Type is used as the target Facet Type in any Resource – ConsistsOf –> Facet schema constraint.
Deleting an IsRelatedTo Type is rejected if that Type is used as the relation Type in any Resource – IsRelatedTo –> Resource schema constraint.
Deleting a ConsistsOf Type is rejected if that Type is used as the relation Type in any Resource – ConsistsOf –> Facet schema constraint.
Deleting a Property Type is rejected if another Type definition still uses it as a direct or collection-valued complex
propertyType.
In Resource Type definitions, the source Resource Type of a schema constraint is the Resource Type that owns the definition. Deleting that owning Resource Type does not leave its own constraints dangling, because the whole Type definition is being removed. The deletion is still rejected if the Resource Type has instances, has subtypes, is used by a ConsistsOf or IsRelatedTo Type definition, or is referenced by another Resource Type definition.