# Information System Model — Core Topology

## Contexts as Logical Partitions

Before diving into the specific types, it is crucial to understand how the Information System organizes data.

Imagine the entire Information System as a global, unbounded pool of interconnected nodes (the **Entity** instances) and directed arrows connecting them (the **Relation** instances). Together, they form the complete data topology managed by the infrastructure.

A Context is conceptually a logical partition or set. Imagine a Context as a **Venn diagram** drawn over this sea of nodes and directed arrows. It creates a filtered, isolated view of the infrastructure.

- A node (an **Entity** instance) can fall inside multiple Venn diagrams (belong to multiple Contexts).
- A directed arrow (a **Relation** instance) connecting two nodes might exist inside one Venn diagram (one Context), but be completely absent in another, even if both nodes are present in both diagrams.

This separation is entirely legal and strictly necessary in a federated research infrastructure, as it allows different communities to view and interact with the exact same **Entity** instances under completely different dependency topologies.

Contexts themselves can be organized hierarchically into a strict single-root tree structure. However, it is crucial to note that Contexts remain strictly separated and isolated by default. The hierarchy does not automatically merge data. Instead, it creates nested Venn diagrams that unlock powerful, perfectly legal operational capabilities: it allows the system to aggregate boundaries to form broader hierarchical views, and enables hierarchical modification operations (such as pushing updates down a specific subtree).

> **Note:** *While conceptually a Context acts as a boundary or a "set", it possesses its own structural metadata—such as a name and a state—which are managed and represented separately within the Information System to describe these logical boundaries and their hierarchies.*

While the model mandates a single-root tree, **it does not enforce a fixed number of hierarchical levels**. The system is intentionally designed to be generic enough to accommodate any organizational depth.

The model adopts the generic term Context because operational terminologies vary widely. For instance, what is commonly called a Virtual Research Environment (VRE) has numerous synonyms depending on the community (e.g., Collaboratory, Science Gateway, Virtual Organization, etc.), as thoroughly analyzed in the *Virtual Research Environment Collaborative Landscape Study* (Carusi & Reimer, 2010)[^carusi-2010].

As a concrete example of this flexibility, the **D4Science** infrastructure maps its organization onto a 3-level hierarchy:

1. **Root** (The infrastructure level)
2. ↳ **VO** (Virtual Organization - domain level)
3. &nbsp;&nbsp;&nbsp;↳ **VRE** (Virtual Research Environment - specific task/community level)

## The Core Graph Model

The logical components discussed in the previous section are formalized by the IS-Model as a directed graph. In terms of strict directed graph theory, the model maps its concepts as follows:

- The nodes (vertices) of the graph are formally modeled as **Entity** instances.
- The directed arrows (edges) connecting the nodes are formally modeled as **Relation** instances.

This graph-based foundation is a deliberate architectural choice. As noted by Angles and Gutierrez (2008)[^angles-2008], graph database models are applied in areas where *"information about data interconnectivity or topology is more important, or as important, as the data itself"*. In the Resource Registry ecosystem, the managed entities and the relations among them operate at the exact same level of importance. Introducing directed graphs as the core modeling tool provides unparalleled advantages for navigating and managing this highly interconnected topology.

### Visual Taxonomy

The universe of the Information System can be summarized in the following structural taxonomy:

- **Graph Instance Type** (instances possess a global ID and Context membership)
  - **Entity**
    - **Resource**
    - **Facet**
  - **Relation**
    - **IsRelatedTo**
    - **ConsistsOf**
- **Embedded Value Type** (nested data structures without independent topological identity)
  - **`Property`**
- **System Object** (administrative and organizational boundaries)
  - **Context**
  - **QueryTemplate**
  - **Type** schemas (also referred to as Type definitions or simply schemas)

### Graph Topologies

While the graph is abstractly composed of vertices and edges, the IS-Model enforces a strict structural taxonomy. Every concrete **Entity** instance and **Relation** instance must belong to a specific formal Type, which is a specialization of one of the four foundational core topologies.

#### Entities

Two categories of **Entity** types are defined:

1. **Resource**: **Entity** types representing a description of a "thing" to be managed (e.g., a Service, a Dataset, a Virtual Machine). As per the model's core design, a **Resource** type does not define custom data fields to describe its characteristics; instead, it is entirely described by a set of attached **Facet** types.
2. **Facet**: **Entity** types contributing to "build" a description of a **Resource**. Each **Facet** type captures a specific aspect or characterisation of its subject **Resource** (e.g., a network endpoint, a state, a licensing policy) and defines the schema for the custom data fields.
   > **Semantic Origin:** The term *Facet* derives directly from the dictionary definition. Merriam-Webster defines a facet as "any of the definable aspects that make up a subject (as of contemplation) or an object (as of consideration)". The Free Dictionary defines it as "One of numerous aspects, as of a subject".

#### Relations

A **Relation** type defines a specific semantic link between two **Entity** types. Because these semantic links are intrinsically asymmetric, every **Relation** type is modeled as strictly directed (with a source and a target) and is conventionally named using a verb.

Two foundational categories of **Relation** types are defined:

1. **IsRelatedTo**: **Relation** types dictating a connection from a source **Resource** to a target **Resource**. They are used to represent dependencies, compositions, or any generic link between two distinct managed concepts.
2. **ConsistsOf**: **Relation** types dictating a connection from a source **Resource** to a target **Facet**. They act as the structural ties used to attach characterizing **Facet** types to their owning **Resource** type.

> **Strict Topological Rules:**
>
> - **Directionality:** While every link is strictly directed from source to target to enforce its semantic meaning, it can always be navigated in both directions during traversal.
> - **Reflexive Relations:** A **Relation** instance can theoretically connect an **Entity** instance to itself, provided the schema types allow it. While this is structurally impossible for **ConsistsOf** instances (since their source and target are strictly forced to be on divergent polymorphic branches: **Resource** and **Facet**), it is perfectly valid for **IsRelatedTo** instances. A **Resource** instance is allowed to be the source of an **IsRelatedTo** instance pointing to itself.
> - **Universal Source:** As derived from the definitions above, the *source* of any link is always a **Resource**. A **Facet** can never be the source. Consequently:
>   - A **Facet** instance cannot be the source of a **Relation** instance pointing to a **Resource** instance.
>   - A **Facet** instance cannot be the source of a **Relation** instance pointing to another **Facet** instance (or to itself).
> - **Facet Ownership (Strict Single Attachment):** A single **Facet** is strictly owned by a single **Resource**. To enforce this mathematically, **every Facet instance has exactly one incoming ConsistsOf instance globally**. Attempting to attach a **Facet** instance via a second **ConsistsOf** instance results in a validation error (Facet Exclusivity violation). It cannot be attached to multiple different **Resources**, nor can it be attached via multiple parallel **ConsistsOf** instances to the same **Resource**. *(Note: In the REST API, a **Facet** can never be created as an independent top-level entity. It is created atomically with its owning **ConsistsOf** instance, either inside a **Resource** mutation payload or as the nested target of a standalone **ConsistsOf** mutation).*

### Architectural Topology: Infrastructure vs Descriptive

The overarching architecture of the Information System must reconcile three foundational concepts that might initially seem contradictory:

1. **Resource-Centric Design:** The infrastructure management revolves fundamentally around **Resource** instances (e.g., Services, Datasets, Nodes). They represent the core logical units.
2. **Facet-Based Resource Model:** The description of these **Resource** instances is entirely decentralized. A **Resource** instance acts as a container; its metadata, configuration, and state are strictly delegated to attached **Facet** instances.
3. **Graph Equivalency (Gutierrez):** As formalized in graph database theory, the relations interconnecting the data are as important as the data itself, if not more so.

The Information System embraces its nature as a true **Graph IS**. This means that despite the logical "subordination" of **Facet** instances to **Resource** instances (since a **Facet** instance solely exists to describe a **Resource** instance), all four base types (**Resource**, **Facet**, **IsRelatedTo**, **ConsistsOf** instances) are granted **absolute topological equality** within the graph database. There are no "second-class citizens". Every piece of information is an independent instance with a unique UUID and equal operational dignity.

To conceptualize this without creating semantic subordination (e.g., purist "macro" vs "micro" terms which incorrectly imply inequality), the graph is formally divided into two architectural topologies:

- **Infrastructure Topology** (**Resource** + **IsRelatedTo**): The topological structure mapping how the core operational entities (services, datasets, hosting nodes) interact to form the network or federation. It acts as the backbone of the system.
- **Descriptive Topology** (**Facet** + **ConsistsOf**): The topological structure that holds the semantic description, configuration, and state. It defines the rich identity and properties of the individual resources without polluting the infrastructure backbone.

> **Notice on Terminology:** To ensure absolute clarity across the Information System documentation and prevent confusion with generic IT and graph-theory concepts, a strict normative vocabulary is enforced (e.g., distinguishing between instances, projections, and manifestations, and regulating the use of topological verbs like "attached to" vs "linked to"). Readers are invited to consult the [Normative Terminology & Typographic Conventions](02-normative-terminology.md) before diving into the model mechanics, and to refer back to it whenever a structural or conceptual doubt arises.

#### Monolithic vs Modular Instances

A common question when approaching this model is: *Why are **Facet** instances modeled as independent graph instances attached via **ConsistsOf** instances, rather than just being complex nested property fields inside a monolithic **Resource** instance?*

The decision to make them full-fledged independent instances is the cornerstone of the multi-tenant sharing model:

1. **Shared Identity vs Contextual Variance:** Imagine a **Resource** instance (e.g., representing a specific service or dataset) shared across 10 Contexts. If it requires a variation in just one Context (e.g., a different access point), representing it as a single monolithic **Resource** instance would force the system to duplicate the entire **Resource** instance just to accommodate that single change. By modeling **Facet** instances as independent instances, the system achieves maximum reuse: the core **Resource** instance is shared, **Facet** instances are shared, but specific Contexts can branch off by simply attaching different **Facet** instances via dedicated **ConsistsOf** instances.
2. **Independent Addressability:** Instantiating **Facet** instances and **ConsistsOf** instances as independent graph elements endows them with an independent ID. This allows them to be directly addressed: a client does not need to download, modify, and re-upload an enormous monolithic **Resource** instance just to update a single state value; it can perform a surgical update directly on the specific **Facet** instance or **ConsistsOf** instance.
3. **System-of-Systems Extensibility:** A federated infrastructure integrates highly heterogeneous instances and operational procedures across different participating systems. Attempting to capture all this variation within strict, monolithic Object-Oriented class hierarchies guarantees brittle schemas that break on every update. By decentralizing property fields into independent **Facet** instances, publishers can dynamically attach new specifications to a **Resource** instance without coordinating a massive, system-wide schema migration. The semantics of a **Resource** instance are no longer statically locked in a class definition, but are dynamically defined by the collection of **Facet** instances attached to it at any given time. This modularity is essential for supporting the continuous evolution of a federated ecosystem.

#### Topological and Contextual Rules

The robust multi-tenant nature of the IS-Model is governed by strict rules regarding where instances can exist (their "Contexts").

In plain words, the operational rules critical for an integrator are:

1. **General Relation Constraint:** Any **Relation** instance (whether of type **IsRelatedTo** or **ConsistsOf**) can only exist in a Context if **both** the instances it connects are also present in that exact same Context. You cannot connect two **Entity** instances together in a Context if one of them is missing.
2. **Facet Dependency:** As a direct consequence of the above rule, a **Facet** instance cannot exist independently. It lives exclusively attached to a **Resource** instance via a **ConsistsOf** instance. Therefore, a **Facet** instance can only ever exist in a Context where its source **Resource** instance is already present.
3. **Resource Presence:** A **Resource** instance is considered present in a Context if and only if it possesses at least one **Facet** instance in that Context. *(Note on Surgical Operations: Because of this strict presence rule and schema validation, if a client attempts to surgically remove from a Context (or delete globally) a mandatory **Facet** instance (or its **ConsistsOf** instance) that would cause the parent **Resource** to violate its `min` cardinality constraints, the operation will be cleanly rejected with a `409 Conflict` (Schema Violation) rather than triggering an implicit deletion of the **Resource** instance. To remove the **Resource** instance from the Context, the client must explicitly invoke a `Remove from Current Context` operation on the **Resource** instance itself, which will cleanly drop it along with all its topological dependencies).*
4. **ConsistsOf Presence:** A **ConsistsOf** instance's presence in a Context is topologically identical to the presence of its target **Facet** instance. One cannot exist in a Context without the other.
5. **IsRelatedTo Presence:** An **IsRelatedTo** instance does not automatically exist in a Context simply because both its source and target **Resource** instances are present there. It must be explicitly created in or added to that Context, strictly bounded by the intersection rule above.

#### Visibility vs Presence

Because of the strict separation of Contexts, the physical *presence* of an instance in a Context governs its *visibility* to clients operating within that Context. The following matrix illustrates the standard read behavior when a client operating within Context `C2` queries an arbitrary instance `I` (e.g., a **Resource** instance):

| Topology of `I` | Standard Read (in `C2`) | Hierarchical Read (in `C2`) |
|-----------------|-------------------------|------------------------------------------------------|
| `I` is present in `C2` | Visible | Visible |
| `I` is present in `C1`, and `C2` is parent of `C1` | Hidden (Isolation) | Visible (Hierarchical expansion) |
| `I` is present in `C1`, but `C1` and `C2` are completely distinct | Hidden (Isolation) | Hidden (Isolation) |
| `I` does not exist globally | Absent | Absent |

*(Note: Hierarchical expansion is purely a read-time visibility override; it does not alter the instance's physical presence. If an instance is visible from a parent Context solely via hierarchical expansion, it is still not considered physically present in that parent Context for write or membership purposes until it is explicitly added there).*

#### System Fields

Before specializing into specific typologies, it is important to establish that all instances in the graph share a common fundamental base. Every instance is equipped with a core set of system fields that govern identification, provenance, and topological behavior.

1. **Identification (`id`)**
   Every **Entity** instance and **Relation** instance is equipped with a system-managed `id` field (String). The exact format (e.g., UUID, Snowflake ID, or monotonic hash) is an implementation detail of the underlying infrastructure (for instance, the REST API payload bindings detailed from Chapter 3 onwards explicitly mandate UUIDs), but the abstract model simply guarantees absolute, global identification.

2. **Provenance (**`Metadata`**)**
   Every **Entity** instance and **Relation** instance is automatically equipped with a `metadata` field (of system type **`Metadata`**). This field is a complex object handling lifecycle tracking with the following nested fields:
   - `createdBy` (String): The principal who created the instance.
   - `creationTime` (Date): The exact timestamp of creation.
   - `lastUpdateBy` (String): The principal who performed the last modification.
   - `lastUpdateTime` (Date): The exact timestamp of the last modification.

3. **Behavior (**`PropagationConstraint`**)**
   Every **Relation** instance (**IsRelatedTo** and **ConsistsOf**) is strictly equipped with a `propagationConstraint` field (of system type **`PropagationConstraint`**). Unlike the previous two fields which are universal, this field is exclusive to **Relation** instances. It defines the "Avalanche Effect"—how the target **Entity** instance behaves when the source **Resource** instance (or the **Relation** instance itself) is added to or removed from a Context. (The mechanics of this effect are detailed in the [Multi-Context Mutations](04-is-model-mutations-and-avalanches.html#multi-context-mutations) section).

   > **Payload Optionality vs Persistence:** While this field is strictly mandatory for the physical integrity of the graph (every **Relation** instance in the database possesses it), it is **optional in a `POST` payload**, for the **Relation** instance being created and for every **ConsistsOf** instance nested in a **Resource** payload: if a client omits it, the API injects the safe defaults defined by the model. In a `PUT` payload it is always required, on the root **Relation** instance and on every nested **ConsistsOf** instance, whether the instance is created or updated, and its omission returns `400 Bad Request`: a `PUT` carries the full client-controlled state, so the same payload can be repeated with the same outcome; on an existing instance the field always has a value, so omitting it cannot mean removing it, and silently restoring the defaults would change the Relation's behaviour.

   This complex field contains two nested enum fields:
   - `add` (Enum): Defines behavior upon adding an instance to a Context (formally referred to as an `Add to Context` operation). Allowed property field values:
     - `propagate`: Adding the source **Resource** instance to Context C adds the **Relation** instance and recursively its target **Entity** instance to C.
     - `unpropagate`: Adding the source **Resource** instance to Context C does NOT add the **Relation** instance nor its target **Entity** instance to C.
   - `remove` (Enum): Defines behavior upon removing an instance from a Context (formally referred to as a `Remove from Current Context` operation). Allowed property field values:
     - `cascade`: Removing the source **Resource** instance (or the **Relation** instance itself) from Context C recursively removes the target **Entity** instance from C.
     - `cascadeWhenOrphan` *(Available for **IsRelatedTo** only)*: Removing the source **Resource** instance (or the **IsRelatedTo** instance itself) from Context C removes the target **Resource** instance from C **only if**, after the operation, no incoming **IsRelatedTo** instance of the target remains in Context C. Every **IsRelatedTo** instance that the operation does not remove from C counts, whatever its source (see [Two Relations from the Same Source](04-is-model-mutations-and-avalanches.html#remove-propagation)).
     - `keep`: Removing the source **Resource** instance (or the **Relation** instance itself) from Context C does NOT remove the target **Entity** instance from C.

   **Propagation Decision Matrix:**

   | Source Action | Constraint Value | Target Instance Effect |
   |---------------|------------------|------------------------|
   | **Add** to Context C | `propagate` | Target **Entity** instance is recursively added to Context C. |
   | **Add** to Context C | `unpropagate` | Target **Entity** instance is **not** added to Context C. |
   | **Remove** from Context C | `cascade` | Target **Entity** instance is recursively removed from Context C. |
   | **Remove** from Context C | `cascadeWhenOrphan` | Target **Resource** instance is removed from Context C **only if**, after the operation, no incoming **IsRelatedTo** instance remains in Context C. |
   | **Remove** from Context C | `keep` | Target **Entity** instance is **not** removed from Context C. |

   **Default Constraints:**
   The IS-Model defines the following safe default property field values for propagation constraints:
   - For **ConsistsOf** instances:
     - **`add` constraint:** defaults to `propagate`.
     - **`remove` constraint:** defaults to `cascade`.
   - For **IsRelatedTo** instances:
     - **`add` constraint:** defaults to `unpropagate`.
     - **`remove` constraint:** defaults to `keep`.

   **Propagation Constraint Validation Matrix:**
   The system enforces strict structural validation on the propagation constraints provided during **Relation** instance creation or update. Invalid combinations are rejected with a `400 Bad Request`.

   | Relation Type | Valid `add` Values | Valid `remove` Values | Invalid Values (400 Bad Request) |
   |---------------|--------------------|-----------------------|----------------------------------|
   | **ConsistsOf** | `propagate`, `unpropagate` | `cascade` | `remove: cascadeWhenOrphan`\*, `remove: keep`\* |
   | **IsRelatedTo** | `propagate`, `unpropagate` | `cascade`, `cascadeWhenOrphan`, `keep` | *None* |

   *\* Note on invalid **ConsistsOf** removal constraints: Because a **Facet** instance is strictly owned by a single **Resource** instance via exactly one **ConsistsOf** instance globally, it cannot exist independently. Therefore, a `keep` constraint is structurally invalid. Similarly, while `cascadeWhenOrphan` would be mathematically identical to a simple `cascade` (the **Facet** instance would always be considered an orphan upon its parent's removal), the system strictly rejects it to prevent ambiguity and false expectations about shared **Facet** ownership.*

### Property

In addition to the universally embedded system fields and simple primitive types (e.g., String, Integer, Boolean, Date, etc.—fully detailed in the [live-registry type documentation](../model-docs/index.html)), **Facet** and **Relation** schemas can define custom complex property fields.

**`Property`** is the foundational base Type provided by the IS-Model specifically for this purpose. Integrators extend this base Type to define custom, reusable complex data structures (e.g., a hypothetical **`NetworkEndpoint`** or **`LicenseInfo`**) that can be embedded inside the schemas of specific **Facet** or **Relation** Types.

**Architectural Distinction (No Identity):** Crucially, unlike **Entity** and **Relation** instances which are independent graph instances with their own global IDs, values derived from a **`Property`** schema never possess an ID. They are strictly nested data structures that are addressable and identifiable only within the boundary of their container instance.

### Type

The five public extensible IS-Model base Types (**Resource**, **Facet**, **IsRelatedTo**, **ConsistsOf**, and **`Property`**) provide the core building blocks of the IS-Model.

*(Note: Beneath these five public Types sit two abstract primitives, **Entity** and **Relation**. They are served as read-only Type definitions, readable by name, because several properties of their subtypes are defined at that level: a client that builds the complete definition of a Type by following its inheritance (a GUI, for example) reads them there, instead of hard-coding them or finding them repeated in every direct subtype. They cannot be instantiated or extended: integrators define their Types exclusively by extending the five public Types).*

**Abstract vs Concrete Base Types:**

- **Resource**, **Facet**, **IsRelatedTo**, and **`Property`** are strictly **Abstract**. They cannot be instantiated directly because they lack semantic meaning on their own (e.g., a generic **IsRelatedTo** instance does not explain *why* or *how* two **Resource** instances are related, and a generic **`Property`** block without fields conveys no data). They must be extended into concrete subtypes (e.g., **EService**, **SoftwareFacet**, **Hosts**, **Event**).
- **ConsistsOf** is **Concrete**. A generic **ConsistsOf** Type inherently possesses complete semantic meaning: "This **Facet** instance describes this **Resource** instance". While integrators *can* extend it to create specialized semantic attachments (e.g., **HasOwner**), they are perfectly free to instantiate a generic **ConsistsOf** instance directly.

The model is intentionally designed to be extended: it provides these foundational base Types so that integrators can define specific derived Types (e.g., **EService**, **SoftwareFacet**, **HasOwner**, **`Event`**) tailored to the exact needs of their infrastructure.

A Type definition provides a strict structural schema that governs how its data is represented in the graph (either instantiated as independent graph instances or manifested as nested property field values). All data in the IS-Model strictly adheres to the schema defined by its specific Type. The model establishes a strict separation of concerns regarding what the schema of each Type category actually dictates:

> **Why all this semantic pedantry?**
> A reader might notice that this documentation rigorously (and sometimes heavily) repeats the words **Type**, *schema*, and *instance*. This is intentional to avoid a frequent source of confusion when discussing graph models: the ambiguity between semantic labels, structural blueprints, and actual data.
>
> - A **Type** on its own is merely a hierarchical semantic label (e.g., "this is a Software").
> - Its **schema** is what actually dictates how its data is represented (whether it is instantiated as independent graph instances or manifested as nested property field values).
>
> If we did not strictly separate these terms, ambiguity would arise. For example, if we casually wrote "A Resource has a ConsistsOf to a Facet", a reader might incorrectly assume we are implicitly defining a new **ConsistsOf** Type in the system. By rigorously writing "The **Resource** schema dictates the allowed **ConsistsOf** Types, and mandates the presence of a **ConsistsOf** instance pointing to a **Facet** instance (min: 1)", we clearly separate the rules of the blueprint from the requirement of concrete data in the graph.

#### Schema

1. **Resource Schema:** The schema of a **Resource** Type declares **ConsistsOf**/**Facet** pairings (and consequently, their subtypes via polymorphism) for its instances, and enforces the cardinality (`min` / `max`) of the declared pairings. Undeclared pairings remain valid under the Open-World Assumption. A **Resource** schema declares no data fields: it describes only the composition of its instances (the **ConsistsOf**/**Facet** pairings, with enforced cardinality) and documents the expected **IsRelatedTo** links (advisory). A **Resource** instance therefore has no custom property fields: besides the system fields (`type`, `supertypes`, `id`, `metadata`, `contexts`) it carries only its `consistsOf` structure, and its data lives in its **Facet** instances.
2. **Facet Schema:** The schema of a **Facet** Type defines the data structure for its instances by specifying a set of arbitrary property fields (either primitive property fields or complex **`Property`** Types), in addition to possessing the system-defined property fields `id` and `metadata`.
3. **IsRelatedTo Schema:** The schema of an **IsRelatedTo** Type dictates the allowed source **Resource** Type and target **Resource** Type (and consequently, their subtypes via polymorphism) for its instances. It can also define its own set of arbitrary property fields for its instances, in addition to possessing the system-defined property fields `id`, `metadata`, and `propagationConstraint`.
4. **ConsistsOf Schema:** The schema of a **ConsistsOf** Type dictates the allowed source **Resource** Type and target **Facet** Type (and consequently, their subtypes via polymorphism) for its instances. It can also define its own set of arbitrary property fields for its instances, in addition to possessing the system-defined property fields `id`, `metadata`, and `propagationConstraint`.
5. **Property Schema:** The schema of a **`Property`** Type defines a complex, reusable data structure composed of primitive property fields or other nested **`Property`** Types, designed to dictate the nested data structure when embedded within the schemas of **Facet** or **Relation** Types.

#### Subtyping and Polymorphism

```eval_rst
*(Notation: we write* :math:`S <: T` *to formally indicate that a Type* :math:`S` *is a subtype of a Type* :math:`T`\ *. For example, **HasContact** <: **ConsistsOf**. For the strict mathematical formulation, refer to the [Formal Semantics](appendix/01-is-model-formal-semantics.md) section).*
```

Because the model is built on inheritance, two fundamental principles apply universally across all Types:

```eval_rst
1. **Polymorphic Validation:** If a schema expects an instance of a specific Type :math:`T`, any instance of its subtypes (:math:`S <: T`) is perfectly valid.
2. **Non-Contradiction Rule:** The schema of a derived Type can add new constraints, but it **can never contradict** the constraints inherited from the schemas of its parent Types. In the case of **Multiple Inheritance** (where a Type extends multiple parent Types), if the parent schemas impose mutually incoherent constraints (e.g., Parent A mandates ``max: 1`` and Parent B mandates ``min: 2`` for the same topological attachment), the system considers the inheritance invalid. The system will outright reject the registration of such an incoherent derived Type (returning an error to the client), shifting the responsibility to the schema designer to provide a mathematically sound definition.
```

#### Polymorphism in Relations (Source and Target)

As a direct consequence of the universal polymorphism rule, the definition of any **Relation** Type (e.g., a specific **IsRelatedTo** or **ConsistsOf** specialization) dictates the allowed Type for its source **Resource** instance and its target **Entity** instance.

For example, the abstract base schemas enforce the following top-level rules:

- **Resource** -- **ConsistsOf** --> **Facet**
- **Resource** -- **IsRelatedTo** --> **Resource**

Thanks to polymorphism, an instance of any subtype derived from the dictated Type is perfectly valid.

#### The Open-World Assumption (Extensibility Paradigm)

To truly satisfy the dynamic and evolving requirements of a System of Systems (as introduced in the architectural overview), the IS-Model operates under the **Open-World Assumption**. This philosophy dictates that schemas define the *minimum* required data and structure, but do not strictly forbid additions.

In the formal IS-Model, this translates to two powerful runtime capabilities:

1. **Dynamic Facet Attachment (Topological Extensibility):** A **Resource** instance can dynamically have arbitrary **Facet** instances attached to it via **ConsistsOf** instances, beyond what is strictly dictated by its schema.
2. **Schema-Mixed Mode (Data Extensibility):** Any instance in the graph that defines properties (whether it is a **Facet**, **IsRelatedTo**, **ConsistsOf**, or even a nested **`Property`** field value) can dynamically host arbitrary custom property fields that are not defined in its formal schema. (Note: A **Resource** instance does not support custom property fields; its extensibility is entirely topological via Facets).

#### Topological Uniqueness Invariants

To ensure deterministic operations, prevent semantic ambiguity, and avoid "double-counting" during searches, the Information System enforces two strict uniqueness rules across the entire graph topology:

1. **Facet Exclusivity (Single Ownership):**
   A **Facet** instance is intrinsically a characterizing aspect of a single **Resource** instance. It must be attached via exactly one **ConsistsOf** instance globally. In other words, a **Facet** instance cannot be attached to multiple **Resource** instances, nor can it be attached via multiple **ConsistsOf** instances to the same **Resource** instance.
2. **IsRelatedTo Polymorphic Uniqueness:**
   Two specific **Resource** instances cannot be linked via multiple **IsRelatedTo** instances belonging to the same polymorphic lineage. The rule holds across every Context: an **IsRelatedTo** instance is one, with one `propagationConstraint` and one set of properties, in every Context it belongs to. Creating a second one in a Context that already holds one returns `409 Conflict`; creating it in a Context where the existing one is not returns `403 Forbidden`, and the client adds the existing instance to that Context instead (Add to Context). Two instances belong to the same polymorphic lineage when their Types are the same or one extends the other, directly or not: sharing an ancestor is not enough, since every such Type descends from **IsRelatedTo**. Two **IsRelatedTo** instances whose Types do not extend one another (e.g. `Hosts` and `CallsFor`) can therefore link the same two **Resource** instances; **IsRelatedTo** itself is abstract and has no instance of its own. This prevents semantic redundancy: for example, you cannot have a generic `Hosts` relation and a specialized `MyHosts` (where `MyHosts <: Hosts`) relation existing simultaneously linking the same two **Resource** instances. Re-asserting the same semantic connection through a more specialized type is redundant; the correct operational pattern is to delete the generic supertype relation and create the specialized one, as polymorphic graph queries will still successfully return the specialized relation when querying for the generic type.
   Conversely, parallel **IsRelatedTo** instances linking the same two **Resource** instances are explicitly permitted if they belong to entirely orthogonal polymorphic branches (e.g., a `Discovers` relation and a `Uses` relation), as they capture orthogonally distinct semantic interactions.

#### Resource Structural Cardinality

As a direct implementation of the overarching Open-World Assumption's topological extensibility, a **Resource** schema declares cardinality-constrained **ConsistsOf**/**Facet** pairings and documented **IsRelatedTo**/**Resource** pairings. Only the Descriptive Topology cardinalities on declared **ConsistsOf**/**Facet** pairings are enforced strictly. **IsRelatedTo** cardinalities are advisory, and pairings omitted from the schema remain valid extensions rather than forbidden topology.

##### ConsistsOf to Facet Cardinality

Because of polymorphism, cardinality rules require careful attention to the exact **ConsistsOf** Type and target **Facet** Type pairings specified in the schema.

**The Non-Contradiction Rule (No `max: 0`):**
Because the IS-Model operates under the Open-World Assumption (which guarantees Topological Extensibility), a schema designer cannot define a structural constraint with `max: 0`. Doing so would act as a "Negative Constraint" (e.g., explicitly forbidding the attachment of a specific **Facet** via a specific **ConsistsOf** Type), which directly contradicts the fundamental extensibility of the model. If a schema designer does not want to strictly require a **Facet**, they must simply omit the constraint entirely (which defaults to `0..*`), leaving the system open to legitimate custom extensions.

To illustrate polymorphic cardinality within a **Resource** schema, assume the following hierarchy of **Facet** Types and **ConsistsOf** Types:

- **ContactFacet** <: **Facet**
- **HasContact** <: **ConsistsOf** (dictating **Resource** -- **HasContact** --> **ContactFacet**)
- **HasOwner** <: **HasContact** (dictating **Resource** -- **HasOwner** --> **ContactFacet**)
- **HasCurator** <: **HasContact** (dictating **Resource** -- **HasCurator** --> **ContactFacet**)

- If a **Resource** schema dictates a generic **ConsistsOf** Type pointing to a **ContactFacet** Type (max: 1), the **Resource** instance can have *at most one* **ContactFacet** instance (or any instance of its subtypes) in total, regardless of whether it is attached via a **HasOwner** instance, a **HasCurator** instance, or a generic **ConsistsOf** instance (because all of them are specializations of **ConsistsOf** and thus count towards the limit).
- If the schema dictates a **HasOwner** Type pointing to a **ContactFacet** Type (max: 1), it can have at most one owner (i.e., one **HasOwner** instance pointing to a **ContactFacet** instance or any instance of its subtypes). The **Resource** instance could still possess another **ContactFacet** instance (or any instance of its subtypes) attached via a **HasCurator** instance.
- If the schema dictates a **HasContact** Type pointing to a **ContactFacet** Type (max: 1), then it can have a **HasOwner** instance pointing to a **ContactFacet** instance (or any instance of its subtypes) OR a **HasCurator** instance pointing to a **ContactFacet** instance (or any instance of its subtypes), but not both simultaneously, because both are specializations of **HasContact**.

##### IsRelatedTo Suggestion

While the attachment of **Facet** instances via **ConsistsOf** instances can be strictly enforced by the system, the cardinalities (`min` and `max`) for **IsRelatedTo** instances between two **Resource** instances are **always considered an advisory suggestion** (First-Class Documentation).

The system intentionally abstains from hard-validating the Infrastructure Topology to respect the Open-World Assumption. While it makes sense to strictly enforce the Descriptive Topology (a **Resource** instance MUST have its core **Facet** instances to be valid), rigidly forcing the Infrastructure Topology (how independent **Resource** instances link to one another) would contradict the extensibility paradigm of a system designed to accept unforeseen valid associations across the federated infrastructure.

Furthermore, there are practical constraints that necessitate this advisory approach:

- **`min` (The Chicken-and-Egg Deadlock):** Minimum cardinalities cannot be enforced as mandatory at creation time due to the multi-step nature of graph insertion. If an instance `R1` strictly requires an instance `R2` to be created, and `R2` requires `R1`, neither could ever be instantiated if the system evaluated Infrastructure Topology synchronously on a single-instance basis. *(For how to atomically replace mandatory elements within the Descriptive Topology without hitting cardinality deadlocks, see the [1-single-context-update-local-copy-on-write](09-api-instances-and-admin.html#single-context-update-local-copy-on-write) API documentation).*
- **`max` (Open-World Extensibility):** Maximum cardinalities are treated as advisory guidelines for clients. Rigidly rejecting a new link simply because a `max` limit was reached would explicitly act as a "Negative Constraint", which directly violates the Open-World Philosophy.

#### Schema-Mixed Mode (Custom Properties Extensibility)

As a direct implementation of the Open-World Assumption's data extensibility, the IS-Model actively supports **Schema-Mixed Mode**. This means that any instance in the graph that defines properties—whether it is a **Facet**, a **ConsistsOf**, an **IsRelatedTo**, or even a nested **`Property`** field value—can dynamically host arbitrary custom property fields that are not defined in its formal schema. This provides ultimate runtime flexibility for corner cases. (Note: **Resource** instances are structurally excluded from Schema-Mixed Mode because they do not host data properties; their extensibility is entirely topological).

Just as with Topological Extensibility for **Facet** attachments, this data extensibility enforces a strict non-contradiction rule for properties: a schema designer cannot define a "Negative Constraint" to explicitly forbid custom properties (e.g., forcing a strict `additionalProperties: false` or `max: 0` equivalent). All unknown properties are naturally accepted by the backend and must be gracefully preserved by clients parsing the API responses.

#### Types as "First-Class Documentation"

Embedding structural rules and textual descriptions directly within the model ensures that *any* Type schema acts as live, "first-class documentation". A dynamic client or GUI does not need hardcoded logic or external manuals to build a data-entry form. By querying the system for a specific Type schema, the GUI automatically knows both the structural constraints and the semantic rationale, adapting its behavior based on the category:

- **Querying a Resource schema:** The GUI discovers the declared topology for instances of that **Resource** Type; undeclared extensions remain valid. Specifically:
  - It discovers which **ConsistsOf** instances (of a dictated Type or its subtypes) pointing to **Facet** instances (of a dictated Type or its subtypes) are required, and their cardinality limits.
  - It discovers which **IsRelatedTo** instances (of a dictated Type or its subtypes) pointing to target **Resource** instances (of a dictated Type or its subtypes) are suggested.
  
  By recursively querying the schemas of these dictated **Facet**, **IsRelatedTo**, and **ConsistsOf** Types, the GUI builds the complete data-entry form.
- **Querying a Facet schema:** The GUI discovers the formally defined property fields (either primitive type values or complex **`Property`** field values of the dictated Type or its subtypes) the **Facet** instance is expected to hold, along with their validation constraints (e.g., `mandatory`, `readonly`, or formatting rules).
- **Querying a ConsistsOf schema:** The GUI discovers the allowed source **Resource** instance (of the dictated Type or its subtypes) and target **Facet** instance (of the dictated Type or its subtypes), the formally defined property fields (either primitive type values or complex **`Property`** field values of the dictated Type or its subtypes) the **ConsistsOf** instance itself is expected to hold along with their validation constraints, and the semantic rationale of the structural attachment.
- **Querying an IsRelatedTo schema:** The GUI discovers the allowed source **Resource** instance (of the dictated Type or its subtypes) and target **Resource** instance (of the dictated Type or its subtypes), the formally defined property fields (either primitive type values or complex **`Property`** field values of the dictated Type or its subtypes) the **IsRelatedTo** instance itself is expected to hold along with their validation constraints, and critically, the *semantic rationale* of the link.
- **Querying a `Property` schema:** The GUI discovers the formally defined internal nested fields that compose this complex **`Property`** field value, whether they are primitive type values (e.g., String, Integer) or further nested complex **`Property`** field values (of the dictated **`Property`** Type or its subtypes), and their respective validation constraints.

The GUI can render these semantic descriptions as inline help or tooltips. This ensures automatic validation and autocompletion based solely on the Information System, meaning the documentation is directly embedded and distributed within the API itself.

### The LEGO Metaphor

To quickly grasp how all these building blocks interact, think of the concrete graph as a massive box of LEGOs, built following a strict instruction manual (the Type schemas):

- **Resource** instances: *Completed, independent constructions* (e.g., a car or a hospital). They are not single, pre-molded toys (monolithic objects with all properties hardcoded), but assemblies.
- **Facet** instances: The fundamental, reusable *LEGO blocks* (e.g., a "Contact block", an "Endpoint block") that make up the main constructions (**Resource** instances).
- **ConsistsOf** instances: The *pegs* that securely snap the blocks (**Facet** instances) into the main construction (**Resource** instance).
- **IsRelatedTo** instances: The *cables, roads, or towing hitches* that connect two independent constructions (**Resource** instances). Crucially, the instruction manual enforces logical interactions: a LEGO helicopter cannot land on a generic house unless it is structurally designed with a helipad, but it can land on a hospital.
- **Property fields**: The *factory-printed markings and colors* of the individual blocks (**Facet** instances), pegs (**ConsistsOf** instances), or cables (**IsRelatedTo** instances). The main construction (**Resource** instance) itself does not hold property fields; it gets its characteristics purely from the blocks you attach to it. For example, two "Contact" blocks are structurally identical, but one might be printed green and the other grey.
- **Schema-Mixed Mode (Custom Properties):** The ability to attach a custom *sticker* (an arbitrary additional property field) to a standard block (**Facet** instance) or connection (**Relation** instance). The system's instruction manual doesn't formally know about this sticker, but the LEGO system physically allows you to slap it onto the piece anyway, ensuring ultimate flexibility for corner cases.

By combining these base elements and enforcing logical connections, you can build completely different and highly modular ecosystems.
