Explanations

About Anchor Forwarding


Introduction

Anchor forwarding lets a ledger delegate anchor operations to a Bridge. This is useful when anchors are managed by an external system (for example, an external alias directory) while the ledger remains the public API surface and source of authorization decisions.

Before diving in, a brief note on alias directories. An alias directory is a service that maps human‑readable identifiers (like phone numbers or emails) to payment credentials. In deployments where an external alias directory (Bridge) owns anchors, anchor forwarding allows the ledger to forward create/update/sign/drop/read operations to that Bridge while still enforcing access rules and signing responses.

What gets forwarded

Ledger can forward the following anchor actions:

  • Create
  • Update
  • Sign (add a proof)
  • Drop (delete)
  • Get (read one)
  • FindAll (get many with filters)

Forwarding is controlled by configuration per action and, optionally, by a forwarding strategy.

Configuration

Set the Bridge handle that should receive forwarded requests. You can update the active ledger config with CLI, for example using minka ledger update -e.

{
  "forward.anchor.create": "MyBridgeHandle",
  "forward.anchor.update": "MyBridgeHandle",
  "forward.anchor.drop": "MyBridgeHandle",
  "forward.anchor.sign": "MyBridgeHandle",
  "forward.anchor.get": "MyBridgeHandle",
  "forward.anchor.findAll": "MyBridgeHandle"
}

Optionally configure a global or per‑action strategy:

{
  "forward.anchor.strategy": "proxy | fallback | validate | none",
  "forward.anchor.create.strategy": "proxy | validate | none",
  "forward.anchor.update.strategy": "proxy | validate | none",
  "forward.anchor.drop.strategy": "proxy | validate | none",
  "forward.anchor.get.strategy": "proxy | fallback | none",
  "forward.anchor.sign.strategy": "proxy | validate | none",
  "forward.anchor.findAll.strategy": "proxy | fallback | none"
}
  • proxy: Forward the request and do not persist or mutate the record locally (proxy‑only).
  • fallback: For reads/lists, return local data when present; otherwise call the Bridge.
  • validate: Attempt the local DB operation first (without committing) to ensure it would succeed, forward to the Bridge, then persist locally if the Bridge succeeds. If the Bridge fails, do not mutate locally.
  • none: Do not forward for this action.

If a per‑action strategy is not set, the global forward.anchor.strategy is applied. If no strategy is provided, sensible defaults are used internally: reads default to fallback; writes default to validate.

Bridge endpoints

The Bridge must expose the same API surface as the ledger for anchors. Requests are forwarded as‑is (with some headers filtered and a ledger authorization added), and responses are expected to match the ledger Anchor API.

Required endpoints:

  • POST /v2/anchors
  • PUT /v2/anchors/:id
  • DELETE /v2/anchors/:id
  • GET /v2/anchors/:id
  • POST /v2/anchors/:id/proofs (sign)
  • GET /v2/anchors (findAll with filters)

Responses must conform to the ledger Anchor API. See the Anchor section in the API reference.

What the ledger forwards

  • Request body/query params: Forwarded unchanged.
  • Headers: Custom client headers are forwarded except a forbidden set. The original client Authorization (if present) is moved to x-forwarded-authorization and is not sent as authorization to the Bridge.
  • Ledger authorization: The ledger adds its own Bearer JWT in Authorization, signed by the ledger. The JWT contains claims identifying the ledger and the intended Bridge audience.

Forbidden headers that are not forwarded include: authorization, x-ledger, content-type, content-length, accept, accept-encoding, caller, connection, host.

Responses and errors

  • Success: The ledger validates proofs on responses returned directly from the Bridge (proxy/validate modes as applicable). In validate mode, the ledger also performs a local operation and returns the local result after the Bridge confirms success. For listing, the ledger returns the page body from the Bridge when forwarded.
  • Error: If the Bridge returns a structured error, the ledger returns that error (reason/detail/custom) as a ledger error to the client. When a forwarded write fails, no local mutation is persisted.

Error structure example:

  {
    reason: `record.duplicated`,
    detail: 'Alias with handle abc@mail.com already exists'
  }

Check out Anchor API Spec Reference for error payload examples.

Access checks and validation

  • Writes (create/update/sign/drop): The ledger validates authorization before any forwarding occurs. It also performs local pre‑checks to ensure the DB operation would succeed (insert/update/sign/drop) when using the validate strategy.
  • Reads (get/findAll): The ledger validates authorization on returned data. With fallback, the ledger will return local data when available; otherwise it fetches from the Bridge and then validates proofs and access before returning.
  • Schema and proofs: Returned anchors are validated for proofs integrity. In validate strategy, local state is also verified before commit.

Proofs added by the ledger when forwarding

When forwarding write operations, the ledger appends a proof with custom.status = "forwarded" to the outgoing meta before calling the Bridge. The Bridge response must still contain valid proofs; the ledger will verify them before returning to the client (or before persisting, in validate mode).

Flows

Create

Update

Sign

Drop

Get by id/handle

Get many (findAll)

Security notes

  • The client Authorization header is not forwarded as authorization; it is copied to x-forwarded-authorization for the Bridge to inspect if needed.
  • The ledger signs forwarded requests by adding its own Bearer JWT in authorization. Bridges can validate the signature with the ledger public key and may also require OAuth on top if desired.
  • Standard Bridge authentication can be configured separately (e.g., OAuth 2.0). If a Bridge uses OAuth, the ledger will still send its own JWT while preserving the client token in x-forwarded-authorization.
  • All communication between ledger and Bridge must use TLS.

Operational notes

  • Errors from the Bridge are surfaced to clients with ledger signatures and without persisting local mutations.
  • In proxy strategy, records are not stored locally. Reads will come from the Bridge and writes will only affect the Bridge.
  • In validate strategy, local operations are performed only after the Bridge confirms success.