diff --git a/src/lib/components/JointSequence.svelte b/src/lib/components/JointSequence.svelte
index 5e77ae1..f09319f 100644
--- a/src/lib/components/JointSequence.svelte
+++ b/src/lib/components/JointSequence.svelte
@@ -98,6 +98,10 @@
return cursorY;
});
const H = Math.max(cursorY + STEP_GAP, minHeight);
+ // Lifelines stop just past the last message rather than running to the bottom of the
+ // box. Diagrams share one height (minHeight) so switching tabs doesn't shift the page;
+ // without this a short diagram trails dashed lines through the reserved space.
+ const lifelineEnd = Math.min(H - 10, cursorY + STEP_GAP - 10);
const graph = new joint.dia.Graph({}, { cellNamespace: joint.shapes });
const paper = new joint.dia.Paper({
@@ -124,7 +128,7 @@
xs.forEach((x) => {
const line = new joint.shapes.standard.Link({
source: { x, y: TOP_PAD + ACTOR_H },
- target: { x, y: H - 10 },
+ target: { x, y: lifelineEnd },
attrs: {
line: {
stroke: theme.lifeline,
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index c6b6e3b..22bc9eb 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -131,27 +131,53 @@
{
name: 'Resource Managed',
parties: 'Agent + Resource',
- desc: 'Bridge to OAuth 2.0 — the resource handles authorization via its existing OAuth AS,
- AAuth has four access modes. All replace API keys with cryptographic identity.
and returns an opaque AAuth Access Token the agent presents on repeat calls with DPoP.',
+ desc: 'Bridge to OAuth 2.0 — the resource runs its own authorization flow and returns a session token,
the one credential a resource issues for its own consumption, bound to the agent’s signature.',
steps: [
{ from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ agent_token'] },
{ from: 'Resource', to: 'Agent', lines: ['202 (interaction required)'], dashed: true },
{ note: 'user completes interaction' },
{ from: 'Agent', to: 'Resource', lines: ['GET pending URL'] },
- { from: 'Resource', to: 'Agent', lines: ['200 OK', 'AAuth-Access: opaque-token'], dashed: true },
- { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ agent_token', 'Authorization: AAuth opaque-token'] },
+ { from: 'Resource', to: 'Agent', lines: ['200 OK', 'AAuth-Access: session-token'], dashed: true },
+ {
+ from: 'Agent',
+ to: 'Resource',
+ lines: [
+ 'HTTPSig w/ agent_token',
+ 'Authorization: AAuth session-token',
+ 'signature covers authorization'
+ ]
+ },
+ { from: 'Resource', to: 'Agent', lines: ['200 OK'], dashed: true }
+ ]
+ },
+ {
+ name: 'Person Identity',
+ parties: 'Agent + Resource + Person Server',
+ desc: "Federated login for agents — the Person Server issues a person token for one resource,
and the resource serves on the person's identity alone. No resource token, no auth token.",
+ steps: [
+ { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /person w/ {resource}'] },
+ { from: 'Person Server', to: 'Agent', lines: ['person_token'], dashed: true },
+ { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ person_token', 'GET /api/documents'] },
{ from: 'Resource', to: 'Agent', lines: ['200 OK'], dashed: true }
]
},
{
name: 'Person Server Managed',
parties: 'Agent + Resource + Person Server',
- desc: "Native AAuth — the resource requires the user's identity or consent (or both).
The user's Person Server issues an auth token after the user approves.",
+ desc: "Native AAuth — the resource needs an authorization decision, not just the person's identity.
It issues a resource token bound to that person token; the Person Server returns an auth token.",
steps: [
- { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ agent_token', 'POST /authorize'] },
- { from: 'Resource', to: 'Agent', lines: ['resource_token', '(aud = Person Server URL)'], dashed: true },
- { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /token w/ resource_token'] },
+ { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /person w/ {resource}'] },
+ { from: 'Person Server', to: 'Agent', lines: ['person_token'], dashed: true },
+ { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ person_token', 'POST /authorize'] },
+ {
+ from: 'Resource',
+ to: 'Agent',
+ lines: ['resource_token', '(aud = Person Server URL)', 'ps / sub / person_token_jti'],
+ dashed: true
+ },
+ { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /auth_token w/ resource_token'] },
{ from: 'Person Server', to: 'Agent', lines: ['auth_token'], dashed: true },
- { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ auth token', 'GET /api/documents'] },
+ { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ auth_token', 'GET /api/documents'] },
{ from: 'Resource', to: 'Agent', lines: ['200 OK'], dashed: true }
]
},
@@ -160,15 +186,45 @@
parties: 'Agent + Resource + Person Server + Access Server',
desc: "Cross-domain AAuth — the resource has its own Access Server that federates with the agent's Person Server.
Authorization works across org and cloud boundaries without pre-registration.",
steps: [
- { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ agent_token', 'POST /authorize'] },
- { from: 'Resource', to: 'Agent', lines: ['resource_token', '(aud = Access Server URL)'], dashed: true },
- { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /token w/ resource_token'] },
- { from: 'Person Server', to: 'Access Server', lines: ['HTTPSig w/ jwks_uri', 'POST /token w/ resource_token'] },
+ { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /person w/ {resource}'] },
+ { from: 'Person Server', to: 'Agent', lines: ['person_token'], dashed: true },
+ { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ person_token', 'POST /authorize'] },
+ {
+ from: 'Resource',
+ to: 'Agent',
+ lines: ['resource_token', '(aud = Access Server URL)', 'ps / sub / person_token_jti'],
+ dashed: true
+ },
+ { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /auth_token w/ resource_token'] },
+ { from: 'Person Server', to: 'Access Server', lines: ['HTTPSig w/ jwks_uri', 'POST /auth_token w/ resource_token'] },
{ from: 'Access Server', to: 'Person Server', lines: ['auth_token'], dashed: true },
{ from: 'Person Server', to: 'Agent', lines: ['auth_token'], dashed: true },
- { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ auth token', 'GET /api/documents'] },
+ { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ auth_token', 'GET /api/documents'] },
{ from: 'Resource', to: 'Agent', lines: ['200 OK'], dashed: true }
]
+ },
+ {
+ name: 'Per-Call',
+ parties: 'Agent + Resource + Person Server + Access Server',
+ desc: "R3 per-call authorization — the resource challenges one invocation with a proposal carrying that call's
concrete parameters. The person approves them, and the retry is verified against what was approved.",
+ steps: [
+ { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ person_token', 'POST /send_email (r3_per_call)'] },
+ {
+ from: 'Resource',
+ to: 'Agent',
+ lines: ['401 + resource_token', 'r3_uri/r3_s256 → per-call proposal'],
+ dashed: true
+ },
+ { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /auth_token w/ resource_token'] },
+ { from: 'Person Server', to: 'Access Server', lines: ['HTTPSig w/ jwks_uri', 'POST /auth_token w/ resource_token'] },
+ { from: 'Access Server', to: 'Resource', lines: ['GET r3_uri (signed)'] },
+ { from: 'Resource', to: 'Access Server', lines: ['proposal: operation + parameters'], dashed: true },
+ { note: 'person approves these exact parameters' },
+ { from: 'Access Server', to: 'Person Server', lines: ['auth_token (r3_granted: this call)'], dashed: true },
+ { from: 'Person Server', to: 'Agent', lines: ['auth_token'], dashed: true },
+ { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ auth_token', 'POST /send_email (same parameters)'] },
+ { from: 'Resource', to: 'Agent', lines: ['200 OK', 'parameters verified vs proposal'], dashed: true }
+ ]
}
];
@@ -181,7 +237,7 @@
status: 'Internet-Draft',
href: 'https://datatracker.ietf.org/doc/draft-hardt-oauth-aauth-protocol',
editorsCopy: 'https://dickhardt.github.io/AAuth/draft-hardt-oauth-aauth-protocol.html',
- desc: 'The authorization protocol for agent-to-resource access. Four access modes, three token types, agent governance, missions, clarification chat, and call chaining.',
+ desc: 'The authorization protocol for agent-to-resource access. Five access modes, four token types, agent governance, missions, clarification chat, and call chaining.',
primary: true,
indent: false
},
@@ -199,7 +255,7 @@
status: 'Exploratory',
href: 'https://dickhardt.github.io/AAuth/draft-hardt-aauth-r3.html',
editorsCopy: null,
- desc: 'Vocabulary-based authorization using formats agents already understand (MCP, OpenAPI, gRPC, GraphQL).',
+ desc: 'Vocabulary-based authorization using formats agents already understand (MCP, OpenAPI, gRPC, GraphQL), plus per-call proposals for operations authorized one call at a time.',
primary: false,
indent: true
}
@@ -562,8 +618,9 @@
How AAuth Works
- Capability grows from simplest to most capable — adopt incrementally as your needs expand.
+ AAuth has five access modes. All replace API keys with cryptographic identity.
+ They differ in what the resource ends up knowing and which party established it — adopt incrementally as your needs expand.
+ Per-call authorization, from R3, governs a single action rather than a class of access.