Skip to content

The operator manifest reference

A UniDPP deployment is data. One versioned, validated file — the operator manifest (unidpp-operator.yaml) — declares every knob of every service: binds, secrets, feature toggles, crypto-suite policy, branding, and the sovereignty declaration. Processes stay plain environment-configured; the manifest is rendered into their environment at launch. Zero code differs between the reference deployment and a tenant: the manifest is the product.

This page documents every field of the manifest schema (api_version: unidpp.org/v1). Each knob below has an anchor (#api_version, #services-issuer-pack_suites, …) — the field list is machine-checked against the schema’s struct definitions by the coverage script in the docs repository.

YAML by convention; a leading { parses as JSON (the schema is identical). Secrets are ${VAR} references substituted from the environment at load — the manifest never carries token values.

unidpp-operator.yaml — the reference deployment
api_version: unidpp.org/v1
deployment:
name: unidpp-reference
profile: reference
base_url: https://registry.unidpp.org
branding:
organization: UniDPP
product_name: UniDPP Reference Deployment
services:
registry:
bind: 127.0.0.1:8390
state_file: registry-journal.jsonl
trust:
bind: 127.0.0.1:8391
state_file: run/trust-journal.jsonl
log:
bind: 127.0.0.1:8392
log_id: unidpp-pilot-log-1
state_file: run/log-journal.jsonl
external_tsa_url: http://timestamp.digicert.com
issuer:
bind: 127.0.0.1:8393
pack_suites: [ecdsa-p256, sm2]
registry_url: http://127.0.0.1:8390
projector:
bind: 127.0.0.1:8394
gateway:
bind: 127.0.0.1:8395
issuer_url: http://127.0.0.1:8393
archive:
bind: 127.0.0.1:8396
sovereignty:
external_calls: external

Four rules the loader enforces before anything starts:

  1. Unknown knobs are loud. A typo is a schema error naming the field and the legal alternatives — never a silent no-op:

    Terminal window
    $ unidpp-config validate bad-manifest.yaml
    unidpp-config: manifest does not match the schema: unknown field `binds`, expected one of `bind`, `admin_token`, `state_file`
  2. Secrets must resolve. ${VAR} substitutes from the environment; an unset reference is an error (secrets never silently resolve to empty). Variable names are ASCII alphanumerics and _; an unterminated ${... is an error.

  3. Semantic validation. Beyond shape: the API version, theme colors, pack suites, and the profile × egress rule (below) are checked.

  4. Profiles constrain. A sovereign deployment with any egress beyond none refuses to validate unless egress_override_reason records why — data-sovereignty claims are validated, not aspirational.

unidpp-config is the manifest CLI. All three subcommands are read-only over the file plus the environment:

Terminal window
$ unidpp-config validate unidpp-operator.yaml
valid: unidpp-reference (profile reference, 7 service(s): ["registry", "trust", "log", "issuer", "projector", "gateway", "archive"])
$ unidpp-config services unidpp-operator.yaml
registry
trust
log
issuer
projector
gateway
archive
$ unidpp-config render-env log unidpp-operator.yaml
UNIDPP_LOG_BIND=127.0.0.1:8392
UNIDPP_LOG_EXTERNAL_TSA_URL=http://timestamp.digicert.com
UNIDPP_LOG_ID=unidpp-pilot-log-1
UNIDPP_LOG_STATE_FILE=run/log-journal.jsonl

render-env <service> <manifest> prints exactly the UNIDPP_* variables the named service’s own environment-based configuration reads, one KEY=value per line in stable order. It fails when the deployment declares no such service block or the name is unknown. stack.sh and tenants/up.sh launch processes from this rendering — manifests drive unmodified binaries.


Type string
Required yes
Constraint must equal unidpp.org/v1
Example api_version: unidpp.org/v1

The manifest’s API version — the only version this generation of the schema speaks. Anything else is refused at load with the offending value named.

Type object (Deployment)
Required yes
Default

The deployment identity and shape. Fields: name, profile, base_url.

Type object (Branding)
Required no
Default organization UniDPP, product name UniDPP Platform, no logo, default theme, empty footer

The whitelabel surface. The console (and any explorer surface) renders its chrome from these values — see the console manual for the preview. Fields: organization, product_name, logo, theme, footer.

Type object (Services)
Required no
Default no services

Per-service configuration blocks. An absent service block means that service is not part of this deployment — the launcher will neither start it nor render its environment. Present blocks: registry, trust, log, issuer, projector, gateway, archive, console.

Type object (Features)
Required no
Default all toggles true

Cross-cutting toggles. Fields: untp_ingest, cddal_negotiation, presentation_render.

Status — declared, not yet consumed. The features block is part of the schema (typed, validated, unknown keys rejected), but as of this writing no service in the running stack reads it and render-env does not emit it. The toggles below describe the intent each knob will govern. Set them only if you accept that they are currently inert.

Type object (Sovereignty)
Required no
Default no residency pinned, egress none, no override reason

The sovereignty declaration: what may leave the box. Fields: data_residency, external_calls, egress_override_reason.


Type string
Required yes
Constraint must not be empty (or whitespace)
Example name: acme-eu

The deployment’s name — the tenant name, unique per operator. It appears in the console’s identity document and dashboard.

Type enum: reference | whitelabel | sovereign
Required yes
Example profile: whitelabel

The deployment shape. See deployment profiles:

  • reference — the hosted reference deployment.
  • whitelabel — an organization’s own branded instance.
  • sovereign — on-prem, jurisdiction-pinned, external calls off (or on only with a recorded reason — see egress_override_reason).

Type string (URL)
Required yes
Example base_url: https://dpp.acme-mobility.example.org

The public base URL of the deployment’s primary surface. Informational for now — used in the console dashboard; the deployment’s own binds and upstreams are declared per service.


Type string
Default UniDPP
Example organization: ACME Mobility

The operating organization’s legal/display name. Rendered in the console chrome (header, login card) and carried by every branded surface.

Type string
Default UniDPP Platform
Example product_name: ACME 产品数字护照

The product name shown in chrome — login, page titles, footers. Unicode is accepted (the sovereign CN tenant ships its product name in Chinese).

Type string (path or data URI), optional
Default absent (no logo; the organization name stands alone)
Example logo: "data:image/svg+xml;base64,..."

A logo the console and explorer serve. Consumed by the console chrome: when set, an <img class="logo"> renders before the organization name.

Type object (Theme)
Default primary #0f62fe, accent #08bdba

Two hex colors. Fields: primary, accent.

Type string
Default #0f62fe
Constraint six-digit hex, #-prefixed (#rrggbb) — anything else is refused

The primary color — headers, badges, the login card border.

Type string
Default #08bdba
Constraint #rrggbb (same as primary)

The accent color.

Validation error when a color is wrong:

Terminal window
unidpp-config: branding.theme.primary must be a #rrggbb hex color (got `red`)

Type object (Footer)
Default no links

Footer links. Fields: legal_url, contact_url.

Type string (URL), optional
Default absent
Example legal_url: https://www.acme-mobility.example.org/legal

The legal/imprint link rendered in the console footer.

Type string (URL), optional
Default absent
Example contact_url: mailto:dpp@acme-mobility.example.org

The contact link rendered in the console footer.


Each block below lists the fields and the environment variables render-env produces. Every service also accepts the common knobs; the service-specific knobs come after.

Type object (ServiceCommon)
Example registry: { bind: 127.0.0.1:8390, admin_token: ${ACME_REGISTRY_TOKEN}, state_file: tenants/acme/registry-journal.jsonl }

The ISO 19135 item + discovery registry. See the registry reference.

Manifest field Environment variable
bind UNIDPP_REGISTRY_BIND
admin_token UNIDPP_REGISTRY_ADMIN_TOKEN
state_file UNIDPP_REGISTRY_STATE_FILE

Type object (ServiceCommon)

The SIGNATIF trust-graph service. See the trust reference.

Manifest field Environment variable
bind UNIDPP_TRUST_BIND
admin_token UNIDPP_TRUST_ADMIN_TOKEN
state_file UNIDPP_TRUST_STATE_FILE

Type object (LogService = common + log_id + external_tsa_url)

The transparency-log anchor service. See the log reference.

Manifest field Environment variable
bind UNIDPP_LOG_BIND
admin_token UNIDPP_LOG_APPEND_TOKEN
state_file UNIDPP_LOG_STATE_FILE
log_id UNIDPP_LOG_ID
external_tsa_url UNIDPP_LOG_EXTERNAL_TSA_URL

Note the token’s variable name: the log calls it the append token (UNIDPP_LOG_APPEND_TOKEN) because appending commitments is its only mutation.

Type string
Default unidpp-log-1
Constraint 1-64 printable ASCII characters
Example log_id: unidpp-pilot-log-1

The log’s identity — the log_id inside every signed tree head and receipt, and what a verifier pins along with the operator key.

Type string (URL), optional
Default absent (no external anchoring)
Example external_tsa_url: http://timestamp.digicert.com

An RFC 3161 timestamp-authority endpoint; every append’s tree head is also anchored there. An unreachable TSA degrades explicitly — the submission failure is recorded, never silently skipped.

Setting this on a sovereign deployment whose external_calls is none is a contradiction the validator refuses, even with an egress override reason on record.

Type object (IssuerService = common + pack_suites + registry_url)

The passport lifecycle issuer. See the issuer reference.

Manifest field Environment variable
bind UNIDPP_ISSUER_BIND
admin_token UNIDPP_ISSUER_ADMIN_TOKEN
state_file UNIDPP_ISSUER_STATE_FILE
pack_suites UNIDPP_ISSUER_PACK_SUITE (comma-joined)
registry_url UNIDPP_ISSUER_REGISTRY_URL

Type list of strings
Default ["ecdsa-p256"]
Constraint at least one suite; no empty entries
Example pack_suites: [ecdsa-p256, sm2] — the co-signature policy

The sovereign pack-signing policy: one suite, or a co-signature set where every listed suite signs the same pack body (a pack verifiable in both circuit-styles). Known suites: ecdsa-p256, sm2. The default EU posture is ecdsa-p256; a Chinese sovereign deployment sets pack_suites: [sm2].

Type string (URL), optional
Default absent (no registry forwarding)
Example registry_url: http://127.0.0.1:8390

The registry the issuer forwards profile registrations and applicability bindings to (its /admin/profiles and /admin/applicability endpoints forward on success). Absent = the issuer keeps profiles locally.

Type object (ServiceCommon)

The lens projection service. See the projector reference.

Manifest field Environment variable
bind UNIDPP_PROJECTOR_BIND
admin_token UNIDPP_PROJECTOR_ADMIN_TOKEN
state_file UNIDPP_PROJECTOR_STATE_FILE

The projector reads passports, profiles, units, and transforms from its own environment (UNIDPP_PROJECTOR_PASSPORTS_DIR, UNIDPP_REGISTRY_URL, …) — those are deployment environment, not manifest fields; see the projector reference for the full list.

Type object (GatewayService = common minus state_file + issuer_url)

The interop gateway. See the gateway reference.

Manifest field Environment variable
bind UNIDPP_GATEWAY_BIND
admin_token UNIDPP_GATEWAY_ADMIN_TOKEN
issuer_url UNIDPP_ISSUER_URL

The gateway keeps no state — it renders, it does not store — so its block declares no state_file.

Type string (URL), optional
Default absent (fixture mode)
Example issuer_url: http://127.0.0.1:8393

The issuer upstream whose passports the gateway renders. Absent = the gateway serves its built-in fixtures only (issuer-upstream-with-fixture-fallback: when the upstream is unreachable the gateway answers from fixtures and says so in the render metadata).

Type object (ServiceCommon)

The Tier-C notarized snapshot service. See the archive reference.

Manifest field Environment variable
bind UNIDPP_ARCHIVE_BIND
admin_token UNIDPP_ARCHIVE_ADMIN_TOKEN
state_file UNIDPP_ARCHIVE_STATE_FILE

The archive’s snapshot directory (UNIDPP_ARCHIVE_SNAPSHOT_DIR) and its log upstream (UNIDPP_LOG_URL) are deployment environment; see the archive reference.

Type object (ServiceCommon)

The admin console. See the console manual.

Manifest field Environment variable
bind UNIDPP_CONSOLE_BIND
admin_token UNIDPP_CONSOLE_ADMIN_TOKEN
state_file UNIDPP_CONSOLE_STATE_FILE

The console’s manifest path is environment, not manifest: UNIDPP_CONSOLE_MANIFEST points the console at the file it manages.

These four knobs appear on every service block (registry, trust, projector, archive, console carry exactly these; log, issuer, gateway add the knobs listed above).

Type string (host:port)
Required yes (on any present service block)
Example bind: 127.0.0.1:9390

The address the service listens on. render-env emits it as the service’s UNIDPP_<SERVICE>_BIND; a bad address makes the service exit at startup.

Type string — an ${VAR} reference, optional
Default absent (open dev mode)
Example admin_token: ${ACME_ISSUER_TOKEN}

The Bearer token guarding the service’s mutations and /admin/* endpoints. Absent = open dev mode — every mutation endpoint answers without authentication. This is the pilot posture; it is not a production posture. The value should always be an ${VAR} reference; inline secrets work at load time but defeat the doctrine (the console editor, for one, is built around references never resolving on screen).

Type string (path), optional
Default absent (state lives in memory only)
Example state_file: run/issuer-journal.jsonl

The service’s append-only JSONL journal — the audit log that replays on start. Absent = no persistence across restarts. Paths are relative to the process working directory; stack.sh and tenants/up.sh launch from the pilot-data root, which is why the reference manifest says registry-journal.jsonl for one service and run/… for others.

Type string (URL), optional
Default absent (the service is loopback-only)
Example public_url: https://registry.unidpp.org

The service’s public hostname when a tunnel or ingress fronts it. The console’s services matrix renders it as the service’s public link; absent renders loopback-only — the console invents nothing. Declaring it does not create the tunnel: provisioning (tunnel token + DNS record) is an operator act, documented in the pilot repo’s README.

The gateway declares no state_file (it is stateless by design); the console’s is accepted by the schema but the console’s own state is the manifest file itself plus in-memory sessions.


Recall the status note: validated, not yet consumed by the running services.

Type boolean
Default true

Accept UNTP ingest on the gateway (POST /untp/ingest — see UNTP interop).

Type boolean
Default true

Serve the CDDAL dictionary form on content negotiation (registry collection reads with Accept: text/cddal — see the registry reference).

Type boolean
Default true

Serve the presentation render on the projector (GET /render — see the projector reference).


Type string, optional
Default absent (no residency pinned)
Example data_residency: EU — or CN, JP

The jurisdiction this deployment pins data to. Displayed in the console dashboard’s egress summary.

Type enum: none | tsa-only | external
Default none

The egress policy — what may leave the box:

  • none — nothing leaves the box.
  • tsa-only — only the RFC 3161 TSA submission (the log’s external_tsa_url).
  • external — upstream fetches permitted (the reference deployment’s posture: the issuer forwards to the registry, the gateway fetches the issuer, the archive anchors into the log).

Type string, optional
Default absent
Example egress_override_reason: CN AICPA timestamp regulation 2026-14

Required when a sovereign profile permits egress beyond none: the recorded, auditable reason. A sovereign manifest with external_calls: tsa-only and no reason is refused:

Terminal window
unidpp-config: profile `sovereign` with external_calls `tsa-only` requires sovereignty.egress_override_reason (recorded, auditable)

With the reason on record, the same manifest validates. The point is honesty: sovereignty claims that contradict the deployment’s actual egress do not load.


The three real deployments of the pilot workspace, all validated:

  • reference — the manifest shown above: seven services, dual pack suites, external egress.
  • whitelabel (acme-eu) — three services (registry 9390, issuer 9393, console 9389), EU residency, ecdsa-p256 packs, egress none, full branding block (theme #7c3aed/#f59e0b, footer links).
  • sovereign (acme-cn) — three services (registry 9590, issuer 9593, console 9589), CN residency, sm2-only packs, egress none — the policy enforced by the validator, not by convention.

See multi-tenant operations for how these run.

The docs repository carries a coverage script that extracts every serde field name from unidpp-config’s schema definitions and checks each has a documented anchor on this page. Run it from the docs repo:

Terminal window
tools/check-manifest-coverage.sh ../unidpp-config/src/lib.rs src/content/docs/operators/manifest.md

It prints one line per field and a final coverage: N/N fields documented. If a knob is added to the schema without documentation, the check fails — this page and the schema move together or not at all.