Skip to content

Upgrading IdentityScribe

Upgrade IdentityScribe between versions safely. This guide focuses on breaking changes and the smallest steps to restore a healthy system.

If you haven’t deployed IdentityScribe before, start with the Deployment and Configuration guides instead.

Organized by upgrade path (e.g., v2.x → v3.0).

This section covers upgrades from any v2 release to v3.0.

  • Update environment variables to the unified SCRIBE_* prefix.
  • Migrate renamed config paths (monitoring.telemetry.*monitoring.*, hints.*monitoring.hints.*).
  • Migrate indices configuration from ldap.indices and transcribes.*.ldap.indices to new paths.
  • Migrate HTTP configuration to the unified http {} server and (optionally) named sockets.
  • Update probes and tooling to the new endpoints (/observe/*, /observe/health/*, /metrics, /*z).
  • Update dashboards/queries for the new metric namespace (scribe.* / scribe_*).
  • Update virtual attribute templates ({{current.*}}{{self.*}}).
  • Fix broad queries that now require an explicit type constraint.
  • Update any client-side error-code matching to SCREAMING_SNAKE_CASE.

After deploying, verify:

  • curl -fsS http://localhost:8080/readyz
  • curl -fsS http://localhost:8080/metrics | head
  • curl -fsS http://localhost:8080/observe/doctor | jq
  • curl -fsS http://localhost:8080/observe/config | jq

Some configuration paths were reorganized for consistency. Old paths are ignored.

  • monitoring.telemetry.*monitoring.*
  • hints.*monitoring.hints.*
# Old
monitoring.telemetry.traces.enabled = true
hints.enabled = true
# New
monitoring.traces.enabled = true
monitoring.hints.enabled = true
  • Start IdentityScribe and check the resolved config at /observe/config (secrets are redacted).
  • If you rely on hints endpoints, confirm /observe/hints and /observe/signatures are reachable (or explicitly disabled).

Index configuration moved from ldap.indices to a dedicated indices {} block at root and transcribe levels. Indices control how the local database indexes transcribed data and are transcribe-specific, not LDAP-specific.

Old PathNew Path
ldap.indices.*indices.* (root level)
transcribes.<type>.ldap.indices.*transcribes.<type>.indices.*
Old Environment VariableNew Environment Variable
SCRIBE_LDAP_INDICES(removed - was unused)
(none)SCRIBE_INDICES_PARTIAL_MATCH
(none)SCRIBE_INDICES_VALUE_MATCH
(none)SCRIBE_INDICES_SORTABLE
# Old
ldap {
indices {
partial-match = "cn, sn"
}
}
transcribes {
user {
ldap {
base = "ou=users,o=data"
indices {
value-match = "uid, mail"
}
}
}
}
# New
indices {
partial-match = "cn, sn"
}
transcribes {
user {
ldap {
base = "ou=users,o=data"
}
indices {
value-match = "uid, mail"
}
}
}
  • Start IdentityScribe and check the resolved config at /observe/config.
  • Verify that /observe/indexes shows the expected index configuration for each transcribe.

Environment variable prefixes are standardized. If you still use the old prefixes, your settings will not be applied.

  • IDENTITY_SCRIBE_*SCRIBE_*
  • SCRIBE_TELEMETRY_*SCRIBE_*
Terminal window
# Old
IDENTITY_SCRIBE_READONLY=true
SCRIBE_TELEMETRY_TRACES_ENABLED=true
# New
SCRIBE_READONLY=true
SCRIBE_TRACES_ENABLED=true

See the Configuration guide for naming conventions and examples.

Logger configuration has been consolidated to five canonical loggers with standardized environment variable overrides. Old logger keys are removed.

OldNew
log.EventStore / log.Scribelog.Ingest
log.Settingslog.Config
log.LDAP, log.AsyncSearch, log.TaskExecutorRemoved (use monitoring/wide logs instead)

New canonical loggers:

  • log.SuperVisor (SCRIBE_LOG_SUPERVISOR)
  • log.Ingest (SCRIBE_LOG_INGEST)
  • log.Monitoring (SCRIBE_LOG_MONITORING)
  • log.License (SCRIBE_LOG_LICENSE)
  • log.Config (SCRIBE_LOG_CONFIG)

Example:

log {
level = "info"
Ingest = "debug"
Config = "warn"
Monitoring = "off" # Disable wide-log output entirely
}

See the Log Configuration Reference for the full set of logger settings and format options.

All HTTP traffic (REST API, monitoring endpoints, site/docs) uses a unified HTTP server configured under http {}. You can keep everything on one port, or split traffic using named sockets.

For full details and patterns, see HTTP Server Configuration.

# Everything on one port
http {
host = "0.0.0.0"
port = 8080
}

Migration (split monitoring to an internal port)

Section titled “Migration (split monitoring to an internal port)”
http {
host = "0.0.0.0"
port = 8080
sockets.internal {
host = "localhost"
port = 9001
}
}
monitoring.socket = "internal"

Several operational endpoints were renamed and legacy routes were removed. No aliases are provided, so probes and dashboards must be updated.

OldNew
/status/observe/status
/status/indexes/observe/indexes
/status/hints/observe/hints
/status/signatures/observe/signatures
/healthy/observe/health/ready (JSON) or /readyz (plain text)
/ (metrics)/metrics
/-/* legacy monitoring routesRemoved

Note: /observe now serves interactive OpenAPI documentation for the Observe endpoints. The status JSON moved to /observe/status.

Use the plain-text aliases:

livenessProbe:
httpGet:
path: /livez
readinessProbe:
httpGet:
path: /readyz
startupProbe:
httpGet:
path: /startedz

The monitoring.hints.endpoints.* configuration is no longer supported. Hints endpoints use fixed paths under /observe/*.

  • If you used custom paths, update your tooling to the fixed endpoints:
    • /observe/hints
    • /observe/signatures
  • If you don’t use hints endpoints, disable them explicitly:
monitoring.hints.persistence.enabled = false
monitoring.hints.explain.enabled = false

See the Monitoring Configuration Reference for the full hints configuration.

Metric names are now standardized to the scribe.* namespace (Prometheus auto-converts dotted names to snake_case scribe_*).

  • Update Prometheus queries and Grafana dashboards to use the new names.
  • If you depend on specific label keys/values, verify them against the published reference.

See Observability for the migration mapping and metric inventory.

Virtual attribute templates use new placeholder names.

  • {{current.*}}{{self.*}}
# Old
filter = "(member={{current.entryDN}})"
# New
filter = "(member={{self.entryDN}})"

If legacy syntax is detected, IdentityScribe fails fast on startup with a clear, actionable error.

Broad searches that could span multiple entry types now require an explicit type constraint. Ambiguous queries are rejected early with a clear error.

  • Add a type constraint such as entryType=<type> or an identifying condition like objectClass=... to broad queries.
  • If you rely on wildcard bases or very broad filters, test queries in staging and update filters/config accordingly.

Error codes are now standardized to SCREAMING_SNAKE_CASE. If your clients match on error codes, you must update them.

See Failures for the stable error contract and troubleshooting workflow (including which IDs/headers to include when opening support tickets).

Once the service is running, a quick “is it healthy?” sweep:

Terminal window
curl -fsS http://localhost:8080/readyz
curl -fsS http://localhost:8080/metrics | head
curl -fsS http://localhost:8080/observe/doctor | jq
curl -fsS http://localhost:8080/observe/channels | jq