Skip to main content

The entity type restriction

An entity type restriction says which entity types a caller may see and write. Like every name in a policy, the types are compiled to IRIs against the file's context declaration when the policy loads. A request's types are expanded against the context the request declares, so a caller cannot reach a forbidden type by spelling it through a context of their own.

[policy.access.entity-type]
allowed = ["Vehicle", "Device"]
type-on-write = "required" # or "optional"; the default is "required"

Reads​

A type selection that the restriction covers only in part is narrowed to that part. This applies to the type parameter, to the selectors of a batch query and to a subscription's entities.

A disjunction keeps the sides that are allowed. When only Vehicle is allowed, ?type=Vehicle,Building is forwarded as type=Vehicle, and (Vehicle;Building)|Vehicle is forwarded as Vehicle. A conjunction is refused as soon as either side is forbidden. ?type=Vehicle;Building asks for entities that are both, and an entity of a forbidden type is not readable for also having an allowed one, so with only Vehicle allowed that request is a 403. A selection left with nothing is a 403 that names the first forbidden type.

In a batch body, a selector narrowed to nothing is dropped and the others are kept. The selectors are a disjunction (NGSI-LD 5.2.33). A body whose every selector is dropped is a 403.

A read by identifier names no type, so it is judged by the entity the broker holds. Libra fetches the entity with a pre-flight request. An entity of a forbidden type gets the same 404 as an absent identifier, so a restricted caller cannot discover which identifiers exist or what they are.

GET /types/{type} naming a forbidden type is refused.

Writes​

A create whose payload names a forbidden type is refused before the broker is reached. A batch create, upsert or update is judged entity by entity. An update, merge or delete by identifier is judged by the entity as it exists, through the same pre-flight as a read.

type-on-write decides what a payload that names no type means. required, the default, refuses it. A write whose type nobody can name is a write the restriction cannot judge. optional forwards it and judges the payload by what it does carry. A replace (PUT) is judged by the entity as it exists, so it never needs optional.

What is unchanged​

An entity-types condition is a different thing from this restriction. It still compares the whole selection. An allow whose condition says entity-types = ["Vehicle"] does not cover ?type=Vehicle,Building, while the restriction narrows it. The condition decides whether the policy matches at all. The restriction decides what an allowed request reaches.

Worked example​

[policy.access.entity-type]
allowed = ["Vehicle"]
RequestAnswer
GET /entities?type=Vehicleforwarded unchanged
GET /entities?type=Vehicle,Buildingforwarded as type=Vehicle
GET /entities?type=Vehicle;Building403: the conjunction names a forbidden type
GET /entities/urn:example:Building:1404, same body as a nonexistent identifier, whether or not the broker holds it
POST /entities with "type": "Building"403 before the broker is reached
GET /types/Building403

Context source registrations are judged by the types they register rather than by the request's type. See context source registrations.