Proposal: Delegated Subject Context
This proposal records the future model for acting on behalf of another subject. It was intentionally out of scope for the completed Session-Bound Invocation Context milestone and is treated as future work by the User Identity and Policy proposal and the Service Architecture proposal. The current state of the implemented session-bound model and its known residuals is tracked in Design Risks Register entries R2 (session-bound invocation context) and R14 (user identity / policy maturity).
The implemented milestone established the simpler rule first:
capability = authority to invoke
calling process session = who invokes
Cross-session capability transfer may delegate authority to invoke when the
capability’s transfer policy permits it. That is not subject delegation. The
User Identity and Policy proposal
already carries a delegationChain field on SessionInfo that records when a
session was minted through an AuthorityBroker approval flow or a federated
IdP; that field is session provenance, not the per-call represented-subject
context this proposal introduces.
Problem
Some workflows legitimately need a process to act on behalf of a different subject:
- a user asks an agent process to send a chat message for them;
- an operator grants a support session bounded access to perform one action;
- a service account performs a maintenance action for a tenant;
- an approval flow lets a worker complete a task in another principal’s name.
The system must support this without making the receiving process “become” the source subject. The caller’s own process session remains the invoker for audit, resource accounting, and privacy. The represented subject is separate, explicit, scoped, and revocable.
Design
Use a delegated-subject capability:
SubjectDelegation {
source_subject,
delegate_subject_or_session,
target_service,
allowed_methods_or_purpose,
disclosure_scope,
expires_at,
}
The exact ABI may be a SubjectDelegation interface, a broker result cap, or a
service-specific delegation cap. The invariant is stable:
invoked service cap = authority to call
calling process session = invoker
SubjectDelegation = represented subject context
Holding a SubjectDelegation is not enough to call a service. The caller must
also hold the service capability being invoked. This composes cleanly with the
service architecture’s existing rule that authority to act flows through the
service capability itself, not through ambient subject identity; see
Service Architecture proposal.
Example
Bob process session = Bob
Bob holds ChatRoot
Bob holds SubjectDelegation(Alice -> Bob, target_service = ChatRoot, scope = post)
ChatRoot.post(channel = "ops", text = "...", represented = AliceDelegation)
The service records:
invoker = Bob session reference
represented_subject = Alice, through bounded delegation
authority_to_call = ChatRoot
Bob has not become Alice. Audit and abuse handling can still identify Bob as
the actor while showing that Alice delegated a bounded representation. This
preserves the audit identity model the
User Identity and Policy proposal
already specifies for UserSession.auditContext: the invoker session reference
is the audit subject, and the represented-subject context is a separate facet
on the call.
Privacy
A delegated-subject capability must not disclose all source-subject facts. It should carry or vend only the facts the issuer allowed for the target service, such as:
- per-service display name;
- guest/operator class;
- a per-service audit pseudonym;
- a narrow claim such as “may approve invoice 123”.
It should not expose account-store records, external IdP claim bags, credential
identifiers, global principal ids, or unrelated profile attributes by default.
The default-private endpoint subject-disclosure rule introduced by the
session-bound milestone applies here too: explicit disclosure is opt-in per
method and bounded by the delegation’s disclosure_scope. See
User Identity and Policy proposal
for the broader privacy posture and
Session-Bound Invocation Context
for the implemented baseline.
Relationship To Capability Transfer
Capability transfer and subject delegation are different operations:
cap transfer only:
receiver gets authority to invoke;
receiver invokes as its own process session.
delegated subject context only:
receiver may present a represented subject;
no service method is callable unless receiver also holds a service cap.
cap transfer + delegated subject context:
receiver invokes the cap as its own process session;
service also sees the represented subject through explicit delegation.
The first implementation path should not depend on this proposal. Implement session-bound invocation context, transfer scopes, and shared-service migration first; add delegated subject context only after those rules are observable and reviewed. The session-bound prerequisites are landed (see Session-Bound Invocation Context and R2 in Design Risks Register); durable identity, ABAC/MAC, and broker maturity tracked under R14 of the same register are still proposal-shaped, so a delegated-subject implementation should not be selected until those mature far enough to give it a stable issuer.
Open Questions
- Whether the kernel should validate generic delegation metadata such as
target_serviceand expiry, or whether services should validate the delegation cap through a method call. - Whether delegated-subject caps are broker-owned, service-owned, or both.
- How revocation of delegated subject context composes with ordinary cap revoke/lease behavior.
- Whether the disclosure scope should be encoded as schema-specific facets or as a common metadata envelope.
- How
SessionInfo.delegationChain(session provenance) and a futureSubjectDelegation(per-call represented subject) compose without re-introducing ambient subject authority; the User Identity and Policy proposal owns the session-provenance side of that boundary.