Trust Subject Flow
Policy constraints often need to know something about the other party: its role, its country, a certification it holds. Nothing on the provider node can look those facts up, so they travel with the negotiation. The consumer publishes them as the subject of its trust token, the provider verifies the token and keeps the subject on the agreement as trustData, and every later evaluation of that agreement sees them under $.subject in the information data source. This page follows that path component by component, states what the verification does and does not prove, and records the design decisions behind it.
The Path
Trust Subject Flow: from the consumer's information sources to a constraint
- The consumer publishes facts. A consumer node exposes the attributes it is willing to disclose through an information source in
publicaccess mode. With the built-in sources that means a static entry such as{ "accessMode": "public", "objects": { "role": "BorderAgency", "country": "GB" } }; the identity sources contribute nothing at this point (see Information Sources). - The consumer PNP gathers them. When the consumer starts a negotiation,
PolicyNegotiationPointServicecalls the information point with no policy and thepublicmode,retrieve(undefined, "public"), and passes the result to the trust component as the subject:generate(organizationIdentity, overrideType, { subject }). - The trust component issues the token. The JWT verifiable credential generator creates a credential whose
credentialSubjectis that object, issued by the consumer's organisation identity and signed with its verification method, with an optional expiry. An empty subject is replaced by{ "id": "<organisation identity>" }. The token travels with the contract request message to the provider. - The provider PNP verifies.
requestFromConsumerhands the token toTrustHelper.verifyTrust. The JWT verifier rejects an expired token, verifies the credential through the identity component (a bad signature is rejected there and a revoked credential is reported), and requires an issuer and a credential subject. It returns the issuer as the counterparty identity together with two data objects:verifiableCredential, the whole verified credential, andsubject, its credential subject. The PNP keeps that result on the negotiation astrustVerificationInfoand passes the data to the negotiator'shandleOfferas additional information for its decision. Every later message in the negotiation is verified the same way and must come from the same identity. - The PAP persists it. At finalisation the PNP creates the agreement in the administration point with
trustData: trustVerificationInfo.data, and the PAP stores it on the policy entity beside the rules (IRightsManagementPolicyTrust). It is returned with the agreement on every latergetAgreement. - Enforcement forwards it. At access time the caller hands the agreement to the enforcement point.
interceptWithIdandinterceptWithLocatorload the agreement from the PAP and forward itstrustDatathemselves;interceptWithPolicytakestrustDataas its fourth parameter, and the dataspace data plane passesagreement.trustDatathere for both pull and push enforcement. - The PDP merges.
PolicyDecisionPointService.evaluatecalls the information point with the agreement and theanymode, then spreads the trust data over the result:{ ...information, ...trustData }. The keysverifiableCredentialandsubjecttherefore override anything an information source returned under the same names, and the merged object is what every arbiter receives asinformation. - The arbiter reads it. A constraint addresses the verified attributes with the information data source and a path under
subject:
{
"leftOperand": "twin:jsonPath",
"twin:jsonPathDataSource": "information",
"twin:jsonPathExpression": "$.subject.role",
"operator": "eq",
"rightOperand": "BorderAgency"
}
The same condition can scope a rule to a party instead, as a PartyCollection refinement on the rule's assignee; the Default Policy Arbiter page describes both forms. Use case 8 walks the whole path with fixtures for the granted and the denied outcome.
The Subject at Each Hop
| Hop | Shape |
|---|---|
| Consumer static source entry | { "role": "BorderAgency", "country": "GB" } |
| Credential subject in the token | { "role": "BorderAgency", "country": "GB" } |
trustData on the provider's agreement | { "verifiableCredential": { "..." : "" }, "subject": { "role": "BorderAgency", "country": "GB" } } |
information seen by the arbiter | The information source output plus the two keys above |
| Constraint path | $.subject.role with "twin:jsonPathDataSource": "information" |
Note the nesting: sources publish top-level keys and the verifier introduces the subject level. A source configured with { "subject": { "role": "BorderAgency" } } would end up at $.subject.subject.role.
Security Caveat
The subject is self-asserted. The consumer node puts whatever its public information sources return into the credential, and verification proves only that the token was issued by the identity it names, is signed with that identity's key, has not expired and has not been revoked. It does not prove that the consumer is a border agency, only that the consumer said so under its own signature. A constraint on $.subject.<attribute> is therefore a check on the counterparty's declaration, adequate for routing and self-classification, and not a substitute for an attestation. Facts that must be established independently belong in a provider-side information source (a profile, a catalogue, a registry lookup) or in a credential issued by a third party that a custom source or verifier checks.
The trust data is also captured once. The subject reflects what the consumer published when the negotiation started; a later change on the consumer node does not update existing agreements.
Design Decisions
- Information sources serve facts that are local or global to the node. A source answers from its own node's configuration, identity documents, profiles or other reachable data. It receives the policy, the payload and the action, and at enforcement time the policy it receives is the stored agreement complete with
trustData, so a custom source could read the counterparty's subject from the agreement if a design called for it. Whether it does so is a design choice for that source; no plumbing is missing. - Attributes about the other party travel in the trust payload. The counterparty's attributes are disclosed by the counterparty, verified as its signed statement, and frozen on the agreement. This keeps the provider's evaluation independent of the consumer's availability at access time and gives a single, auditable record of what was claimed when the agreement was formed.
- The negotiation-time retrieve is deliberately policy-less and public. At that moment no policy exists on the consumer side, and the answer is disclosed to another organisation, so only sources that can answer without a policy, and only entries marked
publicorany, contribute. The identity and profile sources stay silent by construction. - The stored trust data is the counterparty's. Each node persists the verified data of the other party: the provider's copy of the agreement carries the consumer's subject, and the consumer's copy carries what the provider's negotiation tokens declared. A node never stores its own subject on its own agreement. Consumer-side enforcement of
$.subject.*constraints, which would need the consumer's own subject, is tracked as consumer-side trust subject capture. - Facts are node-global. The static source is one shared instance, so attributes added to it at request time (for example a calling user's roles) leak into every negotiation the node starts and can race under concurrency. A per-request channel for subject attributes is the subject of a spike on per-request trust payload subjects; until it lands, the subject should carry attributes of the organisation, not of an individual caller.
Related
- Information Sources
- Default Policy Arbiter
- Rights Management components
- Dataspace-level context: Trust and Identity, Rights Management in the dataspace and ODRL Policies