DEV Community

Cover image for Economic Capability Security in Distributed Financial Systems: Delegation, Replay, Attenuation, and the Confused Deputy
Mayckon Giovani
Mayckon Giovani

Posted on

Economic Capability Security in Distributed Financial Systems: Delegation, Replay, Attenuation, and the Confused Deputy

Abstract

Financial authorization is usually modeled through identities and roles.

A user is authenticated. A service has a role. An operator belongs to a group. A backend checks whether the caller may perform an action.

This model works until economic authority becomes distributed.

A payment orchestrator may be allowed to spend from a treasury account, but only for a specific settlement. A custody service may sign a transaction, but only within an approved amount, asset, destination, and policy window. A downstream service may receive permission to execute a withdrawal without receiving authority to create another withdrawal. A merchant may delegate refund authority to a processor while retaining the ability to revoke it. A risk engine may authorize 500,000 units of provisional exposure without granting permission to consume another 500,000 simply because the same request is replayed.

These are capability problems.

An economic capability is not merely proof that some state is true. It is bounded authority to cause a specific financial state transition.

Once financial authority is represented explicitly, an entire class of security questions becomes visible: replay, delegation, attenuation, confused-deputy attacks, capability laundering, stale authority, double consumption, issuer compromise, transitive privilege expansion, and revocation under partial failure.

This article develops a capability-security model for distributed financial infrastructure. We examine how economic authority should be scoped, delegated, attenuated, consumed, revoked, and audited without allowing downstream systems to manufacture stronger authority than they received.

The core safety requirement is simple:

Authority may move.

It must never grow accidentally.

Authentication is not authorization

Consider a withdrawal endpoint:

POST /withdrawals
Enter fullscreen mode Exit fullscreen mode

The request arrives with an authenticated user.

The backend checks:

user.is_authenticated == true
Enter fullscreen mode Exit fullscreen mode

Then:

user.balance >= amount
Enter fullscreen mode Exit fullscreen mode

Then it executes the withdrawal.

This looks like authorization.

It is mostly authentication plus a balance check.

The system still needs to answer:

Is this user allowed to withdraw this asset?

To this destination?

At this amount?

At this moment?

Using which source of funds?

Under which settlement state?

After which compliance decision?

Against which liquidity allocation?

How many times may the authorization be exercised?

Can another service exercise it on the user's behalf?

Can that service delegate it again?

Authentication answers:

Who is making the request?
Enter fullscreen mode Exit fullscreen mode

Capability security answers:

What exact economic authority does this caller possess?
Enter fullscreen mode Exit fullscreen mode

Those are not interchangeable questions.

Ambient authority

Many financial systems rely on ambient authority.

A service has credentials that allow it to call another service.

For example:

withdrawal-orchestrator
    can call
custody-service
Enter fullscreen mode Exit fullscreen mode

The custody service trusts the caller because:

service_role = withdrawal-orchestrator
Enter fullscreen mode Exit fullscreen mode

This creates broad authority.

Any code executing under that service identity may now potentially request signatures.

The authorization exists because of who the caller is, not because of which specific economic operation it is authorized to perform.

This is ambient authority.

It is convenient.

It is also the foundation of many confused-deputy problems.

Explicit authority

A capability model changes the question.

Instead of:

withdrawal-orchestrator may request signatures
Enter fullscreen mode Exit fullscreen mode

the model becomes:

withdrawal-orchestrator possesses authority
to sign exactly this withdrawal
for at most this amount
to this destination
before this expiration
under this policy
Enter fullscreen mode Exit fullscreen mode

The authority becomes an object.

For example:

EconomicCapability:
    capability_id
    subject
    action
    asset
    amount
    destination
    operation_id
    issued_at
    expires_at
    issuer
Enter fullscreen mode Exit fullscreen mode

The custody service no longer needs to trust the withdrawal orchestrator with general signing authority.

It verifies whether the supplied capability authorizes the exact requested action.

That is a substantial reduction in privilege.

Capabilities represent permission, not identity

A capability can be held by an authenticated service, but the capability itself represents authority.

This distinction is useful.

Suppose Service A receives:

Capability C:
    withdraw 100 USDC
    from account X
    to address Y
Enter fullscreen mode Exit fullscreen mode

Service A may be authenticated as:

service_A
Enter fullscreen mode Exit fullscreen mode

but its ability to execute the withdrawal comes from C.

If Service A calls the custody system with:

withdraw 200 USDC
Enter fullscreen mode Exit fullscreen mode

the request fails even though Service A is perfectly authenticated.

If it asks for:

withdraw 100 USDC
to address Z
Enter fullscreen mode Exit fullscreen mode

the request also fails.

Identity answers who presented the capability.

The capability answers what that identity is allowed to do.

Capability scope

Economic capabilities should be narrowly scoped.

A capability may bind:

action
asset
amount
source
destination
operation
time window
network
counterparty
policy
Enter fullscreen mode Exit fullscreen mode

For example:

action: external_withdrawal
asset: USDC
network: Base
maximum_amount: 100000
source_account: treasury_01
destination: 0xabc...
operation_id: withdrawal_8841
expires_at: 14:05:00
Enter fullscreen mode Exit fullscreen mode

The more irreversible the operation, the narrower the useful scope.

A capability saying:

may transfer funds
Enter fullscreen mode Exit fullscreen mode

is barely better than a role.

A capability saying:

may settle operation 8841 for at most 100,000 USDC
to destination 0xabc on Base before 14:05
Enter fullscreen mode Exit fullscreen mode

contains enough structure to enforce economic intent.

Authority should follow intent

A useful principle is:

capability scope <= business intent scope
Enter fullscreen mode Exit fullscreen mode

If a customer authorized:

transfer 500
to recipient R
Enter fullscreen mode Exit fullscreen mode

no downstream capability should authorize:

transfer up to 1000
to arbitrary recipient
Enter fullscreen mode Exit fullscreen mode

That would increase authority beyond the original intent.

Every derived capability should preserve or reduce the original authority.

Never increase it.

Attenuation

Capability attenuation means deriving a weaker capability from a stronger one.

Suppose Treasury issues:

C0:
    spend up to 1M USDC
    for settlement batch B
Enter fullscreen mode Exit fullscreen mode

The settlement orchestrator may derive:

C1:
    spend up to 250k USDC
    for settlement operation B1
Enter fullscreen mode Exit fullscreen mode

Then a transaction builder derives:

C2:
    spend exactly 247,812 USDC
    to destination D
Enter fullscreen mode Exit fullscreen mode

Authority becomes narrower at every step:

C2 ⊆ C1 ⊆ C0
Enter fullscreen mode Exit fullscreen mode

The important invariant is:

Authority(child) subset_of Authority(parent)
Enter fullscreen mode Exit fullscreen mode

A child capability may restrict.

It must never expand.

Attenuation as an order relation

Let:

C1 <= C0
Enter fullscreen mode Exit fullscreen mode

mean:

every action authorized by C1
is also authorized by C0
Enter fullscreen mode Exit fullscreen mode

Then attenuation requires:

child <= parent
Enter fullscreen mode Exit fullscreen mode

This gives us a useful partial order over authority.

For example:

C0:
    asset ∈ {USDC, USDT}
    amount <= 1M
    destination ∈ approved_destinations

C1:
    asset = USDC
    amount <= 500k
    destination = D1
Enter fullscreen mode Exit fullscreen mode

Then:

C1 <= C0
Enter fullscreen mode Exit fullscreen mode

If instead:

C2:
    amount <= 2M
Enter fullscreen mode Exit fullscreen mode

then:

C2 not<= C0
Enter fullscreen mode Exit fullscreen mode

The derivation must fail.

Authority conservation

Financial systems already enforce conservation of value.

Capability systems need something analogous for authority.

Suppose a capability authorizes spending:

1M
Enter fullscreen mode Exit fullscreen mode

If it can generate two independent children:

C1 = 1M
C2 = 1M
Enter fullscreen mode Exit fullscreen mode

and both can be consumed independently, the system has created 2M of spend authority from 1M.

That is capability inflation.

So attenuation alone is insufficient.

We also need conservation when authority represents consumable capacity.

Splittable capabilities

Suppose:

Parent capacity = 1M
Enter fullscreen mode Exit fullscreen mode

The system may split it into:

Child A = 400k
Child B = 600k
Enter fullscreen mode Exit fullscreen mode

with:

400k + 600k = 1M
Enter fullscreen mode Exit fullscreen mode

A useful invariant is:

sum(active_child_capacity)
+
consumed_parent_capacity
+
remaining_parent_capacity
<=
original_parent_capacity
Enter fullscreen mode Exit fullscreen mode

This turns delegation into a resource-allocation problem.

Delegation

Delegation means transferring some authority to another principal.

For example:

Treasury
    ->
Settlement Orchestrator
        ->
Custody Executor
Enter fullscreen mode Exit fullscreen mode

Treasury may delegate permission to spend from a settlement reserve.

The orchestrator may delegate only the exact amount required for one transaction.

The custody executor receives execution authority without receiving treasury-wide authority.

This is least authority expressed structurally.

Delegation chain

A delegated capability should preserve lineage.

For example:

C0 issued by Treasury
    ->
C1 derived by Settlement Engine
        ->
C2 delegated to Custody
Enter fullscreen mode Exit fullscreen mode

Each capability contains:

parent_capability_id
issuer
delegate
constraints
Enter fullscreen mode Exit fullscreen mode

This creates an authority graph.

It allows the system to answer:

Where did this permission come from?
Enter fullscreen mode Exit fullscreen mode

and:

Which stronger authority allowed it to exist?
Enter fullscreen mode Exit fullscreen mode

Transitive delegation

Delegation becomes dangerous when recipients can delegate again.

Suppose:

Treasury -> Service A
Enter fullscreen mode Exit fullscreen mode

Treasury intends Service A to execute a payment.

But Service A can derive:

Service A -> Service B
Enter fullscreen mode Exit fullscreen mode

Then Service B derives:

Service B -> Service C
Enter fullscreen mode Exit fullscreen mode

Eventually authority reaches code Treasury never intended to trust.

Capability models should therefore include delegation constraints.

For example:

delegation_depth = 0
Enter fullscreen mode Exit fullscreen mode

means:

holder may exercise
holder may not delegate
Enter fullscreen mode Exit fullscreen mode

Or:

delegation_depth <= 2
Enter fullscreen mode Exit fullscreen mode

limits propagation.

Delegation rights are themselves authority

A capability may distinguish:

use
delegate
attenuate
split
revoke
Enter fullscreen mode Exit fullscreen mode

These are different permissions.

Someone allowed to exercise a capability does not automatically need permission to mint child capabilities.

For example:

Custody Executor:
    may_use = true
    may_delegate = false
Enter fullscreen mode Exit fullscreen mode

This reduces authority propagation.

The confused deputy

The confused-deputy problem appears when a privileged service performs an action using its own authority on behalf of a less-privileged caller without correctly binding the action to the caller's permission.

Financial systems are full of potential deputies.

Consider a custody service.

It has broad authority over treasury keys.

A withdrawal service sends:

sign transaction T
Enter fullscreen mode Exit fullscreen mode

If custody checks only:

caller == withdrawal-service
Enter fullscreen mode Exit fullscreen mode

then the withdrawal service can potentially make custody sign any transaction accepted by that interface.

Custody has become a deputy using its own authority.

The correct design requires the withdrawal service to present a capability proving:

transaction T is specifically authorized
Enter fullscreen mode Exit fullscreen mode

Custody should not spend its own ambient authority merely because the caller has the right service identity.

Confused-deputy example

Suppose Service A is allowed to request refunds.

Service B owns treasury execution.

A request arrives:

refund customer 500
Enter fullscreen mode Exit fullscreen mode

Service A sends to B:

transfer 500 to destination X
Enter fullscreen mode Exit fullscreen mode

If B trusts A generally, an attacker compromising A may change X.

A proof-carrying capability might instead bind:

refund_id
amount
asset
destination
original_payment
Enter fullscreen mode Exit fullscreen mode

Service B verifies that the requested transfer exactly matches the authorized refund.

Now A can orchestrate.

It cannot redefine the economic intent.

Capability laundering

Another failure mode occurs when restricted authority passes through a subsystem and emerges as unrestricted authority.

Suppose:

C:
    may transfer 100 USDC
    to destination A
Enter fullscreen mode Exit fullscreen mode

Service X consumes this capability and produces:

authorization_status = approved
Enter fullscreen mode Exit fullscreen mode

Service Y later interprets:

approved == arbitrary transfer allowed
Enter fullscreen mode Exit fullscreen mode

The destination restriction disappeared.

Authority was laundered through a lossy representation.

This is the capability equivalent of collapsing settlement semantics into status=completed.

Semantic preservation across boundaries

Every service boundary should preserve relevant authorization constraints.

If input authority says:

asset = USDC
amount <= 100
destination = A
Enter fullscreen mode Exit fullscreen mode

the next layer cannot reduce it to:

authorized = true
Enter fullscreen mode Exit fullscreen mode

unless that boolean is scoped to a specific immutable operation already containing those constraints.

Otherwise downstream code receives more semantic freedom than upstream policy intended.

Bind authority to operation identity

A strong capability should normally reference:

business_operation_id
Enter fullscreen mode Exit fullscreen mode

For example:

operation_id = withdrawal_8841
Enter fullscreen mode Exit fullscreen mode

Now the capability cannot authorize another withdrawal even if amount, asset, and destination happen to match.

This protects against authority reuse across business intents.

Replay attacks

Suppose a capability authorizes:

withdraw 500 USDC
Enter fullscreen mode Exit fullscreen mode

The operation succeeds.

An attacker submits the same capability again.

If signature verification is the only check, the capability remains perfectly authentic.

The second request may also succeed.

Cryptographic validity does not imply freshness.

Replay prevention must be explicit.

Nonces

A capability may contain a unique nonce:

nonce = 8f12...
Enter fullscreen mode Exit fullscreen mode

The execution boundary records:

nonce consumed
Enter fullscreen mode Exit fullscreen mode

A repeated capability fails.

Conceptually:

if consumed(nonce):
    reject replay
else:
    atomically mark consumed
    execute
Enter fullscreen mode Exit fullscreen mode

The word atomically is doing serious work here.

Check-then-act is unsafe

This is incorrect:

1. query nonce table
2. nonce unused
3. execute withdrawal
4. mark nonce used
Enter fullscreen mode Exit fullscreen mode

Two concurrent requests can both observe:

unused
Enter fullscreen mode Exit fullscreen mode

and both execute.

The consumption must be part of the authoritative state transition.

For example:

BEGIN

INSERT consumed_nonce
    IF NOT EXISTS

reserve funds

create withdrawal

COMMIT
Enter fullscreen mode Exit fullscreen mode

If another transaction tries the same nonce, it fails.

Idempotency and replay are related but different

Idempotency answers:

If the same business request arrives again,
can we return the original result?
Enter fullscreen mode Exit fullscreen mode

Replay protection answers:

Can the same authority create another effect?
Enter fullscreen mode Exit fullscreen mode

Suppose a withdrawal succeeds but the caller times out.

It retries.

The system should not respond:

replay attack
Enter fullscreen mode Exit fullscreen mode

if the retry refers to the same operation.

It should return:

withdrawal already executed
Enter fullscreen mode Exit fullscreen mode

Therefore the capability should bind:

operation_id
Enter fullscreen mode Exit fullscreen mode

and the execution service should preserve the operation result.

Stable economic identity

A useful model:

operation_id:
    identifies economic intent

capability_id:
    identifies authority

attempt_id:
    identifies execution attempt
Enter fullscreen mode Exit fullscreen mode

A retry may create a new attempt.

It should not create a new economic operation.

Nor should it consume the capability twice.

One-shot capabilities

Some authority should be exercised exactly once.

For example:

execute withdrawal W
Enter fullscreen mode Exit fullscreen mode

The state machine is:

Issued
    ->
Consumed
Enter fullscreen mode Exit fullscreen mode

with optional:

Issued
    ->
Revoked
Enter fullscreen mode Exit fullscreen mode

Once consumed:

Consumed is terminal
Enter fullscreen mode Exit fullscreen mode

The capability remains historically valid as evidence.

It no longer grants authority.

Metered capabilities

Other capabilities represent divisible capacity.

Example:

may settle up to 1M today
Enter fullscreen mode Exit fullscreen mode

This is not one-shot.

It is metered.

The system must track:

authorized_amount
consumed_amount
remaining_amount
Enter fullscreen mode Exit fullscreen mode

Invariant:

consumed_amount <= authorized_amount
Enter fullscreen mode Exit fullscreen mode

Each consumption must be atomic.

Partial consumption

Suppose:

capability capacity = 1M
Enter fullscreen mode Exit fullscreen mode

One operation consumes:

300k
Enter fullscreen mode Exit fullscreen mode

Remaining:

700k
Enter fullscreen mode Exit fullscreen mode

Another consumes:

500k
Enter fullscreen mode Exit fullscreen mode

Remaining:

200k
Enter fullscreen mode Exit fullscreen mode

A request for:

300k
Enter fullscreen mode Exit fullscreen mode

must fail.

This sounds trivial.

It stops being trivial when consumption is distributed across services.

Central consumption authority

One solution is to maintain a single authoritative capability ledger.

Every consumer reserves capability capacity through that ledger.

For example:

CapabilityLedger:
    authorized: 1M
    reserved: 200k
    consumed: 600k
    remaining: 200k
Enter fullscreen mode Exit fullscreen mode

This prevents double consumption.

The tradeoff is coordination.

Distributed capability spending

If several services must consume the same capability without central coordination, correctness becomes much harder.

Each service may believe capacity remains.

This is essentially double spending of authority.

Financial capability systems should be very cautious about distributing mutable consumable authority without a clear ownership protocol.

One clean solution is to split capability capacity into non-overlapping child capabilities before distribution.

Instead of:

shared capability = 1M
Enter fullscreen mode Exit fullscreen mode

issue:

Service A capability = 400k
Service B capability = 600k
Enter fullscreen mode Exit fullscreen mode

Now consumption domains are isolated.

Capability partitioning

This mirrors financial reserve segmentation.

Shared authority maximizes flexibility.

Partitioned authority improves fault isolation.

If Service A is compromised, the maximum spend is:

400k
Enter fullscreen mode Exit fullscreen mode

not:

1M
Enter fullscreen mode Exit fullscreen mode

Capability allocation therefore becomes part of blast-radius engineering.

Capability amplification

A dangerous derivation bug may accidentally create stronger authority.

Suppose:

Parent:
    amount <= 100
Enter fullscreen mode Exit fullscreen mode

A child derivation function mistakenly interprets missing amount as:

unlimited
Enter fullscreen mode Exit fullscreen mode

Then:

attenuate(parent, child_constraints)
Enter fullscreen mode Exit fullscreen mode

has actually amplified authority.

This is why constraints should not rely on ambiguous omission semantics.

Missing should usually mean:

inherit parent constraint
Enter fullscreen mode Exit fullscreen mode

not:

remove constraint
Enter fullscreen mode Exit fullscreen mode

Deny by construction

A safe attenuation API should make expansion impossible.

For example:

child.amount =
    min(parent.amount, requested_amount)
Enter fullscreen mode Exit fullscreen mode

not:

child.amount =
    requested_amount
Enter fullscreen mode Exit fullscreen mode

Similarly:

child.expiry =
    min(parent.expiry, requested_expiry)
Enter fullscreen mode Exit fullscreen mode

Destination sets should satisfy:

child.destinations subset_of parent.destinations
Enter fullscreen mode Exit fullscreen mode

Asset sets:

child.assets subset_of parent.assets
Enter fullscreen mode Exit fullscreen mode

Formal attenuation property

Let Perm(C) be the set of actions capability C permits.

Then:

Attenuate(C, r) = C'
Enter fullscreen mode Exit fullscreen mode

must satisfy:

Perm(C') subset_of Perm(C)
Enter fullscreen mode Exit fullscreen mode

For all valid attenuation requests r.

This is a useful property for formal verification.

It is much stronger than unit-testing a few examples.

Capability composition

Sometimes an operation requires several independent capabilities.

A treasury transfer may require:

funding capability
+
liquidity capability
+
compliance capability
+
custody capability
Enter fullscreen mode Exit fullscreen mode

The final operation is valid only if every required authority exists.

Conceptually:

Execute(T)
requires
    C_funds
    AND C_liquidity
    AND C_compliance
    AND C_custody
Enter fullscreen mode Exit fullscreen mode

This limits single-service authority.

Composition should intersect authority

When several capabilities combine, the result should generally reflect the intersection of their permissions.

Suppose:

Funds:
    max 1M

Liquidity:
    max 700k

Compliance:
    max 500k
Enter fullscreen mode Exit fullscreen mode

The operation cannot be:

1M
Enter fullscreen mode Exit fullscreen mode

The effective limit is:

500k
Enter fullscreen mode Exit fullscreen mode

because all constraints must hold.

Threshold authorization

Some capabilities represent authority from independent parties.

For example:

3 treasury signers
2 required
Enter fullscreen mode Exit fullscreen mode

or:

Risk approval
Treasury approval
Custody approval
Enter fullscreen mode Exit fullscreen mode

This is different from attenuation.

It is threshold composition.

A high-value operation may require:

k-of-n authorities
Enter fullscreen mode Exit fullscreen mode

before execution.

This reduces single-point compromise.

Threshold is not automatically safe

Suppose three approval services exist.

All three depend on the same administrator account.

Nominally:

3 independent approvals
Enter fullscreen mode Exit fullscreen mode

Operationally:

1 shared compromise domain
Enter fullscreen mode Exit fullscreen mode

Authority independence has the same hidden-correlation problem we saw with liquidity and guarantees.

Security topology matters.

Context binding

A capability should often bind environmental context.

For example:

network = Base
chain_id = 8453
contract = X
Enter fullscreen mode Exit fullscreen mode

Without this, a signature intended for one context may be replayed elsewhere.

This is particularly relevant in blockchain systems.

The economic intent should include enough domain separation to prevent cross-context reuse.

Asset identity

Never bind authority merely to:

symbol = USDC
Enter fullscreen mode Exit fullscreen mode

Symbols are presentation metadata.

A capability should bind to canonical asset identity.

For example:

network
contract_address
asset_namespace
Enter fullscreen mode Exit fullscreen mode

Otherwise a token sharing the same symbol could satisfy the capability superficially.

Economic authorization must bind to the actual asset.

Destination identity

Likewise, destination should be canonicalized.

Possible forms include:

bank_account_id
wallet_address
merchant_id
beneficiary_id
Enter fullscreen mode Exit fullscreen mode

The capability should bind to the destination identifier used by execution.

If policy approved beneficiary B, execution should not reinterpret a free-text alias later.

Amount semantics

Amount should include:

asset
minor-unit scale
rounding rules
fee semantics
Enter fullscreen mode Exit fullscreen mode

Suppose capability authorizes:

100 USDC
Enter fullscreen mode Exit fullscreen mode

Does that include network fee?

Can execution send:

100 + fee
Enter fullscreen mode Exit fullscreen mode

from treasury?

Can fee volatility increase spend beyond authorized amount?

Capabilities need explicit fee policy.

For example:

principal <= 100
fee <= 2
total <= 102
Enter fullscreen mode Exit fullscreen mode

Otherwise fee handling becomes authority expansion.

Time authority

Capabilities often have expiration:

expires_at
Enter fullscreen mode Exit fullscreen mode

But expiration depends on clock semantics.

Which clock?

Execution node clock?

Database clock?

Issuer clock?

Distributed clock skew can create inconsistent decisions.

For high-value authority, expiration validation should use a trusted time source or bounded clock skew.

The system should know the maximum tolerated skew.

Not-before constraints

A capability may also have:

not_before
Enter fullscreen mode Exit fullscreen mode

This prevents premature execution.

Useful for scheduled settlements, withdrawal windows, or delayed releases.

Again:

not_before <= execution_time <= expires_at
Enter fullscreen mode Exit fullscreen mode

must use clearly defined time semantics.

Revocation

Expiration handles planned authority lifetime.

Revocation handles authority that must end early.

Reasons include:

settlement reversed
customer account frozen
destination compromised
policy changed
issuer compromised
operator mistake
Enter fullscreen mode Exit fullscreen mode

A capability model without revocation assumes every issued permission remains safe until expiry.

That assumption gets uncomfortable quickly around money.

Revocation models

One option is online validation.

Every execution asks:

is capability still valid?
Enter fullscreen mode Exit fullscreen mode

This gives fast revocation.

It also creates a dependency on the revocation service.

If it is unavailable, the system must choose fail-open or fail-closed.

For financial authority, fail-open can be an expensive personality trait.

Short-lived capabilities

Another strategy is issuing capabilities with very short lifetimes.

For example:

expires in 30 seconds
Enter fullscreen mode Exit fullscreen mode

Revocation becomes less critical because authority naturally decays quickly.

This works well when capabilities can be regenerated cheaply.

It works poorly for offline or long-running workflows.

Revocation epochs

A subject may carry a revocation epoch.

For example:

account_authority_epoch = 17
Enter fullscreen mode Exit fullscreen mode

The capability contains:

epoch = 17
Enter fullscreen mode Exit fullscreen mode

If the account is frozen:

account_authority_epoch = 18
Enter fullscreen mode Exit fullscreen mode

All older capabilities become invalid.

This revokes an entire class of authority efficiently.

Epoch granularity matters

A global epoch revokes everything.

That may be too broad.

A system may maintain epochs for:

account
asset
action class
provider
policy
Enter fullscreen mode Exit fullscreen mode

For example:

withdrawal_epoch
Enter fullscreen mode Exit fullscreen mode

can revoke withdrawals without invalidating internal transfers.

This is more precise.

Revocation under partition

Suppose a capability was issued.

Then the revocation service becomes unreachable.

A downstream executor cannot know whether the capability was revoked.

This is a partial-observability problem again.

The system needs a policy.

Possible behavior:

high-risk action:
    fail closed

low-risk action:
    allow if capability is very fresh

emergency mode:
    require secondary approval
Enter fullscreen mode Exit fullscreen mode

Revocation semantics should be designed before the network partition, not improvised during it.

Offline capability risk

The more independently a capability can be verified, the harder immediate revocation becomes.

This is a fundamental tradeoff.

Offline verification improves availability.

Online revocation improves control.

There is no magic configuration that maximizes both.

The system must choose based on consequence.

Capability freshness

A capability can be authentic and unrevoked but still based on stale state.

Suppose:

capability:
    withdraw 100k
Enter fullscreen mode Exit fullscreen mode

issued when balance was:

150k
Enter fullscreen mode Exit fullscreen mode

Another operation consumes:

100k
Enter fullscreen mode Exit fullscreen mode

The capability is still authentic.

It is now economically stale.

This is why capabilities should either reserve capacity or bind to state versions.

Reservation-backed capability

A stronger capability is issued only after reserving the underlying economic resource.

For example:

reserve 100k
issue capability referencing reservation
Enter fullscreen mode Exit fullscreen mode

Now another operation cannot consume the same funds.

The capability carries exclusive authority over reserved capacity.

This is much safer than issuing a statement about unreserved balance.

Capability-backed escrow

For larger workflows, authority may map to escrowed value.

For example:

SettlementCapability:
    escrow_account
    reserved_amount
    destination
Enter fullscreen mode Exit fullscreen mode

Execution spends only from escrow.

This isolates authority from changes elsewhere in the account.

The cost is reduced liquidity flexibility.

Again, resilience versus efficiency.

Capability laundering through queues

Messaging systems create another subtle problem.

Suppose Service A validates capability C and enqueues:

execute withdrawal W
Enter fullscreen mode Exit fullscreen mode

Service B later consumes the queue message.

If the queue message contains only:

withdrawal_id
Enter fullscreen mode Exit fullscreen mode

the proof context is lost.

Service B trusts that A must have validated correctly.

That is ambient authority reintroduced through messaging.

The queued command should carry:

capability reference
proof context
authorization decision identity
Enter fullscreen mode Exit fullscreen mode

or reference an immutable authorized operation record.

Authority at rest

Once an authorized operation is persisted, the database row itself may become the capability.

For example:

Withdrawal:
    id
    status = AUTHORIZED
Enter fullscreen mode Exit fullscreen mode

Any worker that can transition it may now execute economic authority.

This is not necessarily wrong.

But authorization state becomes security-critical.

The system must control who can create AUTHORIZED records and under what proof.

Database privilege escalation

Suppose an internal tool allows operators to edit withdrawal state.

An operator changes:

PENDING_REVIEW
Enter fullscreen mode Exit fullscreen mode

to:

AUTHORIZED
Enter fullscreen mode Exit fullscreen mode

The worker sees the row and executes.

The operator has effectively minted a financial capability through database mutation.

This is why economically meaningful state transitions should happen through domain operations, not arbitrary row editing.

Manual authority

Operators legitimately need emergency powers.

Those powers should be explicit.

For example:

ManualOverrideCapability:
    operator
    operation
    action
    amount
    reason
    second_approver
    expires_at
Enter fullscreen mode Exit fullscreen mode

Emergency access is still capability-based authority.

It is simply issued under a different policy.

Break-glass capabilities

A break-glass capability may allow emergency action outside normal policy.

It should have stronger audit requirements:

short lifetime
high visibility
mandatory reason
multi-party approval
automatic post-incident review
Enter fullscreen mode Exit fullscreen mode

The important principle is that emergency authority becomes more observable as it becomes more powerful.

Not less.

Capability graphs

Once delegation exists, authority forms a graph.

For example:

Treasury Root Authority
        |
        v
Settlement Batch Capability
        |
        +------> Payment A
        |
        +------> Payment B
        |
        +------> Payment C
Enter fullscreen mode Exit fullscreen mode

Or:

Customer Intent
    |
    v
Withdrawal Authorization
    |
    v
Custody Signing Capability
    |
    v
Chain Execution Capability
Enter fullscreen mode Exit fullscreen mode

This graph is useful for security analysis.

Authority blast radius

If capability C is compromised, the graph tells us:

which descendant authorities remain usable?
Enter fullscreen mode Exit fullscreen mode

A broad capability near the root has large blast radius.

A narrow leaf capability has small blast radius.

This gives us an architectural metric:

authority blast radius
Enter fullscreen mode Exit fullscreen mode

not merely permission count.

Dominators in authority graphs

Suppose every high-value withdrawal capability descends from one treasury capability.

That capability dominates the authority graph.

Compromising it compromises the whole path.

Graph analysis can identify such concentration.

This is analogous to shared failure domains in economic contagion.

Security authority also has concentration risk.

Capability concentration

A platform may have thousands of microservices but one credential capable of:

sign any treasury transaction
Enter fullscreen mode Exit fullscreen mode

Operational architecture looks distributed.

Authority architecture is centralized.

That is a meaningful security mismatch.

Least authority

The principle of least privilege becomes sharper as least authority.

A service should receive:

only the economic capability required
for the current operation
for the shortest useful period
over the smallest useful amount
Enter fullscreen mode Exit fullscreen mode

This is more concrete than assigning generic roles.

Privilege escalation

Privilege escalation occurs when an actor obtains authority stronger than intended.

In capability systems this may happen through:

bad attenuation
scope confusion
claim substitution
capability replay
delegation bugs
issuer compromise
context confusion
Enter fullscreen mode Exit fullscreen mode

Each path should be threat-modeled explicitly.

Claim substitution

Suppose the system expects a capability proving:

withdrawal_authorized
Enter fullscreen mode Exit fullscreen mode

but accepts any signed claim from the same issuer.

An attacker presents:

internal_transfer_authorized
Enter fullscreen mode Exit fullscreen mode

If claim type is not bound into verification, signature validity may pass.

The wrong semantic claim gets substituted.

Every capability signature must cover the complete canonical object, including action type.

Audience restriction

A capability intended for Custody Service should not necessarily be usable by another service.

Bind:

audience = custody-service
Enter fullscreen mode Exit fullscreen mode

Then another consumer rejects it.

This prevents authority from being replayed across service boundaries.

Purpose restriction

Audience identifies who may consume the capability.

Purpose identifies why.

For example:

purpose = settlement_execution
Enter fullscreen mode Exit fullscreen mode

This prevents a capability issued for settlement from being repurposed for collateral transfer.

Context must be explicit.

Capability wrapping

Sometimes a service needs to transform authority into another representation.

For example:

EconomicCapability
    ->
blockchain transaction signature
Enter fullscreen mode Exit fullscreen mode

The transformation should be one-way in authority.

The signature authorizes one concrete transaction.

It should not allow recovery of general custody authority.

This is a healthy authority collapse.

Signing as terminal attenuation

A fully specified transaction signature can be viewed as an extremely narrow capability:

execute exactly these transaction bytes
Enter fullscreen mode Exit fullscreen mode

Once the transaction is fixed, many degrees of freedom disappear.

This is desirable.

The closer execution gets, the narrower authority should become.

Late binding

Sometimes destination or amount cannot be known early.

Capability design then needs bounded late binding.

For example:

destination in merchant_set
amount <= 100k
Enter fullscreen mode Exit fullscreen mode

Later the orchestrator selects:

destination = merchant_42
amount = 72k
Enter fullscreen mode Exit fullscreen mode

This is safe if selection remains inside the original constraint set.

Late binding should narrow authority, not reopen previously fixed fields.

Capability race conditions

Two services may try to consume the same remaining capacity simultaneously.

Suppose:

remaining = 100k
Enter fullscreen mode Exit fullscreen mode

Service A wants:

70k
Enter fullscreen mode Exit fullscreen mode

Service B wants:

60k
Enter fullscreen mode Exit fullscreen mode

Both individually fit when read.

Together:

130k
Enter fullscreen mode Exit fullscreen mode

does not.

Capability consumption requires serialization or atomic conditional updates.

For example:

UPDATE capabilities
SET consumed = consumed + 70000
WHERE
    id = C
    AND authorized - consumed >= 70000
Enter fullscreen mode Exit fullscreen mode

Only one conflicting transaction can succeed once capacity falls below the requested amount.

Durable consumption

Capability consumption must survive crashes.

Suppose:

capability marked consumed
Enter fullscreen mode Exit fullscreen mode

then the external request fails before submission.

Can it be retried?

The answer depends on state machine design.

A safer flow separates:

Reserved
Executing
Consumed
Released
Enter fullscreen mode Exit fullscreen mode

For example:

Issued
    ->
Reserved
        ->
Consumed
Enter fullscreen mode Exit fullscreen mode

or:

Reserved
    ->
Released
Enter fullscreen mode Exit fullscreen mode

after safe failure.

Unknown execution outcome

The hardest case:

capability reserved
external request sent
timeout
Enter fullscreen mode Exit fullscreen mode

The system does not know whether the economic action occurred.

It must not:

release capability
Enter fullscreen mode Exit fullscreen mode

immediately.

That could permit duplicate execution.

The capability enters:

ExecutionUnknown
Enter fullscreen mode Exit fullscreen mode

until reconciliation establishes the outcome.

Capability state therefore inherits the same unresolved semantics as settlement state.

Capability state machine

A more realistic lifecycle:

Issued
    |
    v
Reserved
    |
    v
Executing
   / \
  /   \
 v     v
Consumed   ExecutionUnknown
               |
          +----+----+
          |         |
          v         v
      Consumed    Released
Enter fullscreen mode Exit fullscreen mode

And separately:

Issued -> Revoked
Reserved -> RevokedBeforeExecution
Enter fullscreen mode Exit fullscreen mode

depending on policy.

Revocation after reservation

If a capability has reserved funds but has not executed, revocation may release the reservation.

But if execution may already have started, revocation cannot simply undo reality.

The system must inspect execution state.

Again:

revocation != rollback
Enter fullscreen mode Exit fullscreen mode

A familiar pattern by now.

Capability ledger

Financial systems may benefit from an explicit capability ledger.

Not a financial ledger.

An authority ledger.

It records:

issued authority
delegated authority
reserved authority
consumed authority
revoked authority
expired authority
Enter fullscreen mode Exit fullscreen mode

This creates an auditable history of who could have done what.

Authority reconciliation

Just as balances are reconciled, capability capacity may need reconciliation.

For a metered capability:

authorized =
    remaining
    + reserved
    + consumed
    + revoked_unused
Enter fullscreen mode Exit fullscreen mode

subject to the capability's semantics.

If totals do not reconcile, authority has disappeared or multiplied.

Neither is a good sign.

Capability observability

Useful metrics include:

active capability value
capability value by issuer
capability value by action
delegation depth
expired but unconsumed authority
revocation lag
execution-unknown capability value
largest authority concentration
break-glass capability usage
Enter fullscreen mode Exit fullscreen mode

These expose security state in economic units.

That is often much more meaningful than counting tokens.

Value-at-authority

Suppose two credentials are compromised.

Credential A can read customer names.

Credential B can issue 50M of withdrawal capability.

Both are security incidents.

Their economic blast radius is obviously different.

Capability architecture allows direct measurement:

value_at_authority
Enter fullscreen mode Exit fullscreen mode

or more precisely:

maximum economic effect currently authorized
Enter fullscreen mode Exit fullscreen mode

This is useful for incident prioritization.

Issuer compromise

Suppose the capability issuer is compromised.

An attacker can create validly signed capabilities.

Verification succeeds.

This means issuer trust must be bounded.

An issuer should have its own issuance limits:

max capability value
allowed actions
allowed assets
allowed destinations
maximum lifetime
Enter fullscreen mode Exit fullscreen mode

The issuer itself should not possess unlimited authority merely because it creates tokens representing authority.

Issuance budget

For example:

Availability Engine:
    may issue <= 5M aggregate withdrawal capability

Treasury Engine:
    may issue <= 50M settlement capability
Enter fullscreen mode Exit fullscreen mode

Issuance capacity can itself be backed by reservations.

Now compromising the issuer does not automatically expose the entire platform.

Root authority

Eventually capabilities originate from some root authority.

Examples:

customer mandate
treasury mandate
contractual authorization
governance decision
custody key policy
Enter fullscreen mode Exit fullscreen mode

The root should be rare and strongly protected.

Most production operations should use attenuated descendants.

The root should not circulate through ordinary services.

Capability roots and institutional authority

A financial capability is ultimately meaningful because some institution recognizes the authority behind it.

Cryptographic signatures enforce technical authenticity.

The economic system gives them meaning.

For example:

Customer signed intent
Enter fullscreen mode Exit fullscreen mode

matters because the platform accepts that customer as holder of the relevant funds.

Treasury approval
Enter fullscreen mode Exit fullscreen mode

matters because corporate policy gives treasury that authority.

Capability security therefore combines cryptographic structure with institutional semantics.

Formal properties

Several properties are worth stating explicitly.

Attenuation:

Perm(child) subset_of Perm(parent)
Enter fullscreen mode Exit fullscreen mode

Conservation:

consumed
+ reserved
+ remaining
<= authorized
Enter fullscreen mode Exit fullscreen mode

Replay safety:

one one-shot capability
cannot create more than one economic effect
Enter fullscreen mode Exit fullscreen mode

Scope safety:

Execute(action, capability)
implies
action in Perm(capability)
Enter fullscreen mode Exit fullscreen mode

Delegation safety:

Delegated(child, parent)
implies
Perm(child) subset_of Perm(parent)
Enter fullscreen mode Exit fullscreen mode

Expiry safety:

now > expires_at
implies
not Executable(capability)
Enter fullscreen mode Exit fullscreen mode

Audience safety:

consumer != audience
implies
not Executable(capability)
Enter fullscreen mode Exit fullscreen mode

State binding:

required_state_version != current_state_version
implies
Revalidate
Enter fullscreen mode Exit fullscreen mode

These are good candidates for model checking or formal verification.

A Rust sketch

A simplified capability type:

#[derive(Debug, Clone)]
pub struct EconomicCapability {
    pub capability_id: String,
    pub parent_id: Option<String>,

    pub holder: String,
    pub audience: String,

    pub action: Action,
    pub asset: AssetId,

    pub max_amount: u128,
    pub consumed_amount: u128,

    pub source_account: String,
    pub destination: DestinationConstraint,

    pub operation_id: Option<String>,

    pub not_before: u64,
    pub expires_at: u64,

    pub delegation_depth_remaining: u8,
    pub nonce: [u8; 32],

    pub issuer: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Action {
    InternalTransfer,
    ExternalWithdrawal,
    Settlement,
    Refund,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AssetId {
    pub namespace: String,
    pub network: String,
    pub identifier: String,
}

#[derive(Debug, Clone)]
pub enum DestinationConstraint {
    Exact(String),
    AllowList(Vec<String>),
}
Enter fullscreen mode Exit fullscreen mode

The representation is not the difficult part.

The semantics are.

Attenuation function

Conceptually:

pub fn attenuate(
    parent: &EconomicCapability,
    requested_amount: u128,
    destination: DestinationConstraint,
    requested_expiry: u64,
) -> Result<EconomicCapability, CapabilityError> {
    if requested_amount > parent.remaining_amount() {
        return Err(CapabilityError::AuthorityExpansion);
    }

    if requested_expiry > parent.expires_at {
        return Err(CapabilityError::AuthorityExpansion);
    }

    if !parent.destination.contains(&destination) {
        return Err(CapabilityError::AuthorityExpansion);
    }

    if parent.delegation_depth_remaining == 0 {
        return Err(CapabilityError::DelegationForbidden);
    }

    // Construct child with strictly narrower authority.
    todo!()
}
Enter fullscreen mode Exit fullscreen mode

The production implementation would need atomic reservation of parent capacity as part of child issuance.

Otherwise two concurrent attenuations can over-allocate the parent.

Safe derivation requires reservation

Suppose:

Parent remaining: 1M
Enter fullscreen mode Exit fullscreen mode

Two concurrent requests derive:

Child A: 700k
Child B: 700k
Enter fullscreen mode Exit fullscreen mode

Both read:

remaining = 1M
Enter fullscreen mode Exit fullscreen mode

Both appear valid.

Together they create:

1.4M
Enter fullscreen mode Exit fullscreen mode

Therefore child creation must consume or reserve parent authority atomically.

Capability derivation is itself an economic state transition.

Authority cannot be treated as metadata

This is the broader lesson.

If capability issuance can increase economic authority, it belongs in the same category as balance mutation.

It requires:

atomicity
idempotency
durability
auditability
reconciliation
Enter fullscreen mode Exit fullscreen mode

Treating capabilities as disposable JWT-like metadata misses the economic consequences.

Capability systems can fail financially while remaining cryptographically correct

This is perhaps the most important security point.

Every signature can verify.

Every nonce can be unique.

Every certificate can be valid.

The system can still be economically wrong because:

capability was too broad
delegation expanded authority
capacity was double allocated
issuer had excessive authority
revocation arrived too late
context was ambiguous
Enter fullscreen mode Exit fullscreen mode

Cryptographic correctness is necessary.

It is not sufficient.

Security boundary

The real security property is not:

token authentic
Enter fullscreen mode Exit fullscreen mode

It is:

the resulting economic action
was inside the exact authority
intentionally granted by the system
Enter fullscreen mode Exit fullscreen mode

That property spans application state, business policy, ledger state, cryptography, and distributed execution.

Capability security and proof-carrying state

The previous model gave us:

Evidence
    ->
Claim
Enter fullscreen mode Exit fullscreen mode

Capability security extends the chain:

Evidence
    ->
Claim
        ->
Capability
            ->
Reservation
                ->
Execution
Enter fullscreen mode Exit fullscreen mode

Each stage narrows the set of possible actions.

That monotonic narrowing is desirable.

As the operation approaches irreversible external execution, ambiguity should decrease.

Authority should shrink toward execution

Early in a workflow:

customer may withdraw up to 10k today
Enter fullscreen mode Exit fullscreen mode

Later:

withdrawal W may transfer 2k
Enter fullscreen mode Exit fullscreen mode

Later:

transaction T may send exactly 2k to address A
Enter fullscreen mode Exit fullscreen mode

Finally:

signed transaction bytes X
Enter fullscreen mode Exit fullscreen mode

The authority becomes progressively narrower.

This is the opposite of many service architectures, where generic upstream approval becomes increasingly ambiguous as it travels through the system.

Security under partial failure

Distributed failure complicates authority.

A capability may be:

reserved locally
executed externally
confirmation lost
Enter fullscreen mode Exit fullscreen mode

The correct state is not:

unused
Enter fullscreen mode Exit fullscreen mode

It is:

execution outcome unknown
Enter fullscreen mode Exit fullscreen mode

The authority remains unavailable until reconciliation determines whether the action occurred.

This prevents retries from double spending authority.

Capability debt

There is also such a thing as outstanding authority.

Suppose the system issues large numbers of long-lived capabilities.

Even if none are currently used, they represent latent economic power.

This can be viewed as capability debt.

A platform may have:

10M active balances
Enter fullscreen mode Exit fullscreen mode

but:

80M currently exercisable capabilities
Enter fullscreen mode Exit fullscreen mode

That second number deserves attention.

Authority exposure can exceed current transaction flow.

Minimize dormant authority

A useful principle:

issue authority as late as practical
expire it as early as practical
Enter fullscreen mode Exit fullscreen mode

Do not pre-issue broad financial capabilities merely because execution might happen later.

Dormant authority is attack surface.

Conclusion

Distributed financial systems do not merely authenticate actors.

They distribute economic authority.

A service may receive permission to withdraw, settle, sign, refund, release collateral, allocate liquidity, or delegate part of that authority to another component.

When this authority is implicit in roles, service identities, database fields, or generic approval booleans, its boundaries become difficult to reason about.

Capability security makes authority explicit.

A capability answers:

who may act
what action is permitted
over which value
for which operation
under which constraints
for how long
and whether that authority may be delegated
Enter fullscreen mode Exit fullscreen mode

From there, several invariants become enforceable.

Authority can be attenuated but not amplified.

Consumable authority can be split but not duplicated.

One-shot authority cannot be replayed.

Delegated authority cannot exceed its parent.

A privileged deputy cannot substitute its own ambient authority for the caller's bounded permission.

Revocation removes future authority without rewriting history.

Unknown execution outcomes retain their reservation until reconciliation resolves them.

The deeper principle is that authority behaves like a scarce resource.

It can be issued.

It can be delegated.

It can be partitioned.

It can be consumed.

It can be revoked.

And, if the architecture is careless, it can be accidentally multiplied.

That gives us a useful safety property:

For every economically significant action A,
there must exist an authority chain C such that:

A is inside the scope of C,

every delegation step preserves or reduces authority,

the relevant capacity has not already been consumed,

and execution cannot produce more economic effect
than the original authority intended.
Enter fullscreen mode Exit fullscreen mode

Financial systems already work hard to prevent double spending of value.

They should apply the same seriousness to double spending of authority.

Top comments (0)