Spike: does a directory role's metadata reach the wire as metadata_policy?
Date: 2026-08-10 · Status: RESOLVED, proven live on the CBA instance · Objectives: TC-27, TC-04, TC-05, TC-02
This settles the largest technical risk to the response. TC-27 requires a capability envelope governed and versioned independently of OAuth scopes and runtime client configuration, exposed to downstream identity, policy, entitlement and enforcement platforms. Our answer is directory Domain and Role metadata rows, applied as OpenID Federation metadata_policy.
Result: it works, and both publication and withdrawal are proven on the live CBA directory.
The answer, stated once
Three conditions must all hold for a metadata row to reach the wire:
- The role is
RoleType: Federation. Directory-type roles are silently excluded. - The role's domain has a non-null
FederationID. Roles in unrooted domains are silently excluded. - The claim is Active and attached to the SUBJECT, and the policy bucket must match the subject's kind. For a relying party the subject is the software statement. For an authorisation server the evidence points to the organisation.
oauth_authorization_server is never emitted as a bucket on either instance examined. Express capability on openid_relying_party or openid_provider.
Proof, on the live CBA directory
Role Agent-Capability-Spike in domain CBA-Global, carrying one metadata row: openid_relying_party / scope / one_of / ["supplier_invoice","accounts_read"].
Attached at software statement level to the Accounts Payable Orchestrator (e144816f-3448-4dd0-ae66-3eb5caffecd4, entity https://rp.directory.cba.raidiam.io/openid_relying_party/e144816f-3448-4dd0-ae66-3eb5caffecd4), its subordinate statement returned:
"openid_relying_party": {
"scope": { "one_of": ["supplier_invoice", "accounts_read"], "value": "openid" }
}
Note the union: the one_of row merged with a value: "openid" row from a different role the same statement holds. Rows from several roles combine rather than collide.
Setting that claim Inactive and re-fetching returned:
"openid_relying_party": { "scope": { "value": "openid" } }
The capability was withdrawn from the published statement, leaving only the other role's row. That is TC-04 and TC-05 demonstrated on the same mechanism, not merely TC-27.
Captured artefact: docs/artefacts/tc27-subordinate-statement.jwt.
Correction: an earlier conclusion in this document was wrong
The first version of this spike concluded that metadata_policy only lands on a federation-managed, directory-hosted entity, and that self-managed entities get nothing. That was wrong, and it was briefed to a worker before being corrected.
It was disproved from the ConnectID dev reference instance, where a self-hosted OpenID Provider (auth.bank1.directory.dev.connectid.com.au) carries a populated openid_provider policy. Hosting is not the determining factor. See connectid-reference-patterns.md §1.
The original spike failed for two independent reasons, either of which alone would have produced an empty result:
- The claim was attached at organisation level while the subordinate statement being read was that of a software statement. On this evidence that combination emits nothing by design.
- The pre-existing role it was compared against carries its only row on
oauth_authorization_server, a bucket never emitted for a relying party subject.
Why this matters beyond the correction. Requiring federation-managed hosting would have been a significant constraint on CBA, whose authorization servers are self-hosted Ping and Entra. The true rule is far easier for them to satisfy, so the corrected finding is better news than the original.
What this means for the response
The capability envelope is real and it is genuinely independent of OAuth scopes. It is applied by the Trust Controller to a statement the Trust Controller signs. The agent does not assert it, cannot alter it, and does not participate in it. That is precisely the control TC-27 and TC-02 ask for.
Publication and withdrawal are the same mechanism, which makes the TC-04 revocation story much stronger: suspending an agent does not send a message that a consumer might miss, it removes the capability from the signed statement every consumer resolves.
Federation-managed registration remains our default for agent identities, not because policy requires it, but because the directory then hosts a resolvable entity configuration without us deploying anything per agent. That is a convenience, and the response must not claim it is a necessity.
Still open
- Authorisation server subjects. That policy comes from the organisation's claims for an AS rests on one clean data point and could not be falsified read-only. Confirm when the first CBA OP is registered.
- Trust marks on the CBA instance carry no claims body and no
exp. A capability therefore cannot ride inside a trust mark, and a consumer needing the envelope at call time mustresolverather than read marks. Confirm on ConnectID whether that is product-wide or CBA-specific configuration.
Environment state
Both spike claims are Inactive, so the environment is as found and no trust mark issues from them. The role Agent-Capability-Spike and its metadata row remain, clearly named and detached, as the captured evidence for TC-27. It is not owned by the wiring tool and its teardown must not touch it.