Resource Registry — API Access & Query Templates

Query Template Management — base path /query-templates

Authorization & Token Selection

| Action | HTTP | Path | Query Parameters | IS-M / Infra-M | IS-Admin / Ctx-M | IS-Editor | IS-Contrib | IS-Member | |——–|——|——|——————|:————–:|:—————-:|:———:|:———-:|:———:| | List | GET | /query-templates | limit, offset, metadataPolicy | ✅ | ✅ | ✅ | ✅ | ✅ | | Execute JSON Query | QUERY | /query-templates (POST /query-templates/query fallback) | limit, offset, metadataPolicy | ✅ | ✅ | ✅ | ✅ | ✅ | | Create/Update | PUT | /query-templates/{query-template-name} | metadataPolicy | ✅ | ❌ | ❌ | ❌ | ❌ | | Read | GET | /query-templates/{query-template-name} | metadataPolicy | ✅ | ✅ | ✅ | ✅ | ✅ | | Execute | QUERY | /query-templates/{query-template-name} (POST fallback) | limit, offset, polymorphic, hierarchical, metadataPolicy, includeContexts | ✅ | ✅ | ✅ | ✅ | ✅ | | Delete | DELETE | /query-templates/{query-template-name} | None | ✅ | ❌ | ❌ | ❌ | ❌ |

Token Scope Rule:

| Operation Group | Token must be issued for | |—————-|—————————| | List, Execute JSON Query, Read | No specific target Context is required; authorization is evaluated from the token role | | Create/Update, Delete | No specific target Context is required; authorization is evaluated from the token role (requires IS-M / Infra-M) | | Execute | Token Context acts as visibility scope |

HTTP Contract

| Action | Additional Request Headers | Response Headers | Success HTTP Code | Error HTTP Code | |——–|—————————-|——————|——————-|—————–| | List | Accept | Content-Type, Link, X-Warning | 200 OK | None | | Execute JSON Query | Content-Type, Accept | Content-Type, Link, X-Warning | 200 OK | 400 Bad Request | | Create/Update | 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 | 404 Not Found | | Execute | Content-Type, Accept | Content-Type, Link, X-Warning, X-Result-Scope | 200 OK | 400 Bad Request, 403 Forbidden, 404 Not Found | | Delete | None | X-Warning | 204 No Content | 403 Forbidden, 404 Not Found |

Operational Notes

  • Global List Semantics: GET /query-templates and its /access mirror list the global Query Template collection for every operational role; the token Context is not a visibility boundary. Pagination is applied using limit and offset. When metadataPolicy includes metadata, createdBy and lastUpdateBy are redacted for non-privileged callers. Serialization is all-or-nothing: an unreadable row fails the request instead of producing a partial successful page.

  • Global Definition Query Semantics: QUERY /query-templates and its /access mirror search the global Query Template definitions, not the instances returned by executing a stored template. They accept a required JSON QBE object and support the canonical operators and _emit rules. Full metadata and projected metadata-identity aliases are redacted for non-privileged callers; metadataPolicy is ignored with X-Warning when _emit determines the response shape. Result serialization is fail-fast rather than returning a silently incomplete page.

  • Target Limitation (Instances Only): Although the JSON Query engine supports querying Contexts, Type Schemas, Query Templates, and Instances, the Query Template mechanism is by design strictly restricted to Instances. Any query saved within a template is implicitly executed to find instances. Consequently, the root "type" in a saved template must always specify a valid Entity or Relation type (e.g., Resource, EService). Query templates cannot be used to save queries targeting Contexts, Type Schemas, or other Query Templates.

  • Payload Consistency: name in the PUT path parameter must match the name field in the JSON body.

  • Internal ``id`` ownership during upsert: The id field inside the Query Template JSON represents its internal global UUID. The REST endpoint URL strictly uses the readable name, never the UUID. If omitted or null during creation, the backend generates a valid UUID. A supplied UUID already used by another Query Template produces 409 Conflict; reuse across different element types produces 400 Bad Request, following the registry-wide UUID ownership rule. During an update, an explicitly supplied id must match the persisted UUID for that name, otherwise the request is rejected with 400 Bad Request.

  • Upsert Semantics: PUT /query-templates/{name} follows upsert semantics for admin roles: it creates when absent (201 Created) and updates when already present (200 OK). (Contrast with Type definition: while Types strictly forbid online structural updates and return ``409 Conflict``, Query Templates fully support online ``PUT`` updates). Non-admin roles cannot create or update templates; any such attempt returns 403 Forbidden regardless of whether the template already exists.

  • Global Point Read Semantics: GET /query-templates/{name} and its /access mirror resolve the exact, case-sensitive global Query Template name for every operational role without applying token-Context visibility. metadataPolicy=none|root|all controls metadata inclusion; when metadata is present, createdBy and lastUpdateBy are redacted for every non-global role. A missing or case-mismatched name returns 404 Not Found. Successful responses include the canonical name-addressed Content-Location and a Link: rel="collection" to /query-templates.

  • Parameter Validation: Template query parameters (prefixed with $) must be declared in templateVariables; default values are used for validation at save time.

  • Execute Payload: The optional request body for QUERY /query-templates/{name} contains a JSON object of template-variable substitutions and, when present, must use Content-Type: application/json. An absent or empty body uses template defaults. Omitted variables use their declared defaults; malformed JSON, a non-object JSON value, an invalid substitution, or an omitted mandatory variable without a default produces 400 Bad Request.

  • Hierarchical Execution: hierarchical in Execute expands the search boundary and is available to IS-M / Infra-M, IS-Admin / Ctx-M, IS-Editor, IS-Contrib, and IS-Member (see [hierarchical parameter](11-api-query-parameters.md#hierarchical)). Administrative roles retain unrestricted descendant visibility; other roles use the active-only hierarchical channel, omit non-ACTIVE descendant memberships, and receive X-Result-Scope: state-filtered when such descendants exist.

  • Execute Visibility and Privacy: Execution uses the same instance-query engine and role-derived visibility directives as QUERY /instances. Non-privileged callers receive redacted metadata identities, and includeContexts=true exposes only authorized descendant memberships and reports X-Result-Scope: role-filtered. Projection queries preserve the canonical _emit precedence and report ignored enrichment parameters through X-Warning.

  • Permanent Exact-Name Delete: DELETE /query-templates/{name} permanently and atomically removes the Query Template identified by its exact, case-sensitive global name and makes that name reusable. Only IS-M and Infra-M may delete; token Context does not restrict the target. The operation accepts neither a request body nor query parameters. Supplied query parameters are ignored with X-Warning; an unknown or already deleted exact name returns 404 Not Found.

Access API — base path /access

Read-only facade that mirrors the readable collection methods and adds query execution endpoints.

Architectural Note on Dual-Paths (Network-Level Exposure): The existence of duplicated read-only endpoints (e.g., GET /instances vs GET /access/instances) with identical authorization rules serves a critical infrastructure purpose: network-level segregation. The D4Science security model dictates that all write-capable endpoints (e.g., /instances, /contexts) are restricted solely to internal microservice traffic. Conversely, the /access facade (along with its query execution endpoints) is the only branch exposed to the external internet. This architectural split ensures external clients can discover and read instances but cannot physically reach the write API surfaces.

Important — DB-Level Read-Only Restriction: All query execution operations initiated through this facade (including jsonQuery and running query templates via /access) are strictly read-only. The underlying database connection uses a read-only user. Any attempt to execute non-idempotent operations (INSERT, UPDATE, DELETE, etc.) within these queries or templates will be rejected outright at the database engine level.

All endpoints in this class that mirror existing management endpoints (/contexts, /types, /instances, /query-templates) share the same authorization rules as their counterparts.

Normative Mirror-Parity Rule: For mirrored endpoints, status-code semantics are contractually identical to their core counterparts (including 403 vs 404 distinction where applicable). The facade exists for network exposure and read-only separation, not for semantic rewriting.

The tables below enumerate normative facade-to-core Java method bindings. The hidden Access.readCurrentContextLegacy() compatibility alias mirrors ContextManager.readCurrentContextLegacy() and is intentionally excluded as a separate action. Transport-derived behavior that has no dedicated Java method is also kept outside the tables.

Contexts, Types, Query Templates (mirrors)

| Action | HTTP | Path | Facade → Core Method | IS-M / Infra-M | IS-Admin / Ctx-M | IS-Editor | IS-Contrib | IS-Member | |——–|——|——|—|:-:|:-:|:-:|:-:|:-:| | List Contexts | GET | /access/contexts | Access.listContexts() → ContextManager.listContexts() | ✅ | ✅ | ✅ | ✅ | ✅ | | Execute Context JSON Query | QUERY | /access/contexts | Access.queryContexts() → ContextManager.query() | ✅ | ✅ | ✅ | ✅ | ✅ | | Read Context | GET | /access/contexts/{context-uuid} | Access.readContext() → ContextManager.read() | ✅ | ✅ | ✅ | ✅ | ✅ | | Read Current Context | GET | /access/contexts/@current | Access.readCurrentContext() → ContextManager.readCurrentContext() | ✅ | ✅ | ✅ | ✅ | ✅ | | Read Context History | GET | /access/contexts/{context-uuid}/history | Access.readContextHistory() → ContextManager.readHistory() | ✅ | ✅ | ❌ | ❌ | ❌ | | Execute Type JSON Query | QUERY | /access/types | Access.queryTypes() → TypeManager.query() | ✅ | ✅ | ✅ | ✅ | ✅ | | Read Type | GET | /access/types/{type-name} | Access.readType() → TypeManager.read() | ✅ | ✅ | ✅ | ✅ | ✅ | | List Query Templates | GET | /access/query-templates | Access.listQueryTemplates() → QueryTemplateManager.all() | ✅ | ✅ | ✅ | ✅ | ✅ | | Execute Query Template JSON Query | QUERY | /access/query-templates | Access.queryQueryTemplates() → QueryTemplateManager.query() | ✅ | ✅ | ✅ | ✅ | ✅ | | Read Query Template | GET | /access/query-templates/{name} | Access.readQueryTemplate() → QueryTemplateManager.read() | ✅ | ✅ | ✅ | ✅ | ✅ | | Execute Query Template | QUERY | /access/query-templates/{name} | Access.runQueryTemplate() → QueryTemplateManager.run() | ✅ | ✅ | ✅ | ✅ | ✅ |

Instances (mirrors)

| Action | HTTP | Path | Facade → Core Method | IS-M / Infra-M | IS-Admin / Ctx-M | IS-Editor | IS-Contrib | IS-Member | |——–|——|——|—|:-:|:-:|:-:|:-:|:-:| | List Instances | GET | /access/instances/{type} | Access.listInstances() → InstancesManager.readAll() | ✅ | ✅ | ✅ | ✅ | ✅ | | Execute Instance JSON Query | QUERY | /access/instances | Access.jsonQuery() → InstancesManager.query() | ✅ | ✅ | ✅ | ✅ | ✅ | | Read Instance | GET | /access/instances/{type}/{instance-uuid} | Access.readInstance() → InstancesManager.read() | ✅ | ✅ | ✅ | ✅ | ✅ | | List Instance Contexts | GET | /access/instances/{type}/{instance-uuid}/contexts | Access.getInstanceContexts() → InstancesManager.getInstanceContexts() | ✅ | ✅ | ✅ | ✅ | ✅ |

HEAD /access/instances/{type}/{instance-uuid} may be served by Jersey as the automatic bodyless view of the corresponding GET. It is not listed as a facade mirror because neither Access nor InstancesManager declares a separate Java method for it.

Token Selection (Quick Rule)

| Operation Group | Token must be issued for | |—————-|—————————| | Mirror reads and JSON Queries (/access/contexts, /access/types, /access/instances, /access/query-templates) | Same authorization logic as mirrored endpoints (e.g., Token Context acts as visibility scope for Instances, but acts merely as role-bearer for Types and Templates) | | Template execution via /access | Token Context acts as visibility scope |

Notes for jsonQuery:

  • _emit precedence and privacy masking rules are defined canonically in JSON Query Syntax Reference (Canonical _emit Precedence Rules).

  • Reserved leading characters (normative): domain field names starting with @ or _ are not allowed in the IS-Model. These prefixes are reserved for system/query semantics and cannot be used as user-defined field names. In accordance with the API’s lenient processing mode, if a client submits a payload containing custom fields with these reserved prefixes, the fields are ignored and an X-Warning header is emitted. They are not strictly rejected with a 400 Bad Request.