Skip to main content
Version: 2.0.0

Migrating from 1.x to 2.0.0

Back up your data before upgrading

This update modifies the stored data structure to align with the new v2 data model. Once you have migrated and are running v2, you will not be able to roll back to v1 without restoring from a backup.

Before proceeding, take a full backup of your MinIO data directory (e.g. ./minio_data/) and keep it until you have confirmed the upgrade is stable.

This guide covers what changed between 1.1.3 and 2.0.0, what you need to do before upgrading, and what you can adopt at your own pace after the upgrade.

Before you upgrade

1. Update RESOLVER_DOMAIN

The API version path has changed. Update your environment variable from:

RESOLVER_DOMAIN=https://resolver.example.com/api/1.0.0

to:

RESOLVER_DOMAIN=https://resolver.example.com/api/2.0.0

This is the only required configuration change. All API endpoints move from /api/1.0.0/... to /api/2.0.0/.... The route structure after the version prefix is unchanged.

2. Update API client base paths

Any code that calls the IDR needs its base URL updated to /api/2.0.0. This includes registration scripts, resolution clients, and any integrations that construct resolver URLs.

The Link response header has been restructured. Every resolution response now includes:

  • An owl:sameAs entry pointing to the canonical URL of the identifier.
  • A self-referencing linkset entry pointing to ?linkType=all.
  • Up to three parent linkset entries when the request includes qualifier paths.
  • Target link entries for each active response (subject to a size budget, see below).

If your clients parse the Link header, review the parsing logic to handle these new entries. If you only use the linkset JSON body (Accept: application/linkset+json), no changes are needed.

Breaking changes

Composite key expansion

Duplicate detection during registration now uses five fields instead of three:

Field1.x2.0.0
targetUrlUsedUsed
linkTypeUsedUsed
mimeTypeUsedUsed
ianaLanguageIgnoredUsed
contextIgnoredUsed

What this means: two responses that share the same targetUrl, linkType, and mimeType but differ in ianaLanguage or context are now treated as distinct links. Under 1.x these would have been rejected as duplicates.

Existing data does not need migration. Documents registered under 1.x continue to work. The only behavioural difference is that new registrations now allow combinations that were previously blocked.

A new environment variable LINK_HEADER_MAX_SIZE (default: 8192 bytes) controls the maximum size of the Link response header.

If the assembled header exceeds this limit, all target link entries are dropped. The mandatory entries (owl:sameAs and linkset references) are always included.

For identifiers with many registered responses, you may need to increase this value. Watch for "Link header truncated" warnings in the logs.

LINK_HEADER_MAX_SIZE=16384

Linkset metadata for existing identifiers

Linkset JSON responses (?linkType=all) contain an anchor URL and relationship-type keys that include your RESOLVER_DOMAIN. For identifiers registered under 1.x, these URLs still reference /api/1.0.0 after the upgrade.

What is affected:

  • The anchor field in the linkset (e.g. https://example.com/api/1.0.0/gs1/01/...)
  • Relationship-type keys (e.g. https://example.com/api/1.0.0/voc/certificationInfo)

What is NOT affected:

  • 302 redirects — target URLs are unchanged
  • The Link response header — built at query time using the current RESOLVER_DOMAIN
  • Target href values inside the linkset — these point to your resources, not the resolver

How it self-heals: the linkset is rebuilt automatically whenever the document is mutated. Any of the following actions will update the linkset to use /api/2.0.0:

  • Updating a response via PUT /resolver/links/{linkId}
  • Deleting a response via DELETE /resolver/links/{linkId}
  • Re-registering the identifier via POST /resolver

If you need all linksets updated immediately, you can run a no-op update on one response per identifier using the Link Management PUT endpoint (for example, setting a field to its current value). This triggers a linkset rebuild without changing any data.

New features

These features are all opt-in. Existing workflows continue to work without changes.

New endpoints at /resolver/links allow you to list, update, and delete individual link responses without re-registering the entire identifier document.

MethodPathDescription
GET/resolver/links?namespace=...&identificationKeyType=...&identificationKey=...List all responses for an identifier (active and inactive)
GET/resolver/links/{linkId}Get a single response by ID
PUT/resolver/links/{linkId}Update a response (partial update)
DELETE/resolver/links/{linkId}Soft-delete a response (sets active: false)
DELETE/resolver/links/{linkId}?hard=trueHard-delete a response (permanently removes it)

All endpoints require Authorization: Bearer {API_KEY}. See the Developer Guide for request/response details.

UNTP data model fields

Three optional fields have been added to link responses for UN Transparency Protocol compliance:

FieldTypePurpose
encryptionMethod"none" | "AES-128" | "AES-256"Encryption applied to the target resource
accessRoleArray of role URIsRoles that may access this link variant
methodString (e.g. "POST")HTTP method for accessing the target

These fields are stored when provided during registration and appear in linkset output. If omitted, responses behave exactly as before.

Access role filtering

A new ?accessRole= query parameter filters resolution results by UNTP access role.

GET /api/2.0.0/{namespace}/{ai}/{key}?linkType=all&accessRole=customer

Shorthand values are normalised automatically: customer becomes untp:accessRole#Customer.

Responses without an accessRole field are treated as public and always included. When the parameter is omitted, all responses are returned (existing behaviour).

When a response's targetUrl is changed via the Link Management PUT endpoint, the previous URL is recorded in the version history and appears in the linkset as a rel="predecessor-version" entry following RFC 6903.

Decryption key forwarding

A new ?decryptionKey= query parameter forwards the key to the target URL during resolution, but only when the matched response has fwqs: true. When fwqs is false or the parameter is absent, nothing changes.

Every link response now carries:

  • A linkId (UUID) for unique identification.
  • A version number that increments on each update.
  • A versionHistory array recording what changed and when.

These fields are added automatically. Documents created under 1.x are auto-normalised on first read: the service adds linkId, version: 1, and an empty versionHistory to each response, then persists the updated document. No manual migration is needed.

New environment variables

VariableRequiredDefaultDescription
LINK_HEADER_MAX_SIZENo8192Maximum Link header size in bytes. Increase if you see truncation warnings.

Checklist

Required before upgrade

  • Back up your MinIO data directory (e.g. cp -r ./minio_data/ ./minio_data_backup/) — v2 modifies the stored data structure and you cannot roll back without a backup
  • Update RESOLVER_DOMAIN to include /api/2.0.0
  • Update all API clients to use the /api/2.0.0 base path
  • Pull the 2.0.0 container image
  • Review Link header parsing logic if your clients depend on it
  • Test resolution with existing identifiers to confirm auto-normalisation works
  • Set LINK_HEADER_MAX_SIZE if you have identifiers with many responses
  • If your consumers depend on linkset anchor or relationship-type URLs, trigger a linkset rebuild for existing identifiers (see Linkset metadata for existing identifiers)

Optional adoption

  • Use /resolver/links CRUD endpoints for fine-grained link management
  • Add UNTP fields (encryptionMethod, accessRole, method) to new registrations
  • Use ?accessRole= filtering for variant-based disclosure
  • Update linkset parsers to handle predecessor-version entries and UNTP fields