CBA side illustration
CBA Business Banking Accounts
Reports business account balances, postings and payment limits to an agent holding read authority. It is a read only resource, and refuses every state changing call whatever authority is presented.
This service is an illustration built on the CBA side of the boundary. It is not a Raidiam product. It exists to show what a resource server can demand of an agent, and to show that a refusal can always be explained.
What an agent has to discover
Resourcehttps://rs-accounts.demo.cba.raidiam.io
Authorization serverhttps://commbiz.demo.cba.raidiam.io
Trust anchornot configured
Detail typesaccounts_read, accounts_write
Scopesopenid, accounts.read
Sender constrainingDPoP verified when presented, required for bound tokens
Mutabilityread only
Authorization detail types
accounts_read
Authority to read balances, postings and payment limits on the delegating customer's business accounts. It carries no ability to move money and no ability to change a setting. It is the only type this resource will act on.
Required members: type purpose
Optional members: accounts constraints
{
"type": "accounts_read",
"purpose": "Confirm available funds before settling approved supplier invoices",
"accounts": [
"ACC-8801"
]
}
accounts_write
The type the write tools name: changing payees, limits and mandates. It is published so the refusal a read only agent receives is checkable against a declared requirement rather than looking arbitrary. An agent may be entitled by its role to request this type and still be unable to obtain it, because it does not sit under the payment envelope the customer delegated. And a caller that did hold it would still be refused here, because this resource is read only. Two independent gates, each with its own stated reason.
Required members: type purpose
Optional members: none
{
"type": "accounts_write",
"purpose": "Outside the accounts payable envelope. Account administration is performed by a human signatory in CommBiz."
}
Token claims this resource decides on
sub required The business banking customer whose accounts are in scope.
root_grant optional The root delegation this read belongs to. Recorded on every decision so a read can be traced back to the delegation that permitted it.
act optional The RFC 8693 actor chain, recorded on every decision.
cnf.jkt optional The thumbprint of the key the access token is bound to.
authorization_details[accounts_read] required The authority to read. Nothing else admits a call here.
Tools
Guardrails, published in advance
Every call carries a token from the named authorization server
Calls are accepted only with an access token issued by https://commbiz.demo.cba.raidiam.io and addressed to this resource as its audience. A token minted for a different resource is refused even when it is otherwise valid.
Refusal reason missing_access_token, invalid_token · decided at authorization · policy id rs.authenticated_caller
What clears it: Read this metadata document, then request a token from the authorization server it names, with this resource as the audience.
Authority is the RFC 9396 detail type, not a scope
Each tool names one authorization_details type. The token must carry that type, or an umbrella type that narrows to it. Holding a scope, or holding authority for a neighbouring resource, does not admit the call.
Refusal reason insufficient_authority · decided at authorization · policy id rs.authority_gate
What clears it: Obtain a token carrying the detail type the tool names. Delegation only ever narrows, so the delegating envelope must already contain it.
A revoked delegation stops working before its tokens expire
Revocation arrives as a Shared Signals event and is applied to the delegation, not to a single token. Every token issued under a revoked delegation is refused from that moment, whatever its expiry says.
Refusal reason delegation_revoked · decided at authorization · policy id rs.revocation_honoured
What clears it: The customer must grant a fresh delegation. There is no way to appeal a revocation at the resource.
Sender constrained tokens are bound to the key that holds them
A DPoP proof is verified whenever one is presented, and is required whenever the access token names a key in its cnf.jkt claim. Each proof is accepted once, so a captured proof cannot be replayed.
Refusal reason dpop_proof_required, invalid_dpop_proof, dpop_key_mismatch, dpop_proof_replayed, access_token_not_dpop_bound · decided at authorization · policy id rs.dpop_binding
What clears it: Request the access token with a DPoP proof so the authorization server binds it to your key, then send a fresh proof with every call.
CBA Business Banking Accounts never changes state
This resource publishes read_only true and exposes no path that writes. A mutating tool is refused before it runs, regardless of the authority the caller presents, so an agent cannot widen its own position by writing here.
Refusal reason resource_is_read_only · decided at authorization · policy id rs.read_only_resource
What clears it: State changing instructions belong to the resource that owns the record. This one only reports.
A malformed request is refused with the reason it was malformed
Arguments are validated before any business rule runs, and the refusal names the argument at fault rather than returning a bare failure.
Refusal reason tool_error, invalid_amount, unknown_tool · decided at execution · policy id rs.request_validity
What clears it: Correct the named argument. The tool schemas are published in this document.
Read authority never becomes write authority
accounts_read admits the reporting tools and nothing else. The write tools name accounts_write, which does not sit under the supplier_payment envelope, so no attenuation an agent can perform turns reading into writing. Being entitled to ask for a type and being inside the delegated envelope are two separate gates, and the accounts payable orchestrator passes the first and fails the second.
Refusal reason insufficient_authority · decided at authorization · policy id acct.read_authority_is_not_write_authority
What clears it: There is no path from a payment envelope to account administration. Write authority over account standing data is exercised by human signatories through CommBiz administration.
An agent cannot raise the limit that is refusing it
Payment limits are readable so an agent can plan, and are not settable here by anyone. An agent that has just been refused a payment for exceeding the single payment limit cannot come here and raise the limit, which is the whole reason the limit is worth having.
Refusal reason resource_is_read_only · decided at authorization · policy id acct.limits_are_not_agent_settable
What clears it: A human signatory changes limits through CommBiz administration.
Only the delegating customer's accounts are visible
The accounts returned are those of the customer named in the token sub claim. An account id that belongs to another customer is refused as unknown rather than as forbidden, so the resource does not confirm that it exists.
Refusal reason unknown_account · decided at execution · policy id acct.customer_scope
What clears it: Read the account list first. It contains everything this delegation can see.
Observability
Every admission decision, allowed and refused, is recorded with the policy that decided it and the values it turned on. Read them at /decisions.